@praxisui/core 9.0.46 → 9.0.48

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,43 @@ 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 authoredByKey = new Map((this.authoredPageDefinition?.widgets || []).map((widget) => [
38834
+ widget.key,
38835
+ widget,
38836
+ ]));
38837
+ return widgets.map((widget) => {
38838
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
38839
+ if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization')) {
38840
+ return widget;
38841
+ }
38842
+ const authoredEnableCustomization = authoredByKey.get(widget.key)?.definition.inputs?.['enableCustomization'] === true;
38843
+ const enableCustomization = this.enableCustomization &&
38844
+ this.isAuthoringCapabilityEnabled('childCustomization') &&
38845
+ authoredEnableCustomization;
38846
+ if (widget.definition.inputs?.['enableCustomization'] ===
38847
+ enableCustomization) {
38848
+ return widget;
38849
+ }
38850
+ return {
38851
+ ...widget,
38852
+ definition: {
38853
+ ...widget.definition,
38854
+ inputs: {
38855
+ ...(widget.definition.inputs || {}),
38856
+ enableCustomization,
38857
+ },
38858
+ },
38859
+ };
38860
+ });
38861
+ }
38785
38862
  applyBootstrapCompositionHydration(widgets, bootstrapSnapshot) {
38786
38863
  if (!this.compositionDefinition || !bootstrapSnapshot) {
38787
38864
  return this.cloneWidgets(widgets);
@@ -40668,13 +40745,13 @@ class DynamicWidgetPageComponent {
40668
40745
  : normalizedWidgets;
40669
40746
  const hydrated = this.resolvePagePresets({
40670
40747
  ...normalized,
40671
- widgets: this.applyRecordRelatedSurfaceAiContext(stateBoundWidgets),
40748
+ widgets: this.applyChildCustomizationProjection(this.applyRecordRelatedSurfaceAiContext(stateBoundWidgets)),
40672
40749
  });
40673
40750
  this.pageDefinition = hydrated;
40674
40751
  this.page = hydrated;
40675
40752
  this.pageState = runtime.state;
40676
40753
  this.pageRuntime = runtime;
40677
- this.applyResponsivePresentation(hydrated, stateBoundWidgets, runtime);
40754
+ this.applyResponsivePresentation(hydrated, hydrated?.widgets || stateBoundWidgets, runtime);
40678
40755
  const previousAuthoredPage = this.authoredPageDefinition;
40679
40756
  const canonicalPage = this.toPersistedCanonicalPage(hydrated);
40680
40757
  const authoredPageChanged = !previousAuthoredPage ||
@@ -41119,12 +41196,19 @@ class DynamicWidgetPageComponent {
41119
41196
  return !!this.canvas;
41120
41197
  }
41121
41198
  shouldAutoWireOutputs(widget) {
41122
- if (this.enableCustomization) {
41199
+ if (this.authoringCapabilities != null &&
41200
+ this.isAuthoringCapabilityEnabled('childCustomization')) {
41201
+ return true;
41202
+ }
41203
+ if (this.authoringCapabilities == null && this.enableCustomization) {
41123
41204
  return true;
41124
41205
  }
41125
41206
  if (this.hasCompositionOutputLinks(widget?.key)) {
41126
41207
  return true;
41127
41208
  }
41209
+ if (this.authoringCapabilities != null) {
41210
+ return false;
41211
+ }
41128
41212
  return widget?.definition?.inputs?.['enableCustomization'] === true;
41129
41213
  }
41130
41214
  hasCompositionOutputLinks(widgetKey) {
@@ -41970,9 +42054,43 @@ class DynamicWidgetPageComponent {
41970
42054
  }
41971
42055
  toPersistedCanonicalPage(page) {
41972
42056
  this.assertNoLegacyConnections(page);
41973
- const canonicalPage = this.stripDerivedPresetDefaults(this.restoreAuthoredCompositionTargetInputs(page));
42057
+ const canonicalPage = this.stripDerivedPresetDefaults(this.restoreAuthoredChildCustomizationInputs(this.restoreAuthoredCompositionTargetInputs(page)));
41974
42058
  return writeCompositionLinksToPersistedPage(canonicalPage, canonicalPage.composition?.links || []);
41975
42059
  }
42060
+ /** Restores host-projected child authoring inputs from the authored source. */
42061
+ restoreAuthoredChildCustomizationInputs(page) {
42062
+ const authored = this.authoredPageDefinition;
42063
+ if (this.authoringCapabilities == null || !authored) {
42064
+ return page;
42065
+ }
42066
+ const authoredByKey = new Map((authored.widgets || []).map((widget) => [widget.key, widget]));
42067
+ let changed = false;
42068
+ const widgets = (page.widgets || []).map((widget) => {
42069
+ const metadata = this.componentMetadata?.get(widget.definition?.id || '');
42070
+ if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization')) {
42071
+ return widget;
42072
+ }
42073
+ const authoredInputs = authoredByKey.get(widget.key)?.definition.inputs;
42074
+ const inputs = { ...(widget.definition.inputs || {}) };
42075
+ if (authoredInputs &&
42076
+ Object.prototype.hasOwnProperty.call(authoredInputs, 'enableCustomization')) {
42077
+ inputs['enableCustomization'] =
42078
+ authoredInputs['enableCustomization'];
42079
+ }
42080
+ else {
42081
+ delete inputs['enableCustomization'];
42082
+ }
42083
+ if (this.sameJsonStructure(inputs, widget.definition.inputs || {})) {
42084
+ return widget;
42085
+ }
42086
+ changed = true;
42087
+ return {
42088
+ ...widget,
42089
+ definition: { ...widget.definition, inputs },
42090
+ };
42091
+ });
42092
+ return changed ? { ...page, widgets } : page;
42093
+ }
41976
42094
  /**
41977
42095
  * Component-port targets are runtime projections. Restore their authored
41978
42096
  * 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.48",
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",
@@ -14115,7 +14115,7 @@ interface WidgetPageAuthoringCapabilities {
14115
14115
  widgetInputs?: boolean;
14116
14116
  /** Allows removing widgets from the page. */
14117
14117
  widgetRemoval?: boolean;
14118
- /** Allows nested components to receive authoring-only customization inputs. */
14118
+ /** Grants nested authoring only to widgets that explicitly opt in. */
14119
14119
  childCustomization?: boolean;
14120
14120
  }
14121
14121
  /** Fine-grained shell capabilities used by the canonical shell editor. */
@@ -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