@mk-kit/ui 0.41.0 → 0.43.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.
Files changed (53) hide show
  1. package/README.md +4 -4
  2. package/THIRD_PARTY_NOTICES.md +4 -2
  3. package/fesm2022/mk-kit-ui-block-editor.mjs +4 -2
  4. package/fesm2022/mk-kit-ui-block-editor.mjs.map +1 -1
  5. package/fesm2022/mk-kit-ui-checkbox.mjs +4 -2
  6. package/fesm2022/mk-kit-ui-checkbox.mjs.map +1 -1
  7. package/fesm2022/mk-kit-ui-core.mjs +218 -1
  8. package/fesm2022/mk-kit-ui-core.mjs.map +1 -1
  9. package/fesm2022/mk-kit-ui-data.mjs +801 -16
  10. package/fesm2022/mk-kit-ui-data.mjs.map +1 -1
  11. package/fesm2022/mk-kit-ui-datetime.mjs +90 -52
  12. package/fesm2022/mk-kit-ui-datetime.mjs.map +1 -1
  13. package/fesm2022/mk-kit-ui-directives.mjs +395 -2
  14. package/fesm2022/mk-kit-ui-directives.mjs.map +1 -1
  15. package/fesm2022/mk-kit-ui-dnd.mjs +183 -29
  16. package/fesm2022/mk-kit-ui-dnd.mjs.map +1 -1
  17. package/fesm2022/mk-kit-ui-dynamic-form.mjs +149 -2
  18. package/fesm2022/mk-kit-ui-dynamic-form.mjs.map +1 -1
  19. package/fesm2022/mk-kit-ui-feedback.mjs +1 -1
  20. package/fesm2022/mk-kit-ui-feedback.mjs.map +1 -1
  21. package/fesm2022/mk-kit-ui-forms.mjs +331 -81
  22. package/fesm2022/mk-kit-ui-forms.mjs.map +1 -1
  23. package/fesm2022/mk-kit-ui-icon-extended.mjs +425 -0
  24. package/fesm2022/mk-kit-ui-icon-extended.mjs.map +1 -0
  25. package/fesm2022/mk-kit-ui-icon.mjs +296 -459
  26. package/fesm2022/mk-kit-ui-icon.mjs.map +1 -1
  27. package/fesm2022/mk-kit-ui-query-builder.mjs +1 -1
  28. package/fesm2022/mk-kit-ui-query-builder.mjs.map +1 -1
  29. package/fesm2022/mk-kit-ui-rich-text.mjs +4 -2
  30. package/fesm2022/mk-kit-ui-rich-text.mjs.map +1 -1
  31. package/fesm2022/mk-kit-ui-table.mjs +36 -8
  32. package/fesm2022/mk-kit-ui-table.mjs.map +1 -1
  33. package/fesm2022/mk-kit-ui.mjs +1 -0
  34. package/fesm2022/mk-kit-ui.mjs.map +1 -1
  35. package/package.json +5 -1
  36. package/schematics/migrate-primeng/transform.js +4 -1
  37. package/schematics/ng-add/index.js +30 -2
  38. package/schematics/ng-add/schema.json +6 -0
  39. package/styles/mk-kit.css +604 -0
  40. package/types/mk-kit-ui-block-editor.d.ts +2 -0
  41. package/types/mk-kit-ui-checkbox.d.ts +2 -0
  42. package/types/mk-kit-ui-core.d.ts +119 -2
  43. package/types/mk-kit-ui-data.d.ts +359 -3
  44. package/types/mk-kit-ui-datetime.d.ts +41 -19
  45. package/types/mk-kit-ui-directives.d.ts +234 -3
  46. package/types/mk-kit-ui-dnd.d.ts +96 -14
  47. package/types/mk-kit-ui-dynamic-form.d.ts +44 -1
  48. package/types/mk-kit-ui-forms.d.ts +160 -20
  49. package/types/mk-kit-ui-icon-extended.d.ts +83 -0
  50. package/types/mk-kit-ui-icon.d.ts +100 -17
  51. package/types/mk-kit-ui-rich-text.d.ts +2 -0
  52. package/types/mk-kit-ui-table.d.ts +38 -21
  53. package/types/mk-kit-ui.d.ts +1 -0
@@ -26,6 +26,18 @@ type MkPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' |
26
26
  * both a mouse-driven admin and a touch-driven screen.
27
27
  */
28
28
  type MkDensity = 'comfortable' | 'compact' | 'touch';
29
+ /**
30
+ * Contrast preference.
31
+ *
32
+ * `high` applies the high-contrast token preset (`data-mk-contrast="high"`):
33
+ * pure text colours, line-like borders, opaque interaction washes, a thicker
34
+ * focus ring. `system` (the default) writes no attribute and lets the
35
+ * stylesheet follow the OS `prefers-contrast: more` setting; `normal` opts
36
+ * out of that even when the OS asks for more contrast.
37
+ */
38
+ type MkContrastPreference = 'normal' | 'high' | 'system';
39
+ /** Concrete resolved contrast (never `system`). */
40
+ type MkResolvedContrast = 'normal' | 'high';
29
41
  /**
30
42
  * Reactive theme controller for mk-kit.
31
43
  *
@@ -61,6 +73,22 @@ declare class MkThemeService {
61
73
  * it.
62
74
  */
63
75
  readonly density: _angular_core.Signal<MkDensity>;
