@praxisui/core 9.0.46 → 9.0.47

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.
@@ -36942,6 +36942,9 @@ class CompositionRuntimeEngine {
36942
36942
  const occurredAt = event.occurredAt ?? this.now();
36943
36943
  const matchedLinks = this.definition.links.filter((link) => matchesEndpoint(link.from, event.source));
36944
36944
  const matchedLinkIds = matchedLinks.map((link) => link.id);
36945
+ const executionQueue = [...matchedLinks];
36946
+ const queuedLinkIds = new Set(matchedLinkIds);
36947
+ const executedLinks = [];
36945
36948
  let workingState = cloneStateSnapshot(this.store.getSnapshot().state);
36946
36949
  const persistentBootstrapDiagnostics = this.store.getSnapshot().diagnostics.filter((diagnostic) => isBlockingDiagnostic(diagnostic)
36947
36950
  && (diagnostic.phase === 'semantic-validation'
@@ -36953,8 +36956,7 @@ class CompositionRuntimeEngine {
36953
36956
  if (this.haltedByLinkId && matchedLinks.length === 0) {
36954
36957
  runtimeDiagnostics.push(this.createPageHaltedDiagnostic(undefined, occurredAt));
36955
36958
  }
36956
- const blockedFeedbackDiagnostics = this.createFeedbackCycleBlockedDiagnostics(matchedLinks, occurredAt);
36957
- runtimeDiagnostics.push(...blockedFeedbackDiagnostics.values());
36959
+ const blockedFeedbackDiagnostics = this.createFeedbackCycleBlockedDiagnostics(this.definition.links, occurredAt);
36958
36960
  const linkResults = new Map();
36959
36961
  const trace = [];
36960
36962
  const emittedDiagnosticIds = new Set();
@@ -36970,7 +36972,9 @@ class CompositionRuntimeEngine {
36970
36972
  },
36971
36973
  }));
36972
36974
  sequence = this.appendDiagnosticTraceEntries(trace, emittedDiagnosticIds, event.eventId, sequence, runtimeDiagnostics);
36973
- for (const link of matchedLinks) {
36975
+ for (let queueIndex = 0; queueIndex < executionQueue.length; queueIndex += 1) {
36976
+ const link = executionQueue[queueIndex];
36977
+ executedLinks.push(link);
36974
36978
  const previousLink = this.store.getSnapshot().links.find((item) => item.linkId === link.id);
36975
36979
  const stateBefore = cloneStateSnapshot(workingState);
36976
36980
  const blockedFeedbackDiagnostic = blockedFeedbackDiagnostics.get(link.id);
@@ -37027,6 +37031,7 @@ class CompositionRuntimeEngine {
37027
37031
  continue;
37028
37032
  }
37029
37033
  if (blockedFeedbackDiagnostic) {
37034
+ runtimeDiagnostics.push(blockedFeedbackDiagnostic);
37030
37035
  trace.push(this.traceService.createEntry(event.eventId, sequence++, {
37031
37036
  timestamp: occurredAt,
37032
37037
  phase: 'delivery-skipped',
@@ -37113,6 +37118,20 @@ class CompositionRuntimeEngine {
37113
37118
  outputSnapshot: workingState,
37114
37119
  diagnostics: result.diagnostics.map((item) => item.code),
37115
37120
  }));
37121
+ if (result.status === 'delivered' && result.delivery.statePath) {
37122
+ const deliveredLayer = result.delivery.stateLayer ?? 'values';
37123
+ for (const candidate of this.definition.links) {
37124
+ if (queuedLinkIds.has(candidate.id)
37125
+ || candidate.from.kind !== 'state'
37126
+ || candidate.from.ref.path !== result.delivery.statePath
37127
+ || (candidate.from.ref.layer ?? 'values') !== deliveredLayer) {
37128
+ continue;
37129
+ }
37130
+ queuedLinkIds.add(candidate.id);
37131
+ matchedLinkIds.push(candidate.id);
37132
+ executionQueue.push(candidate);
37133
+ }
37134
+ }
37116
37135
  }
37117
37136
  trace.push(this.traceService.createEntry(event.eventId, sequence++, {
37118
37137
  timestamp: occurredAt,
@@ -37154,7 +37173,7 @@ class CompositionRuntimeEngine {
37154
37173
  ? 'degraded'
37155
37174
  : 'ready',
37156
37175
  stateSnapshot: materializedState,
37157
- linkPatches: matchedLinks.map((link) => ({
37176
+ linkPatches: executedLinks.map((link) => ({
37158
37177
  linkId: link.id,
37159
37178
  status: blockedFeedbackDiagnostics.has(link.id)
37160
37179
  ? 'skipped'
@@ -38510,6 +38529,10 @@ class DynamicWidgetPageComponent {
38510
38529
  changes['authoringCapabilities'] ||
38511
38530
  changes['pageIdentity']) {
38512
38531
  this.widgetShellRenderCache.clear();
38532
+ }
38533
+ if (changes['page'] ||
38534
+ changes['context'] ||
38535
+ changes['pageIdentity']) {
38513
38536
  const parsed = this.parsePage(this.page);
38514
38537
  if (changes['page'] || !this.authoredPageDefinition) {
38515
38538
  this.authoredPageDefinition = undefined;
@@ -38536,6 +38559,7 @@ class DynamicWidgetPageComponent {
38536
38559
  const rawWidgets = this.pageDefinition?.widgets || [];
38537
38560
  let widgets = this.applyEditShellActions(rawWidgets);
38538
38561
  widgets = this.applyBootstrapCompositionHydration(widgets, bootstrapSnapshot);
38562
+ widgets = this.applyChildCustomizationProjection(widgets);
38539
38563
  this.pageDefinition = this.pageDefinition
38540
38564
  ? { ...this.pageDefinition, widgets }
38541
38565
  : this.pageDefinition;
@@ -38543,6 +38567,16 @@ class DynamicWidgetPageComponent {
38543
38567
  this.applyResponsivePresentation(this.pageDefinition, widgets, this.pageRuntime);
38544
38568
  this.reportStateDiagnostics(this.pageRuntime.diagnostics);
38545
38569
  }
38570
+ if (!changes['page'] &&
38571
+ !changes['context'] &&
38572
+ !changes['pageIdentity'] &&
38573
+ (changes['enableCustomization'] || changes['authoringCapabilities']) &&
38574
+ this.pageDefinition) {
38575
+ const widgets = this.applyChildCustomizationProjection(this.pageDefinition.widgets || []);
38576
+ this.pageDefinition = { ...this.pageDefinition, widgets };
38577
+ this.page = this.pageDefinition;
38578
+ this.applyResponsivePresentation(this.pageDefinition, widgets, this.pageRuntime);
38579
+ }
38546
38580
  if (this.autoPersist &&
38547
38581
  (changes['pageIdentity'] || changes['componentInstanceId'])) {
38548
38582
  this.appliedPersisted = false;
@@ -38624,8 +38658,14 @@ class DynamicWidgetPageComponent {
38624
38658
  const linksById = new Map(this.compositionDefinition.links.map((link) => [link.id, link]));
38625
38659
  return cycle.matchedLinkIds.every((linkId) => {
38626
38660
  const link = linksById.get(linkId);
38627
- return (link?.to.kind === 'state' &&
38628
- (link.to.ref.layer ?? 'values') === 'transient');
38661
+ if (!link)
38662
+ return false;
38663
+ if (link.to.kind === 'state') {
38664
+ return (link.to.ref.layer ?? 'values') === 'transient';
38665
+ }
38666
+ return link.from.kind === 'state'
38667
+ && (link.from.ref.layer ?? 'values') === 'transient'
38668
+ && link.to.kind === 'component-port';
38629
38669
  });
38630
38670
  }
38631
38671
  applyWidgetInputPatchToPage(page, widgetKey, evt) {
@@ -38782,6 +38822,34 @@ class DynamicWidgetPageComponent {
38782
38822
  applyEditShellActions(widgets) {
38783
38823
  return this.cloneWidgets(widgets);
38784
38824
  }
38825
+ /**
38826
+ * Materializes host-owned child authoring chrome in the active runtime page.
38827
+ * The authored source remains untouched and composition state is not rebuilt.
38828
+ */
38829
+ applyChildCustomizationProjection(widgets) {
38830
+ if (this.authoringCapabilities == null) {
38831
+ return widgets;
38832
+ }
38833
+ const enableCustomization = this.isAuthoringCapabilityEnabled('childCustomization');
38834
+ return widgets.map((widget) => {
38835
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
38836
+ if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization') ||
38837
+ widget.definition.inputs?.['enableCustomization'] ===
38838
+ enableCustomization) {
38839
+ return widget;
38840
+ }
38841
+ return {
38842
+ ...widget,
38843
+ definition: {
38844
+ ...widget.definition,
38845
+ inputs: {
38846
+ ...(widget.definition.inputs || {}),
38847
+ enableCustomization,
38848
+ },
38849
+ },
38850
+ };
38851
+ });
38852
+ }
38785
38853
  applyBootstrapCompositionHydration(widgets, bootstrapSnapshot) {
38786
38854
  if (!this.compositionDefinition || !bootstrapSnapshot) {
38787
38855
  return this.cloneWidgets(widgets);
@@ -40668,13 +40736,13 @@ class DynamicWidgetPageComponent {
40668
40736
  : normalizedWidgets;
40669
40737
  const hydrated = this.resolvePagePresets({
40670
40738
  ...normalized,
40671
- widgets: this.applyRecordRelatedSurfaceAiContext(stateBoundWidgets),
40739
+ widgets: this.applyChildCustomizationProjection(this.applyRecordRelatedSurfaceAiContext(stateBoundWidgets)),
40672
40740
  });
40673
40741
  this.pageDefinition = hydrated;
40674
40742
  this.page = hydrated;
40675
40743
  this.pageState = runtime.state;
40676
40744
  this.pageRuntime = runtime;
40677
- this.applyResponsivePresentation(hydrated, stateBoundWidgets, runtime);
40745
+ this.applyResponsivePresentation(hydrated, hydrated?.widgets || stateBoundWidgets, runtime);
40678
40746
  const previousAuthoredPage = this.authoredPageDefinition;
40679
40747
  const canonicalPage = this.toPersistedCanonicalPage(hydrated);
40680
40748
  const authoredPageChanged = !previousAuthoredPage ||
@@ -41119,12 +41187,19 @@ class DynamicWidgetPageComponent {
41119
41187
  return !!this.canvas;
41120
41188
  }
41121
41189
  shouldAutoWireOutputs(widget) {
41122
- if (this.enableCustomization) {
41190
+ if (this.authoringCapabilities != null &&
41191
+ this.isAuthoringCapabilityEnabled('childCustomization')) {
41192
+ return true;
41193
+ }
41194
+ if (this.authoringCapabilities == null && this.enableCustomization) {
41123
41195
  return true;
41124
41196
  }
41125
41197
  if (this.hasCompositionOutputLinks(widget?.key)) {
41126
41198
  return true;
41127
41199
  }
41200
+ if (this.authoringCapabilities != null) {
41201
+ return false;
41202
+ }
41128
41203
  return widget?.definition?.inputs?.['enableCustomization'] === true;
41129
41204
  }
41130
41205
  hasCompositionOutputLinks(widgetKey) {
@@ -41970,9 +42045,43 @@ class DynamicWidgetPageComponent {
41970
42045
  }
41971
42046
  toPersistedCanonicalPage(page) {
41972
42047
  this.assertNoLegacyConnections(page);
41973
- const canonicalPage = this.stripDerivedPresetDefaults(this.restoreAuthoredCompositionTargetInputs(page));
42048
+ const canonicalPage = this.stripDerivedPresetDefaults(this.restoreAuthoredChildCustomizationInputs(this.restoreAuthoredCompositionTargetInputs(page)));
41974
42049
  return writeCompositionLinksToPersistedPage(canonicalPage, canonicalPage.composition?.links || []);
41975
42050
  }
42051
+ /** Restores host-projected child authoring inputs from the authored source. */
42052
+ restoreAuthoredChildCustomizationInputs(page) {
42053
+ const authored = this.authoredPageDefinition;
42054
+ if (this.authoringCapabilities == null || !authored) {
42055
+ return page;
42056
+ }
42057
+ const authoredByKey = new Map((authored.widgets || []).map((widget) => [widget.key, widget]));
42058
+ let changed = false;
42059
+ const widgets = (page.widgets || []).map((widget) => {
42060
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
42061
+ if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization')) {
42062
+ return widget;
42063
+ }
42064
+ const authoredInputs = authoredByKey.get(widget.key)?.definition.inputs;
42065
+ const inputs = { ...(widget.definition.inputs || {}) };
42066
+ if (authoredInputs &&
42067
+ Object.prototype.hasOwnProperty.call(authoredInputs, 'enableCustomization')) {
42068
+ inputs['enableCustomization'] =
42069
+ authoredInputs['enableCustomization'];
42070
+ }
42071
+ else {
42072
+ delete inputs['enableCustomization'];
42073
+ }
42074
+ if (this.sameJsonStructure(inputs, widget.definition.inputs || {})) {
42075
+ return widget;
42076
+ }
42077
+ changed = true;
42078
+ return {
42079
+ ...widget,
42080
+ definition: { ...widget.definition, inputs },
42081
+ };
42082
+ });
42083
+ return changed ? { ...page, widgets } : page;
42084
+ }
41976
42085
  /**
41977
42086
  * Component-port targets are runtime projections. Restore their authored
41978
42087
  * values before emitting or saving the page so a composition delivery never
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/core",
3
- "version": "9.0.46",
3
+ "version": "9.0.47",
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",
@@ -16617,6 +16617,11 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
16617
16617
  private buildStateRuntime;
16618
16618
  private bootstrapCompositionAdapter;
16619
16619
  private applyEditShellActions;
16620
+ /**
16621
+ * Materializes host-owned child authoring chrome in the active runtime page.
16622
+ * The authored source remains untouched and composition state is not rebuilt.
16623
+ */
16624
+ private applyChildCustomizationProjection;
16620
16625
  private applyBootstrapCompositionHydration;
16621
16626
  buildRuntimeComponentObservation(): PraxisRuntimeComponentObservationEnvelope;
16622
16627
  private registerRuntimeComponentObservationProvider;
@@ -16841,6 +16846,8 @@ declare class DynamicWidgetPageComponent implements OnChanges, OnDestroy {
16841
16846
  private mergeClassNames;
16842
16847
  private resolveRenderedCanvasItem;
16843
16848
  private toPersistedCanonicalPage;
16849
+ /** Restores host-projected child authoring inputs from the authored source. */
16850
+ private restoreAuthoredChildCustomizationInputs;
16844
16851
  /**
16845
16852
  * Component-port targets are runtime projections. Restore their authored
16846
16853
  * values before emitting or saving the page so a composition delivery never