@mk-kit/ui 0.40.0 → 0.42.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.
@@ -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). */
@@ -1347,4 +1394,4 @@ declare function mkQueryOperatorLabel(op: MkQueryOperator, i18n?: MkI18nStrings)
1347
1394
  declare function mkQueryToText(group: MkQueryGroup, fields?: readonly MkQueryField[], i18n?: MkI18nStrings): string;
1348
1395
 
1349
1396
  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 };
1397
+ 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, 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
  /**
@@ -733,6 +808,16 @@ declare class MkBarChart {
733
808
  readonly labelAngle: _angular_core.InputSignal<number | "auto">;
734
809
  /** Accessible summary; generated from the data when omitted. */
735
810
  readonly label: _angular_core.InputSignal<string>;
811
+ /** Make bars clickable + keyboard-focusable (`role="button"`, accessible name) and emit `barClick`. */
812
+ readonly interactive: _angular_core.InputSignalWithTransform<boolean, unknown>;
813
+ /** A bar was clicked or activated with Enter / Space (needs `interactive`). */
814
+ readonly barClick: _angular_core.OutputEmitterRef<{
815
+ series: MkChartSeries;
816
+ seriesIndex: number;
817
+ category: string;
818
+ categoryIndex: number;
819
+ value: number;
820
+ }>;
736
821
  protected readonly hovered: _angular_core.WritableSignal<BarRect | null>;
737
822
  /** Tap-to-pin: a touch tap on a bar pins the tooltip until a tap lands
738
823
  * outside the chart (mouse hover in/out is unaffected). */
@@ -789,10 +874,12 @@ declare class MkBarChart {
789
874
  multi: boolean;
790
875
  } | null>;
791
876
  protected readonly resolvedLabel: _angular_core.Signal<string>;
877
+ protected emitBar(b: BarRect, event?: Event): void;
878
+ protected barLabel(b: BarRect): string;
792
879
  protected setHover(bar: BarRect | null): void;
793
880
  protected pinHover(bar: BarRect, event: PointerEvent): void;
