@forgeroute/ui 0.3.8 → 0.3.9

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.
@@ -105,6 +105,16 @@ export interface ColumnDef {
105
105
  label: string;
106
106
  sortable?: boolean;
107
107
  defaultVisible?: boolean;
108
+ /**
109
+ * Wire name of this column's FILTER, when it must differ from `key`. Defaults to `key` (unset = unchanged behaviour).
110
+ * Replaces `key` only for: the column-filter query param on rows and export requests, the key read from the
111
+ * `/filter-counts` response for this column's options/counts (also the bulk "Change <column>" options), and the key
112
+ * stored in saved views (a view saved under the plain `key` still restores). Everything else stays on `key`:
113
+ * sort (`sort=<key>`), cell values, visibility, `lockedColumn`, `searchFields`, `bulkUpdateOptions` and the
114
+ * `/bulk/<field>` request body. It also names the header filter and the phone-card filter chips' request param. It must not equal a reserved table param (`page`, `size`, `search`, `searchFields`, `sort`, `direction`, `filter`) nor an `Object.prototype` member name such as `constructor` — there is no runtime guard. Example: `{ key: 'direction', filterParam: 'messageDirection' }` keeps the filter
115
+ * from colliding with the table's own `direction=asc|desc` sort param.
116
+ */
117
+ filterParam?: string;
108
118
  /** If true, this column's label appears in the search input placeholder when the column is visible. */
109
119
  searchable?: boolean;
110
120
  /** Values a bulk "Change <label>" may set. When omitted the options come from /filter-counts.
@@ -615,17 +625,56 @@ export declare class MoreMenuComponent {
615
625
  protected readonly openUp: import("@angular/core").WritableSignal<boolean>;
616
626
  /** Caps the dropdown to the space on the side it opens, so it never runs off-screen; it scrolls instead. */
617
627
  protected readonly maxHeight: import("@angular/core").WritableSignal<number | null>;
628
+ /** Caps a fixed dropdown to the visible width minus 8px each side (the CSS cap uses 100vw, which includes classic scrollbars). */
629
+ protected readonly maxWidth: import("@angular/core").WritableSignal<number | null>;
630
+ /**
631
+ * Viewport placement (px) of a `position: fixed` dropdown; null = the dropdown is positioned absolutely under the trigger
632
+ * (an ancestor with a transform / filter / contain makes `fixed` unusable there).
633
+ */
634
+ protected readonly placement: import("@angular/core").WritableSignal<{
635
+ top: number | null;
636
+ bottom: number | null;
637
+ right: number;
638
+ } | null>;
618
639
  private readonly _el;
640
+ private readonly _cdr;
641
+ /** Width of the window when the menu opened: a resize that keeps it (the on-screen keyboard, a collapsing address bar) does not close the menu. */
642
+ private _openWidth;
643
+ constructor();
619
644
  protected readonly visibleActions: () => RowAction[];
620
645
  protected resolveIcon(action: RowAction): string;
621
646
  protected isDisabled(action: RowAction): boolean;
622
647
  toggle(event: Event): void;
648
+ /**
649
+ * Decides where the open dropdown goes: below the trigger when its real height fits, otherwise above when there is more
650
+ * room there, capped to the room on that side (it scrolls inside). Measured against the visible window (the on-screen
651
+ * keyboard and pinch-zoom shrink it, and the home-indicator safe area is kept clear), or, when `position: fixed` is not
652
+ * usable, against the nearest scrolling ancestor. A fixed dropdown also stays inside the screen horizontally.
653
+ */
654
+ private _place;
655
+ /**
656
+ * The layout viewport: the box `position: fixed` offsets are measured from. It excludes scrollbars and ignores pinch-zoom,
657
+ * unlike `window.innerWidth / innerHeight`.
658
+ */
659
+ private _layoutViewport;
660
+ /** The part of the page that is actually visible (shrinks with the on-screen keyboard and pinch-zoom on phones). */
661
+ private _viewport;
662
+ /** Height of the bottom safe area (home indicator) in px; 0 where there is none. */
663
+ protected _safeAreaBottom(): number;
623
664
  onActionClick(action: RowAction, event: Event): void;
624
665
  onDocumentClick(): void;
666
+ /** A touch or mouse press anywhere outside the menu closes it (more reliable than a click on phones: iOS does not send clicks for plain page areas). */
667
+ onDocumentPointerDown(event: Event): void;
625
668
  onEscape(): void;
626
669
  onArrow(event: Event, dir: 1 | -1): void;
627
670
  /** Visible top/bottom of the nearest scrolling ancestor, clipped to the viewport. */
628
671
  private _visibleBounds;
672
+ /**
673
+ * False when an ancestor creates a containing block for `position: fixed` (transform and the individual translate / rotate / scale,
674
+ * filter, perspective, backdrop-filter, contain, container-type, content-visibility, will-change naming any of those).
675
+ */
676
+ private _fixedPositionable;
677
+ private _dropdownEl;
629
678
  private _menuItems;
630
679
  private _trigger;
631
680
  static ɵfac: i0.ɵɵFactoryDeclaration<MoreMenuComponent, never>;
@@ -834,7 +883,7 @@ export declare class SelectComponent implements ControlValueAccessor, Validator,
834
883
  readonly error: import("@angular/core").InputSignal<string>;
835
884
  /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
836
885
  readonly showErrors: import("@angular/core").InputSignal<boolean>;
837
- readonly size: import("@angular/core").InputSignal<"sm" | "default">;
886
+ readonly size: import("@angular/core").InputSignal<"default" | "sm">;
838
887
  readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
839
888
  private readonly _cvaDisabled;
840
889
  protected readonly disabled: import("@angular/core").Signal<boolean>;
@@ -1372,6 +1421,11 @@ export declare class DataTableComponent<T extends Record<string, any>> implement
1372
1421
  protected onSort(field: string): void;
1373
1422
  protected onPageChange(p: number): void;
1374
1423
  protected onTabChange(value: string): void;
1424
+ /**
1425
+ * Wire name of a column's filter: `filterParam` when set, else the column `key`. Used ONLY for the column-filter query
1426
+ * param, the /filter-counts lookup, `_colFilterValues` and saved views (never for sort, row data, bulk fields).
1427
+ */
1428
+ protected _filterName(col: ColumnDef): string;
1375
1429
  protected onColFilterChange(column: string, values: string[]): void;
1376
1430
  protected clearFilters(): void;
1377
1431
  protected getColFilter(col: ColumnDef): {
@@ -1685,7 +1739,7 @@ export declare class ModalComponent implements OnInit, OnDestroy {
1685
1739
  readonly title: import("@angular/core").InputSignal<string>;
1686
1740
  readonly description: import("@angular/core").InputSignal<string>;
1687
1741
  readonly maxWidth: import("@angular/core").InputSignal<string>;
1688
- readonly bodyOverflow: import("@angular/core").InputSignal<"auto" | "visible" | "hidden">;
1742
+ readonly bodyOverflow: import("@angular/core").InputSignal<"hidden" | "auto" | "visible">;
1689
1743
  readonly close: import("@angular/core").OutputEmitterRef<void>;
1690
1744
  protected readonly titleId: string;
1691
1745
  private readonly el;
@@ -1843,7 +1897,7 @@ export declare class AudioPlayerComponent {
1843
1897
  /** Accessible name of the player. */
1844
1898
  readonly ariaLabel: import("@angular/core").InputSignal<string>;
1845
1899
  /** How much to load before play: 'metadata' (default), 'auto' or 'none'. */
1846
- readonly preload: import("@angular/core").InputSignal<"auto" | "none" | "metadata">;
1900
+ readonly preload: import("@angular/core").InputSignal<"none" | "auto" | "metadata">;
1847
1901
  /** Fires when the browser can't load or decode the source. */
1848
1902
  readonly playbackError: import("@angular/core").OutputEmitterRef<void>;
1849
1903
  protected readonly failed: import("@angular/core").WritableSignal<boolean>;
@@ -1908,7 +1962,7 @@ export declare class TooltipDirective {
1908
1962
  /** Tooltip text; empty or null disables the tooltip. */
1909
1963
  readonly uiTooltip: import("@angular/core").InputSignal<string | null | undefined>;
1910
1964
  /** Preferred side; flips to the other side when there is no room. */
1911
- readonly tooltipPosition: import("@angular/core").InputSignal<"top" | "bottom">;
1965
+ readonly tooltipPosition: import("@angular/core").InputSignal<"bottom" | "top">;
1912
1966
  private readonly host;
1913
1967
  private readonly doc;
1914
1968
  private bubble;
@@ -2111,7 +2165,7 @@ export declare class ButtonComponent {
2111
2165
  readonly color: import("@angular/core").InputSignal<string | undefined>;
2112
2166
  readonly active: import("@angular/core").InputSignal<boolean>;
2113
2167
  readonly size: import("@angular/core").InputSignal<"sm" | "md" | "xs" | "lg">;
2114
- readonly type: import("@angular/core").InputSignal<"button" | "reset" | "submit">;
2168
+ readonly type: import("@angular/core").InputSignal<"reset" | "submit" | "button">;
2115
2169
  readonly disabled: import("@angular/core").InputSignal<boolean>;
2116
2170
  readonly loading: import("@angular/core").InputSignal<boolean>;
2117
2171
  readonly fullWidth: import("@angular/core").InputSignal<boolean>;
@@ -2548,6 +2602,8 @@ export interface TemplateItem {
2548
2602
  subject: string | null;
2549
2603
  body: string;
2550
2604
  isActive?: boolean;
2605
+ /** Set when the API says whether this is a built-in system template (true) or one the company wrote (false); drives the System / Custom badge. Absent = no badge. */
2606
+ isSystem?: boolean;
2551
2607
  activeFrom?: string | null;
2552
2608
  activeTo?: string | null;
2553
2609
  useAllYear?: boolean;
@@ -2906,10 +2962,268 @@ export declare class ComboboxComponent<T = unknown> implements ControlValueAcces
2906
2962
  "blurred": "blurred";
2907
2963
  }, never, never, true, never>;
2908
2964
  }
2965
+ export interface RadioOption {
2966
+ value: string;
2967
+ label: string;
2968
+ description?: string;
2969
+ disabled?: boolean;
2970
+ }
2971
+ /**
2972
+ * Group of native radio buttons inside a `<fieldset>` (+ `<legend>` = `label`), a ControlValueAccessor (string value, `''`
2973
+ * = nothing selected). Arrow keys move and select natively because all radios share one `name`.
2974
+ * Built-in validation: `required` -> "<label> is required."; a non-empty value that is not one of the `options` ->
2975
+ * "Select a valid option." (not checked while `options` is empty). Disabled groups are never invalid.
2976
+ *
2977
+ * Validity API (same on every ui input): Angular `Validator`, signals `invalid` + `errorMessage`, `invalidChange` output,
2978
+ * provides `UiFieldValidity`. Messages show after the group lost focus or while `[showErrors]="true"`; a host `[error]` wins.
2979
+ */
2980
+ export declare class RadioGroupComponent implements ControlValueAccessor, Validator, UiFieldValidity {
2981
+ readonly label: import("@angular/core").InputSignal<string>;
2982
+ readonly options: import("@angular/core").InputSignal<RadioOption[]>;
2983
+ readonly required: import("@angular/core").InputSignal<boolean>;
2984
+ readonly hint: import("@angular/core").InputSignal<string>;
2985
+ readonly error: import("@angular/core").InputSignal<string>;
2986
+ /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
2987
+ readonly showErrors: import("@angular/core").InputSignal<boolean>;
2988
+ readonly orientation: import("@angular/core").InputSignal<"vertical" | "horizontal">;
2989
+ /** Native `name` shared by the radios; a unique one is generated when omitted. */
2990
+ readonly name: import("@angular/core").InputSignal<string>;
2991
+ protected readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
2992
+ private readonly _cvaDisabled;
2993
+ protected readonly disabled: import("@angular/core").Signal<boolean>;
2994
+ private readonly _generatedName;
2995
+ protected get _name(): string;
2996
+ protected readonly _descId: string;
2997
+ protected readonly _value: import("@angular/core").WritableSignal<string>;
2998
+ private readonly _reveal;
2999
+ private readonly _issue;
3000
+ /** True while the value breaks a built-in rule or the host passed an `[error]`. */
3001
+ readonly invalid: import("@angular/core").Signal<boolean>;
3002
+ /** Message of the first broken built-in rule ('' when valid), shown or not. */
3003
+ readonly errorMessage: import("@angular/core").Signal<string>;
3004
+ /** Emits whenever the field becomes invalid / valid. */
3005
+ readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
3006
+ protected readonly _activeError: import("@angular/core").Signal<string>;
3007
+ private _onValidatorChange;
3008
+ constructor();
3009
+ /** Re-run the form control's validation when a rule input (required, options) changes. */
3010
+ ngOnChanges(): void;
3011
+ validate(control: AbstractControl): ValidationErrors | null;
3012
+ registerOnValidatorChange(fn: () => void): void;
3013
+ private _onChange;
3014
+ private _onTouched;
3015
+ writeValue(val: string): void;
3016
+ registerOnChange(fn: (v: string) => void): void;
3017
+ registerOnTouched(fn: () => void): void;
3018
+ setDisabledState(d: boolean): void;
3019
+ protected onSelect(value: string): void;
3020
+ /** Touched once focus leaves the whole group (moving between its radios does not count). */
3021
+ protected onFocusOut(event: FocusEvent): void;
3022
+ private _check;
3023
+ static ɵfac: i0.ɵɵFactoryDeclaration<RadioGroupComponent, never>;
3024
+ static ɵcmp: i0.ɵɵComponentDeclaration<RadioGroupComponent, "ui-radio-group", never, {
3025
+ "label": {
3026
+ "alias": "label";
3027
+ "required": false;
3028
+ "isSignal": true;
3029
+ };
3030
+ "options": {
3031
+ "alias": "options";
3032
+ "required": false;
3033
+ "isSignal": true;
3034
+ };
3035
+ "required": {
3036
+ "alias": "required";
3037
+ "required": false;
3038
+ "isSignal": true;
3039
+ };
3040
+ "hint": {
3041
+ "alias": "hint";
3042
+ "required": false;
3043
+ "isSignal": true;
3044
+ };
3045
+ "error": {
3046
+ "alias": "error";
3047
+ "required": false;
3048
+ "isSignal": true;
3049
+ };
3050
+ "showErrors": {
3051
+ "alias": "showErrors";
3052
+ "required": false;
3053
+ "isSignal": true;
3054
+ };
3055
+ "orientation": {
3056
+ "alias": "orientation";
3057
+ "required": false;
3058
+ "isSignal": true;
3059
+ };
3060
+ "name": {
3061
+ "alias": "name";
3062
+ "required": false;
3063
+ "isSignal": true;
3064
+ };
3065
+ "_disabledInput": {
3066
+ "alias": "disabled";
3067
+ "required": false;
3068
+ "isSignal": true;
3069
+ };
3070
+ }, {
3071
+ "invalidChange": "invalidChange";
3072
+ }, never, never, true, never>;
3073
+ }
3074
+ /**
3075
+ * Types and pure helpers for the signer side of sending documents (docs/send-documents-contract.md, Addendum 2026-10-19).
3076
+ * Everything here is app-agnostic: the roles are `signer1 .. signer4`, labels / names come from the host.
3077
+ */
3078
+ /** A CUSTOMER signer role. The countersigner (the sending user) is never a role: it is the document's own setting. */
3079
+ export type SignerRole = 'signer1' | 'signer2' | 'signer3' | 'signer4';
3080
+ /** All roles, in signing order (the order is strictly sequential by role number). */
3081
+ export declare const SIGNER_ROLES: readonly SignerRole[];
3082
+ /** The part of a document the host's `resolveRoles` callback is called with. */
3083
+ export interface DocumentRolesTarget {
3084
+ id: string;
3085
+ title: string;
3086
+ fileName: string | null;
3087
+ }
3088
+ /**
3089
+ * Turns the signer section on (`documentSigners` of `ui-send-message-panel`). `null` / not passed = the panel is the plain single-recipient
3090
+ * panel and nothing about signers is shown or sent.
3091
+ */
3092
+ export interface DocumentSignersConfig {
3093
+ /** Largest number of customer signers the panel accepts (roles above it are ignored). Default 4. */
3094
+ maxSigners?: number;
3095
+ /** Labels per role. Default `Signer 1` .. `Signer 4`. */
3096
+ roleLabels?: Partial<Record<SignerRole, string>>;
3097
+ /** May one person fill two roles? Default false. */
3098
+ allowSameContactInRoles?: boolean;
3099
+ /** Must every further signer have an email address (the chain emails each signer)? Default true; `false` only lets Send through with a warning-free row (the server then decides). */
3100
+ requireSignerEmail?: boolean;
3101
+ /** Name shown in the read-only countersign line ("Countersigned by <name> after all signers."). Default `you`. */
3102
+ countersignerName?: string;
3103
+ /**
3104
+ * Reads the customer roles a document defines when its `GET /documents` row has no `signerRoles` key (an app that keeps its
3105
+ * placements elsewhere). Called once per chosen document, and again on "Retry". A failure blocks Send and offers a retry. An empty
3106
+ * list = the document has no signature fields (informational).
3107
+ */
3108
+ resolveRoles?: (doc: DocumentRolesTarget) => Observable<SignerRole[]>;
3109
+ }
3110
+ /** One entry of `documents.signers` (present only for a document with MORE THAN ONE customer signer, always complete). */
3111
+ export interface SendSigner {
3112
+ role: SignerRole;
3113
+ contactId: string;
3114
+ name: string;
3115
+ email: string | null;
3116
+ /** 1..N, equal to the role number (strictly sequential). */
3117
+ order: number;
3118
+ }
3119
+ /** Values the host has for THIS send, keyed by the keys it declares in `documentContextTypes` (e.g. `{ propertyId: '…' }`). */
3120
+ export type SendContext = Record<string, string>;
3121
+ /** One context key the app's backend accepts. */
3122
+ export interface ContextTypeDef {
3123
+ key: string;
3124
+ label: string;
3125
+ }
3126
+ /** What `documentMergeCheck` sends (default route `POST <baseUrl>/documents/merge-check`). */
3127
+ export interface MergeCheckRequest {
3128
+ documentIds: string[];
3129
+ customerId?: string;
3130
+ signers?: SendSigner[];
3131
+ context?: SendContext;
3132
+ }
3133
+ /** One data field that would be left empty. */
3134
+ export interface MergeCheckEmptyField {
3135
+ key: string;
3136
+ label: string;
3137
+ page?: number;
3138
+ /** `NO_CONTEXT` | `NO_DATA` | `UNKNOWN_PATH` (other values are shown generically). */
3139
+ reason?: string;
3140
+ /** Optional plain-language reason from the server ("no property selected"); wins over the generic text of `reason`. */
3141
+ detail?: string;
3142
+ }
3143
+ export interface MergeCheckResult {
3144
+ documents: {
3145
+ documentId: string;
3146
+ title?: string;
3147
+ empty: MergeCheckEmptyField[];
3148
+ }[];
3149
+ }
3150
+ /** A host function that runs the merge check itself (instead of the default route). */
3151
+ export type MergeCheckFn = (req: MergeCheckRequest) => Observable<MergeCheckResult>;
3152
+ /** The structural part of a chosen document the helpers below read. */
3153
+ export interface SignerDocLike {
3154
+ id: string;
3155
+ title: string;
3156
+ requiresCountersign?: boolean;
3157
+ signerRoles?: SignerRole[];
3158
+ hasMapping?: boolean;
3159
+ hasDataFields?: boolean;
3160
+ }
3161
+ /** Where the roles of a document without a `signerRoles` key stand when the host resolves them. */
3162
+ export interface RoleState {
3163
+ status: 'loading' | 'ready' | 'error';
3164
+ roles: SignerRole[];
3165
+ }
3166
+ /** What the signer logic concluded for the chosen documents (only on the value when `documentSigners` is on). */
3167
+ export interface DocumentSignerInfo {
3168
+ /** `ready` once every document's roles are known; `loading` / `error` block Send. */
3169
+ status: 'loading' | 'ready' | 'error';
3170
+ /** Every chosen document has no signature fields: the send is informational (view-only). */
3171
+ informational: boolean;
3172
+ /** Customer roles of the ONE chosen document (always starting at signer1, no gaps). Empty for several documents / informational. */
3173
+ roles: SignerRole[];
3174
+ /** Exactly one document, with more than one customer signer. */
3175
+ multiSigner: boolean;
3176
+ /** A document that is sent for signing requires the sender's countersignature. */
3177
+ countersign: boolean;
3178
+ /** Several documents are chosen and one of them has several signers (it still goes to the one recipient). */
3179
+ multiDocumentNote: boolean;
3180
+ /** Under the document chip: what the mapping covers ('' when unknown). */
3181
+ fieldsLine: string;
3182
+ }
3183
+ export declare const SIGNER_ROLE_LABEL_DEFAULT: (role: SignerRole) => string;
3184
+ export declare function roleNumber(role: SignerRole): number;
3185
+ /** The label of a role: the host's `roleLabels` entry, else `Signer N`. */
3186
+ export declare function signerRoleLabel(role: SignerRole, cfg?: DocumentSignersConfig | null): string;
3187
+ /** Valid roles only (`signer1..N`, N ≤ maxSigners), unique, sorted. Anything else is dropped. */
3188
+ export declare function normalizeRoles(raw: unknown, maxSigners?: number): SignerRole[];
3189
+ /**
3190
+ * The customer roles a send needs from a document's saved roles: signer1 is always the recipient, and the roles run without gaps up to
3191
+ * the highest saved one (a partial list is never sent). `[]` stays `[]` (no signature fields).
3192
+ */
3193
+ export declare function effectiveRoles(saved: SignerRole[]): SignerRole[];
3194
+ /** True when the document has mapped data fields (the pre-send "fields that will be empty" check applies to it only). */
3195
+ export declare function hasMappedDataFields(doc: SignerDocLike): boolean;
3196
+ /** What the signer logic concludes for the chosen documents. `null` = `documentSigners` is off or nothing is chosen. */
3197
+ export declare function describeDocumentSigners(docs: SignerDocLike[], states: Record<string, RoleState>, cfg: DocumentSignersConfig | null | undefined): DocumentSignerInfo | null;
3198
+ /** The read-only countersign line ('' = not shown). */
3199
+ export declare function countersignLine(info: DocumentSignerInfo | null, cfg: DocumentSignersConfig | null | undefined, viaDocuSign: boolean): string;
3200
+ export interface SignerPick {
3201
+ id: string;
3202
+ name: string;
3203
+ email?: string | null;
3204
+ }
3205
+ /** The complete `signers` list (recipient first), or null while any role has no contact. */
3206
+ export declare function buildSigners(roles: SignerRole[], recipient: SignerPick, picks: Partial<Record<SignerRole, SignerPick | null>>): SendSigner[] | null;
3207
+ /**
3208
+ * The first problem per role (`''` = fine) in signing order: empty → `<Role label> is required.`, no email → `<Name> has no email address.`,
3209
+ * the same person twice (unless allowed) → `<Name> is already <Earlier role label>.` on the later row.
3210
+ */
3211
+ export declare function signerProblems(roles: SignerRole[], recipient: SignerPick, picks: Partial<Record<SignerRole, SignerPick | null>>, cfg: DocumentSignersConfig | null | undefined): Partial<Record<SignerRole, string>>;
3212
+ /** Only the declared context keys, with non-blank values; `undefined` when nothing is left. */
3213
+ export declare function forwardContext(ctx: SendContext | null | undefined, types: readonly ContextTypeDef[]): {
3214
+ context?: SendContext;
3215
+ dropped: string[];
3216
+ };
3217
+ /** One merge-check field as text: `Property Address (no property selected)`. */
3218
+ export declare function mergeFieldText(f: MergeCheckEmptyField): string;
3219
+ /** The warning lines of a merge-check answer: one line for one document, `<title>: …` per document for several. Nothing when nothing is empty. */
3220
+ export declare function mergeWarningLines(res: MergeCheckResult | null | undefined, docTitles: Record<string, string>): string[];
2909
3221
  /** What the sender wants done with the chosen documents. Same values as the backend (`ESIGN` | `ATTACH` | `BOTH`). */
2910
3222
  export type DocumentSendPurpose = 'ESIGN' | 'ATTACH' | 'BOTH';
2911
3223
  /** How the request reaches the recipient — derived from the channel: the Email tab sends `EMAIL`, the Text tab `TEXT`. */
2912
3224
  export type DocumentSendDelivery = 'EMAIL' | 'TEXT';
3225
+ /** Who sends a signature request: the app's own e-signature (`NATIVE`) or DocuSign. */
3226
+ export type DocumentSignatureProvider = 'NATIVE' | 'DOCUSIGN';
2913
3227
  /** One document from `GET <baseUrl>/documents`, reduced to what the picker needs. */
2914
3228
  export interface DocumentOption {
2915
3229
  id: string;
@@ -2917,13 +3231,104 @@ export interface DocumentOption {
2917
3231
  fileName: string | null;
2918
3232
  /** True when the document has a stored file (so it can be attached to an email). */
2919
3233
  hasFile: boolean;
3234
+ /** Only present (and true) when the row says the document needs the sender's countersignature (`requiresCountersign` on the `GET /documents` row): then a DocuSign send offers "Require my countersignature after client signs". */
3235
+ requiresCountersign?: boolean;
3236
+ /** Only with `documentSigners`: the document's customer roles from the `GET /documents` row (`signerRoles`). `[]` = no signature fields (informational). */
3237
+ signerRoles?: SignerRole[];
3238
+ /** The row says the document has saved placements of any kind (drives the "Fields placed for N signers" line and the merge check). */
3239
+ hasMapping?: boolean;
3240
+ /** The row says the document has mapped DATA fields (the pre-send merge check applies to it); when absent, `hasMapping` stands in. */
3241
+ hasDataFields?: boolean;
3242
+ /** Only for an envelope's document (`DocumentSeed.status`). */
3243
+ status?: string;
3244
+ }
3245
+ /** A document the form starts with (`initialDocuments`). `hasFile` defaults to true. */
3246
+ export interface DocumentSeed {
3247
+ id: string;
3248
+ title: string;
3249
+ fileName?: string | null;
3250
+ hasFile?: boolean;
3251
+ requiresCountersign?: boolean;
3252
+ signerRoles?: SignerRole[];
3253
+ hasMapping?: boolean;
3254
+ hasDataFields?: boolean;
3255
+ /** An envelope's document that is not `ACTIVE` (e.g. `ARCHIVED`) blocks the send: "<title> is archived, so this envelope can't be sent. …". */
3256
+ status?: string;
3257
+ }
3258
+ /**
3259
+ * An existing envelope the panel sends (`documentEnvelope`): its documents are fixed (no search, no remove) and the request is sent, not
3260
+ * created. Give `documents` when the host has read them already, or `loadDocuments` to let the panel read them (it shows the wait, and a
3261
+ * failure blocks Send with a Retry button). With neither, the envelope has no documents and cannot be sent.
3262
+ */
3263
+ export interface DocumentEnvelopeTarget {
3264
+ id: string;
3265
+ /** Shown in the subject suggestion ("Signature required: <name>") and in the success toast. */
3266
+ name: string;
3267
+ documents?: DocumentSeed[];
3268
+ loadDocuments?: () => Observable<DocumentSeed[]>;
3269
+ }
3270
+ /** The document a host's `documentPreview` handler is called with. */
3271
+ export interface DocumentPreviewTarget {
3272
+ id: string;
3273
+ title: string;
3274
+ fileName: string | null;
3275
+ }
3276
+ /** Opens a document for preview (the host knows its own route / viewer). Called synchronously inside the click. */
3277
+ export type DocumentPreviewHandler = (doc: DocumentPreviewTarget) => void;
3278
+ /**
3279
+ * Turns on the "Expiry and Reminders" settings of the document section and sets their starting values (the keys you leave out start at
3280
+ * the defaults below). `null` / not passed = the settings are not shown and nothing about them is sent.
3281
+ */
3282
+ export interface DocumentSigningOptions {
3283
+ /** Days until an unsigned request expires: whole number 1-90 (default 7). */
3284
+ expiryDays?: number;
3285
+ /** Days between reminders: whole number 1-30 (default 2). */
3286
+ reminderIntervalDays?: number;
3287
+ /** How many reminders at most: whole number 0-10 (default 3). */
3288
+ maxReminders?: number;
2920
3289
  }
3290
+ /** Defaults and limits of the signing settings (the same limits the servers enforce). */
3291
+ export declare const DEFAULT_SIGNING_OPTIONS: {
3292
+ readonly expiryDays: 7;
3293
+ readonly reminderIntervalDays: 2;
3294
+ readonly maxReminders: 3;
3295
+ };
3296
+ export declare const SIGNING_LIMITS: {
3297
+ readonly expiryDays: {
3298
+ readonly min: 1;
3299
+ readonly max: 90;
3300
+ readonly label: "Expiry (days)";
3301
+ };
3302
+ readonly reminderIntervalDays: {
3303
+ readonly min: 1;
3304
+ readonly max: 30;
3305
+ readonly label: "Reminder Interval (days)";
3306
+ };
3307
+ readonly maxReminders: {
3308
+ readonly min: 0;
3309
+ readonly max: 10;
3310
+ readonly label: "Max Reminders";
3311
+ };
3312
+ };
3313
+ export declare const DOCUMENT_PROVIDER_OPTIONS: RadioOption[];
2921
3314
  /** The value `ui-document-send-options` emits and the message forms turn into `SendEmailPayload.documents` / `SendTextPayload.documents`. */
2922
3315
  export interface DocumentSendValue {
2923
3316
  documentIds: string[];
2924
3317
  documents: DocumentOption[];
2925
3318
  purpose: DocumentSendPurpose;
2926
3319
  delivery: DocumentSendDelivery;
3320
+ /** Only when the signing settings are shown (host `signing` input), valid and the request is a native e-signature one. */
3321
+ expiryDays?: number;
3322
+ reminderIntervalDays?: number;
3323
+ maxReminders?: number;
3324
+ /** Only when the provider choice is offered (`docuSignConnected` and exactly one document on the email channel). */
3325
+ provider?: DocumentSignatureProvider;
3326
+ /** Only with `provider: 'DOCUSIGN'`. */
3327
+ docuSign?: {
3328
+ countersign: boolean;
3329
+ };
3330
+ /** Only when `signers` (the host's `documentSigners`) is on and a document is chosen: what the signer logic concluded. Never part of the payload. */
3331
+ signerInfo?: DocumentSignerInfo;
2927
3332
  }
2928
3333
  export declare const DOCUMENT_PURPOSE_OPTIONS: SelectOption[];
2929
3334
  /**
@@ -2934,6 +3339,16 @@ export declare const DOCUMENT_PURPOSE_OPTIONS: SelectOption[];
2934
3339
  * "What should the recipient do?" select (e-signature / attachment / both). On the text channel documents can only go as a
2935
3340
  * link, so the purpose is fixed to e-signature and the select is not shown.
2936
3341
  *
3342
+ * Optional parts, all off by default (hosts reach them through the same-named inputs of `ui-send-message-panel`):
3343
+ * - `signing` — "Expiry and Reminders" (expiry days, reminder interval, max reminders) for native e-signature requests;
3344
+ * - `docuSignConnected` — "Native E-Sign / Send via DocuSign" choice (email channel, exactly one document);
3345
+ * - `documentPreview` — "Preview Document" button(s) that call the host's handler.
3346
+ * - `signers` — the signer logic of the panel's `documentSigners` (a document's customer roles, informational documents, the
3347
+ * one-signer DocuSign rule, the document's own countersign setting); the value then carries `signerInfo`;
3348
+ * - `envelope` — an existing envelope: its documents are the fixed list (given, or read through `loadDocuments`).
3349
+ *
3350
+ * The signing settings are ONE collapsed summary line ("Signing options: expires in 7 days, ...") with a Change / Hide button.
3351
+ *
2937
3352
  * It is embedded by `ui-send-message-panel` (`[documents]="true"`); it can also be used on its own.
2938
3353
  *
2939
3354
  * ```html
@@ -2941,7 +3356,8 @@ export declare const DOCUMENT_PURPOSE_OPTIONS: SelectOption[];
2941
3356
  * ```
2942
3357
  *
2943
3358
  * Validity: provides `UiFieldValidity` (`invalid` / `errorMessage`) and the `invalidChange` output. Invalid when `required`
2944
- * and nothing is chosen, or when the purpose is "Send as attachment" and a chosen document has no stored file. Messages
3359
+ * and nothing is chosen, when the purpose is "Send as attachment" and a chosen document has no stored file, or when a shown signing
3360
+ * setting is blank / out of range. Messages
2945
3361
  * show only while `showErrors` is true.
2946
3362
  */
2947
3363
  export declare class DocumentSendOptionsComponent implements UiFieldValidity {
@@ -2968,18 +3384,58 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
2968
3384
  * of the value straight away; the user can remove them or add more. Read once — later changes to the input are ignored.
2969
3385
  * `hasFile` defaults to true (an attachment check then relies on the server's answer).
2970
3386
  */
2971
- readonly initialDocuments: import("@angular/core").InputSignal<{
2972
- id: string;
2973
- title: string;
2974
- fileName?: string | null;
2975
- hasFile?: boolean;
2976
- }[]>;
3387
+ readonly initialDocuments: import("@angular/core").InputSignal<DocumentSeed[]>;
3388
+ /**
3389
+ * Shows the "Expiry and Reminders" settings (Expiry 1-90 days, Reminder Interval 1-30 days, Max Reminders 0-10, all required whole
3390
+ * numbers; starting at 7 / 2 / 3 unless this object says otherwise) while at least one document is chosen and the request is a native
3391
+ * e-signature one (purpose e-signature or both; always on the text channel). `null` (default) = not shown, nothing sent. Read once.
3392
+ */
3393
+ readonly signing: import("@angular/core").InputSignal<DocumentSigningOptions | null | undefined>;
3394
+ /**
3395
+ * The host knows whether DocuSign is connected (the library never calls `/docusign/status`). `true` offers "Native E-Sign / Send via
3396
+ * DocuSign" on the email channel while exactly one document is chosen; `false` (default) = no choice, native only.
3397
+ */
3398
+ readonly docuSignConnected: import("@angular/core").InputSignal<boolean>;
3399
+ /**
3400
+ * "Preview Document": called with the document when its button is clicked (one button for one document, one per document for several).
3401
+ * `null` (default) hides the buttons. The host opens its own viewer; to open a new tab do it synchronously inside this call
3402
+ * (`window.open` after an await is blocked as a popup in Safari).
3403
+ */
3404
+ readonly documentPreview: import("@angular/core").InputSignal<DocumentPreviewHandler | null>;
3405
+ /**
3406
+ * Turns on the signer logic (`documentSigners` of the panel): a document's customer roles (from its row's `signerRoles`, or the config's
3407
+ * `resolveRoles`), informational documents (no signature fields), the one-signer DocuSign rule and the read-only countersign rule.
3408
+ * The value then carries `signerInfo`. `null` (default) = none of it; nothing changes.
3409
+ */
3410
+ readonly signers: import("@angular/core").InputSignal<DocumentSignersConfig | null | undefined>;
3411
+ /**
3412
+ * An existing envelope (`documentEnvelope` of the panel): its documents are the list, fixed (no search, no remove buttons). Read when it
3413
+ * is set; `null` (default) = the sender chooses the documents.
3414
+ */
3415
+ readonly envelope: import("@angular/core").InputSignal<DocumentEnvelopeTarget | null>;
3416
+ /** The document list is fixed: an existing envelope's. */
3417
+ readonly locked: import("@angular/core").Signal<boolean>;
2977
3418
  protected readonly purposeOptions: import("@angular/core").Signal<SelectOption[]>;
2978
3419
  readonly search$: Subject<string>;
2979
3420
  readonly options: import("@angular/core").WritableSignal<ComboboxOption<DocumentOption>[]>;
2980
3421
  readonly loading: import("@angular/core").WritableSignal<boolean>;
2981
3422
  readonly selected: import("@angular/core").WritableSignal<DocumentOption[]>;
2982
3423
  readonly purposeChoice: import("@angular/core").WritableSignal<DocumentSendPurpose>;
3424
+ /** What the sender picked in the provider choice (only effective while the choice is offered). */
3425
+ readonly providerChoice: import("@angular/core").WritableSignal<DocumentSignatureProvider>;
3426
+ readonly countersignChoice: import("@angular/core").WritableSignal<boolean>;
3427
+ /** Roles of documents whose row had no `signerRoles` and that the host resolves (`signers().resolveRoles`). */
3428
+ readonly roleStates: import("@angular/core").WritableSignal<Record<string, RoleState>>;
3429
+ /** The envelope's documents: `loading` / `error` while the panel reads them (`loadDocuments`), `ready` once known. */
3430
+ readonly envelopeStatus: import("@angular/core").WritableSignal<"error" | "loading" | "ready" | "idle">;
3431
+ private envelopeSub;
3432
+ private readonly roleSubs;
3433
+ /** The sender opened the collapsed "Signing options" line. */
3434
+ readonly signingOpen: import("@angular/core").WritableSignal<boolean>;
3435
+ readonly expiryDays: import("@angular/core").WritableSignal<string>;
3436
+ readonly reminderIntervalDays: import("@angular/core").WritableSignal<string>;
3437
+ readonly maxReminders: import("@angular/core").WritableSignal<string>;
3438
+ protected readonly providerOptions: RadioOption[];
2983
3439
  /** The search box; cleared (and kept focused) after each pick so the next search starts empty. */
2984
3440
  private readonly combo;
2985
3441
  /** True when the last search request failed (shown inline instead of "No matching documents"). */
@@ -2991,15 +3447,59 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
2991
3447
  * `ESIGN` has nothing to offer there. The section then shows a short note instead of a picker (it never silently sends another purpose).
2992
3448
  */
2993
3449
  readonly available: import("@angular/core").Signal<boolean>;
2994
- /** The purpose that is actually sent: the text channel can only send a link, so it is always e-signature. */
3450
+ /** True when the sender can choose DocuSign: the host says it is connected, email channel, exactly one document (DocuSign sends one), and e-signature is a supported purpose. */
3451
+ readonly providerChoiceShown: import("@angular/core").Signal<boolean>;
3452
+ /** The provider that is actually used: DocuSign only while the choice is offered. */
3453
+ readonly provider: import("@angular/core").Signal<DocumentSignatureProvider>;
3454
+ /** The countersignature checkbox: a DocuSign send of a document flagged `requiresCountersign`. */
3455
+ readonly showCountersign: import("@angular/core").Signal<boolean>;
3456
+ /** The checkbox (no `signers`) or, with `signers` on, the document's own setting: the document says whether it is countersigned. */
3457
+ readonly countersign: import("@angular/core").Signal<boolean>;
3458
+ /** The signing settings are shown: turned on by the host, a document is chosen, and it is a native e-signature request (not attachment only, not DocuSign). */
3459
+ readonly signingVisible: import("@angular/core").Signal<boolean>;
3460
+ /** What the signer logic concluded for the chosen documents (`null` when `signers` is off or nothing is chosen). */
3461
+ readonly signerInfo: import("@angular/core").Signal<DocumentSignerInfo | null>;
3462
+ /** Why an envelope cannot be sent ('' = it can): nothing to send, or a document that is no longer active. Shown under the section. */
3463
+ readonly envelopeProblem: import("@angular/core").Signal<string>;
3464
+ /** Why Send waits for the envelope's documents ('' when they are known). */
3465
+ readonly envelopeReadMessage: import("@angular/core").Signal<"" | "Reading the envelope's documents…" | "The documents of this envelope couldn't be read, so it can't be sent yet.">;
3466
+ /** Why Send waits for the document's signers ('' when they are known). */
3467
+ readonly signerReadMessage: import("@angular/core").Signal<"" | "Reading the document's signers…" | "The signers of this document couldn't be read, so it can't be sent yet.">;
3468
+ /** The collapsed line: "Signing options: expires in 7 days, reminders every 2 days, up to 3". */
3469
+ readonly signingSummary: import("@angular/core").Signal<string>;
3470
+ /** Open when the sender opened it, or while a value is broken (the error must be visible). */
3471
+ readonly signingExpanded: import("@angular/core").Signal<boolean>;
3472
+ /** The purpose that is actually sent: the text channel and DocuSign can only do e-signature. */
2995
3473
  readonly purpose: import("@angular/core").Signal<DocumentSendPurpose>;
2996
3474
  readonly delivery: import("@angular/core").Signal<DocumentSendDelivery>;
2997
3475
  readonly value: import("@angular/core").Signal<DocumentSendValue>;
2998
- /** The first broken rule ('' when valid). */
3476
+ /** The first broken signing setting ('' when fine or not shown) — the inputs show their own messages. */
3477
+ readonly signingError: import("@angular/core").Signal<string>;
3478
+ /** The first broken document rule ('' when fine) — shown under the section. */
3479
+ readonly documentError: import("@angular/core").Signal<string>;
3480
+ /** The first broken rule ('' when valid): the document rules, the wait for the signers, then the signing settings. */
2999
3481
  readonly errorMessage: import("@angular/core").Signal<string>;
3000
3482
  readonly invalid: import("@angular/core").Signal<boolean>;
3001
3483
  constructor();
3484
+ private static seedToOption;
3485
+ /** Sets the envelope's documents as the list; reads them first when the host gave a loader. */
3486
+ private loadEnvelope;
3487
+ /** "Retry" after the envelope's documents could not be read. */
3488
+ retryEnvelope(): void;
3002
3489
  private static toOption;
3490
+ /** Asks the host for the roles of every chosen document that needs it; forgets documents that were removed. */
3491
+ private syncRoleRequests;
3492
+ private requestRoles;
3493
+ /** "Retry" after the roles of a document could not be read. */
3494
+ retryRoles(): void;
3495
+ /** The Change / Hide button: it flips what the sender sees (a line kept open by an error stays open, but a later fix lets it close). */
3496
+ toggleSigning(): void;
3497
+ private seedSigning;
3498
+ /** `ui-text-input` hands the typed text back as a string (or a number from a programmatic write). */
3499
+ protected asText(v: unknown): string;
3500
+ setProvider(p: string): void;
3501
+ /** Calls the host's preview handler straight from the click (no await in between: Safari blocks a tab opened later). */
3502
+ preview(doc: DocumentOption): void;
3003
3503
  onPick(opt: ComboboxOption<DocumentOption> | null): void;
3004
3504
  remove(id: string): void;
3005
3505
  setPurpose(p: string): void;
@@ -3037,11 +3537,84 @@ export declare class DocumentSendOptionsComponent implements UiFieldValidity {
3037
3537
  "required": false;
3038
3538
  "isSignal": true;
3039
3539
  };
3540
+ "signing": {
3541
+ "alias": "signing";
3542
+ "required": false;
3543
+ "isSignal": true;
3544
+ };
3545
+ "docuSignConnected": {
3546
+ "alias": "docuSignConnected";
3547
+ "required": false;
3548
+ "isSignal": true;
3549
+ };
3550
+ "documentPreview": {
3551
+ "alias": "documentPreview";
3552
+ "required": false;
3553
+ "isSignal": true;
3554
+ };
3555
+ "signers": {
3556
+ "alias": "signers";
3557
+ "required": false;
3558
+ "isSignal": true;
3559
+ };
3560
+ "envelope": {
3561
+ "alias": "envelope";
3562
+ "required": false;
3563
+ "isSignal": true;
3564
+ };
3040
3565
  }, {
3041
3566
  "valueChange": "valueChange";
3042
3567
  "invalidChange": "invalidChange";
3043
3568
  }, never, never, true, never>;
3044
3569
  }
3570
+ /**
3571
+ * Video share-link helpers shared by every app (they replace the apps' own copies, e.g. real-estate `video-link.utils.ts`).
3572
+ *
3573
+ * The share link of a video (`VideoMessage.shareLink`) carries the playback settings as query parameters:
3574
+ * autoplay=1 · ref=<contact id> · ctaType · ctaUrl · ctaLabel · hideReactions=1 (in exactly that order).
3575
+ */
3576
+ interface VideoLinkOptions {
3577
+ autoplay?: boolean;
3578
+ /** The recipient: lets the video page track who watched (`ref`). */
3579
+ contactId?: string;
3580
+ /** '' / undefined = none (the video's own default); `schedule` | `contact` | `custom`. */
3581
+ ctaType?: string;
3582
+ ctaUrl?: string;
3583
+ ctaLabel?: string;
3584
+ hideReactions?: boolean;
3585
+ }
3586
+ /**
3587
+ * Default video settings the host reads from its Communication settings (same keys as `/comm-settings` without the `videoDefault`
3588
+ * prefix): `videoDefaultAutoplay` → `autoplay`, `videoDefaultCtaType` → `ctaType`, … Missing keys mean "off" / "none".
3589
+ */
3590
+ interface VideoDefaults {
3591
+ autoplay?: boolean;
3592
+ ctaType?: string;
3593
+ ctaUrl?: string;
3594
+ ctaLabel?: string;
3595
+ hideReactions?: boolean;
3596
+ }
3597
+ /** `baseLink` + the settings as query parameters (unchanged when no setting is on). A base that already has a query gets `&`. */
3598
+ export declare function buildVideoLink(baseLink: string, options?: VideoLinkOptions): string;
3599
+ /**
3600
+ * The share link of a freshly attached video: `baseLink` with the host's defaults and the recipient applied — exactly the link
3601
+ * `ui-video-link-settings` shows before the sender changes anything.
3602
+ */
3603
+ declare function videoLinkWithDefaults(baseLink: string, defaults?: VideoDefaults, contactId?: string): string;
3604
+ /** Strips any "🎬 Watch video: <url>" line previously inserted into a message body (the line format the apps' own composers use). */
3605
+ export declare function stripVideoLink(text: string): string;
3606
+ /** Appends a "🎬 Watch video: <link>" line to a message body (replacing one that is already there). */
3607
+ export declare function appendVideoLink(text: string, link: string): string;
3608
+ /** The line `ui-send-message-panel` puts in the message for an attached video: `Watch "<title>": <link>`. */
3609
+ export declare function videoMessageLine(title: string, link: string): string;
3610
+ /**
3611
+ * Puts `next` into `body` in place of `prev` (the line inserted earlier), so changing a video setting rewrites the link without
3612
+ * touching the rest of the message:
3613
+ * - no `prev` yet → appended after a blank line (no separator for an empty body);
3614
+ * - `prev` is in the body → replaced in place; with an empty `next` it is removed together with its separator;
3615
+ * - `prev` was edited away by the sender → the body is left as the sender wrote it.
3616
+ */
3617
+ export declare function applyVideoLine(body: string, prev: string, next: string): string;
3045
3618
  /** The `documents` key of `SendEmailPayload` / `SendTextPayload`: present only when at least one document was chosen. */
3046
3619
  interface SendDocumentsPayload {
3047
3620
  documentIds: string[];
@@ -3049,7 +3622,54 @@ interface SendDocumentsPayload {
3049
3622
  purpose: DocumentSendPurpose;
3050
3623
  /** `EMAIL` for the email form, `TEXT` for the text form. */
3051
3624
  delivery: DocumentSendDelivery;
3625
+ /** Only when the host turned on `documentSigningOptions` and the request is a native e-signature request (purpose `ESIGN` / `BOTH`): days until the request expires (1-90). */
3626
+ expiryDays?: number;
3627
+ /** Same condition as `expiryDays`: days between reminders (1-30). */
3628
+ reminderIntervalDays?: number;
3629
+ /** Same condition as `expiryDays`: how many reminders at most (0-10). */
3630
+ maxReminders?: number;
3631
+ /** Only when the host passed `docuSignConnected` and the sender can choose (email, exactly one document): which e-signature provider sends the request. */
3632
+ provider?: DocumentSignatureProvider;
3633
+ /** Only with `provider: 'DOCUSIGN'`: `countersign` is true when the sender ticked "Require my countersignature after client signs" (only offered for a document flagged `requiresCountersign`). */
3634
+ docuSign?: {
3635
+ countersign: boolean;
3636
+ };
3637
+ /**
3638
+ * Only when the host turned on `documentSigners`, the request is a native e-signature one, ONE document is chosen and it has MORE THAN ONE
3639
+ * customer signer: all N signers including signer1 (= the recipient), ordered by role, never partial. A single-signer send has no such key.
3640
+ */
3641
+ signers?: SendSigner[];
3642
+ /** Only when the host passed `sendContext` and at least one key it declared in `documentContextTypes` has a value (other keys are dropped). */
3643
+ context?: SendContext;
3644
+ /** Only when the send is of an existing envelope (`documentEnvelope`): its id; the request is not created again, it is sent. */
3645
+ envelopeId?: string;
3646
+ /** Only with `documentSigners` on, when every chosen document has no signature fields: the send is informational (the recipient gets a view link, nothing is signed). */
3647
+ informational?: true;
3648
+ }
3649
+ /** What the success toast of a document send can say (`documentSentMessage` of the panel). */
3650
+ interface DocumentSentInfo {
3651
+ titles: string[];
3652
+ /** Only when an existing envelope was sent (`documentEnvelope`). */
3653
+ envelopeName?: string;
3654
+ channel: 'email' | 'text';
3655
+ provider?: DocumentSignatureProvider;
3656
+ /** Every chosen document has no signature fields (a view link was sent). */
3657
+ informational: boolean;
3658
+ }
3659
+ /** Builds the success toast of a document send (default: `Email sent` / `Text message sent` / `"<title>" sent via DocuSign` / `Envelope "<name>" sent`). */
3660
+ type DocumentSentMessage = (info: DocumentSentInfo) => string;
3661
+ /** The optional parts the form adds to the `documents` payload besides what the document section holds. */
3662
+ interface DocumentsPayloadExtras {
3663
+ signers?: SendSigner[] | null;
3664
+ context?: SendContext;
3665
+ envelopeId?: string;
3052
3666
  }
3667
+ /**
3668
+ * The `documents` part of a payload from what the document section holds. The optional keys (signing settings, provider, DocuSign
3669
+ * options) are present only when the section produced them, so a host that turned none of them on gets exactly
3670
+ * `{ documentIds, purpose, delivery }`.
3671
+ */
3672
+ declare function buildDocumentsPayload(v: DocumentSendValue, delivery: DocumentSendDelivery, purpose?: DocumentSendPurpose, extras?: DocumentsPayloadExtras): SendDocumentsPayload;
3053
3673
  /**
3054
3674
  * Subject of the signature request when the sender has none (texts have no subject). The server treats exactly this
3055
3675
  * text as a placeholder and builds the real subject from the document names.
@@ -3060,7 +3680,7 @@ export declare const DEFAULT_DOCUMENT_SUBJECT = "Document Signature Required";
3060
3680
  * sender leaves the subject out: signing (ESIGN / BOTH) → "Signature required: <title>" (several: "<N> documents to sign: <first>…");
3061
3681
  * attachment only → "Document attached: <title>" (several: "<N> documents attached: <first>…"). '' for no documents.
3062
3682
  */
3063
- export declare function suggestDocumentSubject(titles: string[], purpose: DocumentSendPurpose): string;
3683
+ export declare function suggestDocumentSubject(titles: string[], purpose: DocumentSendPurpose, informational?: boolean): string;
3064
3684
  /** Most people that can be copied on one email (same limit as the server). */
3065
3685
  export declare const MAX_CC = 10;
3066
3686
  /** CC addresses typed as text: comma / semicolon / whitespace separated, trimmed, de-duplicated (case-insensitive). */
@@ -3079,7 +3699,38 @@ interface CreateDocumentRequestBody {
3079
3699
  purpose: DocumentSendPurpose;
3080
3700
  delivery: DocumentSendDelivery;
3081
3701
  ccEmails?: string[];
3702
+ /** Native e-signature requests only, and only when the host turned on `documentSigningOptions`. */
3703
+ expiryDays?: number;
3704
+ reminderIntervalDays?: number;
3705
+ maxReminders?: number;
3706
+ /** Only with `documentSigners` and a document with several customer signers (complete, ordered). */
3707
+ signers?: SendSigner[];
3708
+ /** Only with `sendContext` / `documentContextTypes`. */
3709
+ context?: SendContext;
3710
+ }
3711
+ /** The signing settings of a `documents` payload as optional keys of the create-request body (nothing when there are none). */
3712
+ declare function signingBodyFields(d: SendDocumentsPayload): Pick<CreateDocumentRequestBody, 'expiryDays' | 'reminderIntervalDays' | 'maxReminders'>;
3713
+ /** The body of `POST <baseUrl>/documents/envelopes/{id}/send` for an existing envelope: the create body without the document ids (the envelope already has them). */
3714
+ type ExistingEnvelopeSendBody = Omit<CreateDocumentRequestBody, 'documentIds'> & {
3715
+ templateId?: string;
3716
+ };
3717
+ /**
3718
+ * Sends an envelope that already exists (`documentEnvelope`): `POST <baseUrl>/documents/envelopes/{id}/send` with the recipient, message and
3719
+ * options in the body (nothing is created first). The host can replace it with `[sendEmail]` / `[sendText]` (payload `documents.envelopeId`).
3720
+ */
3721
+ export declare function sendExistingEnvelope(http: HttpClient, apiBase: string, envelopeId: string, body: ExistingEnvelopeSendBody): Observable<unknown>;
3722
+ /** The `signers` / `context` of a `documents` payload as optional keys of the create-request body (nothing when there are none). */
3723
+ declare function signersContextBodyFields(d: SendDocumentsPayload): Pick<CreateDocumentRequestBody, 'signers' | 'context'>;
3724
+ /** What the library sends to send ONE document through DocuSign (`POST <baseUrl>/docusign/send`). See docs/send-documents-contract.md. */
3725
+ interface DocuSignSendBody {
3726
+ documentId: string;
3727
+ contactId: string;
3728
+ subject?: string;
3729
+ message?: string;
3730
+ countersignRequired: boolean;
3082
3731
  }
3732
+ /** The default DocuSign send: `POST <baseUrl>/docusign/send` → 200. The host can replace it with `[sendEmail]`. */
3733
+ declare function sendDocuSignRequest(http: HttpClient, apiBase: string, body: DocuSignSendBody): Observable<unknown>;
3083
3734
  /**
3084
3735
  * The default way a message form sends documents: create the request, then send it.
3085
3736
  * 1. POST <baseUrl>/documents/envelopes → 201 { id, ... }
@@ -3152,19 +3803,45 @@ declare class SendEmailComponent implements OnInit {
3152
3803
  /** Purposes the app's backend supports for documents (default all); a single entry hides the purpose select. */
3153
3804
  readonly documentPurposes: import("@angular/core").InputSignal<DocumentSendPurpose[]>;
3154
3805
  /** Documents already chosen in the Documents section when the form opens. */
3155
- readonly initialDocuments: import("@angular/core").InputSignal<{
3156
- id: string;
3157
- title: string;
3158
- fileName?: string | null;
3159
- hasFile?: boolean;
3160
- }[]>;
3806
+ readonly initialDocuments: import("@angular/core").InputSignal<DocumentSeed[]>;
3807
+ /**
3808
+ * Turns on the signer logic: one required contact per customer signer role of the chosen document, the read-only countersign line,
3809
+ * informational documents (no signature fields) and the one-signer DocuSign rule. `null` (default) = the single recipient, unchanged.
3810
+ */
3811
+ readonly documentSigners: import("@angular/core").InputSignal<DocumentSignersConfig | null>;
3812
+ /** Values the host has for THIS send; only the keys declared in `documentContextTypes` are sent, as `documents.context`. */
3813
+ readonly sendContext: import("@angular/core").InputSignal<SendContext | null>;
3814
+ /** The context keys the app's backend accepts. */
3815
+ readonly documentContextTypes: import("@angular/core").InputSignal<ContextTypeDef[]>;
3816
+ /** `true` = check (default route `POST <baseUrl>/documents/merge-check`), a function = the host's own check; shows a non-blocking "fields that will be empty" warning. */
3817
+ readonly documentMergeCheck: import("@angular/core").InputSignal<boolean | MergeCheckFn>;
3818
+ /** An existing envelope to send: its documents are fixed and it is sent (not created). Payload `documents.envelopeId`. `null` (default) = a new request from the chosen documents. */
3819
+ readonly documentEnvelope: import("@angular/core").InputSignal<DocumentEnvelopeTarget | null>;
3820
+ /** false = the app's email sending is switched off (Communication settings): Send stays off and the form says why. */
3821
+ readonly emailEnabled: import("@angular/core").InputSignal<boolean>;
3822
+ /** Builds the success toast of a document send (default texts otherwise). */
3823
+ readonly documentSentMessage: import("@angular/core").InputSignal<DocumentSentMessage | null>;
3161
3824
  /** Shows a CC field; the typed addresses are sent as `cc`. Off = payload has no such key. */
3162
3825
  readonly showCc: import("@angular/core").InputSignal<boolean>;
3826
+ /** Shows "Expiry and Reminders" for e-signature requests (see `DocumentSigningOptions`); sent as `documents.expiryDays` / `reminderIntervalDays` / `maxReminders`. `null` = off. */
3827
+ readonly documentSigningOptions: import("@angular/core").InputSignal<DocumentSigningOptions | null | undefined>;
3828
+ /** The host says DocuSign is connected: offers "Native E-Sign / Send via DocuSign" for a single document. Off = native only. */
3829
+ readonly docuSignConnected: import("@angular/core").InputSignal<boolean>;
3830
+ /** "Preview Document" button(s) in the Documents section call this; `null` hides them. */
3831
+ readonly documentPreview: import("@angular/core").InputSignal<DocumentPreviewHandler | null>;
3832
+ /**
3833
+ * Turns on the video settings (Playback, Call-to-Action, Hide reactions, Watch Preview, Remove Video) once a video is attached, starting
3834
+ * from these defaults, and makes the video link carry them. `null` (default) = the attached video's plain share link is inserted, as before.
3835
+ */
3836
+ readonly videoDefaults: import("@angular/core").InputSignal<VideoDefaults | null>;
3163
3837
  /** false hides Attach Files and "Schedule for later" (for a host whose send function can't deliver them). */
3164
3838
  readonly attachmentsAndScheduling: import("@angular/core").InputSignal<boolean>;
3165
3839
  readonly sent: import("@angular/core").OutputEmitterRef<void>;
3166
3840
  readonly emailAdded: import("@angular/core").OutputEmitterRef<string>;
3167
3841
  readonly validChange: import("@angular/core").OutputEmitterRef<boolean>;
3842
+ /** A document send was refused because the document / envelope changed meanwhile (404 / 409): the host refreshes its list. */
3843
+ readonly rejected: import("@angular/core").OutputEmitterRef<void>;
3844
+ readonly EMAIL_DISABLED_MESSAGE = "Email sending is disabled, so this can't be sent. Enable it in Communication Settings.";
3168
3845
  mode: 'compose' | 'template';
3169
3846
  subject: string;
3170
3847
  body: string;
@@ -3192,6 +3869,11 @@ declare class SendEmailComponent implements OnInit {
3192
3869
  /** What the document section holds (null / empty = no documents) and whether it currently breaks a rule. */
3193
3870
  documentsValue: DocumentSendValue | null;
3194
3871
  documentsInvalid: boolean;
3872
+ /** The complete signer list of the signer rows (null while a role has no contact) and whether they break a rule. */
3873
+ signersValue: SendSigner[] | null;
3874
+ signersInvalid: boolean;
3875
+ /** Lines of the merge check ("These fields will be left empty: …"). */
3876
+ mergeWarnings: string[];
3195
3877
  readonly savingEmail: import("@angular/core").WritableSignal<boolean>;
3196
3878
  readonly modeTabs: PillTab[];
3197
3879
  /** Market values (`area`, `median_price`, `dom`, `new_listings`) — only the ones `/service-areas` returned. */
@@ -3211,7 +3893,36 @@ declare class SendEmailComponent implements OnInit {
3211
3893
  get pendingEmailValid(): boolean;
3212
3894
  /** True when the sender chose at least one document (only possible when the `documents` input is on). */
3213
3895
  get hasDocuments(): boolean;
3214
- /** The people copied on the email, as typed (empty unless `showCc` is on). */
3896
+ /** True when the sender chose to send the (single) document through DocuSign: DocuSign emails it itself, so CC, attachments and the required Subject / Message do not apply. */
3897
+ get viaDocuSign(): boolean;
3898
+ /** The recipient as Signer 1 (a stable object: it feeds a child input). */
3899
+ readonly recipientPick: import("@angular/core").Signal<{
3900
+ id: string;
3901
+ name: string;
3902
+ email: string;
3903
+ }>;
3904
+ /** The declared context keys with a value (`documents.context`); keys the app did not declare are dropped (with a development warning). */
3905
+ readonly forwardedContext: import("@angular/core").Signal<SendContext | undefined>;
3906
+ /** What the signer logic concluded for the chosen documents (null when `documentSigners` is off or nothing is chosen). */
3907
+ get signerInfo(): DocumentSignerInfo | null;
3908
+ /** The chosen documents the merge check looks at. */
3909
+ get mergeDocuments(): DocumentOption[];
3910
+ /** True when a native e-signature request for ONE document with several customer signers is being built: the signer rows are required. */
3911
+ get signersActive(): boolean;
3912
+ /** The signer section is shown: signer rows, and/or the countersign line (a signed document that is not just attached). */
3913
+ get signersSectionShown(): boolean;
3914
+ /** The signer rows restart whenever the chosen document changes. */
3915
+ get signersKey(): string;
3916
+ onSigners(v: SendSigner[] | null): void;
3917
+ onSignersInvalid(bad: boolean): void;
3918
+ onMergeWarnings(lines: string[]): void;
3919
+ /** The lines of the ONE warning banner: what choosing a document removed, a multi-signer document among several, the merge check. */
3920
+ get warningLines(): {
3921
+ key: string;
3922
+ text: string;
3923
+ testId: string | null;
3924
+ }[];
3925
+ /** The people copied on the email, as typed (empty unless `showCc` is on, and not used by a DocuSign send). */
3215
3926
  get ccList(): string[];
3216
3927
  /** The first problem with the CC field ('' when fine). */
3217
3928
  get ccError(): string;
@@ -3279,6 +3990,20 @@ declare class SendEmailComponent implements OnInit {
3279
3990
  onFilesSelected(event: Event): void;
3280
3991
  removeAttachment(index: number): void;
3281
3992
  insertVideo(v: VideoMessage): void;
3993
+ /** The body of the default DocuSign send: Subject / Message only when the sender has them (DocuSign has its own defaults otherwise). */
3994
+ private docuSignBody;
3995
+ /** The video attached through the settings flow (null = none) and the line it put into the message. */
3996
+ videoPicked: VideoMessage | null;
3997
+ /** Bumped to re-create the video picker (it keeps its own selection and has no clear output). */
3998
+ videoPickerKey: number;
3999
+ private _videoLine;
4000
+ /** The picker's output: with `videoDefaults` the video gets its settings section, otherwise the plain link is inserted as before. */
4001
+ onVideoSelected(v: VideoMessage): void;
4002
+ /** The settings section's output: rewrites the video line of the message with the current link (the rest of the message is untouched). */
4003
+ onVideoLink(link: string): void;
4004
+ /** "Remove Video": takes the video line out of the message and brings the picker back. */
4005
+ removeVideo(): void;
4006
+ private discardVideo;
3282
4007
  submit(): void;
3283
4008
  static ɵfac: i0.ɵɵFactoryDeclaration<SendEmailComponent, never>;
3284
4009
  static ɵcmp: i0.ɵɵComponentDeclaration<SendEmailComponent, "ui-send-email", never, {
@@ -3352,12 +4077,67 @@ declare class SendEmailComponent implements OnInit {
3352
4077
  "required": false;
3353
4078
  "isSignal": true;
3354
4079
  };
3355
- "showCc": {
3356
- "alias": "showCc";
4080
+ "documentSigners": {
4081
+ "alias": "documentSigners";
3357
4082
  "required": false;
3358
4083
  "isSignal": true;
3359
4084
  };
3360
- "attachmentsAndScheduling": {
4085
+ "sendContext": {
4086
+ "alias": "sendContext";
4087
+ "required": false;
4088
+ "isSignal": true;
4089
+ };
4090
+ "documentContextTypes": {
4091
+ "alias": "documentContextTypes";
4092
+ "required": false;
4093
+ "isSignal": true;
4094
+ };
4095
+ "documentMergeCheck": {
4096
+ "alias": "documentMergeCheck";
4097
+ "required": false;
4098
+ "isSignal": true;
4099
+ };
4100
+ "documentEnvelope": {
4101
+ "alias": "documentEnvelope";
4102
+ "required": false;
4103
+ "isSignal": true;
4104
+ };
4105
+ "emailEnabled": {
4106
+ "alias": "emailEnabled";
4107
+ "required": false;
4108
+ "isSignal": true;
4109
+ };
4110
+ "documentSentMessage": {
4111
+ "alias": "documentSentMessage";
4112
+ "required": false;
4113
+ "isSignal": true;
4114
+ };
4115
+ "showCc": {
4116
+ "alias": "showCc";
4117
+ "required": false;
4118
+ "isSignal": true;
4119
+ };
4120
+ "documentSigningOptions": {
4121
+ "alias": "documentSigningOptions";
4122
+ "required": false;
4123
+ "isSignal": true;
4124
+ };
4125
+ "docuSignConnected": {
4126
+ "alias": "docuSignConnected";
4127
+ "required": false;
4128
+ "isSignal": true;
4129
+ };
4130
+ "documentPreview": {
4131
+ "alias": "documentPreview";
4132
+ "required": false;
4133
+ "isSignal": true;
4134
+ };
4135
+ "videoDefaults": {
4136
+ "alias": "videoDefaults";
4137
+ "required": false;
4138
+ "isSignal": true;
4139
+ };
4140
+ "attachmentsAndScheduling": {
3361
4141
  "alias": "attachmentsAndScheduling";
3362
4142
  "required": false;
3363
4143
  "isSignal": true;
@@ -3366,6 +4146,7 @@ declare class SendEmailComponent implements OnInit {
3366
4146
  "sent": "sent";
3367
4147
  "emailAdded": "emailAdded";
3368
4148
  "validChange": "validChange";
4149
+ "rejected": "rejected";
3369
4150
  }, never, never, true, never>;
3370
4151
  }
3371
4152
  /** What the text form sends — the default `POST <baseUrl>/text-messages` body, or the host's `sendFn` argument. */
@@ -3406,6 +4187,8 @@ declare class SendTextComponent implements OnInit {
3406
4187
  * also marks a record Sent. Loading, toasts, `sent` and the double-send guard behave the same.
3407
4188
  */
3408
4189
  readonly sendFn: import("@angular/core").InputSignal<((payload: SendTextPayload) => Observable<unknown>) | null>;
4190
+ /** Builds the success toast of a document send (default texts otherwise). */
4191
+ readonly documentSentMessage: import("@angular/core").InputSignal<DocumentSentMessage | null>;
3409
4192
  /** Shows the "Documents" section (search your documents; they are texted as a link). Off = the form is unchanged. */
3410
4193
  readonly documents: import("@angular/core").InputSignal<boolean>;
3411
4194
  /** false hides Attach Image and "Schedule for later" (for a host whose send function can't deliver them). */
@@ -3413,15 +4196,35 @@ declare class SendTextComponent implements OnInit {
3413
4196
  /** Purposes the app's backend supports for documents (default all). The text form only sends `ESIGN`; without it the section is unavailable. */
3414
4197
  readonly documentPurposes: import("@angular/core").InputSignal<DocumentSendPurpose[]>;
3415
4198
  /** Documents already chosen in the Documents section when the form opens. */
3416
- readonly initialDocuments: import("@angular/core").InputSignal<{
3417
- id: string;
3418
- title: string;
3419
- fileName?: string | null;
3420
- hasFile?: boolean;
3421
- }[]>;
4199
+ readonly initialDocuments: import("@angular/core").InputSignal<DocumentSeed[]>;
4200
+ /**
4201
+ * Turns on the signer logic for documents (informational documents, the multi-signer rule). A document with several customer signers
4202
+ * can't be texted (the link goes to the first signer only): the section says "Send it by email." and Send stays off. `null` = unchanged.
4203
+ */
4204
+ readonly documentSigners: import("@angular/core").InputSignal<DocumentSignersConfig | null>;
4205
+ /** Values the host has for THIS send; only the keys declared in `documentContextTypes` are sent, as `documents.context`. */
4206
+ readonly sendContext: import("@angular/core").InputSignal<SendContext | null>;
4207
+ /** The context keys the app's backend accepts. */
4208
+ readonly documentContextTypes: import("@angular/core").InputSignal<ContextTypeDef[]>;
4209
+ /** `true` = check (default route `POST <baseUrl>/documents/merge-check`), a function = the host's own check; shows a non-blocking "fields that will be empty" warning. */
4210
+ readonly documentMergeCheck: import("@angular/core").InputSignal<boolean | MergeCheckFn>;
4211
+ /** An existing envelope to text: its documents are fixed and it is sent (not created). Payload `documents.envelopeId`. */
4212
+ readonly documentEnvelope: import("@angular/core").InputSignal<DocumentEnvelopeTarget | null>;
4213
+ /** Shows "Expiry and Reminders" for the texted signing link (see `DocumentSigningOptions`); sent as `documents.expiryDays` / `reminderIntervalDays` / `maxReminders`. `null` = off. */
4214
+ readonly documentSigningOptions: import("@angular/core").InputSignal<DocumentSigningOptions | null | undefined>;
4215
+ /** "Preview Document" button(s) in the Documents section call this; `null` hides them. */
4216
+ readonly documentPreview: import("@angular/core").InputSignal<DocumentPreviewHandler | null>;
4217
+ /**
4218
+ * Turns on the video settings (Playback, Call-to-Action, Hide reactions, Watch Preview, Remove Video) once a video is attached, starting
4219
+ * from these defaults, and makes the video link carry them. `null` (default) = the plain share link is inserted, as before.
4220
+ * A text is limited to 320 characters: a link with settings is longer, and Send stays off while the message is over the limit.
4221
+ */
4222
+ readonly videoDefaults: import("@angular/core").InputSignal<VideoDefaults | null>;
3422
4223
  readonly sent: import("@angular/core").OutputEmitterRef<void>;
3423
4224
  readonly phoneAdded: import("@angular/core").OutputEmitterRef<string>;
3424
4225
  readonly validChange: import("@angular/core").OutputEmitterRef<boolean>;
4226
+ /** A document send was refused because the document / envelope changed meanwhile (404 / 409): the host refreshes its list. */
4227
+ readonly rejected: import("@angular/core").OutputEmitterRef<void>;
3425
4228
  readonly MAX_LENGTH = 320;
3426
4229
  mode: 'compose' | 'template';
3427
4230
  body: string;
@@ -3443,6 +4246,8 @@ declare class SendTextComponent implements OnInit {
3443
4246
  /** What the document section holds (null / empty = no documents) and whether it currently breaks a rule. */
3444
4247
  documentsValue: DocumentSendValue | null;
3445
4248
  documentsInvalid: boolean;
4249
+ /** Lines of the merge check ("These fields will be left empty: …"). */
4250
+ mergeWarnings: string[];
3446
4251
  readonly mediaAttachment: import("@angular/core").WritableSignal<{
3447
4252
  url: string;
3448
4253
  mediaType: string;
@@ -3462,6 +4267,17 @@ declare class SendTextComponent implements OnInit {
3462
4267
  get pendingPhoneValid(): boolean;
3463
4268
  /** True when the sender chose at least one document (only possible when the `documents` input is on). */
3464
4269
  get hasDocuments(): boolean;
4270
+ /** The declared context keys with a value (`documents.context`). */
4271
+ readonly forwardedContext: import("@angular/core").Signal<SendContext | undefined>;
4272
+ /** The chosen documents the merge check looks at. */
4273
+ get mergeDocuments(): DocumentOption[];
4274
+ onMergeWarnings(lines: string[]): void;
4275
+ /** The lines of the ONE warning banner: what choosing a document removed, the merge check. */
4276
+ get warningLines(): {
4277
+ key: string;
4278
+ text: string;
4279
+ testId: string | null;
4280
+ }[];
3465
4281
  /** Set when choosing the first document removed something the sender had already added - said out loud (aria-live), never silently. */
3466
4282
  docsRemovedNote: string;
3467
4283
  onDocumentsChange(v: DocumentSendValue): void;
@@ -3482,6 +4298,8 @@ declare class SendTextComponent implements OnInit {
3482
4298
  get resolvedBody(): string;
3483
4299
  /** Template fields the user still has to fill — tags with no non-blank known value and nothing applied. */
3484
4300
  get missingVars(): string[];
4301
+ /** Why Send is off when the video link pushes the text over the SMS limit ('' otherwise). */
4302
+ get videoLengthError(): string;
3485
4303
  /** Compose mode: a `{{…}}` the form can't fill blocks sending (the server would refuse it). */
3486
4304
  get composeTagError(): string;
3487
4305
  /** Missing fields with nothing typed yet — Send stays disabled until this is empty. */
@@ -3510,6 +4328,18 @@ declare class SendTextComponent implements OnInit {
3510
4328
  onFileSelected(event: Event): void;
3511
4329
  removeMedia(): void;
3512
4330
  insertVideo(v: VideoMessage): void;
4331
+ /** The video attached through the settings flow (null = none) and the line it put into the message. */
4332
+ videoPicked: VideoMessage | null;
4333
+ /** Bumped to re-create the video picker (it keeps its own selection and has no clear output). */
4334
+ videoPickerKey: number;
4335
+ private _videoLine;
4336
+ /** The picker's output: with `videoDefaults` the video gets its settings section, otherwise the plain link is inserted as before. */
4337
+ onVideoSelected(v: VideoMessage): void;
4338
+ /** The settings section's output: rewrites the video line of the message with the current link (the rest of the message is untouched). */
4339
+ onVideoLink(link: string): void;
4340
+ /** "Remove Video": takes the video line out of the message and brings the picker back. */
4341
+ removeVideo(): void;
4342
+ private discardVideo;
3513
4343
  submit(): void;
3514
4344
  static ɵfac: i0.ɵɵFactoryDeclaration<SendTextComponent, never>;
3515
4345
  static ɵcmp: i0.ɵɵComponentDeclaration<SendTextComponent, "ui-send-text", never, {
@@ -3548,6 +4378,11 @@ declare class SendTextComponent implements OnInit {
3548
4378
  "required": false;
3549
4379
  "isSignal": true;
3550
4380
  };
4381
+ "documentSentMessage": {
4382
+ "alias": "documentSentMessage";
4383
+ "required": false;
4384
+ "isSignal": true;
4385
+ };
3551
4386
  "documents": {
3552
4387
  "alias": "documents";
3553
4388
  "required": false;
@@ -3568,10 +4403,51 @@ declare class SendTextComponent implements OnInit {
3568
4403
  "required": false;
3569
4404
  "isSignal": true;
3570
4405
  };
4406
+ "documentSigners": {
4407
+ "alias": "documentSigners";
4408
+ "required": false;
4409
+ "isSignal": true;
4410
+ };
4411
+ "sendContext": {
4412
+ "alias": "sendContext";
4413
+ "required": false;
4414
+ "isSignal": true;
4415
+ };
4416
+ "documentContextTypes": {
4417
+ "alias": "documentContextTypes";
4418
+ "required": false;
4419
+ "isSignal": true;
4420
+ };
4421
+ "documentMergeCheck": {
4422
+ "alias": "documentMergeCheck";
4423
+ "required": false;
4424
+ "isSignal": true;
4425
+ };
4426
+ "documentEnvelope": {
4427
+ "alias": "documentEnvelope";
4428
+ "required": false;
4429
+ "isSignal": true;
4430
+ };
4431
+ "documentSigningOptions": {
4432
+ "alias": "documentSigningOptions";
4433
+ "required": false;
4434
+ "isSignal": true;
4435
+ };
4436
+ "documentPreview": {
4437
+ "alias": "documentPreview";
4438
+ "required": false;
4439
+ "isSignal": true;
4440
+ };
4441
+ "videoDefaults": {
4442
+ "alias": "videoDefaults";
4443
+ "required": false;
4444
+ "isSignal": true;
4445
+ };
3571
4446
  }, {
3572
4447
  "sent": "sent";
3573
4448
  "phoneAdded": "phoneAdded";
3574
4449
  "validChange": "validChange";
4450
+ "rejected": "rejected";
3575
4451
  }, never, never, true, never>;
3576
4452
  }
3577
4453
  /** One match of the host's `jobSearch` function; `description` is the small second line (e.g. the customer). */
@@ -3626,12 +4502,67 @@ export declare class SendMessagePanelComponent {
3626
4502
  /** Purposes the app's backend supports for documents (default all three); `['ESIGN']` hides the purpose select. */
3627
4503
  readonly documentPurposes: import("@angular/core").InputSignal<DocumentSendPurpose[]>;
3628
4504
  /** Documents already chosen when the panel opens (e.g. the row "Send Document" was clicked on); the user can change them. */
3629
- readonly initialDocuments: import("@angular/core").InputSignal<{
3630
- id: string;
3631
- title: string;
3632
- fileName?: string | null;
3633
- hasFile?: boolean;
3634
- }[]>;
4505
+ readonly initialDocuments: import("@angular/core").InputSignal<DocumentSeed[]>;
4506
+ /**
4507
+ * Turns on the signer logic of the Documents section (docs/send-documents-contract.md, Addendum 2026-10-19), all off when `null` (default):
4508
+ * - a document with MORE THAN ONE customer signer shows one required contact picker per further role (Signer 1 is the recipient), Send
4509
+ * stays off until every role has a contact, and `documents.signers` (complete, ordered by role) is added to the payload;
4510
+ * - a document that requires the sender's countersignature shows one read-only line ("Countersigned by <name> after all signers.");
4511
+ * - a document with no signature fields (`signerRoles: []`) is informational: no signers, countersign line, DocuSign or signing options -
4512
+ * the recipient gets a view link;
4513
+ * - DocuSign is offered only for a signed document with one customer signer, and the countersign checkbox is replaced by the document's setting.
4514
+ * The roles come from the `GET /documents` row (`signerRoles`) or from `resolveRoles`. A multi-signer document can't be texted.
4515
+ */
4516
+ readonly documentSigners: import("@angular/core").InputSignal<DocumentSignersConfig | null>;
4517
+ /** Values the host has for THIS send (e.g. `{ propertyId }`); only keys listed in `documentContextTypes` are sent, as `documents.context`. */
4518
+ readonly sendContext: import("@angular/core").InputSignal<SendContext | null>;
4519
+ /** The context keys the app's backend accepts. */
4520
+ readonly documentContextTypes: import("@angular/core").InputSignal<ContextTypeDef[]>;
4521
+ /**
4522
+ * The pre-send "fields that will be empty" check, for documents with mapped data fields only (non-blocking warning): `true` = default route
4523
+ * `POST <baseUrl>/documents/merge-check`, a function = your own call, `false` (default) = off.
4524
+ */
4525
+ readonly documentMergeCheck: import("@angular/core").InputSignal<boolean | MergeCheckFn>;
4526
+ /**
4527
+ * Sends an EXISTING envelope: its documents are fixed (no search, no remove), the recipient is chosen in the panel, and the request is sent
4528
+ * (`POST <baseUrl>/documents/envelopes/{id}/send`, or your `sendEmail` / `sendText` with `documents.envelopeId`) instead of created.
4529
+ * Turns the Documents section on by itself. `null` (default) = a new request from the chosen documents.
4530
+ */
4531
+ readonly documentEnvelope: import("@angular/core").InputSignal<DocumentEnvelopeTarget | null>;
4532
+ /** Builds the success toast of a document send (`"<title>" sent for signature`, `Envelope "<name>" sent` …); the default texts apply when unset. */
4533
+ readonly documentSentMessage: import("@angular/core").InputSignal<DocumentSentMessage | null>;
4534
+ /** false = the app's email sending is switched off (Communication settings): the Email tab says so and Send stays off. Default true. */
4535
+ readonly emailEnabled: import("@angular/core").InputSignal<boolean>;
4536
+ /** The footer button text instead of `Send Email` / `Send Text` (e.g. `Send Document`, `Send Envelope`). */
4537
+ readonly sendLabel: import("@angular/core").InputSignal<string>;
4538
+ /** The 620px wide panel (a long form with signers). Default false. */
4539
+ readonly wide: import("@angular/core").InputSignal<boolean>;
4540
+ /**
4541
+ * Shows "Expiry and Reminders" in the Documents section (Expiry 1-90 days, Reminder Interval 1-30 days, Max Reminders 0-10; required
4542
+ * whole numbers) for native e-signature requests, on the Email tab (purpose e-signature or both) and the Text tab. Pass `{}` for the
4543
+ * defaults 7 / 2 / 3 or set any of `expiryDays`, `reminderIntervalDays`, `maxReminders`. The values are sent as
4544
+ * `documents.expiryDays` / `reminderIntervalDays` / `maxReminders`. `null` (default) = not shown, nothing sent.
4545
+ */
4546
+ readonly documentSigningOptions: import("@angular/core").InputSignal<DocumentSigningOptions | null | undefined>;
4547
+ /**
4548
+ * Email tab: the host says DocuSign is connected (the library never calls `/docusign/status`). Offers "Native E-Sign / Send via DocuSign"
4549
+ * while exactly one document is chosen; DocuSign sends through `POST <baseUrl>/docusign/send` (or your `sendEmail`, which then gets
4550
+ * `documents.provider === 'DOCUSIGN'`). A document row/`initialDocuments` entry with `requiresCountersign: true` also offers "Require my
4551
+ * countersignature after client signs". Default `false` = native only.
4552
+ */
4553
+ readonly docuSignConnected: import("@angular/core").InputSignal<boolean>;
4554
+ /**
4555
+ * "Preview Document" in the Documents section: called with the chosen document when its button is clicked. The library has no route
4556
+ * of its own — the host opens its viewer. Open a tab synchronously inside this function (Safari blocks `window.open` after an await).
4557
+ * `null` (default) = no preview button.
4558
+ */
4559
+ readonly documentPreview: import("@angular/core").InputSignal<DocumentPreviewHandler | null>;
4560
+ /**
4561
+ * The "Video" section (always the last section of the Email and Text forms): once a video is attached it shows Playback, Call-to-Action
4562
+ * (+ URL / label), Hide reactions, Watch Preview and Remove Video, starting from these defaults (your Communication settings), and the
4563
+ * link in the message carries them (`buildVideoLink`). `null` (default) = the plain share link is inserted, with no settings.
4564
+ */
4565
+ readonly videoDefaults: import("@angular/core").InputSignal<VideoDefaults | null>;
3635
4566
  /** The Documents section is shown only when the host turned it on AND the user may send documents. */
3636
4567
  protected readonly documentsOn: import("@angular/core").Signal<boolean>;
3637
4568
  /**
@@ -3655,6 +4586,8 @@ export declare class SendMessagePanelComponent {
3655
4586
  readonly closed: import("@angular/core").OutputEmitterRef<void>;
3656
4587
  readonly sent: import("@angular/core").OutputEmitterRef<void>;
3657
4588
  readonly emailAdded: import("@angular/core").OutputEmitterRef<string>;
4589
+ /** A document / envelope send was refused because it changed meanwhile (404 / 409): the host refreshes its list. */
4590
+ readonly rejected: import("@angular/core").OutputEmitterRef<void>;
3658
4591
  readonly phoneAdded: import("@angular/core").OutputEmitterRef<string>;
3659
4592
  readonly sendEmailRef: import("@angular/core").Signal<SendEmailComponent | undefined>;
3660
4593
  readonly sendTextRef: import("@angular/core").Signal<SendTextComponent | undefined>;
@@ -3785,6 +4718,71 @@ export declare class SendMessagePanelComponent {
3785
4718
  "required": false;
3786
4719
  "isSignal": true;
3787
4720
  };
4721
+ "documentSigners": {
4722
+ "alias": "documentSigners";
4723
+ "required": false;
4724
+ "isSignal": true;
4725
+ };
4726
+ "sendContext": {
4727
+ "alias": "sendContext";
4728
+ "required": false;
4729
+ "isSignal": true;
4730
+ };
4731
+ "documentContextTypes": {
4732
+ "alias": "documentContextTypes";
4733
+ "required": false;
4734
+ "isSignal": true;
4735
+ };
4736
+ "documentMergeCheck": {
4737
+ "alias": "documentMergeCheck";
4738
+ "required": false;
4739
+ "isSignal": true;
4740
+ };
4741
+ "documentEnvelope": {
4742
+ "alias": "documentEnvelope";
4743
+ "required": false;
4744
+ "isSignal": true;
4745
+ };
4746
+ "documentSentMessage": {
4747
+ "alias": "documentSentMessage";
4748
+ "required": false;
4749
+ "isSignal": true;
4750
+ };
4751
+ "emailEnabled": {
4752
+ "alias": "emailEnabled";
4753
+ "required": false;
4754
+ "isSignal": true;
4755
+ };
4756
+ "sendLabel": {
4757
+ "alias": "sendLabel";
4758
+ "required": false;
4759
+ "isSignal": true;
4760
+ };
4761
+ "wide": {
4762
+ "alias": "wide";
4763
+ "required": false;
4764
+ "isSignal": true;
4765
+ };
4766
+ "documentSigningOptions": {
4767
+ "alias": "documentSigningOptions";
4768
+ "required": false;
4769
+ "isSignal": true;
4770
+ };
4771
+ "docuSignConnected": {
4772
+ "alias": "docuSignConnected";
4773
+ "required": false;
4774
+ "isSignal": true;
4775
+ };
4776
+ "documentPreview": {
4777
+ "alias": "documentPreview";
4778
+ "required": false;
4779
+ "isSignal": true;
4780
+ };
4781
+ "videoDefaults": {
4782
+ "alias": "videoDefaults";
4783
+ "required": false;
4784
+ "isSignal": true;
4785
+ };
3788
4786
  "showJobPicker": {
3789
4787
  "alias": "showJobPicker";
3790
4788
  "required": false;
@@ -3810,9 +4808,135 @@ export declare class SendMessagePanelComponent {
3810
4808
  "closed": "closed";
3811
4809
  "sent": "sent";
3812
4810
  "emailAdded": "emailAdded";
4811
+ "rejected": "rejected";
3813
4812
  "phoneAdded": "phoneAdded";
3814
4813
  }, never, never, true, never>;
3815
4814
  }
4815
+ /**
4816
+ * ui-document-signers — the signer section of a document send: one required contact per customer signer role of the chosen document
4817
+ * (Signer 1 is the recipient, shown read-only) in signing order, and the one read-only countersign line.
4818
+ *
4819
+ * Internal child of the message forms (`ui-send-message-panel` with `documentSigners`); hosts do not place it. Rows exist only for a
4820
+ * document with MORE THAN ONE customer signer; a single-signer document shows nothing here except the countersign line. It emits the
4821
+ * complete `signers` list (never a partial one: `null` until every role has a contact) and its validity (`UiFieldValidity`):
4822
+ * a missing contact is `<Role label> is required.`, a contact without an email `<Name> has no email address.`, the same person in two
4823
+ * roles `<Name> is already <Role label>.` (unless the config allows it).
4824
+ */
4825
+ export declare class DocumentSignersComponent implements UiFieldValidity {
4826
+ /** The signer logic's conclusion for the chosen document(s) (`ui-document-send-options` value `signerInfo`). */
4827
+ readonly info: import("@angular/core").InputSignal<DocumentSignerInfo | null>;
4828
+ readonly config: import("@angular/core").InputSignal<DocumentSignersConfig | null>;
4829
+ /** The recipient of the message = Signer 1. */
4830
+ readonly recipient: import("@angular/core").InputSignal<SignerPick>;
4831
+ /** Shows the "<Role> is required." messages now (otherwise after the first blur). */
4832
+ readonly showErrors: import("@angular/core").InputSignal<boolean>;
4833
+ /** The sender chose DocuSign: only the countersign line applies. */
4834
+ readonly viaDocuSign: import("@angular/core").InputSignal<boolean>;
4835
+ /** The complete signer list (recipient first) or null while a role has no contact. Emitted on every change. */
4836
+ readonly signersChange: import("@angular/core").OutputEmitterRef<SendSigner[] | null>;
4837
+ readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
4838
+ readonly picks: import("@angular/core").WritableSignal<Partial<Record<SignerRole, ContactLookup | null>>>;
4839
+ protected readonly rowsShown: import("@angular/core").Signal<boolean>;
4840
+ protected readonly line: import("@angular/core").Signal<string>;
4841
+ readonly problems: import("@angular/core").Signal<Partial<Record<SignerRole, string>>>;
4842
+ readonly signers: import("@angular/core").Signal<SendSigner[] | null>;
4843
+ readonly errorMessage: import("@angular/core").Signal<string>;
4844
+ readonly invalid: import("@angular/core").Signal<boolean>;
4845
+ constructor();
4846
+ protected label(role: SignerRole): string;
4847
+ /** Under a picker: the problems of a chosen contact (no email / same person twice); the empty-row message is the picker's own (`visibleErrorMessage`). */
4848
+ protected visibleProblem(role: SignerRole): string;
4849
+ pick(role: SignerRole, c: ContactLookup | null): void;
4850
+ static ɵfac: i0.ɵɵFactoryDeclaration<DocumentSignersComponent, never>;
4851
+ static ɵcmp: i0.ɵɵComponentDeclaration<DocumentSignersComponent, "ui-document-signers", never, {
4852
+ "info": {
4853
+ "alias": "info";
4854
+ "required": false;
4855
+ "isSignal": true;
4856
+ };
4857
+ "config": {
4858
+ "alias": "config";
4859
+ "required": false;
4860
+ "isSignal": true;
4861
+ };
4862
+ "recipient": {
4863
+ "alias": "recipient";
4864
+ "required": false;
4865
+ "isSignal": true;
4866
+ };
4867
+ "showErrors": {
4868
+ "alias": "showErrors";
4869
+ "required": false;
4870
+ "isSignal": true;
4871
+ };
4872
+ "viaDocuSign": {
4873
+ "alias": "viaDocuSign";
4874
+ "required": false;
4875
+ "isSignal": true;
4876
+ };
4877
+ }, {
4878
+ "signersChange": "signersChange";
4879
+ "invalidChange": "invalidChange";
4880
+ }, never, never, true, never>;
4881
+ }
4882
+ /** Quiet time after the last change before the check is requested. */
4883
+ export declare const MERGE_CHECK_DEBOUNCE_MS = 300;
4884
+ /**
4885
+ * ui-document-merge-check — the pre-send "fields that will be empty" check (non-blocking), logic only (it renders nothing).
4886
+ *
4887
+ * Internal child of the message forms. While `enabled` is `true` (default route `POST <baseUrl>/documents/merge-check`) or a host
4888
+ * function, and at least one chosen document has mapped data fields, it asks which data fields would be left empty for this recipient,
4889
+ * these signers and this context, and emits the warning lines (`warningsChange`). Debounced, a newer request cancels an older one
4890
+ * (`switchMap`), never cached. A failed or slow check emits no warning and never blocks Send. Documents with no mapped data fields
4891
+ * are not sent to the check.
4892
+ */
4893
+ export declare class DocumentMergeCheckComponent {
4894
+ private readonly http;
4895
+ private readonly destroyRef;
4896
+ private readonly apiBase;
4897
+ /** `true` = the default route, a function = the host's own call, `false` / `null` = off. */
4898
+ readonly enabled: import("@angular/core").InputSignal<boolean | MergeCheckFn | null>;
4899
+ readonly documents: import("@angular/core").InputSignal<SignerDocLike[]>;
4900
+ readonly customerId: import("@angular/core").InputSignal<string>;
4901
+ readonly signers: import("@angular/core").InputSignal<SendSigner[] | null>;
4902
+ readonly context: import("@angular/core").InputSignal<SendContext | undefined>;
4903
+ /** The warning lines (empty = nothing to warn about). Emitted whenever they change. */
4904
+ readonly warningsChange: import("@angular/core").OutputEmitterRef<string[]>;
4905
+ private readonly request;
4906
+ constructor();
4907
+ private lastLines;
4908
+ private call;
4909
+ static ɵfac: i0.ɵɵFactoryDeclaration<DocumentMergeCheckComponent, never>;
4910
+ static ɵcmp: i0.ɵɵComponentDeclaration<DocumentMergeCheckComponent, "ui-document-merge-check", never, {
4911
+ "enabled": {
4912
+ "alias": "enabled";
4913
+ "required": false;
4914
+ "isSignal": true;
4915
+ };
4916
+ "documents": {
4917
+ "alias": "documents";
4918
+ "required": false;
4919
+ "isSignal": true;
4920
+ };
4921
+ "customerId": {
4922
+ "alias": "customerId";
4923
+ "required": false;
4924
+ "isSignal": true;
4925
+ };
4926
+ "signers": {
4927
+ "alias": "signers";
4928
+ "required": false;
4929
+ "isSignal": true;
4930
+ };
4931
+ "context": {
4932
+ "alias": "context";
4933
+ "required": false;
4934
+ "isSignal": true;
4935
+ };
4936
+ }, {
4937
+ "warningsChange": "warningsChange";
4938
+ }, never, never, true, never>;
4939
+ }
3816
4940
  export interface BulkMessageContact {
3817
4941
  id: string;
3818
4942
  name: string;
@@ -4816,7 +5940,7 @@ export declare class FormSectionComponent {
4816
5940
  }, {}, never, ["*"], true, never>;
4817
5941
  }
4818
5942
  export declare class FormRowComponent {
4819
- readonly cols: import("@angular/core").InputSignal<2 | 1 | 3>;
5943
+ readonly cols: import("@angular/core").InputSignal<1 | 2 | 3>;
4820
5944
  static ɵfac: i0.ɵɵFactoryDeclaration<FormRowComponent, never>;
4821
5945
  static ɵcmp: i0.ɵɵComponentDeclaration<FormRowComponent, "ui-form-row", never, {
4822
5946
  "cols": {
@@ -5256,6 +6380,12 @@ export declare class AppShellComponent implements OnInit, OnDestroy {
5256
6380
  private readonly router;
5257
6381
  private _routerSub?;
5258
6382
  readonly navGroups: import("@angular/core").InputSignal<NavGroup[]>;
6383
+ /**
6384
+ * The page's title, rendered in the top bar as the page's single `<h1>` (id `shell-page-title`, `tabindex="-1"` so an app can
6385
+ * focus it after navigation) and used as the accessible name of `<main>`. A page that has no title here keeps its own heading.
6386
+ * A page shown with a title MUST NOT also render its own `<h1>` (that would be two h1s); give it a visually hidden one only
6387
+ * when the title is not set.
6388
+ */
5259
6389
  readonly pageTitle: import("@angular/core").InputSignal<string>;
5260
6390
  readonly appName: import("@angular/core").InputSignal<string>;
5261
6391
  readonly user: import("@angular/core").InputSignal<ShellUser | null>;
@@ -5882,115 +7012,6 @@ export declare class RadioComponent {
5882
7012
  "selected": "selected";
5883
7013
  }, never, ["*"], true, never>;
5884
7014
  }
5885
- export interface RadioOption {
5886
- value: string;
5887
- label: string;
5888
- description?: string;
5889
- disabled?: boolean;
5890
- }
5891
- /**
5892
- * Group of native radio buttons inside a `<fieldset>` (+ `<legend>` = `label`), a ControlValueAccessor (string value, `''`
5893
- * = nothing selected). Arrow keys move and select natively because all radios share one `name`.
5894
- * Built-in validation: `required` -> "<label> is required."; a non-empty value that is not one of the `options` ->
5895
- * "Select a valid option." (not checked while `options` is empty). Disabled groups are never invalid.
5896
- *
5897
- * Validity API (same on every ui input): Angular `Validator`, signals `invalid` + `errorMessage`, `invalidChange` output,
5898
- * provides `UiFieldValidity`. Messages show after the group lost focus or while `[showErrors]="true"`; a host `[error]` wins.
5899
- */
5900
- export declare class RadioGroupComponent implements ControlValueAccessor, Validator, UiFieldValidity {
5901
- readonly label: import("@angular/core").InputSignal<string>;
5902
- readonly options: import("@angular/core").InputSignal<RadioOption[]>;
5903
- readonly required: import("@angular/core").InputSignal<boolean>;
5904
- readonly hint: import("@angular/core").InputSignal<string>;
5905
- readonly error: import("@angular/core").InputSignal<string>;
5906
- /** Reveal the built-in error messages now (e.g. after a failed Save click), without waiting for blur. */
5907
- readonly showErrors: import("@angular/core").InputSignal<boolean>;
5908
- readonly orientation: import("@angular/core").InputSignal<"vertical" | "horizontal">;
5909
- /** Native `name` shared by the radios; a unique one is generated when omitted. */
5910
- readonly name: import("@angular/core").InputSignal<string>;
5911
- protected readonly _disabledInput: import("@angular/core").InputSignal<boolean>;
5912
- private readonly _cvaDisabled;
5913
- protected readonly disabled: import("@angular/core").Signal<boolean>;
5914
- private readonly _generatedName;
5915
- protected get _name(): string;
5916
- protected readonly _descId: string;
5917
- protected readonly _value: import("@angular/core").WritableSignal<string>;
5918
- private readonly _reveal;
5919
- private readonly _issue;
5920
- /** True while the value breaks a built-in rule or the host passed an `[error]`. */
5921
- readonly invalid: import("@angular/core").Signal<boolean>;
5922
- /** Message of the first broken built-in rule ('' when valid), shown or not. */
5923
- readonly errorMessage: import("@angular/core").Signal<string>;
5924
- /** Emits whenever the field becomes invalid / valid. */
5925
- readonly invalidChange: import("@angular/core").OutputEmitterRef<boolean>;
5926
- protected readonly _activeError: import("@angular/core").Signal<string>;
5927
- private _onValidatorChange;
5928
- constructor();
5929
- /** Re-run the form control's validation when a rule input (required, options) changes. */
5930
- ngOnChanges(): void;
5931
- validate(control: AbstractControl): ValidationErrors | null;
5932
- registerOnValidatorChange(fn: () => void): void;
5933
- private _onChange;
5934
- private _onTouched;
5935
- writeValue(val: string): void;
5936
- registerOnChange(fn: (v: string) => void): void;
5937
- registerOnTouched(fn: () => void): void;
5938
- setDisabledState(d: boolean): void;
5939
- protected onSelect(value: string): void;
5940
- /** Touched once focus leaves the whole group (moving between its radios does not count). */
5941
- protected onFocusOut(event: FocusEvent): void;
5942
- private _check;
5943
- static ɵfac: i0.ɵɵFactoryDeclaration<RadioGroupComponent, never>;
5944
- static ɵcmp: i0.ɵɵComponentDeclaration<RadioGroupComponent, "ui-radio-group", never, {
5945
- "label": {
5946
- "alias": "label";
5947
- "required": false;
5948
- "isSignal": true;
5949
- };
5950
- "options": {
5951
- "alias": "options";
5952
- "required": false;
5953
- "isSignal": true;
5954
- };
5955
- "required": {
5956
- "alias": "required";
5957
- "required": false;
5958
- "isSignal": true;
5959
- };
5960
- "hint": {
5961
- "alias": "hint";
5962
- "required": false;
5963
- "isSignal": true;
5964
- };
5965
- "error": {
5966
- "alias": "error";
5967
- "required": false;
5968
- "isSignal": true;
5969
- };
5970
- "showErrors": {
5971
- "alias": "showErrors";
5972
- "required": false;
5973
- "isSignal": true;
5974
- };
5975
- "orientation": {
5976
- "alias": "orientation";
5977
- "required": false;
5978
- "isSignal": true;
5979
- };
5980
- "name": {
5981
- "alias": "name";
5982
- "required": false;
5983
- "isSignal": true;
5984
- };
5985
- "_disabledInput": {
5986
- "alias": "disabled";
5987
- "required": false;
5988
- "isSignal": true;
5989
- };
5990
- }, {
5991
- "invalidChange": "invalidChange";
5992
- }, never, never, true, never>;
5993
- }
5994
7015
  /** One row of a `ui-radio-matrix`: `value` is the key in the model, `label` the row header. */
5995
7016
  export interface RadioMatrixRow {
5996
7017
  value: string;
@@ -6146,7 +7167,7 @@ export declare class DetailCardComponent {
6146
7167
  /** Bold uppercase title. Empty = no title text. */
6147
7168
  readonly title: import("@angular/core").InputSignal<string>;
6148
7169
  /** 1-6 makes the title a real heading for screen readers (role=heading, aria-level); null keeps it plain text. */
6149
- readonly headingLevel: import("@angular/core").InputSignal<2 | 1 | 5 | 3 | 6 | 4 | null>;
7170
+ readonly headingLevel: import("@angular/core").InputSignal<1 | 2 | 3 | 4 | 5 | 6 | null>;
6150
7171
  /** Optional id for the title text; the card is then labelled by it. Without it the title is the card's aria-label. */
6151
7172
  readonly titleId: import("@angular/core").InputSignal<string>;
6152
7173
  /** Grey line under the title. */
@@ -6257,4 +7278,4 @@ export declare class DividerComponent {
6257
7278
  };
6258
7279
  }, {}, never, never, true, never>;
6259
7280
  }
6260
- export type { SendDocumentsPayload, SendEmailPayload, SendTextPayload };
7281
+ export type { CreateDocumentRequestBody, DocuSignSendBody, DocumentSentInfo, DocumentSentMessage, DocumentsPayloadExtras, ExistingEnvelopeSendBody, SendDocumentsPayload, SendEmailPayload, SendTextPayload, VideoDefaults, VideoLinkOptions };