@praxisui/manual-form 8.0.0-beta.2 → 8.0.0-beta.20
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 +26 -0
- package/fesm2022/praxisui-manual-form.mjs +344 -2
- package/index.d.ts +4 -2
- package/package.json +11 -5
package/README.md
CHANGED
|
@@ -368,6 +368,32 @@ Modo dinâmico (sem host tipado):
|
|
|
368
368
|
- Métodos públicos:
|
|
369
369
|
- `tryOpenFieldEditor(fieldName: string)`: tenta abrir o editor do campo, respeitando `enableCustomization` (no‑op quando `false`).
|
|
370
370
|
|
|
371
|
+
## Contrato agentic de authoring
|
|
372
|
+
|
|
373
|
+
`PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST` e o contrato AI executavel do pacote.
|
|
374
|
+
|
|
375
|
+
O manifesto governa a orquestracao do formulario manual:
|
|
376
|
+
|
|
377
|
+
- `manualField.add`
|
|
378
|
+
- `manualField.remove`
|
|
379
|
+
- `manualField.label.set`
|
|
380
|
+
- `layout.configure`
|
|
381
|
+
- `toolbar.configure`
|
|
382
|
+
- `autosave.enabled.set`
|
|
383
|
+
- `submitBehavior.set`
|
|
384
|
+
- `metadataBridge.configure`
|
|
385
|
+
|
|
386
|
+
Regras de fronteira:
|
|
387
|
+
|
|
388
|
+
- `ManualFormInstance` e a superficie runtime do pacote: config, mapa de metadata, `FormGroup` e persistencia devem permanecer coerentes
|
|
389
|
+
- as operacoes escrevem nos paths reais do runtime (`currentConfig`, `currentFieldMetadata`, `form`, inputs como `enableCustomization`, `enableAutoSave`, `autoSaveDebounceMs`, `persistenceOptions`, e outputs como `submitted`, `saved`, `resetEvent`)
|
|
390
|
+
- IDs de campo manual sao nomes estaveis de campo, nunca indice de array
|
|
391
|
+
- remocao de campo exige confirmacao explicita
|
|
392
|
+
- autosave deve declarar debounce seguro e chave de persistencia deterministica
|
|
393
|
+
- toolbar de campo e metadata bridge sao entry points de runtime controlados por `enableCustomization`; nao existe objeto persistido `toolbar.*` ou `metadataBridge.*`
|
|
394
|
+
- edicoes profundas de `FieldMetadata` sao delegadas ao `@praxisui/metadata-editor`
|
|
395
|
+
- authoring avancado de `FormConfig` pertence ao `@praxisui/dynamic-form`
|
|
396
|
+
|
|
371
397
|
## Header e Actions
|
|
372
398
|
|
|
373
399
|
- `<praxis-manual-form-header>`: recebe `instance`, `title`, `description`, `saveLabel`, `resetLabel` e emite `save/reset`.
|
|
@@ -576,7 +576,7 @@ const ENUMS = {
|
|
|
576
576
|
headerAlign: ['start', 'center'],
|
|
577
577
|
schemaType: ['response', 'request'],
|
|
578
578
|
customizationSource: ['user', 'server', 'system'],
|
|
579
|
-
formRuleTargetType: ['field', 'section', 'action', 'row', 'column'],
|
|
579
|
+
formRuleTargetType: ['field', 'section', 'action', 'row', 'column', 'visualBlock'],
|
|
580
580
|
formRuleContext: ['visibility', 'readOnly', 'style', 'validation', 'notification'],
|
|
581
581
|
mode: ['create', 'edit', 'view'],
|
|
582
582
|
schemaSource: ['resource', 'filter'],
|
|
@@ -5359,6 +5359,348 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
5359
5359
|
args: ['dblclick']
|
|
5360
5360
|
}] } });
|
|
5361
5361
|
|
|
5362
|
+
const manualFieldAddSchema = {
|
|
5363
|
+
type: 'object',
|
|
5364
|
+
required: ['fieldName', 'controlType'],
|
|
5365
|
+
properties: {
|
|
5366
|
+
fieldName: { type: 'string' },
|
|
5367
|
+
controlType: { type: 'string' },
|
|
5368
|
+
label: { type: 'string' },
|
|
5369
|
+
required: { type: 'boolean' },
|
|
5370
|
+
sectionId: { type: 'string' },
|
|
5371
|
+
source: { enum: ['manual-template', 'detected-component', 'metadata-bridge'] },
|
|
5372
|
+
delegateFieldMetadataTo: { enum: ['praxis-metadata-editor'] },
|
|
5373
|
+
},
|
|
5374
|
+
};
|
|
5375
|
+
const manualFieldRemoveSchema = {
|
|
5376
|
+
type: 'object',
|
|
5377
|
+
required: ['fieldName'],
|
|
5378
|
+
properties: {
|
|
5379
|
+
fieldName: { type: 'string' },
|
|
5380
|
+
removeFromLayout: { type: 'boolean' },
|
|
5381
|
+
clearPersistedValue: { type: 'boolean' },
|
|
5382
|
+
},
|
|
5383
|
+
};
|
|
5384
|
+
const manualFieldLabelSetSchema = {
|
|
5385
|
+
type: 'object',
|
|
5386
|
+
required: ['fieldName', 'label'],
|
|
5387
|
+
properties: {
|
|
5388
|
+
fieldName: { type: 'string' },
|
|
5389
|
+
label: { type: 'string' },
|
|
5390
|
+
updatePlaceholderWhenEmpty: { type: 'boolean' },
|
|
5391
|
+
},
|
|
5392
|
+
};
|
|
5393
|
+
const layoutConfigureSchema = {
|
|
5394
|
+
type: 'object',
|
|
5395
|
+
minProperties: 1,
|
|
5396
|
+
properties: {
|
|
5397
|
+
usePathNames: { type: 'boolean' },
|
|
5398
|
+
sections: { type: 'array' },
|
|
5399
|
+
rows: { type: 'array' },
|
|
5400
|
+
columns: { type: 'array' },
|
|
5401
|
+
fieldOrder: {
|
|
5402
|
+
type: 'array',
|
|
5403
|
+
items: { type: 'string' },
|
|
5404
|
+
},
|
|
5405
|
+
delegateAdvancedFormConfigTo: { enum: ['praxis-dynamic-form'] },
|
|
5406
|
+
},
|
|
5407
|
+
};
|
|
5408
|
+
const toolbarConfigureSchema = {
|
|
5409
|
+
type: 'object',
|
|
5410
|
+
minProperties: 1,
|
|
5411
|
+
properties: {
|
|
5412
|
+
enableCustomization: { type: 'boolean' },
|
|
5413
|
+
editableFlags: {
|
|
5414
|
+
type: 'array',
|
|
5415
|
+
items: { enum: ['required', 'readOnly', 'hidden', 'disabled', 'openMetadataEditor'] },
|
|
5416
|
+
},
|
|
5417
|
+
},
|
|
5418
|
+
};
|
|
5419
|
+
const autosaveEnabledSetSchema = {
|
|
5420
|
+
type: 'object',
|
|
5421
|
+
required: ['enabled'],
|
|
5422
|
+
properties: {
|
|
5423
|
+
enabled: { type: 'boolean' },
|
|
5424
|
+
debounceMs: { type: 'number' },
|
|
5425
|
+
storageKey: { type: 'string' },
|
|
5426
|
+
namespace: { type: 'string' },
|
|
5427
|
+
tenantId: { type: 'string' },
|
|
5428
|
+
profileId: { type: 'string' },
|
|
5429
|
+
},
|
|
5430
|
+
};
|
|
5431
|
+
const submitBehaviorSetSchema = {
|
|
5432
|
+
type: 'object',
|
|
5433
|
+
minProperties: 1,
|
|
5434
|
+
properties: {
|
|
5435
|
+
action: { enum: ['submit', 'saveDraft', 'reset', 'cancel', 'custom'] },
|
|
5436
|
+
clearAfterSave: { type: 'boolean' },
|
|
5437
|
+
focusFirstError: { type: 'boolean' },
|
|
5438
|
+
scrollToErrors: { type: 'boolean' },
|
|
5439
|
+
confirmOnUnsavedChanges: { type: 'boolean' },
|
|
5440
|
+
delegateFormSubmitTo: { enum: ['praxis-dynamic-form'] },
|
|
5441
|
+
},
|
|
5442
|
+
};
|
|
5443
|
+
const metadataBridgeConfigureSchema = {
|
|
5444
|
+
type: 'object',
|
|
5445
|
+
minProperties: 1,
|
|
5446
|
+
properties: {
|
|
5447
|
+
enabled: { type: 'boolean' },
|
|
5448
|
+
fieldName: { type: 'string' },
|
|
5449
|
+
openMode: { enum: ['field-toolbar', 'double-click', 'programmatic'] },
|
|
5450
|
+
persistDraftAfterPatch: { type: 'boolean' },
|
|
5451
|
+
delegateFieldMetadataTo: { enum: ['praxis-metadata-editor'] },
|
|
5452
|
+
delegateControlDiscoveryTo: { enum: ['praxis-dynamic-fields'] },
|
|
5453
|
+
},
|
|
5454
|
+
};
|
|
5455
|
+
const PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST = {
|
|
5456
|
+
schemaVersion: '1.0.0',
|
|
5457
|
+
componentId: 'praxis-manual-form',
|
|
5458
|
+
ownerPackage: '@praxisui/manual-form',
|
|
5459
|
+
configSchemaId: 'ManualFormInstance',
|
|
5460
|
+
manifestVersion: '1.0.0',
|
|
5461
|
+
runtimeInputs: [
|
|
5462
|
+
{ name: 'formId', type: 'string', description: 'Required manual form id used for runtime state and persistence key composition.' },
|
|
5463
|
+
{ name: 'formGroup', type: 'FormGroup | null', description: 'Host-owned typed FormGroup adopted by the manual form runtime when provided.' },
|
|
5464
|
+
{ name: 'formTitle', type: 'string | null', description: 'Manual form title override.' },
|
|
5465
|
+
{ name: 'formDescription', type: 'string | null', description: 'Manual form description override.' },
|
|
5466
|
+
{ name: 'actions', type: 'FormActionsLayout | null', description: 'Manual toolbar/actions layout.' },
|
|
5467
|
+
{ name: 'enableAutoSave', type: 'boolean', description: 'Enables draft persistence through ManualFormInstance.saveDraft.' },
|
|
5468
|
+
{ name: 'autoSaveDebounceMs', type: 'number', description: 'Autosave debounce in milliseconds.' },
|
|
5469
|
+
{ name: 'enableCustomization', type: 'boolean', description: 'Enables field toolbar and metadata editor bridge.' },
|
|
5470
|
+
{ name: 'persistenceOptions', type: 'ManualFormPersistenceOptions | null', description: 'Namespace, tenant, profile, locale and storage key controls.' },
|
|
5471
|
+
{ name: 'usePathNames', type: 'boolean', description: 'Uses FormControlName.path as FieldMetadata.name for nested manual forms.' },
|
|
5472
|
+
],
|
|
5473
|
+
editableTargets: [
|
|
5474
|
+
{ kind: 'manualField', resolver: 'manual-form-field-by-name', description: 'Detected or declared manual field tracked by ManualFormInstance field metadata.' },
|
|
5475
|
+
{ kind: 'layout', resolver: 'manual-form-layout', description: 'Manual layout ownership: host template layout plus optional FormConfig sections for authored structure.' },
|
|
5476
|
+
{ kind: 'toolbar', resolver: 'manual-form-customization-toolbar', description: 'Customization toolbar and quick metadata toggles.' },
|
|
5477
|
+
{ kind: 'autosave', resolver: 'manual-form-autosave-policy', description: 'Autosave enablement, debounce and persistence key controls.' },
|
|
5478
|
+
{ kind: 'metadataBridge', resolver: 'manual-field-metadata-bridge', description: 'Bridge from manual fields to @praxisui/metadata-editor patches.' },
|
|
5479
|
+
{ kind: 'submitBehavior', resolver: 'manual-form-submit-behavior', description: 'Submit, reset, validation focus and unsaved-change behavior.' },
|
|
5480
|
+
],
|
|
5481
|
+
operations: [
|
|
5482
|
+
{
|
|
5483
|
+
operationId: 'manualField.add',
|
|
5484
|
+
title: 'Add manual field metadata',
|
|
5485
|
+
scope: 'field',
|
|
5486
|
+
targetKind: 'manualField',
|
|
5487
|
+
target: { kind: 'manualField', resolver: 'manual-form-field-by-name', ambiguityPolicy: 'fail', required: true },
|
|
5488
|
+
inputSchema: manualFieldAddSchema,
|
|
5489
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-field-add', handlerContract: {
|
|
5490
|
+
reads: ['ManualFormInstance.currentConfig', 'ManualFormInstance.currentFieldMetadata', 'ManualFieldKeyService', 'dynamic-fields-control-discovery'],
|
|
5491
|
+
writes: ['currentConfig.fieldMetadata', 'currentFieldMetadata', 'form'],
|
|
5492
|
+
identityKeys: ['fieldName'],
|
|
5493
|
+
inputSchema: manualFieldAddSchema,
|
|
5494
|
+
failureModes: ['duplicate-manual-field-id', 'control-type-not-discovered', 'host-template-field-missing', 'field-metadata-delegation-required'],
|
|
5495
|
+
description: 'Adds metadata for a manual field while preserving host-owned template layout and delegating advanced FieldMetadata edits.',
|
|
5496
|
+
} }],
|
|
5497
|
+
validators: ['manual-field-id-unique', 'control-type-discovered', 'host-template-field-exists', 'metadata-bridge-does-not-redefine-schema', 'manual-form-round-trip'],
|
|
5498
|
+
affectedPaths: ['currentConfig.fieldMetadata', 'currentFieldMetadata', 'form'],
|
|
5499
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
5500
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
5501
|
+
destructive: false,
|
|
5502
|
+
requiresConfirmation: false,
|
|
5503
|
+
},
|
|
5504
|
+
{
|
|
5505
|
+
operationId: 'manualField.remove',
|
|
5506
|
+
title: 'Remove manual field metadata',
|
|
5507
|
+
scope: 'field',
|
|
5508
|
+
targetKind: 'manualField',
|
|
5509
|
+
target: { kind: 'manualField', resolver: 'manual-form-field-by-name', ambiguityPolicy: 'fail', required: true },
|
|
5510
|
+
inputSchema: manualFieldRemoveSchema,
|
|
5511
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-field-remove', handlerContract: {
|
|
5512
|
+
reads: ['ManualFormInstance.currentConfig', 'ManualFormInstance.currentFieldMetadata', 'ManualFormInstance.form', 'FormConfig.sections'],
|
|
5513
|
+
writes: ['currentConfig.fieldMetadata', 'currentConfig.sections', 'currentFieldMetadata', 'form'],
|
|
5514
|
+
identityKeys: ['fieldName'],
|
|
5515
|
+
inputSchema: manualFieldRemoveSchema,
|
|
5516
|
+
failureModes: ['manual-field-not-found', 'field-still-referenced-by-layout', 'persisted-value-removal-not-confirmed'],
|
|
5517
|
+
description: 'Removes a manual field by stable field name and requires explicit confirmation before metadata, layout or value loss.',
|
|
5518
|
+
} }],
|
|
5519
|
+
destructive: true,
|
|
5520
|
+
requiresConfirmation: true,
|
|
5521
|
+
validators: ['manual-field-exists', 'field-removal-confirmed', 'layout-field-references-valid', 'manual-form-round-trip'],
|
|
5522
|
+
affectedPaths: ['currentConfig.fieldMetadata', 'currentConfig.sections', 'currentFieldMetadata', 'form'],
|
|
5523
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
5524
|
+
preconditions: ['manual-form-instance-loaded', 'explicit-confirmation-provided'],
|
|
5525
|
+
},
|
|
5526
|
+
{
|
|
5527
|
+
operationId: 'manualField.label.set',
|
|
5528
|
+
title: 'Set manual field label',
|
|
5529
|
+
scope: 'field',
|
|
5530
|
+
targetKind: 'manualField',
|
|
5531
|
+
target: { kind: 'manualField', resolver: 'manual-form-field-by-name', ambiguityPolicy: 'fail', required: true },
|
|
5532
|
+
inputSchema: manualFieldLabelSetSchema,
|
|
5533
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-field-label-set', handlerContract: {
|
|
5534
|
+
reads: ['ManualFormInstance.currentFieldMetadata', 'ManualFieldMetadataBridgeService'],
|
|
5535
|
+
writes: ['currentConfig.fieldMetadata[].label', 'currentConfig.fieldMetadata[].placeholder', 'currentFieldMetadata'],
|
|
5536
|
+
identityKeys: ['fieldName'],
|
|
5537
|
+
inputSchema: manualFieldLabelSetSchema,
|
|
5538
|
+
failureModes: ['manual-field-not-found', 'label-empty', 'metadata-patch-rejected'],
|
|
5539
|
+
description: 'Sets a manual field label through the metadata bridge without redefining backend schema semantics.',
|
|
5540
|
+
} }],
|
|
5541
|
+
validators: ['manual-field-exists', 'field-label-valid', 'metadata-bridge-does-not-redefine-schema', 'manual-form-round-trip'],
|
|
5542
|
+
affectedPaths: ['currentConfig.fieldMetadata[].label', 'currentConfig.fieldMetadata[].placeholder', 'currentFieldMetadata'],
|
|
5543
|
+
submissionImpact: 'visual-only',
|
|
5544
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
5545
|
+
destructive: false,
|
|
5546
|
+
requiresConfirmation: false,
|
|
5547
|
+
},
|
|
5548
|
+
{
|
|
5549
|
+
operationId: 'layout.configure',
|
|
5550
|
+
title: 'Configure manual form layout',
|
|
5551
|
+
scope: 'layout',
|
|
5552
|
+
targetKind: 'layout',
|
|
5553
|
+
target: { kind: 'layout', resolver: 'manual-form-layout', ambiguityPolicy: 'fail', required: false },
|
|
5554
|
+
inputSchema: layoutConfigureSchema,
|
|
5555
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-layout-configure', handlerContract: {
|
|
5556
|
+
reads: ['ManualFormInstance.currentConfig', 'FormConfig.sections', 'host-template-layout', 'praxis-dynamic-form-authoring-manifest'],
|
|
5557
|
+
writes: ['currentConfig.sections', 'usePathNames'],
|
|
5558
|
+
identityKeys: ['sectionId', 'rowId', 'columnId', 'fieldName'],
|
|
5559
|
+
inputSchema: layoutConfigureSchema,
|
|
5560
|
+
failureModes: ['layout-field-reference-missing', 'advanced-form-config-delegation-required', 'host-template-layout-conflict'],
|
|
5561
|
+
description: 'Configures manual layout metadata and delegates advanced FormConfig layout semantics to the dynamic-form manifest.',
|
|
5562
|
+
} }],
|
|
5563
|
+
validators: ['layout-field-references-valid', 'manual-layout-does-not-replace-host-template', 'delegates-form-config', 'manual-form-round-trip'],
|
|
5564
|
+
affectedPaths: ['currentConfig.sections', 'usePathNames'],
|
|
5565
|
+
submissionImpact: 'config-only',
|
|
5566
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
5567
|
+
destructive: false,
|
|
5568
|
+
requiresConfirmation: false,
|
|
5569
|
+
},
|
|
5570
|
+
{
|
|
5571
|
+
operationId: 'toolbar.configure',
|
|
5572
|
+
title: 'Configure manual form customization toolbar',
|
|
5573
|
+
scope: 'toolbarUi',
|
|
5574
|
+
targetKind: 'toolbar',
|
|
5575
|
+
target: { kind: 'toolbar', resolver: 'manual-form-customization-toolbar', ambiguityPolicy: 'fail', required: false },
|
|
5576
|
+
inputSchema: toolbarConfigureSchema,
|
|
5577
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-toolbar-configure', handlerContract: {
|
|
5578
|
+
reads: ['ManualFormComponent.enableCustomization', 'ManualFieldToolbarComponent', 'ManualFieldEditorOnDblclickDirective'],
|
|
5579
|
+
writes: ['enableCustomization'],
|
|
5580
|
+
identityKeys: ['formId'],
|
|
5581
|
+
inputSchema: toolbarConfigureSchema,
|
|
5582
|
+
failureModes: ['toolbar-disabled-with-required-bridge', 'unsupported-toolbar-flag'],
|
|
5583
|
+
description: 'Configures the manual customization toolbar and keeps metadata edit entry points behind enableCustomization.',
|
|
5584
|
+
} }],
|
|
5585
|
+
validators: ['toolbar-flags-supported', 'metadata-bridge-gated-by-customization', 'manual-form-round-trip'],
|
|
5586
|
+
affectedPaths: ['enableCustomization'],
|
|
5587
|
+
submissionImpact: 'visual-only',
|
|
5588
|
+
preconditions: ['manual-form-component-loaded'],
|
|
5589
|
+
destructive: false,
|
|
5590
|
+
requiresConfirmation: false,
|
|
5591
|
+
},
|
|
5592
|
+
{
|
|
5593
|
+
operationId: 'autosave.enabled.set',
|
|
5594
|
+
title: 'Set manual form autosave policy',
|
|
5595
|
+
scope: 'interaction',
|
|
5596
|
+
targetKind: 'autosave',
|
|
5597
|
+
target: { kind: 'autosave', resolver: 'manual-form-autosave-policy', ambiguityPolicy: 'fail', required: false },
|
|
5598
|
+
inputSchema: autosaveEnabledSetSchema,
|
|
5599
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-autosave-enabled-set', handlerContract: {
|
|
5600
|
+
reads: ['enableAutoSave', 'autoSaveDebounceMs', 'ManualFormPersistenceOptions', 'ASYNC_CONFIG_STORAGE'],
|
|
5601
|
+
writes: ['enableAutoSave', 'autoSaveDebounceMs', 'persistenceOptions'],
|
|
5602
|
+
identityKeys: ['formId', 'storageKey', 'namespace', 'tenantId', 'profileId'],
|
|
5603
|
+
inputSchema: autosaveEnabledSetSchema,
|
|
5604
|
+
failureModes: ['autosave-storage-missing', 'unsafe-debounce', 'ambiguous-storage-key', 'ssr-storage-not-safe'],
|
|
5605
|
+
description: 'Sets autosave explicitly and requires safe debounce plus deterministic persistence key composition.',
|
|
5606
|
+
} }],
|
|
5607
|
+
validators: ['autosave-explicit', 'autosave-debounce-safe', 'autosave-storage-available', 'persistence-key-deterministic', 'manual-form-round-trip'],
|
|
5608
|
+
affectedPaths: ['enableAutoSave', 'autoSaveDebounceMs', 'persistenceOptions'],
|
|
5609
|
+
submissionImpact: 'config-only',
|
|
5610
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
5611
|
+
destructive: false,
|
|
5612
|
+
requiresConfirmation: false,
|
|
5613
|
+
},
|
|
5614
|
+
{
|
|
5615
|
+
operationId: 'submitBehavior.set',
|
|
5616
|
+
title: 'Set manual form submit behavior',
|
|
5617
|
+
scope: 'interaction',
|
|
5618
|
+
targetKind: 'submitBehavior',
|
|
5619
|
+
target: { kind: 'submitBehavior', resolver: 'manual-form-submit-behavior', ambiguityPolicy: 'fail', required: false },
|
|
5620
|
+
inputSchema: submitBehaviorSetSchema,
|
|
5621
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-submit-behavior-set', handlerContract: {
|
|
5622
|
+
reads: ['ManualFormComponent.submitted', 'ManualFormInstance.form', 'FormConfig.behavior', 'praxis-dynamic-form-authoring-manifest'],
|
|
5623
|
+
writes: ['currentConfig.behavior', 'submitted', 'saved', 'resetEvent'],
|
|
5624
|
+
identityKeys: ['formId', 'action'],
|
|
5625
|
+
inputSchema: submitBehaviorSetSchema,
|
|
5626
|
+
failureModes: ['submit-action-unsupported', 'advanced-form-submit-delegation-required', 'validation-focus-target-missing'],
|
|
5627
|
+
description: 'Configures manual submit/reset behavior and delegates dynamic-form submit payload semantics to the dynamic-form manifest.',
|
|
5628
|
+
} }],
|
|
5629
|
+
validators: ['submit-behavior-supported', 'delegates-form-config', 'manual-form-round-trip'],
|
|
5630
|
+
affectedPaths: ['currentConfig.behavior', 'submitted', 'saved', 'resetEvent'],
|
|
5631
|
+
submissionImpact: 'affects-submission',
|
|
5632
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
5633
|
+
destructive: false,
|
|
5634
|
+
requiresConfirmation: false,
|
|
5635
|
+
},
|
|
5636
|
+
{
|
|
5637
|
+
operationId: 'metadataBridge.configure',
|
|
5638
|
+
title: 'Configure manual metadata bridge',
|
|
5639
|
+
scope: 'fieldMetadataPath',
|
|
5640
|
+
targetKind: 'metadataBridge',
|
|
5641
|
+
target: { kind: 'metadataBridge', resolver: 'manual-field-metadata-bridge', ambiguityPolicy: 'fail', required: false },
|
|
5642
|
+
inputSchema: metadataBridgeConfigureSchema,
|
|
5643
|
+
effects: [{ kind: 'compile-domain-patch', handler: 'manual-metadata-bridge-configure', handlerContract: {
|
|
5644
|
+
reads: ['ManualFieldMetadataBridgeService', 'SettingsPanelService', 'PRAXIS_METADATA_EDITOR_AUTHORING_MANIFEST', 'dynamic-fields-discovery'],
|
|
5645
|
+
writes: ['enableCustomization', 'currentFieldMetadata', 'currentConfig.fieldMetadata'],
|
|
5646
|
+
identityKeys: ['formId', 'fieldName', 'openMode'],
|
|
5647
|
+
inputSchema: metadataBridgeConfigureSchema,
|
|
5648
|
+
failureModes: ['metadata-editor-unavailable', 'field-metadata-delegation-required', 'control-discovery-delegation-required', 'draft-persistence-failed'],
|
|
5649
|
+
description: 'Configures the bridge that opens metadata-editor for manual fields and persists accepted patches through ManualFormInstance.',
|
|
5650
|
+
} }],
|
|
5651
|
+
validators: ['metadata-bridge-does-not-redefine-schema', 'delegates-field-metadata', 'control-type-discovered', 'metadata-bridge-gated-by-customization', 'manual-form-round-trip'],
|
|
5652
|
+
affectedPaths: ['enableCustomization', 'currentFieldMetadata', 'currentConfig.fieldMetadata'],
|
|
5653
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
5654
|
+
preconditions: ['manual-form-instance-loaded'],
|
|
5655
|
+
destructive: false,
|
|
5656
|
+
requiresConfirmation: false,
|
|
5657
|
+
},
|
|
5658
|
+
],
|
|
5659
|
+
validators: [
|
|
5660
|
+
{ validatorId: 'manual-field-id-unique', level: 'error', code: 'MANUAL_FORM_FIELD_ID_UNIQUE', description: 'Manual field names must be unique in the instance metadata map.' },
|
|
5661
|
+
{ validatorId: 'manual-field-exists', level: 'error', code: 'MANUAL_FORM_FIELD_EXISTS', description: 'Target manual field must exist before patching or removing it.' },
|
|
5662
|
+
{ validatorId: 'field-removal-confirmed', level: 'error', code: 'MANUAL_FORM_FIELD_REMOVAL_CONFIRMED', description: 'Removing a field or its persisted value requires explicit confirmation.' },
|
|
5663
|
+
{ validatorId: 'field-label-valid', level: 'error', code: 'MANUAL_FORM_FIELD_LABEL_VALID', description: 'Manual field label must be a non-empty user-facing string.' },
|
|
5664
|
+
{ validatorId: 'host-template-field-exists', level: 'error', code: 'MANUAL_FORM_HOST_FIELD_EXISTS', description: 'Manual field metadata must correspond to a host template control or declared metadata bridge target.' },
|
|
5665
|
+
{ validatorId: 'control-type-discovered', level: 'error', code: 'MANUAL_FORM_CONTROL_TYPE_DISCOVERED', description: 'Control type must be discovered through dynamic-fields mappings or delegated discovery.' },
|
|
5666
|
+
{ validatorId: 'metadata-bridge-does-not-redefine-schema', level: 'error', code: 'MANUAL_FORM_METADATA_BRIDGE_SCHEMA_SAFE', description: 'Metadata bridge patches must not silently redefine backend schema or schema-driven FormConfig semantics.' },
|
|
5667
|
+
{ validatorId: 'delegates-field-metadata', level: 'error', code: 'MANUAL_FORM_DELEGATES_FIELD_METADATA', description: 'Advanced FieldMetadata edits must be delegated to the metadata-editor manifest.' },
|
|
5668
|
+
{ validatorId: 'delegates-form-config', level: 'error', code: 'MANUAL_FORM_DELEGATES_FORM_CONFIG', description: 'Advanced FormConfig semantics must be delegated to the dynamic-form manifest.' },
|
|
5669
|
+
{ validatorId: 'layout-field-references-valid', level: 'error', code: 'MANUAL_FORM_LAYOUT_FIELD_REFERENCES_VALID', description: 'Layout field references must resolve to manual fields.' },
|
|
5670
|
+
{ validatorId: 'manual-layout-does-not-replace-host-template', level: 'error', code: 'MANUAL_FORM_LAYOUT_HOST_TEMPLATE_SAFE', description: 'Manual layout metadata must not pretend to rewrite host-owned HTML template structure.' },
|
|
5671
|
+
{ validatorId: 'toolbar-flags-supported', level: 'error', code: 'MANUAL_FORM_TOOLBAR_FLAGS_SUPPORTED', description: 'Toolbar quick edit flags must be supported by the manual field toolbar.' },
|
|
5672
|
+
{ validatorId: 'metadata-bridge-gated-by-customization', level: 'error', code: 'MANUAL_FORM_METADATA_BRIDGE_GATED', description: 'Metadata bridge entry points must respect enableCustomization.' },
|
|
5673
|
+
{ validatorId: 'autosave-explicit', level: 'error', code: 'MANUAL_FORM_AUTOSAVE_EXPLICIT', description: 'Autosave enablement and persistence policy must be explicit.' },
|
|
5674
|
+
{ validatorId: 'autosave-debounce-safe', level: 'error', code: 'MANUAL_FORM_AUTOSAVE_DEBOUNCE_SAFE', description: 'Autosave debounce must be positive and safe for storage backends.' },
|
|
5675
|
+
{ validatorId: 'autosave-storage-available', level: 'error', code: 'MANUAL_FORM_AUTOSAVE_STORAGE_AVAILABLE', description: 'Autosave requires a valid AsyncConfigStorage implementation.' },
|
|
5676
|
+
{ validatorId: 'persistence-key-deterministic', level: 'error', code: 'MANUAL_FORM_PERSISTENCE_KEY_DETERMINISTIC', description: 'Persistence key composition must be deterministic across reopen/reload.' },
|
|
5677
|
+
{ validatorId: 'submit-behavior-supported', level: 'error', code: 'MANUAL_FORM_SUBMIT_BEHAVIOR_SUPPORTED', description: 'Submit behavior must map to supported manual form outputs or delegated dynamic-form semantics.' },
|
|
5678
|
+
{ validatorId: 'manual-form-round-trip', level: 'error', code: 'MANUAL_FORM_ROUND_TRIP', description: 'Open, edit, apply/save, reopen and runtime consume must preserve manual form config.' },
|
|
5679
|
+
],
|
|
5680
|
+
roundTripRequirements: [
|
|
5681
|
+
'ManualFormInstance is the package-level runtime document: config, field metadata map, FormGroup and persistence key must remain coherent.',
|
|
5682
|
+
'Manual field ids are stable field names; array indexes are not canonical identity.',
|
|
5683
|
+
'Field removal is destructive and requires confirmation before metadata, layout references or persisted values are removed.',
|
|
5684
|
+
'Autosave must be explicit, have a safe debounce and use deterministic persistence key composition through ManualFormPersistenceOptions.',
|
|
5685
|
+
'The metadata bridge may apply metadata-editor patches but must not silently redefine backend schema or duplicate FieldMetadata semantics.',
|
|
5686
|
+
'Advanced FormConfig authoring belongs to praxis-dynamic-form; this manifest governs manual form orchestration and delegates deeper FormConfig semantics.',
|
|
5687
|
+
],
|
|
5688
|
+
examples: [
|
|
5689
|
+
{ id: 'add-text-field', request: 'Add a manual text field for customer name.', operationId: 'manualField.add', params: { fieldName: 'customerName', controlType: 'input', label: 'Customer name', source: 'manual-template', delegateFieldMetadataTo: 'praxis-metadata-editor' }, isPositive: true },
|
|
5690
|
+
{ id: 'remove-obsolete-field', request: 'Remove the obsolete nickname field from the manual form.', operationId: 'manualField.remove', params: { fieldName: 'nickname', removeFromLayout: true, clearPersistedValue: true }, isPositive: true },
|
|
5691
|
+
{ id: 'rename-label', request: 'Change the label of cpf to CPF/CNPJ.', operationId: 'manualField.label.set', params: { fieldName: 'cpf', label: 'CPF/CNPJ' }, isPositive: true },
|
|
5692
|
+
{ id: 'enable-path-names', request: 'Use nested form paths as field names.', operationId: 'layout.configure', params: { usePathNames: true }, isPositive: true },
|
|
5693
|
+
{ id: 'configure-toolbar', request: 'Enable customization toolbar with required and hidden toggles.', operationId: 'toolbar.configure', params: { enableCustomization: true, editableFlags: ['required', 'hidden', 'openMetadataEditor'] }, isPositive: true },
|
|
5694
|
+
{ id: 'enable-autosave', request: 'Enable autosave every second for this tenant profile.', operationId: 'autosave.enabled.set', params: { enabled: true, debounceMs: 1000, namespace: 'sales', tenantId: 'acme', profileId: 'admin' }, isPositive: true },
|
|
5695
|
+
{ id: 'set-submit-behavior', request: 'Focus the first invalid field and scroll to errors on submit.', operationId: 'submitBehavior.set', params: { action: 'submit', focusFirstError: true, scrollToErrors: true }, isPositive: true },
|
|
5696
|
+
{ id: 'configure-metadata-bridge', request: 'Open metadata editor from the toolbar and persist draft after patch.', operationId: 'metadataBridge.configure', params: { enabled: true, openMode: 'field-toolbar', persistDraftAfterPatch: true, delegateFieldMetadataTo: 'praxis-metadata-editor', delegateControlDiscoveryTo: 'praxis-dynamic-fields' }, isPositive: true },
|
|
5697
|
+
{ id: 'reject-duplicate-field', request: 'Add another customerName field with a different label.', operationId: 'manualField.add', params: { fieldName: 'customerName', controlType: 'input', label: 'Duplicate customer' }, isPositive: false },
|
|
5698
|
+
{ id: 'reject-unconfirmed-removal', request: 'Remove email and clear its saved value without confirmation.', operationId: 'manualField.remove', params: { fieldName: 'email', clearPersistedValue: true }, isPositive: false },
|
|
5699
|
+
{ id: 'reject-unsafe-autosave', request: 'Autosave every millisecond with no storage identity.', operationId: 'autosave.enabled.set', params: { enabled: true, debounceMs: 1 }, isPositive: false },
|
|
5700
|
+
{ id: 'reject-schema-redefinition', request: 'Use manual form metadata bridge to replace the backend schema for cpf.', operationId: 'metadataBridge.configure', params: { enabled: true, fieldName: 'cpf', backendSchemaOverride: { type: 'number' } }, isPositive: false },
|
|
5701
|
+
],
|
|
5702
|
+
};
|
|
5703
|
+
|
|
5362
5704
|
/*
|
|
5363
5705
|
* Public API Surface of praxis-manual-form
|
|
5364
5706
|
*/
|
|
@@ -5367,4 +5709,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
5367
5709
|
* Generated bundle index. Do not edit.
|
|
5368
5710
|
*/
|
|
5369
5711
|
|
|
5370
|
-
export { MANUAL_FORM_AI_CAPABILITIES, MANUAL_FORM_CONSTRUCTOR_TO_CONTROL_TYPE, MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE, ManualFieldDirective, ManualFieldEditorOnDblclickDirective, ManualFieldKeyService, ManualFieldMetadataBridgeService, ManualFormActionsComponent, ManualFormComponent, ManualFormConfigEditorComponent, ManualFormDocExampleComponent, ManualFormDocExampleShowcaseComponent, ManualFormHeaderComponent, ManualFormInstance, ManualFormInstanceFactory, createManualFormSeed, toFieldMetadataMap };
|
|
5712
|
+
export { MANUAL_FORM_AI_CAPABILITIES, MANUAL_FORM_CONSTRUCTOR_TO_CONTROL_TYPE, MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE, ManualFieldDirective, ManualFieldEditorOnDblclickDirective, ManualFieldKeyService, ManualFieldMetadataBridgeService, ManualFormActionsComponent, ManualFormComponent, ManualFormConfigEditorComponent, ManualFormDocExampleComponent, ManualFormDocExampleShowcaseComponent, ManualFormHeaderComponent, ManualFormInstance, ManualFormInstanceFactory, PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST, createManualFormSeed, toFieldMetadataMap };
|
package/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormConfig, FieldMetadata, DynamicFormService, AsyncConfigStorage, FormActionsLayout, FormActionButton, AiCapability, FormMessagesLayout, FormBehaviorLayout, FormHookStage, FieldDefinition, FieldControlType, AiCapabilityCategory, AiValueKind, AiCapabilityCatalog } from '@praxisui/core';
|
|
1
|
+
import { FormConfig, FieldMetadata, DynamicFormService, AsyncConfigStorage, FormActionsLayout, FormActionButton, AiCapability, FormMessagesLayout, FormBehaviorLayout, FormHookStage, FieldDefinition, FieldControlType, AiCapabilityCategory, AiValueKind, AiCapabilityCatalog, ComponentAuthoringManifest } from '@praxisui/core';
|
|
2
2
|
import { FormGroup, FormControlName, FormGroupName, AbstractControl, FormControl } from '@angular/forms';
|
|
3
3
|
import { Observable, BehaviorSubject } from 'rxjs';
|
|
4
4
|
import * as _angular_core from '@angular/core';
|
|
@@ -524,5 +524,7 @@ interface CapabilityCatalog extends AiCapabilityCatalog {
|
|
|
524
524
|
}
|
|
525
525
|
declare const MANUAL_FORM_AI_CAPABILITIES: CapabilityCatalog;
|
|
526
526
|
|
|
527
|
-
|
|
527
|
+
declare const PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST: ComponentAuthoringManifest;
|
|
528
|
+
|
|
529
|
+
export { MANUAL_FORM_AI_CAPABILITIES, MANUAL_FORM_CONSTRUCTOR_TO_CONTROL_TYPE, MANUAL_FORM_SELECTOR_TO_CONTROL_TYPE, ManualFieldDirective, ManualFieldEditorOnDblclickDirective, ManualFieldKeyService, ManualFieldMetadataBridgeService, ManualFormActionsComponent, ManualFormComponent, ManualFormConfigEditorComponent, ManualFormDocExampleComponent, ManualFormDocExampleShowcaseComponent, ManualFormHeaderComponent, ManualFormInstance, ManualFormInstanceFactory, PRAXIS_MANUAL_FORM_AUTHORING_MANIFEST, createManualFormSeed, toFieldMetadataMap };
|
|
528
530
|
export type { Capability, CapabilityCatalog, CapabilityCategory, ManualFieldKeyResolution, ManualFieldMetadataMap, ManualFormDocExampleLevel, ManualFormDocExampleTab, ManualFormId, ManualFormPersistenceOptions, ManualFormSeed, ManualFormSeedOptions, ManualFormSnapshot, ManualFormState, ValueKind };
|
package/package.json
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/manual-form",
|
|
3
|
-
"version": "8.0.0-beta.
|
|
3
|
+
"version": "8.0.0-beta.20",
|
|
4
4
|
"description": "Manual form toolkit for Praxis UI: container, instance factory and editor bridge for @praxisui/* fields.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^20.1.0",
|
|
7
7
|
"@angular/core": "^20.1.0",
|
|
8
|
-
"@praxisui/core": "^8.0.0-beta.
|
|
9
|
-
"@praxisui/dynamic-fields": "^8.0.0-beta.
|
|
10
|
-
"@praxisui/settings-panel": "^8.0.0-beta.
|
|
11
|
-
"@praxisui/metadata-editor": "^8.0.0-beta.
|
|
8
|
+
"@praxisui/core": "^8.0.0-beta.20",
|
|
9
|
+
"@praxisui/dynamic-fields": "^8.0.0-beta.20",
|
|
10
|
+
"@praxisui/settings-panel": "^8.0.0-beta.20",
|
|
11
|
+
"@praxisui/metadata-editor": "^8.0.0-beta.20",
|
|
12
|
+
"@angular/cdk": "^20.1.0",
|
|
13
|
+
"@angular/forms": "^20.1.0",
|
|
14
|
+
"@angular/material": "^20.1.0",
|
|
15
|
+
"@angular/router": "^20.1.0",
|
|
16
|
+
"@praxisui/ai": "^8.0.0-beta.20",
|
|
17
|
+
"rxjs": "~7.8.0"
|
|
12
18
|
},
|
|
13
19
|
"dependencies": {
|
|
14
20
|
"tslib": "^2.3.0"
|