@praxisui/core 10.0.0-rc.26 → 10.0.0-rc.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -57,9 +57,10 @@ const preview = await firstValueFrom(bulkClient.readProposalResults(contract, pr
57
57
  await session.confirm(idempotencyKeyForThisIntent);
58
58
  // On an uncertain HTTP failure, retain this session and retry with the same key.
59
59
  // The host schedules further authorized readbacks for an accepted nonterminal execution.
60
- if (!session.isTerminal()) await session.refreshExecution();
60
+ const reads = new AbortController(); // This view owns GET lifetime, not confirmation custody.
61
+ if (!session.isTerminal()) await session.refreshExecution(reads.signal);
61
62
  if (session.isTerminal()) {
62
- const results = await session.readResults();
63
+ const results = await session.readResults(200, undefined, reads.signal);
63
64
  }
64
65
  ```
65
66
 
@@ -69,6 +70,24 @@ the descriptor. The caller controls when to read status again and presents each
69
70
  authorized page of results. This example is a service integration sketch, not a
70
71
  ready visual workflow or a deployment claim.
71
72
 
73
+ `refreshExecution(signal?)` and `readResults(size?, after?, signal?)` retain their
74
+ Promise API and optionally accept a standard `AbortSignal`. An already aborted
75
+ signal dispatches no GET; abort unsubscribes the actual HTTP request, releases the
76
+ read slot, and prevents a late Promise continuation from updating the session.
77
+ Abort listeners are removed on success, failure and cancellation. A cancelled GET
78
+ keeps the original proposal, confirmation key and accepted execution; it does not
79
+ mark that execution terminal or prove rollback. A new authorized read may observe
80
+ the same execution. Overlapping execution refreshes remain rejected, while an
81
+ aborted generation cannot release the slot of its successor.
82
+
83
+ The caller owns GET cancellation and its observation budget; the Core session does
84
+ not invent a global read timeout. Use a fresh read lifetime for a fresh consultation
85
+ and abort reads when the owning view closes. Do not race a Promise with a timer:
86
+ connect the signal to the read itself so the HTTP subscription is torn down.
87
+ `evaluate` and `confirm` do not accept this signal: a dispatched POST and its original
88
+ key stay in intent custody across view teardown. GET failure/cancellation must never
89
+ start a new evaluation or confirmation automatically.
90
+
72
91
  The backend is the authority on proposal expiry. A client clock hint must not
73
92
  block a same-key replay after an uncertain confirmation; the backend may return
74
93
  409 or 410 and the host must explain that state without inventing a new intent.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-15T19:07:41.629Z",
3
+ "generatedAt": "2026-10-15T22:42:56.841Z",
4
4
  "packageName": "@praxisui/core",
5
- "packageVersion": "10.0.0-rc.26",
5
+ "packageVersion": "10.0.0-rc.27",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 4,
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { Component, InjectionToken, Injectable, inject, Inject, Optional, SkipSelf, makeEnvironmentProviders, signal, computed, APP_INITIALIZER, 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, TemplateRef, Renderer2 } from '@angular/core';
3
3
  import * as i1 from '@angular/common/http';
4
4
  import { HttpHeaders, HttpClient, HttpParams, HttpResponse, HttpContextToken, HttpErrorResponse, 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, timer, switchMap as switchMap$1, catchError as catchError$1, forkJoin, isObservable, combineLatest, merge, Subscription, defaultIfEmpty, timeout as timeout$1 } from 'rxjs';
5
+ import { of, defer, throwError, from, EMPTY, BehaviorSubject, firstValueFrom, Subject, finalize as finalize$1, shareReplay as shareReplay$1, map as map$1, Observable, timer, switchMap as switchMap$1, catchError as catchError$1, forkJoin, isObservable, combineLatest, merge, Subscription, defaultIfEmpty, timeout as timeout$1 } from 'rxjs';
6
6
  import { switchMap, map, take, catchError, concatMap, tap, shareReplay, takeUntil, toArray, finalize, exhaustMap, filter, timeout } from 'rxjs/operators';
7
7
  import * as i1$3 from '@angular/common';
8
8
  import { Location, DOCUMENT, NgTemplateOutlet, CommonModule, NgComponentOutlet } from '@angular/common';
@@ -15529,6 +15529,9 @@ class BulkSyncSession {
15529
15529
  }, ...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
15530
15530
  confirmationKey = null;
15531
15531
  refreshInFlight = false;
15532
+ refreshGeneration = 0;
15533
+ refreshSignal;
15534
+ resultsGeneration = 0;
15532
15535
  ownedContract;
15533
15536
  options;
15534
15537
  /** Return detached wire data while retaining the original technical error for UX mapping. */
@@ -15607,17 +15610,25 @@ class BulkSyncSession {
15607
15610
  throw error;
15608
15611
  }
15609
15612
  }
15610
- async refreshExecution() {
15613
+ /** One cancellable consultation; the caller owns its deadline. POST custody is unchanged. */
15614
+ async refreshExecution(signal) {
15615
+ this.requireReadLifetime(signal);
15611
15616
  const current = this.current();
15612
15617
  if (!current.execution)
15613
15618
  throw new Error('No accepted execution is known to this session.');
15614
15619
  if (isBulkExecutionTerminal(current.execution.status))
15615
15620
  return structuredClone(current.execution);
15616
- if (this.refreshInFlight)
15621
+ if (this.refreshInFlight && !this.refreshSignal?.aborted) {
15617
15622
  throw new Error('An execution readback is already in flight.');
15623
+ }
15624
+ const generation = ++this.refreshGeneration;
15618
15625
  this.refreshInFlight = true;
15626
+ this.refreshSignal = signal;
15619
15627
  try {
15620
- const execution = await firstValueFrom(this.client.readExecution(this.ownedContract, current.execution.executionId, this.options));
15628
+ const execution = await this.readValue(() => this.client.readExecution(this.ownedContract, current.execution.executionId, this.options), signal);
15629
+ this.requireReadLifetime(signal);
15630
+ if (generation !== this.refreshGeneration)
15631
+ throw this.readAborted();
15621
15632
  if (execution.proposalId !== current.execution.proposalId) {
15622
15633
  throw new Error('Execution readback changed the proposal identity.');
15623
15634
  }
@@ -15626,25 +15637,63 @@ class BulkSyncSession {
15626
15637
  return structuredClone(execution);
15627
15638
  }
15628
15639
  catch (error) {
15629
- this.fail(error);
15640
+ if (generation === this.refreshGeneration && !signal?.aborted)
15641
+ this.fail(error);
15630
15642
  throw error;
15631
15643
  }
15632
15644
  finally {
15633
- this.refreshInFlight = false;
15645
+ if (generation === this.refreshGeneration) {
15646
+ this.refreshInFlight = false;
15647
+ this.refreshSignal = undefined;
15648
+ }
15634
15649
  }
15635
15650
  }
15636
- async readResults(size = 200, after) {
15651
+ /** Cancels only this results GET; an abort never discards the accepted execution. */
15652
+ async readResults(size = 200, after, signal) {
15653
+ this.requireReadLifetime(signal);
15654
+ const generation = ++this.resultsGeneration;
15637
15655
  const execution = this.current().execution;
15638
15656
  if (!execution)
15639
15657
  throw new Error('Results require an accepted execution.');
15640
15658
  try {
15641
- return await firstValueFrom(this.client.readResults(this.ownedContract, execution.executionId, size, after, this.options));
15659
+ return await this.readValue(() => this.client.readResults(this.ownedContract, execution.executionId, size, after, this.options), signal);
15642
15660
  }
15643
15661
  catch (error) {
15644
- this.current.set({ ...this.current(), error });
15662
+ if (generation === this.resultsGeneration && !signal?.aborted) {
15663
+ this.current.set({ ...this.current(), error });
15664
+ }
15645
15665
  throw error;
15646
15666
  }
15647
15667
  }
15668
+ readAborted() {
15669
+ return new DOMException('Bulk observation was cancelled.', 'AbortError');
15670
+ }
15671
+ requireReadLifetime(signal) {
15672
+ if (signal?.aborted)
15673
+ throw this.readAborted();
15674
+ }
15675
+ /** Cancellation owns the HTTP subscription, not just its Promise observer. */
15676
+ async readValue(read, signal) {
15677
+ this.requireReadLifetime(signal);
15678
+ const value = await firstValueFrom(new Observable(subscriber => {
15679
+ if (signal?.aborted) {
15680
+ subscriber.error(this.readAborted());
15681
+ return;
15682
+ }
15683
+ const abort = () => subscriber.error(this.readAborted());
15684
+ signal?.addEventListener('abort', abort, { once: true });
15685
+ // defer converts a synchronous client failure into an Observable failure,
15686
+ // so the listener is removed by the same teardown on every path.
15687
+ const subscription = defer(read).subscribe(subscriber);
15688
+ return () => {
15689
+ subscription.unsubscribe();
15690
+ signal?.removeEventListener('abort', abort);
15691
+ };
15692
+ }));
15693
+ // Abort may occur after HTTP next but before this Promise continuation.
15694
+ this.requireReadLifetime(signal);
15695
+ return value;
15696
+ }
15648
15697
  fail(error) {
15649
15698
  this.current.set({ ...this.current(), phase: 'error', error });
15650
15699
  }
@@ -27004,15 +27053,30 @@ function removeValueAtPath(target, path) {
27004
27053
  if (!segments.length) {
27005
27054
  return;
27006
27055
  }
27056
+ const parents = [];
27007
27057
  let current = target;
27008
27058
  for (const segment of segments.slice(0, -1)) {
27009
27059
  const next = current[segment];
27010
27060
  if (!next || typeof next !== 'object' || Array.isArray(next)) {
27011
27061
  return;
27012
27062
  }
27063
+ parents.push({ parent: current, key: segment });
27013
27064
  current = next;
27014
27065
  }
27015
27066
  delete current[segments[segments.length - 1]];
27067
+ for (let i = parents.length - 1; i >= 0; i -= 1) {
27068
+ const { parent, key } = parents[i];
27069
+ const child = parent[key];
27070
+ if (child &&
27071
+ typeof child === 'object' &&
27072
+ !Array.isArray(child) &&
27073
+ Object.keys(child).length === 0) {
27074
+ delete parent[key];
27075
+ }
27076
+ else {
27077
+ break;
27078
+ }
27079
+ }
27016
27080
  }
27017
27081
  function normalizeEndpoint(endpoint) {
27018
27082
  if (endpoint.kind === 'component-port') {
@@ -39273,7 +39337,10 @@ class WidgetPageCompositionFactory {
39273
39337
  }
39274
39338
  const isStructured = typeof state === 'object'
39275
39339
  && !Array.isArray(state)
39276
- && ('values' in state || 'schema' in state || 'derived' in state);
39340
+ && ('values' in state ||
39341
+ 'schema' in state ||
39342
+ 'derived' in state ||
39343
+ 'transientValues' in state);
39277
39344
  if (isStructured) {
39278
39345
  const structured = state;
39279
39346
  return {
@@ -39632,7 +39699,10 @@ class WidgetPageStateRuntimeService {
39632
39699
  return { values: {} };
39633
39700
  const isStructured = typeof state === 'object'
39634
39701
  && !Array.isArray(state)
39635
- && ('values' in state || 'schema' in state || 'derived' in state);
39702
+ && ('values' in state ||
39703
+ 'schema' in state ||
39704
+ 'derived' in state ||
39705
+ 'transientValues' in state);
39636
39706
  if (isStructured) {
39637
39707
  const structured = state;
39638
39708
  const normalized = {
@@ -46069,6 +46139,9 @@ class DynamicWidgetPageComponent {
46069
46139
  injector = inject(Injector);
46070
46140
  settingsSessions = new Map();
46071
46141
  widgetSettingsSession;
46142
+ activeSettingsPanelSession;
46143
+ activeSettingsFocusReturnTarget = null;
46144
+ pendingContextNavigationFocusTarget;
46072
46145
  settingsIdentityRevision = 0;
46073
46146
  acceptedPageIdentity;
46074
46147
  storage = inject(ASYNC_CONFIG_STORAGE);
@@ -46237,13 +46310,15 @@ class DynamicWidgetPageComponent {
46237
46310
  // Controlled hosts return pageChange through [page]. That acknowledgement
46238
46311
  // must not dispose the open settings provider or rebuild its size template.
46239
46312
  // Any other input change or different document still invalidates the editor.
46240
- if (this.widgetSettingsKey && changes['page'] && Object.keys(changes).length === 1
46241
- && this.authoredPageDefinition
46242
- && this.sameJsonStructure(this.parsePage(this.page), this.authoredPageDefinition))
46313
+ if (this.widgetSettingsKey &&
46314
+ changes['page'] &&
46315
+ Object.keys(changes).length === 1 &&
46316
+ this.isAcknowledgedCanonicalPage(incomingPage)) {
46243
46317
  return;
46244
- const acknowledgedPage = changes['page'] && Object.keys(changes).length === 1
46245
- && this.authoredPageDefinition
46246
- && this.sameJsonStructure(this.parsePage(this.page), this.authoredPageDefinition);
46318
+ }
46319
+ const acknowledgedPage = changes['page'] &&
46320
+ Object.keys(changes).length === 1 &&
46321
+ this.isAcknowledgedCanonicalPage(incomingPage);
46247
46322
  if (!acknowledgedPage && (changes['page'] || changes['context'] || changes['pageIdentity']
46248
46323
  || changes['componentInstanceId'] || changes['enableCustomization'] || changes['authoringCapabilities'])) {
46249
46324
  this.settingsIdentityRevision++;
@@ -46270,6 +46345,8 @@ class DynamicWidgetPageComponent {
46270
46345
  if (changes['page'] ||
46271
46346
  changes['context'] ||
46272
46347
  changes['pageIdentity']) {
46348
+ const previousPageDefinition = this.pageDefinition;
46349
+ const previousPageRuntime = this.pageRuntime;
46273
46350
  const parsed = this.parsePage(this.page);
46274
46351
  if (changes['page'] || !this.authoredPageDefinition) {
46275
46352
  this.authoredPageDefinition = undefined;
@@ -46280,7 +46357,17 @@ class DynamicWidgetPageComponent {
46280
46357
  })
46281
46358
  : undefined;
46282
46359
  }
46283
- const resolvedPage = parsed ? this.resolvePagePresets(parsed) : parsed;
46360
+ const shouldPreserveEphemeralState = !this.isHydrating &&
46361
+ !changes['page']?.isFirstChange() &&
46362
+ !changes['pageIdentity'] &&
46363
+ !changes['componentInstanceId'] &&
46364
+ this.samePageContextIdentity(this.pageDefinition, parsed);
46365
+ const runtimeSeedPage = shouldPreserveEphemeralState && parsed
46366
+ ? this.preserveEphemeralRuntimeState(parsed)
46367
+ : parsed;
46368
+ const resolvedPage = runtimeSeedPage
46369
+ ? this.resolvePagePresets(runtimeSeedPage)
46370
+ : runtimeSeedPage;
46284
46371
  this.assertNoLegacyConnections(resolvedPage);
46285
46372
  this.widgetDiagnostics = {};
46286
46373
  this.widgetDiagnosticsChange.emit({});
@@ -46300,6 +46387,10 @@ class DynamicWidgetPageComponent {
46300
46387
  }
46301
46388
  this.pageRuntime = this.buildStateRuntime(this.pageDefinition?.state, this.pageDefinition?.context);
46302
46389
  this.pageState = this.pageRuntime.state;
46390
+ const resetNonPersistentPaths = this.collectResetNonPersistentStatePaths(previousPageDefinition, previousPageRuntime, this.pageDefinition, this.pageRuntime);
46391
+ if (resetNonPersistentPaths.length > 0) {
46392
+ this.clearMountedSourceSelectionsForNonPersistentState([previousPageDefinition, this.pageDefinition], resetNonPersistentPaths);
46393
+ }
46303
46394
  const bootstrapSnapshot = this.bootstrapCompositionAdapter(this.pageDefinition);
46304
46395
  const rawWidgets = this.pageDefinition?.widgets || [];
46305
46396
  let widgets = this.applyEditShellActions(rawWidgets);
@@ -48251,6 +48342,10 @@ class DynamicWidgetPageComponent {
48251
48342
  return session;
48252
48343
  }
48253
48344
  releaseSettingsSession(session) {
48345
+ if (this.activeSettingsPanelSession === session) {
48346
+ this.activeSettingsPanelSession = undefined;
48347
+ this.activeSettingsFocusReturnTarget = null;
48348
+ }
48254
48349
  this.settingsSessions.delete(session);
48255
48350
  if (!session.destroyed)
48256
48351
  session.destroy();
@@ -48261,6 +48356,7 @@ class DynamicWidgetPageComponent {
48261
48356
  this.releaseSettingsSession(session);
48262
48357
  }
48263
48358
  if (key === undefined) {
48359
+ this.pendingContextNavigationFocusTarget = undefined;
48264
48360
  this.configEditorContextRequests.clear();
48265
48361
  this.pendingWidgetComponentSettings.set(new Set());
48266
48362
  }
@@ -48295,12 +48391,14 @@ class DynamicWidgetPageComponent {
48295
48391
  label: this.widgetSettingsLabel(),
48296
48392
  icon: 'settings',
48297
48393
  disabled: !canWidget,
48394
+ editorGroup: 'widget-shell',
48298
48395
  },
48299
48396
  {
48300
48397
  id: 'size',
48301
48398
  label: this.sizeEditorLabel(),
48302
48399
  icon: 'straighten',
48303
48400
  disabled: !canSize,
48401
+ editorGroup: 'widget-shell',
48304
48402
  },
48305
48403
  ],
48306
48404
  activeModeId: activeMode,
@@ -48344,6 +48442,9 @@ class DynamicWidgetPageComponent {
48344
48442
  else if (mode === 'size' && !canSize) {
48345
48443
  mode = canWidget ? 'widget' : canContent ? 'content' : 'size';
48346
48444
  }
48445
+ this.pendingContextNavigationFocusTarget = {
48446
+ target: this.activeSettingsFocusReturnTarget,
48447
+ };
48347
48448
  if (mode === 'content') {
48348
48449
  void this.openWidgetComponentSettings(targetKey);
48349
48450
  }
@@ -48351,10 +48452,15 @@ class DynamicWidgetPageComponent {
48351
48452
  this.openWidgetSettingsPanel(targetKey, mode);
48352
48453
  }
48353
48454
  }
48455
+ resolveSettingsFocusReturnTarget() {
48456
+ const pending = this.pendingContextNavigationFocusTarget;
48457
+ this.pendingContextNavigationFocusTarget = undefined;
48458
+ return pending ? pending.target : this.captureFocusReturnTarget();
48459
+ }
48354
48460
  openWidgetSettingsPanel(key, initialTab) {
48355
48461
  if (this.destroyed || !this.settingsPanel)
48356
48462
  return;
48357
- const focusReturnTarget = this.captureFocusReturnTarget();
48463
+ const focusReturnTarget = this.resolveSettingsFocusReturnTarget();
48358
48464
  const page = this.ensurePageDefinition();
48359
48465
  const widget = page.widgets.find(item => item.key === key);
48360
48466
  if (!widget)
@@ -48365,6 +48471,10 @@ class DynamicWidgetPageComponent {
48365
48471
  const session = this.createSettingsSession(key);
48366
48472
  const owner = session.get(DestroyRef);
48367
48473
  const contextNavigation = this.buildWidgetSettingsContextNavigation(key, initialTab);
48474
+ const previousActiveSession = this.activeSettingsPanelSession;
48475
+ const previousFocusTarget = this.activeSettingsFocusReturnTarget;
48476
+ this.activeSettingsPanelSession = session;
48477
+ this.activeSettingsFocusReturnTarget = focusReturnTarget;
48368
48478
  let ref;
48369
48479
  try {
48370
48480
  ref = this.settingsPanel.open({
@@ -48377,7 +48487,10 @@ class DynamicWidgetPageComponent {
48377
48487
  const page = this.ensurePageDefinition();
48378
48488
  const widget = page.widgets.find(item => item.key === key);
48379
48489
  const uiShell = this.mergedContext['ui']?.shell || {};
48490
+ this.activeSettingsPanelSession = session;
48491
+ this.activeSettingsFocusReturnTarget = focusReturnTarget;
48380
48492
  this.closeSizeEditor(false);
48493
+ this.selectWidget(key);
48381
48494
  this.prepareSizeEditor(key);
48382
48495
  this.widgetSettingsKey = key;
48383
48496
  this.widgetSettingsSession = session;
@@ -48407,6 +48520,10 @@ class DynamicWidgetPageComponent {
48407
48520
  });
48408
48521
  }
48409
48522
  catch (error) {
48523
+ if (this.activeSettingsPanelSession === session) {
48524
+ this.activeSettingsPanelSession = previousActiveSession;
48525
+ this.activeSettingsFocusReturnTarget = previousFocusTarget;
48526
+ }
48410
48527
  if (this.widgetSettingsSession === session)
48411
48528
  this.closeSizeEditor(false);
48412
48529
  else
@@ -48416,15 +48533,27 @@ class DynamicWidgetPageComponent {
48416
48533
  ref.applied$.pipe(takeUntilDestroyed(owner)).subscribe(value => this.commitWidgetSettings(key, value, false));
48417
48534
  ref.saved$.pipe(takeUntilDestroyed(owner)).subscribe(value => this.commitWidgetSettings(key, value, true));
48418
48535
  ref.closed$?.pipe(take(1), takeUntilDestroyed(owner)).subscribe(() => {
48419
- const active = this.widgetSettingsSession === session;
48420
- if (active) {
48536
+ const wasActiveWidgetSettings = this.widgetSettingsSession === session;
48537
+ const wasActivePanelSession = this.activeSettingsPanelSession === session;
48538
+ if (wasActivePanelSession &&
48539
+ !wasActiveWidgetSettings &&
48540
+ previousActiveSession &&
48541
+ !previousActiveSession.destroyed) {
48542
+ this.activeSettingsPanelSession = previousActiveSession;
48543
+ this.activeSettingsFocusReturnTarget = previousFocusTarget;
48544
+ this.releaseSettingsSession(session);
48545
+ return;
48546
+ }
48547
+ if (wasActiveWidgetSettings) {
48421
48548
  this.widgetSettingsSelectTab = undefined;
48422
48549
  this.closeSizeEditor(false);
48423
48550
  }
48424
- else
48551
+ else {
48425
48552
  this.releaseSettingsSession(session);
48426
- if (active)
48553
+ }
48554
+ if (wasActivePanelSession) {
48427
48555
  this.restoreFocus(focusReturnTarget);
48556
+ }
48428
48557
  });
48429
48558
  }
48430
48559
  sizeEditorLayoutItems() {
@@ -48561,6 +48690,7 @@ class DynamicWidgetPageComponent {
48561
48690
  } });
48562
48691
  }
48563
48692
  async openWidgetComponentSettings(key) {
48693
+ const focusReturnTarget = this.resolveSettingsFocusReturnTarget();
48564
48694
  if (this.destroyed || !this.canOpenWidgetComponentSettings(key))
48565
48695
  return;
48566
48696
  if (!this.settingsPanel) {
@@ -48582,7 +48712,6 @@ class DynamicWidgetPageComponent {
48582
48712
  const materializedInputs = metadata.configEditor?.contextResolver
48583
48713
  ? this.readMaterializedInputsForWidget(metadata, key)
48584
48714
  : undefined;
48585
- const focusReturnTarget = this.captureFocusReturnTarget();
48586
48715
  const session = this.createSettingsSession(key);
48587
48716
  const owner = session.get(DestroyRef);
48588
48717
  let opened = false;
@@ -48602,6 +48731,12 @@ class DynamicWidgetPageComponent {
48602
48731
  const appliedValues = new Subject();
48603
48732
  owner.onDestroy(() => appliedValues.complete());
48604
48733
  const contextNavigation = this.buildWidgetSettingsContextNavigation(key, 'content');
48734
+ const previousActiveSession = this.activeSettingsPanelSession;
48735
+ const previousFocusTarget = this.activeSettingsFocusReturnTarget;
48736
+ const previousSelectedWidgetKey = this.selectedWidgetKeyState();
48737
+ this.activeSettingsPanelSession = session;
48738
+ this.activeSettingsFocusReturnTarget = focusReturnTarget;
48739
+ this.selectWidget(key);
48605
48740
  const ref = this.settingsPanel.open({
48606
48741
  owner,
48607
48742
  id: `dynamic-page-component:${key}`,
@@ -48631,8 +48766,22 @@ class DynamicWidgetPageComponent {
48631
48766
  });
48632
48767
  ref.saved$.pipe(takeUntilDestroyed(owner)).subscribe((result) => this.applyWidgetComponentInputs(key, result, true));
48633
48768
  ref.closed$?.pipe(take(1), takeUntilDestroyed(owner)).subscribe(() => {
48769
+ const wasActivePanelSession = this.activeSettingsPanelSession === session;
48770
+ if (wasActivePanelSession &&
48771
+ previousActiveSession &&
48772
+ !previousActiveSession.destroyed) {
48773
+ this.activeSettingsPanelSession = previousActiveSession;
48774
+ this.activeSettingsFocusReturnTarget = previousFocusTarget;
48775
+ if (previousSelectedWidgetKey) {
48776
+ this.selectWidget(previousSelectedWidgetKey);
48777
+ }
48778
+ this.releaseSettingsSession(session);
48779
+ return;
48780
+ }
48634
48781
  this.releaseSettingsSession(session);
48635
- this.restoreFocus(focusReturnTarget);
48782
+ if (wasActivePanelSession) {
48783
+ this.restoreFocus(focusReturnTarget);
48784
+ }
48636
48785
  });
48637
48786
  }
48638
48787
  finally {
@@ -48668,6 +48817,8 @@ class DynamicWidgetPageComponent {
48668
48817
  restoreFocus(target) {
48669
48818
  queueMicrotask(() => {
48670
48819
  if (!this.destroyed
48820
+ && !this.activeSettingsPanelSession
48821
+ && this.pendingWidgetComponentSettings().size === 0
48671
48822
  && target?.isConnected
48672
48823
  && !target.hasAttribute('disabled')
48673
48824
  && target.getAttribute('aria-disabled') !== 'true') {
@@ -48977,6 +49128,7 @@ class DynamicWidgetPageComponent {
48977
49128
  return (endpoint.kind === 'component-port' && endpoint.ref.widget === widgetKey);
48978
49129
  }
48979
49130
  openPageSettings() {
49131
+ const focusReturnTarget = this.resolveSettingsFocusReturnTarget();
48980
49132
  if (this.destroyed || !this.canInvokePageSettings())
48981
49133
  return;
48982
49134
  if (!this.settingsPanel)
@@ -48991,6 +49143,10 @@ class DynamicWidgetPageComponent {
48991
49143
  const owner = session.get(DestroyRef);
48992
49144
  const appliedValues = new Subject();
48993
49145
  owner.onDestroy(() => appliedValues.complete());
49146
+ const previousActiveSession = this.activeSettingsPanelSession;
49147
+ const previousFocusTarget = this.activeSettingsFocusReturnTarget;
49148
+ this.activeSettingsPanelSession = session;
49149
+ this.activeSettingsFocusReturnTarget = focusReturnTarget;
48994
49150
  const ref = this.settingsPanel.open({
48995
49151
  owner,
48996
49152
  id: 'dynamic-page-settings',
@@ -49020,7 +49176,21 @@ class DynamicWidgetPageComponent {
49020
49176
  appliedValues.next(accepted);
49021
49177
  });
49022
49178
  ref.saved$.pipe(takeUntilDestroyed(owner)).subscribe((result) => this.applyPageLayout(result, true));
49023
- ref.closed$?.pipe(take(1), takeUntilDestroyed(owner)).subscribe(() => this.releaseSettingsSession(session));
49179
+ ref.closed$?.pipe(take(1), takeUntilDestroyed(owner)).subscribe(() => {
49180
+ const wasActivePanelSession = this.activeSettingsPanelSession === session;
49181
+ if (wasActivePanelSession &&
49182
+ previousActiveSession &&
49183
+ !previousActiveSession.destroyed) {
49184
+ this.activeSettingsPanelSession = previousActiveSession;
49185
+ this.activeSettingsFocusReturnTarget = previousFocusTarget;
49186
+ this.releaseSettingsSession(session);
49187
+ return;
49188
+ }
49189
+ this.releaseSettingsSession(session);
49190
+ if (wasActivePanelSession) {
49191
+ this.restoreFocus(focusReturnTarget);
49192
+ }
49193
+ });
49024
49194
  }
49025
49195
  canInvokePageSettings() {
49026
49196
  return this.isAuthoringCapabilityEnabled('pageSettings')
@@ -49153,11 +49323,227 @@ class DynamicWidgetPageComponent {
49153
49323
  }, persist);
49154
49324
  }
49155
49325
  applyAuthoringPageUpdate(next, persist = true, runtime, syncCompositionAdapter = true, skipStateWidgetProjection = false, emitUnchangedCanonicalPage = true) {
49156
- this.applyPageUpdate(next, persist, runtime, syncCompositionAdapter, skipStateWidgetProjection, emitUnchangedCanonicalPage);
49326
+ const runtimeSeed = !runtime && !this.isHydrating
49327
+ ? (this.preserveEphemeralRuntimeState(next) ?? next)
49328
+ : next;
49329
+ this.applyPageUpdate(runtimeSeed, persist, runtime, syncCompositionAdapter, skipStateWidgetProjection, emitUnchangedCanonicalPage);
49157
49330
  if (this.authoredPageDefinition) {
49158
49331
  this.pageAuthoringChange.emit(this.clonePageDefinition(this.authoredPageDefinition));
49159
49332
  }
49160
49333
  }
49334
+ isAcknowledgedCanonicalPage(incomingPage) {
49335
+ if (!incomingPage || !this.authoredPageDefinition) {
49336
+ return false;
49337
+ }
49338
+ if (this.sameJsonStructure(incomingPage, this.authoredPageDefinition)) {
49339
+ return true;
49340
+ }
49341
+ if (this.hasExplicitNonPersistentStateOverride(incomingPage)) {
49342
+ return false;
49343
+ }
49344
+ const normalizedIncoming = this.toPersistedCanonicalPage({
49345
+ ...incomingPage,
49346
+ state: this.stateRuntime.normalizeState(incomingPage.state),
49347
+ });
49348
+ return this.sameJsonStructure(normalizedIncoming, this.authoredPageDefinition);
49349
+ }
49350
+ hasExplicitNonPersistentStateOverride(page) {
49351
+ const schema = page?.state?.schema || {};
49352
+ const values = page?.state?.values;
49353
+ if (!values || typeof values !== 'object') {
49354
+ return false;
49355
+ }
49356
+ for (const rawPath of Object.keys(schema)) {
49357
+ const entry = schema[rawPath];
49358
+ if (entry?.persist !== false) {
49359
+ continue;
49360
+ }
49361
+ const path = rawPath.trim();
49362
+ if (!path) {
49363
+ continue;
49364
+ }
49365
+ const value = this.conn.extractByPath(values, path);
49366
+ if (value !== undefined && !this.sameJsonStructure(value, entry.initial)) {
49367
+ return true;
49368
+ }
49369
+ }
49370
+ return false;
49371
+ }
49372
+ collectResetNonPersistentStatePaths(previousPage, previousRuntime, nextPage, nextRuntime) {
49373
+ if (!previousPage || !previousRuntime || !nextRuntime) {
49374
+ return [];
49375
+ }
49376
+ const previousSchema = previousPage.state?.schema ?? {};
49377
+ const nextSchema = nextPage?.state?.schema ?? {};
49378
+ const candidatePaths = new Set([
49379
+ ...Object.keys(previousSchema).filter((path) => previousSchema[path]?.persist === false),
49380
+ ...Object.keys(nextSchema).filter((path) => nextSchema[path]?.persist === false),
49381
+ ]);
49382
+ const resetPaths = [];
49383
+ for (const rawPath of candidatePaths) {
49384
+ const path = rawPath.trim();
49385
+ if (!path) {
49386
+ continue;
49387
+ }
49388
+ const prevEntry = previousSchema[rawPath] ?? nextSchema[rawPath];
49389
+ const nextEntry = nextSchema[rawPath] ?? previousSchema[rawPath];
49390
+ const prevValue = this.conn.extractByPath(previousRuntime.primaryValues, path);
49391
+ const hadLiveSelection = prevValue !== undefined &&
49392
+ !this.sameJsonStructure(prevValue, prevEntry?.initial);
49393
+ if (!hadLiveSelection) {
49394
+ continue;
49395
+ }
49396
+ const nextValue = this.conn.extractByPath(nextRuntime.primaryValues, path);
49397
+ const isNowReset = nextValue === undefined ||
49398
+ this.sameJsonStructure(nextValue, nextEntry?.initial);
49399
+ if (isNowReset) {
49400
+ resetPaths.push(path);
49401
+ }
49402
+ }
49403
+ return [...new Set(resetPaths)];
49404
+ }
49405
+ samePageContextIdentity(left, right) {
49406
+ if (!left || !right) {
49407
+ return false;
49408
+ }
49409
+ const leftPageId = left.context?.['pageId'] ?? null;
49410
+ const rightPageId = right.context?.['pageId'] ?? null;
49411
+ if (leftPageId !== rightPageId) {
49412
+ return false;
49413
+ }
49414
+ if (leftPageId !== null) {
49415
+ return true;
49416
+ }
49417
+ const leftKeys = new Set((left.widgets || []).map((w) => w.key));
49418
+ const rightKeys = (right.widgets || []).map((w) => w.key);
49419
+ if (leftKeys.size === 0 && rightKeys.length === 0) {
49420
+ return true;
49421
+ }
49422
+ return rightKeys.some((key) => leftKeys.has(key));
49423
+ }
49424
+ preserveEphemeralRuntimeState(incomingPage) {
49425
+ if (!incomingPage || !this.pageRuntime || this.isHydrating) {
49426
+ return incomingPage;
49427
+ }
49428
+ const schema = incomingPage.state?.schema || {};
49429
+ const nonPersistentPaths = Object.keys(schema)
49430
+ .filter((path) => schema[path]?.persist === false)
49431
+ .map((path) => path.trim())
49432
+ .filter(Boolean);
49433
+ if (!nonPersistentPaths.length) {
49434
+ return incomingPage;
49435
+ }
49436
+ const incomingWidgets = new Set((incomingPage.widgets || []).map((widget) => widget.key));
49437
+ const incomingLinks = incomingPage.composition?.links || [];
49438
+ const previousLinks = this.pageDefinition?.composition?.links || incomingLinks;
49439
+ let mergedValues = this.cloneStateValues(incomingPage.state?.values || {});
49440
+ let preservedAny = false;
49441
+ for (const path of nonPersistentPaths) {
49442
+ const schemaEntry = schema[path];
49443
+ const incomingValue = this.conn.extractByPath(mergedValues, path);
49444
+ const hasExplicitIncomingOverride = incomingValue !== undefined &&
49445
+ !this.sameJsonStructure(incomingValue, schemaEntry?.initial);
49446
+ if (hasExplicitIncomingOverride) {
49447
+ continue;
49448
+ }
49449
+ const previousWriterWidgets = previousLinks.filter((link) => link.from.kind === 'component-port' &&
49450
+ link.to.kind === 'state' &&
49451
+ this.isSameOrNestedStatePath(link.to.ref.path, path));
49452
+ if (previousWriterWidgets.length > 0) {
49453
+ const hasActiveWriter = incomingLinks.some((link) => link.from.kind === 'component-port' &&
49454
+ link.to.kind === 'state' &&
49455
+ this.isSameOrNestedStatePath(link.to.ref.path, path) &&
49456
+ incomingWidgets.has(link.from.ref.widget));
49457
+ if (!hasActiveWriter) {
49458
+ continue;
49459
+ }
49460
+ }
49461
+ const liveValue = this.conn.extractByPath(this.pageRuntime.primaryValues, path);
49462
+ if (liveValue === undefined) {
49463
+ continue;
49464
+ }
49465
+ mergedValues = this.conn.setValueAtPath(mergedValues, path, this.cloneStateValues(liveValue));
49466
+ preservedAny = true;
49467
+ }
49468
+ if (!preservedAny) {
49469
+ return incomingPage;
49470
+ }
49471
+ return {
49472
+ ...incomingPage,
49473
+ state: {
49474
+ ...(incomingPage.state || {}),
49475
+ values: mergedValues,
49476
+ },
49477
+ };
49478
+ }
49479
+ isSameOrNestedStatePath(candidate, base) {
49480
+ const normalizedCandidate = String(candidate || '').trim();
49481
+ const normalizedBase = String(base || '').trim();
49482
+ if (!normalizedCandidate || !normalizedBase) {
49483
+ return false;
49484
+ }
49485
+ return (normalizedCandidate === normalizedBase ||
49486
+ normalizedCandidate.startsWith(`${normalizedBase}.`) ||
49487
+ normalizedBase.startsWith(`${normalizedCandidate}.`));
49488
+ }
49489
+ clearMountedSourceSelectionsForNonPersistentState(pages, resetPaths) {
49490
+ if (!this.widgetLoaders) {
49491
+ return;
49492
+ }
49493
+ const matchesResetPath = (path) => !resetPaths || resetPaths.some((resetPath) => this.isSameOrNestedStatePath(path, resetPath));
49494
+ const sourceWidgets = new Set();
49495
+ for (const page of pages) {
49496
+ if (!page) {
49497
+ continue;
49498
+ }
49499
+ const schema = page.state?.schema || {};
49500
+ const nonPersistentPaths = Object.keys(schema)
49501
+ .filter((path) => schema[path]?.persist === false)
49502
+ .map((path) => path.trim())
49503
+ .filter((path) => path && matchesResetPath(path));
49504
+ if (!nonPersistentPaths.length) {
49505
+ continue;
49506
+ }
49507
+ const links = page.composition?.links || [];
49508
+ for (const link of links) {
49509
+ const fromRef = link.from?.ref;
49510
+ const toRef = link.to?.ref;
49511
+ const toPath = typeof toRef?.path === 'string' ? toRef.path : '';
49512
+ if (link.from?.kind === 'component-port' &&
49513
+ link.to?.kind === 'state' &&
49514
+ typeof fromRef?.widget === 'string' &&
49515
+ toPath &&
49516
+ matchesResetPath(toPath) &&
49517
+ nonPersistentPaths.some((path) => this.isSameOrNestedStatePath(toPath, path))) {
49518
+ sourceWidgets.add(fromRef.widget);
49519
+ }
49520
+ }
49521
+ for (const widget of page.widgets || []) {
49522
+ const outputs = widget.definition?.outputs;
49523
+ if (!outputs || typeof outputs !== 'object') {
49524
+ continue;
49525
+ }
49526
+ for (const rawActions of Object.values(outputs)) {
49527
+ const actions = Array.isArray(rawActions) ? rawActions : [rawActions];
49528
+ for (const action of actions) {
49529
+ const candidate = action;
49530
+ if (candidate?.type === 'setState' &&
49531
+ typeof candidate.path === 'string' &&
49532
+ matchesResetPath(candidate.path) &&
49533
+ nonPersistentPaths.some((path) => this.isSameOrNestedStatePath(candidate.path, path))) {
49534
+ sourceWidgets.add(widget.key);
49535
+ }
49536
+ }
49537
+ }
49538
+ }
49539
+ }
49540
+ for (const widgetKey of sourceWidgets) {
49541
+ const loader = this.findWidgetLoader(widgetKey);
49542
+ if (loader && typeof loader.clearSelection === 'function') {
49543
+ loader.clearSelection();
49544
+ }
49545
+ }
49546
+ }
49161
49547
  applyPageUpdate(next, persist = true, runtime, syncCompositionAdapter = true, skipStateWidgetProjection = false, emitUnchangedCanonicalPage = true) {
49162
49548
  this.assertNoLegacyConnections(next);
49163
49549
  if (this.getDataSourcesSignature(next.dataSources) !==
@@ -49182,7 +49568,7 @@ class DynamicWidgetPageComponent {
49182
49568
  state: {
49183
49569
  primaryValues: this.cloneStateValues(effectiveRuntime.primaryValues),
49184
49570
  derivedValues: this.cloneStateValues(effectiveRuntime.derivedValues),
49185
- transientValues: this.cloneStateValues(this.compositionRuntime.getSnapshot().state.transientValues),
49571
+ transientValues: {},
49186
49572
  changedPaths: [],
49187
49573
  diagnostics: [],
49188
49574
  },
@@ -49266,7 +49652,7 @@ class DynamicWidgetPageComponent {
49266
49652
  state: {
49267
49653
  primaryValues: this.cloneStateValues(nextRuntime.primaryValues),
49268
49654
  derivedValues: this.cloneStateValues(nextRuntime.derivedValues),
49269
- transientValues: this.cloneStateValues(this.compositionRuntime.getSnapshot().state.transientValues),
49655
+ transientValues: {},
49270
49656
  changedPaths: updates.map((u) => u.targetStatePath),
49271
49657
  diagnostics: [],
49272
49658
  },
@@ -52340,6 +52726,7 @@ class DynamicWidgetPageComponent {
52340
52726
  dataSources: stored.dataSources ?? baseline.dataSources,
52341
52727
  }
52342
52728
  : (stored ?? defaultPage);
52729
+ this.clearMountedSourceSelectionsForNonPersistentState([loaded]);
52343
52730
  this.authoredPageDefinition = this.clonePageDefinition(loaded);
52344
52731
  this.applyPageUpdate(loaded, false);
52345
52732
  }
@@ -52414,6 +52801,7 @@ class DynamicWidgetPageComponent {
52414
52801
  if (mutation.revision === this.persistenceRevision) {
52415
52802
  this.isHydrating = true;
52416
52803
  try {
52804
+ this.clearMountedSourceSelectionsForNonPersistentState([mutation.defaultPage]);
52417
52805
  this.authoredPageDefinition = this.clonePageDefinition(mutation.defaultPage);
52418
52806
  this.applyPageUpdate(mutation.defaultPage, false);
52419
52807
  }
@@ -53799,7 +54187,42 @@ class PraxisSurfaceHostComponent {
53799
54187
  loader.renderNow();
53800
54188
  }
53801
54189
  enrichWidget(widget, widgetKey) {
53802
- if (!widget || widget.id !== 'praxis-rich-content') {
54190
+ if (!widget) {
54191
+ return widget;
54192
+ }
54193
+ if (widget.id === 'praxis-crud') {
54194
+ const explicitContext = widget.inputs?.['context'] &&
54195
+ typeof widget.inputs['context'] === 'object' &&
54196
+ !Array.isArray(widget.inputs['context'])
54197
+ ? widget.inputs['context']
54198
+ : {};
54199
+ const hostContext = this.context &&
54200
+ typeof this.context === 'object' &&
54201
+ !Array.isArray(this.context)
54202
+ ? this.context
54203
+ : {};
54204
+ const mergedContext = {
54205
+ ...hostContext,
54206
+ ...explicitContext,
54207
+ };
54208
+ if ((!mergedContext['surfaceRuntime'] ||
54209
+ typeof mergedContext['surfaceRuntime'] !== 'object') &&
54210
+ hostContext['surfaceRuntime'] &&
54211
+ typeof hostContext['surfaceRuntime'] === 'object') {
54212
+ mergedContext['surfaceRuntime'] = hostContext['surfaceRuntime'];
54213
+ }
54214
+ if (Object.keys(mergedContext).length === 0) {
54215
+ return widget;
54216
+ }
54217
+ return {
54218
+ ...widget,
54219
+ inputs: {
54220
+ ...(widget.inputs || {}),
54221
+ context: mergedContext,
54222
+ },
54223
+ };
54224
+ }
54225
+ if (widget.id !== 'praxis-rich-content') {
53803
54226
  return widget;
53804
54227
  }
53805
54228
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/core",
3
- "version": "10.0.0-rc.26",
3
+ "version": "10.0.0-rc.27",
4
4
  "description": "Core library for Praxis UI Workspace: types, tokens, services and utilities shared across @praxisui/* packages.",
5
5
  "peerDependencies": {
6
6
  "@angular/cdk": "^21.0.0",
@@ -1885,6 +1885,10 @@ interface FilteringConfig {
1885
1885
  selectedFieldIds?: string[];
1886
1886
  /** Exibir opções avançadas por padrão */
1887
1887
  showAdvanced?: boolean;
1888
+ /** Exibir botão "Gerenciar campos" na barra do filtro (padrão: true) */
1889
+ showAddButton?: boolean;
1890
+ /** Exibir botão "Configurações do filtro" na barra quando customização estiver disponível (padrão: true) */
1891
+ showFilterSettings?: boolean;
1888
1892
  /** Permitir salvar tags/atalhos de filtro */
1889
1893
  allowSaveTags?: boolean;
1890
1894
  /** Atalhos governados, somente leitura, aplicados como patch do DTO de filtro */
@@ -2959,6 +2959,10 @@ interface FilteringConfig {
2959
2959
  selectedFieldIds?: string[];
2960
2960
  /** Exibir opções avançadas por padrão */
2961
2961
  showAdvanced?: boolean;
2962
+ /** Exibir botão "Gerenciar campos" na barra do filtro (padrão: true) */
2963
+ showAddButton?: boolean;
2964
+ /** Exibir botão "Configurações do filtro" na barra quando customização estiver disponível (padrão: true) */
2965
+ showFilterSettings?: boolean;
2962
2966
  /** Permitir salvar tags/atalhos de filtro */
2963
2967
  allowSaveTags?: boolean;
2964
2968
  /** Atalhos governados, somente leitura, aplicados como patch do DTO de filtro */
@@ -11788,6 +11792,9 @@ declare class BulkSyncSession {
11788
11792
  private readonly current;
11789
11793
  private confirmationKey;
11790
11794
  private refreshInFlight;
11795
+ private refreshGeneration;
11796
+ private refreshSignal?;
11797
+ private resultsGeneration;
11791
11798
  private readonly ownedContract;
11792
11799
  private readonly options?;
11793
11800
  /** Return detached wire data while retaining the original technical error for UX mapping. */
@@ -11804,8 +11811,14 @@ declare class BulkSyncSession {
11804
11811
  constructor(client: BulkOperationClientService, contract: BulkExecutionContract, options?: ResourceDiscoveryRequestOptions);
11805
11812
  evaluate<WI extends BulkWireId>(request: BulkSyncEvaluationRequest<WI>): Promise<BulkProposal>;
11806
11813
  confirm(idempotencyKey: string): Promise<BulkExecution>;
11807
- refreshExecution(): Promise<BulkExecution>;
11808
- readResults<WI extends BulkWireId>(size?: number, after?: string): Promise<BulkCursorPage<BulkItemResult<WI>>>;
11814
+ /** One cancellable consultation; the caller owns its deadline. POST custody is unchanged. */
11815
+ refreshExecution(signal?: AbortSignal): Promise<BulkExecution>;
11816
+ /** Cancels only this results GET; an abort never discards the accepted execution. */
11817
+ readResults<WI extends BulkWireId>(size?: number, after?: string, signal?: AbortSignal): Promise<BulkCursorPage<BulkItemResult<WI>>>;
11818
+ private readAborted;
11819
+ private requireReadLifetime;
11820
+ /** Cancellation owns the HTTP subscription, not just its Promise observer. */
11821
+ private readValue;
11809
11822
  private fail;
11810
11823
  }
11811
11824
  declare class BulkSyncStateService {
@@ -14778,6 +14791,12 @@ interface SettingsPanelContextMode {
14778
14791
  label: string;
14779
14792
  icon?: string;
14780
14793
  disabled?: boolean;
14794
+ /**
14795
+ * Optional logical group identifier. Modes sharing the same `editorGroup`
14796
+ * operate on the same active editor instance (in-place tab/section switch)
14797
+ * without triggering an intermediate `onApply()` before switching.
14798
+ */
14799
+ editorGroup?: string;
14781
14800
  }
14782
14801
  interface SettingsPanelContextNavigation {
14783
14802
  targets?: ReadonlyArray<SettingsPanelContextTarget>;
@@ -18876,6 +18895,9 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
18876
18895
  private readonly injector;
18877
18896
  private readonly settingsSessions;
18878
18897
  private widgetSettingsSession?;
18898
+ private activeSettingsPanelSession?;
18899
+ private activeSettingsFocusReturnTarget;
18900
+ private pendingContextNavigationFocusTarget?;
18879
18901
  private settingsIdentityRevision;
18880
18902
  private acceptedPageIdentity;
18881
18903
  private readonly storage;
@@ -19088,6 +19110,7 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
19088
19110
  private widgetSettingsSelectTab?;
19089
19111
  private buildWidgetSettingsContextNavigation;
19090
19112
  private navigateToWidgetSettingsContext;
19113
+ private resolveSettingsFocusReturnTarget;
19091
19114
  private openWidgetSettingsPanel;
19092
19115
  sizeEditorLayoutItems(): {
19093
19116
  key: string;
@@ -19125,6 +19148,13 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
19125
19148
  private restoreWidgetShellFields;
19126
19149
  private applyPageLayout;
19127
19150
  private applyAuthoringPageUpdate;
19151
+ private isAcknowledgedCanonicalPage;
19152
+ private hasExplicitNonPersistentStateOverride;
19153
+ private collectResetNonPersistentStatePaths;
19154
+ private samePageContextIdentity;
19155
+ private preserveEphemeralRuntimeState;
19156
+ private isSameOrNestedStatePath;
19157
+ private clearMountedSourceSelectionsForNonPersistentState;
19128
19158
  private applyPageUpdate;
19129
19159
  private handleDataSourceUpdate;
19130
19160
  private flushPendingDataSourceUpdates;