@agridea/suibi-module 0.1.0-preview.7 → 0.1.0-preview.8c4fa92

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.
Files changed (34) hide show
  1. package/dist/elements/browser/main.js +76 -72
  2. package/dist/elements/browser/styles.css +1 -1
  3. package/dist/elements/browser/suibi-module-latest.css +1 -1
  4. package/dist/elements/browser/suibi-module-latest.js +76 -72
  5. package/dist/elements/browser/{suibi-module.v0.1.0-preview.7.css → suibi-module.v0.1.0-preview.8c4fa92.css} +1 -1
  6. package/dist/elements/browser/suibi-module.v0.1.0-preview.8c4fa92.js +79 -0
  7. package/dist/elements/browser/suibi-theme-dark.css +1 -1
  8. package/dist/elements/browser/version.txt +1 -1
  9. package/dist/types/app/app.d.ts +1 -3
  10. package/dist/types/app/components/add-dashed-button/add-dashed-button.component.d.ts +9 -0
  11. package/dist/types/app/components/data-preview/data-preview.component.d.ts +2 -0
  12. package/dist/types/app/components/empty-state/empty-state.component.d.ts +10 -0
  13. package/dist/types/app/components/planning-result/planning-result.component.d.ts +69 -0
  14. package/dist/types/app/components/workflow-stepper/workflow-stepper.component.d.ts +48 -0
  15. package/dist/types/app/core/data/naebi-data.service.d.ts +14 -4
  16. package/dist/types/app/core/master-data/master-data.service.d.ts +6 -1
  17. package/dist/types/app/core/navigation/navigation.service.d.ts +2 -0
  18. package/dist/types/app/core/planning/planning-balance.service.d.ts +18 -0
  19. package/dist/types/app/core/planning/planning-balance.types.d.ts +206 -0
  20. package/dist/types/app/core/validation/capabilities.d.ts +5 -5
  21. package/dist/types/app/core/validation/global-validation.service.d.ts +0 -3
  22. package/dist/types/app/header-bar.d.ts +2 -2
  23. package/dist/types/app/jsonforms/registry/renderers.registry.d.ts +4 -0
  24. package/dist/types/app/jsonforms/renderers/layout/array/array-layout.renderer.d.ts +43 -0
  25. package/dist/types/app/jsonforms/renderers/layout/categorization/selected-category-categorization.renderer.d.ts +3 -0
  26. package/dist/types/app/nutrient-cycle/animal-stock/animal-stock-master-detail.component.d.ts +0 -1
  27. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-detail.component.d.ts +1 -1
  28. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-list.component.d.ts +1 -0
  29. package/dist/types/app/nutrient-cycle/farm-manure-trading/farm-manure-trading-master-detail.component.d.ts +0 -1
  30. package/dist/types/app/nutrient-cycle/field-spreading/field-spreading.component.d.ts +0 -1
  31. package/dist/types/app/nutrient-cycle/lifetime-performance/lifetime-performance-form.component.d.ts +1 -1
  32. package/dist/types/environments/environment.d.ts +5 -0
  33. package/package.json +1 -1
  34. package/dist/elements/browser/suibi-module.v0.1.0-preview.7.js +0 -75
