@mk-kit/ui 0.52.1 → 0.53.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.
@@ -1,14 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, ChangeDetectionStrategy, Component, booleanAttribute, inject, ElementRef, Renderer2, DOCUMENT, PLATFORM_ID, numberAttribute, computed, effect, Directive, signal, contentChildren, output, TemplateRef, model, contentChild, linkedSignal, DestroyRef, afterNextRender, afterRenderEffect, untracked, Injector, viewChild, forwardRef, ViewEncapsulation } from '@angular/core';
3
- import { isPlatformBrowser, NgTemplateOutlet, DOCUMENT as DOCUMENT$1 } from '@angular/common';
4
- import { mkUniqueId, MK_I18N, MkFieldContext, mkHighlight } from '@mk-kit/ui/core';
2
+ import { input, ChangeDetectionStrategy, Component, signal, computed, numberAttribute, contentChildren, ElementRef, effect, booleanAttribute, output, inject, TemplateRef, Directive, DOCUMENT, model, contentChild, linkedSignal, DestroyRef, afterNextRender, PLATFORM_ID, afterRenderEffect, untracked, Injector, viewChild, forwardRef, ViewEncapsulation } from '@angular/core';
5
3
  import { MkIcon } from '@mk-kit/ui/icon';
4
+ import { NgTemplateOutlet, isPlatformBrowser, DOCUMENT as DOCUMENT$1 } from '@angular/common';
5
+ import { MK_I18N, mkUniqueId, MkFieldContext, mkHighlight } from '@mk-kit/ui/core';
6
6
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
7
7
  import { mkInjectFieldTouched } from '@mk-kit/ui/core/signal-forms';
8
8
  import { MkCopyToClipboard } from '@mk-kit/ui/directives';
9
9
  import { mkComputeDiff, mkDiffStats, mkStripAnsi, mkParseAnsi, mkRenderMarkdown, mkParseMarkdown } from '@mk-kit/core';
10
10
  export { mkComputeDiff, mkDiffStats, mkParseAnsi, mkParseMarkdown, mkRenderMarkdown, mkStripAnsi } from '@mk-kit/core';
11
- import { mkMoveItemInArray, MkDropList, MkDrag } from '@mk-kit/ui/dnd';
11
+ export * from '@mk-kit/ui/status';
12
12
 
