@praxisui/core 10.0.0-rc.22 → 10.0.0-rc.24

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
@@ -1011,10 +1011,17 @@ widget appearance/size, or registered content editor session. It uses the existi
1011
1011
  `owner` option; no session identity is persisted in the page document.
1012
1012
 
1013
1013
  The session is cancelled when its panel closes, the page is destroyed, or an external
1014
- page/context/identity/authoring input change invalidates it. A page-only acknowledgement
1015
- identical to the current authored document keeps the session alive for subsequent
1016
- Apply/Save. This is deliberately conservative: a different external document cancels
1017
- open editors even when a particular widget happens to be unchanged.
1014
+ page/context/identity/authoring input change invalidates it. An acknowledgement identical
1015
+ to the current authored page keeps the session alive for subsequent Apply/Save, including
1016
+ when the host resends an equivalent `pageIdentity` object. After the first input change,
1017
+ identity equivalence means strict equality of its five fields: `appId`, `tenantId`,
1018
+ `userId`, `routePath` and `locale`; whitespace, delimiters and missing values are not
1019
+ normalized. Core retains a private snapshot of those accepted primitive values, so
1020
+ mutating the host's previous object before resending a clone still changes the scope.
1021
+ Resending only that equivalent identity also preserves data-source overlays,
1022
+ composition and persistence scope. Context, instance and authoring capability changes
1023
+ remain invalidating. A different external document cancels open editors even when a
1024
+ particular widget happens to be unchanged. This does not confirm an HTTP save.
1018
1025
 
1019
1026
  Confirmed widget removal cancels sessions targeting that key, plus page-wide settings
1020
1027
  that could restore the removed widget. Asynchronous editor results cannot open a panel
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-15T06:07:49.426Z",
3
+ "generatedAt": "2026-10-15T13:55:17.858Z",
4
4
  "packageName": "@praxisui/core",
5
- "packageVersion": "10.0.0-rc.22",
5
+ "packageVersion": "10.0.0-rc.24",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 4,
@@ -45912,6 +45912,7 @@ class DynamicWidgetPageComponent {
45912
45912
  settingsSessions = new Map();
45913
45913
  widgetSettingsSession;
45914
45914
  settingsIdentityRevision = 0;
45915
+ acceptedPageIdentity;
45915
45916
  storage = inject(ASYNC_CONFIG_STORAGE);
45916
45917
  componentKeys = inject(ComponentKeyService);
45917
45918
  componentMetadata = inject(ComponentMetadataRegistry, {
@@ -46047,6 +46048,29 @@ class DynamicWidgetPageComponent {
46047
46048
  this.compositionRuntime.destroy();
46048
46049
  }
46049
46050
  ngOnChanges(changes) {
46051
+ const identityChange = changes['pageIdentity'];
46052
+ if (identityChange) {
46053
+ const currentIdentity = identityChange.currentValue;
46054
+ const equivalentIdentity = !identityChange.isFirstChange()
46055
+ && this.samePageIdentity(this.acceptedPageIdentity, currentIdentity);
46056
+ // Hosts own the input object and may mutate it before sending a clone.
46057
+ // Retain accepted primitive values, never Angular's mutable previousValue.
46058
+ this.acceptedPageIdentity = currentIdentity == null ? currentIdentity : {
46059
+ appId: currentIdentity.appId,
46060
+ tenantId: currentIdentity.tenantId,
46061
+ userId: currentIdentity.userId,
46062
+ routePath: currentIdentity.routePath,
46063
+ locale: currentIdentity.locale,
46064
+ };
46065
+ if (equivalentIdentity) {
46066
+ // All scope owners use the same no-op normalization. Keep the caller's
46067
+ // change record intact and preserve first-change initialization.
46068
+ changes = { ...changes };
46069
+ delete changes['pageIdentity'];
46070
+ if (Object.keys(changes).length === 0)
46071
+ return;
46072
+ }
46073
+ }
46050
46074
  // applyResponsivePresentation may replace `this.page` with a runtime
46051
46075
  // projection below; persistence must inspect the actual host input.
46052
46076
  const incomingPage = changes['page']
@@ -46181,6 +46205,17 @@ class DynamicWidgetPageComponent {
46181
46205
  this.savePage(parsed);
46182
46206
  }
46183
46207
  }
46208
+ samePageIdentity(left, right) {
46209
+ if (left === right)
46210
+ return true;
46211
+ if (!left || !right)
46212
+ return false;
46213
+ return left.appId === right.appId
46214
+ && left.tenantId === right.tenantId
46215
+ && left.userId === right.userId
46216
+ && left.routePath === right.routePath
46217
+ && left.locale === right.locale;
46218
+ }
46184
46219
  onWidgetEvent(fromKey, evt) {
46185
46220
  this.widgetEvent.emit({
46186
46221
  ...evt,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/core",
3
- "version": "10.0.0-rc.22",
3
+ "version": "10.0.0-rc.24",
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",
@@ -18785,6 +18785,7 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
18785
18785
  private readonly settingsSessions;
18786
18786
  private widgetSettingsSession?;
18787
18787
  private settingsIdentityRevision;
18788
+ private acceptedPageIdentity;
18788
18789
  private readonly storage;
18789
18790
  private readonly componentKeys;
18790
18791
  private readonly componentMetadata;
@@ -18859,6 +18860,7 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
18859
18860
  constructor();
18860
18861
  ngOnDestroy(): void;
18861
18862
  ngOnChanges(changes: SimpleChanges): void;
18863
+ private samePageIdentity;
18862
18864
  onWidgetEvent(fromKey: string, evt: WidgetEventEnvelope): void;
18863
18865
  private isTransientOnlyCompositionCycle;
18864
18866
  private applyWidgetInputPatchToPage;