76
+ private readonly _contrast;
77
+ /**
78
+ * The user's contrast preference: `normal`, `high` or `system` (follow the
79
+ * OS `prefers-contrast` setting — the default). Written as
80
+ * `data-mk-contrast` on `<html>` and persisted; `system` removes the
81
+ * attribute so the pure-CSS `prefers-contrast: more` mapping takes over.
82
+ *
83
+ * Like density, the attribute also works per subtree: put
84
+ * `data-mk-contrast="high"` on any element to raise contrast there only.
85
+ */
86
+ readonly contrast: _angular_core.Signal<MkContrastPreference>;
87
+ private readonly _systemPrefersContrast;
88
+ /** The concrete contrast in effect (`normal` or `high`). */
89
+ readonly resolvedContrast: _angular_core.Signal<MkResolvedContrast>;
90
+ /** Convenience boolean for template bindings. */
91
+ readonly isHighContrast: _angular_core.Signal<boolean>;
64
92
  constructor();
65
93
  /** Set the global density mode. */
66
94
  setDensity(density: MkDensity): void;
@@ -72,6 +100,13 @@ declare class MkThemeService {
72
100
  */
73
101
  toggleDensity(): void;
74
102
  private readInitialDensity;
103
+ /** Set the contrast preference explicitly. */
104
+ setContrast(contrast: MkContrastPreference): void;
105
+ /** Toggle between normal and high contrast (resolving `system` first). */
106
+ toggleContrast(): void;
107
+ private readInitialContrast;
108
+ private readSystemContrast;
109
+ private watchSystemContrast;
75
110
  /** Set the theme preference explicitly. */
76
111
  setTheme(preference: MkThemePreference): void;
77
112
  /** Toggle between light and dark (resolving `system` first). */
@@ -712,6 +747,18 @@ interface MkValidationStrings {
712
747
  * strings are functions so translators control word order.
713
748
  */
714
749
  interface MkI18nStrings {
750
+ /**
751
+ * BCP 47 locale tag (`'pl-PL'`, `'de'`) used by the formatting pipes
752
+ * (`mkCurrency`, `mkRelativeTime`, `mkFileSize`, `mkPluralize`) and any
753
+ * other `Intl`-based formatting that has no explicit locale of its own.
754
+ * Unset → the runtime (browser / Node) default locale.
755
+ */
756
+ locale?: string;
757
+ /**
758
+ * ISO 4217 currency code the `mkCurrency` pipe falls back to when the
759
+ * template passes none. Unset → `'USD'`.
760
+ */
761
+ currency?: string;
715
762
  /** Validation messages (deep-merged by provideMkI18n). */
716
763
  validation: MkValidationStrings;
717
764
  /** Generic "Close" control (dialog, drawer, bottom-sheet). */
@@ -933,6 +980,12 @@ interface MkI18nStrings {
933
980
  logCopyAll: string;
934
981
  /** Log viewer: soft-wrap toolbar toggle. */
935
982
  logWrapLines: string;
983
+ /** Org chart: default accessible label of the tree. */
984
+ orgChartLabel: string;
985
+ /** Org chart: aria-label of a collapsed node's toggle (`{label}` = node label). */
986
+ orgChartExpand: string;
987
+ /** Org chart: aria-label of an expanded node's toggle (`{label}` = node label). */
988
+ orgChartCollapse: string;
936
989
  /** Chat: accessible name of the message log. */
937
990
  chatLabel: string;
938
991
  /** Chat: accessible name of the composer textarea. */
@@ -1268,6 +1321,70 @@ type MkErrorMessages = Readonly<Record<string, string | ((err: any) => string)>>
1268
1321
  */
1269
1322
  declare function mkFirstErrorMessage(errors: ValidationErrors | null | undefined, strings: MkValidationStrings, overrides?: MkErrorMessages): string | null;
1270
1323
 
1324
+ /**
1325
+ * The shape of a Signal Forms validation error as `mk-kit` reads it — the
1326
+ * `{ kind, message? }` contract of `ValidationError` from
1327
+ * `@angular/forms/signals`, plus whatever payload the error class carries
1328
+ * (`min`, `maxLength`, `pattern`, …). Declared structurally so `@mk-kit/ui/core`
1329
+ * stays free of a runtime dependency on the signals entry point.
1330
+ */
1331
+ interface MkSignalValidationError {
1332
+ /** Identifies the kind of error (`'required'`, `'minLength'`, …). */
1333
+ readonly kind: string;
1334
+ /** Human-readable message, when the schema supplied one. */
1335
+ readonly message?: string;
1336
+ }
1337
+ /**
1338
+ * Converts Signal Forms errors to the reactive-forms `ValidationErrors` shape
1339
+ * the `validation` i18n table is keyed by, so both form systems render the
1340
+ * same messages. The built-in kinds map to Angular's classic keys and payloads
1341
+ * (`minLength` → `minlength: { requiredLength }`, `minDate` → `mkMinDate`,
1342
+ * …); any other kind is kept as-is with its payload spread into the value.
1343
+ *
1344
+ * @returns The error map in the order the errors were reported, or `null`
1345
+ * when the list is empty.
1346
+ */
1347
+ declare function mkSignalErrorsToValidationErrors(errors: readonly MkSignalValidationError[] | null | undefined): ValidationErrors | null;
1348
+ /**
1349
+ * Resolves the message for the first Signal Forms error on a field, the way
1350
+ * `mkFirstErrorMessage` does for reactive forms.
1351
+ *
1352
+ * Lookup order: the field's `overrides` for that kind, then the `message` the
1353
+ * schema attached to the error (`required(p.email, { message: '…' })`), then
1354
+ * the i18n `validation` table, then the generic fallback.
1355
+ *
1356
+ * @returns The message, or `null` when there are no errors.
1357
+ */
1358
+ declare function mkSignalErrorMessage(errors: readonly MkSignalValidationError[] | null | undefined, strings: MkValidationStrings, overrides?: MkErrorMessages): string | null;
1359
+
1360
+ /**
1361
+ * Touched-gate for a control's `invalid` input under Signal Forms.
1362
+ *
1363
+ * When a control is bound with the `[formField]` directive, Angular writes the
1364
+ * field's `invalid()` state straight into the control's `invalid` input — from
1365
+ * the first render, before the user has reached the field. mk-kit controls
1366
+ * pass that input through this gate so the invalid visual (and `aria-invalid`)
1367
+ * only shows once the field is touched or dirty, matching how `mk-form-field`
1368
+ * reveals its message and how `submit()` (which marks every field touched)
1369
+ * surfaces the remaining problems.
1370
+ *
1371
+ * Returns a signal that is always `true` for a control that is not bound with
1372
+ * `[formField]`, so a standalone `[invalid]="true"` keeps working as before.
1373
+ * Call it in a field initializer (an injection context):
1374
+ *
1375
+ * ```ts
1376
+ * private readonly fieldTouched = mkInjectFieldTouched();
1377
+ * protected readonly isInvalid = computed(
1378
+ * () => (this.invalid() && this.fieldTouched()) || (this.field?.hasError() ?? false),
1379
+ * );
1380
+ * ```
1381
+ *
1382
+ * The binding is looked up lazily, on first read: the `FormField` directive
1383
+ * itself injects the element's `NG_VALUE_ACCESSOR` (the control) while it is
1384
+ * created, so resolving it from the control's constructor would be circular.
1385
+ */
1386
+ declare function mkInjectFieldTouched(): Signal<boolean>;
1387
+
1271
1388
  /** Value kind of a filterable field; decides the editor and the operators offered. */
1272
1389
  type MkQueryValueType = 'string' | 'number' | 'boolean' | 'date' | 'select';
1273
1390
  /** A choice for `select` fields. */
@@ -1346,5 +1463,5 @@ declare function mkQueryOperatorLabel(op: MkQueryOperator, i18n?: MkI18nStrings)
1346
1463
  */
1347
1464
  declare function mkQueryToText(group: MkQueryGroup, fields?: readonly MkQueryField[], i18n?: MkI18nStrings): string;
1348
1465
 
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 };
1466
+ 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, mkInjectFieldTouched, mkIsQueryGroup, mkIsResponsive, mkQueryCompact, mkQueryIsEmpty, mkQueryOperatorLabel, mkQueryOperatorsFor, mkQueryRuleCount, mkQueryRuleIsComplete, mkQueryRuleMatches, mkQueryToPredicate, mkQueryToText, mkSignalErrorMessage, mkSignalErrorsToValidationErrors, mkUniqueId, mkValidatorChange, provideMkI18n };
1467
+ export type { MkAnchoredPosition, MkAnchoredPositionOptions, MkAriaLivePoliteness, MkBlockEditorStrings, MkBreakpoint, MkBreakpoints, MkCodeLanguage, MkContrastPreference, MkDateNames, MkDensity, MkErrorMessages, MkI18nStrings, MkOverlayConfig, MkPlacement, MkQueryCombinator, MkQueryField, MkQueryFieldOption, MkQueryGroup, MkQueryNode, MkQueryOperator, MkQueryRule, MkQueryValueType, MkResolvedContrast, MkResolvedTheme, MkResponsive, MkSignalValidationError, MkSize$1 as MkSize, MkSortAnnounceDirection, MkThemePreference, MkTone, MkValidationStrings, MkValidatorChangeRef, MkVariant };
@@ -107,6 +107,81 @@ declare class MkBadge {
107
107
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkBadge, "mk-badge", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
108
108
  }
109
109
 
110
+ /** Corner of the host an {@link MkBadgeOverlay} is anchored to. */
111
+ type MkBadgeOverlayPosition = 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start';
112
+ /**
113
+ * Badge overlay — anchors a small badge (count, dot or short text) to a corner
114
+ * of ANY element: an icon button, an avatar, a tab label. The host stays a
115
+ * single tab stop; the badge is a decorative, non-focusable child.
116
+ *
117
+ * - Numbers above `mkBadgeOverlayMax` (default 99) collapse to `99+`.
118
+ * - `mkBadgeOverlayDot` renders a textless dot ("something is new").
119
+ * - `mkBadgeOverlayAriaLabel` is the screen-reader text ("3 unread"). It is
120
+ * rendered in a visually hidden span and wired to the host with
121
+ * `aria-describedby`, so it is announced after the host's own name even
122
+ * when the host has an `aria-label`. When it is given, the visible badge is
123
+ * `aria-hidden` so the count is not read twice.
124
+ * - Positions use logical insets, so `top-end` sits at the top-right in LTR
125
+ * and the top-left in RTL.
126
+ *
127
+ * The badge is painted with the global `.mk-badge-overlay` styles from
128
+ * `@mk-kit/ui/styles.css` and follows the `--mk-*` tone tokens.
129
+ *
130
+ * ```html
131
+ * <button mkButton iconOnly aria-label="Notifications"
132
+ * [mkBadgeOverlay]="unread()" mkBadgeOverlayTone="danger"
133
+ * [mkBadgeOverlayAriaLabel]="unread() + ' unread'">
134
+ * <mk-icon name="bell" />
135
+ * </button>
136
+ *
137
+ * <mk-avatar name="Ada Lovelace" mkBadgeOverlay mkBadgeOverlayDot
138
+ * mkBadgeOverlayTone="success" mkBadgeOverlayPosition="bottom-end" />
139
+ * ```
140
+ */
141
+ declare class MkBadgeOverlay {
142
+ private readonly host;
143
+ private readonly renderer;
144
+ private readonly document;
145
+ private readonly isBrowser;
146
+ /**
147
+ * Badge content — a count or a short label. `null` / empty hides the badge
148
+ * unless `mkBadgeOverlayDot` is set. Numeric strings are treated as numbers
149
+ * so `mkBadgeOverlay="120"` also collapses to `99+`.
150
+ */
151
+ readonly content: _angular_core.InputSignal<string | number | null | undefined>;
152
+ /** Corner the badge is anchored to (logical: `end` flips in RTL). */
153
+ readonly position: _angular_core.InputSignal<MkBadgeOverlayPosition>;
154
+ /** Semantic color tone (same scale as `mk-badge`). */
155
+ readonly tone: _angular_core.InputSignal<MkTone>;
156
+ /** Render a textless dot instead of the content. */
157
+ readonly dot: _angular_core.InputSignalWithTransform<boolean, unknown>;
158
+ /** Numbers above this render as `<max>+`. `0` disables the cap. */
159
+ readonly max: _angular_core.InputSignalWithTransform<number, unknown>;
160
+ /** Hide the badge while keeping the directive (and its aria wiring) in place. */
161
+ readonly hidden: _angular_core.InputSignalWithTransform<boolean, unknown>;
162
+ /**
163
+ * Screen-reader text for the badge, e.g. `"3 unread"`. Announced as the
164
+ * host's description; the visible badge becomes `aria-hidden`.
165
+ */
166
+ readonly ariaLabel: _angular_core.InputSignal<string>;
167
+ /** The text painted in the badge (`''` in dot mode). */
168
+ readonly label: _angular_core.Signal<string>;
169
+ /** Whether the badge is currently rendered. */
170
+ readonly visible: _angular_core.Signal<boolean>;
171
+ private readonly srId;
172
+ private badge;
173
+ private sr;
174
+ /** Set when WE made the host positioned, so we can undo it on removal. */
175
+ private positionedHost;
176
+ constructor();
177
+ private attach;
178
+ private detach;
179
+ /** Create / update / remove the hidden description and its aria-describedby link. */
180
+ private syncSr;
181
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkBadgeOverlay, never>;
182
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MkBadgeOverlay, "[mkBadgeOverlay]", never, { "content": { "alias": "mkBadgeOverlay"; "required": false; "isSignal": true; }; "position": { "alias": "mkBadgeOverlayPosition"; "required": false; "isSignal": true; }; "tone": { "alias": "mkBadgeOverlayTone"; "required": false; "isSignal": true; }; "dot": { "alias": "mkBadgeOverlayDot"; "required": false; "isSignal": true; }; "max": { "alias": "mkBadgeOverlayMax"; "required": false; "isSignal": true; }; "hidden": { "alias": "mkBadgeOverlayHidden"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "mkBadgeOverlayAriaLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
183
+ }
184
+
110
185
  /** Visual treatment for a {@link MkTag}. */
111
186
  type MkTagVariant = 'solid' | 'soft' | 'outline';
112
187
  /**
@@ -310,6 +385,205 @@ declare class MkTimelineItem {
310
385
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkTimelineItem, "mk-timeline-item", never, { "tone": { "alias": "tone"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "time": { "alias": "time"; "required": false; "isSignal": true; }; "heading": { "alias": "heading"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
311
386
  }
312
387
 
388
+ /** A node in an {@link MkOrgChart} tree. `children` makes it a parent. */
389
+ interface MkOrgChartNode<T = unknown> {
390
+ /** Unique id — drives selection (`[(selected)]`) and expansion (`[(expanded)]`). */
391
+ id: string;
392
+ /** Primary text of the default card (and the initials fallback). */
393
+ label?: string;
394
+ /**
395
+ * Arbitrary payload handed to the node template. The default card reads
396
+ * `data.title` (sub-label) and `data.avatar` (image URL) when present.
397
+ */
398
+ data?: T;
399
+ /** Direct reports; a non-empty array makes the node collapsible. */
400
+ children?: MkOrgChartNode<T>[];
401
+ /** Initial expansion (default `true`). Only consulted when `[(expanded)]` is not bound. */
402
+ expanded?: boolean;
403
+ }
404
+ /** One row of a flat list accepted by {@link mkOrgChartFromFlat}. */
405
+ interface MkOrgChartFlatNode<T = unknown> {
406
+ id: string;
407
+ label?: string;
408
+ data?: T;
409
+ /** Id of the parent row; `null` / `undefined` / unknown id = root. */
410
+ parentId?: string | null;
411
+ expanded?: boolean;
412
+ }
413
+ /**
414
+ * Build the nested `nodes` input from a flat `parentId` list (the shape most
415
+ * HR / directory APIs return). Row order is preserved among siblings; rows
416
+ * whose `parentId` does not match any row become roots.
417
+ *
418
+ * ```ts
419
+ * const nodes = mkOrgChartFromFlat([
420
+ * { id: 'ceo', label: 'Ada' },
421
+ * { id: 'cto', label: 'Grace', parentId: 'ceo' },
422
+ * ]);
423
+ * ```
424
+ */
425
+ declare function mkOrgChartFromFlat<T = unknown>(list: readonly MkOrgChartFlatNode<T>[]): MkOrgChartNode<T>[];
426
+ /**
427
+ * `data` type seen by a node template: `T` when it could be inferred (the
428
+ * template binds `[mkOrgChartNodeDef]="nodes"`), otherwise `any` so an
429
+ * untyped `<ng-template mkOrgChartNodeDef>` can still read `node.data?.title`.
430
+ */
431
+ type MkOrgChartTemplateData<T> = keyof T extends never ? any : T;
432
+ /** Template context of `ng-template[mkOrgChartNodeDef]`. */
433
+ interface MkOrgChartNodeContext<T = unknown> {
434
+ /** The node (also available as `let-node`). */
435
+ $implicit: MkOrgChartNode<MkOrgChartTemplateData<T>>;
436
+ node: MkOrgChartNode<MkOrgChartTemplateData<T>>;
437
+ /** 1-based depth (roots are 1). */
438
+ depth: number;
439
+ /** Whether the node's children are currently shown. */
440
+ expanded: boolean;
441
+ /** Whether the node is the selected one. */
442
+ selected: boolean;
443
+ }
444
+ /**
445
+ * Custom node card for `mk-org-chart`:
446
+ *
447
+ * ```html
448
+ * <mk-org-chart [nodes]="nodes">
449
+ * <ng-template mkOrgChartNodeDef let-node let-selected="selected">
450
+ * <strong>{{ node.label }}</strong> — {{ node.data?.title }}
451
+ * </ng-template>
452
+ * </mk-org-chart>
453
+ * ```
454
+ *
455
+ * Bind the same array you pass to `nodes` to get a typed `node.data` in the
456
+ * template: `<ng-template [mkOrgChartNodeDef]="nodes" let-node>`.
457
+ */
458
+ declare class MkOrgChartNodeDef<T = unknown> {
459
+ /**
460
+ * Type-inference hook only (the value is not used at runtime): bind the
461
+ * `nodes` array so `let-node` is typed as `MkOrgChartNode<T>`.
462
+ */
463
+ readonly mkOrgChartNodeDef: _angular_core.InputSignal<"" | readonly MkOrgChartNode<T>[] | undefined>;
464
+ readonly template: TemplateRef<any>;
465
+ static ngTemplateContextGuard<T>(_dir: MkOrgChartNodeDef<T>, ctx: unknown): ctx is MkOrgChartNodeContext<T>;
466
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkOrgChartNodeDef<any>, never>;
467
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MkOrgChartNodeDef<any>, "ng-template[mkOrgChartNodeDef]", never, { "mkOrgChartNodeDef": { "alias": "mkOrgChartNodeDef"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
468
+ }
469
+ /** Chart direction: `top` = root at the top, `left` = root at the inline start. */
470
+ type MkOrgChartOrientation = 'top' | 'left';
471
+ /** Payload of `(nodeToggle)`. */
472
+ interface MkOrgChartToggleEvent<T = unknown> {
473
+ node: MkOrgChartNode<T>;
474
+ expanded: boolean;
475
+ }
476
+ /** One visible node after flattening (pre-order, i.e. DOM order). */
477
+ interface MkOrgChartRow {
478
+ node: MkOrgChartNode;
479
+ depth: number;
480
+ parentId: string | null;
481
+ /** Ids of the sibling set this row belongs to (in order). */
482
+ siblings: readonly string[];
483
+ hasChildren: boolean;
484
+ expanded: boolean;
485
+ }
486
+ /**
487
+ * Organisation chart — a reporting-line hierarchy drawn with plain nested
488
+ * lists and CSS connectors (no canvas, prints and themes like everything
489
+ * else). Feed it a tree (`nodes`) or convert a flat `parentId` list with
490
+ * {@link mkOrgChartFromFlat}. Nodes render as a default card (avatar /
491
+ * initials, label, `data.title`) or through an `mkOrgChartNodeDef` template.
492
+ *
493
+ * Follows the ARIA tree pattern (`role="tree"` / `treeitem` / `group`, one
494
+ * roving tab stop). Keyboard (top-down; the axes swap for `orientation="left"`
495
+ * and in RTL): Down = first child (expands a collapsed node first), Up =
496
+ * parent, Left/Right = previous/next sibling, Home/End = first/last visible
497
+ * node, Enter/Space = select (or toggle when not selectable), `*` = expand
498
+ * all siblings, `+`/`-` = expand/collapse.
499
+ *
500
+ * ```html
501
+ * <mk-org-chart
502
+ * [nodes]="company"
503
+ * selectable
504
+ * [(selected)]="personId"
505
+ * collapsible
506
+ * (nodeClick)="open($event)"
507
+ * />
508
+ * ```
509
+ */
510
+ declare class MkOrgChart<T = unknown> {
511
+ private readonly host;
512
+ private readonly document;
513
+ /** Localised strings (override globally via `provideMkI18n`). */
514
+ protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
515
+ /** The hierarchy to render (roots first). */
516
+ readonly nodes: _angular_core.InputSignal<readonly MkOrgChartNode<T>[]>;
517
+ /** Root at the top (children below) or at the inline start (children to the side). */
518
+ readonly orientation: _angular_core.InputSignal<MkOrgChartOrientation>;
519
+ /** Allow choosing a node (adds selection styling + `aria-selected`). */
520
+ readonly selectable: _angular_core.InputSignalWithTransform<boolean, unknown>;
521
+ /** Show a toggle on every parent so branches can be hidden. */
522
+ readonly collapsible: _angular_core.InputSignalWithTransform<boolean, unknown>;
523
+ /** Scale factor applied to the whole chart (clamped to 0.5–2). */
524
+ readonly zoom: _angular_core.InputSignalWithTransform<number, unknown>;
525
+ /** Accessible name for the tree. */
526
+ readonly ariaLabel: _angular_core.InputSignal<string>;
527
+ /** Two-way selected node id (`null` = nothing selected). */
528
+ readonly selected: _angular_core.ModelSignal<string | null>;
529
+ /**
530
+ * Two-way ids of the expanded parents. Leave unbound to let the chart
531
+ * manage expansion itself (seeded from each node's `expanded` flag).
532
+ */
533
+ readonly expanded: _angular_core.ModelSignal<readonly string[] | undefined>;
534
+ /** Emits the node whose card was clicked or activated with Enter/Space. */
535
+ readonly nodeClick: _angular_core.OutputEmitterRef<MkOrgChartNode<T>>;
536
+ /** Emits whenever a node is expanded or collapsed. */
537
+ readonly nodeToggle: _angular_core.OutputEmitterRef<MkOrgChartToggleEvent<T>>;
538
+ protected readonly nodeDef: _angular_core.Signal<MkOrgChartNodeDef<T> | undefined>;
539
+ protected readonly zoomLevel: _angular_core.Signal<number>;
540
+ /**
541
+ * Expanded parent ids. Controlled by `expanded` when bound; otherwise kept
542
+ * locally — a node's `expanded` flag only seeds ids not present in the
543
+ * previous `nodes` value, so re-emitting the array never reverts branches
544
+ * the user has since toggled.
545
+ */
546
+ private readonly expandedIds;
547
+ /** Id of the node holding the roving tab stop. */
548
+ private readonly activeId;
549
+ /** Visible nodes in DOM (pre-order) order. */
550
+ protected readonly rows: _angular_core.Signal<MkOrgChartRow[]>;
551
+ private readonly rowById;
552
+ /** The single id with `tabindex="0"` (falls back to the first visible node). */
553
+ private readonly tabStopId;
554
+ protected isExpanded(node: MkOrgChartNode<T>): boolean;
555
+ protected isSelected(node: MkOrgChartNode<T>): boolean;
556
+ protected tabIndexFor(node: MkOrgChartNode<T>): number;
557
+ protected toggleLabel(node: MkOrgChartNode<T>): string;
558
+ protected context(node: MkOrgChartNode<T>, depth: number): MkOrgChartNodeContext<T>;
559
+ /** `data.title` / `data.avatar` of the default card, read defensively. */
560
+ protected field(node: MkOrgChartNode<T>, key: 'title' | 'avatar'): string | undefined;
561
+ /** Expand or collapse a parent (no-op for leaves / non-collapsible charts). */
562
+ toggle(node: MkOrgChartNode<T>): void;
563
+ /** Expand or collapse a parent explicitly. */
564
+ setExpanded(node: MkOrgChartNode<T>, expanded: boolean): void;
565
+ /** Select a node by reference (no-op unless `selectable`). */
566
+ select(node: MkOrgChartNode<T>): void;
567
+ private activate;
568
+ protected onCardClick(event: Event, node: MkOrgChartNode<T>): void;
569
+ protected onToggleClick(event: Event, node: MkOrgChartNode<T>): void;
570
+ /** Keeps the roving tab stop on whichever item last received focus. */
571
+ protected onFocusIn(event: Event): void;
572
+ protected onKeydown(event: Event): void;
573
+ /**
574
+ * Map an arrow key to a tree direction. Top-down: Down = into, Up = parent,
575
+ * Left/Right = siblings (mirrored in RTL). Left-to-right: Right = into,
576
+ * Left = parent (mirrored in RTL), Up/Down = siblings.
577
+ */
578
+ private intentOf;
579
+ private siblingsOf;
580
+ private isRtl;
581
+ private itemIdOf;
582
+ private focusItem;
583
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkOrgChart<any>, never>;
584
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkOrgChart<any>, "mk-org-chart", ["mkOrgChart"], { "nodes": { "alias": "nodes"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "collapsible": { "alias": "collapsible"; "required": false; "isSignal": true; }; "zoom": { "alias": "zoom"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "expanded": { "alias": "expanded"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "expanded": "expandedChange"; "nodeClick": "nodeClick"; "nodeToggle": "nodeToggle"; }, ["nodeDef"], never, true, never>;
585
+ }
586
+
313
587
  /** Direction of a {@link MkStatCard} delta. */
314
588
  type MkStatTrend = 'up' | 'down' | 'neutral';
315
589
  /**
@@ -1191,24 +1465,81 @@ interface HeatCell {
1191
1465
  display: string;
1192
1466
  xLabel: string;
1193
1467
  bg: string;
1194
- strong: boolean;
1468
+ /** Draw the value with `--mk-text-inverse` (else `--mk-text`). */
1469
+ inverse: boolean;
1195
1470
  }
1196
1471
  interface HeatRow {
1197
1472
  label: string;
1198
1473
  cells: HeatCell[];
1199
1474
  }
1475
+ /** An sRGB colour as 0–255 channels. */
1476
+ type MkRgb = readonly [number, number, number];
1477
+ /** The resolved colours a heatmap picks its cell text against. */
1478
+ interface MkHeatmapPalette {
1479
+ /** The `accent` input, resolved to sRGB. */
1480
+ accent: MkRgb;
1481
+ /** `--mk-surface-2` — the zero-intensity cell colour. */
1482
+ surface: MkRgb;
1483
+ /** `--mk-text`. */
1484
+ text: MkRgb;
1485
+ /** `--mk-text-inverse`. */
1486
+ textInverse: MkRgb;
1487
+ }
1488
+ /** Which text token a cell value is drawn with, and the intensity to paint the cell at. */
1489
+ interface MkHeatmapCellColors {
1490
+ /** Accent share of the cell background, 0–1. */
1491
+ intensity: number;
1492
+ /** `true` → `--mk-text-inverse`, `false` → `--mk-text`. */
1493
+ inverse: boolean;
1494
+ /** Contrast ratio of the chosen text against the cell background (1–21). */
1495
+ contrast: number;
1496
+ }
1497
+ /** WCAG AA minimum contrast for normal text — what cell values are held to. */
1498
+ declare const MK_HEATMAP_MIN_CONTRAST = 4.5;
1499
+ /** WCAG 2.x relative luminance of an sRGB colour. */
1500
+ declare function mkRelativeLuminance([r, g, b]: MkRgb): number;
1501
+ /** WCAG 2.x contrast ratio (1–21) between two colours. */
1502
+ declare function mkContrastRatio(a: MkRgb, b: MkRgb): number;
1503
+ /** What `color-mix(in srgb, a t%, b)` yields: a linear blend in gamma-encoded sRGB. */
1504
+ declare function mkMixRgb(a: MkRgb, b: MkRgb, t: number): MkRgb;
1505
+ /**
1506
+ * Parse a CSS colour as the CSSOM serialises it — `rgb(r, g, b)` /
1507
+ * `rgba(r, g, b, a)` — or a `#rgb` / `#rrggbb` literal. `null` for anything
1508
+ * else (an unresolved `var()`, `color(...)`, …).
1509
+ */
1510
+ declare function mkParseRgb(text: string | null | undefined): MkRgb | null;
1511
+ /**
1512
+ * Choose the text token for a cell at intensity `t` (0–1) — light text on
1513
+ * dark cells, dark text on light cells, decided by contrast against the
1514
+ * actual blend rather than a fixed threshold.
1515
+ *
1516
+ * Every accent ramp has a crossover band where neither `--mk-text` nor
1517
+ * `--mk-text-inverse` reaches 4.5:1 (the cell is mid-luminance). When values
1518
+ * are printed in the cells, a cell in that band is painted at the nearest
1519
+ * intensity just outside it, so its value stays readable; the shift is a few
1520
+ * percent of the ramp and the cell keeps its order relative to its
1521
+ * neighbours. Without a resolved palette (server rendering, tests) a plain
1522
+ * threshold is used.
1523
+ */
1524
+ declare function mkHeatmapCellColors(t: number, palette: MkHeatmapPalette | null, showValues: boolean): MkHeatmapCellColors;
1200
1525
  /**
1201
1526
  * Heatmap — a matrix of cells shaded by value intensity, for correlation
1202
1527
  * grids, activity-by-time tables and the like. Rendered as a semantic
1203
1528
  * `<table>` (so it is inherently screen-reader friendly) with cell colours
1204
1529
  * mixed from `accent` over the surface via `color-mix`, so it tracks the theme.
1205
1530
  *
1531
+ * Printed values (`showValues`) pick `--mk-text` or `--mk-text-inverse` per
1532
+ * cell by contrast against that cell's actual colour, in both themes — see
1533
+ * {@link mkHeatmapCellColors}.
1534
+ *
1206
1535
  * ```html
1207
1536
  * <mk-heatmap
1208
1537
  * [xLabels]="hours" [yLabels]="days" [data]="matrix()" showValues />
1209
1538
  * ```
1210
1539
  */
1211
1540
  declare class MkHeatmap {
1541
+ private readonly doc;
1542
+ private readonly host;
1212
1543
  /** Column labels (x axis). */
1213
1544
  readonly xLabels: _angular_core.InputSignal<readonly string[]>;
1214
1545
  /** Row labels (y axis). */
@@ -1229,9 +1560,21 @@ declare class MkHeatmap {
1229
1560
  readonly format: _angular_core.InputSignal<(value: number) => string>;
1230
1561
  /** Accessible summary; generated from the data when omitted. */
1231
1562
  readonly label: _angular_core.InputSignal<string>;
1563
+ /**
1564
+ * The accent and the text/surface tokens resolved through the CSSOM, so
1565
+ * each cell can pick a text colour that actually contrasts with its blend.
1566
+ * `null` until resolved (server, jsdom) — the cells then fall back to a
1567
+ * threshold.
1568
+ */
1569
+ protected readonly palette: _angular_core.WritableSignal<MkHeatmapPalette | null>;
1570
+ /** Bumped when the document theme changes so the palette is re-resolved. */
1571
+ private readonly themeTick;
1572
+ constructor();
1232
1573
  private readonly domain;
1233
1574
  /** Fraction (0–1) of the domain a value sits at. */
1234
1575
  private ratio;
1576
+ /** The `color-mix()` expression painting a cell at intensity `t`. */
1577
+ private cellBackground;
1235
1578
  protected readonly rows: _angular_core.Signal<HeatRow[]>;
1236
1579
  /** Legend swatches from 0 → 1 intensity. */
1237
1580
  protected readonly scaleStops: _angular_core.Signal<{
@@ -1240,6 +1583,17 @@ declare class MkHeatmap {
1240
1583
  swatches: string[];
1241
1584
  }>;
1242
1585
  protected readonly resolvedLabel: _angular_core.Signal<string>;
1586
+ /**
1587
+ * Resolve the accent and the tokens to sRGB through a hidden probe: the
1588
+ * probe's computed `color` is what the browser would paint, `var()`s and
1589
+ * `color-mix()` included. `null` when the environment cannot resolve them.
1590
+ */
1591
+ protected resolvePalette(): MkHeatmapPalette | null;
1592
+ /**
1593
+ * Re-resolve when the theme flips: `data-theme` / class changes on the root
1594
+ * element (MkThemeService and most hand-rolled toggles) and the OS scheme.
1595
+ */
1596
+ private watchTheme;
1243
1597
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkHeatmap, never>;
1244
1598
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkHeatmap, "mk-heatmap", never, { "xLabels": { "alias": "xLabels"; "required": false; "isSignal": true; }; "yLabels": { "alias": "yLabels"; "required": false; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "accent": { "alias": "accent"; "required": false; "isSignal": true; }; "showValues": { "alias": "showValues"; "required": false; "isSignal": true; }; "showScale": { "alias": "showScale"; "required": false; "isSignal": true; }; "format": { "alias": "format"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1245
1599
  }
@@ -1664,6 +2018,8 @@ declare class MkSkeletonPreset {
1664
2018
  declare class MkInlineEdit implements ControlValueAccessor {
1665
2019
  private readonly injector;
1666
2020
  private readonly field;
2021
+ /** Signal Forms: gates `invalid` until the bound field is touched or dirty. */
2022
+ private readonly fieldTouched;
1667
2023
  protected readonly i18n: _mk_kit_ui_core.MkI18nStrings;
1668
2024
  private readonly displayRef;
1669
2025
  private readonly inputRef;
@@ -2622,5 +2978,5 @@ declare function mkParseMarkdown(src: string, options?: MkMarkdownParseOptions):
2622
2978
  */
2623
2979
  declare function mkRenderMarkdown(blocks: MkMarkdownBlock[], options?: MkMarkdownRenderOptions): string;
2624
2980
 
2625
- export { MK_CHART_PALETTE_SIZE, MkAvatar, MkAvatarGroup, MkBadge, MkBarChart, MkCalendarHeatmap, MkCard, MkCardFooter, MkCardHeader, MkCardTitle, MkCarousel, MkCarouselSlide, MkCode, MkCountdown, MkDescItem, MkDescriptionList, MkDiff, MkDivider, MkDonutChart, MkEmptyState, MkFunnelChart, MkGauge, MkHeatmap, MkInlineEdit, MkJsonViewer, MkKanban, MkLineChart, MkList, MkListItem, MkLogViewer, MkMarkdown, MkProfileActions, MkProfileCard, MkProfileMeta, MkProgressBar, MkProgressRing, MkQrCode, MkRadarChart, MkScatterChart, MkSkeleton, MkSkeletonPreset, MkSparkline, MkSpinner, MkStatCard, MkTag, MkTimeline, MkTimelineItem, MkTreemap, MkVirtualScroll, mkArcPath, mkAreaPath, mkBuildJsonTree, mkChartColor, mkComputeDiff, mkDiffStats, mkEncodeQr, mkFormatCompact, mkLinePath, mkLinearScale, mkNiceTicks, mkParseAnsi, mkParseMarkdown, mkRenderMarkdown, mkSplitDuration, mkSquarify, mkStripAnsi };
2626
- export type { MkAnsiSpan, MkAvatarShape, MkAvatarStatus, MkBadgeVariant, MkBarOrientation, MkCalendarHeatmapCell, MkCalendarHeatmapEntry, MkCardPadding, MkCardVariant, MkChartSeries, MkChartSlice, MkDescriptionLayout, MkDiffMode, MkDiffOp, MkDiffOptions, MkDiffRow, MkDiffSegment, MkDiffStats, MkDividerOrientation, MkDurationParts, MkFunnelSegment, MkJsonNode, MkKanbanCard, MkKanbanCardMovedEvent, MkKanbanColumn, MkLogToken, MkMarkdownAlign, MkMarkdownBlock, MkMarkdownInline, MkMarkdownList, MkMarkdownListItem, MkMarkdownParseOptions, MkMarkdownRenderOptions, MkPoint, MkProfileCardOrientation, MkQrEcc, MkScatterPoint, MkScatterSeries, MkSkeletonPresetKind, MkSkeletonShape, MkSparklineType, MkStatTrend, MkTagVariant, MkTreemapItem, MkTreemapRect };
2981
+ export { MK_CHART_PALETTE_SIZE, MK_HEATMAP_MIN_CONTRAST, MkAvatar, MkAvatarGroup, MkBadge, MkBadgeOverlay, MkBarChart, MkCalendarHeatmap, MkCard, MkCardFooter, MkCardHeader, MkCardTitle, MkCarousel, MkCarouselSlide, MkCode, MkCountdown, MkDescItem, MkDescriptionList, MkDiff, MkDivider, MkDonutChart, MkEmptyState, MkFunnelChart, MkGauge, MkHeatmap, MkInlineEdit, MkJsonViewer, MkKanban, MkLineChart, MkList, MkListItem, MkLogViewer, MkMarkdown, MkOrgChart, MkOrgChartNodeDef, MkProfileActions, MkProfileCard, MkProfileMeta, MkProgressBar, MkProgressRing, MkQrCode, MkRadarChart, MkScatterChart, MkSkeleton, MkSkeletonPreset, MkSparkline, MkSpinner, MkStatCard, MkTag, MkTimeline, MkTimelineItem, MkTreemap, MkVirtualScroll, mkArcPath, mkAreaPath, mkBuildJsonTree, mkChartColor, mkComputeDiff, mkContrastRatio, mkDiffStats, mkEncodeQr, mkFormatCompact, mkHeatmapCellColors, mkLinePath, mkLinearScale, mkMixRgb, mkNiceTicks, mkOrgChartFromFlat, mkParseAnsi, mkParseMarkdown, mkParseRgb, mkRelativeLuminance, mkRenderMarkdown, mkSplitDuration, mkSquarify, mkStripAnsi };
2982
+ export type { MkAnsiSpan, MkAvatarShape, MkAvatarStatus, MkBadgeOverlayPosition, MkBadgeVariant, MkBarOrientation, MkCalendarHeatmapCell, MkCalendarHeatmapEntry, MkCardPadding, MkCardVariant, MkChartSeries, MkChartSlice, MkDescriptionLayout, MkDiffMode, MkDiffOp, MkDiffOptions, MkDiffRow, MkDiffSegment, MkDiffStats, MkDividerOrientation, MkDurationParts, MkFunnelSegment, MkHeatmapCellColors, MkHeatmapPalette, MkJsonNode, MkKanbanCard, MkKanbanCardMovedEvent, MkKanbanColumn, MkLogToken, MkMarkdownAlign, MkMarkdownBlock, MkMarkdownInline, MkMarkdownList, MkMarkdownListItem, MkMarkdownParseOptions, MkMarkdownRenderOptions, MkOrgChartFlatNode, MkOrgChartNode, MkOrgChartNodeContext, MkOrgChartOrientation, MkOrgChartTemplateData, MkOrgChartToggleEvent, MkPoint, MkProfileCardOrientation, MkQrEcc, MkRgb, MkScatterPoint, MkScatterSeries, MkSkeletonPresetKind, MkSkeletonShape, MkSparklineType, MkStatTrend, MkTagVariant, MkTreemapItem, MkTreemapRect };