794
881
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkBarChart, never>;
795
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkBarChart, "mk-bar-chart", never, { "categories": { "alias": "categories"; "required": false; "isSignal": true; }; "series": { "alias": "series"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "stacked": { "alias": "stacked"; "required": false; "isSignal": true; }; "showGrid": { "alias": "showGrid"; "required": false; "isSignal": true; }; "showLegend": { "alias": "showLegend"; "required": false; "isSignal": true; }; "labelAngle": { "alias": "labelAngle"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
882
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkBarChart, "mk-bar-chart", never, { "categories": { "alias": "categories"; "required": false; "isSignal": true; }; "series": { "alias": "series"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "stacked": { "alias": "stacked"; "required": false; "isSignal": true; }; "showGrid": { "alias": "showGrid"; "required": false; "isSignal": true; }; "showLegend": { "alias": "showLegend"; "required": false; "isSignal": true; }; "labelAngle": { "alias": "labelAngle"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; }, { "barClick": "barClick"; }, never, never, true, never>;
796
883
  }
797
884
 
798
885
  /**
@@ -840,6 +927,17 @@ declare class MkLineChart {
840
927
  readonly showLegend: _angular_core.InputSignal<boolean | undefined>;
841
928
  /** Accessible summary; generated from the data when omitted. */
842
929
  readonly label: _angular_core.InputSignal<string>;
930
+ /** Make x positions keyboard-focusable (`role="button"`, accessible name) and emit `pointClick`. */
931
+ readonly interactive: _angular_core.InputSignalWithTransform<boolean, unknown>;
932
+ /** A category (x position) was clicked or activated with Enter / Space (needs `interactive`). */
933
+ readonly pointClick: _angular_core.OutputEmitterRef<{
934
+ index: number;
935
+ category: string;
936
+ values: Array<{
937
+ series: MkChartSeries;
938
+ value: number;
939
+ }>;
940
+ }>;
843
941
  protected readonly hoverIndex: _angular_core.WritableSignal<number | null>;
844
942
  /** Tap-to-pin: a touch tap on a hit band pins the tooltip until a tap lands
845
943
  * outside the chart (mouse hover in/out is unaffected). */
@@ -905,10 +1003,12 @@ declare class MkLineChart {
905
1003
  multi: boolean;
906
1004
  } | null>;
907
1005
  protected readonly resolvedLabel: _angular_core.Signal<string>;
1006
+ protected emitPoint(index: number, event?: Event): void;
1007
+ protected pointLabel(index: number): string;
908
1008
  protected setHover(index: number | null): void;
909
1009
  protected pinHover(index: number, event: PointerEvent): void;
910
1010
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkLineChart, never>;
911
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkLineChart, "mk-line-chart", never, { "categories": { "alias": "categories"; "required": false; "isSignal": true; }; "series": { "alias": "series"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "stacked": { "alias": "stacked"; "required": false; "isSignal": true; }; "showDots": { "alias": "showDots"; "required": false; "isSignal": true; }; "showGrid": { "alias": "showGrid"; "required": false; "isSignal": true; }; "showLegend": { "alias": "showLegend"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1011
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkLineChart, "mk-line-chart", never, { "categories": { "alias": "categories"; "required": false; "isSignal": true; }; "series": { "alias": "series"; "required": false; "isSignal": true; }; "width": { "alias": "width"; "required": false; "isSignal": true; }; "responsive": { "alias": "responsive"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "area": { "alias": "area"; "required": false; "isSignal": true; }; "stacked": { "alias": "stacked"; "required": false; "isSignal": true; }; "showDots": { "alias": "showDots"; "required": false; "isSignal": true; }; "showGrid": { "alias": "showGrid"; "required": false; "isSignal": true; }; "showLegend": { "alias": "showLegend"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; }, { "pointClick": "pointClick"; }, never, never, true, never>;
912
1012
  }
913
1013
 
914
1014
  interface SliceGeom {
@@ -947,6 +1047,17 @@ declare class MkDonutChart {
947
1047
  readonly centerSublabel: _angular_core.InputSignal<string>;
948
1048
  /** Accessible summary; generated from the data when omitted. */
949
1049
  readonly label: _angular_core.InputSignal<string>;
1050
+ /**
1051
+ * Make slices (and legend rows) clickable and keyboard-focusable: they get
1052
+ * `role="button"` + an accessible name and emit `sliceClick`. Off by default —
1053
+ * the chart stays a static picture with its screen-reader table.
1054
+ */
1055
+ readonly interactive: _angular_core.InputSignalWithTransform<boolean, unknown>;
1056
+ /** A slice was clicked or activated with Enter / Space (needs `interactive`). */
1057
+ readonly sliceClick: _angular_core.OutputEmitterRef<{
1058
+ slice: MkChartSlice;
1059
+ index: number;
1060
+ }>;
950
1061
  protected readonly hovered: _angular_core.WritableSignal<number | null>;
951
1062
  /** Tap-to-pin: a touch tap on a slice pins the tooltip until a tap lands
952
1063
  * outside the chart (mouse hover in/out is unaffected). */
@@ -971,10 +1082,12 @@ declare class MkDonutChart {
971
1082
  percent: number;
972
1083
  } | null>;
973
1084
  protected readonly resolvedLabel: _angular_core.Signal<string>;
1085
+ protected emitSlice(index: number, event?: Event): void;
1086
+ protected sliceLabel(index: number): string;
974
1087
  protected setHover(index: number | null): void;
975
1088
  protected pinHover(index: number, event: PointerEvent): void;
976
1089
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkDonutChart, never>;
977
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDonutChart, "mk-donut-chart", never, { "slices": { "alias": "slices"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "thickness": { "alias": "thickness"; "required": false; "isSignal": true; }; "showLegend": { "alias": "showLegend"; "required": false; "isSignal": true; }; "centerLabel": { "alias": "centerLabel"; "required": false; "isSignal": true; }; "centerSublabel": { "alias": "centerSublabel"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
1090
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDonutChart, "mk-donut-chart", never, { "slices": { "alias": "slices"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "thickness": { "alias": "thickness"; "required": false; "isSignal": true; }; "showLegend": { "alias": "showLegend"; "required": false; "isSignal": true; }; "centerLabel": { "alias": "centerLabel"; "required": false; "isSignal": true; }; "centerSublabel": { "alias": "centerSublabel"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; }, { "sliceClick": "sliceClick"; }, never, never, true, never>;
978
1091
  }
979
1092
 
980
1093
  /**
@@ -1153,24 +1266,81 @@ interface HeatCell {
1153
1266
  display: string;
1154
1267
  xLabel: string;
1155
1268
  bg: string;
1156
- strong: boolean;
1269
+ /** Draw the value with `--mk-text-inverse` (else `--mk-text`). */
1270
+ inverse: boolean;
1157
1271
  }
1158
1272
  interface HeatRow {
1159
1273
  label: string;
1160
1274
  cells: HeatCell[];
1161
1275
  }
1276
+ /** An sRGB colour as 0–255 channels. */
1277
+ type MkRgb = readonly [number, number, number];
1278
+ /** The resolved colours a heatmap picks its cell text against. */
1279
+ interface MkHeatmapPalette {
1280
+ /** The `accent` input, resolved to sRGB. */
1281
+ accent: MkRgb;
1282
+ /** `--mk-surface-2` — the zero-intensity cell colour. */
1283
+ surface: MkRgb;
1284
+ /** `--mk-text`. */
1285
+ text: MkRgb;
1286
+ /** `--mk-text-inverse`. */
1287
+ textInverse: MkRgb;
1288
+ }
1289
+ /** Which text token a cell value is drawn with, and the intensity to paint the cell at. */
1290
+ interface MkHeatmapCellColors {
1291
+ /** Accent share of the cell background, 0–1. */
1292
+ intensity: number;
1293
+ /** `true` → `--mk-text-inverse`, `false` → `--mk-text`. */
1294
+ inverse: boolean;
1295
+ /** Contrast ratio of the chosen text against the cell background (1–21). */
1296
+ contrast: number;
1297
+ }
1298
+ /** WCAG AA minimum contrast for normal text — what cell values are held to. */
1299
+ declare const MK_HEATMAP_MIN_CONTRAST = 4.5;
1300
+ /** WCAG 2.x relative luminance of an sRGB colour. */
1301
+ declare function mkRelativeLuminance([r, g, b]: MkRgb): number;
1302
+ /** WCAG 2.x contrast ratio (1–21) between two colours. */
1303
+ declare function mkContrastRatio(a: MkRgb, b: MkRgb): number;
1304
+ /** What `color-mix(in srgb, a t%, b)` yields: a linear blend in gamma-encoded sRGB. */
1305
+ declare function mkMixRgb(a: MkRgb, b: MkRgb, t: number): MkRgb;
1306
+ /**
1307
+ * Parse a CSS colour as the CSSOM serialises it — `rgb(r, g, b)` /
1308
+ * `rgba(r, g, b, a)` — or a `#rgb` / `#rrggbb` literal. `null` for anything
1309
+ * else (an unresolved `var()`, `color(...)`, …).
1310
+ */
1311
+ declare function mkParseRgb(text: string | null | undefined): MkRgb | null;
1312
+ /**
1313
+ * Choose the text token for a cell at intensity `t` (0–1) — light text on
1314
+ * dark cells, dark text on light cells, decided by contrast against the
1315
+ * actual blend rather than a fixed threshold.
1316
+ *
1317
+ * Every accent ramp has a crossover band where neither `--mk-text` nor
1318
+ * `--mk-text-inverse` reaches 4.5:1 (the cell is mid-luminance). When values
1319
+ * are printed in the cells, a cell in that band is painted at the nearest
1320
+ * intensity just outside it, so its value stays readable; the shift is a few
1321
+ * percent of the ramp and the cell keeps its order relative to its
1322
+ * neighbours. Without a resolved palette (server rendering, tests) a plain
1323
+ * threshold is used.
1324
+ */
1325
+ declare function mkHeatmapCellColors(t: number, palette: MkHeatmapPalette | null, showValues: boolean): MkHeatmapCellColors;
1162
1326
  /**
1163
1327
  * Heatmap — a matrix of cells shaded by value intensity, for correlation
1164
1328
  * grids, activity-by-time tables and the like. Rendered as a semantic
1165
1329
  * `<table>` (so it is inherently screen-reader friendly) with cell colours
1166
1330
  * mixed from `accent` over the surface via `color-mix`, so it tracks the theme.
1167
1331
  *
1332
+ * Printed values (`showValues`) pick `--mk-text` or `--mk-text-inverse` per
1333
+ * cell by contrast against that cell's actual colour, in both themes — see
1334
+ * {@link mkHeatmapCellColors}.
1335
+ *
1168
1336
  * ```html
1169
1337
  * <mk-heatmap
1170
1338
  * [xLabels]="hours" [yLabels]="days" [data]="matrix()" showValues />
1171
1339
  * ```
1172
1340
  */
1173
1341
  declare class MkHeatmap {
1342
+ private readonly doc;
1343
+ private readonly host;
1174
1344
  /** Column labels (x axis). */
1175
1345
  readonly xLabels: _angular_core.InputSignal<readonly string[]>;
1176
1346
  /** Row labels (y axis). */
@@ -1191,9 +1361,21 @@ declare class MkHeatmap {
1191
1361
  readonly format: _angular_core.InputSignal<(value: number) => string>;
1192
1362
  /** Accessible summary; generated from the data when omitted. */
1193
1363
  readonly label: _angular_core.InputSignal<string>;
1364
+ /**
1365
+ * The accent and the text/surface tokens resolved through the CSSOM, so
1366
+ * each cell can pick a text colour that actually contrasts with its blend.
1367
+ * `null` until resolved (server, jsdom) — the cells then fall back to a
1368
+ * threshold.
1369
+ */
1370
+ protected readonly palette: _angular_core.WritableSignal<MkHeatmapPalette | null>;
1371
+ /** Bumped when the document theme changes so the palette is re-resolved. */
1372
+ private readonly themeTick;
1373
+ constructor();
1194
1374
  private readonly domain;
1195
1375
  /** Fraction (0–1) of the domain a value sits at. */
1196
1376
  private ratio;
1377
+ /** The `color-mix()` expression painting a cell at intensity `t`. */
1378
+ private cellBackground;
1197
1379
  protected readonly rows: _angular_core.Signal<HeatRow[]>;
1198
1380
  /** Legend swatches from 0 → 1 intensity. */
1199
1381
  protected readonly scaleStops: _angular_core.Signal<{
@@ -1202,6 +1384,17 @@ declare class MkHeatmap {
1202
1384
  swatches: string[];
1203
1385
  }>;
1204
1386
  protected readonly resolvedLabel: _angular_core.Signal<string>;
1387
+ /**
1388
+ * Resolve the accent and the tokens to sRGB through a hidden probe: the
1389
+ * probe's computed `color` is what the browser would paint, `var()`s and
1390
+ * `color-mix()` included. `null` when the environment cannot resolve them.
1391
+ */
1392
+ protected resolvePalette(): MkHeatmapPalette | null;
1393
+ /**
1394
+ * Re-resolve when the theme flips: `data-theme` / class changes on the root
1395
+ * element (MkThemeService and most hand-rolled toggles) and the OS scheme.
1396
+ */
1397
+ private watchTheme;
1205
1398
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkHeatmap, never>;
1206
1399
  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>;
1207
1400
  }
@@ -2584,5 +2777,5 @@ declare function mkParseMarkdown(src: string, options?: MkMarkdownParseOptions):
2584
2777
  */
2585
2778
  declare function mkRenderMarkdown(blocks: MkMarkdownBlock[], options?: MkMarkdownRenderOptions): string;
2586
2779
 
2587
- 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 };
2588
- 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 };
2780
+ 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, 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, mkParseAnsi, mkParseMarkdown, mkParseRgb, mkRelativeLuminance, mkRenderMarkdown, mkSplitDuration, mkSquarify, mkStripAnsi };
2781
+ 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, MkPoint, MkProfileCardOrientation, MkQrEcc, MkRgb, MkScatterPoint, MkScatterSeries, MkSkeletonPresetKind, MkSkeletonShape, MkSparklineType, MkStatTrend, MkTagVariant, MkTreemapItem, MkTreemapRect };
@@ -243,6 +243,9 @@ declare class MkDatePicker implements ControlValueAccessor, Validator {
243
243
  /** Two-way selected date. */
244
244
  readonly value: _angular_core.ModelSignal<Date | null>;
245
245
  /** Earliest selectable date (inclusive). */
246
+ /** Accessible name when the picker is used without an `mk-form-field` label. */
247
+ readonly ariaLabel: _angular_core.InputSignal<string>;
248
+ protected readonly ariaLabelAttr: _angular_core.Signal<string | null>;
246
249
  readonly min: _angular_core.InputSignal<Date | null>;
247
250
  /** Latest selectable date (inclusive). */
248
251
  readonly max: _angular_core.InputSignal<Date | null>;
@@ -311,7 +314,7 @@ declare class MkDatePicker implements ControlValueAccessor, Validator {
311
314
  validate(control: AbstractControl): ValidationErrors | null;
312
315
  registerOnValidatorChange(fn: () => void): void;
313
316
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkDatePicker, never>;
314
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDatePicker, "mk-date-picker", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "disabledDate": { "alias": "disabledDate"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "displayFormat": { "alias": "displayFormat"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
317
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkDatePicker, "mk-date-picker", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "disabledDate": { "alias": "disabledDate"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "displayFormat": { "alias": "displayFormat"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
315
318
  }
316
319
 
317
320
  /** A selectable time option. */
@@ -363,6 +366,9 @@ declare class MkTimePicker implements ControlValueAccessor, Validator {
363
366
  */
364
367
  readonly value: _angular_core.ModelSignal<string | Date | null>;
365
368
  /** Shape of the form value: a `HH:mm` string or a `Date`. */
369
+ /** Accessible name when the picker is used without an `mk-form-field` label. */
370
+ readonly ariaLabel: _angular_core.InputSignal<string>;
371
+ protected readonly ariaLabelAttr: _angular_core.Signal<string | null>;
366
372
  readonly valueFormat: _angular_core.InputSignal<"string" | "date">;
367
373
  /** Earliest selectable time `HH:mm` (inclusive). */
368
374
  readonly min: _angular_core.InputSignal<string | null>;
@@ -453,7 +459,7 @@ declare class MkTimePicker implements ControlValueAccessor, Validator {
453
459
  validate(control: AbstractControl): ValidationErrors | null;
454
460
  registerOnValidatorChange(fn: () => void): void;
455
461
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkTimePicker, never>;
456
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkTimePicker, "mk-time-picker", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "valueFormat": { "alias": "valueFormat"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "hour12": { "alias": "hour12"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
462
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkTimePicker, "mk-time-picker", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "valueFormat": { "alias": "valueFormat"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "step": { "alias": "step"; "required": false; "isSignal": true; }; "hour12": { "alias": "hour12"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
457
463
  }
458
464
 
459
465
  /** A selectable time-of-day option in the panel's list. */