@praxisui/visual-builder 8.0.0-beta.11 → 8.0.0-beta.13

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
@@ -86,10 +86,38 @@ Use the canonical public services:
86
86
 
87
87
  Main exports available from `@praxisui/visual-builder`:
88
88
 
89
+ - Agentic authoring: `PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST`
89
90
  - Components: `RuleEditorComponent`, `RuleCanvasComponent`, `RuleNodeComponent`, `FieldConditionEditorComponent`, `ConditionalValidatorEditorComponent`, `CollectionValidatorEditorComponent`, `MetadataEditorComponent`, `JsonViewerComponent`, `ExportDialogComponent`, `VisualRuleBuilderComponent`, `TemplateGalleryComponent`, `TemplateEditorDialogComponent`, `TemplatePreviewDialogComponent`, `RuleListComponent`, `ContextVariableManagerComponent`
90
91
  - Services: `RuleBuilderService`, `ExportIntegrationService`, `WebhookIntegrationService`, `RuleTemplateService`, `RuleValidationService`, `RuleNodeRegistryService`, `ContextManagementService`, `FieldSchemaService`
91
92
  - Models/Types: `FieldSchema`, `RuleBuilderConfig`, `ArrayFieldSchema`, `ContextScope`, `ContextEntry`, `ContextValue`
92
93
 
94
+ ## Agentic Authoring Contract
95
+
96
+ `PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST` is the executable AI authoring contract for this package.
97
+
98
+ The manifest governs visual graph and JSON Logic orchestration:
99
+
100
+ - `node.add`
101
+ - `node.remove`
102
+ - `node.configure`
103
+ - `edge.connect`
104
+ - `edge.remove`
105
+ - `variable.add`
106
+ - `condition.set`
107
+ - `effect.set`
108
+ - `dsl.roundTrip.validate`
109
+
110
+ Boundary rules:
111
+
112
+ - `RuleBuilderState` is the visual source of truth
113
+ - operations write canonical runtime paths under `RuleBuilderState`, `RuleBuilderConfig`, `RuleNodeRegistryService` and `ContextManagementService`
114
+ - node ids and context variable scope/name are stable identities
115
+ - graph edges must reference existing nodes and avoid cycles where required
116
+ - conditions persist as JSON Logic objects, not JavaScript or legacy textual DSL
117
+ - effects must be constrained by target property schemas and `RULE_PROPERTY_SCHEMA`
118
+ - `dsl.roundTrip.validate` validates the JSON export/import path currently implemented by `RuleBuilderService`; form-config import remains supported but is not advertised as a round-trip export target by this operation
119
+ - component-specific configuration belongs to child component manifests
120
+
93
121
  ## Legacy Note
94
122
 
95
123
  The old textual `ExpressionEditorComponent` and DSL validation path were removed from the canonical library surface. Legacy DSL migration material should not be used as a baseline for new integrations.
@@ -9983,6 +9983,12 @@ class TargetSelectorComponent {
9983
9983
  description: this.t('target.type.action.description', 'Botoes de acao.'),
9984
9984
  icon: 'smart_button',
9985
9985
  },
9986
+ {
9987
+ id: 'visualBlock',
9988
+ label: this.t('target.type.visualBlock.label', 'Bloco visual'),
9989
+ description: this.t('target.type.visualBlock.description', 'Bloco editorial no layout.'),
9990
+ icon: 'notes',
9991
+ },
9986
9992
  ];
9987
9993
  }
9988
9994
  ngOnInit() {
@@ -10153,6 +10159,8 @@ class TargetSelectorComponent {
10153
10159
  return this.targetSchemas.rows || {};
10154
10160
  case 'column':
10155
10161
  return this.targetSchemas.columns || {};
10162
+ case 'visualBlock':
10163
+ return this.targetSchemas.visualBlocks || {};
10156
10164
  default:
10157
10165
  return {};
10158
10166
  }
@@ -10781,6 +10789,8 @@ class RuleDefinitionComponent {
10781
10789
  return this.t('ruleDefinition.targetType.rowPlural', 'Linhas');
10782
10790
  case 'column':
10783
10791
  return this.t('ruleDefinition.targetType.columnPlural', 'Colunas');
10792
+ case 'visualBlock':
10793
+ return this.t('ruleDefinition.targetType.visualBlockPlural', 'Blocos visuais');
10784
10794
  default:
10785
10795
  return this.t('ruleDefinition.targetType.fieldPlural', 'Campos');
10786
10796
  }
@@ -12657,6 +12667,9 @@ class RuleEditorComponent {
12657
12667
  return;
12658
12668
  }
12659
12669
  const finalResponse = validation.correctedResponse || aiResponse;
12670
+ const finalCondition = finalResponse.condition
12671
+ ? finalResponse.condition
12672
+ : undefined;
12660
12673
  try {
12661
12674
  const draftNodeId = this.ruleBuilderService.addNode({
12662
12675
  type: RuleNodeType.PROPERTY_RULE,
@@ -12665,7 +12678,7 @@ class RuleEditorComponent {
12665
12678
  type: 'propertyRule',
12666
12679
  targetType: finalResponse.targetType,
12667
12680
  targets: finalResponse.targetIds,
12668
- condition: finalResponse.condition || undefined,
12681
+ condition: finalCondition,
12669
12682
  properties: finalResponse.effects.properties,
12670
12683
  propertiesWhenFalse: finalResponse.effects.propertiesWhenFalse,
12671
12684
  },
@@ -13320,6 +13333,403 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13320
13333
  type: Output
13321
13334
  }] } });
13322
13335
 
