@praxisui/core 9.0.44 → 9.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-08-30T15:02:07.421Z",
3
+ "generatedAt": "2026-08-30T19:03:13.983Z",
4
4
  "packageName": "@praxisui/core",
5
- "packageVersion": "9.0.44",
5
+ "packageVersion": "9.0.45",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 4,
@@ -528,7 +528,7 @@
528
528
  "name": "pageChange",
529
529
  "type": "WidgetPageDefinition",
530
530
  "required": false,
531
- "description": "Emitido ao alterar a definição da página."
531
+ "description": "Emitido ao alterar a definição authorada da página; projeções transitórias de composição permanecem somente no runtime."
532
532
  },
533
533
  {
534
534
  "name": "widgetEvent",
@@ -38418,6 +38418,12 @@ class DynamicWidgetPageComponent {
38418
38418
  layoutAnnouncement = '';
38419
38419
  canvasResizeHandles = CANVAS_RESIZE_HANDLES;
38420
38420
  pageDefinition;
38421
+ /**
38422
+ * Last canonical definition accepted from the host or published by the
38423
+ * runtime. Composition deliveries are materialized in `pageDefinition`, but
38424
+ * must never replace this authored source of truth.
38425
+ */
38426
+ authoredPageDefinition;
38421
38427
  pageState = { values: {} };
38422
38428
  pageRuntime = {
38423
38429
  state: { values: {} },
@@ -38505,6 +38511,15 @@ class DynamicWidgetPageComponent {
38505
38511
  changes['pageIdentity']) {
38506
38512
  this.widgetShellRenderCache.clear();
38507
38513
  const parsed = this.parsePage(this.page);
38514
+ if (changes['page'] || !this.authoredPageDefinition) {
38515
+ this.authoredPageDefinition = undefined;
38516
+ this.authoredPageDefinition = parsed
38517
+ ? this.toPersistedCanonicalPage({
38518
+ ...parsed,
38519
+ state: this.stateRuntime.normalizeState(parsed.state),
38520
+ })
38521
+ : undefined;
38522
+ }
38508
38523
  const resolvedPage = parsed ? this.resolvePagePresets(parsed) : parsed;
38509
38524
  this.assertNoLegacyConnections(resolvedPage);
38510
38525
  this.widgetDiagnostics = {};
@@ -38600,7 +38615,7 @@ class DynamicWidgetPageComponent {
38600
38615
  !widgetInputPatchResult.changed) {
38601
38616
  return;
38602
38617
  }
38603
- this.applyPageUpdate({ ...pageWithPatchedInputs, widgets, state }, true, nextRuntime, false);
38618
+ this.applyPageUpdate({ ...pageWithPatchedInputs, widgets, state }, true, nextRuntime, false, false, false);
38604
38619
  }
38605
38620
  isTransientOnlyCompositionCycle(cycle) {
38606
38621
  if (!this.compositionDefinition || !cycle.matchedLinkIds.length) {
@@ -39284,7 +39299,7 @@ class DynamicWidgetPageComponent {
39284
39299
  },
39285
39300
  },
39286
39301
  };
39287
- this.applyPageUpdate({ ...page, widgets }, false, stateResult.runtime, false, true);
39302
+ this.applyPageUpdate({ ...page, widgets }, false, stateResult.runtime, false, true, false);
39288
39303
  return true;
39289
39304
  }
39290
39305
  applyRecordSurfaceSourceState(page, fromKey, evt, surface, payload) {
@@ -39446,7 +39461,7 @@ class DynamicWidgetPageComponent {
39446
39461
  widgets = this.applyCompositionWidgetDeliveries(widgets, cycle).widgets;
39447
39462
  widgets = this.projectPersistentCompositionStateInputs(widgets, cycle.snapshot.state, cycle.snapshot.generatedAt);
39448
39463
  const runtime = this.buildStateRuntime(state, page.context);
39449
- this.applyPageUpdate({ ...page, widgets, state }, true, runtime, false, true);
39464
+ this.applyPageUpdate({ ...page, widgets, state }, true, runtime, false, true, false);
39450
39465
  }
39451
39466
  matchesRuntimeSourceRef(endpoint, sourceRef) {
39452
39467
  return (endpoint.kind === 'component-port' &&
@@ -40628,7 +40643,7 @@ class DynamicWidgetPageComponent {
40628
40643
  themePreset: themePreset || undefined,
40629
40644
  }, persist);
40630
40645
  }
40631
- applyPageUpdate(next, persist = true, runtime = this.buildStateRuntime(next.state, next.context), syncCompositionAdapter = true, skipStateWidgetProjection = false) {
40646
+ applyPageUpdate(next, persist = true, runtime = this.buildStateRuntime(next.state, next.context), syncCompositionAdapter = true, skipStateWidgetProjection = false, emitUnchangedCanonicalPage = true) {
40632
40647
  this.assertNoLegacyConnections(next);
40633
40648
  const normalized = { ...next, state: runtime.state };
40634
40649
  const normalizedWidgets = this.applyEditShellActions(normalized.widgets || []);
@@ -40660,10 +40675,19 @@ class DynamicWidgetPageComponent {
40660
40675
  this.pageState = runtime.state;
40661
40676
  this.pageRuntime = runtime;
40662
40677
  this.applyResponsivePresentation(hydrated, stateBoundWidgets, runtime);
40678
+ const previousAuthoredPage = this.authoredPageDefinition;
40663
40679
  const canonicalPage = this.toPersistedCanonicalPage(hydrated);
40664
- this.pageChange.emit(canonicalPage);
40680
+ const authoredPageChanged = !previousAuthoredPage ||
40681
+ !this.sameJsonStructure(previousAuthoredPage, canonicalPage);
40682
+ this.authoredPageDefinition = this.clonePageDefinition(canonicalPage);
40683
+ if (authoredPageChanged || emitUnchangedCanonicalPage) {
40684
+ this.pageChange.emit(canonicalPage);
40685
+ }
40665
40686
  this.reportStateDiagnostics(runtime.diagnostics);
40666
- if (persist && this.autoPersist && !this.isHydrating) {
40687
+ if (authoredPageChanged &&
40688
+ persist &&
40689
+ this.autoPersist &&
40690
+ !this.isHydrating) {
40667
40691
  this.savePage(canonicalPage);
40668
40692
  }
40669
40693
  }
@@ -41941,9 +41965,99 @@ class DynamicWidgetPageComponent {
41941
41965
  }
41942
41966
  toPersistedCanonicalPage(page) {
41943
41967
  this.assertNoLegacyConnections(page);
41944
- const canonicalPage = this.stripDerivedPresetDefaults(page);
41968
+ const canonicalPage = this.stripDerivedPresetDefaults(this.restoreAuthoredCompositionTargetInputs(page));
41945
41969
  return writeCompositionLinksToPersistedPage(canonicalPage, canonicalPage.composition?.links || []);
41946
41970
  }
41971
+ /**
41972
+ * Component-port targets are runtime projections. Restore their authored
41973
+ * values before emitting or saving the page so a composition delivery never
41974
+ * becomes an accidental document edit.
41975
+ */
41976
+ restoreAuthoredCompositionTargetInputs(page) {
41977
+ const authored = this.authoredPageDefinition;
41978
+ const links = page.composition?.links || [];
41979
+ if (!authored || !links.length) {
41980
+ return page;
41981
+ }
41982
+ const next = this.clonePageDefinition(page);
41983
+ const authoredByKey = new Map((authored.widgets || []).map((widget) => [widget.key, widget]));
41984
+ for (const link of links) {
41985
+ if (link.to.kind !== 'component-port')
41986
+ continue;
41987
+ const target = link.to.ref;
41988
+ const widgetIndex = (next.widgets || []).findIndex((widget) => widget.key === target.widget);
41989
+ const authoredWidget = authoredByKey.get(target.widget);
41990
+ if (widgetIndex < 0 || !authoredWidget)
41991
+ continue;
41992
+ if (target.nestedPath?.length) {
41993
+ const authoredNested = this.nestedWidgetAccessor.resolveNestedWidget(authoredWidget, target.nestedPath);
41994
+ const authoredInputs = authoredNested?.inputs;
41995
+ const hasAuthoredValue = !!authoredInputs &&
41996
+ Object.prototype.hasOwnProperty.call(authoredInputs, target.port);
41997
+ const result = hasAuthoredValue
41998
+ ? this.nestedWidgetAccessor.setNestedWidgetInput(next.widgets[widgetIndex], target.nestedPath, target.port, this.cloneStateValues(authoredInputs?.[target.port]))
41999
+ : this.nestedWidgetAccessor.removeNestedWidgetInput(next.widgets[widgetIndex], target.nestedPath, target.port);
42000
+ if (result.changed) {
42001
+ next.widgets[widgetIndex] = result.widget;
42002
+ }
42003
+ continue;
42004
+ }
42005
+ const inputPath = this.resolveComponentBindingPath(target.port, target.bindingPath);
42006
+ if (!inputPath)
42007
+ continue;
42008
+ const authoredInputs = authoredWidget.definition.inputs || {};
42009
+ const authoredValue = this.readOwnValueAtPath(authoredInputs, inputPath);
42010
+ const runtimeInputs = this.cloneStateValues(next.widgets[widgetIndex].definition.inputs || {});
42011
+ const inputs = authoredValue.found
42012
+ ? this.conn.setValueAtPath(runtimeInputs, inputPath, this.cloneStateValues(authoredValue.value))
42013
+ : this.removeOwnValueAtPath(runtimeInputs, inputPath);
42014
+ next.widgets[widgetIndex] = {
42015
+ ...next.widgets[widgetIndex],
42016
+ definition: {
42017
+ ...next.widgets[widgetIndex].definition,
42018
+ inputs,
42019
+ },
42020
+ };
42021
+ }
42022
+ return next;
42023
+ }
42024
+ readOwnValueAtPath(source, path) {
42025
+ const tokens = this.tokenizeInputPath(path);
42026
+ let current = source;
42027
+ for (const token of tokens) {
42028
+ if ((typeof current !== 'object' || current === null) ||
42029
+ !Object.prototype.hasOwnProperty.call(current, token)) {
42030
+ return { found: false };
42031
+ }
42032
+ current = current[token];
42033
+ }
42034
+ return { found: tokens.length > 0, value: current };
42035
+ }
42036
+ removeOwnValueAtPath(source, path) {
42037
+ const tokens = this.tokenizeInputPath(path);
42038
+ if (!tokens.length)
42039
+ return source;
42040
+ const clone = this.cloneStateValues(source);
42041
+ let current = clone;
42042
+ for (const token of tokens.slice(0, -1)) {
42043
+ if (typeof current?.[token] !== 'object' || current[token] === null) {
42044
+ return clone;
42045
+ }
42046
+ current[token] = Array.isArray(current[token])
42047
+ ? [...current[token]]
42048
+ : { ...current[token] };
42049
+ current = current[token];
42050
+ }
42051
+ delete current[tokens[tokens.length - 1]];
42052
+ return clone;
42053
+ }
42054
+ tokenizeInputPath(path) {
42055
+ const tokens = [];
42056
+ for (const match of String(path || '').matchAll(/([^.\[\]]+)|\[(\d+)\]/g)) {
42057
+ tokens.push(match[2] === undefined ? match[1] : Number(match[2]));
42058
+ }
42059
+ return tokens;
42060
+ }
41947
42061
  /**
41948
42062
  * Preset defaults are a runtime projection, not authored page state.
41949
42063
  *
@@ -42039,6 +42153,7 @@ class DynamicWidgetPageComponent {
42039
42153
  if (!stored)
42040
42154
  return;
42041
42155
  this.isHydrating = true;
42156
+ this.authoredPageDefinition = undefined;
42042
42157
  this.applyPageUpdate(stored, false);
42043
42158
  this.isHydrating = false;
42044
42159
  },
@@ -43013,7 +43128,7 @@ const PRAXIS_DYNAMIC_PAGE_COMPONENT_METADATA = {
43013
43128
  {
43014
43129
  name: 'pageChange',
43015
43130
  type: 'WidgetPageDefinition',
43016
- description: 'Emitido ao alterar a definição da página.',
43131
+ description: 'Emitido ao alterar a definição authorada da página; projeções transitórias de composição permanecem somente no runtime.',
43017
43132
  },
43018
43133
  {
43019
43134
  name: 'widgetEvent',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/core",
3
- "version": "9.0.44",
3
+ "version": "9.0.45",
4
4
  "description": "Core library for Praxis UI Workspace: types, tokens, services and utilities shared across @praxisui/* packages.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -16552,6 +16552,12 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
16552
16552
  layoutAnnouncement: string;
16553
16553
  readonly canvasResizeHandles: readonly CanvasResizeHandleDefinition[];
16554
16554
  private pageDefinition?;
16555
+ /**
16556
+ * Last canonical definition accepted from the host or published by the
16557
+ * runtime. Composition deliveries are materialized in `pageDefinition`, but
16558
+ * must never replace this authored source of truth.
16559
+ */
16560
+ private authoredPageDefinition?;
16555
16561
  private pageState;
16556
16562
  private pageRuntime;
16557
16563
  private readonly configEditorContextRequests;
@@ -16835,6 +16841,15 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
16835
16841
  private mergeClassNames;
16836
16842
  private resolveRenderedCanvasItem;
16837
16843
  private toPersistedCanonicalPage;
16844
+ /**
16845
+ * Component-port targets are runtime projections. Restore their authored
16846
+ * values before emitting or saving the page so a composition delivery never
16847
+ * becomes an accidental document edit.
16848
+ */
16849
+ private restoreAuthoredCompositionTargetInputs;
16850
+ private readOwnValueAtPath;
16851
+ private removeOwnValueAtPath;
16852
+ private tokenizeInputPath;
16838
16853
  /**
16839
16854
  * Preset defaults are a runtime projection, not authored page state.
16840
16855
  *