@praxisui/core 10.0.0-rc.0 → 10.0.0-rc.4

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
  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, ElementRef, ChangeDetectorRef, afterEveryRender, contentChild, viewChild, HostBinding, output, afterNextRender, ViewChild, ViewEncapsulation, createEnvironmentInjector, EnvironmentInjector, reflectComponentType, HostListener, ViewChildren } from '@angular/core';
2
+ import { Component, InjectionToken, Injectable, inject, Inject, Optional, SkipSelf, makeEnvironmentProviders, APP_INITIALIZER, signal, computed, DestroyRef, ENVIRONMENT_INITIALIZER, ErrorHandler, isSignal, Input, Directive, input, booleanAttribute, ChangeDetectionStrategy, EventEmitter, Output, SecurityContext, ViewContainerRef, Injector, effect, SimpleChange, ElementRef, ChangeDetectorRef, afterEveryRender, contentChild, viewChild, HostBinding, output, afterNextRender, ViewChild, ViewEncapsulation, createEnvironmentInjector, EnvironmentInjector, reflectComponentType, HostListener, ViewChildren } 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
- 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, combineLatest, merge, timeout } from 'rxjs';
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, isObservable, combineLatest, merge, timeout } from 'rxjs';
6
6
  import { switchMap, map, take, catchError, concatMap, tap, shareReplay, takeUntil, toArray, finalize } from 'rxjs/operators';
7
7
  import * as i1$3 from '@angular/common';
8
8
  import { Location, DOCUMENT, NgTemplateOutlet, CommonModule, NgComponentOutlet } from '@angular/common';
@@ -6386,6 +6386,62 @@ function createDefaultTableConfig() {
6386
6386
  localDataMode: {
6387
6387
  enabled: false,
6388
6388
  },
6389
+ detail: {
6390
+ schemaContract: {
6391
+ kind: 'praxis.detail.schema',
6392
+ version: '1.0.0',
6393
+ compat: 'semver',
6394
+ allowedNodes: [
6395
+ 'layout',
6396
+ 'stack',
6397
+ 'tabs',
6398
+ 'tab',
6399
+ 'text',
6400
+ 'icon',
6401
+ 'image',
6402
+ 'badge',
6403
+ 'avatar',
6404
+ 'metric',
6405
+ 'progress',
6406
+ 'compose',
6407
+ 'card',
6408
+ 'value',
6409
+ 'action',
6410
+ 'list',
6411
+ 'formRef',
6412
+ 'tableRef',
6413
+ 'chartRef',
6414
+ 'richText',
6415
+ 'templateRef',
6416
+ ],
6417
+ sanitization: 'strict',
6418
+ },
6419
+ source: {
6420
+ mode: 'inline',
6421
+ inlineSchema: {
6422
+ layout: 'stack',
6423
+ items: [],
6424
+ },
6425
+ fallbackMode: 'none',
6426
+ },
6427
+ rendering: {
6428
+ strategy: 'registry',
6429
+ registryId: 'praxis.detail.default',
6430
+ hostLayout: 'auto',
6431
+ fallbackNodePolicy: 'failClosed',
6432
+ },
6433
+ height: {
6434
+ mode: 'fixed',
6435
+ px: 160,
6436
+ },
6437
+ lazyLoad: {
6438
+ enabled: false,
6439
+ cache: { enabled: true, ttlMs: 300000 },
6440
+ retry: { maxAttempts: 2 },
6441
+ cancelOnCollapse: true,
6442
+ dedupeByRowKey: true,
6443
+ },
6444
+ },
6389
6445
  expansion: {
6390
6446
  enabled: false,
6391
6447
  contractVersion: '1.0.0',
@@ -6413,62 +6469,6 @@ function createDefaultTableConfig() {
6413
6469
  filterChange: true,
6414
6470
  dataRefresh: true,
6415
6471
  },
6416
- detail: {
6417
- schemaContract: {
6418
- kind: 'praxis.detail.schema',
6419
- version: '1.0.0',
6420
- compat: 'semver',
6421
- allowedNodes: [
6422
- 'layout',
6423
- 'stack',
6424
- 'tabs',
6425
- 'tab',
6426
- 'text',
6427
- 'icon',
6428
- 'image',
6429
- 'badge',
6430
- 'avatar',
6431
- 'metric',
6432
- 'progress',
6433
- 'compose',
6434
- 'card',
6435
- 'value',
6436
- 'action',
6437
- 'list',
6438
- 'formRef',
6439
- 'tableRef',
6440
- 'chartRef',
6441
- 'richText',
6442
- 'templateRef',
6443
- ],
6444
- sanitization: 'strict',
6445
- },
6446
- source: {
6447
- mode: 'inline',
6448
- inlineSchema: {
6449
- layout: 'stack',
6450
- items: [],
6451
- },
6452
- fallbackMode: 'none',
6453
- },
6454
- rendering: {
6455
- strategy: 'registry',
6456
- registryId: 'praxis.detail.default',
6457
- hostLayout: 'auto',
6458
- fallbackNodePolicy: 'failClosed',
6459
- },
6460
- height: {
6461
- mode: 'fixed',
6462
- px: 160,
6463
- },
6464
- lazyLoad: {
6465
- enabled: false,
6466
- cache: { enabled: true, ttlMs: 300000 },
6467
- retry: { maxAttempts: 2 },
6468
- cancelOnCollapse: true,
6469
- dedupeByRowKey: true,
6470
- },
6471
- },
6472
6472
  virtualization: {
6473
6473
  policy: 'fixed-height-only',
6474
6474
  },
@@ -9231,7 +9231,11 @@ class GlobalActionService {
9231
9231
  }
9232
9232
  return { success: false, error: 'Window not available' };
9233
9233
  }, () => [this.requirement('platform-api', 'window.open', typeof window !== 'undefined')]);