13336
+ const nodeAddSchema = {
13337
+ type: 'object',
13338
+ required: ['nodeId', 'nodeType'],
13339
+ properties: {
13340
+ nodeId: { type: 'string' },
13341
+ nodeType: {
13342
+ enum: [
13343
+ 'fieldCondition',
13344
+ 'propertyRule',
13345
+ 'andGroup',
13346
+ 'orGroup',
13347
+ 'notGroup',
13348
+ 'xorGroup',
13349
+ 'impliesGroup',
13350
+ 'requiredIf',
13351
+ 'visibleIf',
13352
+ 'disabledIf',
13353
+ 'readonlyIf',
13354
+ 'forEach',
13355
+ 'uniqueBy',
13356
+ 'minLength',
13357
+ 'maxLength',
13358
+ 'ifDefined',
13359
+ 'ifNotNull',
13360
+ 'ifExists',
13361
+ 'withDefault',
13362
+ 'functionCall',
13363
+ 'fieldToField',
13364
+ 'contextual',
13365
+ 'atLeast',
13366
+ 'exactly',
13367
+ 'expression',
13368
+ 'contextualTemplate',
13369
+ 'custom',
13370
+ ],
13371
+ },
13372
+ label: { type: 'string' },
13373
+ parentId: { type: 'string' },
13374
+ config: { type: 'object' },
13375
+ metadata: { type: 'object' },
13376
+ },
13377
+ };
13378
+ const nodeRemoveSchema = {
13379
+ type: 'object',
13380
+ required: ['nodeId'],
13381
+ properties: {
13382
+ nodeId: { type: 'string' },
13383
+ removeDescendants: { type: 'boolean' },
13384
+ preserveDisconnectedChildren: { type: 'boolean' },
13385
+ },
13386
+ };
13387
+ const nodeConfigureSchema = {
13388
+ type: 'object',
13389
+ required: ['nodeId'],
13390
+ properties: {
13391
+ nodeId: { type: 'string' },
13392
+ label: { type: 'string' },
13393
+ configPatch: { type: 'object' },
13394
+ metadataPatch: { type: 'object' },
13395
+ expanded: { type: 'boolean' },
13396
+ },
13397
+ };
13398
+ const edgeConnectSchema = {
13399
+ type: 'object',
13400
+ required: ['sourceNodeId', 'targetNodeId'],
13401
+ properties: {
13402
+ sourceNodeId: { type: 'string' },
13403
+ targetNodeId: { type: 'string' },
13404
+ edgeKind: { enum: ['child', 'condition', 'effect'] },
13405
+ insertIndex: { type: 'number' },
13406
+ },
13407
+ };
13408
+ const edgeRemoveSchema = {
13409
+ type: 'object',
13410
+ required: ['sourceNodeId', 'targetNodeId'],
13411
+ properties: {
13412
+ sourceNodeId: { type: 'string' },
13413
+ targetNodeId: { type: 'string' },
13414
+ edgeKind: { enum: ['child', 'condition', 'effect'] },
13415
+ removeOrphanTarget: { type: 'boolean' },
13416
+ },
13417
+ };
13418
+ const variableAddSchema = {
13419
+ type: 'object',
13420
+ required: ['name', 'scope', 'type'],
13421
+ properties: {
13422
+ name: { type: 'string' },
13423
+ scope: { type: 'string' },
13424
+ type: { enum: ['string', 'number', 'boolean', 'object', 'array'] },
13425
+ valueType: { enum: ['literal', 'field', 'context', 'function'] },
13426
+ defaultValue: {},
13427
+ description: { type: 'string' },
13428
+ },
13429
+ };
13430
+ const conditionSetSchema = {
13431
+ type: 'object',
13432
+ required: ['nodeId', 'condition'],
13433
+ properties: {
13434
+ nodeId: { type: 'string' },
13435
+ condition: { type: 'object' },
13436
+ mode: { enum: ['replace', 'merge'] },
13437
+ source: { enum: ['visual', 'jsonLogic'] },
13438
+ },
13439
+ };
13440
+ const effectSetSchema = {
13441
+ type: 'object',
13442
+ required: ['nodeId', 'targetType', 'targets', 'properties'],
13443
+ properties: {
13444
+ nodeId: { type: 'string' },
13445
+ targetType: { enum: ['field', 'section', 'action', 'row', 'column', 'visualBlock'] },
13446
+ targets: {
13447
+ type: 'array',
13448
+ items: { type: 'string' },
13449
+ },
13450
+ properties: { type: 'object' },
13451
+ propertiesWhenFalse: { type: 'object' },
13452
+ conditionNodeId: { type: 'string' },
13453
+ },
13454
+ };
13455
+ const dslRoundTripValidateSchema = {
13456
+ type: 'object',
13457
+ properties: {
13458
+ format: { enum: ['json'] },
13459
+ requireStableIds: { type: 'boolean' },
13460
+ compareMode: { enum: ['semantic', 'exact'] },
13461
+ },
13462
+ };
13463
+ const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST = {
13464
+ schemaVersion: '1.0.0',
13465
+ componentId: 'praxis-visual-builder',
13466
+ ownerPackage: '@praxisui/visual-builder',
13467
+ configSchemaId: 'RuleBuilderState',
13468
+ manifestVersion: '1.0.0',
13469
+ runtimeInputs: [
13470
+ { name: 'config', type: 'RuleBuilderConfig | null', description: 'Builder configuration with field schemas, target schemas, context variables, validation and export/import settings.' },
13471
+ { name: 'initialRules', type: 'RuleBuilderState | FormLayoutRule[] | JsonLogicExpression | null', description: 'Initial rules loaded into the visual builder.' },
13472
+ { name: 'rulesChanged', type: 'RuleBuilderState', description: 'Emitted visual builder state after graph or JSON Logic changes.' },
13473
+ { name: 'exportRequested', type: 'ExportOptions', description: 'Emitted export request for JSON, TypeScript or form-config payloads.' },
13474
+ { name: 'importRequested', type: 'ImportOptions', description: 'Emitted import request for JSON or form-config payloads.' },
13475
+ ],
13476
+ editableTargets: [
13477
+ { kind: 'node', resolver: 'rule-node-by-id', description: 'Visual rule graph node keyed by stable RuleNode.id.' },
13478
+ { kind: 'edge', resolver: 'rule-node-edge-by-source-target', description: 'Parent-child or semantic graph edge between existing rule nodes.' },
13479
+ { kind: 'variable', resolver: 'context-variable-by-name-scope', description: 'Context variable available to rule conditions and contextual nodes.' },
13480
+ { kind: 'condition', resolver: 'json-logic-condition-by-node', description: 'JSON Logic condition attached to a node or represented by condition nodes.' },
13481
+ { kind: 'effect', resolver: 'property-effect-by-node', description: 'Targeted property effect persisted as propertyRule/FormLayoutRule semantics.' },
13482
+ { kind: 'dslDocument', resolver: 'rule-builder-json-logic-document', description: 'Serialized JSON Logic/form-config document produced from the visual model.' },
13483
+ ],
13484
+ operations: [
13485
+ {
13486
+ operationId: 'node.add',
13487
+ title: 'Add visual rule node',
13488
+ scope: 'rules',
13489
+ targetKind: 'node',
13490
+ target: { kind: 'node', resolver: 'rule-node-by-id', ambiguityPolicy: 'fail', required: true },
13491
+ inputSchema: nodeAddSchema,
13492
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-node-add', handlerContract: {
13493
+ reads: ['RuleBuilderState.nodes', 'RuleBuilderState.rootNodes', 'RuleNodeRegistryService', 'RuleBuilderService.addNode'],
13494
+ writes: ['RuleBuilderState.nodes', 'RuleBuilderState.rootNodes', 'RuleNodeRegistryService'],
13495
+ identityKeys: ['nodeId'],
13496
+ inputSchema: nodeAddSchema,
13497
+ failureModes: ['duplicate-node-id', 'unsupported-node-type', 'parent-node-not-found', 'graph-cycle-created'],
13498
+ description: 'Adds a rule node by stable id and validates graph integrity before the state can be serialized.',
13499
+ } }],
13500
+ validators: ['node-id-unique', 'node-type-supported', 'parent-node-exists', 'graph-valid', 'dsl-round-trip-stable'],
13501
+ affectedPaths: ['RuleBuilderState.nodes', 'RuleBuilderState.rootNodes', 'RuleNodeRegistryService'],
13502
+ submissionImpact: 'config-only',
13503
+ preconditions: ['rule-builder-state-loaded'],
13504
+ destructive: false,
13505
+ requiresConfirmation: false,
13506
+ },
13507
+ {
13508
+ operationId: 'node.remove',
13509
+ title: 'Remove visual rule node',
13510
+ scope: 'rules',
13511
+ targetKind: 'node',
13512
+ target: { kind: 'node', resolver: 'rule-node-by-id', ambiguityPolicy: 'fail', required: true },
13513
+ inputSchema: nodeRemoveSchema,
13514
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-node-remove', handlerContract: {
13515
+ reads: ['RuleBuilderState.nodes', 'RuleBuilderState.rootNodes', 'RuleNodeRegistryService', 'RuleBuilderService.removeNode'],
13516
+ writes: ['RuleBuilderState.nodes', 'RuleBuilderState.rootNodes', 'RuleNodeRegistryService'],
13517
+ identityKeys: ['nodeId'],
13518
+ inputSchema: nodeRemoveSchema,
13519
+ failureModes: ['node-not-found', 'destructive-removal-not-confirmed', 'orphaned-edge-created', 'dsl-round-trip-failed'],
13520
+ description: 'Removes a node and governed descendants by id, requiring confirmation because conditions/effects can be lost.',
13521
+ } }],
13522
+ destructive: true,
13523
+ requiresConfirmation: true,
13524
+ validators: ['node-exists', 'destructive-removal-confirmed', 'edges-reference-existing-nodes', 'dsl-round-trip-stable'],
13525
+ affectedPaths: ['RuleBuilderState.nodes', 'RuleBuilderState.rootNodes', 'RuleNodeRegistryService'],
13526
+ submissionImpact: 'config-only',
13527
+ preconditions: ['rule-builder-state-loaded', 'explicit-confirmation-provided'],
13528
+ },
13529
+ {
13530
+ operationId: 'node.configure',
13531
+ title: 'Configure visual rule node',
13532
+ scope: 'rules',
13533
+ targetKind: 'node',
13534
+ target: { kind: 'node', resolver: 'rule-node-by-id', ambiguityPolicy: 'fail', required: true },
13535
+ inputSchema: nodeConfigureSchema,
13536
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-node-configure', handlerContract: {
13537
+ reads: ['RuleBuilderState.nodes', 'RuleBuilderService.updateNode', 'RuleNodeRegistryService'],
13538
+ writes: ['RuleBuilderState.nodes', 'RuleBuilderState.currentJSON'],
13539
+ identityKeys: ['nodeId'],
13540
+ inputSchema: nodeConfigureSchema,
13541
+ failureModes: ['node-not-found', 'config-shape-invalid', 'node-type-config-mismatch', 'dsl-round-trip-failed'],
13542
+ description: 'Applies a typed patch to a rule node while preserving node identity and JSON Logic serialization.',
13543
+ } }],
13544
+ validators: ['node-exists', 'node-config-compatible', 'graph-valid', 'dsl-round-trip-stable'],
13545
+ affectedPaths: ['RuleBuilderState.nodes', 'RuleBuilderState.currentJSON'],
13546
+ submissionImpact: 'config-only',
13547
+ preconditions: ['rule-builder-state-loaded'],
13548
+ destructive: false,
13549
+ requiresConfirmation: false,
13550
+ },
13551
+ {
13552
+ operationId: 'edge.connect',
13553
+ title: 'Connect visual graph edge',
13554
+ scope: 'interaction',
13555
+ targetKind: 'edge',
13556
+ target: { kind: 'edge', resolver: 'rule-node-edge-by-source-target', ambiguityPolicy: 'fail', required: true },
13557
+ inputSchema: edgeConnectSchema,
13558
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-edge-connect', handlerContract: {
13559
+ reads: ['RuleBuilderState.nodes', 'RuleNodeRegistryService.validateIntegrity'],
13560
+ writes: ['RuleBuilderState.nodes[].children', 'RuleBuilderState.nodes[].parentId'],
13561
+ identityKeys: ['sourceNodeId', 'targetNodeId', 'edgeKind'],
13562
+ inputSchema: edgeConnectSchema,
13563
+ failureModes: ['source-node-not-found', 'target-node-not-found', 'duplicate-edge', 'graph-cycle-created'],
13564
+ description: 'Connects two existing nodes and rejects edges that break registry integrity or acyclic graph requirements.',
13565
+ } }],
13566
+ validators: ['node-exists', 'edges-reference-existing-nodes', 'graph-acyclic-where-required', 'dsl-round-trip-stable'],
13567
+ affectedPaths: ['RuleBuilderState.nodes[].children', 'RuleBuilderState.nodes[].parentId'],
13568
+ submissionImpact: 'config-only',
13569
+ preconditions: ['rule-builder-state-loaded'],
13570
+ destructive: false,
13571
+ requiresConfirmation: false,
13572
+ },
13573
+ {
13574
+ operationId: 'edge.remove',
13575
+ title: 'Remove visual graph edge',
13576
+ scope: 'interaction',
13577
+ targetKind: 'edge',
13578
+ target: { kind: 'edge', resolver: 'rule-node-edge-by-source-target', ambiguityPolicy: 'fail', required: true },
13579
+ inputSchema: edgeRemoveSchema,
13580
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-edge-remove', handlerContract: {
13581
+ reads: ['RuleBuilderState.nodes', 'RuleNodeRegistryService.validateIntegrity'],
13582
+ writes: ['RuleBuilderState.nodes[].children', 'RuleBuilderState.nodes[].parentId'],
13583
+ identityKeys: ['sourceNodeId', 'targetNodeId', 'edgeKind'],
13584
+ inputSchema: edgeRemoveSchema,
13585
+ failureModes: ['edge-not-found', 'destructive-removal-not-confirmed', 'orphaned-node-created', 'dsl-round-trip-failed'],
13586
+ description: 'Removes a graph edge by source and target ids with confirmation when the target can become orphaned.',
13587
+ } }],
13588
+ destructive: true,
13589
+ requiresConfirmation: true,
13590
+ validators: ['edge-exists', 'destructive-removal-confirmed', 'graph-valid', 'dsl-round-trip-stable'],
13591
+ affectedPaths: ['RuleBuilderState.nodes[].children', 'RuleBuilderState.nodes[].parentId'],
13592
+ submissionImpact: 'config-only',
13593
+ preconditions: ['rule-builder-state-loaded', 'explicit-confirmation-provided'],
13594
+ },
13595
+ {
13596
+ operationId: 'variable.add',
13597
+ title: 'Add context variable',
13598
+ scope: 'dataBinding',
13599
+ targetKind: 'variable',
13600
+ target: { kind: 'variable', resolver: 'context-variable-by-name-scope', ambiguityPolicy: 'fail', required: true },
13601
+ inputSchema: variableAddSchema,
13602
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-variable-add', handlerContract: {
13603
+ reads: ['RuleBuilderConfig.contextVariables', 'ContextManagementService'],
13604
+ writes: ['RuleBuilderConfig.contextVariables', 'ContextManagementService'],
13605
+ identityKeys: ['scope', 'name'],
13606
+ inputSchema: variableAddSchema,
13607
+ failureModes: ['duplicate-variable', 'scope-not-found', 'variable-type-invalid', 'context-token-conflict'],
13608
+ description: 'Adds a governed context variable that can be referenced by contextual and field condition nodes.',
13609
+ } }],
13610
+ validators: ['variable-id-unique', 'variable-scope-exists', 'context-variable-reference-valid', 'dsl-round-trip-stable'],
13611
+ affectedPaths: ['RuleBuilderConfig.contextVariables', 'ContextManagementService'],
13612
+ submissionImpact: 'config-only',
13613
+ preconditions: ['rule-builder-config-loaded'],
13614
+ destructive: false,
13615
+ requiresConfirmation: false,
13616
+ },
13617
+ {
13618
+ operationId: 'condition.set',
13619
+ title: 'Set JSON Logic condition',
13620
+ scope: 'rules',
13621
+ targetKind: 'condition',
13622
+ target: { kind: 'condition', resolver: 'json-logic-condition-by-node', ambiguityPolicy: 'fail', required: true },
13623
+ inputSchema: conditionSetSchema,
13624
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-condition-set', handlerContract: {
13625
+ reads: ['RuleBuilderState.nodes', 'RuleBuilderService.loadFromConditionExpression', 'RuleBuilderService.buildConditionExpressionFromGraph'],
13626
+ writes: ['RuleBuilderState.nodes[].config.condition', 'RuleBuilderState.currentJSON'],
13627
+ identityKeys: ['nodeId'],
13628
+ inputSchema: conditionSetSchema,
13629
+ failureModes: ['node-not-found', 'json-logic-invalid', 'unsupported-operator', 'visual-parse-failed', 'dsl-round-trip-failed'],
13630
+ description: 'Sets a canonical JSON Logic condition and proves it can parse back into the visual graph.',
13631
+ } }],
13632
+ validators: ['json-logic-valid', 'condition-operators-supported', 'condition-fields-known', 'dsl-round-trip-stable'],
13633
+ affectedPaths: ['RuleBuilderState.nodes[].config.condition', 'RuleBuilderState.currentJSON'],
13634
+ submissionImpact: 'config-only',
13635
+ preconditions: ['rule-builder-state-loaded'],
13636
+ destructive: false,
13637
+ requiresConfirmation: false,
13638
+ },
13639
+ {
13640
+ operationId: 'effect.set',
13641
+ title: 'Set visual property effect',
13642
+ scope: 'rules',
13643
+ targetKind: 'effect',
13644
+ target: { kind: 'effect', resolver: 'property-effect-by-node', ambiguityPolicy: 'fail', required: true },
13645
+ inputSchema: effectSetSchema,
13646
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-effect-set', handlerContract: {
13647
+ reads: ['RuleBuilderState.nodes', 'RuleBuilderConfig.targetPropertySchemas', 'RULE_PROPERTY_SCHEMA', 'RuleBuilderService.export'],
13648
+ writes: ['RuleBuilderState.nodes[].config.targetType', 'RuleBuilderState.nodes[].config.targets', 'RuleBuilderState.nodes[].config.properties', 'RuleBuilderState.nodes[].config.propertiesWhenFalse', 'RuleBuilderState.currentJSON'],
13649
+ identityKeys: ['nodeId', 'targetType', 'targets'],
13650
+ inputSchema: effectSetSchema,
13651
+ failureModes: ['node-not-found', 'target-not-found', 'property-not-allowed-for-target', 'effect-value-invalid', 'dsl-round-trip-failed'],
13652
+ description: 'Sets a property effect using governed target property schemas so export to FormLayoutRule remains deterministic.',
13653
+ } }],
13654
+ validators: ['effect-targets-exist', 'effect-properties-governed', 'effect-values-valid', 'dsl-round-trip-stable'],
13655
+ affectedPaths: ['RuleBuilderState.nodes[].config.targetType', 'RuleBuilderState.nodes[].config.targets', 'RuleBuilderState.nodes[].config.properties', 'RuleBuilderState.nodes[].config.propertiesWhenFalse', 'RuleBuilderState.currentJSON'],
13656
+ submissionImpact: 'affects-schema-backed-data',
13657
+ preconditions: ['rule-builder-state-loaded', 'target-schema-loaded'],
13658
+ destructive: false,
13659
+ requiresConfirmation: false,
13660
+ },
13661
+ {
13662
+ operationId: 'dsl.roundTrip.validate',
13663
+ title: 'Validate visual and DSL round trip',
13664
+ scope: 'runtimeCoverage',
13665
+ targetKind: 'dslDocument',
13666
+ target: { kind: 'dslDocument', resolver: 'rule-builder-json-logic-document', ambiguityPolicy: 'fail', required: false },
13667
+ inputSchema: dslRoundTripValidateSchema,
13668
+ effects: [{ kind: 'compile-domain-patch', handler: 'visual-builder-dsl-round-trip-validate', handlerContract: {
13669
+ reads: ['RuleBuilderState', 'RuleBuilderService.export', 'RuleBuilderService.import', 'RuleBuilderService.buildConditionExpressionFromGraph', 'RuleNodeRegistryService.validateIntegrity'],
13670
+ writes: ['RuleBuilderState.validationErrors', 'RuleBuilderState.currentJSON'],
13671
+ identityKeys: ['format', 'compareMode'],
13672
+ inputSchema: dslRoundTripValidateSchema,
13673
+ failureModes: ['graph-invalid', 'export-failed', 'import-failed', 'semantic-drift', 'unstable-node-identity'],
13674
+ description: 'Exports the visual model to JSON, imports it back and rejects semantic drift or unstable identity.',
13675
+ } }],
13676
+ validators: ['graph-valid', 'dsl-round-trip-stable', 'json-logic-valid', 'registry-integrity-valid'],
13677
+ affectedPaths: ['RuleBuilderState.currentJSON', 'RuleBuilderState.validationErrors'],
13678
+ submissionImpact: 'none',
13679
+ preconditions: ['rule-builder-state-loaded'],
13680
+ destructive: false,
13681
+ requiresConfirmation: false,
13682
+ },
13683
+ ],
13684
+ validators: [
13685
+ { validatorId: 'node-id-unique', level: 'error', code: 'VISUAL_BUILDER_NODE_ID_UNIQUE', description: 'Rule node ids must be unique and stable.' },
13686
+ { validatorId: 'node-exists', level: 'error', code: 'VISUAL_BUILDER_NODE_EXISTS', description: 'Target node must exist before it is configured or removed.' },
13687
+ { validatorId: 'node-type-supported', level: 'error', code: 'VISUAL_BUILDER_NODE_TYPE_SUPPORTED', description: 'Node type must be supported by the rule node registry and visual editor.' },
13688
+ { validatorId: 'node-config-compatible', level: 'error', code: 'VISUAL_BUILDER_NODE_CONFIG_COMPATIBLE', description: 'Node config must match the declared node type.' },
13689
+ { validatorId: 'parent-node-exists', level: 'error', code: 'VISUAL_BUILDER_PARENT_NODE_EXISTS', description: 'Parent node must exist when adding a child node.' },
13690
+ { validatorId: 'edge-exists', level: 'error', code: 'VISUAL_BUILDER_EDGE_EXISTS', description: 'Target edge must exist before removal.' },
13691
+ { validatorId: 'edges-reference-existing-nodes', level: 'error', code: 'VISUAL_BUILDER_EDGES_REFERENCE_NODES', description: 'Every edge must reference existing source and target nodes.' },
13692
+ { validatorId: 'graph-valid', level: 'error', code: 'VISUAL_BUILDER_GRAPH_VALID', description: 'Graph structure must pass registry integrity validation.' },
13693
+ { validatorId: 'graph-acyclic-where-required', level: 'error', code: 'VISUAL_BUILDER_GRAPH_ACYCLIC', description: 'Hierarchical rule graph edges must not introduce cycles.' },
13694
+ { validatorId: 'destructive-removal-confirmed', level: 'error', code: 'VISUAL_BUILDER_DESTRUCTIVE_REMOVAL_CONFIRMED', description: 'Destructive node or edge removal requires explicit confirmation.' },
13695
+ { validatorId: 'variable-id-unique', level: 'error', code: 'VISUAL_BUILDER_VARIABLE_ID_UNIQUE', description: 'Context variable name and scope must be unique.' },
13696
+ { validatorId: 'variable-scope-exists', level: 'error', code: 'VISUAL_BUILDER_VARIABLE_SCOPE_EXISTS', description: 'Context variable scope must exist in ContextManagementService before variables are added.' },
13697
+ { validatorId: 'context-variable-reference-valid', level: 'error', code: 'VISUAL_BUILDER_CONTEXT_VARIABLE_VALID', description: 'Context variable references must resolve to declared variables.' },
13698
+ { validatorId: 'json-logic-valid', level: 'error', code: 'VISUAL_BUILDER_JSON_LOGIC_VALID', description: 'Conditions must be valid JSON Logic objects, not JavaScript or legacy textual DSL.' },
13699
+ { validatorId: 'condition-operators-supported', level: 'error', code: 'VISUAL_BUILDER_CONDITION_OPERATORS_SUPPORTED', description: 'Condition operators must be supported by visual parsing and export.' },
13700
+ { validatorId: 'condition-fields-known', level: 'error', code: 'VISUAL_BUILDER_CONDITION_FIELDS_KNOWN', description: 'Condition field references must resolve to configured field schemas or context variables.' },
13701
+ { validatorId: 'effect-targets-exist', level: 'error', code: 'VISUAL_BUILDER_EFFECT_TARGETS_EXIST', description: 'Effect targets must exist in configured target schemas.' },
13702
+ { validatorId: 'effect-properties-governed', level: 'error', code: 'VISUAL_BUILDER_EFFECT_PROPERTIES_GOVERNED', description: 'Effect properties must be allowed for the target type.' },
13703
+ { validatorId: 'effect-values-valid', level: 'error', code: 'VISUAL_BUILDER_EFFECT_VALUES_VALID', description: 'Effect property values must satisfy target property schema types.' },
13704
+ { validatorId: 'registry-integrity-valid', level: 'error', code: 'VISUAL_BUILDER_REGISTRY_INTEGRITY_VALID', description: 'RuleNodeRegistryService integrity checks must pass.' },
13705
+ { validatorId: 'dsl-round-trip-stable', level: 'error', code: 'VISUAL_BUILDER_DSL_ROUND_TRIP_STABLE', description: 'Serialized JSON output must import back to the same semantic visual model.' },
13706
+ ],
13707
+ roundTripRequirements: [
13708
+ 'RuleBuilderState is the visual source of truth; JSON export must import back without semantic drift.',
13709
+ 'RuleNode.id and context variable scope/name are canonical identities; array indexes are not canonical identities.',
13710
+ 'Edges must reference existing nodes and must not create cycles in hierarchical rule graphs.',
13711
+ 'Conditions are canonical JSON Logic objects. JavaScript expressions and legacy textual DSL must not be introduced as persisted authoring payloads.',
13712
+ 'Effects must be constrained by target property schemas and RULE_PROPERTY_SCHEMA so exported FormLayoutRule payloads stay deterministic.',
13713
+ 'Component-specific configuration belongs to child component manifests; visual-builder owns graph, JSON Logic, variables and property-effect orchestration.',
13714
+ ],
13715
+ examples: [
13716
+ { id: 'add-field-condition', request: 'Add a condition that age is greater than 18.', operationId: 'node.add', params: { nodeId: 'age-gt-18', nodeType: 'fieldCondition', label: 'Age over 18', config: { type: 'fieldCondition', fieldName: 'age', operator: 'gt', value: 18 } }, isPositive: true },
13717
+ { id: 'add-property-rule', request: 'Add a rule that hides the spouse section.', operationId: 'node.add', params: { nodeId: 'hide-spouse-section', nodeType: 'propertyRule', config: { type: 'propertyRule', targetType: 'section', targets: ['spouse'], properties: { visible: false } } }, isPositive: true },
13718
+ { id: 'configure-node', request: 'Rename the eligibility rule and mark it expanded.', operationId: 'node.configure', params: { nodeId: 'eligibility', label: 'Eligibility rule', expanded: true }, isPositive: true },
13719
+ { id: 'connect-edge', request: 'Make the age condition a child of the AND group.', operationId: 'edge.connect', params: { sourceNodeId: 'eligibility-and', targetNodeId: 'age-gt-18', edgeKind: 'child' }, isPositive: true },
13720
+ { id: 'remove-edge', request: 'Disconnect the age condition from the AND group.', operationId: 'edge.remove', params: { sourceNodeId: 'eligibility-and', targetNodeId: 'age-gt-18', edgeKind: 'child' }, isPositive: true },
13721
+ { id: 'add-variable', request: 'Add a global variable for current tenant.', operationId: 'variable.add', params: { name: 'tenantId', scope: 'global', type: 'string', valueType: 'context', description: 'Current tenant id' }, isPositive: true },
13722
+ { id: 'set-condition', request: 'Set this condition to require country equal Brazil.', operationId: 'condition.set', params: { nodeId: 'country-br', condition: { '===': [{ var: 'country' }, 'BR'] }, source: 'jsonLogic' }, isPositive: true },
13723
+ { id: 'set-effect', request: 'Make the salary field readonly when the condition is true.', operationId: 'effect.set', params: { nodeId: 'salary-readonly', targetType: 'field', targets: ['salary'], properties: { readonly: true } }, isPositive: true },
13724
+ { id: 'validate-round-trip', request: 'Validate that this graph exports and imports without drift.', operationId: 'dsl.roundTrip.validate', params: { format: 'json', requireStableIds: true, compareMode: 'semantic' }, isPositive: true },
13725
+ { id: 'reject-duplicate-node', request: 'Add another node with id age-gt-18.', operationId: 'node.add', params: { nodeId: 'age-gt-18', nodeType: 'fieldCondition' }, isPositive: false },
13726
+ { id: 'reject-cycle', request: 'Connect a child back to its parent and create a cycle.', operationId: 'edge.connect', params: { sourceNodeId: 'age-gt-18', targetNodeId: 'eligibility-and', edgeKind: 'child' }, isPositive: false },
13727
+ { id: 'reject-javascript-condition', request: 'Use age > 18 as a JavaScript expression.', operationId: 'condition.set', params: { nodeId: 'age-gt-18', condition: 'age > 18' }, isPositive: false },
13728
+ { id: 'reject-unknown-effect-property', request: 'Set an unknown field property named sparkle.', operationId: 'effect.set', params: { nodeId: 'sparkle-field', targetType: 'field', targets: ['name'], properties: { sparkle: true } }, isPositive: false },
13729
+ { id: 'reject-drift', request: 'Accept the graph even though export/import changes node meaning.', operationId: 'dsl.roundTrip.validate', params: { format: 'json', compareMode: 'exact' }, isPositive: false },
13730
+ ],
13731
+ };
13732
+
13323
13733
  /**
13324
13734
  * Array Field Schema Support for Collection Validators
13325
13735
  * Phase 2 Implementation
@@ -20427,4 +20837,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
20427
20837
  * Generated bundle index. Do not edit.
20428
20838
  */
