@mk-kit/ui 0.36.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -933,6 +933,93 @@ interface MkI18nStrings {
933
933
  logCopyAll: string;
934
934
  /** Log viewer: soft-wrap toolbar toggle. */
935
935
  logWrapLines: string;
936
+ /** Chat: accessible name of the message log. */
937
+ chatLabel: string;
938
+ /** Chat: accessible name of the composer textarea. */
939
+ chatComposerLabel: string;
940
+ /** Chat: composer placeholder. */
941
+ chatPlaceholder: string;
942
+ /** Chat: send button. */
943
+ chatSend: string;
944
+ /** Chat: stop-generating button (replaces send while busy). */
945
+ chatStop: string;
946
+ /** Chat: attach-files button. */
947
+ chatAttach: string;
948
+ /** Chat: remove one pending attachment. */
949
+ chatRemoveAttachment: string;
950
+ /** Chat: group label of pending / shown attachments. */
951
+ chatAttachments: string;
952
+ /** Chat: group label of quick-reply suggestions. */
953
+ chatSuggestions: string;
954
+ /** Chat: copy-message button. */
955
+ chatCopy: string;
956
+ /** Chat: retry a failed message. */
957
+ chatRetry: string;
958
+ /** Chat: typing indicator. */
959
+ chatTyping: string;
960
+ /** Chat: screen-reader text while a reply streams in. */
961
+ chatStreaming: string;
962
+ /** Chat: scroll-to-newest button. */
963
+ chatJumpToLatest: string;
964
+ /** Chat: empty-state text. */
965
+ chatEmpty: string;
966
+ /** Chat: author fallback for the user's own messages. */
967
+ chatYou: string;
968
+ /** Chat: author fallback for assistant messages. */
969
+ chatAssistant: string;
970
+ /** Chat: tool call in progress. */
971
+ chatToolRunning: string;
972
+ /** Chat: tool call finished. */
973
+ chatToolDone: string;
974
+ /** Chat: tool call failed. */
975
+ chatToolError: string;
976
+ /** Dynamic form: add an item to an array field. */
977
+ dynamicFormAdd: string;
978
+ /** Dynamic form: remove one item of an array field (index is 1-based). */
979
+ dynamicFormRemove: (index: number) => string;
980
+ /** Query builder: accessible name of the whole builder. */
981
+ queryBuilderLabel: string;
982
+ queryAddRule: string;
983
+ queryAddGroup: string;
984
+ queryRemoveRule: string;
985
+ queryRemoveGroup: string;
986
+ /** Combinator labels — also used by `mkQueryToText`. */
987
+ queryAnd: string;
988
+ queryOr: string;
989
+ queryNot: string;
990
+ queryField: string;
991
+ queryOperator: string;
992
+ queryValue: string;
993
+ queryValueFrom: string;
994
+ queryValueTo: string;
995
+ queryEmptyGroup: string;
996
+ queryTrue: string;
997
+ queryFalse: string;
998
+ queryOpEq: string;
999
+ queryOpNeq: string;
1000
+ queryOpContains: string;
1001
+ queryOpNotContains: string;
1002
+ queryOpStartsWith: string;
1003
+ queryOpEndsWith: string;
1004
+ queryOpGt: string;
1005
+ queryOpGte: string;
1006
+ queryOpLt: string;
1007
+ queryOpLte: string;
1008
+ queryOpBetween: string;
1009
+ queryOpIn: string;
1010
+ queryOpNotIn: string;
1011
+ queryOpBefore: string;
1012
+ queryOpAfter: string;
1013
+ queryOpEmpty: string;
1014
+ queryOpNotEmpty: string;
1015
+ /** Dialog: label of the move grip (arrow keys move, Home resets). */
1016
+ dialogMove: string;
1017
+ /** Dialog: label of the resize grip (arrow keys resize, Home resets). */
1018
+ dialogResize: string;
1019
+ /** Listbox: filter box placeholder / label. */
1020
+ listboxFilter: string;
1021
+ /** Listbox: shown when the filter matches nothing. */
1022
+ listboxEmpty: string;
936
1023
  /** Announced when an event is picked up in keyboard move mode. */
937
1024
  eventCalendarGrabbed: (title: string, from: string, to: string) => string;
938
1025
  /** Announced after each keyboard step: current day + time range. */
@@ -1181,5 +1268,83 @@ type MkErrorMessages = Readonly<Record<string, string | ((err: any) => string)>>
1181
1268
  */
1182
1269
  declare function mkFirstErrorMessage(errors: ValidationErrors | null | undefined, strings: MkValidationStrings, overrides?: MkErrorMessages): string | null;
1183
1270
 
1184
- export { MK_BREAKPOINTS, MK_DEFAULT_BREAKPOINTS, MK_DEFAULT_DATE_NAMES, MK_DEFAULT_I18N, MK_DEFAULT_VALIDATION, MK_I18N, MK_OVERLAY_DATA, MkAnchoredPanel, MkBreakpointService, MkFieldContext, MkFocusTrap, MkLiveAnnouncer, MkOverlayRef, MkOverlayService, MkThemeService, mkComputeAnchoredPosition, mkFirstErrorMessage, mkGetFocusable, mkHighlight, mkHighlightJson, mkIsResponsive, mkUniqueId, mkValidatorChange, provideMkI18n };
1185
- export type { MkAnchoredPosition, MkAnchoredPositionOptions, MkAriaLivePoliteness, MkBlockEditorStrings, MkBreakpoint, MkBreakpoints, MkCodeLanguage, MkDateNames, MkDensity, MkErrorMessages, MkI18nStrings, MkOverlayConfig, MkPlacement, MkResolvedTheme, MkResponsive, MkSize$1 as MkSize, MkSortAnnounceDirection, MkThemePreference, MkTone, MkValidationStrings, MkValidatorChangeRef, MkVariant };
1271
+ /** Value kind of a filterable field; decides the editor and the operators offered. */
1272
+ type MkQueryValueType = 'string' | 'number' | 'boolean' | 'date' | 'select';
1273
+ /** A choice for `select` fields. */
1274
+ interface MkQueryFieldOption {
1275
+ label: string;
1276
+ value: unknown;
1277
+ }
1278
+ /** A field the user can filter on. */
1279
+ interface MkQueryField {
1280
+ /** Property key on the row objects / the API's filter name. */
1281
+ key: string;
1282
+ /** Label shown in the field picker. */
1283
+ label: string;
1284
+ /** Default `string`. */
1285
+ type?: MkQueryValueType;
1286
+ /** Choices for `select` fields. */
1287
+ options?: readonly MkQueryFieldOption[];
1288
+ /** Restrict / reorder the operators offered (default: all for the type). */
1289
+ operators?: readonly MkQueryOperator[];
1290
+ /** Placeholder of the value editor. */
1291
+ placeholder?: string;
1292
+ }
1293
+ /** Comparison operators. Which apply depends on the field type. */
1294
+ type MkQueryOperator = 'eq' | 'neq' | 'contains' | 'notContains' | 'startsWith' | 'endsWith' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'in' | 'notIn' | 'before' | 'after' | 'empty' | 'notEmpty';
1295
+ /** A leaf condition. `value` is `[from, to]` for `between`, an array for `in` / `notIn`, absent for `empty` / `notEmpty`. Dates are ISO strings. */
1296
+ interface MkQueryRule {
1297
+ id: string;
1298
+ field: string;
1299
+ operator: MkQueryOperator;
1300
+ value?: unknown;
1301
+ }
1302
+ type MkQueryCombinator = 'and' | 'or';
1303
+ /** A group of rules and nested groups joined by one combinator, optionally negated. */
1304
+ interface MkQueryGroup {
1305
+ id: string;
1306
+ combinator: MkQueryCombinator;
1307
+ /** Negate the whole group. */
1308
+ not?: boolean;
1309
+ rules: MkQueryNode[];
1310
+ }
1311
+ type MkQueryNode = MkQueryRule | MkQueryGroup;
1312
+
1313
+ /** Operators offered per field type, in menu order. */
1314
+ declare const MK_QUERY_OPERATORS: Readonly<Record<MkQueryValueType, readonly MkQueryOperator[]>>;
1315
+ /** Operators that take no value. */
1316
+ declare const MK_QUERY_UNARY: ReadonlySet<MkQueryOperator>;
1317
+ /** True for a group node (as opposed to a rule). */
1318
+ declare function mkIsQueryGroup(node: MkQueryNode): node is MkQueryGroup;
1319
+ /** A fresh empty group. */
1320
+ declare function mkCreateQueryGroup(init?: Partial<Omit<MkQueryGroup, 'id'>>): MkQueryGroup;
1321
+ /** A fresh rule on `field`, using its first operator. */
1322
+ declare function mkCreateQueryRule(field: MkQueryField): MkQueryRule;
1323
+ /** Operators a field offers (its own list, else the defaults for its type). */
1324
+ declare function mkQueryOperatorsFor(field: MkQueryField | undefined): readonly MkQueryOperator[];
1325
+ /** True when the tree holds no rule at all (empty groups only). */
1326
+ declare function mkQueryIsEmpty(group: MkQueryGroup): boolean;
1327
+ /** Number of rules in the tree. */
1328
+ declare function mkQueryRuleCount(group: MkQueryGroup): number;
1329
+ /** Drop empty groups and rules that still need a value, so the API gets only complete conditions. */
1330
+ declare function mkQueryCompact(group: MkQueryGroup): MkQueryGroup;
1331
+ /** A rule is complete when its operator needs no value or has one. */
1332
+ declare function mkQueryRuleIsComplete(rule: MkQueryRule): boolean;
1333
+ /** Evaluate one rule against a row. */
1334
+ declare function mkQueryRuleMatches(rule: MkQueryRule, row: Record<string, unknown>, field?: MkQueryField): boolean;
1335
+ /**
1336
+ * Compile a query into a row predicate for client-side filtering
1337
+ * (`rows.filter(mkQueryToPredicate(query, fields))`). Unfinished rules are
1338
+ * ignored, so a half-edited query never blanks the table.
1339
+ */
1340
+ declare function mkQueryToPredicate<T extends object = Record<string, unknown>>(group: MkQueryGroup, fields?: readonly MkQueryField[]): (row: T) => boolean;
1341
+ /** Localised label of an operator. */
1342
+ declare function mkQueryOperatorLabel(op: MkQueryOperator, i18n?: MkI18nStrings): string;
1343
+ /**
1344
+ * Human-readable sentence for a query, e.g.
1345
+ * `(Name contains "ada" and Orders at least 10) or Status is any of Active, Invited`.
1346
+ */
1347
+ declare function mkQueryToText(group: MkQueryGroup, fields?: readonly MkQueryField[], i18n?: MkI18nStrings): string;
1348
+
1349
+ export { MK_BREAKPOINTS, MK_DEFAULT_BREAKPOINTS, MK_DEFAULT_DATE_NAMES, MK_DEFAULT_I18N, MK_DEFAULT_VALIDATION, MK_I18N, MK_OVERLAY_DATA, MK_QUERY_OPERATORS, MK_QUERY_UNARY, MkAnchoredPanel, MkBreakpointService, MkFieldContext, MkFocusTrap, MkLiveAnnouncer, MkOverlayRef, MkOverlayService, MkThemeService, mkComputeAnchoredPosition, mkCreateQueryGroup, mkCreateQueryRule, mkFirstErrorMessage, mkGetFocusable, mkHighlight, mkHighlightJson, mkIsQueryGroup, mkIsResponsive, mkQueryCompact, mkQueryIsEmpty, mkQueryOperatorLabel, mkQueryOperatorsFor, mkQueryRuleCount, mkQueryRuleIsComplete, mkQueryRuleMatches, mkQueryToPredicate, mkQueryToText, mkUniqueId, mkValidatorChange, provideMkI18n };
1350
+ export type { MkAnchoredPosition, MkAnchoredPositionOptions, MkAriaLivePoliteness, MkBlockEditorStrings, MkBreakpoint, MkBreakpoints, MkCodeLanguage, MkDateNames, MkDensity, MkErrorMessages, MkI18nStrings, MkOverlayConfig, MkPlacement, MkQueryCombinator, MkQueryField, MkQueryFieldOption, MkQueryGroup, MkQueryNode, MkQueryOperator, MkQueryRule, MkQueryValueType, MkResolvedTheme, MkResponsive, MkSize$1 as MkSize, MkSortAnnounceDirection, MkThemePreference, MkTone, MkValidationStrings, MkValidatorChangeRef, MkVariant };
@@ -0,0 +1,305 @@
1
+ import { ValidatorFn, AbstractControl, FormGroup, FormControl, FormArray } from '@angular/forms';
2
+ import * as _mk_kit_ui_core from '@mk-kit/ui/core';
3
+ import * as _angular_core from '@angular/core';
4
+ import { TemplateRef } from '@angular/core';
5
+
6
+ /**
7
+ * Field kinds `mk-dynamic-form` renders out of the box. Each maps to one
8
+ * mk-kit control; `custom` renders a projected `mkDynamicField` template.
9
+ */
10
+ type MkDynamicFieldType = 'text' | 'email' | 'password' | 'url' | 'tel' | 'search' | 'textarea' | 'number' | 'currency' | 'date' | 'time' | 'datetime' | 'select' | 'multi-select' | 'autocomplete' | 'radio' | 'toggle' | 'checkbox' | 'switch' | 'slider' | 'rating' | 'color' | 'tags' | 'phone' | 'file' | 'code' | 'custom';
11
+ /** One option of a select / radio / toggle / autocomplete field. */
12
+ interface MkDynamicOption {
13
+ label: string;
14
+ value: unknown;
15
+ disabled?: boolean;
16
+ }
17
+ /**
18
+ * Declarative validators — plain data so a schema can be stored as JSON.
19
+ * `custom` takes Angular validator functions for anything else.
20
+ */
21
+ interface MkDynamicValidators {
22
+ min?: number;
23
+ max?: number;
24
+ minLength?: number;
25
+ maxLength?: number;
26
+ /** A RegExp or its source string. */
27
+ pattern?: string | RegExp;
28
+ email?: boolean;
29
+ /** Angular validator functions appended after the declarative ones. */
30
+ custom?: ValidatorFn[];
31
+ }
32
+ /**
33
+ * A serialisable condition over the form value (dotted paths reach into
34
+ * groups: `address.country`). Combine with `and` / `or`; a function is the
35
+ * escape hatch for TypeScript-only schemas.
36
+ */
37
+ type MkDynamicCondition = {
38
+ field: string;
39
+ eq?: unknown;
40
+ neq?: unknown;
41
+ in?: unknown[];
42
+ notIn?: unknown[];
43
+ truthy?: boolean;
44
+ empty?: boolean;
45
+ } | {
46
+ and: MkDynamicCondition[];
47
+ } | {
48
+ or: MkDynamicCondition[];
49
+ } | {
50
+ not: MkDynamicCondition;
51
+ } | ((value: Record<string, unknown>) => boolean);
52
+ /** Properties shared by every field that holds a value. */
53
+ interface MkDynamicFieldBase {
54
+ /** Key in the form value. */
55
+ key: string;
56
+ type: MkDynamicFieldType;
57
+ label?: string;
58
+ hint?: string;
59
+ placeholder?: string;
60
+ required?: boolean;
61
+ disabled?: boolean;
62
+ /** Initial value when the form (or a new array item) is created. */
63
+ default?: unknown;
64
+ validators?: MkDynamicValidators;
65
+ /** Options for select / multi-select / radio / toggle / autocomplete. */
66
+ options?: readonly MkDynamicOption[];
67
+ /**
68
+ * Extra inputs forwarded to the underlying control — the subset each type
69
+ * understands (`rows`, `min`, `max`, `step`, `currency`, `accept`,
70
+ * `multiple`, `swatches`, `language`, …). See the docs table.
71
+ */
72
+ props?: Record<string, unknown>;
73
+ /** Grid columns (1–12) the field spans. Default: the form's `columns` split. */
74
+ span?: number;
75
+ /** Render (and enable) only when the condition holds. Hidden fields are excluded from the value. */
76
+ showWhen?: MkDynamicCondition;
77
+ /** Disable while the condition holds. */
78
+ disabledWhen?: MkDynamicCondition;
79
+ }
80
+ /** A nested object: its fields become a child `FormGroup` under `key`. */
81
+ interface MkDynamicGroup {
82
+ type: 'group';
83
+ key: string;
84
+ label?: string;
85
+ hint?: string;
86
+ fields: MkDynamicField[];
87
+ span?: number;
88
+ /** Columns for the group's own grid (default: inherits the form's). */
89
+ columns?: number;
90
+ showWhen?: MkDynamicCondition;
91
+ disabledWhen?: MkDynamicCondition;
92
+ }
93
+ /** A list of objects: a `FormArray` of groups with add / remove controls. */
94
+ interface MkDynamicArray {
95
+ type: 'array';
96
+ key: string;
97
+ label?: string;
98
+ hint?: string;
99
+ /** Fields of one item. */
100
+ fields: MkDynamicField[];
101
+ min?: number;
102
+ max?: number;
103
+ addLabel?: string;
104
+ /** Initial items (each is patched over the item defaults). */
105
+ default?: Record<string, unknown>[];
106
+ span?: number;
107
+ columns?: number;
108
+ showWhen?: MkDynamicCondition;
109
+ disabledWhen?: MkDynamicCondition;
110
+ }
111
+ /** A heading + description with no value of its own. */
112
+ interface MkDynamicSection {
113
+ type: 'section';
114
+ label: string;
115
+ hint?: string;
116
+ span?: number;
117
+ showWhen?: MkDynamicCondition;
118
+ }
119
+ type MkDynamicField = MkDynamicFieldBase | MkDynamicGroup | MkDynamicArray | MkDynamicSection;
120
+ /** The whole form. */
121
+ interface MkDynamicSchema {
122
+ fields: MkDynamicField[];
123
+ /** Default number of columns fields are laid out in (1–12). Default 1. */
124
+ columns?: number;
125
+ }
126
+ declare function mkIsGroup(f: MkDynamicField): f is MkDynamicGroup;
127
+ declare function mkIsArray(f: MkDynamicField): f is MkDynamicArray;
128
+ declare function mkIsSection(f: MkDynamicField): f is MkDynamicSection;
129
+ declare function mkIsValueField(f: MkDynamicField): f is MkDynamicFieldBase;
130
+
131
+ /** The empty value a field type starts with when no `default` is given. */
132
+ declare function mkDynamicEmptyValue(field: MkDynamicFieldBase): unknown;
133
+ /** Default value object of a field list (groups nested, arrays as item lists). */
134
+ declare function mkDynamicDefaults(fields: readonly MkDynamicField[]): Record<string, unknown>;
135
+ /** Angular validators for one value field, from its declarative `validators` + `required`. */
136
+ declare function mkDynamicValidators(field: MkDynamicFieldBase): ValidatorFn[];
137
+ /** Build the `FormControl` / `FormGroup` / `FormArray` for one field. */
138
+ declare function mkDynamicControl(field: MkDynamicField, value?: unknown): AbstractControl;
139
+ /** A `FormGroup` for a field list; `value` (partial) overrides the defaults. */
140
+ declare function mkDynamicGroup(fields: readonly MkDynamicField[], value?: Record<string, unknown>): FormGroup;
141
+ /** Build the reactive form of a whole schema. */
142
+ declare function mkDynamicForm(schema: MkDynamicSchema, value?: Record<string, unknown>): FormGroup;
143
+ /**
144
+ * Evaluate a condition against a form value. `value` is normally the whole
145
+ * form value; inside an array item the item's own value is used, with the
146
+ * root available under `$root`.
147
+ */
148
+ declare function mkDynamicCondition(cond: MkDynamicCondition | undefined, value: Record<string, unknown>): boolean;
149
+ /** Depth-first list of every value field with its dotted path. */
150
+ declare function mkDynamicFlatten(fields: readonly MkDynamicField[], prefix?: string): Array<{
151
+ path: string;
152
+ field: MkDynamicFieldBase | MkDynamicGroup | MkDynamicArray;
153
+ }>;
154
+ /** Column span a field takes in a grid of `columns`. */
155
+ declare function mkDynamicSpan(field: MkDynamicField, columns: number): number;
156
+
157
+ /** Context handed to a custom field template. */
158
+ interface MkDynamicFieldContext {
159
+ $implicit: MkDynamicFieldBase;
160
+ field: MkDynamicFieldBase;
161
+ /** The field's `FormControl` — bind it with `[formControl]`. */
162
+ control: FormControl;
163
+ /** The current value of the whole form (or array item). */
164
+ value: Record<string, unknown>;
165
+ }
166
+ /**
167
+ * Registers a renderer for a custom field type:
168
+ *
169
+ * ```html
170
+ * <mk-dynamic-form [schema]="schema">
171
+ * <ng-template mkDynamicField="signature" let-field let-control="control">
172
+ * <mk-signature-pad [formControl]="control" />
173
+ * </ng-template>
174
+ * </mk-dynamic-form>
175
+ * ```
176
+ *
177
+ * A field `{ type: 'custom', key: 'sig', props: { renderer: 'signature' } }`
178
+ * (or any built-in `type` you want to override) then renders this template
179
+ * inside the usual `mk-form-field`.
180
+ */
181
+ declare class MkDynamicFieldDef {
182
+ /** The type (or `props.renderer` name) this template renders. */
183
+ readonly mkDynamicField: _angular_core.InputSignal<string>;
184
+ readonly template: TemplateRef<MkDynamicFieldContext>;
185
+ static ngTemplateContextGuard(_dir: MkDynamicFieldDef, ctx: unknown): ctx is MkDynamicFieldContext;
186
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkDynamicFieldDef, never>;
187
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MkDynamicFieldDef, "ng-template[mkDynamicField]", never, { "mkDynamicField": { "alias": "mkDynamicField"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
188
+ }
189
+ /**
190
+ * Renders one field list (the root, a group, or one array item) as a grid.
191
+ * Internal — projected by {@link MkDynamicForm}; recursive for groups/arrays.
192
+ */
193
+ declare class MkDynamicFields {
194
+ private readonly root;
195
+ protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
196
+ readonly fields: _angular_core.InputSignal<readonly MkDynamicField[]>;
197
+ readonly group: _angular_core.InputSignal<FormGroup<any>>;
198
+ readonly columns: _angular_core.InputSignalWithTransform<number, unknown>;
199
+ /** Value the conditions of this level are evaluated against. */
200
+ readonly scope: _angular_core.InputSignal<Record<string, unknown>>;
201
+ protected readonly labelPosition: _angular_core.Signal<any>;
202
+ protected readonly size: _angular_core.Signal<any>;
203
+ protected control(f: MkDynamicField): AbstractControl;
204
+ protected formGroup(f: MkDynamicGroup): FormGroup;
205
+ protected formArray(f: MkDynamicArray): FormArray<FormGroup>;
206
+ protected isVisible(f: MkDynamicField): boolean;
207
+ protected span(f: MkDynamicField): number;
208
+ protected columnsOf(f: MkDynamicGroup | MkDynamicArray): number;
209
+ protected isGroup: typeof mkIsGroup;
210
+ protected isArray: typeof mkIsArray;
211
+ protected isSection: typeof mkIsSection;
212
+ protected isValue: typeof mkIsValueField;
213
+ /** Custom template for a value field, if one is registered. */
214
+ protected customTemplate(f: MkDynamicFieldBase): TemplateRef<MkDynamicFieldContext> | null;
215
+ protected customContext(f: MkDynamicFieldBase): MkDynamicFieldContext;
216
+ /** `props.x` with a typed default. */
217
+ protected p(f: MkDynamicFieldBase, key: string, fallback: unknown): any;
218
+ protected inputType(f: MkDynamicFieldBase): string;
219
+ protected itemScope(f: MkDynamicArray, index: number): Record<string, unknown>;
220
+ protected canAdd(f: MkDynamicArray): boolean;
221
+ protected canRemove(f: MkDynamicArray): boolean;
222
+ protected addItem(f: MkDynamicArray): void;
223
+ protected removeItem(f: MkDynamicArray, index: number): void;
224
+ protected trackItem(index: number, item: FormGroup): FormGroup;
225
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkDynamicFields, never>;
226
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDynamicFields, "mk-dynamic-fields", never, { "fields": { "alias": "fields"; "required": true; "isSignal": true; }; "group": { "alias": "group"; "required": true; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "scope": { "alias": "scope"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
227
+ }
228
+ /**
229
+ * Dynamic form — renders a form from a JSON schema and manages one reactive
230
+ * `FormGroup` for it. Every value field renders inside `mk-form-field`, so
231
+ * labels, hints, required marks and localised validation messages come from
232
+ * the schema alone.
233
+ *
234
+ * ```html
235
+ * <mk-dynamic-form [schema]="schema" [(value)]="user" (formSubmit)="save($event)">
236
+ * <button mkButton type="submit">Save</button>
237
+ * </mk-dynamic-form>
238
+ * ```
239
+ *
240
+ * ```ts
241
+ * schema: MkDynamicSchema = {
242
+ * columns: 2,
243
+ * fields: [
244
+ * { key: 'name', type: 'text', label: 'Name', required: true },
245
+ * { key: 'role', type: 'select', label: 'Role', options: roles },
246
+ * { key: 'company', type: 'text', label: 'Company', showWhen: { field: 'role', eq: 'b2b' } },
247
+ * ],
248
+ * };
249
+ * ```
250
+ *
251
+ * - Hidden fields (`showWhen` false) are disabled, so `value` only carries
252
+ * what the user can see; `form.getRawValue()` has everything.
253
+ * - `form` is the live `FormGroup` for anything the schema does not cover.
254
+ * - Custom field types: project an `ng-template[mkDynamicField]`.
255
+ */
256
+ declare class MkDynamicForm {
257
+ private readonly destroyRef;
258
+ /** The schema. Changing it rebuilds the form (values of surviving keys are kept). */
259
+ readonly schema: _angular_core.InputSignal<MkDynamicSchema>;
260
+ /** Two-way form value (visible, enabled fields only). */
261
+ readonly value: _angular_core.ModelSignal<Record<string, unknown>>;
262
+ /** Disable every control. */
263
+ readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
264
+ /** Label placement forwarded to every `mk-form-field`. */
265
+ readonly labelPosition: _angular_core.InputSignal<"top" | "float">;
266
+ /** Control size forwarded to the fields. */
267
+ readonly size: _angular_core.InputSignal<"sm" | "md" | "lg">;
268
+ /** Emits the value when the form is submitted and valid. */
269
+ readonly formSubmit: _angular_core.OutputEmitterRef<Record<string, unknown>>;
270
+ /** Emits when a submit is attempted while invalid (every control is marked touched). */
271
+ readonly invalidSubmit: _angular_core.OutputEmitterRef<FormGroup<any>>;
272
+ private readonly defs;
273
+ private readonly formSignal;
274
+ private readonly formValue;
275
+ private subscription;
276
+ private applying;
277
+ /** The live reactive form. */
278
+ get form(): FormGroup;
279
+ protected readonly formRef: _angular_core.Signal<FormGroup<any>>;
280
+ /** Value including disabled fields — what conditions are evaluated against. */
281
+ protected readonly scope: _angular_core.Signal<Record<string, unknown>>;
282
+ protected readonly columns: _angular_core.Signal<number>;
283
+ protected readonly fields: _angular_core.Signal<MkDynamicField[]>;
284
+ /** `true` while every control passes validation. */
285
+ readonly valid: _angular_core.Signal<boolean>;
286
+ constructor();
287
+ private attach;
288
+ /** Re-evaluate conditions and push the form value to `value`. @internal */
289
+ sync(): void;
290
+ private applyConditions;
291
+ /** Template registered for a custom type / renderer name. @internal */
292
+ templateFor(name: string): TemplateRef<MkDynamicFieldContext> | null;
293
+ /** Patch part of the value. */
294
+ patch(value: Record<string, unknown>): void;
295
+ /** Reset to the schema defaults (or the given value). */
296
+ reset(value?: Record<string, unknown>): void;
297
+ /** Mark every control touched so validation messages show. */
298
+ touchAll(): void;
299
+ protected onSubmit(event: Event): void;
300
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkDynamicForm, never>;
301
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDynamicForm, "mk-dynamic-form", never, { "schema": { "alias": "schema"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "labelPosition": { "alias": "labelPosition"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "formSubmit": "formSubmit"; "invalidSubmit": "invalidSubmit"; }, ["defs"], ["*"], true, never>;
302
+ }
303
+
304
+ export { MkDynamicFieldDef, MkDynamicFields, MkDynamicForm, mkDynamicCondition, mkDynamicControl, mkDynamicDefaults, mkDynamicEmptyValue, mkDynamicFlatten, mkDynamicForm, mkDynamicGroup, mkDynamicSpan, mkDynamicValidators, mkIsArray, mkIsGroup, mkIsSection, mkIsValueField };
305
+ export type { MkDynamicArray, MkDynamicCondition, MkDynamicField, MkDynamicFieldBase, MkDynamicFieldContext, MkDynamicFieldType, MkDynamicGroup, MkDynamicGroup as MkDynamicGroupField, MkDynamicOption, MkDynamicSchema, MkDynamicSection, MkDynamicValidators };
@@ -543,13 +543,53 @@ declare class MkDialog {
543
543
  readonly titleId: _angular_core.InputSignal<string>;
544
544
  /** Hide the header close button. */
545
545
  readonly hideClose: _angular_core.InputSignalWithTransform<boolean, unknown>;
546
+ /**
547
+ * Let the user move the dialog by dragging its header (pointer / touch) or
548
+ * with the arrow keys on the grip that appears in the header. Double-click
549
+ * the header or press Home on the grip to snap back to the centre.
550
+ */
551
+ readonly draggable: _angular_core.InputSignalWithTransform<boolean, unknown>;
552
+ /**
553
+ * Let the user resize the dialog from the corner grip (pointer / touch, or
554
+ * arrow keys on the grip; Home resets). The panel never grows past the
555
+ * viewport or shrinks below a usable minimum.
556
+ */
557
+ readonly resizable: _angular_core.InputSignalWithTransform<boolean, unknown>;
558
+ private readonly destroyRef;
559
+ /** The body-level overlay panel this dialog lives in (`null` when inline). */
560
+ private panelEl;
561
+ /** Current drag offset from the centred position, px. */
562
+ private offset;
546
563
  constructor();
547
564
  /** Close the surrounding overlay, if any. */
548
565
  protected close(): void;
566
+ /** Snap back to the centred, preset-sized panel. */
567
+ reset(): void;
568
+ protected onHeaderPointerDown(event: PointerEvent): void;
569
+ protected onGripPointerDown(event: PointerEvent): void;
570
+ protected onResizerPointerDown(event: PointerEvent): void;
571
+ protected onHeaderDoubleClick(event: MouseEvent): void;
572
+ protected onGripKeydown(event: KeyboardEvent): void;
573
+ protected onResizerKeydown(event: KeyboardEvent): void;
574
+ private static arrowDelta;
575
+ private startPointer;
576
+ /** Move the panel to `(x, y)` px from its centred spot, kept inside the viewport. */
577
+ private moveTo;
578
+ /** Resize the panel to `w × h` px within [minimum, viewport]. */
579
+ private resizeTo;
580
+ /**
581
+ * Once the user takes hold, the entrance animation must never run again —
582
+ * toggling `animation` back on (as a transient class would) restarts it,
583
+ * so the panel would blink after every drag. The class is never removed.
584
+ */
585
+ private markMoved;
586
+ private clampIntoView;
587
+ private isRtl;
588
+ private panel;
549
589
  /** Point the owning dialog panel's `aria-labelledby` at the title element. */
550
590
  private wireLabelledBy;
551
591
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkDialog, never>;
552
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDialog, "mk-dialog", never, { "dialogTitle": { "alias": "dialogTitle"; "required": false; "isSignal": true; }; "titleId": { "alias": "titleId"; "required": false; "isSignal": true; }; "hideClose": { "alias": "hideClose"; "required": false; "isSignal": true; }; }, {}, never, ["[mkDialogHeader], mk-dialog-title", "*", "[mkDialogFooter]"], true, never>;
592
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDialog, "mk-dialog", never, { "dialogTitle": { "alias": "dialogTitle"; "required": false; "isSignal": true; }; "titleId": { "alias": "titleId"; "required": false; "isSignal": true; }; "hideClose": { "alias": "hideClose"; "required": false; "isSignal": true; }; "draggable": { "alias": "draggable"; "required": false; "isSignal": true; }; "resizable": { "alias": "resizable"; "required": false; "isSignal": true; }; }, {}, never, ["[mkDialogHeader], mk-dialog-title", "*", "[mkDialogFooter]"], true, never>;
553
593
  }
554
594
 
555
595
  /** Data contract for {@link MkConfirmDialog} / `MkDialogService.confirm`. */
@@ -1266,5 +1306,74 @@ declare class MkTourService {
1266
1306
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<MkTourService>;
1267
1307
  }
1268
1308
 
1269
- export { MK_TOUR_DATA, MkAlert, MkBanner, MkBottomSheet, MkBottomSheetService, MkConfirmDialog, MkDialog, MkDialogService, MkDialogTitle, MkHovercard, MkHovercardTrigger, MkLoadingBar, MkLoadingBarService, MkNotificationCenter, MkPopconfirm, MkPopconfirmTrigger, MkPopover, MkPopoverTrigger, MkPromptDialog, MkResult, MkSnackbar, MkSnackbarContainer, MkSnackbarRef, MkSnackbarService, MkToast, MkToastContainer, MkToastService, MkTooltip, MkTooltipPanel, MkTourPopup, MkTourService };
1309
+ /**
1310
+ * The translucent panel with a spinner that `mkBlockUi` and
1311
+ * `MkBlockUiService` drop over a region or the page.
1312
+ */
1313
+ declare class MkBlockUiOverlay {
1314
+ protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
1315
+ readonly message: _angular_core.WritableSignal<string>;
1316
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkBlockUiOverlay, never>;
1317
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkBlockUiOverlay, "mk-block-ui-overlay", never, {}, {}, never, never, true, never>;
1318
+ }
1319
+ /**
1320
+ * Block UI — cover the host element with a translucent panel and spinner
1321
+ * while something loads, so its contents can neither be read nor operated:
1322
+ * a card refreshing, a form submitting, a table re-fetching.
1323
+ *
1324
+ * Children get `inert` (no clicks, no Tab stops) and the host `aria-busy`.
1325
+ * `mkBlockUiDelay` (ms) holds the overlay back for quick operations so the
1326
+ * screen does not flash.
1327
+ *
1328
+ * ```html
1329
+ * <mk-card [mkBlockUi]="saving()" mkBlockUiMessage="Saving…">…</mk-card>
1330
+ * <form [mkBlockUi]="submitting()" [mkBlockUiDelay]="300">…</form>
1331
+ * ```
1332
+ */
1333
+ declare class MkBlockUi {
1334
+ private readonly host;
1335
+ private readonly document;
1336
+ private readonly injector;
1337
+ private readonly appRef;
1338
+ /** Block while `true`. */
1339
+ readonly mkBlockUi: _angular_core.InputSignalWithTransform<boolean, unknown>;
1340
+ /** Text under the spinner (also its accessible label). */
1341
+ readonly mkBlockUiMessage: _angular_core.InputSignal<string>;
1342
+ /** Wait this many ms before showing, to avoid a flash on fast operations. */
1343
+ readonly mkBlockUiDelay: _angular_core.InputSignalWithTransform<number, unknown>;
1344
+ private mounted;
1345
+ private timer;
1346
+ constructor();
1347
+ private mount;
1348
+ private unmount;
1349
+ private cancelTimer;
1350
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkBlockUi, never>;
1351
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MkBlockUi, "[mkBlockUi]", never, { "mkBlockUi": { "alias": "mkBlockUi"; "required": false; "isSignal": true; }; "mkBlockUiMessage": { "alias": "mkBlockUiMessage"; "required": false; "isSignal": true; }; "mkBlockUiDelay": { "alias": "mkBlockUiDelay"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1352
+ }
1353
+ /**
1354
+ * Block the whole page. Reference-counted: every `block()` returns a release
1355
+ * function, and the overlay disappears once all of them have been called.
1356
+ *
1357
+ * ```ts
1358
+ * const release = this.blockUi.block('Exporting…');
1359
+ * try { await this.api.export(); } finally { release(); }
1360
+ * ```
1361
+ */
1362
+ declare class MkBlockUiService {
1363
+ private readonly document;
1364
+ private readonly injector;
1365
+ private readonly appRef;
1366
+ private mounted;
1367
+ private readonly _count;
1368
+ /** Number of active blocks. */
1369
+ readonly count: _angular_core.Signal<number>;
1370
+ /** Show the page overlay (or update its message); call the returned function to release. */
1371
+ block(message?: string): () => void;
1372
+ /** True while the page is blocked. */
1373
+ isBlocked(): boolean;
1374
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkBlockUiService, never>;
1375
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<MkBlockUiService>;
1376
+ }
1377
+
1378
+ export { MK_TOUR_DATA, MkAlert, MkBanner, MkBlockUi, MkBlockUiOverlay, MkBlockUiService, MkBottomSheet, MkBottomSheetService, MkConfirmDialog, MkDialog, MkDialogService, MkDialogTitle, MkHovercard, MkHovercardTrigger, MkLoadingBar, MkLoadingBarService, MkNotificationCenter, MkPopconfirm, MkPopconfirmTrigger, MkPopover, MkPopoverTrigger, MkPromptDialog, MkResult, MkSnackbar, MkSnackbarContainer, MkSnackbarRef, MkSnackbarService, MkToast, MkToastContainer, MkToastService, MkTooltip, MkTooltipPanel, MkTourPopup, MkTourService };
1270
1379
  export type { MkAlertTone, MkAlertVariant, MkBottomSheetConfig, MkConfirmDialogData, MkDialogConfig, MkDialogSize, MkNotification, MkPromptDialogData, MkResultIconVariant, MkResultStatus, MkResultTone, MkSnackbarConfig, MkSnackbarDismissReason, MkSnackbarItem, MkSnackbarTone, MkToastAction, MkToastConfig, MkToastItem, MkToastTone, MkTourController, MkTourData, MkTourStep };