@@ -1 +1 @@
1
- :host,suibi-module{color-scheme:dark;--mat-sys-background: #121410;--mat-sys-error: #ffb4ab;--mat-sys-error-container: #93000a;--mat-sys-inverse-on-surface: #2f312d;--mat-sys-inverse-primary: #e722ff;--mat-sys-inverse-surface: #e2e3dc;--mat-sys-on-background: #e2e3dc;--mat-sys-on-error: #690005;--mat-sys-on-error-container: #ffdad6;--mat-sys-on-primary: #013a00;--mat-sys-on-primary-container: #77ff61;--mat-sys-on-primary-fixed: #002200;--mat-sys-on-primary-fixed-variant: #015300;--mat-sys-on-secondary: #263422;--mat-sys-on-secondary-container: #d7e8cd;--mat-sys-on-secondary-fixed: #121f0e;--mat-sys-on-secondary-fixed-variant: #3c4b37;--mat-sys-on-surface: #e2e3dc;--mat-sys-on-surface-variant: #dfe4d7;--mat-sys-on-tertiary: #013a00;--mat-sys-on-tertiary-container: #77ff61;--mat-sys-on-tertiary-fixed: #002200;--mat-sys-on-tertiary-fixed-variant: #015300;--mat-sys-outline: #8d9387;--mat-sys-outline-variant: #43483f;--mat-sys-primary: #02e600;--mat-sys-primary-container: #015300;--mat-sys-primary-fixed: #77ff61;--mat-sys-primary-fixed-dim: #02e600;--mat-sys-scrim: #000000;--mat-sys-secondary: #bbcbb2;--mat-sys-secondary-container: #3c4b37;--mat-sys-secondary-fixed: #d7e8cd;--mat-sys-secondary-fixed-dim: #bbcbb2;--mat-sys-shadow: #000000;--mat-sys-surface: #121410;--mat-sys-surface-bright: #383a35;--mat-sys-surface-container: #1e201c;--mat-sys-surface-container-high: #282b26;--mat-sys-surface-container-highest: #333531;--mat-sys-surface-container-low: #1a1c18;--mat-sys-surface-container-lowest: #0c0f0b;--mat-sys-surface-dim: #121410;--mat-sys-surface-tint: #02e600;--mat-sys-surface-variant: #43483f;--mat-sys-tertiary: #02e600;--mat-sys-tertiary-container: #015300;--mat-sys-tertiary-fixed: #77ff61;--mat-sys-tertiary-fixed-dim: #02e600;--mat-sys-neutral-variant20: #2c3229;--mat-sys-neutral10: #1a1c18;--mat-sys-level0: 0px 0px 0px 0px rgba(0, 0, 0, .2), 0px 0px 0px 0px rgba(0, 0, 0, .14), 0px 0px 0px 0px rgba(0, 0, 0, .12);--mat-sys-level1: 0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12);--mat-sys-level2: 0px 3px 3px -2px rgba(0, 0, 0, .2), 0px 3px 4px 0px rgba(0, 0, 0, .14), 0px 1px 8px 0px rgba(0, 0, 0, .12);--mat-sys-level3: 0px 3px 5px -1px rgba(0, 0, 0, .2), 0px 6px 10px 0px rgba(0, 0, 0, .14), 0px 1px 18px 0px rgba(0, 0, 0, .12);--mat-sys-level4: 0px 5px 5px -3px rgba(0, 0, 0, .2), 0px 8px 10px 1px rgba(0, 0, 0, .14), 0px 3px 14px 2px rgba(0, 0, 0, .12);--mat-sys-level5: 0px 7px 8px -4px rgba(0, 0, 0, .2), 0px 12px 17px 2px rgba(0, 0, 0, .14), 0px 5px 22px 4px rgba(0, 0, 0, .12);--mat-sys-body-large: 300 1rem / 1.5rem Serif;--mat-sys-body-large-font: Serif;--mat-sys-body-large-line-height: 1.5rem;--mat-sys-body-large-size: 1rem;--mat-sys-body-large-tracking: .031rem;--mat-sys-body-large-weight: 300;--mat-sys-body-medium: 300 .875rem / 1.25rem Serif;--mat-sys-body-medium-font: Serif;--mat-sys-body-medium-line-height: 1.25rem;--mat-sys-body-medium-size: .875rem;--mat-sys-body-medium-tracking: .016rem;--mat-sys-body-medium-weight: 300;--mat-sys-body-small: 300 .75rem / 1rem Serif;--mat-sys-body-small-font: Serif;--mat-sys-body-small-line-height: 1rem;--mat-sys-body-small-size: .75rem;--mat-sys-body-small-tracking: .025rem;--mat-sys-body-small-weight: 300;--mat-sys-display-large: 300 3.562rem / 4rem Serif;--mat-sys-display-large-font: Serif;--mat-sys-display-large-line-height: 4rem;--mat-sys-display-large-size: 3.562rem;--mat-sys-display-large-tracking: -.016rem;--mat-sys-display-large-weight: 300;--mat-sys-display-medium: 300 2.812rem / 3.25rem Serif;--mat-sys-display-medium-font: Serif;--mat-sys-display-medium-line-height: 3.25rem;--mat-sys-display-medium-size: 2.812rem;--mat-sys-display-medium-tracking: 0;--mat-sys-display-medium-weight: 300;--mat-sys-display-small: 300 2.25rem / 2.75rem Serif;--mat-sys-display-small-font: Serif;--mat-sys-display-small-line-height: 2.75rem;--mat-sys-display-small-size: 2.25rem;--mat-sys-display-small-tracking: 0;--mat-sys-display-small-weight: 300;--mat-sys-headline-large: 300 2rem / 2.5rem Serif;--mat-sys-headline-large-font: Serif;--mat-sys-headline-large-line-height: 2.5rem;--mat-sys-headline-large-size: 2rem;--mat-sys-headline-large-tracking: 0;--mat-sys-headline-large-weight: 300;--mat-sys-headline-medium: 300 1.75rem / 2.25rem Serif;--mat-sys-headline-medium-font: Serif;--mat-sys-headline-medium-line-height: 2.25rem;--mat-sys-headline-medium-size: 1.75rem;--mat-sys-headline-medium-tracking: 0;--mat-sys-headline-medium-weight: 300;--mat-sys-headline-small: 300 1.5rem / 2rem Serif;--mat-sys-headline-small-font: Serif;--mat-sys-headline-small-line-height: 2rem;--mat-sys-headline-small-size: 1.5rem;--mat-sys-headline-small-tracking: 0;--mat-sys-headline-small-weight: 300;--mat-sys-label-large: 600 .875rem / 1.25rem Serif;--mat-sys-label-large-font: Serif;--mat-sys-label-large-line-height: 1.25rem;--mat-sys-label-large-size: .875rem;--mat-sys-label-large-tracking: .006rem;--mat-sys-label-large-weight: 600;--mat-sys-label-large-weight-prominent: 800;--mat-sys-label-medium: 600 .75rem / 1rem Serif;--mat-sys-label-medium-font: Serif;--mat-sys-label-medium-line-height: 1rem;--mat-sys-label-medium-size: .75rem;--mat-sys-label-medium-tracking: .031rem;--mat-sys-label-medium-weight: 600;--mat-sys-label-medium-weight-prominent: 800;--mat-sys-label-small: 600 .688rem / 1rem Serif;--mat-sys-label-small-font: Serif;--mat-sys-label-small-line-height: 1rem;--mat-sys-label-small-size: .688rem;--mat-sys-label-small-tracking: .031rem;--mat-sys-label-small-weight: 600;--mat-sys-title-large: 300 1.375rem / 1.75rem Serif;--mat-sys-title-large-font: Serif;--mat-sys-title-large-line-height: 1.75rem;--mat-sys-title-large-size: 1.375rem;--mat-sys-title-large-tracking: 0;--mat-sys-title-large-weight: 300;--mat-sys-title-medium: 600 1rem / 1.5rem Serif;--mat-sys-title-medium-font: Serif;--mat-sys-title-medium-line-height: 1.5rem;--mat-sys-title-medium-size: 1rem;--mat-sys-title-medium-tracking: .009rem;--mat-sys-title-medium-weight: 600;--mat-sys-title-small: 600 .875rem / 1.25rem Serif;--mat-sys-title-small-font: Serif;--mat-sys-title-small-line-height: 1.25rem;--mat-sys-title-small-size: .875rem;--mat-sys-title-small-tracking: .006rem;--mat-sys-title-small-weight: 600;--mat-sys-corner-extra-large: 28px;--mat-sys-corner-extra-large-top: 28px 28px 0 0;--mat-sys-corner-extra-small: 4px;--mat-sys-corner-extra-small-top: 4px 4px 0 0;--mat-sys-corner-full: 9999px;--mat-sys-corner-large: 16px;--mat-sys-corner-large-end: 0 16px 16px 0;--mat-sys-corner-large-start: 16px 0 0 16px;--mat-sys-corner-large-top: 16px 16px 0 0;--mat-sys-corner-medium: 12px;--mat-sys-corner-none: 0;--mat-sys-corner-small: 8px;--mat-sys-dragged-state-layer-opacity: .16;--mat-sys-focus-state-layer-opacity: .12;--mat-sys-hover-state-layer-opacity: .08;--mat-sys-pressed-state-layer-opacity: .12;--mat-sys-surface: #121212;--mat-form-field-filled-container-color: #2a2a2a;--mat-card-elevated-container-color: #1e1e1e;font-family:Roboto Thin,Roboto,Arial,sans-serif;display:block;line-height:1.4;box-sizing:border-box;background:var(--mat-sys-surface, #121212);color:var(--mat-sys-on-surface, #e0e0e0)}*,*:before,*:after{box-sizing:inherit}.suibi-surface{background:var(--mat-sys-surface-container-low, #1e1e1e);border:1px solid var(--mat-sys-outline-variant, #2a2a2a);border-radius:8px;padding:16px}pre{background:#1d1f21;color:#c5c8c6;padding:8px 16px;border-radius:4px}:host .mat-mdc-form-field-error,suibi-module .mat-mdc-form-field-error{color:#e72200}.group-layout.mat-mdc-card-outlined{border:0;--mdc-outlined-card-outline-color: transparent;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f;border-radius:8px}.horizontal-layout>div:has([style*="display: none"]){display:none!important}
1
+ :host,suibi-module{color-scheme:dark;--mat-sys-background: #121410;--mat-sys-error: #ffb4ab;--mat-sys-error-container: #93000a;--mat-sys-inverse-on-surface: #2f312d;--mat-sys-inverse-primary: #e722ff;--mat-sys-inverse-surface: #e2e3dc;--mat-sys-on-background: #e2e3dc;--mat-sys-on-error: #690005;--mat-sys-on-error-container: #ffdad6;--mat-sys-on-primary: #013a00;--mat-sys-on-primary-container: #77ff61;--mat-sys-on-primary-fixed: #002200;--mat-sys-on-primary-fixed-variant: #015300;--mat-sys-on-secondary: #263422;--mat-sys-on-secondary-container: #d7e8cd;--mat-sys-on-secondary-fixed: #121f0e;--mat-sys-on-secondary-fixed-variant: #3c4b37;--mat-sys-on-surface: #e2e3dc;--mat-sys-on-surface-variant: #dfe4d7;--mat-sys-on-tertiary: #013a00;--mat-sys-on-tertiary-container: #77ff61;--mat-sys-on-tertiary-fixed: #002200;--mat-sys-on-tertiary-fixed-variant: #015300;--mat-sys-outline: #8d9387;--mat-sys-outline-variant: #43483f;--mat-sys-primary: #02e600;--mat-sys-primary-container: #015300;--mat-sys-primary-fixed: #77ff61;--mat-sys-primary-fixed-dim: #02e600;--mat-sys-scrim: #000000;--mat-sys-secondary: #bbcbb2;--mat-sys-secondary-container: #3c4b37;--mat-sys-secondary-fixed: #d7e8cd;--mat-sys-secondary-fixed-dim: #bbcbb2;--mat-sys-shadow: #000000;--mat-sys-surface: #121410;--mat-sys-surface-bright: #383a35;--mat-sys-surface-container: #1e201c;--mat-sys-surface-container-high: #282b26;--mat-sys-surface-container-highest: #333531;--mat-sys-surface-container-low: #1a1c18;--mat-sys-surface-container-lowest: #0c0f0b;--mat-sys-surface-dim: #121410;--mat-sys-surface-tint: #02e600;--mat-sys-surface-variant: #43483f;--mat-sys-tertiary: #02e600;--mat-sys-tertiary-container: #015300;--mat-sys-tertiary-fixed: #77ff61;--mat-sys-tertiary-fixed-dim: #02e600;--mat-sys-neutral-variant20: #2c3229;--mat-sys-neutral10: #1a1c18;--mat-sys-level0: 0px 0px 0px 0px rgba(0, 0, 0, .2), 0px 0px 0px 0px rgba(0, 0, 0, .14), 0px 0px 0px 0px rgba(0, 0, 0, .12);--mat-sys-level1: 0px 2px 1px -1px rgba(0, 0, 0, .2), 0px 1px 1px 0px rgba(0, 0, 0, .14), 0px 1px 3px 0px rgba(0, 0, 0, .12);--mat-sys-level2: 0px 3px 3px -2px rgba(0, 0, 0, .2), 0px 3px 4px 0px rgba(0, 0, 0, .14), 0px 1px 8px 0px rgba(0, 0, 0, .12);--mat-sys-level3: 0px 3px 5px -1px rgba(0, 0, 0, .2), 0px 6px 10px 0px rgba(0, 0, 0, .14), 0px 1px 18px 0px rgba(0, 0, 0, .12);--mat-sys-level4: 0px 5px 5px -3px rgba(0, 0, 0, .2), 0px 8px 10px 1px rgba(0, 0, 0, .14), 0px 3px 14px 2px rgba(0, 0, 0, .12);--mat-sys-level5: 0px 7px 8px -4px rgba(0, 0, 0, .2), 0px 12px 17px 2px rgba(0, 0, 0, .14), 0px 5px 22px 4px rgba(0, 0, 0, .12);--mat-sys-body-large: 300 1rem / 1.5rem Serif;--mat-sys-body-large-font: Serif;--mat-sys-body-large-line-height: 1.5rem;--mat-sys-body-large-size: 1rem;--mat-sys-body-large-tracking: .031rem;--mat-sys-body-large-weight: 300;--mat-sys-body-medium: 300 .875rem / 1.25rem Serif;--mat-sys-body-medium-font: Serif;--mat-sys-body-medium-line-height: 1.25rem;--mat-sys-body-medium-size: .875rem;--mat-sys-body-medium-tracking: .016rem;--mat-sys-body-medium-weight: 300;--mat-sys-body-small: 300 .75rem / 1rem Serif;--mat-sys-body-small-font: Serif;--mat-sys-body-small-line-height: 1rem;--mat-sys-body-small-size: .75rem;--mat-sys-body-small-tracking: .025rem;--mat-sys-body-small-weight: 300;--mat-sys-display-large: 300 3.562rem / 4rem Serif;--mat-sys-display-large-font: Serif;--mat-sys-display-large-line-height: 4rem;--mat-sys-display-large-size: 3.562rem;--mat-sys-display-large-tracking: -.016rem;--mat-sys-display-large-weight: 300;--mat-sys-display-medium: 300 2.812rem / 3.25rem Serif;--mat-sys-display-medium-font: Serif;--mat-sys-display-medium-line-height: 3.25rem;--mat-sys-display-medium-size: 2.812rem;--mat-sys-display-medium-tracking: 0;--mat-sys-display-medium-weight: 300;--mat-sys-display-small: 300 2.25rem / 2.75rem Serif;--mat-sys-display-small-font: Serif;--mat-sys-display-small-line-height: 2.75rem;--mat-sys-display-small-size: 2.25rem;--mat-sys-display-small-tracking: 0;--mat-sys-display-small-weight: 300;--mat-sys-headline-large: 300 2rem / 2.5rem Serif;--mat-sys-headline-large-font: Serif;--mat-sys-headline-large-line-height: 2.5rem;--mat-sys-headline-large-size: 2rem;--mat-sys-headline-large-tracking: 0;--mat-sys-headline-large-weight: 300;--mat-sys-headline-medium: 300 1.75rem / 2.25rem Serif;--mat-sys-headline-medium-font: Serif;--mat-sys-headline-medium-line-height: 2.25rem;--mat-sys-headline-medium-size: 1.75rem;--mat-sys-headline-medium-tracking: 0;--mat-sys-headline-medium-weight: 300;--mat-sys-headline-small: 300 1.5rem / 2rem Serif;--mat-sys-headline-small-font: Serif;--mat-sys-headline-small-line-height: 2rem;--mat-sys-headline-small-size: 1.5rem;--mat-sys-headline-small-tracking: 0;--mat-sys-headline-small-weight: 300;--mat-sys-label-large: 600 .875rem / 1.25rem Serif;--mat-sys-label-large-font: Serif;--mat-sys-label-large-line-height: 1.25rem;--mat-sys-label-large-size: .875rem;--mat-sys-label-large-tracking: .006rem;--mat-sys-label-large-weight: 600;--mat-sys-label-large-weight-prominent: 800;--mat-sys-label-medium: 600 .75rem / 1rem Serif;--mat-sys-label-medium-font: Serif;--mat-sys-label-medium-line-height: 1rem;--mat-sys-label-medium-size: .75rem;--mat-sys-label-medium-tracking: .031rem;--mat-sys-label-medium-weight: 600;--mat-sys-label-medium-weight-prominent: 800;--mat-sys-label-small: 600 .688rem / 1rem Serif;--mat-sys-label-small-font: Serif;--mat-sys-label-small-line-height: 1rem;--mat-sys-label-small-size: .688rem;--mat-sys-label-small-tracking: .031rem;--mat-sys-label-small-weight: 600;--mat-sys-title-large: 300 1.375rem / 1.75rem Serif;--mat-sys-title-large-font: Serif;--mat-sys-title-large-line-height: 1.75rem;--mat-sys-title-large-size: 1.375rem;--mat-sys-title-large-tracking: 0;--mat-sys-title-large-weight: 300;--mat-sys-title-medium: 600 1rem / 1.5rem Serif;--mat-sys-title-medium-font: Serif;--mat-sys-title-medium-line-height: 1.5rem;--mat-sys-title-medium-size: 1rem;--mat-sys-title-medium-tracking: .009rem;--mat-sys-title-medium-weight: 600;--mat-sys-title-small: 600 .875rem / 1.25rem Serif;--mat-sys-title-small-font: Serif;--mat-sys-title-small-line-height: 1.25rem;--mat-sys-title-small-size: .875rem;--mat-sys-title-small-tracking: .006rem;--mat-sys-title-small-weight: 600;--mat-sys-corner-extra-large: 28px;--mat-sys-corner-extra-large-top: 28px 28px 0 0;--mat-sys-corner-extra-small: 4px;--mat-sys-corner-extra-small-top: 4px 4px 0 0;--mat-sys-corner-full: 9999px;--mat-sys-corner-large: 16px;--mat-sys-corner-large-end: 0 16px 16px 0;--mat-sys-corner-large-start: 16px 0 0 16px;--mat-sys-corner-large-top: 16px 16px 0 0;--mat-sys-corner-medium: 12px;--mat-sys-corner-none: 0;--mat-sys-corner-small: 8px;--mat-sys-dragged-state-layer-opacity: .16;--mat-sys-focus-state-layer-opacity: .12;--mat-sys-hover-state-layer-opacity: .08;--mat-sys-pressed-state-layer-opacity: .12;--mat-sys-surface: #121212;--mat-form-field-filled-container-color: #2a2a2a;--mat-card-elevated-container-color: #1e1e1e;--mat-card-elevated-container-shape: 12px;--mat-card-filled-container-shape: 12px;--mat-card-outlined-container-shape: 12px;--mat-card-outlined-outline-width: 0px;--mat-card-outlined-outline-color: transparent;--mat-card-elevated-container-elevation: 0 2px 12px rgba(0, 0, 0, .35);--mat-card-outlined-container-elevation: 0 2px 12px rgba(0, 0, 0, .35);--mat-card-filled-container-elevation: 0 2px 12px rgba(0, 0, 0, .35);font-family:Roboto Thin,Roboto,Arial,sans-serif;display:block;line-height:1.4;box-sizing:border-box;background:var(--mat-sys-surface, #121212);color:var(--mat-sys-on-surface, #e0e0e0)}*,*:before,*:after{box-sizing:inherit}.suibi-surface{background:var(--mat-sys-surface-container-low, #1e1e1e);border:1px solid var(--mat-sys-outline-variant, #2a2a2a);border-radius:8px;padding:16px}pre{background:#1d1f21;color:#c5c8c6;padding:8px 16px;border-radius:4px}:host .mat-mdc-form-field-error,suibi-module .mat-mdc-form-field-error{color:#e72200}.horizontal-layout>div:has([style*="display: none"]){display:none!important}
@@ -1 +1 @@
1
- 0.1.0-preview.7 b4c7c60
1
+ 0.1.0-preview.8c4fa92 8c4fa92
@@ -25,12 +25,10 @@ export declare class App {
25
25
  readonly isDirty: import("@angular/core").Signal<boolean>;
26
26
  constructor();
27
27
  readonly currentPage: import("@angular/core").WritableSignal<PageId>;
28
- private lastPageInput;
29
- private readonly syncPageEffect;
30
28
  go(page: PageId): void;
31
29
  setLocale(locale: Locale): void;
32
30
  emitData(): void;
33
31
  private emitDataIfDirty;
34
- private setupAutosave;
32
+ private initAutosave;
35
33
  onValidationErrorSelected(error: ErrorObject): void;
36
34
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * AddDashedButtonComponent
3
+ * Full-width dashed call-to-action button used as the primary add action in list views.
4
+ * Styled with the brand primary colour; works in both empty and non-empty list states.
5
+ */
6
+ export declare class AddDashedButtonComponent {
7
+ label: import("@angular/core").InputSignal<string>;
8
+ clicked: import("@angular/core").OutputEmitterRef<void>;
9
+ }
@@ -1,8 +1,10 @@
1
1
  import { NaebiDataService } from '../../core/data/naebi-data.service';
2
+ import { PlanningBalanceService } from '../../core/planning/planning-balance.service';
2
3
  export declare class DataPreviewComponent {
3
4
  readonly naebi: NaebiDataService;
4
5
  private readonly host;
5
6
  private readonly emitter;
7
+ readonly planning: PlanningBalanceService;
6
8
  readonly metadataPreview: import("@angular/core").Signal<import("../../../public-api").SuibiDataEventMetadata>;
7
9
  constructor(naebi: NaebiDataService);
8
10
  emitData(): void;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * EmptyStateComponent
3
+ * Reusable centered placeholder shown when a list has no entries.
4
+ * Displays a faded icon, a primary message, and an optional hint line.
5
+ */
6
+ export declare class EmptyStateComponent {
7
+ primaryText: import("@angular/core").InputSignal<string>;
8
+ /** Optional hint displayed below the primary message. */
9
+ secondaryText: import("@angular/core").InputSignal<string>;
10
+ }
@@ -0,0 +1,69 @@
1
+ import { SafeResourceUrl } from '@angular/platform-browser';
2
+ import { PlanningBalanceService, PlanningEndpoint } from '../../core/planning/planning-balance.service';
3
+ import { MasterDataService } from '../../core/master-data/master-data.service';
4
+ import type { BalanceRow, CropRequirementRow, NutrientEntry, ValidationMessage } from '../../core/planning/planning-balance.types';
5
+ export declare class PlanningResultComponent {
6
+ readonly planning: PlanningBalanceService;
7
+ private readonly naebi;
8
+ private readonly sanitizer;
9
+ readonly masterData: MasterDataService;
10
+ readonly selectedEndpoint: import("@angular/core").WritableSignal<PlanningEndpoint>;
11
+ private readonly result;
12
+ /**
13
+ * Merges interleaved kg/% rows from totalBalance into one row per nutrient
14
+ * for use in the Section-D summary table.
15
+ */
16
+ readonly balanceRows: import("@angular/core").Signal<BalanceRow[]>;
17
+ /** Farm-wide gas emissions (NH₃, NO, N₂O, N₂). */
18
+ readonly farmEmissions: import("@angular/core").Signal<NutrientEntry[]>;
19
+ readonly validationMessages: import("@angular/core").Signal<ValidationMessage[]>;
20
+ /** Land area stats converted from m² → ha (÷ 10 000). */
21
+ readonly landStats: import("@angular/core").Signal<{
22
+ total: number;
23
+ fertilizable: number;
24
+ slurry: number;
25
+ } | null>;
26
+ /** Fodder net balance (positive = surplus, negative = deficit). */
27
+ readonly fodderTotal: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").FodderQuantity | null>;
28
+ readonly animalStockTotals: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").AnimalStock | null>;
29
+ /** Housing-type segments for the A2 table, pre-built to avoid dynamic key access in template. */
30
+ readonly animalStockSegments: import("@angular/core").Signal<{
31
+ label: string;
32
+ data: import("../../core/planning/planning-balance.types").TotalNutrientSet;
33
+ }[]>;
34
+ /** A3 equivalent: manure trading balance per product. */
35
+ readonly manureTradingBalance: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").FarmManureTrading | null>;
36
+ /** A4 equivalent: manure storage totals. */
37
+ readonly storageBalance: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").TotalNutrientSet | null>;
38
+ /** A5 equivalent: field spreading totals for key nutrients. */
39
+ readonly fieldSpreadingBalance: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").TotalNutrientSet | null>;
40
+ readonly requirementPerCultivationCategory: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").NutrientRequirementEntry[]>;
41
+ readonly totalRequirement: import("@angular/core").Signal<NutrientEntry[]>;
42
+ /**
43
+ * Merge area/yield data from fieldCultivation with nutrient requirements so
44
+ * each row has everything needed to display Section C of the PDF report.
45
+ */
46
+ readonly cropRequirementRows: import("@angular/core").Signal<CropRequirementRow[]>;
47
+ readonly fodderDetail: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").RequiredEffectiveYieldFromFodderCropland | null>;
48
+ readonly fodderEffectiveYield: import("@angular/core").Signal<import("../../core/planning/planning-balance.types").FodderQuantity | null>;
49
+ /** SafeResourceUrl for the PDF iframe, or null if no report is present. */
50
+ readonly pdfUrl: import("@angular/core").Signal<SafeResourceUrl | null>;
51
+ private _prevBlobUrl;
52
+ private readonly _blobCleanup;
53
+ /** Human-readable label for a molecular formula symbol. */
54
+ formulaLabel(f: string): string;
55
+ /** Returns CSS modifier class based on the balance percentage value. */
56
+ balancePctClass(pct: number | null): string;
57
+ /** Returns the quantity for a given formula from a nutrient entry list, or 0 if absent. */
58
+ reqValue(requirement: NutrientEntry[], formula: string): number;
59
+ /**
60
+ * Sums entries by formula for the given ordered formula list (kg unit only).
61
+ * Multiple per-product rows with the same formula are aggregated into one.
62
+ */
63
+ sumNutrients(entries: NutrientEntry[], formulas: readonly string[]): NutrientEntry[];
64
+ /** Summary chips for Sections A1–A5 (Ntot / P₂O₅ / K₂O / Mg). */
65
+ sumStockNutrients(entries: NutrientEntry[]): NutrientEntry[];
66
+ /** Summary chips for Sections C & D (N avail. / P₂O₅ / K₂O / Mg). */
67
+ sumKeyNutrients(entries: NutrientEntry[]): NutrientEntry[];
68
+ runPlanning(): void;
69
+ }
@@ -0,0 +1,48 @@
1
+ import { PageId } from '../../core/navigation/navigation.service';
2
+ /**
3
+ * WorkflowStepperComponent
4
+ * Horizontal navigation stepper for the main data-entry workflow.
5
+ *
6
+ * Design contract:
7
+ * - Uses mat-stepper as a header-only nav bar (step content is empty; content
8
+ * area is hidden via CSS so the stepper acts as a pure navigation indicator).
9
+ * - [selectedIndex] is driven by the currentPage input — no internal routing state.
10
+ * - Navigation is delegated back to App via the onNavigate callback, preserving
11
+ * the custom-element page-attribute reflection.
12
+ * - Error indicators: any page with at least one enriched validation error shows
13
+ * the error ring on its step circle. Requires STEPPER_GLOBAL_OPTIONS { showError: true }.
14
+ * - Non-workflow pages (e.g. data_preview): mat-stepper rejects out-of-bounds selectedIndex,
15
+ * so we clamp to 0; the no-active-step CSS class neutralises the visual active indicator,
16
+ * and onStepperClick delegates clicks for all headers (bypassing the stepper's
17
+ * "no-change" guard that suppresses selectedIndexChange for the currently selected step).
18
+ *
19
+ * Extension points:
20
+ * - Completed state: replace the hardcoded `false` on [completed] with a per-page
21
+ * computed once domain completion rules are defined (e.g. all required fields valid).
22
+ * - New pages: add an entry to WORKFLOW_STEPS and extend PageId.
23
+ */
24
+ export declare class WorkflowStepperComponent {
25
+ protected readonly steps: readonly {
26
+ readonly pageId: PageId;
27
+ readonly labelKey: string;
28
+ }[];
29
+ /**
30
+ * Current page from the parent. Controls which step circle is highlighted.
31
+ * Non-workflow pages (e.g. data_preview) use index 0 as a valid CDK fallback;
32
+ * the no-active-step CSS class removes the visual active indicator for those pages.
33
+ */
34
+ readonly currentPage: import("@angular/core").InputSignal<PageId>;
35
+ /**
36
+ * Navigation callback provided by App.
37
+ * Using a callback (instead of an output EventEmitter) matches the existing
38
+ * header-bar pattern and ensures the custom-element page-attribute is reflected.
39
+ */
40
+ readonly onNavigate: import("@angular/core").InputSignal<(page: PageId) => void>;
41
+ private readonly validationSvc;
42
+ protected readonly pagesWithErrors: import("@angular/core").Signal<Set<PageId>>;
43
+ protected readonly isOnWorkflowPage: import("@angular/core").Signal<boolean>;
44
+ protected readonly clampedStepIndex: import("@angular/core").Signal<number>;
45
+ protected onSelectedIndexChange(index: number): void;
46
+ protected onStepperClick(event: MouseEvent): void;
47
+ private navigateTo;
48
+ }
@@ -29,7 +29,7 @@ export declare class NaebiDataService {
29
29
  hoursPerDay: number;
30
30
  };
31
31
  stall: {
32
- stableSystem: number;
32
+ stableSystem: string;
33
33
  stableCapacity: number;
34
34
  stableVentilationType: number;
35
35
  stableAirPurification: number;
@@ -101,6 +101,10 @@ export declare class NaebiDataService {
101
101
  quantity: number;
102
102
  typeOfManureRecyclingProduct: string;
103
103
  transactionUnit: string;
104
+ manureDerivation: {
105
+ zoologicalAnimal: string;
106
+ percentageAllocation: number;
107
+ }[];
104
108
  ingredient: {
105
109
  quantity: number;
106
110
  molecularFormula: string;
@@ -115,6 +119,11 @@ export declare class NaebiDataService {
115
119
  zoologicalAnimal: string;
116
120
  percentageAllocation: number;
117
121
  }[];
122
+ ingredient: {
123
+ quantity: number;
124
+ molecularFormula: string;
125
+ unit: string;
126
+ }[];
118
127
  }[];
119
128
  };
120
129
  fieldSpreading: {
@@ -138,6 +147,7 @@ export declare class NaebiDataService {
138
147
  proportionAppliedOtherMonths: number;
139
148
  };
140
149
  fertiliser: {
150
+ descriptor: string;
141
151
  fertiliserProductCategory: string;
142
152
  quantity: number;
143
153
  transactionUnit: string;
@@ -159,8 +169,6 @@ export declare class NaebiDataService {
159
169
  }[];
160
170
  };
161
171
  lifetimePerformance: {
162
- dailyGain: number;
163
- liveWeight: number;
164
172
  milkProductionReport: number;
165
173
  };
166
174
  fodder: {
@@ -214,11 +222,13 @@ export declare class NaebiDataService {
214
222
  userSpecificPlantName: string;
215
223
  isMainCrop: boolean;
216
224
  areaSize: number;
217
- yieldPerSquareMeasure: number;
218
225
  }[];
219
226
  };
220
227
  generateReport: boolean;
221
228
  };
229
+ calculationVersion: {
230
+ version: string;
231
+ };
222
232
  }>;
223
233
  private readonly _lastEmitted;
224
234
  private readonly _dirty;
@@ -1,7 +1,9 @@
1
1
  import { Locale } from '../i18n/i18n.service';
2
- type MasterDataKeyField = 'id' | 'code';
2
+ /** The property name of the primary key in a master-data catalog entry. */
3
+ type MasterDataKeyField = string;
3
4
  interface MasterDataCatalog {
4
5
  entries: any[];
6
+ /** Property name to use as the lookup key; 'id' entries are coerced to Number. */
5
7
  key: MasterDataKeyField;
6
8
  }
7
9
  declare const MASTER_DATA: Record<string, MasterDataCatalog>;
@@ -21,5 +23,8 @@ export declare class MasterDataService {
21
23
  resolveUtilisation(id: number | string | null | undefined, locale?: Locale): string;
22
24
  resolveManureProduct(code: string | null | undefined, locale?: Locale): string;
23
25
  resolveZoologicalAnimal(code: string | null | undefined, locale?: Locale): string;
26
+ resolveCultivationCategory(code: string | null | undefined, locale?: Locale): string;
27
+ resolveAgronomicCropCategory(code: string | null | undefined, locale?: Locale): string;
28
+ resolveFeedstuffProduct(code: string | null | undefined, locale?: Locale): string;
24
29
  }
25
30
  export {};
@@ -62,6 +62,8 @@ export declare class NavigationService {
62
62
  /**
63
63
  * Set active category/tab for current page (without changing page/entry).
64
64
  * Generic method supporting any page's categorization navigation.
65
+ * No-op when page and category are already the same values to prevent
66
+ * unnecessary signal emissions that re-trigger the tab index computed.
65
67
  */
66
68
  setCategory(page: PageId, category: string): void;
67
69
  /**
@@ -0,0 +1,18 @@
1
+ import { NaebiData } from '../data/naebi-data.service';
2
+ import type { PlanningBalanceResponse } from './planning-balance.types';
3
+ export type { PlanningBalanceResponse } from './planning-balance.types';
4
+ /** Which backend to target for planning requests. */
5
+ export type PlanningEndpoint = 'ebilanz' | 'blw';
6
+ /**
7
+ * Sends NAEBI data to a planning endpoint and exposes the result as a
8
+ * signal-based resource. Call `runPlanning(data, endpoint)` to trigger a request.
9
+ *
10
+ * The ID counter ensures each call re-fetches even if the payload hasn't changed.
11
+ */
12
+ export declare class PlanningBalanceService {
13
+ private readonly _trigger;
14
+ private _nextId;
15
+ readonly planningResource: import("@angular/common/http").HttpResourceRef<PlanningBalanceResponse | undefined>;
16
+ /** Fire a new planning-balance request with the current NAEBI data payload. */
17
+ runPlanning(data: NaebiData, endpoint: PlanningEndpoint): void;
18
+ }
@@ -0,0 +1,206 @@
1
+ /**
2
+ * TypeScript interfaces for the planning-balance API response.
3
+ * These match the eBilanz / BLW response shape observed in the example data.
4
+ */
5
+ /** A single nutrient quantity entry (kg or % unit). */
6
+ export interface NutrientEntry {
7
+ molecularFormula: string;
8
+ quantity: number;
9
+ quantityCorrected?: number;
10
+ unit: string;
11
+ productFamilyType?: string;
12
+ typeOfManureRecyclingProduct?: string;
13
+ fertiliserProductCategory?: string;
14
+ }
15
+ export interface CalculationVersion {
16
+ version: string;
17
+ validFrom: string;
18
+ validTo: string;
19
+ }
20
+ export interface AreaAndYieldPerAgronomicCropCategory {
21
+ agronomicCropCategory: string;
22
+ areaSize: number;
23
+ effectiveYield: number;
24
+ isMainCrop: boolean;
25
+ isNutrientPoorFodder: boolean;
26
+ yieldPerSquareMeasure?: number;
27
+ }
28
+ export interface AreaPerCultivationType {
29
+ areaSize: number;
30
+ isMainCrop: boolean;
31
+ }
32
+ export interface AreaAndYieldPerCultivationCategory {
33
+ cultivationCategory: string;
34
+ areaAndYieldPerAgronomicCropCategory: AreaAndYieldPerAgronomicCropCategory[];
35
+ areaPerCultivationType: AreaPerCultivationType[];
36
+ }
37
+ export interface AreaPerSubCategory {
38
+ cultivationSubCategory: string;
39
+ areaSize: number;
40
+ isMainCrop: boolean;
41
+ }
42
+ export interface FieldCultivation {
43
+ areaAndYieldPerCultivationCategory: AreaAndYieldPerCultivationCategory[];
44
+ areaPerSubCategory: AreaPerSubCategory[];
45
+ fertilizableAreaSize: number;
46
+ slurrySpreadingAreaSize: number;
47
+ totalAgriculturalLandAreaSize: number;
48
+ }
49
+ export interface FodderQuantity {
50
+ quantity: number;
51
+ unit: string;
52
+ proportionNutrientPoorFodder?: number;
53
+ }
54
+ export interface FodderProduct {
55
+ typeOfFeedstuffProduct: string;
56
+ quantity: number;
57
+ unit: string;
58
+ isNutrientPoorFodder: boolean;
59
+ }
60
+ export interface ConsumptionAnimalStock {
61
+ animalCategoryPRIF: number;
62
+ averageQuantity: number;
63
+ order: string;
64
+ quantity: number;
65
+ unit: string;
66
+ }
67
+ export interface RequiredEffectiveYieldFromFodderCropland {
68
+ consumptionAnimalStock: ConsumptionAnimalStock[];
69
+ cropFromNonFodderCroplandPerProduct: FodderProduct[];
70
+ dispensePerProduct: FodderProduct[];
71
+ supplyPerProduct: FodderProduct[];
72
+ totalBalance: FodderQuantity;
73
+ totalConsumptionAnimalStock: FodderQuantity;
74
+ totalCropFromNonFodderCropland: FodderQuantity;
75
+ totalDispense: FodderQuantity;
76
+ totalSupply: FodderQuantity;
77
+ }
78
+ export interface FodderBalance {
79
+ requiredEffectiveYieldFromFodderCropland: RequiredEffectiveYieldFromFodderCropland;
80
+ totalBalance: FodderQuantity;
81
+ totalEffectiveYieldFromFodderCropland: FodderQuantity;
82
+ totalNutrientPoorFodder: FodderQuantity;
83
+ }
84
+ export interface EmissionAndAccumulationEntry {
85
+ animalCategoryPRIF: number;
86
+ order: string;
87
+ accumulation: NutrientEntry[];
88
+ emission: NutrientEntry[];
89
+ manureExcretion?: unknown[];
90
+ }
91
+ export interface AccumulationEntireExcretion {
92
+ animalCategoryPRIF: number;
93
+ order: string;
94
+ durationSumTotalCorrectedNutrientBalance: number;
95
+ accumulation: NutrientEntry[];
96
+ }
97
+ export interface TotalNutrientSet {
98
+ accumulation: NutrientEntry[];
99
+ emission?: NutrientEntry[];
100
+ }
101
+ export interface AnimalStock {
102
+ accumulationEntireExcretion: AccumulationEntireExcretion[];
103
+ emissionAndAccumulationPasture: EmissionAndAccumulationEntry[];
104
+ emissionAndAccumulationStall: EmissionAndAccumulationEntry[];
105
+ emissionAndAccumulationYard: EmissionAndAccumulationEntry[];
106
+ totalAccumulationEntireExcretion: TotalNutrientSet;
107
+ totalEmissionAndAccumulationAnimalStock: TotalNutrientSet;
108
+ totalEmissionAndAccumulationPasture: TotalNutrientSet;
109
+ totalEmissionAndAccumulationStall: TotalNutrientSet;
110
+ totalEmissionAndAccumulationYard: TotalNutrientSet;
111
+ }
112
+ export interface ManureTradingProduct {
113
+ typeOfManureRecyclingProduct: string;
114
+ quantity: number;
115
+ unit: string;
116
+ ingredient: NutrientEntry[];
117
+ }
118
+ export interface FarmManureTrading {
119
+ balancePerProduct: ManureTradingProduct[];
120
+ dispensePerProduct: ManureTradingProduct[];
121
+ supplyPerProduct: ManureTradingProduct[];
122
+ totalBalance: {
123
+ ingredient: NutrientEntry[];
124
+ };
125
+ }
126
+ export interface NutrientRequirementEntry {
127
+ agronomicCropCategory?: string;
128
+ cultivationCategory?: string;
129
+ isMainCrop?: boolean;
130
+ requirement: NutrientEntry[];
131
+ }
132
+ export interface FieldCultivationNutrients {
133
+ nutrientTransferUnfertilizedCultivation: NutrientEntry[];
134
+ requirementPerAgronomicCropCategory: NutrientRequirementEntry[];
135
+ requirementPerCultivationCategory: NutrientRequirementEntry[];
136
+ totalRequirement: NutrientEntry[];
137
+ }
138
+ export interface FieldSpreading {
139
+ emissionAndAccumulationFieldSpreading: TotalNutrientSet;
140
+ totalEmissionAndAccumulationFieldSpreading: TotalNutrientSet;
141
+ }
142
+ export interface StorageBalance {
143
+ emissionAndAccumulationManureStorage: TotalNutrientSet;
144
+ totalEmissionAndAccumulationManureStorage: TotalNutrientSet;
145
+ }
146
+ export interface NutrientBalance {
147
+ animalStock: AnimalStock;
148
+ farmManureTrading: FarmManureTrading;
149
+ fieldCultivation: FieldCultivationNutrients;
150
+ fieldSpreading: FieldSpreading;
151
+ storage: StorageBalance;
152
+ /** Final per-nutrient balance figures: kg lines + % lines interleaved. */
153
+ totalBalance: NutrientEntry[];
154
+ /** Farm-wide gas emissions (NH3, NO, N2O, N2). */
155
+ totalEmissionFarm: NutrientEntry[];
156
+ nutrientBalanceTMP?: unknown[];
157
+ }
158
+ export interface NutrientCycle {
159
+ creationDateTime: string;
160
+ facilitySpecificProducts: {
161
+ manureRecyclingProduct: unknown[];
162
+ };
163
+ fieldCultivation: FieldCultivation;
164
+ fodderBalance: FodderBalance;
165
+ nutrientBalance: NutrientBalance;
166
+ version: string;
167
+ /** Base64-encoded PDF report, if returned by the endpoint. */
168
+ report?: string;
169
+ }
170
+ export interface ValidationMessageDetail {
171
+ designation_deu: string;
172
+ designation_eng: string;
173
+ designation_fra: string;
174
+ designation_ita: string;
175
+ }
176
+ export interface ValidationMessage {
177
+ field: string;
178
+ type: string;
179
+ detail: ValidationMessageDetail;
180
+ }
181
+ /** Full response from the planning-balance endpoint. */
182
+ export interface PlanningBalanceResponse {
183
+ calculationVersion: CalculationVersion;
184
+ nutrientCycle: NutrientCycle;
185
+ validationMessage: ValidationMessage[];
186
+ }
187
+ /** Merged kg + % row for the final balance table (Section D). */
188
+ export interface BalanceRow {
189
+ molecularFormula: string;
190
+ quantity: number;
191
+ quantityCorrected: number;
192
+ quantityPct: number | null;
193
+ quantityCorrectedPct: number | null;
194
+ unit: 'kg';
195
+ }
196
+ /** Crop requirement row enriched with area and yield for display (Section C). */
197
+ export interface CropRequirementRow {
198
+ cropCode: string;
199
+ cultivationCategory: string;
200
+ isMainCrop: boolean;
201
+ areaHa: number;
202
+ effectiveYield: number;
203
+ /** kg/ha yield per square measure field (m² basis), converted to dt/ha for display. */
204
+ yieldDtHa: number | null;
205
+ requirement: NutrientEntry[];
206
+ }
@@ -5,14 +5,14 @@
5
5
  * All master data is embedded statically at compile time - no runtime HTTP calls.
6
6
  */
7
7
  /**
8
- * Derives permitted stable systems (husbandry type IDs) for a given animal category.
8
+ * Derives permitted stable systems (stableSystem enum strings) for a given animal category.
9
9
  *
10
10
  * @param animalCategoryPRIF - The PRIF animal category ID
11
- * @returns Array of permitted husbandry type IDs (stable systems)
11
+ * @returns Array of permitted stableSystem enum strings (e.g. 'HUS_TETHER')
12
12
  */
13
- export declare function derivePermittedStableSystems(animalCategoryPRIF: number | null | undefined): number[];
13
+ export declare function derivePermittedStableSystems(animalCategoryPRIF: number | null | undefined): string[];
14
14
  /**
15
15
  * Pre-computed map for performance (memoized at module load).
16
- * Maps animalCategoryPRIF -> array of permitted stableSystem values.
16
+ * Maps animalCategoryPRIF -> array of permitted stableSystem enum strings.
17
17
  */
18
- export declare const PERMITTED_STABLE_SYSTEMS: Record<number, number[]>;
18
+ export declare const PERMITTED_STABLE_SYSTEMS: Record<number, string[]>;
@@ -31,10 +31,7 @@ export declare class GlobalValidationService {
31
31
  private readonly dataSvc;
32
32
  private readonly ajv;
33
33
  private readonly validateFn;
34
- private readonly rawErrors;
35
34
  readonly errors: import("@angular/core").Signal<EnrichedValidationError[]>;
36
- constructor();
37
- validate(): void;
38
35
  private consolidateErrors;
39
36
  private enrichErrors;
40
37
  private inferCategory;
@@ -2,8 +2,8 @@ import { Locale } from './core/i18n/i18n.service';
2
2
  import { PageId } from './core/navigation/navigation.service';
3
3
  /**
4
4
  * HeaderBarComponent
5
- * - Displays navigation buttons for page switching.
6
- * - Emits events via provided callback inputs (parent supplies functions) to avoid outputs overhead inside shadow root.
5
+ * Top app bar: application branding, utility actions (data preview, save indicator).
6
+ * Main workflow navigation is delegated to WorkflowStepperComponent below the toolbar.
7
7
  */
8
8
  export declare class HeaderBarComponent {
9
9
  locale: import("@angular/core").InputSignal<Locale>;
@@ -6,6 +6,7 @@ import { LogicalGroupRenderer } from '../renderers/layout/group/logical-group.re
6
6
  import { RankedTester } from '@jsonforms/core';
7
7
  import { ConstraintLayoutRenderer } from '../renderers/layout/constraint/constraint-layout.renderer';
8
8
  import { SelectedCategoryCategorizationRenderer } from '../renderers/layout/categorization/selected-category-categorization.renderer';
9
+ import { CustomArrayLayoutRenderer } from '../renderers/layout/array/array-layout.renderer';
9
10
  export declare const CUSTOM_JSONFORMS_RENDERERS: ({
10
11
  tester: RankedTester;
11
12
  renderer: typeof ConstraintLayoutRenderer;
@@ -27,4 +28,7 @@ export declare const CUSTOM_JSONFORMS_RENDERERS: ({
27
28
  } | {
28
29
  tester: RankedTester;
29
30
  renderer: typeof CodeListSelectRenderer;
31
+ } | {
32
+ tester: RankedTester;
33
+ renderer: typeof CustomArrayLayoutRenderer;
30
34
  })[];
@@ -0,0 +1,43 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { JsonFormsAbstractControl, JsonFormsAngularService } from '@jsonforms/angular';
3
+ import { ArrayLayoutProps, ArrayTranslations, JsonFormsState, OwnPropsOfRenderer, RankedTester, StatePropsOfArrayLayout, UISchemaElement, UISchemaTester } from '@jsonforms/core';
4
+ /**
5
+ * CustomArrayLayoutRenderer
6
+ * Overrides the stock JSONForms `ArrayLayoutRenderer` (rank 4 → this is rank 5) to apply
7
+ * the project UX pattern: centered empty-state placeholder when the array has no entries,
8
+ * and the full-width dashed add-button always anchored below the list.
9
+ *
10
+ * The add button label is driven by `translations.addTooltip` resolved via the JSONForms
11
+ * i18n pipeline — configure per-array labels there.
12
+ */
13
+ export declare class CustomArrayLayoutRenderer extends JsonFormsAbstractControl<StatePropsOfArrayLayout> implements OnInit {
14
+ noData: boolean;
15
+ /** Indices 0..n-1 used to render per-item cards and drive sort-button disabled state. */
16
+ indices: number[];
17
+ translations: ArrayTranslations;
18
+ showSortButtons: boolean;
19
+ addItem: (path: string, value: unknown) => () => void;
20
+ moveItemUp: (path: string, index: number) => () => void;
21
+ moveItemDown: (path: string, index: number) => () => void;
22
+ removeItems: (path: string, toDelete: number[]) => () => void;
23
+ uischemas: {
24
+ tester: UISchemaTester;
25
+ uischema: UISchemaElement;
26
+ }[];
27
+ constructor(jsonFormsService: JsonFormsAngularService);
28
+ get emptyText(): string;
29
+ get addLabel(): string;
30
+ mapToProps(state: JsonFormsState): StatePropsOfArrayLayout & {
31
+ translations: ArrayTranslations;
32
+ };
33
+ mapAdditionalProps(props: ArrayLayoutProps & {
34
+ translations: ArrayTranslations;
35
+ }): void;
36
+ remove(index: number): void;
37
+ add(): void;
38
+ up(index: number): void;
39
+ down(index: number): void;
40
+ ngOnInit(): void;
41
+ getProps(index: number): OwnPropsOfRenderer;
42
+ }
43
+ export declare const customArrayLayoutRendererTester: RankedTester;
@@ -19,12 +19,15 @@ export declare class SelectedCategoryCategorizationRenderer extends JsonFormsBas
19
19
  categoryLabels: string[];
20
20
  private readonly categoryKeyToIndex;
21
21
  private readonly indexToCategoryKey;
22
+ private _prevCategorySignature;
22
23
  readonly selectedTabIndex: import("@angular/core").Signal<number>;
23
24
  ngOnInit(): void;
24
25
  /**
25
26
  * Build bidirectional category key ↔ tab index mapping from UI schema.
26
27
  * Reads options.categoryKey from each visible Category element.
27
28
  * Example: { base: 0, formOfDetention: 1, feeding: 2 }
29
+ * Skips signal writes when the tab structure hasn't changed (pure data changes
30
+ * fire $state on every keystroke; no need to mark selectedTabIndex stale each time).
28
31
  */
29
32
  private buildCategoryMappings;
30
33
  onTabChange(newIndex: number): void;