9234
- this.register('navigation.openRoute', async (payload) => this.handleNavigationOpenRoute(payload), () => [this.requirement('platform-api', 'Router|window.location', !!this.router || (typeof window !== 'undefined' && !!window.location))]);
9234
+ const navOpenRouteHandler = async (payload) => this.handleNavigationOpenRoute(payload);
9235
+ const navOpenRouteReadiness = () => [this.requirement('platform-api', 'Router|window.location', !!this.router || (typeof window !== 'undefined' && !!window.location))];
9236
+ this.register('navigation.openRoute', navOpenRouteHandler, navOpenRouteReadiness);
9237
+ this.register('navigation.navigate', navOpenRouteHandler, navOpenRouteReadiness);
9238
+ this.register('praxis:router.navigate', navOpenRouteHandler, navOpenRouteReadiness);
9235
9239
  this.register('dialog.alert', async (payload) => {
9236
9240
  if (!this.dialog)
9237
9241
  return { success: false, error: 'Dialog service not available' };
@@ -9438,11 +9442,14 @@ class GlobalActionService {
9438
9442
  const url = this.buildNavigationUrl(payload);
9439
9443
  if (!url)
9440
9444
  return { success: false, error: 'Missing path' };
9445
+ const isObject = typeof payload === 'object' && payload !== null;
9446
+ const replaceUrl = isObject ? !!payload.replaceUrl : false;
9447
+ const state = isObject ? payload.state : undefined;
9441
9448
  try {
9442
9449
  if (this.router) {
9443
9450
  const navigated = await this.router.navigateByUrl(url, {
9444
- replaceUrl: !!payload?.replaceUrl,
9445
- state: payload?.state,
9451
+ replaceUrl,
9452
+ state,
9446
9453
  });
9447
9454
  if (navigated) {
9448
9455
  return { success: true };
@@ -9453,7 +9460,7 @@ class GlobalActionService {
9453
9460
  };
9454
9461
  }
9455
9462
  if (typeof window !== 'undefined' && window.location) {
9456
- if (payload?.replaceUrl && typeof window.location.replace === 'function') {
9463
+ if (replaceUrl && typeof window.location.replace === 'function') {
9457
9464
  window.location.replace(url);
9458
9465
  }
9459
9466
  else if (typeof window.location.assign === 'function') {
@@ -9543,6 +9550,28 @@ class GlobalActionService {
9543
9550
  return { success: true };
9544
9551
  }
9545
9552
  buildNavigationUrl(payload) {
9553
+ if (typeof payload === 'string') {
9554
+ const raw = payload.trim();
9555
+ if (!raw)
9556
+ return '';
9557
+ const hashIndex = raw.indexOf('#');
9558
+ const withoutHash = hashIndex >= 0 ? raw.slice(0, hashIndex) : raw;
9559
+ const rawHash = hashIndex >= 0 ? raw.slice(hashIndex + 1) : '';
9560
+ const queryIndex = withoutHash.indexOf('?');
9561
+ const rawPath = (queryIndex >= 0 ? withoutHash.slice(0, queryIndex) : withoutHash).trim();
9562
+ if (!rawPath)
9563
+ return '';
9564
+ const normalizedPath = rawPath.startsWith('/') ? rawPath : `/${rawPath}`;
9565
+ const rawQuery = queryIndex >= 0 ? withoutHash.slice(queryIndex + 1).trim() : '';
9566
+ let query = '';
9567
+ if (rawQuery) {
9568
+ const params = new URLSearchParams(rawQuery);
9569
+ const serialized = params.toString();
9570
+ query = serialized ? `?${serialized}` : '';
9571
+ }
9572
+ const fragment = this.buildFragment(rawHash);
9573
+ return `${normalizedPath}${query}${fragment}`;
9574
+ }
9546
9575
  const rawPath = String(payload?.path || '').trim();
9547
9576
  if (!rawPath)
9548
9577
  return '';
@@ -16467,10 +16496,10 @@ class EnterpriseRuntimeContextService {
16467
16496
  return response;
16468
16497
  }
16469
16498
  headers(fallback) {
16470
- return {
16471
- ...this.normalizeHeaders(fallback ?? {}),
16472
- ...this.normalizeHeaders(this.headersFromSnapshot(this.contextSubject.value)),
16473
- };
16499
+ return this.mergeHeaders(fallback ?? {}, this.headersFromSnapshot(this.contextSubject.value));
16500
+ }
16501
+ effectiveRequestHeaders(fallback) {
16502
+ return this.mergeHeaders(this.options?.includeGlobalFetchHeaders ?? true ? this.globalFetchHeaders() : {}, this.options?.headersFactory?.() ?? {}, fallback ?? {}, this.headersFromSnapshot(this.contextSubject.value));
16474
16503
  }
16475
16504
  async load() {
16476
16505
  const context = await firstValueFrom(this.http.get(this.endpoint('context'), {
@@ -16520,11 +16549,7 @@ class EnterpriseRuntimeContextService {
16520
16549
  }
16521
16550
  }
16522
16551
  requestHeaders(options = {}) {
16523
- const merged = this.normalizeHeaders({
16524
- ...(this.options?.includeGlobalFetchHeaders ?? true ? this.globalFetchHeaders() : {}),
16525
- ...(this.options?.headersFactory?.() ?? {}),
16526
- ...(options.includeSnapshot ? this.headersFromSnapshot(this.contextSubject.value) : {}),
16527
- });
16552
+ const merged = this.mergeHeaders(this.options?.includeGlobalFetchHeaders ?? true ? this.globalFetchHeaders() : {}, this.options?.headersFactory?.() ?? {}, options.includeSnapshot ? this.headersFromSnapshot(this.contextSubject.value) : {});
16528
16553
  let headers = new HttpHeaders();
16529
16554
  for (const [key, value] of Object.entries(merged)) {
16530
16555
  if (value) {
@@ -16558,6 +16583,7 @@ class EnterpriseRuntimeContextService {
16558
16583
  }
16559
16584
  normalizeHeaders(headers) {
16560
16585
  const normalized = {};
16586
+ const canonicalKeyByLowercase = new Map();
16561
16587
  for (const [key, value] of Object.entries(headers)) {
16562
16588
  if (typeof value !== 'string') {
16563
16589
  continue;
@@ -16566,10 +16592,19 @@ class EnterpriseRuntimeContextService {
16566
16592
  if (!trimmed) {
16567
16593
  continue;
16568
16594
  }
16595
+ const lowercase = key.toLowerCase();
16596
+ const previousKey = canonicalKeyByLowercase.get(lowercase);
16597
+ if (previousKey) {
16598
+ delete normalized[previousKey];
16599
+ }
16569
16600
  normalized[key] = trimmed;
16601
+ canonicalKeyByLowercase.set(lowercase, key);
16570
16602
  }
16571
16603
  return normalized;
16572
16604
  }
16605
+ mergeHeaders(...sources) {
16606
+ return this.normalizeHeaders(Object.assign({}, ...sources.map((source) => this.normalizeHeaders(source))));
16607
+ }
16573
16608
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EnterpriseRuntimeContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
16574
16609
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: EnterpriseRuntimeContextService, providedIn: 'root' });
16575
16610
  }
@@ -25181,11 +25216,24 @@ function compareValues(left, right) {
25181
25216
  }
25182
25217
  return 0;
25183
25218
  }
25219
+ function isSubscribable$2(val) {
25220
+ return val != null && typeof val === 'object' && typeof val.subscribe === 'function';
25221
+ }
25184
25222
  function clone$1(value) {
25185
25223
  if (value == null || typeof value !== 'object') {
25186
25224
  return value;
25187
25225
  }
25188
- return JSON.parse(JSON.stringify(value));
25226
+ if (isSignal(value) || isObservable(value) || isSubscribable$2(value) || typeof value === 'function') {
25227
+ return value;
25228
+ }
25229
+ if (Array.isArray(value)) {
25230
+ return value.map((item) => clone$1(item));
25231
+ }
25232
+ const result = {};
25233
+ for (const [k, v] of Object.entries(value)) {
25234
+ result[k] = clone$1(v);
25235
+ }
25236
+ return result;
25189
25237
  }
25190
25238
 
25191
25239
  /** Utility: generate a random id using crypto.randomUUID or fallback. */
@@ -33295,6 +33343,74 @@ const BUILTIN_WIDGET_SHELL_PRESETS = [
33295
33343
  },
33296
33344
  },
33297
33345
  },
33346
+ {
33347
+ id: 'glass-dark',
33348
+ label: {
33349
+ key: 'praxis.widgetShell.presets.glass-dark.label',
33350
+ text: 'Glass dark',
33351
+ },
33352
+ description: {
33353
+ key: 'praxis.widgetShell.presets.glass-dark.description',
33354
+ text: 'Translucent dark glass surface with token governance and backdrop blur.',
33355
+ },
33356
+ category: 'sectioned',
33357
+ appearance: {
33358
+ card: {
33359
+ background: 'color-mix(in srgb, var(--md-sys-color-surface, #0f172a) 60%, transparent)',
33360
+ borderColor: 'color-mix(in srgb, var(--md-sys-color-outline-variant, #fff) 18%, transparent)',
33361
+ borderRadius: '16px',
33362
+ shadow: '0 8px 32px rgba(0, 0, 0, 0.25)',
33363
+ backdropFilter: 'blur(12px)',
33364
+ fallbackBackground: 'var(--md-sys-color-surface, #0f172a)',
33365
+ },
33366
+ header: {
33367
+ background: 'transparent',
33368
+ borderColor: 'color-mix(in srgb, var(--md-sys-color-outline-variant, #fff) 15%, transparent)',
33369
+ titleColor: 'var(--md-sys-color-on-surface, #e6edf3)',
33370
+ subtitleColor: 'var(--md-sys-color-on-surface-variant, #9fb0c4)',
33371
+ iconColor: 'var(--md-sys-color-primary, #38bdf8)',
33372
+ },
33373
+ body: {
33374
+ background: 'transparent',
33375
+ textColor: 'var(--md-sys-color-on-surface, #e6edf3)',
33376
+ padding: '12px',
33377
+ },
33378
+ },
33379
+ },
33380
+ {
33381
+ id: 'glass-light',
33382
+ label: {
33383
+ key: 'praxis.widgetShell.presets.glass-light.label',
33384
+ text: 'Glass light',
33385
+ },
33386
+ description: {
33387
+ key: 'praxis.widgetShell.presets.glass-light.description',
33388
+ text: 'Translucent light glass surface with token governance and backdrop blur.',
33389
+ },
33390
+ category: 'sectioned',
33391
+ appearance: {
33392
+ card: {
33393
+ background: 'color-mix(in srgb, var(--md-sys-color-surface, #ffffff) 65%, transparent)',
33394
+ borderColor: 'color-mix(in srgb, var(--md-sys-color-outline-variant, #000) 14%, transparent)',
33395
+ borderRadius: '16px',
33396
+ shadow: '0 8px 32px rgba(0, 0, 0, 0.08)',
33397
+ backdropFilter: 'blur(12px)',
33398
+ fallbackBackground: 'var(--md-sys-color-surface, #ffffff)',
33399
+ },
33400
+ header: {
33401
+ background: 'transparent',
33402
+ borderColor: 'color-mix(in srgb, var(--md-sys-color-outline-variant, #000) 10%, transparent)',
33403
+ titleColor: 'var(--md-sys-color-on-surface)',
33404
+ subtitleColor: 'var(--md-sys-color-on-surface-variant)',
33405
+ iconColor: 'var(--md-sys-color-primary)',
33406
+ },
33407
+ body: {
33408
+ background: 'transparent',
33409
+ textColor: 'var(--md-sys-color-on-surface)',
33410
+ padding: '12px',
33411
+ },
33412
+ },
33413
+ },
33298
33414
  {
33299
33415
  id: 'light-neutral',
33300
33416
  label: {
@@ -33643,6 +33759,8 @@ class DynamicWidgetLoaderDirective {
33643
33759
  currentUsesInitialBindings = false;
33644
33760
  currentInitialBindingSignature = null;
33645
33761
  boundInputValues = {};
33762
+ signalEffects = new Map();
33763
+ inputObservableSubs = new Map();
33646
33764
  outputSubs = [];
33647
33765
  shellActionContributionEffect;
33648
33766
  shellActionContributor;
@@ -33650,6 +33768,37 @@ class DynamicWidgetLoaderDirective {
33650
33768
  getWidgetShellActionAvailability(action) {
33651
33769
  return this.shellActionContributor?.getWidgetShellActionAvailability?.(action);
33652
33770
  }
33771
+ /**
33772
+ * Updates a single input on the currently rendered widget component instance without recreating the component.
33773
+ * Dispatches change detection exclusively to this widget subtree.
33774
+ */
33775
+ setInput(inputName, value) {
33776
+ if (!this.compRef || this.destroyed) {
33777
+ return false;
33778
+ }
33779
+ const def = this.widgetDefinition;
33780
+ const meta = def?.id ? this.registry.get(def.id) : undefined;
33781
+ const trimmed = typeof inputName === 'string' ? inputName.trim() : '';
33782
+ if (!trimmed)
33783
+ return false;
33784
+ return this.bindSingleInput(this.compRef, trimmed, value, meta || undefined);
33785
+ }
33786
+ /**
33787
+ * Patches multiple inputs on the currently rendered widget component instance without recreating the component.
33788
+ * Dispatches change detection exclusively to this widget subtree.
33789
+ */
33790
+ patchInputs(inputPatch) {
33791
+ if (!this.compRef || this.destroyed || !inputPatch || typeof inputPatch !== 'object') {
33792
+ return false;
33793
+ }
33794
+ let anyChanged = false;
33795
+ for (const [key, value] of Object.entries(inputPatch)) {
33796
+ if (this.setInput(key, value)) {
33797
+ anyChanged = true;
33798
+ }
33799
+ }
33800
+ return anyChanged;
33801
+ }
33653
33802
  /** Dispatch a shell action to the inner widget instance when supported. */
33654
33803
  dispatchAction(action) {
33655
33804
  const instance = this.compRef?.instance;
@@ -33838,6 +33987,10 @@ class DynamicWidgetLoaderDirective {
33838
33987
  }
33839
33988
  destroyCurrent() {
33840
33989
  this.releaseShellActionContributor();
33990
+ this.signalEffects.forEach((eff) => eff.destroy());
33991
+ this.signalEffects.clear();
33992
+ this.inputObservableSubs.forEach((sub) => sub.unsubscribe());
33993
+ this.inputObservableSubs.clear();
33841
33994
  this.outputSubs.forEach((u) => u());
33842
33995
  this.outputSubs = [];
33843
33996
  if (this.compRef) {
@@ -33896,37 +34049,58 @@ class DynamicWidgetLoaderDirective {
33896
34049
  || hasDetachedDynamicFormRuntimeInputs
33897
34050
  || hasDetachedFilterRuntimeInputs;
33898
34051
  }
34052
+ cleanupInputReactiveBinding(key) {
34053
+ const existingEffect = this.signalEffects.get(key);
34054
+ if (existingEffect) {
34055
+ existingEffect.destroy();
34056
+ this.signalEffects.delete(key);
34057
+ }
34058
+ const existingSub = this.inputObservableSubs.get(key);
34059
+ if (existingSub) {
34060
+ existingSub.unsubscribe();
34061
+ this.inputObservableSubs.delete(key);
34062
+ }
34063
+ }
34064
+ bindSingleInput(compRef, key, raw, meta, manualChanges) {
34065
+ this.cleanupInputReactiveBinding(key);
34066
+ if (isSignal(raw)) {
34067
+ const initialVal = raw();
34068
+ const changed = this.applyDirectInputValue(compRef, key, initialVal, meta, manualChanges);
34069
+ const eff = effect(() => {
34070
+ const currentVal = raw();
34071
+ if (!this.destroyed && this.compRef) {
34072
+ this.applyDirectInputValue(this.compRef, key, currentVal, meta);
34073
+ }
34074
+ }, { ...(ngDevMode ? { debugName: "eff" } : /* istanbul ignore next */ {}), injector: this.injector });
34075
+ this.signalEffects.set(key, eff);
34076
+ return changed;
34077
+ }
34078
+ if (isObservable(raw) || isSubscribableInput(raw)) {
34079
+ const sub = raw.subscribe({
34080
+ next: (emittedValue) => {
34081
+ if (!this.destroyed && this.compRef) {
34082
+ this.applyDirectInputValue(this.compRef, key, emittedValue, meta);
34083
+ }
34084
+ },
34085
+ error: (err) => {
34086
+ console.error(`[DynamicWidgetLoader] Error in reactive input stream '${key}':`, err);
34087
+ },
34088
+ });
34089
+ this.inputObservableSubs.set(key, sub);
34090
+ return true;
34091
+ }
34092
+ return this.applyDirectInputValue(compRef, key, raw, meta, manualChanges);
34093
+ }
33899
34094
  bindInputs(compRef, id, inputs, bindingOrder, meta) {
33900
34095
  const prioritized = this.orderedInputEntries(id, inputs, bindingOrder);
33901
34096
  const manualChanges = {};
33902
34097
  let changed = false;
33903
- const apply = (key, raw) => {
33904
- const value = this.resolveAndCoerceValue(key, raw, meta);
33905
- try {
33906
- const hadPreviousValue = Object.prototype.hasOwnProperty.call(this.boundInputValues, key);
33907
- const previousValue = this.boundInputValues[key];
33908
- if (hadPreviousValue
33909
- && this.areInputValuesEquivalent(previousValue, value)) {
33910
- return;
33911
- }
33912
- if (this.hasDeclaredInput(compRef, key)) {
33913
- compRef.setInput(key, value);
33914
- }
33915
- else {
33916
- compRef.instance[key] = value;
33917
- manualChanges[key] = new SimpleChange(previousValue, value, !hadPreviousValue);
33918
- }
33919
- this.boundInputValues[key] = value;
33920
- changed = true;
33921
- }
33922
- catch (e) {
33923
- console.warn(`[DynamicWidgetLoader] Failed to set input ${key}`, e);
33924
- }
33925
- };
33926
34098
  // Apply every input before the final detectChanges. ComponentRef.setInput marks
33927
34099
  // OnPush views for checking and lets Angular deliver one coherent ngOnChanges cycle.
33928
34100
  for (const [key, raw] of prioritized) {
33929
- apply(key, raw);
34101
+ if (this.bindSingleInput(compRef, key, raw, meta, manualChanges)) {
34102
+ changed = true;
34103
+ }
33930
34104
  }
33931
34105
  if (Object.keys(manualChanges).length
33932
34106
  && typeof compRef.instance?.ngOnChanges === 'function') {
@@ -33934,6 +34108,39 @@ class DynamicWidgetLoaderDirective {
33934
34108
  }
33935
34109
  return changed;
33936
34110
  }
34111
+ applyDirectInputValue(compRef, key, raw, meta, manualChanges) {
34112
+ const unwrapped = isSignal(raw) ? raw() : raw;
34113
+ const value = this.resolveAndCoerceValue(key, unwrapped, meta);
34114
+ const hadPreviousValue = Object.prototype.hasOwnProperty.call(this.boundInputValues, key);
34115
+ const previousValue = this.boundInputValues[key];
34116
+ if (hadPreviousValue && this.areInputValuesEquivalent(previousValue, value)) {
34117
+ return false;
34118
+ }
34119
+ try {
34120
+ if (this.hasDeclaredInput(compRef, key)) {
34121
+ compRef.setInput(key, value);
34122
+ }
34123
+ else {
34124
+ compRef.instance[key] = value;
34125
+ const change = new SimpleChange(previousValue, value, !hadPreviousValue);
34126
+ if (manualChanges) {
34127
+ manualChanges[key] = change;
34128
+ }
34129
+ else if (typeof compRef.instance?.ngOnChanges === 'function') {
34130
+ compRef.instance.ngOnChanges({ [key]: change });
34131
+ }
34132
+ }
34133
+ this.boundInputValues[key] = value;
34134
+ if (!manualChanges) {
34135
+ compRef.changeDetectorRef.detectChanges();
34136
+ }
34137
+ return true;
34138
+ }
34139
+ catch (e) {
34140
+ console.warn(`[DynamicWidgetLoader] Failed to set input ${key} dynamically`, e);
34141
+ return false;
34142
+ }
34143
+ }
33937
34144
  hasDeclaredInput(compRef, key) {
33938
34145
  const inputs = compRef.componentType?.ɵcmp?.inputs;
33939
34146
  return !!inputs && Object.prototype.hasOwnProperty.call(inputs, key);
@@ -33988,6 +34195,9 @@ class DynamicWidgetLoaderDirective {
33988
34195
  return [...prioritized, ...others];
33989
34196
  }
33990
34197
  resolveAndCoerceValue(key, raw, meta) {
34198
+ if (isSignal(raw) || isObservable(raw) || isSubscribableInput(raw)) {
34199
+ return raw;
34200
+ }
33991
34201
  let value = this.resolveValue(raw, key, [key]);
33992
34202
  // Coerção leve baseada em metadata, quando disponível
33993
34203
  if (meta?.inputs?.length) {
@@ -34031,6 +34241,14 @@ class DynamicWidgetLoaderDirective {
34031
34241
  if (Object.is(previousValue, value)) {
34032
34242
  return true;
34033
34243
  }
34244
+ if (isSignal(previousValue)
34245
+ || isSignal(value)
34246
+ || isObservable(previousValue)
34247
+ || isObservable(value)
34248
+ || isSubscribableInput(previousValue)
34249
+ || isSubscribableInput(value)) {
34250
+ return false;
34251
+ }
34034
34252
  return this.areJsonLikeInputsEqual(previousValue, value, new Set(), new Set());
34035
34253
  }
34036
34254
  areJsonLikeInputsEqual(previousValue, value, previousAncestors, valueAncestors) {
@@ -34182,6 +34400,9 @@ class DynamicWidgetLoaderDirective {
34182
34400
  }
34183
34401
  }
34184
34402
  resolveValue(raw, key, path = []) {
34403
+ if (isSignal(raw) || isObservable(raw) || isSubscribableInput(raw)) {
34404
+ return raw;
34405
+ }
34185
34406
  if (typeof raw === 'string') {
34186
34407
  if (this.isDeferredTemplateExpressionKey(key, path)) {
34187
34408
  return raw;
@@ -34279,7 +34500,11 @@ class DynamicWidgetLoaderDirective {
34279
34500
  const primitive = typeMap.get(expected) || 'any';
34280
34501
  if (!(metaInput.name in inputs) || primitive === 'any')
34281
34502
  continue;
34282
- const resolved = this.resolveValue(inputs[metaInput.name], metaInput.name, [metaInput.name]);
34503
+ const rawVal = inputs[metaInput.name];
34504
+ if (isSignal(rawVal) || isObservable(rawVal) || isSubscribableInput(rawVal)) {
34505
+ continue;
34506
+ }
34507
+ const resolved = this.resolveValue(rawVal, metaInput.name, [metaInput.name]);
34283
34508
  const coerced = this.coercePrimitive(resolved, primitive);
34284
34509
  // Atualiza inputs com valor possivelmente coerido, para bind subsequente
34285
34510
  inputs[metaInput.name] = coerced;
@@ -34385,6 +34610,9 @@ function isSubscribableOutput(value) {
34385
34610
  function isRecord(value) {
34386
34611
  return !!value && typeof value === 'object' && !Array.isArray(value);
34387
34612
  }
34613
+ function isSubscribableInput(value) {
34614
+ return !!value && typeof value.subscribe === 'function';
34615
+ }
34388
34616
 
34389
34617
  /** Private rendered geometry shared by shell recovery and canvas authoring. */
34390
34618
  function measureWidgetShellHeight(shell) {
@@ -34657,6 +34885,8 @@ const WIDGET_SHELL_I18N_CONFIG = {
34657
34885
  'controls.moreActions': 'Mais ações',
34658
34886
  'controls.expandContent': 'Expandir conteúdo',
34659
34887
  'controls.collapseContent': 'Recolher conteúdo',
34888
+ 'controls.expandWindow': 'Expandir em janela',
34889
+ 'controls.collapseWindow': 'Restaurar janela',
34660
34890
  'controls.exitFullscreen': 'Sair da tela cheia',
34661
34891
  'controls.enterFullscreen': 'Tela cheia',
34662
34892
  },
@@ -34665,6 +34895,8 @@ const WIDGET_SHELL_I18N_CONFIG = {
34665
34895
  'controls.moreActions': 'More actions',
34666
34896
  'controls.expandContent': 'Expand content',
34667
34897
  'controls.collapseContent': 'Collapse content',
34898
+ 'controls.expandWindow': 'Expand window',
34899
+ 'controls.collapseWindow': 'Restore window',
34668
34900
  'controls.exitFullscreen': 'Exit fullscreen',
34669
34901
  'controls.enterFullscreen': 'Fullscreen',
34670
34902
  },
@@ -35210,8 +35442,17 @@ class WidgetShellComponent {
35210
35442
  return [];
35211
35443
  const reserved = new Set(custom.map((a) => a.id));
35212
35444
  const actions = [];
35213
- const allowCollapse = this.shell?.windowActions?.collapsible !== false && !this.fullscreen;
35214
- const allowFullscreen = this.shell?.windowActions?.fullscreen !== false;
35445
+ const isExpandedWindow = this.expanded && !this.fullscreen;
35446
+ const isOverlay = this.expanded || this.fullscreen;
35447
+ const allowCollapse = this.shell?.windowActions?.collapsible !== false && !isOverlay;
35448
+ const maximizeMode = this.shell?.windowActions?.maximizeMode;
35449
+ const allowExpand = !this.fullscreen &&
35450
+ (maximizeMode === 'expand'
35451
+ ? this.shell?.windowActions?.expandable !== false
35452
+ : this.shell?.windowActions?.expandable === true);
35453
+ const allowFullscreen = maximizeMode === 'expand'
35454
+ ? this.shell?.windowActions?.fullscreen === true
35455
+ : this.shell?.windowActions?.fullscreen !== false;
35215
35456
  if (allowCollapse && !reserved.has('collapse')) {
35216
35457
  actions.push({
35217
35458
  id: 'collapse',
@@ -35223,6 +35464,17 @@ class WidgetShellComponent {
35223
35464
  variant: 'icon',
35224
35465
  });
35225
35466
  }
35467
+ if (allowExpand && !reserved.has('expand')) {
35468
+ actions.push({
35469
+ id: 'expand',
35470
+ placement: 'window',
35471
+ icon: isExpandedWindow ? 'ms:collapse_content' : 'ms:open_in_new',
35472
+ tooltip: isExpandedWindow
35473
+ ? this.t('controls.collapseWindow', 'Restaurar janela')
35474
+ : this.t('controls.expandWindow', 'Expandir em janela'),
35475
+ variant: 'icon',
35476
+ });
35477
+ }
35226
35478
  if (allowFullscreen && !reserved.has('fullscreen')) {
35227
35479
  actions.push({
35228
35480
  id: 'fullscreen',
@@ -35321,6 +35573,7 @@ class WidgetShellComponent {
35321
35573
  [style.--pdx-shell-card-shadow]="appearance?.card?.shadow || null"
35322
35574
  [class.pdx-shell--backdrop]="!!appearance?.card?.backdropFilter && appearance?.card?.backdropFilter !== 'none'"
35323
35575
  [style.--pdx-shell-card-filter]="appearance?.card?.backdropFilter || null"
35576
+ [style.--pdx-shell-card-backdrop-filter]="appearance?.card?.backdropFilter || null"
35324
35577
  [style.--pdx-shell-card-fallback-bg]="appearance?.card?.fallbackBackground || null"
35325
35578
  [style.--pdx-shell-header-bg]="appearance?.header?.background || null"
35326
35579
  [style.--pdx-shell-header-border-width]="appearance?.header?.borderWidth || null"
@@ -35518,7 +35771,7 @@ class WidgetShellComponent {
35518
35771
  @if (expanded || fullscreen) {
35519
35772
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
35520
35773
  }
35521
- `, isInline: true, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{--pdx-shell-card-border-width: initial;--pdx-shell-card-border-style: initial;--pdx-shell-header-border-width: initial;--pdx-shell-header-border-style: initial;--pdx-shell-card-filter: initial;--pdx-shell-card-fallback-bg: initial;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-width:var(--pdx-shell-card-border-width, 1px);border-style:var(--pdx-shell-card-border-style, solid);border-color: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.dashboard{-webkit-backdrop-filter:var(--pdx-shell-card-filter, none);backdrop-filter:var(--pdx-shell-card-filter, none)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface))}}@media(prefers-reduced-transparency:reduce){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}}.pdx-shell.dashboard.pdx-shell--backdrop.expanded,.pdx-shell.dashboard.pdx-shell--backdrop.fullscreen{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}.pdx-shell-header{flex-shrink:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px;border-bottom:var(--pdx-shell-header-border-width, 1px) var(--pdx-shell-header-border-style, 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 min(14rem,50%);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.praxis-icon-button:not(:disabled):not(.praxis-icon-button--pressed){color:var(--pdx-shell-icon-color, var(--md-sys-color-on-surface-variant))}.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.dashboard.pdx-shell--sticky-header{overflow:clip}.pdx-shell--sticky-header>.pdx-shell-header{position:sticky;top:var(--pdx-shell-sticky-header-offset, 0px);z-index:2;isolation:isolate;background:var(--md-sys-color-surface-container)}.pdx-shell--backdrop.pdx-shell--sticky-header>.pdx-shell-header{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface-container))}.pdx-shell--sticky-header>.pdx-shell-header:before{content:\"\";position:absolute;inset:0;z-index:-1;pointer-events:none;background:var(--pdx-shell-header-bg, transparent)}.pdx-shell--sticky-header>.pdx-shell-body{isolation:isolate}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 12px);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-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: "component", type: WidgetShellAvatarComponent, selector: "praxis-widget-shell-avatar", inputs: ["avatar"] }, { 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.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.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4.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 });
35774
+ `, isInline: true, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{--pdx-shell-card-border-width: initial;--pdx-shell-card-border-style: initial;--pdx-shell-header-border-width: initial;--pdx-shell-header-border-style: initial;--pdx-shell-card-filter: initial;--pdx-shell-card-fallback-bg: initial;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-width:var(--pdx-shell-card-border-width, 1px);border-style:var(--pdx-shell-card-border-style, solid);border-color: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) );backdrop-filter:var(--pdx-shell-card-backdrop-filter, none);-webkit-backdrop-filter:var(--pdx-shell-card-backdrop-filter, none);overflow:hidden}.pdx-shell.dashboard{-webkit-backdrop-filter:var(--pdx-shell-card-filter, none);backdrop-filter:var(--pdx-shell-card-filter, none)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface))}}@media(prefers-reduced-transparency:reduce){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}}.pdx-shell.dashboard.pdx-shell--backdrop.expanded,.pdx-shell.dashboard.pdx-shell--backdrop.fullscreen{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}.pdx-shell-header{flex-shrink:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px;border-bottom:var(--pdx-shell-header-border-width, 1px) var(--pdx-shell-header-border-style, 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 min(14rem,50%);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.praxis-icon-button:not(:disabled):not(.praxis-icon-button--pressed){color:var(--pdx-shell-icon-color, var(--md-sys-color-on-surface-variant))}.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.dashboard.pdx-shell--sticky-header{overflow:clip}.pdx-shell--sticky-header>.pdx-shell-header{position:sticky;top:var(--pdx-shell-sticky-header-offset, 0px);z-index:2;isolation:isolate;background:var(--md-sys-color-surface-container)}.pdx-shell--backdrop.pdx-shell--sticky-header>.pdx-shell-header{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface-container))}.pdx-shell--sticky-header>.pdx-shell-header:before{content:\"\";position:absolute;inset:0;z-index:-1;pointer-events:none;background:var(--pdx-shell-header-bg, transparent)}.pdx-shell--sticky-header>.pdx-shell-body{isolation:isolate}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 12px);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-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.expanded,.pdx-shell.fullscreen{background:var(--pdx-shell-overlay-bg, var(--md-sys-color-surface, #ffffff));color:var(--md-sys-color-on-surface)}.pdx-shell.fullscreen>.pdx-shell-body{padding:var(--pdx-shell-fullscreen-body-padding, 24px)}.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: "component", type: WidgetShellAvatarComponent, selector: "praxis-widget-shell-avatar", inputs: ["avatar"] }, { 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.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.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i4.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 });
35522
35775
  }
35523
35776
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellComponent, decorators: [{
35524
35777
  type: Component,
@@ -35566,6 +35819,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
35566
35819
  [style.--pdx-shell-card-shadow]="appearance?.card?.shadow || null"
35567
35820
  [class.pdx-shell--backdrop]="!!appearance?.card?.backdropFilter && appearance?.card?.backdropFilter !== 'none'"
35568
35821
  [style.--pdx-shell-card-filter]="appearance?.card?.backdropFilter || null"
35822
+ [style.--pdx-shell-card-backdrop-filter]="appearance?.card?.backdropFilter || null"
35569
35823
  [style.--pdx-shell-card-fallback-bg]="appearance?.card?.fallbackBackground || null"
35570
35824
  [style.--pdx-shell-header-bg]="appearance?.header?.background || null"
35571
35825
  [style.--pdx-shell-header-border-width]="appearance?.header?.borderWidth || null"
@@ -35763,7 +36017,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
35763
36017
  @if (expanded || fullscreen) {
35764
36018
  <div class="pdx-shell-backdrop" (click)="closeOverlay()"></div>
35765
36019
  }
35766
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{--pdx-shell-card-border-width: initial;--pdx-shell-card-border-style: initial;--pdx-shell-header-border-width: initial;--pdx-shell-header-border-style: initial;--pdx-shell-card-filter: initial;--pdx-shell-card-fallback-bg: initial;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-width:var(--pdx-shell-card-border-width, 1px);border-style:var(--pdx-shell-card-border-style, solid);border-color: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.dashboard{-webkit-backdrop-filter:var(--pdx-shell-card-filter, none);backdrop-filter:var(--pdx-shell-card-filter, none)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface))}}@media(prefers-reduced-transparency:reduce){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}}.pdx-shell.dashboard.pdx-shell--backdrop.expanded,.pdx-shell.dashboard.pdx-shell--backdrop.fullscreen{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}.pdx-shell-header{flex-shrink:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px;border-bottom:var(--pdx-shell-header-border-width, 1px) var(--pdx-shell-header-border-style, 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 min(14rem,50%);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.praxis-icon-button:not(:disabled):not(.praxis-icon-button--pressed){color:var(--pdx-shell-icon-color, var(--md-sys-color-on-surface-variant))}.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.dashboard.pdx-shell--sticky-header{overflow:clip}.pdx-shell--sticky-header>.pdx-shell-header{position:sticky;top:var(--pdx-shell-sticky-header-offset, 0px);z-index:2;isolation:isolate;background:var(--md-sys-color-surface-container)}.pdx-shell--backdrop.pdx-shell--sticky-header>.pdx-shell-header{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface-container))}.pdx-shell--sticky-header>.pdx-shell-header:before{content:\"\";position:absolute;inset:0;z-index:-1;pointer-events:none;background:var(--pdx-shell-header-bg, transparent)}.pdx-shell--sticky-header>.pdx-shell-body{isolation:isolate}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 12px);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-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"] }]
36020
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}:host(.pdx-widget-shell-collapsed){height:auto}.pdx-shell{--pdx-shell-card-border-width: initial;--pdx-shell-card-border-style: initial;--pdx-shell-header-border-width: initial;--pdx-shell-header-border-style: initial;--pdx-shell-card-filter: initial;--pdx-shell-card-fallback-bg: initial;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-width:var(--pdx-shell-card-border-width, 1px);border-style:var(--pdx-shell-card-border-style, solid);border-color: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) );backdrop-filter:var(--pdx-shell-card-backdrop-filter, none);-webkit-backdrop-filter:var(--pdx-shell-card-backdrop-filter, none);overflow:hidden}.pdx-shell.dashboard{-webkit-backdrop-filter:var(--pdx-shell-card-filter, none);backdrop-filter:var(--pdx-shell-card-filter, none)}@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface))}}@media(prefers-reduced-transparency:reduce){.pdx-shell.dashboard.pdx-shell--backdrop{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}}.pdx-shell.dashboard.pdx-shell--backdrop.expanded,.pdx-shell.dashboard.pdx-shell--backdrop.fullscreen{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface));-webkit-backdrop-filter:none;backdrop-filter:none}.pdx-shell-header{flex-shrink:0;display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px;border-bottom:var(--pdx-shell-header-border-width, 1px) var(--pdx-shell-header-border-style, 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 min(14rem,50%);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.praxis-icon-button:not(:disabled):not(.praxis-icon-button--pressed){color:var(--pdx-shell-icon-color, var(--md-sys-color-on-surface-variant))}.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.dashboard.pdx-shell--sticky-header{overflow:clip}.pdx-shell--sticky-header>.pdx-shell-header{position:sticky;top:var(--pdx-shell-sticky-header-offset, 0px);z-index:2;isolation:isolate;background:var(--md-sys-color-surface-container)}.pdx-shell--backdrop.pdx-shell--sticky-header>.pdx-shell-header{background:var(--pdx-shell-card-fallback-bg, var(--md-sys-color-surface-container))}.pdx-shell--sticky-header>.pdx-shell-header:before{content:\"\";position:absolute;inset:0;z-index:-1;pointer-events:none;background:var(--pdx-shell-header-bg, transparent)}.pdx-shell--sticky-header>.pdx-shell-body{isolation:isolate}.pdx-shell-body{flex:1;min-height:0;padding:var(--pdx-shell-body-padding, 12px);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-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.expanded,.pdx-shell.fullscreen{background:var(--pdx-shell-overlay-bg, var(--md-sys-color-surface, #ffffff));color:var(--md-sys-color-on-surface)}.pdx-shell.fullscreen>.pdx-shell-body{padding:var(--pdx-shell-fullscreen-body-padding, 24px)}.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"] }]
35767
36021
  }], ctorParameters: () => [], propDecorators: { hostCollapsed: [{
35768
36022
  type: HostBinding,
35769
36023
  args: ['class.pdx-widget-shell-collapsed']
@@ -36282,6 +36536,9 @@ function validateCanvasArrangement(page, source) {
36282
36536
  return null;
36283
36537
  }
36284
36538
 
36539
+ function isSubscribable$1(val) {
36540
+ return val != null && typeof val === 'object' && typeof val.subscribe === 'function';
36541
+ }
36285
36542
  class WidgetPageCompositionFactory {
36286
36543
  create(page) {
36287
36544
  const normalizedState = this.normalizeState(page.state);
@@ -36421,7 +36678,17 @@ class WidgetPageCompositionFactory {
36421
36678
  if (value == null || typeof value !== 'object') {
36422
36679
  return value;
36423
36680
  }
36424
- return JSON.parse(JSON.stringify(value));
36681
+ if (isSignal(value) || isObservable(value) || isSubscribable$1(value) || typeof value === 'function') {
36682
+ return value;
36683
+ }
36684
+ if (Array.isArray(value)) {
36685
+ return value.map((item) => this.clone(item));
36686
+ }
36687
+ const result = {};
36688
+ for (const [k, v] of Object.entries(value)) {
36689
+ result[k] = this.clone(v);
36690
+ }
36691
+ return result;
36425
36692
  }
36426
36693
  }
36427
36694
 
@@ -36719,11 +36986,16 @@ class WidgetPageStateRuntimeService {
36719
36986
  && ('values' in state || 'schema' in state || 'derived' in state);
36720
36987
  if (isStructured) {
36721
36988
  const structured = state;
36722
- return {
36989
+ const normalized = {
36723
36990
  values: this.clone(structured.values) || {},
36724
- schema: this.clone(structured.schema),
36725
- derived: this.clone(structured.derived),
36726
36991
  };
36992
+ if (structured.schema !== undefined) {
36993
+ normalized.schema = this.clone(structured.schema);
36994
+ }
36995
+ if (structured.derived !== undefined) {
36996
+ normalized.derived = this.clone(structured.derived);
36997
+ }
36998
+ return normalized;
36727
36999
  }
36728
37000
  return { values: this.clone(state) || {} };
36729
37001
  }
@@ -39223,6 +39495,9 @@ class RuntimeTraceService {
39223
39495
  }
39224
39496
  }
39225
39497
 
39498
+ function isSubscribable(val) {
39499
+ return val != null && typeof val === 'object' && typeof val.subscribe === 'function';
39500
+ }
39226
39501
  class CompositionRuntimeEngine {
39227
39502
  store;
39228
39503
  linkExecutor;
@@ -39814,7 +40089,17 @@ class CompositionRuntimeEngine {
39814
40089
  if (value == null || typeof value !== 'object') {
39815
40090
  return value;
39816
40091
  }
39817
- return JSON.parse(JSON.stringify(value));
40092
+ if (isSignal(value) || isObservable(value) || isSubscribable(value) || typeof value === 'function') {
40093
+ return value;
40094
+ }
40095
+ if (Array.isArray(value)) {
40096
+ return value.map((item) => this.cloneJson(item));
40097
+ }
40098
+ const result = {};
40099
+ for (const [k, v] of Object.entries(value)) {
40100
+ result[k] = this.cloneJson(v);
40101
+ }
40102
+ return result;
39818
40103
  }
39819
40104
  extractDerivedNodeKey(message) {
39820
40105
  const match = message.match(/Derived state '([^']+)'/);
@@ -43758,7 +44043,19 @@ class DynamicWidgetPageComponent {
43758
44043
  if (value == null || typeof value !== 'object') {
43759
44044
  return value;
43760
44045
  }
43761
- return JSON.parse(JSON.stringify(value));
44046
+ if (isSignal(value) || isObservable(value) || typeof value === 'function') {
44047
+ return value;
44048
+ }
44049
+ if (Array.isArray(value)) {
44050
+ return value.map((item) => this.cloneStateValues(item));
44051
+ }
44052
+ const result = {};
44053
+ for (const [k, v] of Object.entries(value)) {
44054
+ if (v !== undefined) {
44055
+ result[k] = this.cloneStateValues(v);
44056
+ }
44057
+ }
44058
+ return result;
43762
44059
  }
43763
44060
  cloneGrouping(grouping) {
43764
44061
  return this.cloneStateValues(grouping);
@@ -46729,6 +47026,89 @@ class DynamicWidgetPageComponent {
46729
47026
  getPageSnapshot() {
46730
47027
  return this.clonePageDefinition(this.ensurePageDefinition());
46731
47028
  }
47029
+ /**
47030
+ * Granularly updates a single input for a specific widget on the page without recreating
47031
+ * the canvas layout, rerendering neighboring widgets, or recalculating responsive breakpoints.
47032
+ * Returns true if the widget loader was found and the input was updated.
47033
+ */
47034
+ setWidgetInput(widgetKey, inputName, value) {
47035
+ const trimmedKey = typeof widgetKey === 'string' ? widgetKey.trim() : '';
47036
+ const trimmedInput = typeof inputName === 'string' ? inputName.trim() : '';
47037
+ if (!trimmedKey || !trimmedInput) {
47038
+ return false;
47039
+ }
47040
+ const loader = this.findWidgetLoader(trimmedKey);
47041
+ const success = loader?.setInput(trimmedInput, value) ?? false;
47042
+ // Keep all in-memory widget definition inputs aligned without triggering canvas re-evaluation
47043
+ const currentWidgets = this.widgets();
47044
+ const targetWidget = currentWidgets.find((w) => w.key === trimmedKey);
47045
+ if (targetWidget?.definition) {
47046
+ if (!targetWidget.definition.inputs) {
47047
+ targetWidget.definition.inputs = {};
47048
+ }
47049
+ targetWidget.definition.inputs[trimmedInput] = value;
47050
+ }
47051
+ if (this.pageDefinition?.widgets) {
47052
+ const pageDefWidget = this.pageDefinition.widgets.find((w) => w.key === trimmedKey);
47053
+ if (pageDefWidget?.definition) {
47054
+ if (!pageDefWidget.definition.inputs) {
47055
+ pageDefWidget.definition.inputs = {};
47056
+ }
47057
+ pageDefWidget.definition.inputs[trimmedInput] = value;
47058
+ }
47059
+ }
47060
+ if (this.authoredPageDefinition?.widgets) {
47061
+ const authoredWidget = this.authoredPageDefinition.widgets.find((w) => w.key === trimmedKey);
47062
+ if (authoredWidget?.definition) {
47063
+ if (!authoredWidget.definition.inputs) {
47064
+ authoredWidget.definition.inputs = {};
47065
+ }
47066
+ authoredWidget.definition.inputs[trimmedInput] = value;
47067
+ }
47068
+ }
47069
+ return success;
47070
+ }
47071
+ /**
47072
+ * Granularly patches multiple inputs for a specific widget on the page without recreating
47073
+ * the canvas layout, rerendering neighboring widgets, or recalculating responsive breakpoints.
47074
+ * Returns true if the widget loader was found and at least one input was updated.
47075
+ */
47076
+ patchWidgetInputs(widgetKey, inputPatch) {
47077
+ const trimmedKey = typeof widgetKey === 'string' ? widgetKey.trim() : '';
47078
+ if (!trimmedKey || !inputPatch || typeof inputPatch !== 'object') {
47079
+ return false;
47080
+ }
47081
+ const loader = this.findWidgetLoader(trimmedKey);
47082
+ const success = loader?.patchInputs(inputPatch) ?? false;
47083
+ // Keep all in-memory widget definition inputs aligned without triggering canvas re-evaluation
47084
+ const currentWidgets = this.widgets();
47085
+ const targetWidget = currentWidgets.find((w) => w.key === trimmedKey);
47086
+ if (targetWidget?.definition) {
47087
+ if (!targetWidget.definition.inputs) {
47088
+ targetWidget.definition.inputs = {};
47089
+ }
47090
+ Object.assign(targetWidget.definition.inputs, inputPatch);
47091
+ }
47092
+ if (this.pageDefinition?.widgets) {
47093
+ const pageDefWidget = this.pageDefinition.widgets.find((w) => w.key === trimmedKey);
47094
+ if (pageDefWidget?.definition) {
47095
+ if (!pageDefWidget.definition.inputs) {
47096
+ pageDefWidget.definition.inputs = {};
47097
+ }
47098
+ Object.assign(pageDefWidget.definition.inputs, inputPatch);
47099
+ }
47100
+ }
47101
+ if (this.authoredPageDefinition?.widgets) {
47102
+ const authoredWidget = this.authoredPageDefinition.widgets.find((w) => w.key === trimmedKey);
47103
+ if (authoredWidget?.definition) {
47104
+ if (!authoredWidget.definition.inputs) {
47105
+ authoredWidget.definition.inputs = {};
47106
+ }
47107
+ Object.assign(authoredWidget.definition.inputs, inputPatch);
47108
+ }
47109
+ }
47110
+ return success;
47111
+ }
46732
47112
  isCanvasWidgetBlocked(widgetKey) {
46733
47113
  return this.blockedCanvasWidgetKey === widgetKey;
46734
47114
  }
@@ -47452,11 +47832,92 @@ class DynamicWidgetPageComponent {
47452
47832
  }
47453
47833
  catch { }
47454
47834
  }
47835
+ cloneInputsPreservingLiveReferences(inputs) {
47836
+ if (!inputs || typeof inputs !== 'object') {
47837
+ return inputs;
47838
+ }
47839
+ const cloned = {};
47840
+ for (const [key, val] of Object.entries(inputs)) {
47841
+ if (val == null
47842
+ || typeof val !== 'object'
47843
+ || typeof val === 'function'
47844
+ || isSignal(val)
47845
+ || isObservable(val)) {
47846
+ cloned[key] = val;
47847
+ }
47848
+ else if (Array.isArray(val)) {
47849
+ cloned[key] = val.map((item) => item != null && typeof item === 'object' && !isSignal(item) && !isObservable(item)
47850
+ ? this.cloneInputsPreservingLiveReferences(item)
47851
+ : item);
47852
+ }
47853
+ else {
47854
+ cloned[key] = this.cloneInputsPreservingLiveReferences(val);
47855
+ }
47856
+ }
47857
+ return cloned;
47858
+ }
47859
+ cloneWidgetInstance(widget) {
47860
+ const clonedWidget = { ...widget };
47861
+ if (widget.shell) {
47862
+ clonedWidget.shell = { ...widget.shell };
47863
+ if (widget.shell.actions) {
47864
+ clonedWidget.shell.actions = [...widget.shell.actions];
47865
+ }
47866
+ }
47867
+ if (widget.definition) {
47868
+ clonedWidget.definition = { ...widget.definition };
47869
+ if (widget.definition.bindingOrder) {
47870
+ clonedWidget.definition.bindingOrder = [...widget.definition.bindingOrder];
47871
+ }
47872
+ if (widget.definition.outputs) {
47873
+ clonedWidget.definition.outputs = { ...widget.definition.outputs };
47874
+ }
47875
+ if (widget.definition.inputs) {
47876
+ clonedWidget.definition.inputs = this.cloneInputsPreservingLiveReferences(widget.definition.inputs);
47877
+ }
47878
+ }
47879
+ return clonedWidget;
47880
+ }
47455
47881
  clonePageDefinition(page) {
47456
- return JSON.parse(JSON.stringify(page));
47882
+ if (!page || typeof page !== 'object')
47883
+ return page;
47884
+ const cloned = {
47885
+ ...page,
47886
+ widgets: Array.isArray(page.widgets) ? this.cloneWidgets(page.widgets) : [],
47887
+ };
47888
+ if (page.layout) {
47889
+ cloned.layout = { ...page.layout };
47890
+ }
47891
+ if (page.grouping) {
47892
+ cloned.grouping = [...page.grouping];
47893
+ }
47894
+ if (page.canvas) {
47895
+ cloned.canvas = {
47896
+ ...page.canvas,
47897
+ items: page.canvas.items
47898
+ ? Object.fromEntries(Object.entries(page.canvas.items).map(([k, v]) => [k, { ...v }]))
47899
+ : {},
47900
+ };
47901
+ }
47902
+ if (page.context) {
47903
+ cloned.context = { ...page.context };
47904
+ }
47905
+ if (page.state) {
47906
+ const stateObj = {
47907
+ values: page.state.values ? { ...page.state.values } : {},
47908
+ };
47909
+ if (page.state.schema !== undefined)
47910
+ stateObj.schema = page.state.schema;
47911
+ if (page.state.derived !== undefined)
47912
+ stateObj.derived = page.state.derived;
47913
+ cloned.state = stateObj;
47914
+ }
47915
+ return cloned;
47457
47916
  }
47458
47917
  cloneWidgets(widgets) {
47459
- return JSON.parse(JSON.stringify(widgets));
47918
+ if (!Array.isArray(widgets))
47919
+ return [];
47920
+ return widgets.map((w) => this.cloneWidgetInstance(w));
47460
47921
  }
47461
47922
  applyGroupingOverrides(grouping, overrides) {
47462
47923
  if (!grouping?.length)