20429
20839
 
20430
- export { ArrayFieldAnalyzer, CollectionValidatorEditorComponent, ConditionalValidatorEditorComponent, ConditionalValidatorType, ConfigurationError, ContextError, ContextManagementService, ConversionError, ErrorCategory, ErrorHandler, ErrorSeverity, ExportDialogComponent, ExportIntegrationService, ExpressionError, FIELD_TYPE_OPERATORS, FieldConditionEditorComponent, FieldSchemaService, FieldType, InternalError, JsonViewerComponent, MetadataEditorComponent, OPERATOR_LABELS, PraxisVisualBuilder, RegistryError, RuleBuilderService, RuleCanvasComponent, RuleEditorComponent, RuleListComponent, RuleNodeComponent, RuleNodeRegistryService, RuleNodeType, RuleTemplateService, RuleValidationService, TemplateEditorDialogComponent, TemplateGalleryComponent, TemplatePreviewDialogComponent, ValidationError as VBValidationError, ValidationCategory, ValidationSeverity, VisualBuilderError, VisualRuleBuilderComponent, WebhookIntegrationService, createError, getArrayItemFieldPaths, globalErrorHandler, isArrayFieldSchema };
20840
+ export { ArrayFieldAnalyzer, CollectionValidatorEditorComponent, ConditionalValidatorEditorComponent, ConditionalValidatorType, ConfigurationError, ContextError, ContextManagementService, ConversionError, ErrorCategory, ErrorHandler, ErrorSeverity, ExportDialogComponent, ExportIntegrationService, ExpressionError, FIELD_TYPE_OPERATORS, FieldConditionEditorComponent, FieldSchemaService, FieldType, InternalError, JsonViewerComponent, MetadataEditorComponent, OPERATOR_LABELS, PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST, PraxisVisualBuilder, RegistryError, RuleBuilderService, RuleCanvasComponent, RuleEditorComponent, RuleListComponent, RuleNodeComponent, RuleNodeRegistryService, RuleNodeType, RuleTemplateService, RuleValidationService, TemplateEditorDialogComponent, TemplateGalleryComponent, TemplatePreviewDialogComponent, ValidationError as VBValidationError, ValidationCategory, ValidationSeverity, VisualBuilderError, VisualRuleBuilderComponent, WebhookIntegrationService, createError, getArrayItemFieldPaths, globalErrorHandler, isArrayFieldSchema };
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { EventEmitter, OnInit, OnDestroy, OnChanges, AfterViewInit, ElementRef, ChangeDetectorRef, SimpleChanges } from '@angular/core';
3
- import { JsonLogicExpression, FormLayoutRule, RulePropertySchema, PraxisI18nService } from '@praxisui/core';
3
+ import { JsonLogicExpression, ComponentAuthoringManifest, FormLayoutRule, RulePropertySchema, PraxisI18nService } from '@praxisui/core';
4
4
  import { Observable } from 'rxjs';
