ngx-dynamic-entity-builder 1.4.0 → 1.5.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-dynamic-entity-builder",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Angular standalone visual builder for authoring dynamic-entity EntityConfig (fields, tabs, validators, RBAC).",
5
5
  "//typings": "Local workspace resolution only: ng-packagr 21 writes types/ngx-dynamic-entity-builder.d.ts into dist/package.json. Do NOT add a 'main' field here — ng-packagr does not generate one, so it would be copied verbatim and resolve wrongly in the published package.",
6
6
  "typings": "types/ngx-dynamic-entity-builder.d.ts",
@@ -10,8 +10,8 @@
10
10
  "@angular/core": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
11
11
  "@angular/forms": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
12
12
  "@angular/material": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0 || ^22.0.0",
13
- "@dynamic-entity/core": "^1.4.0",
14
- "ngx-dynamic-entity": "^1.4.0",
13
+ "@dynamic-entity/core": "^1.5.0",
14
+ "ngx-dynamic-entity": "^1.5.0",
15
15
  "rxjs": "^7.0.0"
16
16
  },
17
17
  "keywords": [
@@ -346,6 +346,35 @@ declare class FieldPaletteComponent {
346
346
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<FieldPaletteComponent, "ngx-field-palette", never, {}, { "pick": "pick"; }, never, never, true, never>;
347
347
  }
348
348
 
349
+ /** One choosable field: the reference stored, the label shown, and the path behind it. */
350
+ interface FieldPathOption {
351
+ value: string;
352
+ label: string;
353
+ path: string;
354
+ }
355
+ /**
356
+ * Every field in the config, offered by path.
357
+ *
358
+ * Four places in the builder name a field — `showWhen` keys, `patchOnTrue` mappings,
359
+ * `autoPatch` targets and rule triggers/targets — and each was a free-text box. Typing an id
360
+ * is the one way left to author an ambiguous reference: ids are unique per scope, so
361
+ * `address` names nothing in particular once two tabs have one. Choosing from this list
362
+ * always yields a path.
363
+ *
364
+ * `collectFieldScopes` rather than the tab-level view, so a field nested inside a `group` is
365
+ * offered too, and every entry carries the scope `refOf` needs.
366
+ */
367
+ declare function fieldPathOptions(config: EntityFormConfig | null | undefined, language: string): FieldPathOption[];
368
+ /**
369
+ * The options plus whatever is already selected.
370
+ *
371
+ * A reference written before paths existed is a bare id, and one written against a field
372
+ * since deleted is a path nothing answers to. Neither appears in the list, and a `mat-select`
373
+ * silently drops a value it has no option for — so opening such a config and saving it would
374
+ * quietly erase the reference. They are kept, and shown as they are.
375
+ */
376
+ declare function withExistingOptions(options: readonly FieldPathOption[], current: readonly (string | undefined)[]): FieldPathOption[];
377
+
349
378
  /**
350
379
  * FieldInspectorComponent — edits every property of the currently selected field.
351
380
  */
@@ -358,10 +387,45 @@ declare class FieldInspectorComponent {
358
387
  protected labelValue(field: NestedFieldConfig): string;
359
388
  protected placeholderValue(field: NestedFieldConfig): string;
360
389
  protected optionLabel(option: DropdownOption): string;
390
+ /**
391
+ * Every tab a field can live on, sub-tabs included.
392
+ *
393
+ * `moveFieldToTab` existed on the store with nothing calling it, so a field authored on the
394
+ * wrong tab had to be deleted and rebuilt — losing its validators, options and every rule
395
+ * aimed at it.
396
+ */
397
+ protected readonly tabOptions: _angular_core.Signal<{
398
+ id: string;
399
+ label: string;
400
+ }[]>;
401
+ /**
402
+ * The tab the selected field currently sits on.
403
+ *
404
+ * Looked up by identity rather than parsed out of the path: the scope of
405
+ * `incident.incidentDetails.incidentTime` is two segments and the field belongs to the
406
+ * *last* of them, while a field inside a group has the group id in that position and
407
+ * belongs to no tab of that name at all.
408
+ */
409
+ protected currentTabId(field: NestedFieldConfig): string;
410
+ protected moveToTab(field: NestedFieldConfig, tabId: string): void;
411
+ /**
412
+ * Fields offered wherever this inspector names one — the `showWhen` key and both ends of a
413
+ * `patchOnTrue` mapping. All three were free text, which is the one way left to write a
414
+ * reference that names two fields at once.
415
+ */
416
+ protected readonly fieldOptions: _angular_core.Signal<FieldPathOption[]>;
417
+ /** Options plus whatever is already selected, so an unknown reference is never dropped. */
418
+ protected optionsWith(...current: (string | undefined)[]): FieldPathOption[];
361
419
  protected showWhenEntries(field: NestedFieldConfig): {
362
420
  key: string;
363
421
  display: string;
364
422
  }[];
423
+ /**
424
+ * Seeds a new condition with the first field not already watched.
425
+ *
426
+ * It used to seed the literal string `field`, which is not a field id at all — so a new
427
+ * condition started out referencing nothing and silently hid the field until it was edited.
428
+ */
365
429
  protected addShowWhen(field: NestedFieldConfig): void;
366
430
  protected renameShowWhen(field: NestedFieldConfig, oldKey: string, newKey: string): void;
367
431
  protected setShowWhenValue(field: NestedFieldConfig, key: string, raw: string): void;
@@ -391,12 +455,6 @@ declare class TabManagerComponent {
391
455
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<TabManagerComponent, "ngx-tab-manager", never, {}, {}, never, never, true, never>;
392
456
  }
393
457
 
394
- /** One choosable field: the reference stored, the label shown, and the path behind it. */
395
- interface RuleFieldOption {
396
- value: string;
397
- label: string;
398
- path: string;
399
- }
400
458
  /**
401
459
  * RuleFormComponent — dialog/panel form for creating or editing a FormRule.
402
460
  */
@@ -406,33 +464,23 @@ declare class RuleFormComponent {
406
464
  save: EventEmitter<FormRule>;
407
465
  cancel: EventEmitter<void>;
408
466
  readonly operators: RuleOperator[];
409
- /**
410
- * Every field in the config, offered by path.
411
- *
412
- * Both pickers used to be free text — the trigger was typed by hand and the targets could
413
- * not be edited at all, so a rule only ever acted on the field it triggered from. Typing an
414
- * id is also the one way left to write an ambiguous reference: ids are unique per scope, so
415
- * `address` names nothing in particular once two tabs have one. Choosing from this list
416
- * always yields a path.
417
- */
418
- protected readonly fieldOptions: _angular_core.Signal<RuleFieldOption[]>;
419
- /**
420
- * The options plus whatever the rule already names.
421
- *
422
- * A rule written before paths existed holds a bare id, and one written against a field that
423
- * has since been deleted holds a path nothing answers to. Neither appears in the list, and a
424
- * `mat-select` silently drops a value it has no option for — so opening such a rule and
425
- * saving it would quietly erase the reference. They are kept, and shown as they are.
426
- */
427
- private withExisting;
467
+ protected readonly fieldOptions: _angular_core.Signal<FieldPathOption[]>;
428
468
  /**
429
469
  * Methods, not `computed`. Both read `rule`, which is a plain `@Input` object mutated in
430
470
  * place rather than a signal — a computed would cache the first evaluation and never see a
431
471
  * different rule being edited.
432
472
  */
433
- protected triggerOptions(): RuleFieldOption[];
434
- protected targetOptions(): RuleFieldOption[];
435
- /** Field targets only — a rule may also target a tab, which this picker does not manage. */
473
+ protected triggerOptions(): FieldPathOption[];
474
+ protected targetOptions(): FieldPathOption[];
475
+ private cachedTargets;
476
+ /**
477
+ * Field targets only — a rule may also target a tab, which this picker does not manage.
478
+ *
479
+ * The array identity is held stable while the contents are unchanged. This is bound through
480
+ * `[ngModel]` on a multi-select, and a fresh array on each call made `ngModel` see a new
481
+ * value on every change-detection pass: it wrote, which scheduled another pass, which built
482
+ * another array. Opening the rule editor locked the browser outright.
483
+ */
436
484
  protected targetValues(): string[];
437
485
  /**
438
486
  * Replaces the field targets, leaving any tab target untouched.
@@ -476,6 +524,17 @@ declare class EntityReferenceConfigComponent {
476
524
  protected readonly field: _angular_core.Signal<NestedFieldConfig>;
477
525
  /** Sibling fields that can drive a cascade — anything but this field itself. */
478
526
  protected readonly parentCandidates: _angular_core.Signal<NestedFieldConfig[]>;
527
+ private readonly fieldOptions;
528
+ /**
529
+ * Cascade parents, offered by path.
530
+ *
531
+ * The picker existed but its values were bare ids, which name a field only while no second
532
+ * scope reuses the id — so the one control that was already a list could still produce an
533
+ * ambiguous reference.
534
+ */
535
+ protected parentOptions(): FieldPathOption[];
536
+ /** Options plus whatever is already selected, so an unknown reference is never dropped. */
537
+ protected optionsWith(...current: (string | undefined)[]): FieldPathOption[];
479
538
  private readonly filtersParseError;
480
539
  protected readonly filtersError: _angular_core.Signal<string>;
481
540
  protected ref(field: NestedFieldConfig): ngx_dynamic_entity.EntityReferenceConfig;
@@ -519,5 +578,5 @@ declare class EntityBuilderTreeNodeComponent {
519
578
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<EntityBuilderTreeNodeComponent, "ngx-entity-builder-tree-node", never, { "field": { "alias": "field"; "required": true; }; "index": { "alias": "index"; "required": true; }; "totalCount": { "alias": "totalCount"; "required": true; }; }, {}, never, never, true, never>;
520
579
  }
521
580
 
522
- export { BuilderStore, EntityBuilderCanvasComponent, EntityBuilderComponent, EntityBuilderTreeNodeComponent, EntityReferenceConfigComponent, FieldInspectorComponent, FieldPaletteComponent, FieldRulesListComponent, RuleFormComponent, TabManagerComponent };
523
- export type { BuilderFieldGroup, BuilderProblem };
581
+ export { BuilderStore, EntityBuilderCanvasComponent, EntityBuilderComponent, EntityBuilderTreeNodeComponent, EntityReferenceConfigComponent, FieldInspectorComponent, FieldPaletteComponent, FieldRulesListComponent, RuleFormComponent, TabManagerComponent, fieldPathOptions, withExistingOptions };
582
+ export type { BuilderFieldGroup, BuilderProblem, FieldPathOption };