13
13
  /**
14
14
  * Card — a themed surface container that groups related content. Compose it
@@ -114,226 +114,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
114
114
  }, template: "<span class=\"mk-divider__label\"><ng-content /></span>\n", styles: [":host{display:flex;align-items:center;gap:var(--mk-space-3);width:100%;color:var(--mk-text-muted);font-size:var(--mk-font-size-sm)}:host:before,:host:after{content:\"\";flex:1 1 auto;height:var(--mk-border-width);background-color:var(--mk-border)}.mk-divider__label:empty{display:none}.mk-divider__label{flex:0 0 auto;line-height:var(--mk-line-height-tight)}:host(.mk-divider--vertical){display:inline-flex;flex-direction:column;width:auto;height:100%;min-height:1em;align-self:stretch}:host(.mk-divider--vertical):before,:host(.mk-divider--vertical):after{width:var(--mk-border-width);height:auto}\n"] }]
115
115
  }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }] } });
116
116
 
117
- /**
118
- * Badge — a compact status pill, typically for counts or short state labels.
119
- * Set `dot` for a minimal notification indicator with no text.
120
- *
121
- * ```html
122
- * <mk-badge tone="success">Active</mk-badge>
123
- * <mk-badge tone="danger" variant="solid">3</mk-badge>
124
- * <mk-badge tone="danger" dot aria-label="Unread messages" />
125
- * ```
126
- */
127
- class MkBadge {
128
- /** Semantic color tone. */
129
- tone = input('primary', /* @ts-ignore */
130
- ...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
131
- /** Visual treatment. */
132
- variant = input('soft', /* @ts-ignore */
133
- ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
134
- /** Size scale. */
135
- size = input('md', /* @ts-ignore */
136
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
137
- /** Render as a tiny dot (no text) for notification indicators. */
138
- dot = input(false, { ...(ngDevMode ? { debugName: "dot" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
139
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkBadge, deps: [], target: i0.ɵɵFactoryTarget.Component });
140
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkBadge, isStandalone: true, selector: "mk-badge", inputs: { tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, dot: { classPropertyName: "dot", publicName: "dot", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.mk-badge--sm": "size() === 'sm'", "class.mk-badge--md": "size() === 'md'", "class.mk-badge--lg": "size() === 'lg'", "class.mk-badge--solid": "variant() === 'solid'", "class.mk-badge--soft": "variant() === 'soft'", "class.mk-badge--outline": "variant() === 'outline'", "class.mk-badge--dot": "dot()", "attr.data-tone": "tone()" }, classAttribute: "mk-badge" }, ngImport: i0, template: "@if (!dot()) {\n <ng-content />\n}\n", styles: ["@charset \"UTF-8\";:host{--_main: var(--mk-primary);--_contrast: var(--mk-primary-contrast);--_subtle: var(--mk-primary-subtle);--_subtle-text: var(--mk-primary-subtle-text);display:inline-flex;align-items:center;justify-content:center;gap:var(--mk-space-1);height:1.375rem;min-width:1.375rem;padding:0 var(--mk-space-2);border:var(--mk-border-width) solid transparent;border-radius:var(--mk-radius-pill);font-family:inherit;font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-medium);line-height:1;white-space:nowrap;vertical-align:middle}:host([data-tone=primary]){--_main: var(--mk-primary);--_hover: var(--mk-primary-hover);--_active: var(--mk-primary-active);--_contrast: var(--mk-primary-contrast);--_subtle: var(--mk-primary-subtle);--_subtle-text: var(--mk-primary-subtle-text)}:host([data-tone=success]){--_main: var(--mk-success);--_hover: var(--mk-success-hover);--_active: var(--mk-success-hover);--_contrast: var(--mk-success-contrast);--_subtle: var(--mk-success-subtle);--_subtle-text: var(--mk-success-subtle-text)}:host([data-tone=warning]){--_main: var(--mk-warning);--_hover: var(--mk-warning-hover);--_active: var(--mk-warning-hover);--_contrast: var(--mk-warning-contrast);--_subtle: var(--mk-warning-subtle);--_subtle-text: var(--mk-warning-subtle-text)}:host([data-tone=danger]){--_main: var(--mk-danger);--_hover: var(--mk-danger-hover);--_active: var(--mk-danger-hover);--_contrast: var(--mk-danger-contrast);--_subtle: var(--mk-danger-subtle);--_subtle-text: var(--mk-danger-subtle-text)}:host([data-tone=info]){--_main: var(--mk-info);--_hover: var(--mk-info-hover);--_active: var(--mk-info-hover);--_contrast: var(--mk-info-contrast);--_subtle: var(--mk-info-subtle);--_subtle-text: var(--mk-info-subtle-text)}:host([data-tone=neutral]){--_main: var(--mk-surface-inverse);--_hover: var(--mk-surface-inverse);--_active: var(--mk-surface-inverse);--_contrast: var(--mk-text-inverse);--_subtle: var(--mk-neutral-subtle);--_subtle-text: var(--mk-neutral-subtle-text)}:host(.mk-badge--sm){height:1.125rem;min-width:1.125rem;padding:0 var(--mk-space-1);font-size:var(--mk-font-size-xs)}:host(.mk-badge--lg){height:1.625rem;min-width:1.625rem;padding:0 var(--mk-space-3);font-size:var(--mk-font-size-sm)}:host(.mk-badge--solid){background-color:var(--_main);color:var(--_contrast)}:host(.mk-badge--soft){background-color:var(--_subtle);color:var(--_subtle-text)}:host(.mk-badge--outline){background-color:transparent;color:var(--_subtle-text);border-color:color-mix(in srgb,var(--_main) 42%,var(--mk-border-strong))}:host(.mk-badge--dot){width:.625rem;height:.625rem;min-width:0;padding:0;border-radius:var(--mk-radius-circle)}:host(.mk-badge--dot.mk-badge--sm){width:.5rem;height:.5rem}:host(.mk-badge--dot.mk-badge--lg){width:.75rem;height:.75rem}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
141
- }
142
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkBadge, decorators: [{
143
- type: Component,
144
- args: [{ selector: 'mk-badge', changeDetection: ChangeDetectionStrategy.OnPush, host: {
145
- class: 'mk-badge',
146
- '[class.mk-badge--sm]': "size() === 'sm'",
147
- '[class.mk-badge--md]': "size() === 'md'",
148
- '[class.mk-badge--lg]': "size() === 'lg'",
149
- '[class.mk-badge--solid]': "variant() === 'solid'",
150
- '[class.mk-badge--soft]': "variant() === 'soft'",
151
- '[class.mk-badge--outline]': "variant() === 'outline'",
152
- '[class.mk-badge--dot]': 'dot()',
153
- '[attr.data-tone]': 'tone()',
154
- }, template: "@if (!dot()) {\n <ng-content />\n}\n", styles: ["@charset \"UTF-8\";:host{--_main: var(--mk-primary);--_contrast: var(--mk-primary-contrast);--_subtle: var(--mk-primary-subtle);--_subtle-text: var(--mk-primary-subtle-text);display:inline-flex;align-items:center;justify-content:center;gap:var(--mk-space-1);height:1.375rem;min-width:1.375rem;padding:0 var(--mk-space-2);border:var(--mk-border-width) solid transparent;border-radius:var(--mk-radius-pill);font-family:inherit;font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-medium);line-height:1;white-space:nowrap;vertical-align:middle}:host([data-tone=primary]){--_main: var(--mk-primary);--_hover: var(--mk-primary-hover);--_active: var(--mk-primary-active);--_contrast: var(--mk-primary-contrast);--_subtle: var(--mk-primary-subtle);--_subtle-text: var(--mk-primary-subtle-text)}:host([data-tone=success]){--_main: var(--mk-success);--_hover: var(--mk-success-hover);--_active: var(--mk-success-hover);--_contrast: var(--mk-success-contrast);--_subtle: var(--mk-success-subtle);--_subtle-text: var(--mk-success-subtle-text)}:host([data-tone=warning]){--_main: var(--mk-warning);--_hover: var(--mk-warning-hover);--_active: var(--mk-warning-hover);--_contrast: var(--mk-warning-contrast);--_subtle: var(--mk-warning-subtle);--_subtle-text: var(--mk-warning-subtle-text)}:host([data-tone=danger]){--_main: var(--mk-danger);--_hover: var(--mk-danger-hover);--_active: var(--mk-danger-hover);--_contrast: var(--mk-danger-contrast);--_subtle: var(--mk-danger-subtle);--_subtle-text: var(--mk-danger-subtle-text)}:host([data-tone=info]){--_main: var(--mk-info);--_hover: var(--mk-info-hover);--_active: var(--mk-info-hover);--_contrast: var(--mk-info-contrast);--_subtle: var(--mk-info-subtle);--_subtle-text: var(--mk-info-subtle-text)}:host([data-tone=neutral]){--_main: var(--mk-surface-inverse);--_hover: var(--mk-surface-inverse);--_active: var(--mk-surface-inverse);--_contrast: var(--mk-text-inverse);--_subtle: var(--mk-neutral-subtle);--_subtle-text: var(--mk-neutral-subtle-text)}:host(.mk-badge--sm){height:1.125rem;min-width:1.125rem;padding:0 var(--mk-space-1);font-size:var(--mk-font-size-xs)}:host(.mk-badge--lg){height:1.625rem;min-width:1.625rem;padding:0 var(--mk-space-3);font-size:var(--mk-font-size-sm)}:host(.mk-badge--solid){background-color:var(--_main);color:var(--_contrast)}:host(.mk-badge--soft){background-color:var(--_subtle);color:var(--_subtle-text)}:host(.mk-badge--outline){background-color:transparent;color:var(--_subtle-text);border-color:color-mix(in srgb,var(--_main) 42%,var(--mk-border-strong))}:host(.mk-badge--dot){width:.625rem;height:.625rem;min-width:0;padding:0;border-radius:var(--mk-radius-circle)}:host(.mk-badge--dot.mk-badge--sm){width:.5rem;height:.5rem}:host(.mk-badge--dot.mk-badge--lg){width:.75rem;height:.75rem}\n"] }]
155
- }], propDecorators: { tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], dot: [{ type: i0.Input, args: [{ isSignal: true, alias: "dot", required: false }] }] } });
156
-
157
- /**
158
- * Badge overlay — anchors a small badge (count, dot or short text) to a corner
159
- * of ANY element: an icon button, an avatar, a tab label. The host stays a
160
- * single tab stop; the badge is a decorative, non-focusable child.
161
- *
162
- * - Numbers above `mkBadgeOverlayMax` (default 99) collapse to `99+`.
163
- * - `mkBadgeOverlayDot` renders a textless dot ("something is new").
164
- * - `mkBadgeOverlayAriaLabel` is the screen-reader text ("3 unread"). It is
165
- * rendered in a visually hidden span and wired to the host with
166
- * `aria-describedby`, so it is announced after the host's own name even
167
- * when the host has an `aria-label`. When it is given, the visible badge is
168
- * `aria-hidden` so the count is not read twice.
169
- * - Positions use logical insets, so `top-end` sits at the top-right in LTR
170
- * and the top-left in RTL.
171
- *
172
- * The badge is painted with the global `.mk-badge-overlay` styles from
173
- * `@mk-kit/ui/styles.css` and follows the `--mk-*` tone tokens.
174
- *
175
- * ```html
176
- * <button mkButton iconOnly aria-label="Notifications"
177
- * [mkBadgeOverlay]="unread()" mkBadgeOverlayTone="danger"
178
- * [mkBadgeOverlayAriaLabel]="unread() + ' unread'">
179
- * <mk-icon name="bell" />
180
- * </button>
181
- *
182
- * <mk-avatar name="Ada Lovelace" mkBadgeOverlay mkBadgeOverlayDot
183
- * mkBadgeOverlayTone="success" mkBadgeOverlayPosition="bottom-end" />
184
- * ```
185
- */
186
- class MkBadgeOverlay {
187
- host = inject(ElementRef);
188
- renderer = inject(Renderer2);
189
- document = inject(DOCUMENT);
190
- isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
191
- /**
192
- * Badge content — a count or a short label. `null` / empty hides the badge
193
- * unless `mkBadgeOverlayDot` is set. Numeric strings are treated as numbers
194
- * so `mkBadgeOverlay="120"` also collapses to `99+`.
195
- */
196
- content = input(null, { ...(ngDevMode ? { debugName: "content" } : /* istanbul ignore next */ {}), alias: 'mkBadgeOverlay' });
197
- /** Corner the badge is anchored to (logical: `end` flips in RTL). */
198
- position = input('top-end', { ...(ngDevMode ? { debugName: "position" } : /* istanbul ignore next */ {}), alias: 'mkBadgeOverlayPosition' });
199
- /** Semantic color tone (same scale as `mk-badge`). */
200
- tone = input('primary', { ...(ngDevMode ? { debugName: "tone" } : /* istanbul ignore next */ {}), alias: 'mkBadgeOverlayTone' });
201
- /** Render a textless dot instead of the content. */
202
- dot = input(false, { ...(ngDevMode ? { debugName: "dot" } : /* istanbul ignore next */ {}), alias: 'mkBadgeOverlayDot',
203
- transform: booleanAttribute });
204
- /** Numbers above this render as `<max>+`. `0` disables the cap. */
205
- max = input(99, { ...(ngDevMode ? { debugName: "max" } : /* istanbul ignore next */ {}), alias: 'mkBadgeOverlayMax',
206
- transform: numberAttribute });
207
- /** Hide the badge while keeping the directive (and its aria wiring) in place. */
208
- hidden = input(false, { ...(ngDevMode ? { debugName: "hidden" } : /* istanbul ignore next */ {}), alias: 'mkBadgeOverlayHidden',
209
- transform: booleanAttribute });
210
- /**
211
- * Screen-reader text for the badge, e.g. `"3 unread"`. Announced as the
212
- * host's description; the visible badge becomes `aria-hidden`.
213
- */
214
- ariaLabel = input('', { ...(ngDevMode ? { debugName: "ariaLabel" } : /* istanbul ignore next */ {}), alias: 'mkBadgeOverlayAriaLabel' });
215
- /** The text painted in the badge (`''` in dot mode). */
216
- label = computed(() => {
217
- if (this.dot())
218
- return '';
219
- const raw = this.content();
220
- if (raw === null || raw === undefined || raw === '')
221
- return '';
222
- const max = this.max();
223
- const n = typeof raw === 'number' ? raw : /^\d+$/.test(raw) ? Number(raw) : NaN;
224
- if (Number.isFinite(n) && max > 0 && n > max)
225
- return `${max}+`;
226
- return String(raw);
227
- }, /* @ts-ignore */
228
- ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
229
- /** Whether the badge is currently rendered. */
230
- visible = computed(() => !this.hidden() && (this.dot() || this.label() !== ''), /* @ts-ignore */
231
- ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
232
- srId = mkUniqueId('mk-badge-overlay');
233
- badge = null;
234
- sr = null;
235
- /** Set when WE made the host positioned, so we can undo it on removal. */
236
- positionedHost = false;
237
- constructor() {
238
- if (!this.isBrowser)
239
- return;
240
- effect(() => {
241
- const visible = this.visible();
242
- if (!visible) {
243
- this.detach();
244
- return;
245
- }
246
- const badge = this.attach();
247
- const dot = this.dot();
248
- const srText = this.ariaLabel().trim();
249
- this.renderer.setAttribute(badge, 'data-tone', this.tone());
250
- this.renderer.setAttribute(badge, 'data-position', this.position());
251
- if (dot) {
252
- this.renderer.addClass(badge, 'mk-badge-overlay--dot');
253
- }
254
- else {
255
- this.renderer.removeClass(badge, 'mk-badge-overlay--dot');
256
- }
257
- this.renderer.setProperty(badge, 'textContent', this.label());
258
- // A dot has nothing to read; a labelled badge is described via the
259
- // hidden span instead — either way the visual is hidden from AT.
260
- if (dot || srText) {
261
- this.renderer.setAttribute(badge, 'aria-hidden', 'true');
262
- }
263
- else {
264
- this.renderer.removeAttribute(badge, 'aria-hidden');
265
- }
266
- this.syncSr(srText);
267
- });
268
- }
269
- attach() {
270
- if (this.badge)
271
- return this.badge;
272
- const el = this.host.nativeElement;
273
- const view = this.document.defaultView;
274
- const position = view?.getComputedStyle(el).position;
275
- if (!position || position === 'static') {
276
- this.renderer.setStyle(el, 'position', 'relative');
277
- this.positionedHost = true;
278
- }
279
- const badge = this.renderer.createElement('span');
280
- this.renderer.addClass(badge, 'mk-badge-overlay');
281
- this.renderer.appendChild(el, badge);
282
- this.badge = badge;
283
- return badge;
284
- }
285
- detach() {
286
- if (this.badge) {
287
- this.renderer.removeChild(this.host.nativeElement, this.badge);
288
- this.badge = null;
289
- }
290
- this.syncSr('');
291
- if (this.positionedHost) {
292
- this.renderer.removeStyle(this.host.nativeElement, 'position');
293
- this.positionedHost = false;
294
- }
295
- }
296
- /** Create / update / remove the hidden description and its aria-describedby link. */
297
- syncSr(text) {
298
- const el = this.host.nativeElement;
299
- if (text) {
300
- if (!this.sr) {
301
- const sr = this.renderer.createElement('span');
302
- this.renderer.addClass(sr, 'mk-visually-hidden');
303
- this.renderer.setAttribute(sr, 'id', this.srId);
304
- this.renderer.appendChild(el, sr);
305
- this.sr = sr;
306
- const ids = (el.getAttribute('aria-describedby') ?? '').split(/\s+/).filter(Boolean);
307
- if (!ids.includes(this.srId))
308
- ids.push(this.srId);
309
- this.renderer.setAttribute(el, 'aria-describedby', ids.join(' '));
310
- }
311
- this.renderer.setProperty(this.sr, 'textContent', text);
312
- }
313
- else if (this.sr) {
314
- this.renderer.removeChild(el, this.sr);
315
- this.sr = null;
316
- const ids = (el.getAttribute('aria-describedby') ?? '')
317
- .split(/\s+/)
318
- .filter((id) => id && id !== this.srId);
319
- if (ids.length) {
320
- this.renderer.setAttribute(el, 'aria-describedby', ids.join(' '));
321
- }
322
- else {
323
- this.renderer.removeAttribute(el, 'aria-describedby');
324
- }
325
- }
326
- }
327
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkBadgeOverlay, deps: [], target: i0.ɵɵFactoryTarget.Directive });
328
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.7", type: MkBadgeOverlay, isStandalone: true, selector: "[mkBadgeOverlay]", inputs: { content: { classPropertyName: "content", publicName: "mkBadgeOverlay", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "mkBadgeOverlayPosition", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "mkBadgeOverlayTone", isSignal: true, isRequired: false, transformFunction: null }, dot: { classPropertyName: "dot", publicName: "mkBadgeOverlayDot", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "mkBadgeOverlayMax", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "mkBadgeOverlayHidden", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "mkBadgeOverlayAriaLabel", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0 });
329
- }
330
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkBadgeOverlay, decorators: [{
331
- type: Directive,
332
- args: [{
333
- selector: '[mkBadgeOverlay]',
334
- }]
335
- }], ctorParameters: () => [], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkBadgeOverlay", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkBadgeOverlayPosition", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkBadgeOverlayTone", required: false }] }], dot: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkBadgeOverlayDot", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkBadgeOverlayMax", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkBadgeOverlayHidden", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "mkBadgeOverlayAriaLabel", required: false }] }] } });
336
-
337
117
  /**
338
118
  * Tag — a non-interactive label for categories, keywords or metadata. Unlike
339
119
  * {@link MkChip} it carries no interaction; use it purely for display.
@@ -579,48 +359,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
579
359
  }, template: "<span class=\"mk-list-item__leading\"><ng-content select=\"[mkListLeading]\" /></span>\n<span class=\"mk-list-item__content\"><ng-content /></span>\n<span class=\"mk-list-item__trailing\"><ng-content select=\"[mkListTrailing]\" /></span>\n", styles: [":host{display:flex;align-items:center;gap:var(--mk-space-3);padding:var(--mk-space-3) var(--mk-space-4);min-height:2.75rem;border-top:var(--mk-border-width) solid var(--mk-list-item-border, transparent);color:var(--mk-text);transition:background-color var(--mk-duration-fast) var(--mk-ease-standard),color var(--mk-duration-fast) var(--mk-ease-standard)}:host(:first-child){border-top-color:transparent}.mk-list-item__leading,.mk-list-item__trailing{display:inline-flex;align-items:center;flex:0 0 auto;color:var(--mk-text-muted)}.mk-list-item__leading:empty,.mk-list-item__trailing:empty{display:none}.mk-list-item__content{flex:1 1 auto;min-width:0;line-height:var(--mk-line-height-snug)}.mk-list-item__trailing{margin-inline-start:auto}:host(.mk-list-item--interactive){cursor:pointer;-webkit-user-select:none;user-select:none}:host(.mk-list-item--interactive:hover){background-color:var(--mk-neutral-subtle)}:host(.mk-list-item--interactive:focus-visible){outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}:host(.mk-list-item--selected){background-color:var(--mk-selected-bg);color:var(--mk-selected-text)}:host(.mk-list-item--disabled){cursor:not-allowed;opacity:.55;pointer-events:none}\n"] }]
580
360
  }], propDecorators: { interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], activated: [{ type: i0.Output, args: ["activated"] }] } });
581
361
 
582
- /**
583
- * EmptyState — a centered placeholder for "nothing here yet" situations: empty
584
- * tables, no search results, a fresh dashboard, a cleared inbox. Provide a
585
- * `title` (and usually a `description`), an `icon` or projected media, and
586
- * call-to-action buttons via the actions slot.
587
- *
588
- * Slots: `[mkEmptyStateMedia]` (custom illustration, overrides `icon`), default
589
- * content (extra body), `[mkEmptyStateActions]` (buttons).
590
- *
591
- * ```html
592
- * <mk-empty-state icon="search" title="No results"
593
- * description="Try adjusting your filters.">
594
- * <button mkButton mkEmptyStateActions variant="outline">Clear filters</button>
595
- * </mk-empty-state>
596
- * ```
597
- */
598
- class MkEmptyState {
599
- /** Name of a registered icon shown above the title (ignored if media is projected). */
600
- icon = input('', /* @ts-ignore */
601
- ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
602
- /** Main heading, e.g. "No invoices yet". */
603
- title = input('', /* @ts-ignore */
604
- ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
605
- /** Supporting sentence under the title. */
606
- description = input('', /* @ts-ignore */
607
- ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
608
- /** Overall scale of the block. */
609
- size = input('md', /* @ts-ignore */
610
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
611
- iconSize = () => this.size() === 'sm' ? 28 : this.size() === 'lg' ? 48 : 36;
612
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkEmptyState, deps: [], target: i0.ɵɵFactoryTarget.Component });
613
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkEmptyState, isStandalone: true, selector: "mk-empty-state", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.mk-empty-state--sm": "size() === 'sm'", "class.mk-empty-state--lg": "size() === 'lg'" }, classAttribute: "mk-empty-state" }, ngImport: i0, template: "@if (icon()) {\n <span class=\"mk-empty-state__icon\" aria-hidden=\"true\">\n <mk-icon [name]=\"icon()\" [size]=\"iconSize()\" />\n </span>\n}\n<ng-content select=\"[mkEmptyStateMedia]\" />\n\n@if (title()) {\n <p class=\"mk-empty-state__title\">{{ title() }}</p>\n}\n@if (description()) {\n <p class=\"mk-empty-state__description\">{{ description() }}</p>\n}\n\n<ng-content />\n\n<div class=\"mk-empty-state__actions\">\n <ng-content select=\"[mkEmptyStateActions]\" />\n</div>\n", styles: [":host{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--mk-space-2);padding:var(--mk-space-8) var(--mk-space-5);text-align:center;font-family:var(--mk-font-sans);color:var(--mk-text)}:host(.mk-empty-state--sm){padding:var(--mk-space-5) var(--mk-space-4)}:host(.mk-empty-state--lg){padding:var(--mk-space-12) var(--mk-space-6)}.mk-empty-state__icon{display:inline-flex;align-items:center;justify-content:center;margin-bottom:var(--mk-space-1);color:var(--mk-text-subtle)}.mk-empty-state__title{margin:0;font-size:var(--mk-font-size-lg);font-weight:var(--mk-font-weight-semibold);line-height:var(--mk-line-height-snug);color:var(--mk-text)}:host(.mk-empty-state--sm) .mk-empty-state__title{font-size:var(--mk-font-size-md)}:host(.mk-empty-state--lg) .mk-empty-state__title{font-size:var(--mk-font-size-xl)}.mk-empty-state__description{margin:0;max-width:34ch;font-size:var(--mk-font-size-md);line-height:var(--mk-line-height-normal);color:var(--mk-text-muted)}.mk-empty-state__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--mk-space-2);margin-top:var(--mk-space-3)}.mk-empty-state__actions:empty{display:none}\n"], dependencies: [{ kind: "component", type: MkIcon, selector: "mk-icon", inputs: ["name", "size", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
614
- }
615
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkEmptyState, decorators: [{
616
- type: Component,
617
- args: [{ selector: 'mk-empty-state', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MkIcon], host: {
618
- class: 'mk-empty-state',
619
- '[class.mk-empty-state--sm]': "size() === 'sm'",
620
- '[class.mk-empty-state--lg]': "size() === 'lg'",
621
- }, template: "@if (icon()) {\n <span class=\"mk-empty-state__icon\" aria-hidden=\"true\">\n <mk-icon [name]=\"icon()\" [size]=\"iconSize()\" />\n </span>\n}\n<ng-content select=\"[mkEmptyStateMedia]\" />\n\n@if (title()) {\n <p class=\"mk-empty-state__title\">{{ title() }}</p>\n}\n@if (description()) {\n <p class=\"mk-empty-state__description\">{{ description() }}</p>\n}\n\n<ng-content />\n\n<div class=\"mk-empty-state__actions\">\n <ng-content select=\"[mkEmptyStateActions]\" />\n</div>\n", styles: [":host{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--mk-space-2);padding:var(--mk-space-8) var(--mk-space-5);text-align:center;font-family:var(--mk-font-sans);color:var(--mk-text)}:host(.mk-empty-state--sm){padding:var(--mk-space-5) var(--mk-space-4)}:host(.mk-empty-state--lg){padding:var(--mk-space-12) var(--mk-space-6)}.mk-empty-state__icon{display:inline-flex;align-items:center;justify-content:center;margin-bottom:var(--mk-space-1);color:var(--mk-text-subtle)}.mk-empty-state__title{margin:0;font-size:var(--mk-font-size-lg);font-weight:var(--mk-font-weight-semibold);line-height:var(--mk-line-height-snug);color:var(--mk-text)}:host(.mk-empty-state--sm) .mk-empty-state__title{font-size:var(--mk-font-size-md)}:host(.mk-empty-state--lg) .mk-empty-state__title{font-size:var(--mk-font-size-xl)}.mk-empty-state__description{margin:0;max-width:34ch;font-size:var(--mk-font-size-md);line-height:var(--mk-line-height-normal);color:var(--mk-text-muted)}.mk-empty-state__actions{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:var(--mk-space-2);margin-top:var(--mk-space-3)}.mk-empty-state__actions:empty{display:none}\n"] }]
622
- }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
623
-
624
362
  /**
625
363
  * Timeline — a vertical sequence of chronological events (activity feeds, order
626
364
  * status, audit logs). A container for `<mk-timeline-item>`s that draws the
@@ -1427,42 +1165,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
1427
1165
  }, template: "<svg\n class=\"mk-progress-ring__svg\"\n [attr.viewBox]=\"'0 0 ' + size() + ' ' + size()\"\n [attr.width]=\"size()\"\n [attr.height]=\"size()\"\n aria-hidden=\"true\"\n focusable=\"false\"\n>\n <circle\n class=\"mk-progress-ring__track\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"thickness()\"\n fill=\"none\"\n />\n <circle\n class=\"mk-progress-ring__arc\"\n [attr.cx]=\"center()\"\n [attr.cy]=\"center()\"\n [attr.r]=\"radius()\"\n [attr.stroke-width]=\"thickness()\"\n [attr.stroke-dasharray]=\"circumference()\"\n [attr.stroke-dashoffset]=\"indeterminate() ? circumference() * 0.7 : dashOffset()\"\n fill=\"none\"\n stroke-linecap=\"round\"\n />\n</svg>\n\n@if (showLabel() && !indeterminate()) {\n <span class=\"mk-progress-ring__label\">{{ percent() }}%</span>\n}\n<span class=\"mk-progress-ring__center\"><ng-content /></span>\n", styles: [":host{--_ring: var(--mk-primary);display:inline-grid;place-items:center;position:relative;line-height:0;vertical-align:middle}:host([data-tone=primary]){--_ring: var(--mk-primary)}:host([data-tone=success]){--_ring: var(--mk-success)}:host([data-tone=warning]){--_ring: var(--mk-warning)}:host([data-tone=danger]){--_ring: var(--mk-danger)}:host([data-tone=info]){--_ring: var(--mk-info)}:host([data-tone=neutral]){--_ring: var(--mk-text-muted)}.mk-progress-ring__svg{grid-area:1/1;transform:rotate(-90deg)}.mk-progress-ring__track{stroke:var(--mk-border)}.mk-progress-ring__arc{stroke:var(--_ring);transition:stroke-dashoffset var(--mk-duration-normal) var(--mk-ease-standard)}:host(.mk-progress-ring--indeterminate) .mk-progress-ring__svg{animation:mk-progress-ring-spin .9s linear infinite;transform-origin:center}:host(.mk-progress-ring--indeterminate) .mk-progress-ring__arc{transition:none}.mk-progress-ring__label{grid-area:1/1;line-height:1;font-family:var(--mk-font-sans);font-size:.7em;font-weight:var(--mk-font-weight-semibold);color:var(--mk-text);font-variant-numeric:tabular-nums}.mk-progress-ring__center{grid-area:1/1;display:grid;place-items:center;line-height:1}.mk-progress-ring__center:empty{display:none}@keyframes mk-progress-ring-spin{to{transform:rotate(270deg)}}@media(prefers-reduced-motion:reduce){:host(.mk-progress-ring--indeterminate) .mk-progress-ring__svg{animation-duration:1.8s}.mk-progress-ring__arc{transition:none}}\n"] }]
1428
1166
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], thickness: [{ type: i0.Input, args: [{ isSignal: true, alias: "thickness", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], indeterminate: [{ type: i0.Input, args: [{ isSignal: true, alias: "indeterminate", required: false }] }], showLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "showLabel", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
1429
1167
 
1430
- /**
1431
- * Spinner — a circular indeterminate loading indicator. Exposes `role="status"`
1432
- * with a visually-hidden label so assistive tech announces the loading state.
1433
- * The animation slows under `prefers-reduced-motion`.
1434
- *
1435
- * ```html
1436
- * <mk-spinner />
1437
- * <mk-spinner size="lg" tone="neutral" label="Fetching results" />
1438
- * ```
1439
- */
1440
- class MkSpinner {
1441
- i18n = inject(MK_I18N);
1442
- /** Size scale. */
1443
- size = input('md', /* @ts-ignore */
1444
- ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
1445
- /** Semantic color tone. */
1446
- tone = input('primary', /* @ts-ignore */
1447
- ...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
1448
- /** Visually-hidden status label announced to screen readers. */
1449
- label = input(this.i18n.loading, /* @ts-ignore */
1450
- ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1451
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkSpinner, deps: [], target: i0.ɵɵFactoryTarget.Component });
1452
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.7", type: MkSpinner, isStandalone: true, selector: "mk-spinner", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "class.mk-spinner--sm": "size() === 'sm'", "class.mk-spinner--md": "size() === 'md'", "class.mk-spinner--lg": "size() === 'lg'", "attr.data-tone": "tone()" }, classAttribute: "mk-spinner" }, ngImport: i0, template: "<span class=\"mk-spinner__circle\" aria-hidden=\"true\"></span>\n<span class=\"mk-spinner__sr\">{{ label() }}</span>\n", styles: [":host{--_color: var(--mk-primary);--_size: var(--mk-spinner-size, 1.5rem);--_thickness: var(--mk-spinner-thickness, 2px);display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;color:var(--_color)}:host([data-tone=primary]){--_color: var(--mk-primary)}:host([data-tone=neutral]){--_color: var(--mk-text-muted)}:host([data-tone=success]){--_color: var(--mk-success)}:host([data-tone=warning]){--_color: var(--mk-warning)}:host([data-tone=danger]){--_color: var(--mk-danger)}:host([data-tone=info]){--_color: var(--mk-info)}:host(.mk-spinner--sm){--_size: var(--mk-spinner-size, 1rem);--_thickness: var(--mk-spinner-thickness, 2px)}:host(.mk-spinner--md){--_size: var(--mk-spinner-size, 1.5rem);--_thickness: var(--mk-spinner-thickness, 2px)}:host(.mk-spinner--lg){--_size: var(--mk-spinner-size, 2.25rem);--_thickness: var(--mk-spinner-thickness, 3px)}.mk-spinner__circle{display:block;width:var(--_size);height:var(--_size);border:var(--_thickness) solid currentColor;border-right-color:transparent;border-radius:50%;opacity:.9;animation:mk-spinner-spin .7s linear infinite}@keyframes mk-spinner-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.mk-spinner__circle{animation-duration:1.6s}}.mk-spinner__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1453
- }
1454
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkSpinner, decorators: [{
1455
- type: Component,
1456
- args: [{ selector: 'mk-spinner', changeDetection: ChangeDetectionStrategy.OnPush, host: {
1457
- class: 'mk-spinner',
1458
- role: 'status',
1459
- '[class.mk-spinner--sm]': "size() === 'sm'",
1460
- '[class.mk-spinner--md]': "size() === 'md'",
1461
- '[class.mk-spinner--lg]': "size() === 'lg'",
1462
- '[attr.data-tone]': 'tone()',
1463
- }, template: "<span class=\"mk-spinner__circle\" aria-hidden=\"true\"></span>\n<span class=\"mk-spinner__sr\">{{ label() }}</span>\n", styles: [":host{--_color: var(--mk-primary);--_size: var(--mk-spinner-size, 1.5rem);--_thickness: var(--mk-spinner-thickness, 2px);display:inline-flex;align-items:center;justify-content:center;vertical-align:middle;color:var(--_color)}:host([data-tone=primary]){--_color: var(--mk-primary)}:host([data-tone=neutral]){--_color: var(--mk-text-muted)}:host([data-tone=success]){--_color: var(--mk-success)}:host([data-tone=warning]){--_color: var(--mk-warning)}:host([data-tone=danger]){--_color: var(--mk-danger)}:host([data-tone=info]){--_color: var(--mk-info)}:host(.mk-spinner--sm){--_size: var(--mk-spinner-size, 1rem);--_thickness: var(--mk-spinner-thickness, 2px)}:host(.mk-spinner--md){--_size: var(--mk-spinner-size, 1.5rem);--_thickness: var(--mk-spinner-thickness, 2px)}:host(.mk-spinner--lg){--_size: var(--mk-spinner-size, 2.25rem);--_thickness: var(--mk-spinner-thickness, 3px)}.mk-spinner__circle{display:block;width:var(--_size);height:var(--_size);border:var(--_thickness) solid currentColor;border-right-color:transparent;border-radius:50%;opacity:.9;animation:mk-spinner-spin .7s linear infinite}@keyframes mk-spinner-spin{to{transform:rotate(360deg)}}@media(prefers-reduced-motion:reduce){.mk-spinner__circle{animation-duration:1.6s}}.mk-spinner__sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n"] }]
1464
- }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
1465
-
1466
1168
  /**
1467
1169
  * Shared, framework-agnostic helpers for the mk-kit SVG charts. Pure functions
1468
1170
  * only — no Angular, no DOM — so they stay trivially testable and reusable.
@@ -4869,120 +4571,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
4869
4571
  }, template: "@if (showStats()) {\n <div class=\"mk-diff__header\">\n <span class=\"mk-diff__label\">{{ beforeLabel() }} \u2192 {{ afterLabel() }}</span>\n <span class=\"mk-diff__stats\" [attr.aria-label]=\"i18n.diffChanges\">\n <span class=\"mk-diff__stat mk-diff__stat--add\">+{{ stats().added }}</span>\n <span class=\"mk-diff__stat mk-diff__stat--del\">\u2212{{ stats().removed }}</span>\n </span>\n </div>\n}\n\n<!-- Shared code cell (word segments when present, else plain text). -->\n<ng-template #cell let-row>\n @if (row.segments) {\n @for (seg of row.segments; track $index) {\n <span [class.mk-diff__word]=\"seg.changed\">{{ seg.text }}</span>\n }\n } @else {\n {{ row.text }}\n }\n</ng-template>\n\n<!-- The bodies scroll horizontally, so they are focusable labelled regions to\n stay keyboard-scrollable. Changed lines carry a visually-hidden\n \"Added:\"/\"Removed:\" prefix \u2014 color alone never marks a change. -->\n@if (mode() === 'split') {\n <div\n class=\"mk-diff__body mk-diff__body--split\"\n role=\"region\"\n tabindex=\"0\"\n [attr.aria-label]=\"i18n.diffChanges\"\n >\n @for (row of splitRows(); track $index) {\n <div\n class=\"mk-diff__cell\"\n [class.mk-diff__cell--delete]=\"row.left?.op === 'delete'\"\n [class.mk-diff__cell--empty]=\"!row.left\"\n >\n @if (lineNumbers()) {\n <span class=\"mk-diff__num\">{{ row.left?.beforeNo ?? '' }}</span>\n }\n @if (row.left?.op === 'delete') {\n <span class=\"mk-visually-hidden\">{{ i18n.diffRemovedLine }}</span>\n }\n <span class=\"mk-diff__marker\" aria-hidden=\"true\">{{\n row.left ? marker(row.left.op) : ''\n }}</span>\n <code class=\"mk-diff__code\">@if (row.left) {\n <ng-container [ngTemplateOutlet]=\"cell\" [ngTemplateOutletContext]=\"{ $implicit: row.left }\" />\n }</code>\n </div>\n <div\n class=\"mk-diff__cell\"\n [class.mk-diff__cell--insert]=\"row.right?.op === 'insert'\"\n [class.mk-diff__cell--empty]=\"!row.right\"\n >\n @if (lineNumbers()) {\n <span class=\"mk-diff__num\">{{ row.right?.afterNo ?? '' }}</span>\n }\n @if (row.right?.op === 'insert') {\n <span class=\"mk-visually-hidden\">{{ i18n.diffAddedLine }}</span>\n }\n <span class=\"mk-diff__marker\" aria-hidden=\"true\">{{\n row.right ? marker(row.right.op) : ''\n }}</span>\n <code class=\"mk-diff__code\">@if (row.right) {\n <ng-container [ngTemplateOutlet]=\"cell\" [ngTemplateOutletContext]=\"{ $implicit: row.right }\" />\n }</code>\n </div>\n }\n </div>\n} @else {\n <div\n class=\"mk-diff__body\"\n role=\"region\"\n tabindex=\"0\"\n [attr.aria-label]=\"i18n.diffChanges\"\n >\n @for (row of rows(); track $index) {\n <div\n class=\"mk-diff__row\"\n [class.mk-diff__row--insert]=\"row.op === 'insert'\"\n [class.mk-diff__row--delete]=\"row.op === 'delete'\"\n >\n @if (lineNumbers()) {\n <span class=\"mk-diff__num\">{{ row.beforeNo ?? '' }}</span>\n <span class=\"mk-diff__num\">{{ row.afterNo ?? '' }}</span>\n }\n @if (row.op === 'insert') {\n <span class=\"mk-visually-hidden\">{{ i18n.diffAddedLine }}</span>\n } @else if (row.op === 'delete') {\n <span class=\"mk-visually-hidden\">{{ i18n.diffRemovedLine }}</span>\n }\n <span class=\"mk-diff__marker\" aria-hidden=\"true\">{{ marker(row.op) }}</span>\n <code class=\"mk-diff__code\"><ng-container [ngTemplateOutlet]=\"cell\" [ngTemplateOutletContext]=\"{ $implicit: row }\" /></code>\n </div>\n }\n </div>\n}\n", styles: [":host{--_add-bg: color-mix(in srgb, var(--mk-success) 12%, var(--mk-surface));--_add-word: color-mix(in srgb, var(--mk-success) 28%, var(--mk-surface));--_del-bg: color-mix(in srgb, var(--mk-danger) 12%, var(--mk-surface));--_del-word: color-mix(in srgb, var(--mk-danger) 28%, var(--mk-surface));display:block;overflow:hidden;background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);font-family:var(--mk-font-sans)}.mk-diff__header{display:flex;align-items:center;justify-content:space-between;gap:var(--mk-space-2);padding:var(--mk-space-2) var(--mk-space-3);background-color:var(--mk-surface-2);border-bottom:var(--mk-border-width) solid var(--mk-border-subtle);font-size:var(--mk-font-size-sm)}.mk-diff__label{color:var(--mk-text-muted);font-weight:var(--mk-font-weight-medium)}.mk-diff__stats{display:flex;gap:var(--mk-space-2);font-family:var(--mk-font-mono);font-size:var(--mk-font-size-xs);font-weight:var(--mk-font-weight-semibold)}.mk-diff__stat--add{color:var(--mk-success)}.mk-diff__stat--del{color:var(--mk-danger-text)}.mk-diff__body{direction:ltr;overflow-x:auto;font-family:var(--mk-font-mono);font-size:var(--mk-font-size-sm);line-height:1.6}.mk-diff__body:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:calc(-1 * var(--mk-focus-ring-width))}.mk-diff__row{display:flex;align-items:baseline;min-height:1.6em}.mk-diff__row--insert{background-color:var(--_add-bg)}.mk-diff__row--delete{background-color:var(--_del-bg)}.mk-diff__num{flex:none;width:3ch;padding:0 var(--mk-space-2);text-align:right;color:var(--mk-text-subtle);user-select:none;-webkit-user-select:none}.mk-diff__marker{flex:none;width:2ch;text-align:center;color:var(--mk-text-muted);-webkit-user-select:none;user-select:none}.mk-diff__code{flex:1 1 auto;min-width:0;padding-right:var(--mk-space-3);white-space:pre-wrap;overflow-wrap:anywhere;color:var(--mk-text);font:inherit;background:none}.mk-diff__word{border-radius:var(--mk-radius-sm)}.mk-diff__row--insert .mk-diff__word{background-color:var(--_add-word)}.mk-diff__row--delete .mk-diff__word{background-color:var(--_del-word)}.mk-diff__body--split{display:grid;grid-template-columns:1fr 1fr}.mk-diff__cell{display:flex;align-items:baseline;min-height:1.6em;border-right:var(--mk-border-width) solid var(--mk-border-subtle)}.mk-diff__cell:nth-child(2n){border-right:none}.mk-diff__cell--insert{background-color:var(--_add-bg)}.mk-diff__cell--delete{background-color:var(--_del-bg)}.mk-diff__cell--empty{background-color:var(--mk-surface-2)}.mk-diff__cell--insert .mk-diff__word{background-color:var(--_add-word)}.mk-diff__cell--delete .mk-diff__word{background-color:var(--_del-word)}.mk-diff__cell--insert .mk-diff__marker{color:var(--mk-success)}.mk-diff__cell--delete .mk-diff__marker{color:var(--mk-danger-text)}\n"] }]
4870
4572
  }], propDecorators: { before: [{ type: i0.Input, args: [{ isSignal: true, alias: "before", required: false }] }], after: [{ type: i0.Input, args: [{ isSignal: true, alias: "after", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], wordHighlight: [{ type: i0.Input, args: [{ isSignal: true, alias: "wordHighlight", required: false }] }], lineNumbers: [{ type: i0.Input, args: [{ isSignal: true, alias: "lineNumbers", required: false }] }], ignoreTrailingWhitespace: [{ type: i0.Input, args: [{ isSignal: true, alias: "ignoreTrailingWhitespace", required: false }] }], showStats: [{ type: i0.Input, args: [{ isSignal: true, alias: "showStats", required: false }] }], beforeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "beforeLabel", required: false }] }], afterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "afterLabel", required: false }] }] } });
4871
4573
 
4872
- /** Stable empty fallback so out-of-range lookups don't allocate per call. */
4873
- const NO_CONNECTIONS = [];
4874
- /**
4875
- * Kanban board — a horizontal row of columns whose cards can be dragged and
4876
- * reordered within a column or transferred between columns. Built on the dnd
4877
- * group's connected `[mkDropList]` / `[mkDrag]` directives, so it inherits both
4878
- * pointer and keyboard dragging (WCAG 2.1.1) for free.
4879
- *
4880
- * Bind `columns` two-way; the model is updated immutably on each drop. Project
4881
- * an `<ng-template>` to render custom card content — it receives the card as
4882
- * `$implicit` and the owning column as `column`:
4883
- *
4884
- * ```html
4885
- * <mk-kanban [(columns)]="board" (cardMoved)="onMoved($event)">
4886
- * <ng-template #cardTemplate let-card let-column="column">
4887
- * <strong>{{ card.title }}</strong>
4888
- * </ng-template>
4889
- * </mk-kanban>
4890
- * ```
4891
- */
4892
- class MkKanban {
4893
- /** The board's columns and their cards (two-way). Updated on every drop. */
4894
- columns = model([], /* @ts-ignore */
4895
- ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
4896
- /** Disable all dragging on the board. */
4897
- disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4898
- /** Emitted after the model is updated when a card is moved. */
4899
- cardMoved = output();
4900
- /** Optional consumer-projected card renderer (`$implicit` = card). */
4901
- cardTemplate = contentChild(TemplateRef, /* @ts-ignore */
4902
- ...(ngDevMode ? [{ debugName: "cardTemplate" }] : /* istanbul ignore next */ []));
4903
- /** Board-scoped prefix so this board's drop-list ids never collide. */
4904
- boardId = mkUniqueId('mk-kanban');
4905
- /** Column count as its own computed so id arrays survive card-only updates. */
4906
- columnCount = computed(() => this.columns().length, /* @ts-ignore */
4907
- ...(ngDevMode ? [{ debugName: "columnCount" }] : /* istanbul ignore next */ []));
4908
- /** Stable drop-list id per column, positionally matched to `columns()`. */
4909
- listIds = computed(() => Array.from({ length: this.columnCount() }, (_, i) => `${this.boardId}-col-${i}`), /* @ts-ignore */
4910
- ...(ngDevMode ? [{ debugName: "listIds" }] : /* istanbul ignore next */ []));
4911
- /**
4912
- * Per-column connected-target ids (every other column's list). One stable
4913
- * array per column, recomputed only when the column count changes — a fresh
4914
- * array per change-detection pass would dirty each `MkDropList`'s
4915
- * `connectedTo` input identity on every cycle.
4916
- */
4917
- connections = computed(() => {
4918
- const ids = this.listIds();
4919
- return ids.map((_, i) => ids.filter((_, j) => j !== i));
4920
- }, /* @ts-ignore */
4921
- ...(ngDevMode ? [{ debugName: "connections" }] : /* istanbul ignore next */ []));
4922
- /** Ids of every other column's list — the connected transfer targets for `i`. */
4923
- connectedTo(index) {
4924
- return this.connections()[index] ?? NO_CONNECTIONS;
4925
- }
4926
- /**
4927
- * Apply a drop from the dnd module. Reads the source/target columns from the
4928
- * event's containers (matched by their drop-list ids), updates the two-way
4929
- * `columns` model immutably, then emits {@link cardMoved}.
4930
- */
4931
- onDrop(event) {
4932
- const ids = this.listIds();
4933
- const fromCol = ids.indexOf(event.previousContainer.id());
4934
- const toCol = ids.indexOf(event.container.id());
4935
- if (fromCol === -1 || toCol === -1)
4936
- return;
4937
- this.moveCard(fromCol, toCol, event.previousIndex, event.currentIndex);
4938
- }
4939
- /**
4940
- * Immutably move the card at `fromIndex` of column `fromCol` to `toIndex` of
4941
- * column `toCol`, updating the model and emitting {@link cardMoved}. Column
4942
- * indices refer to positions in `columns()`.
4943
- */
4944
- moveCard(fromCol, toCol, fromIndex, toIndex) {
4945
- const cols = this.columns();
4946
- const source = cols[fromCol];
4947
- const target = cols[toCol];
4948
- if (!source || !target)
4949
- return;
4950
- const card = source.cards[fromIndex];
4951
- if (!card)
4952
- return;
4953
- const next = cols.map((col, i) => {
4954
- if (fromCol === toCol && i === fromCol) {
4955
- const cards = [...col.cards];
4956
- mkMoveItemInArray(cards, fromIndex, toIndex);
4957
- return { ...col, cards };
4958
- }
4959
- if (i === fromCol) {
4960
- return { ...col, cards: col.cards.filter((_, idx) => idx !== fromIndex) };
4961
- }
4962
- if (i === toCol) {
4963
- const cards = [...col.cards];
4964
- cards.splice(Math.max(0, Math.min(toIndex, cards.length)), 0, card);
4965
- return { ...col, cards };
4966
- }
4967
- return col;
4968
- });
4969
- this.columns.set(next);
4970
- this.cardMoved.emit({
4971
- card,
4972
- from: source.id,
4973
- to: target.id,
4974
- fromIndex,
4975
- toIndex,
4976
- });
4977
- }
4978
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkKanban, deps: [], target: i0.ɵɵFactoryTarget.Component });
4979
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MkKanban, isStandalone: true, selector: "mk-kanban", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { columns: "columnsChange", cardMoved: "cardMoved" }, host: { classAttribute: "mk-kanban" }, queries: [{ propertyName: "cardTemplate", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"mk-kanban__board\">\n @for (column of columns(); track column.id; let colIndex = $index) {\n <section\n class=\"mk-kanban__column\"\n role=\"region\"\n [attr.aria-label]=\"column.title\"\n >\n <header class=\"mk-kanban__column-header\">\n <span class=\"mk-kanban__column-title\">{{ column.title }}</span>\n <span class=\"mk-kanban__column-count\" aria-hidden=\"true\">\n {{ column.cards.length }}\n </span>\n </header>\n\n <div\n mkDropList\n class=\"mk-kanban__cards\"\n [mkDropListData]=\"column.cards\"\n [mkDropListId]=\"listIds()[colIndex]\"\n [mkDropListLabel]=\"column.title\"\n [mkDropListConnectedTo]=\"connectedTo(colIndex)\"\n [mkDropListDisabled]=\"disabled()\"\n mkDropListOrientation=\"vertical\"\n (mkDropListDropped)=\"onDrop($event)\"\n >\n @for (card of column.cards; track card.id) {\n <div\n mkDrag\n class=\"mk-kanban__card\"\n [mkDragData]=\"card\"\n [mkDragDisabled]=\"disabled()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"cardTemplate() ?? defaultCard\"\n [ngTemplateOutletContext]=\"{ $implicit: card, column: column }\"\n />\n </div>\n }\n </div>\n </section>\n }\n</div>\n\n<ng-template #defaultCard let-card>\n <span class=\"mk-kanban__card-title\">{{ card.title }}</span>\n</ng-template>\n", styles: [":host{display:block;color:var(--mk-text)}.mk-kanban__board{display:flex;gap:var(--mk-space-4);align-items:flex-start;overflow-x:auto;padding-bottom:var(--mk-space-2)}.mk-kanban__column{display:flex;flex-direction:column;flex:0 0 auto;width:17rem;max-height:100%;background-color:var(--mk-surface-2);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg)}.mk-kanban__column-header{display:flex;align-items:center;justify-content:space-between;gap:var(--mk-space-2);padding:var(--mk-space-3) var(--mk-space-4);font-weight:600;border-bottom:var(--mk-border-width) solid var(--mk-border)}.mk-kanban__column-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-kanban__column-count{flex:0 0 auto;min-width:1.5rem;padding:0 var(--mk-space-2);font-size:.75rem;font-weight:600;line-height:1.5rem;text-align:center;color:var(--mk-text-muted);background-color:var(--mk-surface);border-radius:var(--mk-radius-md)}.mk-kanban__cards{display:flex;flex-direction:column;gap:var(--mk-space-2);flex:1 1 auto;min-height:var(--mk-space-8);padding:var(--mk-space-3);overflow-y:auto}.mk-kanban__card{padding:var(--mk-space-3) var(--mk-space-4);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);box-shadow:var(--mk-shadow-sm)}.mk-kanban__card:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-kanban__card-title{display:block;min-width:0;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "component", type: MkDropList, selector: "[mkDropList]", inputs: ["mkDropListData", "mkDropListId", "mkDropListConnectedTo", "mkDropListLabel", "mkDropListLabelledBy", "mkDropListOrientation", "mkDropListDisabled"], outputs: ["mkDropListDropped"], exportAs: ["mkDropList"] }, { kind: "component", type: MkDrag, selector: "[mkDrag]", inputs: ["mkDragData", "mkDragDisabled", "mkDragTouchDelay"], exportAs: ["mkDrag"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4980
- }
4981
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MkKanban, decorators: [{
4982
- type: Component,
4983
- args: [{ selector: 'mk-kanban', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MkDropList, MkDrag, NgTemplateOutlet], host: { class: 'mk-kanban' }, template: "<div class=\"mk-kanban__board\">\n @for (column of columns(); track column.id; let colIndex = $index) {\n <section\n class=\"mk-kanban__column\"\n role=\"region\"\n [attr.aria-label]=\"column.title\"\n >\n <header class=\"mk-kanban__column-header\">\n <span class=\"mk-kanban__column-title\">{{ column.title }}</span>\n <span class=\"mk-kanban__column-count\" aria-hidden=\"true\">\n {{ column.cards.length }}\n </span>\n </header>\n\n <div\n mkDropList\n class=\"mk-kanban__cards\"\n [mkDropListData]=\"column.cards\"\n [mkDropListId]=\"listIds()[colIndex]\"\n [mkDropListLabel]=\"column.title\"\n [mkDropListConnectedTo]=\"connectedTo(colIndex)\"\n [mkDropListDisabled]=\"disabled()\"\n mkDropListOrientation=\"vertical\"\n (mkDropListDropped)=\"onDrop($event)\"\n >\n @for (card of column.cards; track card.id) {\n <div\n mkDrag\n class=\"mk-kanban__card\"\n [mkDragData]=\"card\"\n [mkDragDisabled]=\"disabled()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"cardTemplate() ?? defaultCard\"\n [ngTemplateOutletContext]=\"{ $implicit: card, column: column }\"\n />\n </div>\n }\n </div>\n </section>\n }\n</div>\n\n<ng-template #defaultCard let-card>\n <span class=\"mk-kanban__card-title\">{{ card.title }}</span>\n</ng-template>\n", styles: [":host{display:block;color:var(--mk-text)}.mk-kanban__board{display:flex;gap:var(--mk-space-4);align-items:flex-start;overflow-x:auto;padding-bottom:var(--mk-space-2)}.mk-kanban__column{display:flex;flex-direction:column;flex:0 0 auto;width:17rem;max-height:100%;background-color:var(--mk-surface-2);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-lg)}.mk-kanban__column-header{display:flex;align-items:center;justify-content:space-between;gap:var(--mk-space-2);padding:var(--mk-space-3) var(--mk-space-4);font-weight:600;border-bottom:var(--mk-border-width) solid var(--mk-border)}.mk-kanban__column-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mk-kanban__column-count{flex:0 0 auto;min-width:1.5rem;padding:0 var(--mk-space-2);font-size:.75rem;font-weight:600;line-height:1.5rem;text-align:center;color:var(--mk-text-muted);background-color:var(--mk-surface);border-radius:var(--mk-radius-md)}.mk-kanban__cards{display:flex;flex-direction:column;gap:var(--mk-space-2);flex:1 1 auto;min-height:var(--mk-space-8);padding:var(--mk-space-3);overflow-y:auto}.mk-kanban__card{padding:var(--mk-space-3) var(--mk-space-4);background-color:var(--mk-surface);border:var(--mk-border-width) solid var(--mk-border);border-radius:var(--mk-radius-md);box-shadow:var(--mk-shadow-sm)}.mk-kanban__card:focus-visible{outline:var(--mk-focus-ring-width) solid var(--mk-focus-ring);outline-offset:var(--mk-focus-ring-offset)}.mk-kanban__card-title{display:block;min-width:0;overflow-wrap:anywhere}\n"] }]
4984
- }], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }, { type: i0.Output, args: ["columnsChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], cardMoved: [{ type: i0.Output, args: ["cardMoved"] }], cardTemplate: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TemplateRef), { isSignal: true }] }] } });
4985
-
4986
4574
  /**
4987
4575
  * Dependency-free QR Code encoder.
4988
4576
  *
@@ -6087,5 +5675,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImpor
6087
5675
  * Generated bundle index. Do not edit.
6088
5676
  */
6089
5677
 
6090
- 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, mkContrastRatio, mkEncodeQr, mkFormatCompact, mkHeatmapCellColors, mkLinePath, mkLinearScale, mkMixRgb, mkNiceTicks, mkOrgChartFromFlat, mkParseRgb, mkRelativeLuminance, mkSplitDuration, mkSquarify };
5678
+ export { MK_CHART_PALETTE_SIZE, MK_HEATMAP_MIN_CONTRAST, MkAvatar, MkAvatarGroup, MkBarChart, MkCalendarHeatmap, MkCard, MkCardFooter, MkCardHeader, MkCardTitle, MkCarousel, MkCarouselSlide, MkCode, MkCountdown, MkDescItem, MkDescriptionList, MkDiff, MkDivider, MkDonutChart, MkFunnelChart, MkGauge, MkHeatmap, MkInlineEdit, MkJsonViewer, MkLineChart, MkList, MkListItem, MkLogViewer, MkMarkdown, MkOrgChart, MkOrgChartNodeDef, MkProfileActions, MkProfileCard, MkProfileMeta, MkProgressBar, MkProgressRing, MkQrCode, MkRadarChart, MkScatterChart, MkSkeleton, MkSkeletonPreset, MkSparkline, MkStatCard, MkTag, MkTimeline, MkTimelineItem, MkTreemap, MkVirtualScroll, mkArcPath, mkAreaPath, mkBuildJsonTree, mkChartColor, mkContrastRatio, mkEncodeQr, mkFormatCompact, mkHeatmapCellColors, mkLinePath, mkLinearScale, mkMixRgb, mkNiceTicks, mkOrgChartFromFlat, mkParseRgb, mkRelativeLuminance, mkSplitDuration, mkSquarify };
6091
5679
  //# sourceMappingURL=mk-kit-ui-data.mjs.map