@praxisui/core 9.0.47 → 9.0.49

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
@@ -212,6 +212,14 @@ those descriptors only in its render projection, so the authored and persisted
212
212
  document keeps stable semantic keys. Plain strings remain untouched, and
213
213
  framework chrome continues to come from each library's i18n catalog.
214
214
 
215
+ During generic document traversal, a record containing only `{ key }` remains
216
+ structural. A descriptor must also carry `text` or `params` to be localized.
217
+ This keeps contracts such as analytics mappings (`{ key: "status" }`) intact,
218
+ even if a page catalog happens to use the same key. Typed component metadata
219
+ may still resolve key-only `PraxisTextValue` values directly through
220
+ `PraxisI18nService`; the UI Composition Plan compiler also materializes
221
+ fallback `text` for page-owned key-only copy before persistence.
222
+
215
223
  ### Composition link delivery and failures
216
224
 
217
225
  Composition links execute in their persisted array order inside one synchronous
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-08-30T21:38:22.309Z",
3
+ "generatedAt": "2026-08-31T13:56:05.891Z",
4
4
  "packageName": "@praxisui/core",
5
- "packageVersion": "9.0.47",
5
+ "packageVersion": "9.0.49",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 4,
@@ -20509,7 +20509,8 @@ function resolvePraxisI18nDocument(document, options) {
20509
20509
  options.i18n.getFallbackLocale();
20510
20510
  const ancestors = new Set();
20511
20511
  const visit = (value) => {
20512
- if (isPraxisI18nMessageDescriptor(value)) {
20512
+ if (isPraxisI18nMessageDescriptor(value) &&
20513
+ isExplicitDocumentMessageDescriptor(value)) {
20513
20514
  return resolveDescriptor(value, locale, fallbackLocale, options);
20514
20515
  }
20515
20516
  if (Array.isArray(value)) {
@@ -20555,6 +20556,17 @@ function isPraxisI18nMessageDescriptor(value) {
20555
20556
  (typeof text === 'string' && !!text)) &&
20556
20557
  (params == null || isPlainRecord(params)));
20557
20558
  }
20559
+ /**
20560
+ * Generic document traversal needs stronger evidence than the public
20561
+ * descriptor guard. Key-only records are common structural contracts (for
20562
+ * example analytics field mappings), so only descriptors with an explicit
20563
+ * text fallback or interpolation params are localized. Typed consumers can
20564
+ * continue to resolve key-only descriptors directly through PraxisI18nService.
20565
+ */
20566
+ function isExplicitDocumentMessageDescriptor(descriptor) {
20567
+ return (Object.prototype.hasOwnProperty.call(descriptor, 'text') ||
20568
+ Object.prototype.hasOwnProperty.call(descriptor, 'params'));
20569
+ }
20558
20570
  function resolveDescriptor(descriptor, locale, fallbackLocale, options) {
20559
20571
  const key = descriptor.key?.trim();
20560
20572
  if (!key) {
@@ -38830,12 +38842,21 @@ class DynamicWidgetPageComponent {
38830
38842
  if (this.authoringCapabilities == null) {
38831
38843
  return widgets;
38832
38844
  }
38833
- const enableCustomization = this.isAuthoringCapabilityEnabled('childCustomization');
38845
+ const authoredByKey = new Map((this.authoredPageDefinition?.widgets || []).map((widget) => [
38846
+ widget.key,
38847
+ widget,
38848
+ ]));
38834
38849
  return widgets.map((widget) => {
38835
38850
  const metadata = this.componentMetadata?.get(widget.definition?.id || '');
38836
- if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization') ||
38837
- widget.definition.inputs?.['enableCustomization'] ===
38838
- enableCustomization) {
38851
+ if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization')) {
38852
+ return widget;
38853
+ }
38854
+ const authoredEnableCustomization = authoredByKey.get(widget.key)?.definition.inputs?.['enableCustomization'] === true;
38855
+ const enableCustomization = this.enableCustomization &&
38856
+ this.isAuthoringCapabilityEnabled('childCustomization') &&
38857
+ authoredEnableCustomization;
38858
+ if (widget.definition.inputs?.['enableCustomization'] ===
38859
+ enableCustomization) {
38839
38860
  return widget;
38840
38861
  }
38841
38862
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/core",
3
- "version": "9.0.47",
3
+ "version": "9.0.49",
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. */