5
5
  import { MatDialog, MatDialogRef } from '@angular/material/dialog';
6
6
  import { MatSnackBar } from '@angular/material/snack-bar';
@@ -121,7 +121,7 @@ interface FieldConditionConfig {
121
121
  }
122
122
  interface PropertyRuleConfig {
123
123
  type: 'propertyRule';
124
- targetType: 'field' | 'section' | 'action' | 'row' | 'column';
124
+ targetType: 'field' | 'section' | 'action' | 'row' | 'column' | 'visualBlock';
125
125
  /** Target IDs without prefix (namespace is defined by targetType) */
126
126
  targets: string[];
127
127
  /** Properties applied when condition is true */
@@ -512,9 +512,10 @@ interface RuleBuilderConfig {
512
512
  actions?: Record<string, unknown>;
513
513
  rows?: Record<string, unknown>;
514
514
  columns?: Record<string, unknown>;
515
+ visualBlocks?: Record<string, unknown>;
515
516
  };
516
517
  /** Optional property schema per targetType for typed property editing */
517
- targetPropertySchemas?: Record<'field' | 'section' | 'action' | 'row' | 'column', Array<{
518
+ targetPropertySchemas?: Record<'field' | 'section' | 'action' | 'row' | 'column' | 'visualBlock', Array<{
518
519
  name: string;
519
520
  type: 'string' | 'boolean' | 'object' | 'enum' | 'number';
520
521
  label?: string;
@@ -630,6 +631,8 @@ declare class PraxisVisualBuilder {
630
631
  static ɵcmp: i0.ɵɵComponentDeclaration<PraxisVisualBuilder, "praxis-visual-builder", never, { "config": { "alias": "config"; "required": false; }; "initialRules": { "alias": "initialRules"; "required": false; }; }, { "rulesChanged": "rulesChanged"; "exportRequested": "exportRequested"; "importRequested": "importRequested"; }, never, never, true, never>;
631
632
  }
632
633
 
634
+ declare const PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST: ComponentAuthoringManifest;
635
+
633
636
  /**
634
637
  * Field schema model for dynamic field configuration in the Visual Builder
635
638
  */
@@ -639,7 +642,7 @@ interface FieldSchema {
639
642
  /** Human-readable field label */
640
643
  label: string;
641
644
  /** Logical origin to help context-sensitive filtering (form field, section, row, column, table column, etc.) */
642
- origin?: 'field' | 'section' | 'action' | 'row' | 'column' | 'tableField' | 'tableColumn';
645
+ origin?: 'field' | 'section' | 'action' | 'row' | 'column' | 'visualBlock' | 'tableField' | 'tableColumn';
643
646
  /** Field data type */
644
647
  type: FieldType | string;
645
648
  /** Optional description or help text */
@@ -2179,7 +2182,7 @@ declare const createError: {
2179
2182
  internal: (message: string, cause?: Error) => InternalError;
2180
2183
  };
2181
2184
 
2182
- type TargetType = 'field' | 'section' | 'action' | 'row' | 'column';
2185
+ type TargetType = 'field' | 'section' | 'action' | 'row' | 'column' | 'visualBlock';
2183
2186
  type RuleNodeConfigExtended = RuleNodeConfig & {
2184
2187
  targetType?: TargetType;
2185
2188
  properties?: Record<string, any>;
@@ -2905,5 +2908,5 @@ declare class RuleListComponent {
2905
2908
  static ɵcmp: i0.ɵɵComponentDeclaration<RuleListComponent, "praxis-rule-list", never, { "rules": { "alias": "rules"; "required": false; }; "selectedRuleId": { "alias": "selectedRuleId"; "required": false; }; "nodeMap": { "alias": "nodeMap"; "required": false; }; "validationErrors": { "alias": "validationErrors"; "required": false; }; }, { "ruleSelected": "ruleSelected"; "ruleDeleted": "ruleDeleted"; "ruleDuplicated": "ruleDuplicated"; "ruleAdded": "ruleAdded"; "aiRequested": "aiRequested"; }, never, never, true, never>;
2906
2909
  }
2907
2910
 
2908
- export { ArrayFieldAnalyzer, CollectionValidatorEditorComponent, ConditionalValidatorEditorComponent, ConditionalValidatorType, ConfigurationError, ContextError, ContextManagementService, ConversionError, ErrorCategory, ErrorHandler, ErrorSeverity, ExportDialogComponent, ExportIntegrationService, ExpressionError, FIELD_TYPE_OPERATORS, FieldConditionEditorComponent, FieldSchemaService, FieldType, InternalError, JsonViewerComponent, MetadataEditorComponent, OPERATOR_LABELS, PraxisVisualBuilder, RegistryError, RuleBuilderService, RuleCanvasComponent, RuleEditorComponent, RuleListComponent, RuleNodeComponent, RuleNodeRegistryService, RuleNodeType, RuleTemplateService, RuleValidationService, TemplateEditorDialogComponent, TemplateGalleryComponent, TemplatePreviewDialogComponent, ValidationError as VBValidationError, ValidationCategory, ValidationSeverity, VisualBuilderError, VisualRuleBuilderComponent, WebhookIntegrationService, createError, getArrayItemFieldPaths, globalErrorHandler, isArrayFieldSchema };
2911
+ export { ArrayFieldAnalyzer, CollectionValidatorEditorComponent, ConditionalValidatorEditorComponent, ConditionalValidatorType, ConfigurationError, ContextError, ContextManagementService, ConversionError, ErrorCategory, ErrorHandler, ErrorSeverity, ExportDialogComponent, ExportIntegrationService, ExpressionError, FIELD_TYPE_OPERATORS, FieldConditionEditorComponent, FieldSchemaService, FieldType, InternalError, JsonViewerComponent, MetadataEditorComponent, OPERATOR_LABELS, PRAXIS_VISUAL_BUILDER_AUTHORING_MANIFEST, PraxisVisualBuilder, RegistryError, RuleBuilderService, RuleCanvasComponent, RuleEditorComponent, RuleListComponent, RuleNodeComponent, RuleNodeRegistryService, RuleNodeType, RuleTemplateService, RuleValidationService, TemplateEditorDialogComponent, TemplateGalleryComponent, TemplatePreviewDialogComponent, ValidationError as VBValidationError, ValidationCategory, ValidationSeverity, VisualBuilderError, VisualRuleBuilderComponent, WebhookIntegrationService, createError, getArrayItemFieldPaths, globalErrorHandler, isArrayFieldSchema };
2909
2912
  export type { ArrayCollectionValidationRule, ArrayFieldSchema, ArrayValidationContext, ArrayValidationError, BooleanGroupConfig, CardinalityConfig, CircularReference, CleanupResult, CollectionValidationConfig, CollectionValidatorConfig, ConditionalValidatorConfig, ConditionalValidatorPreview, ContextEntry, ContextScope, ContextValue, ContextVariable, ContextualConfig, ContextualTemplateConfig, CustomConfig, CustomFunction, DocumentationLink, EnhancedFieldSchema, ErrorInfo, ErrorStatistics, ExportDialogData, ExportFormat, ExportOptions, ExportResult, ExpressionConfig, ExternalSystemConfig, FieldConditionConfig, FieldFormat, FieldOption, FieldSchema, FieldSchemaContext, FieldToFieldConfig, FieldUIConfig, FunctionCallConfig, FunctionParameter, ImportOptions, IntegrationEndpoint, IntegrationResult, MemoryStats, OptionalFieldConfig, PropertyRuleConfig, RegistryIntegrityResult, RegistryValidationResult, RuleBuilderConfig, RuleBuilderSnapshot, RuleBuilderState, RuleContextProvider, RuleFunctionRegistry, RuleNode, RuleNodeConfig, RuleNodeTree, RuleNodeTypeString, RuleTemplate, RuleValidationResult, SpecificationMetadata, TemplateApplicationResult, TemplateCategory, TemplateDisplayMode, TemplateEditorDialogData, TemplateEditorResult, TemplateMetadata, TemplatePreviewDialogData, TemplateSearchCriteria, TemplateSortOption, TemplateStats, TemplateValidationResult, ValidComparisonOperator, ValidationConfig, ValidationContext, ValidationError$1 as ValidationError, ValidationIssue, ValidationResult, ValidationRule, ValueType, WebhookConfig, WebhookDelivery, WebhookEvent, WebhookStats };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@praxisui/visual-builder",
3
- "version": "8.0.0-beta.11",
3
+ "version": "8.0.0-beta.13",
4
4
  "description": "Visual rule and expression builder for Praxis UI with JSON Logic authoring, validation and context variables.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^20.0.0",
@@ -8,7 +8,7 @@
8
8
  "@angular/cdk": "^20.0.0",
9
9
  "@angular/material": "^20.0.0",
10
10
  "@angular/forms": "^20.0.0",
11
- "@praxisui/settings-panel": "^8.0.0-beta.11"
11
+ "@praxisui/settings-panel": "^8.0.0-beta.13"
12
12
  },
13
13
  "dependencies": {
14
14
  "tslib": "^2.3.0",