@praxisui/page-builder 9.0.5-rc.2 → 9.0.5-rc.21

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.
@@ -12541,7 +12541,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
12541
12541
  * Capabilities catalog for the canonical dynamic page builder/runtime.
12542
12542
  */
12543
12543
  const PAGE_BUILDER_AI_CAPABILITIES = {
12544
- version: 'v1.2',
12544
+ version: 'v1.3',
12545
12545
  enums: {},
12546
12546
  targets: [
12547
12547
  'page-builder',
@@ -12558,7 +12558,7 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
12558
12558
  'Canvas e o modelo espacial canonico da pagina quando houver posicionamento explicito.',
12559
12559
  'Taxonomia editorial: condition usa Json Logic canonico; transform usa pipeline declarativo; policy cobre apenas comportamento operacional.',
12560
12560
  'Para criacao agentic de paginas, o preview pode trazer uiCompositionPlan como plano intermediario validavel; o page-builder compila esse plano para WidgetPageDefinition antes de aplicar.',
12561
- 'UiCompositionPlan usa widgets[].componentId e bindings declarativos. O JSON persistido continua sendo page.widgets[].definition.id e page.composition.links.',
12561
+ 'UiCompositionPlan usa widgets[].componentId e bindings declarativos. UiCompositionPlanTemplateReference pode piná-lo por registryKey + configSha256, mas precisa ser resolvido pelo backend governado antes da compilação. O JSON persistido continua sendo page.widgets[].definition.id e page.composition.links.',
12562
12562
  'Nested component ports usam endpoint component-port com nestedPath. O owner em ref.widget ou bindings[].*.widget continua sendo o widget top-level; a porta real do filho fica em port/direction e o caminho ate o filho fica em nestedPath.',
12563
12563
  'Nao gere links nested via owner.widgetEvent, bindingPath profundo, page.connections ou wrappers host-specific. widgetEvent e bridge legada/avancada, nao contrato principal de authoring.',
12564
12564
  'Payloads legados de layout ainda podem ser ingeridos, mas sao normalizados para canvas e nao devem ser reemitidos.',
@@ -12568,6 +12568,9 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
12568
12568
  { path: 'uiCompositionPlan', category: 'page', valueKind: 'object', description: 'Plano declarativo intermediario aceito em preview agentic antes do WidgetPageDefinition.' },
12569
12569
  { path: 'uiCompositionPlan.version', category: 'page', valueKind: 'string', description: 'Versao do plano. Valor atual: 1.0.' },
12570
12570
  { path: 'uiCompositionPlan.kind', category: 'page', valueKind: 'string', description: 'Discriminador do plano. Valor atual: praxis.ui-composition-plan.' },
12571
+ { path: 'uiCompositionPlan.i18n', category: 'page', valueKind: 'object', description: 'Catalogo de textos de negocio da pagina, compilado para page.i18n. Descritores PraxisTextValue podem declarar apenas key quando a chave existir no dicionario do fallbackLocale; o compilador materializa text no documento executavel.' },
12572
+ { path: 'uiCompositionPlan.context', category: 'context', valueKind: 'object', description: 'Contexto explicito da pagina, compilado para page.context; nao substitui contextScopes de autoria.' },
12573
+ { path: 'uiCompositionPlan.layout', category: 'layout', valueKind: 'object', description: 'Layout responsivo canonico compilado para page.layout quando a pagina nao usa apenas canvas/preset.' },
12571
12574
  { path: 'uiCompositionPlan.layoutPreset', category: 'layout', valueKind: 'string', description: 'Preset semantico opcional da composicao planejada.' },
12572
12575
  { path: 'uiCompositionPlan.layoutPresetOptions', category: 'layout', valueKind: 'object', description: 'Opcoes semanticas opcionais do preset, como familia visual, estrategia responsiva e politica de densidade.' },
12573
12576
  { path: 'uiCompositionPlan.grouping', category: 'layout', valueKind: 'array', description: 'Agrupamentos semanticos opcionais para organizar widgets em hero, section, tabs ou rail no runtime.' },
@@ -12578,8 +12581,14 @@ const PAGE_BUILDER_AI_CAPABILITIES = {
12578
12581
  { path: 'uiCompositionPlan.widgets', category: 'widgets', valueKind: 'array', description: 'Widgets planejados antes da compilacao para page.widgets.' },
12579
12582
  { path: 'uiCompositionPlan.widgets[].key', category: 'widgets', valueKind: 'string', description: 'ID estavel do widget planejado.', critical: true },
12580
12583
  { path: 'uiCompositionPlan.widgets[].componentId', category: 'widgets', valueKind: 'string', description: 'Componente registrado que sera compilado para definition.id.', critical: true },
12584
+ { path: 'uiCompositionPlan.widgets[].shell', category: 'widgets', valueKind: 'object', description: 'Moldura governada do widget, compilada para page.widgets[].shell sem enriquecimento do host.' },
12581
12585
  { path: 'uiCompositionPlan.widgets[].inputs', category: 'widgets', valueKind: 'object', description: 'Inputs canonicos do componente, compilados para definition.inputs.' },
12582
12586
  { path: 'uiCompositionPlan.widgets[].bindingOrder', category: 'widgets', valueKind: 'array', description: 'Ordem declarativa de binding, compilada para definition.bindingOrder.' },
12587
+ { path: 'uiCompositionPlan.selectionSyncs', category: 'connections', valueKind: 'array', description: 'Atalhos declarativos para projetar o mesmo contexto de selecao a partir de varias portas; sempre compilam para links canonicos explicitos.' },
12588
+ { path: 'uiCompositionPlan.contextScopes', category: 'context', valueKind: 'array', description: 'Escopos de autoria que distribuem contexto explicito a widgets top-level ou nested; nao criam heranca ambiente no runtime.' },
12589
+ { path: 'uiCompositionPlan.contextScopes[].context', category: 'context', valueKind: 'object', description: 'Mapa input -> constant ou state. Constant e state.initial viram inputs explicitos; state tambem gera link state-read canonico.' },
12590
+ { path: 'uiCompositionPlan.contextScopes[].context.<token>', category: 'context', valueKind: 'object', description: 'Descritor constant ou state. Em state, initial aceita um valor JSON opcional materializado no input antes da primeira propagacao; nao cria um segundo state store.' },
12591
+ { path: 'uiCompositionPlan.contextScopes[].targets', category: 'context', valueKind: 'array', description: 'Destinos explicitos do escopo, identificados por widget owner e nestedPath canonico opcional.' },
12583
12592
  { path: 'uiCompositionPlan.bindings', category: 'connections', valueKind: 'array', description: 'Bindings declarativos que serao compilados para page.composition.links.' },
12584
12593
  { path: 'uiCompositionPlan.bindings[].id', category: 'connections', valueKind: 'string', description: 'Identificador estavel do binding planejado.' },
12585
12594
  { path: 'uiCompositionPlan.bindings[].from', category: 'connections', valueKind: 'object', description: 'Endpoint de origem: component-port ou state.' },
@@ -13226,12 +13235,13 @@ const PAGE_BUILDER_COMPONENT_CONTEXT_PACK = {
13226
13235
  },
13227
13236
  hints: [
13228
13237
  'For agentic page creation, prefer returning uiCompositionPlan in the preview envelope and let the page-builder compiler emit WidgetPageDefinition.',
13238
+ 'Carry page-owned i18n, explicit context, canonical layout and governed widget shell in uiCompositionPlan; when a PraxisTextValue key exists in the fallbackLocale dictionary, omit repeated text and let the compiler materialize the executable fallback.',
13229
13239
  'Use uiCompositionPlan.widgets[].componentId in plans; the compiler maps it to page.widgets[].definition.id.',
13230
- 'Use uiCompositionPlan.bindings as the declarative source for wiring; the compiler emits page.composition.links.',
13240
+ 'Use uiCompositionPlan.selectionSyncs for repeated selection projections, contextScopes for repeated explicit widget context, and bindings for remaining wiring; constant values and state.initial become explicit inputs, while state references compile to page.composition.links.',
13231
13241
  'For nested component ports, use component-port endpoints with nestedPath in uiCompositionPlan.bindings; keep widget as the top-level owner and put the real child port in port/direction.',
13232
13242
  'NestedPath must be relative to the owner widget and must end with a widget segment containing a stable key. Do not use index as the only identity.',
13233
13243
  'Do not author nested links through owner.widgetEvent, deep bindingPath, page.connections, or host-specific wrapper outputs; those are legacy or bridge mechanisms.',
13234
- 'Do not emit both uiCompositionPlan.bindings and hand-authored page.composition.links as competing sources of truth for the same preview.',
13244
+ 'Do not emit uiCompositionPlan shorthands/bindings and hand-authored page.composition.links as competing sources of truth for the same preview.',
13235
13245
  'Use page.widgets[].key as the merge key; avoid array indexes.',
13236
13246
  'Canvas items use 1-based col/row with integer spans.',
13237
13247
  'Widget definition id must match a registered component selector.',
@@ -13574,7 +13584,7 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
13574
13584
  componentId: 'praxis-page-builder',
13575
13585
  ownerPackage: '@praxisui/page-builder',
13576
13586
  configSchemaId: 'WidgetPageDefinition',
13577
- manifestVersion: '1.0.0',
13587
+ manifestVersion: '1.1.0',
13578
13588
  runtimeInputs: [
13579
13589
  { name: 'page', type: 'WidgetPageDefinition', description: 'Canonical renderable page document consumed by praxis-dynamic-page.' },
13580
13590
  { name: 'pageIdentity', type: 'PageIdentity | null', description: 'Persistence identity for ui_user_config save/apply flows; not persisted inside page.' },
@@ -13765,11 +13775,11 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
13765
13775
  target: { kind: 'agenticPreview', resolver: 'agentic-preview-result', ambiguityPolicy: 'fail', required: true },
13766
13776
  inputSchema: { type: 'object', required: ['uiCompositionPlan'], properties: { uiCompositionPlan: { type: 'object' } } },
13767
13777
  effects: [{ kind: 'compile-domain-patch', handler: 'page-builder-ui-composition-plan-compile', handlerContract: {
13768
- reads: ['UiCompositionPlan', 'UiCompositionPlan.selectionSyncs', 'UiCompositionPlan.contextScopes', 'compileUiCompositionPlan', 'PAGE_BUILDER_WIDGET_AI_CATALOGS', 'ComponentDocMeta.configEditor'],
13778
+ reads: ['UiCompositionPlanAuthoringInput', 'UiCompositionPlan', 'UiCompositionPlanTemplateReference', 'UiCompositionPlanTemplateMaterialization', 'UiCompositionPlan.i18n', 'UiCompositionPlan.context', 'UiCompositionPlan.layout', 'UiCompositionPlan.selectionSyncs', 'UiCompositionPlan.contextScopes', 'resolveUiCompositionPlanTemplate', 'compileUiCompositionPlan', 'PAGE_BUILDER_WIDGET_AI_CATALOGS', 'ComponentDocMeta.configEditor'],
13769
13779
  writes: ['compiledFormPatch.patch.page'],
13770
13780
  identityKeys: ['uiCompositionPlan.id', 'widgetKey', 'uiCompositionPlan.bindings[].id', 'uiCompositionPlan.selectionSyncs[].id', 'uiCompositionPlan.contextScopes[].id'],
13771
- failureModes: ['ui-composition-plan-invalid', 'widget-catalog-missing', 'compiled-page-invalid', 'child-config-editor-missing'],
13772
- description: 'Compiles the agentic intermediate UiCompositionPlan into a renderable WidgetPageDefinition patch.page.',
13781
+ failureModes: ['ui-composition-plan-invalid', 'ui-composition-template-reference-invalid', 'ui-composition-template-not-found', 'ui-composition-template-hash-mismatch', 'ui-composition-template-overrides-unsupported', 'widget-catalog-missing', 'compiled-page-invalid', 'child-config-editor-missing'],
13782
+ description: 'Resolves an optional exact governed template reference and compiles the expanded UiCompositionPlan into a renderable WidgetPageDefinition patch.page.',
13773
13783
  } }],
13774
13784
  validators: ['ui-composition-plan-valid', 'compiled-page-valid', 'widget-keys-unique', 'composition-endpoints-resolve', 'canvas-items-reference-existing-widgets'],
13775
13785
  affectedPaths: ['uiCompositionPlan', 'compiledFormPatch.patch.page'],
@@ -13904,8 +13914,9 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
13904
13914
  roundTripRequirements: [
13905
13915
  'WidgetPageDefinition is the canonical persisted runtime page shape for page-builder.',
13906
13916
  'UiCompositionPlan is an intermediate agentic plan and must compile before local preview/apply.',
13917
+ 'UiCompositionPlan.i18n, context and layout compile into the corresponding WidgetPageDefinition fields so a complete page never depends on host-only enrichment. A key-only PraxisTextValue receives text from the fallbackLocale dictionary when available.',
13907
13918
  'UiCompositionPlan.selectionSyncs is an authoring shorthand that compiles into explicit canonical page.composition.links and is never persisted in WidgetPageDefinition.',
13908
- 'UiCompositionPlan.contextScopes compiles constant context into explicit widget inputs and state context into explicit page.composition.links; runtime inheritance is never ambient.',
13919
+ 'UiCompositionPlan.contextScopes compiles constants and state.initial into explicit widget inputs, and state context into explicit page.composition.links; runtime inheritance is never ambient.',
13909
13920
  'Widget keys and composition link ids are stable identities; array indexes are never canonical identities.',
13910
13921
  'Persisted wiring uses page.composition.links and must not write legacy connections.',
13911
13922
  'Nested component ports use component-port refs with nestedPath ending in a stable widget key.',
@@ -14037,6 +14048,56 @@ const PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST = {
14037
14048
  ],
14038
14049
  };
14039
14050
 
14051
+ /**
14052
+ * Pure, fail-closed normalization for an exact template reference.
14053
+ *
14054
+ * The function performs no HTTP, registry search or template selection. The governed backend must
14055
+ * supply the exact materialization and its revision evidence before the existing compiler runs.
14056
+ */
14057
+ function resolveUiCompositionPlanTemplate(input, materialization) {
14058
+ if (!hasTemplateReference(input)) {
14059
+ return { valid: true, referenced: false, plan: input, diagnostics: [] };
14060
+ }
14061
+ const diagnostics = validateTemplateReference(input);
14062
+ if (diagnostics.length) {
14063
+ return { valid: false, referenced: true, plan: null, diagnostics };
14064
+ }
14065
+ if (!materialization || materialization.registryKey !== input.templateRef.registryKey) {
14066
+ return invalidTemplateResolution('ui-composition-template-not-found', 'The exact governed template was not supplied.');
14067
+ }
14068
+ if (!SHA_256_PATTERN.test(materialization.revision?.configSha256 ?? '')) {
14069
+ return invalidTemplateResolution('ui-composition-template-revision-invalid', 'The governed template revision is invalid.');
14070
+ }
14071
+ if (materialization.revision.configSha256 !== input.templateRef.configSha256) {
14072
+ return invalidTemplateResolution('ui-composition-template-hash-mismatch', 'The governed template content no longer matches the pinned hash.');
14073
+ }
14074
+ if (materialization.authoringPlan?.kind !== 'praxis.ui-composition-plan') {
14075
+ return invalidTemplateResolution('ui-composition-template-authoring-plan-kind-invalid', 'The governed artifact is not a UI composition plan.');
14076
+ }
14077
+ if (materialization.authoringPlan.version !== '1.0') {
14078
+ return invalidTemplateResolution('ui-composition-template-authoring-plan-version-invalid', 'The governed UI composition plan version is unsupported.');
14079
+ }
14080
+ const plan = clone(materialization.authoringPlan);
14081
+ plan.diagnostics = {
14082
+ ...(plan.diagnostics ?? {}),
14083
+ templateResolution: {
14084
+ registryKey: materialization.registryKey,
14085
+ configSha256: materialization.revision.configSha256,
14086
+ ...(materialization.revision.version == null ? {} : { version: materialization.revision.version }),
14087
+ ...(materialization.revision.etag ? { etag: materialization.revision.etag } : {}),
14088
+ },
14089
+ };
14090
+ return {
14091
+ valid: true,
14092
+ referenced: true,
14093
+ plan,
14094
+ diagnostics: [{
14095
+ code: 'ui-composition-template-reference-resolved',
14096
+ message: 'The exact governed template reference was resolved.',
14097
+ path: 'templateRef',
14098
+ }],
14099
+ };
14100
+ }
14040
14101
  function compileUiCompositionPlan(plan) {
14041
14102
  const diagnostics = validateUiCompositionPlan(plan);
14042
14103
  if (diagnostics.length) {
@@ -14047,27 +14108,115 @@ function compileUiCompositionPlan(plan) {
14047
14108
  };
14048
14109
  }
14049
14110
  const bindings = expandedBindings(plan);
14050
- const widgets = materializeContextScopeConstants(plan, plan.widgets.map((widget) => toWidgetInstance(widget, bindings)));
14111
+ const widgets = materializeContextScopeInputs(plan, plan.widgets.map((widget) => toWidgetInstance(widget, bindings)));
14112
+ const page = {
14113
+ i18n: clone(plan.i18n),
14114
+ context: clone(plan.context),
14115
+ layout: clone(plan.layout),
14116
+ layoutPreset: plan.layoutPreset,
14117
+ layoutPresetOptions: clone(plan.layoutPresetOptions),
14118
+ canvas: resolveCanvas(plan),
14119
+ deviceLayouts: clone(plan.deviceLayouts),
14120
+ grouping: clone(plan.grouping),
14121
+ slotAssignments: clone(plan.slotAssignments),
14122
+ state: clone(plan.state),
14123
+ themePreset: plan.themePreset,
14124
+ widgets,
14125
+ composition: {
14126
+ version: '1.0.0',
14127
+ links: bindings.map(toCompositionLink),
14128
+ },
14129
+ };
14051
14130
  return {
14052
14131
  valid: true,
14053
- page: {
14054
- layoutPreset: plan.layoutPreset,
14055
- layoutPresetOptions: clone(plan.layoutPresetOptions),
14056
- canvas: resolveCanvas(plan),
14057
- deviceLayouts: clone(plan.deviceLayouts),
14058
- grouping: clone(plan.grouping),
14059
- slotAssignments: clone(plan.slotAssignments),
14060
- state: clone(plan.state),
14061
- themePreset: plan.themePreset,
14062
- widgets,
14063
- composition: {
14064
- version: '1.0.0',
14065
- links: bindings.map(toCompositionLink),
14066
- },
14067
- },
14132
+ page: materializeLocalizedFallbacks(page),
14068
14133
  diagnostics: [],
14069
14134
  };
14070
14135
  }
14136
+ const SHA_256_PATTERN = /^[0-9a-f]{64}$/;
14137
+ const TEMPLATE_REFERENCE_FIELDS = new Set(['version', 'kind', 'templateRef', 'overrides']);
14138
+ const TEMPLATE_REF_FIELDS = new Set(['registryKey', 'configSha256']);
14139
+ function hasTemplateReference(input) {
14140
+ return input != null && typeof input === 'object' && 'templateRef' in input;
14141
+ }
14142
+ function validateTemplateReference(input) {
14143
+ const diagnostics = [];
14144
+ if (input.kind !== 'praxis.ui-composition-plan') {
14145
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-kind-invalid', 'kind'));
14146
+ }
14147
+ if (input.version !== '1.0') {
14148
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-version-invalid', 'version'));
14149
+ }
14150
+ if (!isRecord$1(input.templateRef)) {
14151
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-object-required', 'templateRef'));
14152
+ return diagnostics;
14153
+ }
14154
+ const registryKey = input.templateRef.registryKey;
14155
+ if (typeof registryKey !== 'string' || !registryKey || registryKey !== registryKey.trim()) {
14156
+ diagnostics.push(templateDiagnostic('ui-composition-template-registry-key-invalid', 'templateRef.registryKey'));
14157
+ }
14158
+ if (typeof input.templateRef.configSha256 !== 'string' || !SHA_256_PATTERN.test(input.templateRef.configSha256)) {
14159
+ diagnostics.push(templateDiagnostic('ui-composition-template-config-sha256-invalid', 'templateRef.configSha256'));
14160
+ }
14161
+ if (Object.keys(input.templateRef).some((field) => !TEMPLATE_REF_FIELDS.has(field))
14162
+ || Object.keys(input.templateRef).length !== TEMPLATE_REF_FIELDS.size) {
14163
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-fields-invalid', 'templateRef'));
14164
+ }
14165
+ if (input.overrides !== undefined && (!isRecord$1(input.overrides) || Object.keys(input.overrides).length > 0)) {
14166
+ diagnostics.push(templateDiagnostic('ui-composition-template-overrides-unsupported', 'overrides'));
14167
+ }
14168
+ if (Object.keys(input).some((field) => !TEMPLATE_REFERENCE_FIELDS.has(field))) {
14169
+ diagnostics.push(templateDiagnostic('ui-composition-template-reference-mixed-plan'));
14170
+ }
14171
+ return diagnostics;
14172
+ }
14173
+ function invalidTemplateResolution(code, message) {
14174
+ return {
14175
+ valid: false,
14176
+ referenced: true,
14177
+ plan: null,
14178
+ diagnostics: [{ code, message, path: 'templateRef' }],
14179
+ };
14180
+ }
14181
+ function templateDiagnostic(code, path) {
14182
+ return { code, message: 'The governed template reference is invalid.', path };
14183
+ }
14184
+ function isRecord$1(value) {
14185
+ return value != null && typeof value === 'object' && !Array.isArray(value);
14186
+ }
14187
+ /**
14188
+ * Keeps authoring plans compact while preserving a portable executable page.
14189
+ * A descriptor authored as `{ key }` inherits its runtime fallback from the
14190
+ * page-owned fallback-locale dictionary. The source plan remains untouched.
14191
+ */
14192
+ function materializeLocalizedFallbacks(page) {
14193
+ const materialized = clone(page);
14194
+ const fallbackLocale = materialized.i18n?.fallbackLocale?.trim() || 'pt-BR';
14195
+ const dictionary = materialized.i18n?.dictionaries?.[fallbackLocale];
14196
+ if (!dictionary)
14197
+ return materialized;
14198
+ const descriptorKeys = new Set(['key', 'text', 'params']);
14199
+ const visit = (value) => {
14200
+ if (Array.isArray(value)) {
14201
+ value.forEach(visit);
14202
+ return;
14203
+ }
14204
+ if (!value || typeof value !== 'object')
14205
+ return;
14206
+ const record = value;
14207
+ const keys = Object.keys(record);
14208
+ const key = typeof record['key'] === 'string' ? record['key'].trim() : '';
14209
+ if (key
14210
+ && !Object.prototype.hasOwnProperty.call(record, 'text')
14211
+ && keys.every((candidate) => descriptorKeys.has(candidate))
14212
+ && typeof dictionary[key] === 'string') {
14213
+ record['text'] = dictionary[key];
14214
+ }
14215
+ Object.values(record).forEach(visit);
14216
+ };
14217
+ visit(materialized);
14218
+ return materialized;
14219
+ }
14071
14220
  function resolveCanvas(plan) {
14072
14221
  if (plan.canvas) {
14073
14222
  return clone(plan.canvas);
@@ -14075,6 +14224,13 @@ function resolveCanvas(plan) {
14075
14224
  if (!plan.widgets?.length) {
14076
14225
  return undefined;
14077
14226
  }
14227
+ // An explicitly authored flow/grid layout is already a complete spatial
14228
+ // decision. Synthesizing a canvas here would silently take precedence over
14229
+ // that layout in the runtime. Preset- or role-driven plans still opt into
14230
+ // automatic canvas materialization below.
14231
+ if (plan.layout && !plan.layoutPreset?.trim() && !isMasterDetailPlan(plan)) {
14232
+ return undefined;
14233
+ }
14078
14234
  if (isMasterDetailPlan(plan)) {
14079
14235
  return masterDetailCanvas(plan.widgets);
14080
14236
  }
@@ -14247,7 +14403,14 @@ function validateSelectionSync(selectionSync, widgetKeys, diagnostics, path) {
14247
14403
  }
14248
14404
  for (const [sourceIndex, source] of (selectionSync.sources ?? []).entries()) {
14249
14405
  validateEndpoint(source, widgetKeys, diagnostics, `${path}.sources.${sourceIndex}`, false);
14250
- if (source?.kind === 'component-port' && source.direction !== 'output') {
14406
+ if (source?.kind !== 'component-port') {
14407
+ diagnostics.push({
14408
+ code: 'selection-sync-source-component-port-required',
14409
+ message: 'Selection sync sources must be component output ports.',
14410
+ path: `${path}.sources.${sourceIndex}.kind`,
14411
+ });
14412
+ }
14413
+ else if (source.direction !== 'output') {
14251
14414
  diagnostics.push({
14252
14415
  code: 'selection-sync-source-direction-invalid',
14253
14416
  message: 'Selection sync sources must be component output ports.',
@@ -14319,14 +14482,25 @@ function validateContextScope(contextScope, plan, widgetKeys, diagnostics, path)
14319
14482
  path: `${path}.context`,
14320
14483
  });
14321
14484
  }
14322
- if (contextValue?.kind === 'state' && !contextValue.path?.trim()) {
14323
- diagnostics.push({
14324
- code: 'context-scope-state-path-required',
14325
- message: `Context value "${contextKey}" must declare a state path.`,
14326
- path: `${path}.context.${contextKey}.path`,
14327
- });
14485
+ if (contextValue?.kind === 'state') {
14486
+ if (!contextValue.path?.trim()) {
14487
+ diagnostics.push({
14488
+ code: 'context-scope-state-path-required',
14489
+ message: `Context value "${contextKey}" must declare a state path.`,
14490
+ path: `${path}.context.${contextKey}.path`,
14491
+ });
14492
+ }
14493
+ }
14494
+ else if (contextValue?.kind === 'constant') {
14495
+ if (!Object.prototype.hasOwnProperty.call(contextValue, 'value')) {
14496
+ diagnostics.push({
14497
+ code: 'context-scope-constant-value-required',
14498
+ message: `Context value "${contextKey}" must declare a constant value.`,
14499
+ path: `${path}.context.${contextKey}.value`,
14500
+ });
14501
+ }
14328
14502
  }
14329
- else if (contextValue?.kind !== 'state' && contextValue?.kind !== 'constant') {
14503
+ else {
14330
14504
  diagnostics.push({
14331
14505
  code: 'context-scope-value-kind-invalid',
14332
14506
  message: `Context value "${contextKey}" must be constant or state.`,
@@ -14634,7 +14808,7 @@ function expandContextScopeBindings(contextScope) {
14634
14808
  });
14635
14809
  });
14636
14810
  }
14637
- function materializeContextScopeConstants(plan, sourceWidgets) {
14811
+ function materializeContextScopeInputs(plan, sourceWidgets) {
14638
14812
  const accessor = new NestedWidgetConfigAccessor();
14639
14813
  const widgets = sourceWidgets.map((widget) => clone(widget));
14640
14814
  for (const contextScope of plan.contextScopes ?? []) {
@@ -14647,10 +14821,17 @@ function materializeContextScopeConstants(plan, sourceWidgets) {
14647
14821
  : Object.keys(contextScope.context);
14648
14822
  for (const contextKey of inheritedKeys) {
14649
14823
  const contextValue = contextScope.context[contextKey];
14650
- if (!contextValue || contextValue.kind !== 'constant')
14824
+ if (!contextValue)
14825
+ continue;
14826
+ const hasInitial = contextValue.kind === 'state'
14827
+ && Object.prototype.hasOwnProperty.call(contextValue, 'initial');
14828
+ if (contextValue.kind !== 'constant' && !hasInitial)
14651
14829
  continue;
14830
+ const inputValue = contextValue.kind === 'constant'
14831
+ ? contextValue.value
14832
+ : contextValue.initial;
14652
14833
  if (target.nestedPath?.length) {
14653
- const result = accessor.setNestedWidgetInput(widgets[widgetIndex], target.nestedPath, contextKey, contextValue.value);
14834
+ const result = accessor.setNestedWidgetInput(widgets[widgetIndex], target.nestedPath, contextKey, inputValue);
14654
14835
  widgets[widgetIndex] = result.widget;
14655
14836
  }
14656
14837
  else {
@@ -14660,7 +14841,7 @@ function materializeContextScopeConstants(plan, sourceWidgets) {
14660
14841
  ...widgets[widgetIndex].definition,
14661
14842
  inputs: {
14662
14843
  ...(widgets[widgetIndex].definition.inputs ?? {}),
14663
- [contextKey]: clone(contextValue.value),
14844
+ [contextKey]: clone(inputValue),
14664
14845
  },
14665
14846
  },
14666
14847
  };
@@ -14678,6 +14859,7 @@ function toWidgetInstance(widget, bindings) {
14678
14859
  const outputs = linkedTopLevelOutputs(widget.key, widget.outputs, bindings);
14679
14860
  return {
14680
14861
  key: widget.key,
14862
+ shell: clone(widget.shell),
14681
14863
  definition: {
14682
14864
  id: widget.componentId,
14683
14865
  bindingOrder: widget.bindingOrder,
@@ -25555,4 +25737,4 @@ function providePraxisPageBuilderMetadata() {
25555
25737
  * Generated bundle index. Do not edit.
25556
25738
  */
25557
25739
 
25558
- export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };
25740
+ export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/page-builder",
3
- "version": "9.0.5-rc.2",
3
+ "version": "9.0.5-rc.21",
4
4
  "description": "Page and widget builder utilities for Praxis UI (grid, dynamic widgets, editors).",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
@@ -8,9 +8,9 @@
8
8
  "@angular/forms": "^21.0.0",
9
9
  "@angular/cdk": "^21.0.0",
10
10
  "@angular/material": "^21.0.0",
11
- "@praxisui/ai": "^9.0.5-rc.2",
12
- "@praxisui/core": "^9.0.5-rc.2",
13
- "@praxisui/settings-panel": "^9.0.5-rc.2",
11
+ "@praxisui/ai": "^9.0.5-rc.21",
12
+ "@praxisui/core": "^9.0.5-rc.21",
13
+ "@praxisui/settings-panel": "^9.0.5-rc.21",
14
14
  "rxjs": "~7.8.0"
15
15
  },
16
16
  "dependencies": {
@@ -1534,6 +1534,7 @@ interface UiCompositionPlanWidget {
1534
1534
  key: string;
1535
1535
  componentId: string;
1536
1536
  role?: string;
1537
+ shell?: WidgetInstance['shell'];
1537
1538
  inputs?: Record<string, unknown>;
1538
1539
  outputs?: Record<string, unknown>;
1539
1540
  bindingOrder?: string[];
@@ -1575,6 +1576,8 @@ type UiCompositionPlanContextValue = {
1575
1576
  path: string;
1576
1577
  layer?: 'values' | 'derived' | 'transient';
1577
1578
  condition?: unknown;
1579
+ /** Explicit value materialized before the first state propagation. */
1580
+ initial?: unknown;
1578
1581
  };
1579
1582
  interface UiCompositionPlanContextScopeTarget {
1580
1583
  widget: string;
@@ -1583,8 +1586,9 @@ interface UiCompositionPlanContextScopeTarget {
1583
1586
  }
1584
1587
  /**
1585
1588
  * Groups reusable parent/resource context for one or more component targets.
1586
- * Constants become explicit widget inputs and state values become explicit
1587
- * canonical links during compilation; no hidden runtime inheritance remains.
1589
+ * Constants and explicit state initial values become widget inputs, while
1590
+ * state values become canonical links during compilation. No hidden runtime
1591
+ * inheritance remains in the executable page.
1588
1592
  */
1589
1593
  interface UiCompositionPlanContextScope {
1590
1594
  id: string;
@@ -1596,6 +1600,12 @@ interface UiCompositionPlanContextScope {
1596
1600
  interface UiCompositionPlan {
1597
1601
  version: '1.0';
1598
1602
  kind: 'praxis.ui-composition-plan';
1603
+ /** Page-owned business copy compiled verbatim into WidgetPageDefinition.i18n. */
1604
+ i18n?: WidgetPageDefinition['i18n'];
1605
+ /** Explicit page-wide context compiled into WidgetPageDefinition.context. */
1606
+ context?: WidgetPageDefinition['context'];
1607
+ /** Canonical responsive grid layout compiled into WidgetPageDefinition.layout. */
1608
+ layout?: WidgetPageDefinition['layout'];
1599
1609
  layoutPreset?: string;
1600
1610
  layoutPresetOptions?: Record<string, unknown>;
1601
1611
  canvas?: WidgetPageCanvasLayout;
@@ -1608,7 +1618,43 @@ interface UiCompositionPlan {
1608
1618
  selectionSyncs?: UiCompositionPlanSelectionSync[];
1609
1619
  contextScopes?: UiCompositionPlanContextScope[];
1610
1620
  bindings?: UiCompositionPlanBinding[];
1621
+ /** Non-executable authoring and resolution evidence; never copied into WidgetPageDefinition. */
1622
+ diagnostics?: Record<string, unknown>;
1611
1623
  }
1624
+ interface UiCompositionPlanTemplateRef {
1625
+ registryKey: string;
1626
+ configSha256: string;
1627
+ }
1628
+ /** Compact intermediate authoring input. It is never a runtime persistence shape. */
1629
+ interface UiCompositionPlanTemplateReference {
1630
+ version: '1.0';
1631
+ kind: 'praxis.ui-composition-plan';
1632
+ templateRef: UiCompositionPlanTemplateRef;
1633
+ overrides?: Readonly<Record<string, never>>;
1634
+ }
1635
+ interface UiCompositionPlanTemplateRevision {
1636
+ version?: number;
1637
+ etag?: string;
1638
+ configSha256: string;
1639
+ }
1640
+ /** Exact template body and revision evidence supplied by the governed backend. */
1641
+ interface UiCompositionPlanTemplateMaterialization {
1642
+ registryKey: string;
1643
+ revision: UiCompositionPlanTemplateRevision;
1644
+ authoringPlan: UiCompositionPlan;
1645
+ }
1646
+ type UiCompositionPlanAuthoringInput = UiCompositionPlan | UiCompositionPlanTemplateReference;
1647
+ type UiCompositionPlanTemplateResolutionResult = {
1648
+ valid: true;
1649
+ referenced: boolean;
1650
+ plan: UiCompositionPlan;
1651
+ diagnostics: UiCompositionPlanDiagnostic[];
1652
+ } | {
1653
+ valid: false;
1654
+ referenced: true;
1655
+ plan: null;
1656
+ diagnostics: UiCompositionPlanDiagnostic[];
1657
+ };
1612
1658
  interface UiCompositionPlanDiagnostic {
1613
1659
  code: string;
1614
1660
  message: string;
@@ -1623,6 +1669,13 @@ type UiCompositionPlanCompileResult = {
1623
1669
  page: null;
1624
1670
  diagnostics: UiCompositionPlanDiagnostic[];
1625
1671
  };
1672
+ /**
1673
+ * Pure, fail-closed normalization for an exact template reference.
1674
+ *
1675
+ * The function performs no HTTP, registry search or template selection. The governed backend must
1676
+ * supply the exact materialization and its revision evidence before the existing compiler runs.
1677
+ */
1678
+ declare function resolveUiCompositionPlanTemplate(input: UiCompositionPlanAuthoringInput, materialization?: UiCompositionPlanTemplateMaterialization): UiCompositionPlanTemplateResolutionResult;
1626
1679
  declare function compileUiCompositionPlan(plan: UiCompositionPlan): UiCompositionPlanCompileResult;
1627
1680
  declare function validateUiCompositionPlan(plan: UiCompositionPlan): UiCompositionPlanDiagnostic[];
1628
1681
 
@@ -2133,5 +2186,5 @@ declare const PRAXIS_PAGE_BUILDER_COMPONENT_METADATA: ComponentDocMeta;
2133
2186
  /** Provider para auto-registrar metadados do componente Page Builder. */
2134
2187
  declare function providePraxisPageBuilderMetadata(): Provider;
2135
2188
 
2136
- export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, validateUiCompositionPlan };
2137
- export type { Capability, CapabilityCatalog, CapabilityCategory, ComponentPaletteData, ComponentPaletteSelection, ConfirmDialogData, PageBuilderAgenticAuthoringAttachmentSummary, PageBuilderAgenticAuthoringCandidate, PageBuilderAgenticAuthoringComponentCapabilitiesResult, PageBuilderAgenticAuthoringComponentCapability, PageBuilderAgenticAuthoringComponentCapabilityCatalog, PageBuilderAgenticAuthoringComponentCapabilityExample, PageBuilderAgenticAuthoringComponentFieldAlias, PageBuilderAgenticAuthoringConversationMessage, PageBuilderAgenticAuthoringGateResult, PageBuilderAgenticAuthoringIntentResolutionRequest, PageBuilderAgenticAuthoringIntentResolutionResult, PageBuilderAgenticAuthoringOptions, PageBuilderAgenticAuthoringPendingClarification, PageBuilderAgenticAuthoringPromptRequest, PageBuilderAgenticAuthoringProvider, PageBuilderAgenticAuthoringQuickReply, PageBuilderAgenticAuthoringResourceCandidatesRequest, PageBuilderAgenticAuthoringResourceCandidatesResult, PageBuilderAgenticAuthoringSharedRuleHandoff, PageBuilderAgenticAuthoringTarget, PageBuilderAgenticAuthoringTurnStreamConnectionError, PageBuilderAgenticAuthoringTurnStreamEvent, PageBuilderAgenticAuthoringTurnStreamRequest, PageBuilderAgenticAuthoringTurnStreamStartResponse, PageBuilderApplyRequest, PageBuilderApplyResult, PageBuilderCompiledFormPatch, PageBuilderMinimalFormPlanResult, PageBuilderPreviewDiagnostics, PageBuilderPreviewResult, PageBuilderProjectKnowledgeAudit, UiCompositionPlan, UiCompositionPlanBinding, UiCompositionPlanCompileResult, UiCompositionPlanComponentPortEndpoint, UiCompositionPlanContextScope, UiCompositionPlanContextScopeTarget, UiCompositionPlanContextValue, UiCompositionPlanDiagnostic, UiCompositionPlanEndpoint, UiCompositionPlanGlobalActionEndpoint, UiCompositionPlanInputSource, UiCompositionPlanSelectionSync, UiCompositionPlanSelectionSyncMapping, UiCompositionPlanSourceEndpoint, UiCompositionPlanStateEndpoint, UiCompositionPlanTargetEndpoint, UiCompositionPlanTransform, UiCompositionPlanWidget, ValueKind };
2189
+ export { ComponentPaletteDialogComponent, ConfirmDialogComponent, ConnectionEditorComponent, DynamicPageBuilderComponent, DynamicPageConfigEditorComponent, FloatingToolbarComponent, PAGE_BUILDER_AGENTIC_AUTHORING_OPTIONS, PAGE_BUILDER_AI_CAPABILITIES, PAGE_BUILDER_COMPONENT_CONTEXT_PACK, PAGE_BUILDER_WIDGET_AI_CATALOGS, PLACEHOLDER, PRAXIS_PAGE_BUILDER_AUTHORING_MANIFEST, PRAXIS_PAGE_BUILDER_COMPONENT_METADATA, PageBuilderAgenticAuthoringService, PageConfigEditorComponent, TileToolbarComponent, WidgetShellEditorComponent, clearWidgetAiCatalogs, compileUiCompositionPlan, getPageAiCatalog, getWidgetAiCapabilities, providePageBuilderWidgetAiCatalogs, providePraxisPageBuilderMetadata, registerWidgetAiCatalog, registerWidgetAiCatalogs, resolveUiCompositionPlanTemplate, validateUiCompositionPlan };
2190
+ export type { Capability, CapabilityCatalog, CapabilityCategory, ComponentPaletteData, ComponentPaletteSelection, ConfirmDialogData, PageBuilderAgenticAuthoringAttachmentSummary, PageBuilderAgenticAuthoringCandidate, PageBuilderAgenticAuthoringComponentCapabilitiesResult, PageBuilderAgenticAuthoringComponentCapability, PageBuilderAgenticAuthoringComponentCapabilityCatalog, PageBuilderAgenticAuthoringComponentCapabilityExample, PageBuilderAgenticAuthoringComponentFieldAlias, PageBuilderAgenticAuthoringConversationMessage, PageBuilderAgenticAuthoringGateResult, PageBuilderAgenticAuthoringIntentResolutionRequest, PageBuilderAgenticAuthoringIntentResolutionResult, PageBuilderAgenticAuthoringOptions, PageBuilderAgenticAuthoringPendingClarification, PageBuilderAgenticAuthoringPromptRequest, PageBuilderAgenticAuthoringProvider, PageBuilderAgenticAuthoringQuickReply, PageBuilderAgenticAuthoringResourceCandidatesRequest, PageBuilderAgenticAuthoringResourceCandidatesResult, PageBuilderAgenticAuthoringSharedRuleHandoff, PageBuilderAgenticAuthoringTarget, PageBuilderAgenticAuthoringTurnStreamConnectionError, PageBuilderAgenticAuthoringTurnStreamEvent, PageBuilderAgenticAuthoringTurnStreamRequest, PageBuilderAgenticAuthoringTurnStreamStartResponse, PageBuilderApplyRequest, PageBuilderApplyResult, PageBuilderCompiledFormPatch, PageBuilderMinimalFormPlanResult, PageBuilderPreviewDiagnostics, PageBuilderPreviewResult, PageBuilderProjectKnowledgeAudit, UiCompositionPlan, UiCompositionPlanAuthoringInput, UiCompositionPlanBinding, UiCompositionPlanCompileResult, UiCompositionPlanComponentPortEndpoint, UiCompositionPlanContextScope, UiCompositionPlanContextScopeTarget, UiCompositionPlanContextValue, UiCompositionPlanDiagnostic, UiCompositionPlanEndpoint, UiCompositionPlanGlobalActionEndpoint, UiCompositionPlanInputSource, UiCompositionPlanSelectionSync, UiCompositionPlanSelectionSyncMapping, UiCompositionPlanSourceEndpoint, UiCompositionPlanStateEndpoint, UiCompositionPlanTargetEndpoint, UiCompositionPlanTemplateMaterialization, UiCompositionPlanTemplateRef, UiCompositionPlanTemplateReference, UiCompositionPlanTemplateResolutionResult, UiCompositionPlanTemplateRevision, UiCompositionPlanTransform, UiCompositionPlanWidget, ValueKind };