{
 "package": "@mk-kit/ui",
 "version": "0.60.2",
 "site": "https://mk-kit.dev",
 "entries": [
  {
   "name": "core",
   "import": "@mk-kit/ui/core",
   "exports": [
    {
     "name": "MkAnchoredPanel",
     "description": "Anchored-overlay directive. Apply it to a floating panel element (a dropdown\nlist, calendar, menu, …) that is rendered inside its component's own template\n— typically inside an `@if (open()) { … }` block. On init the directive\n**teleports the panel to `document.body` and into the browser top layer** via\nthe native Popover API (`popover=\"manual\"` + `showPopover()`), then positions\nit against the anchor with `position: fixed`. Because the element stays part\nof the component's Angular view, all bindings, `@for` content, events and\nprojected content keep working after the move.\n\nThe top layer is immune to ancestor `overflow`, `transform` and `z-index`\nstacking contexts, so the panel can never be clipped by a container or hidden\nbehind sibling content. Where the Popover API is unavailable the panel still\nrenders in a `document.body` portal with a `z-index` fallback.\n\n```html\n<ul #panel mkAnchoredPanel [mkAnchoredPanelFor]=\"trigger\" [matchWidth]=\"true\"\n    (dismiss)=\"close()\"> … </ul>\n```",
     "file": "projects/mk-kit/core/overlay/anchored-overlay.ts",
     "kind": "directive",
     "selector": "[mkAnchoredPanel]",
     "selectors": [
      "mkAnchoredPanel"
     ],
     "exportAs": "mkAnchoredPanel",
     "inputs": [
      {
       "name": "mkAnchoredPanelFor",
       "type": "HTMLElement | ElementRef<HTMLElement> | undefined",
       "description": "The trigger element to position against.",
       "default": "undefined"
      },
      {
       "name": "anchorRect",
       "type": "{ x: number; y: number; } | undefined",
       "description": "Viewport-point anchor (e.g. a right-click position) — takes precedence.",
       "default": "undefined"
      },
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": "Preferred placement relative to the anchor.",
       "default": "'bottom-start'"
      },
      {
       "name": "gap",
       "type": "number",
       "description": "Distance in px between the anchor and the panel.",
       "default": "4"
      },
      {
       "name": "matchWidth",
       "type": "boolean",
       "description": "Set the panel's `min-width` to the anchor's width (dropdowns).",
       "default": "false"
      },
      {
       "name": "flip",
       "type": "boolean",
       "description": "Flip to the opposite side when the preferred side would overflow.",
       "default": "true"
      },
      {
       "name": "clamp",
       "type": "boolean",
       "description": "Clamp the panel inside the viewport.",
       "default": "true"
      },
      {
       "name": "keepOpenWhen",
       "type": "((target: Node) => boolean) | null",
       "description": "Predicate consulted before an outside pointerdown dismisses the panel.\nReturn `true` for targets that must keep it open — e.g. a nested panel\n(a submenu) that lives in the top layer outside this element.",
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "dismiss",
       "type": "void",
       "description": "Emitted on an outside pointerdown or when the window loses focus."
      }
     ],
     "methods": [
      {
       "name": "position",
       "signature": "(track?: boolean): void",
       "description": "Recompute and apply the panel position. Safe to call at any time.\nWith `track` (scroll-driven), the panel follows the anchor unclamped and\ndismisses once the anchor leaves the viewport (matching the CDK's\nreposition-with-auto-close scroll behaviour)."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/core-services"
    },
    {
     "name": "MkAccentService",
     "description": "Runtime accent — the user picks one of `MK_ACCENTS` and every kit\ncontrol recolours: the service writes the `--mk-primary` family\n(`primary`, `-hover`, `-active`, `-subtle`, `-subtle-hover`,\n`-subtle-text`), `--mk-focus-ring`, `--mk-selected-bg` / `-text` and three\naccent tokens of its own — `--mk-accent`, `--mk-accent-ink`,\n`--mk-accent-glow` — onto `<html>`, and mirrors the key as\n`data-mk-accent`. Hover / active are a touch darker in light and a touch\nlighter in dark (it follows `MkThemeService`). The choice persists\nin `localStorage` (`mk-kit-accent`); nothing is written until `set()` is\ncalled, so an app that never picks keeps the preset's own primary.\n\n```ts\nreadonly accent = inject(MkAccentService);\naccent.set('coral');           // every button, ring and chip turns coral\naccent.key();                  // 'coral'\nmkAccentSwatch(accent.key());  // for the picker\n```",
     "file": "projects/mk-kit/core/theme/accent.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "set",
       "signature": "(key: MkAccentKey): void",
       "description": "Pick an accent; persisted."
      },
      {
       "name": "reset",
       "signature": "(): void",
       "description": "Back to the preset's own primary; the stored choice is cleared."
      }
     ],
     "properties": [
      {
       "name": "key",
       "type": "Signal<MkAccentKey | null>",
       "description": "The chosen accent, or `null` while the preset's own primary is in use.",
       "readonly": true
      },
      {
       "name": "accent",
       "type": "Signal<MkAccent>",
       "description": "The chosen accent's definition (indigo when none is chosen).",
       "readonly": true
      }
     ]
    },
    {
     "name": "MkBreakpointService",
     "description": "Reactive viewport breakpoints, one `matchMedia` listener per step.\n\n```ts\nprivate readonly bp = inject(MkBreakpointService);\nreadonly compact = this.bp.down('md');          // Signal<boolean>\nreadonly columns = computed(() => this.bp.resolve({ xs: 1, md: 2, xl: 4 }));\n```\n\nOn the server (no `window`) everything reports `xs`.",
     "file": "projects/mk-kit/core/layout/breakpoint.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "up",
       "signature": "(bp: MkBreakpoint): Signal<boolean>",
       "description": "True while the viewport is at least `bp` wide (`up('md')` = md, lg, xl, 2xl)."
      },
      {
       "name": "down",
       "signature": "(bp: MkBreakpoint): Signal<boolean>",
       "description": "True while the viewport is narrower than `bp` (`down('md')` = xs, sm)."
      },
      {
       "name": "between",
       "signature": "(from: MkBreakpoint, to: MkBreakpoint): Signal<boolean>",
       "description": "True while the viewport is at least `from` and narrower than `to`."
      },
      {
       "name": "observe",
       "signature": "(query: string): Signal<boolean>",
       "description": "Any media query as a signal, e.g. `observe('(orientation: portrait)')`."
      },
      {
       "name": "resolve",
       "signature": "<T>(value: MkResponsive<T>): T | undefined",
       "description": "Pick the entry of a responsive value for the current viewport —\nmobile-first, so `{ xs: 1, md: 2 }` gives 1 on `sm` and 2 on `xl`.\nA plain value is returned as is. Read inside a `computed` to track it."
      }
     ],
     "properties": [
      {
       "name": "breakpoints",
       "type": "MkBreakpoints",
       "description": "The breakpoint scale in effect (see `MK_BREAKPOINTS`).",
       "readonly": true
      },
      {
       "name": "current",
       "type": "Signal<MkBreakpoint>",
       "description": "The widest breakpoint the viewport currently satisfies.",
       "readonly": true
      }
     ],
     "docs": "/core-services"
    },
    {
     "name": "MkLiveAnnouncer",
     "description": "Announces messages to assistive technology via a visually-hidden\n`aria-live` region. Used by toasts, form validation, sort changes, etc.\nso state changes are perceivable without sight. WCAG 4.1.3 (Status Messages).",
     "file": "projects/mk-kit/core/a11y/live-announcer.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "announce",
       "signature": "(message: string, politeness?: MkAriaLivePoliteness): void",
       "description": "Announce `message`. `politeness` controls interruption behavior."
      }
     ],
     "properties": [],
     "docs": "/core-services"
    },
    {
     "name": "MkOverlayService",
     "description": "Lightweight, dependency-free overlay renderer. Instantiates a standalone\ncomponent into a body-level host, manages the backdrop, focus trapping,\nEscape handling, and scroll locking. Powers Dialog, Menu, and others.",
     "file": "projects/mk-kit/core/overlay/overlay.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "closeAll",
       "signature": "(): void",
       "description": "Close every open overlay, newest first. Each is closed with no result, so\n`afterClosed` resolves undefined exactly as a backdrop click or Escape\nwould. Safe to call when nothing is open."
      },
      {
       "name": "open",
       "signature": "<TComponent, TResult = unknown, TData = unknown>(component: Type<TComponent>, config?: MkOverlayConfig<TData>): MkOverlayRef<TResult, TComponent>",
       "description": ""
      }
     ],
     "properties": [
      {
       "name": "openCount",
       "type": "number",
       "description": "How many overlays are currently open.",
       "readonly": true
      }
     ],
     "docs": "/core-services"
    },
    {
     "name": "MkThemeService",
     "description": "Reactive theme controller for mk-kit.\n\n- `preference()` is the user's choice: `light`, `dark`, or `system`.\n- `resolvedTheme()` is the concrete theme currently applied.\n- Writes `data-mk-theme` on `<html>` and persists the choice to\n  `localStorage`. When set to `system`, it live-tracks the OS setting and\n  removes the attribute so pure-CSS `prefers-color-scheme` takes over.\n\nProvided in root — inject it anywhere and bind to the signals.",
     "file": "projects/mk-kit/core/theme/theme.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "setDensity",
       "signature": "(density: MkDensity): void",
       "description": "Set the global density mode."
      },
      {
       "name": "toggleDensity",
       "signature": "(): void",
       "description": "Toggle between comfortable and compact — the two modes a density switch in\na UI offers. `touch` is a deliberate choice for a specific screen, not\nsomething to land on by toggling, so from `touch` this returns to\ncomfortable rather than cycling."
      },
      {
       "name": "setContrast",
       "signature": "(contrast: MkContrastPreference): void",
       "description": "Set the contrast preference explicitly."
      },
      {
       "name": "toggleContrast",
       "signature": "(): void",
       "description": "Toggle between normal and high contrast (resolving `system` first)."
      },
      {
       "name": "setTheme",
       "signature": "(preference: MkThemePreference): void",
       "description": "Set the theme preference explicitly."
      },
      {
       "name": "toggle",
       "signature": "(): void",
       "description": "Toggle between light and dark (resolving `system` first)."
      }
     ],
     "properties": [
      {
       "name": "preference",
       "type": "Signal<MkThemePreference>",
       "description": "The user's theme preference.",
       "readonly": true
      },
      {
       "name": "resolvedTheme",
       "type": "Signal<MkResolvedTheme>",
       "description": "The concrete theme in effect (`light` or `dark`).",
       "readonly": true
      },
      {
       "name": "isDark",
       "type": "Signal<boolean>",
       "description": "Convenience boolean for template bindings.",
       "readonly": true
      },
      {
       "name": "density",
       "type": "Signal<MkDensity>",
       "description": "The global density mode. `compact` tightens control heights and the core\nspacing steps via the `data-mk-density` attribute, `touch` enlarges them —\nevery component follows automatically because they read the same tokens.\n\nThis signal is the GLOBAL mode only. To make one screen or dialog touch-\nsized inside an otherwise comfortable app, put `data-mk-density=\"touch\"`\non that element instead; the tokens inherit and this service stays out of\nit.",
       "readonly": true
      },
      {
       "name": "contrast",
       "type": "Signal<MkContrastPreference>",
       "description": "The user's contrast preference: `normal`, `high` or `system` (follow the\nOS `prefers-contrast` setting — the default). Written as\n`data-mk-contrast` on `<html>` and persisted; `system` removes the\nattribute so the pure-CSS `prefers-contrast: more` mapping takes over.\n\nLike density, the attribute also works per subtree: put\n`data-mk-contrast=\"high\"` on any element to raise contrast there only.",
       "readonly": true
      },
      {
       "name": "resolvedContrast",
       "type": "Signal<MkResolvedContrast>",
       "description": "The concrete contrast in effect (`normal` or `high`).",
       "readonly": true
      },
      {
       "name": "isHighContrast",
       "type": "Signal<boolean>",
       "description": "Convenience boolean for template bindings.",
       "readonly": true
      }
     ],
     "docs": "/core-services"
    },
    {
     "name": "MkFieldContext",
     "description": "Field context — the contract a field wrapper (`mk-form-field`) exposes to\nthe control nested inside it. Controls inject it optionally\n(`inject(MkFieldContext, { optional: true })`) to adopt the wrapper's\ncontrol id and to reflect its required/error state and `aria-describedby`\nwiring — without depending on the `@mk-kit/ui/forms` entry point.\n\n`MkFormField` provides itself under this token; standalone usage (no\nwrapper) simply yields `null`.",
     "file": "projects/mk-kit/core/forms/field-context.ts",
     "kind": "class",
     "methods": [],
     "properties": [
      {
       "name": "controlId",
       "type": "string",
       "description": "Id for the nested interactive control — adopt on your control element.",
       "readonly": true
      },
      {
       "name": "labelId",
       "type": "string",
       "description": "Id of the field's label element, for `aria-labelledby`.",
       "readonly": true
      },
      {
       "name": "size",
       "type": "Signal<MkSize>",
       "description": "The field's visual size, mirrored onto the nested control.",
       "readonly": true
      },
      {
       "name": "isRequired",
       "type": "Signal<boolean>",
       "description": "Whether the field is required (explicitly or via the bound control).",
       "readonly": true
      },
      {
       "name": "hasError",
       "type": "Signal<boolean>",
       "description": "Whether the field currently shows an error.",
       "readonly": true
      },
      {
       "name": "describedBy",
       "type": "Signal<string | null>",
       "description": "Space-separated id list for the nested control's `aria-describedby`,\nor `null` when there is nothing to describe.",
       "readonly": true
      }
     ]
    },
    {
     "name": "MkFocusTrap",
     "description": "Traps keyboard focus within `root` (wrapping Tab / Shift+Tab), moves focus\ninside on activation, and restores focus to the previously-focused element\non release. Essential for accessible modals/menus (WCAG 2.4.3, 2.1.2).",
     "file": "projects/mk-kit/core/a11y/focus-trap.ts",
     "kind": "class",
     "methods": [
      {
       "name": "activate",
       "signature": "(initialFocus?: HTMLElement): void",
       "description": "Activate the trap and move focus to the first focusable element (or root)."
      },
      {
       "name": "release",
       "signature": "(): void",
       "description": "Deactivate and restore focus to the trigger element."
      }
     ],
     "properties": [],
     "docs": "/core-services"
    },
    {
     "name": "MkOverlayRef",
     "description": "Handle to an open overlay. Injected into the rendered component and returned\nfrom `MkOverlayService.open`. Resolve the overlay by calling `close`.\n\nThe close result is exposed three ways so the handle fits whatever style the\ncalling code already uses — they all settle together:\n\n- `result` — a signal, for template binding and signal-based components.\n- `closed$` — an Observable that emits once and completes, for RxJS\n  pipelines. A service that hands a dialog result back to its callers can\n  return this directly instead of wrapping the promise in `from(...)`.\n- `afterClosed` — a Promise, for `await` / `.then()`.",
     "file": "projects/mk-kit/core/overlay/overlay-ref.ts",
     "kind": "class",
     "typeParams": "<TResult = unknown, TComponent = unknown>",
     "methods": [
      {
       "name": "close",
       "signature": "(result?: TResult): void",
       "description": "Close the overlay, optionally returning a result."
      }
     ],
     "properties": [
      {
       "name": "componentRef",
       "type": "ComponentRef<TComponent> | undefined",
       "description": "The rendered component instance (set by the service after creation).",
       "readonly": false
      },
      {
       "name": "closed",
       "type": "Signal<boolean>",
       "description": "Becomes `true` once the overlay has been dismissed.",
       "readonly": true
      },
      {
       "name": "result",
       "type": "Signal<TResult | undefined>",
       "description": "The value passed to `close`, or `undefined` while open and for a dismissal\n(Escape / backdrop). Read `closed()` to tell \"closed with no result\" apart\nfrom \"still open\".",
       "readonly": true
      },
      {
       "name": "afterClosed",
       "type": "Promise<TResult | undefined>",
       "description": "Resolves with the close result when the overlay is dismissed.",
       "readonly": true
      },
      {
       "name": "closed$",
       "type": "Observable<TResult | undefined>",
       "description": "Emits the close result once, then completes. Subscribing after the overlay\nhas already closed replays the result immediately, so a late subscriber\nnever hangs.",
       "readonly": true
      }
     ]
    },
    {
     "name": "mkAccentSwatch",
     "description": "The swatch a picker shows for an accent (bumblebee is the black / yellow split).",
     "file": "projects/mk-kit/core/theme/accent.service.ts",
     "kind": "function",
     "signatures": [
      "(key: MkAccentKey): string"
     ]
    },
    {
     "name": "mkBodyLevelAncestor",
     "description": "The direct child of `document.body` an overlay-root descendant lives under,\ncrossing shadow boundaries on the way up — `null` when the node is not under\n`body` at all. The overlay service uses it to keep the overlay's own host\nout of the elements it makes `inert` behind a modal.",
     "file": "projects/mk-kit/core/overlay/overlay-root.ts",
     "kind": "function",
     "signatures": [
      "(node: Node, body: HTMLElement): Element | null"
     ]
    },
    {
     "name": "mkComputeAnchoredPosition",
     "description": "Pure viewport-positioning maths shared by every anchored overlay\n(`MkAnchoredPanel` and the tooltip). Given the anchor rect, the panel\nsize and the viewport size, returns the top/left for a `position: fixed`\npanel — flipping to the opposite side when it would overflow and clamping\nback inside the viewport.",
     "file": "projects/core/src/anchor.ts",
     "kind": "function",
     "signatures": [
      "(anchor: MkRectLike, panel: MkDimensions, viewport: MkDimensions, opts: MkAnchoredPositionOptions): MkAnchoredPosition"
     ]
    },
    {
     "name": "mkCreateQueryGroup",
     "description": "A fresh empty group.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(init?: Partial<Omit<MkQueryGroup, \"id\">>): MkQueryGroup"
     ]
    },
    {
     "name": "mkCreateQueryRule",
     "description": "A fresh rule on `field`, using its first operator.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(field: MkQueryField): MkQueryRule"
     ]
    },
    {
     "name": "mkFirstErrorMessage",
     "description": "Resolves the message for the first error on a control, mirroring how\n`mat-error` shows one message at a time.\n\nLookup order per key: the field's `overrides`, then the i18n `validation`\ntable, then the error payload's own `message` string (so a custom validator\ncan carry its text), then the generic fallback. Keys are visited in the\norder the validators put them on the control, so composing\n`[Validators.required, Validators.email]` surfaces \"required\" while empty.",
     "file": "projects/mk-kit/core/forms/validation-messages.ts",
     "kind": "function",
     "signatures": [
      "(errors: ValidationErrors | null | undefined, strings: MkValidationStrings, overrides?: MkErrorMessages): string | null"
     ]
    },
    {
     "name": "mkGetFocusable",
     "description": "Returns the tabbable elements inside `root`, in DOM order.",
     "file": "projects/mk-kit/core/a11y/focus-trap.ts",
     "kind": "function",
     "signatures": [
      "(root: HTMLElement): HTMLElement[]"
     ]
    },
    {
     "name": "mkHexAlpha",
     "description": "`#rrggbb` → `rgba(r,g,b,a)`.",
     "file": "projects/mk-kit/core/theme/accent.service.ts",
     "kind": "function",
     "signatures": [
      "(hex: string, alpha: number): string"
     ]
    },
    {
     "name": "mkHighlight",
     "description": "Highlight `src` for `language`, falling back to escaped plain text.",
     "file": "projects/core/src/highlight.ts",
     "kind": "function",
     "signatures": [
      "(src: string, language: string): string"
     ]
    },
    {
     "name": "mkHighlightJson",
     "description": "Highlight a JSON document. Recognises object keys, strings, numbers, the\n`true`/`false`/`null` literals and structural punctuation. Invalid JSON is\nstill highlighted token-by-token (the editor validates separately).",
     "file": "projects/core/src/highlight.ts",
     "kind": "function",
     "signatures": [
      "(src: string): string"
     ]
    },
    {
     "name": "mkIsQueryGroup",
     "description": "True for a group node (as opposed to a rule).",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(node: MkQueryNode): node is MkQueryGroup"
     ]
    },
    {
     "name": "mkIsResponsive",
     "description": "True when `value` is a per-breakpoint map rather than a plain value.",
     "file": "projects/mk-kit/core/layout/breakpoint.service.ts",
     "kind": "function",
     "signatures": [
      "<T>(value: MkResponsive<T>): value is Partial<Record<MkBreakpoint, T>>"
     ]
    },
    {
     "name": "mkMergeI18n",
     "description": "Merges `overrides` over a complete string map — shallow for the top level,\ndeep for the `dateNames`, `blockEditor` and `validation` groups. Exported\nso locale packs and tests can build a map without providing it.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "function",
     "signatures": [
      "(base: MkI18nStrings, overrides: MkI18nOverrides): MkI18nStrings"
     ]
    },
    {
     "name": "mkQueryCompact",
     "description": "Drop empty groups and rules that still need a value, so the API gets only complete conditions.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(group: MkQueryGroup): MkQueryGroup"
     ]
    },
    {
     "name": "mkQueryIsEmpty",
     "description": "True when the tree holds no rule at all (empty groups only).",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(group: MkQueryGroup): boolean"
     ]
    },
    {
     "name": "mkQueryOperatorLabel",
     "description": "Localised label of an operator.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(op: MkQueryOperator, i18n?: MkQueryTextStrings): string"
     ]
    },
    {
     "name": "mkQueryOperatorsFor",
     "description": "Operators a field offers (its own list, else the defaults for its type).",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(field: MkQueryField | undefined): readonly MkQueryOperator[]"
     ]
    },
    {
     "name": "mkQueryRuleCount",
     "description": "Number of rules in the tree.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(group: MkQueryGroup): number"
     ]
    },
    {
     "name": "mkQueryRuleIsComplete",
     "description": "A rule is complete when its operator needs no value or has one.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(rule: MkQueryRule): boolean"
     ]
    },
    {
     "name": "mkQueryRuleMatches",
     "description": "Evaluate one rule against a row.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(rule: MkQueryRule, row: Record<string, unknown>, field?: MkQueryField): boolean"
     ]
    },
    {
     "name": "mkQueryToPredicate",
     "description": "Compile a query into a row predicate for client-side filtering\n(`rows.filter(mkQueryToPredicate(query, fields))`). Unfinished rules are\nignored, so a half-edited query never blanks the table.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "<T extends object = Record<string, unknown>>(group: MkQueryGroup, fields?: readonly MkQueryField[]): (row: T) => boolean"
     ]
    },
    {
     "name": "mkQueryToText",
     "description": "Human-readable sentence for a query, e.g.\n`(Name contains \"ada\" and Orders at least 10) or Status is any of Active, Invited`.",
     "file": "projects/core/src/query.ts",
     "kind": "function",
     "signatures": [
      "(group: MkQueryGroup, fields?: readonly MkQueryField[], i18n?: MkQueryTextStrings): string"
     ]
    },
    {
     "name": "mkSignalErrorMessage",
     "description": "Resolves the message for the first Signal Forms error on a field, the way\n`mkFirstErrorMessage` does for reactive forms.\n\nLookup order: the field's `overrides` for that kind, then the `message` the\nschema attached to the error (`required(p.email, { message: '…' })`), then\nthe i18n `validation` table, then the generic fallback.",
     "file": "projects/mk-kit/core/forms/signal-forms.ts",
     "kind": "function",
     "signatures": [
      "(errors: readonly MkSignalValidationError[] | null | undefined, strings: MkValidationStrings, overrides?: MkErrorMessages): string | null"
     ]
    },
    {
     "name": "mkSignalErrorsToValidationErrors",
     "description": "Converts Signal Forms errors to the reactive-forms `ValidationErrors` shape\nthe `validation` i18n table is keyed by, so both form systems render the\nsame messages. The built-in kinds map to Angular's classic keys and payloads\n(`minLength` → `minlength: { requiredLength }`, `minDate` → `mkMinDate`,\n…); any other kind is kept as-is with its payload spread into the value.",
     "file": "projects/mk-kit/core/forms/signal-forms.ts",
     "kind": "function",
     "signatures": [
      "(errors: readonly MkSignalValidationError[] | null | undefined): ValidationErrors | null"
     ]
    },
    {
     "name": "mkUniqueId",
     "description": "Generates a stable, unique DOM id for wiring `aria-*` relationships\n(labels, descriptions, controls). Prefer this over `Math.random()` so\nids are deterministic within a render and SSR-safe.",
     "file": "projects/core/src/id.ts",
     "kind": "function",
     "signatures": [
      "(prefix?: string): string"
     ]
    },
    {
     "name": "mkValidatorChange",
     "description": "Re-validates the bound form control whenever a validator's inputs change.\n\nA `Validator` whose constraints come from component inputs (`[min]`,\n`[max]`, `[required]`, …) must tell Angular when those inputs change,\notherwise the control keeps the verdict computed under the old constraints.\n`NgModel`/`FormControlName` pass a callback to `registerOnValidatorChange`\nfor exactly this; call it from an effect over the constraint signals.\n\nMust be called from an injection context (i.e. as a field initialiser).\n\n```ts\nprivate readonly validatorChange = mkValidatorChange(() => {\n  this.min();\n  this.max();\n});\n\nregisterOnValidatorChange(fn: () => void): void {\n  this.validatorChange.register(fn);\n}\n```",
     "file": "projects/mk-kit/core/forms/validator-change.ts",
     "kind": "function",
     "signatures": [
      "(deps: () => void): MkValidatorChangeRef"
     ]
    },
    {
     "name": "provideMkI18n",
     "description": "Provide localised strings — pass any subset, merged over `base` (the\nEnglish defaults unless given). The nested `dateNames`, `blockEditor` and\n`validation` groups are merged deeply, so partial overrides of those work\ntoo.\n\n```ts\nbootstrapApplication(App, {\n  providers: [provideMkI18n({ noResults: 'Brak wyników', close: 'Zamknij' })],\n});\n```\n\nA locale pack is a complete map that serves as the base — either through\nits own helper (`provideMkI18nPl(overrides)` from `@mk-kit/ui/locales/pl`)\nor explicitly: `provideMkI18n(overrides, MK_PL_I18N)`.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "function",
     "signatures": [
      "(overrides: MkI18nOverrides, base?: MkI18nStrings): Provider"
     ],
     "docs": "/core-services"
    },
    {
     "name": "MK_BREAKPOINTS",
     "description": "Override the breakpoint scale app-wide: `{ provide: MK_BREAKPOINTS, useValue: { …, lg: 1100 } }`.",
     "file": "projects/mk-kit/core/layout/breakpoint.service.ts",
     "kind": "token",
     "type": "InjectionToken<MkBreakpoints>"
    },
    {
     "name": "MK_I18N",
     "description": "The active string map. Defaults to `MK_DEFAULT_I18N`; override with\n`provideMkI18n`. Inject it (`inject(MK_I18N)`) wherever a built-in\nstring is rendered.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "token",
     "type": "InjectionToken<MkI18nStrings>"
    },
    {
     "name": "MK_OVERLAY_DATA",
     "description": "Injection token exposing the data passed to an overlay component.",
     "file": "projects/mk-kit/core/overlay/overlay-ref.ts",
     "kind": "token",
     "type": "InjectionToken<unknown>"
    },
    {
     "name": "MK_OVERLAY_ROOT",
     "description": "Where mk-kit mounts everything that leaves the component tree: overlay\ncontainers (dialogs), anchored panels (selects, menus, tooltips), toast /\nsnackbar containers and the tour surfaces. Defaults to `document.body`.\n\nOverride it to confine those surfaces to another element — `@mk-kit/ui/embed`\npoints it at a themed shadow-DOM host so overlays opened by embedded custom\nelements stay isolated from the host page's stylesheet:\n\n```ts\n{ provide: MK_OVERLAY_ROOT, useValue: () => myOverlayHost }\n```",
     "file": "projects/mk-kit/core/overlay/overlay-root.ts",
     "kind": "token",
     "type": "InjectionToken<MkOverlayRootFn>"
    },
    {
     "name": "MK_ACCENT_ORDER",
     "description": "Picker order.",
     "file": "projects/mk-kit/core/theme/accent.service.ts",
     "kind": "const",
     "type": "readonly MkAccentKey[]"
    },
    {
     "name": "MK_ACCENTS",
     "description": "High-saturation, distinct, energising accents — the set the `momentum` preset was designed around.",
     "file": "projects/mk-kit/core/theme/accent.service.ts",
     "kind": "const",
     "type": "Record<MkAccentKey, MkAccent>"
    },
    {
     "name": "MK_DEFAULT_BREAKPOINTS",
     "description": "The default scale (same numbers as Tailwind, so mental models transfer).",
     "file": "projects/mk-kit/core/layout/breakpoint.service.ts",
     "kind": "const",
     "type": "MkBreakpoints"
    },
    {
     "name": "MK_DEFAULT_DATE_NAMES",
     "description": "The built-in English date names.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "const",
     "type": "MkDateNames"
    },
    {
     "name": "MK_DEFAULT_I18N",
     "description": "The built-in English strings.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "const",
     "type": "MkI18nStrings"
    },
    {
     "name": "MK_DEFAULT_VALIDATION",
     "description": "The built-in English validation messages.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "const",
     "type": "MkValidationStrings"
    },
    {
     "name": "MK_QUERY_OPERATORS",
     "description": "Operators offered per field type, in menu order.",
     "file": "projects/core/src/query.ts",
     "kind": "const",
     "type": "Readonly<Record<MkQueryValueType, readonly MkQueryOperator[]>>"
    },
    {
     "name": "MK_QUERY_TEXT_EN",
     "description": "English defaults for `MkQueryTextStrings`.",
     "file": "projects/core/src/query.ts",
     "kind": "const",
     "type": "MkQueryTextStrings"
    },
    {
     "name": "MK_QUERY_UNARY",
     "description": "Operators that take no value.",
     "file": "projects/core/src/query.ts",
     "kind": "const",
     "type": "ReadonlySet<MkQueryOperator>"
    },
    {
     "name": "MkAccent",
     "description": "`fill` = bars, rings and buttons · `ink` = small accent text on a light ground.",
     "file": "projects/mk-kit/core/theme/accent.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "fill",
       "type": "string",
       "description": ""
      },
      {
       "name": "ink",
       "type": "string",
       "description": ""
      },
      {
       "name": "name",
       "type": "string",
       "description": ""
      }
     ]
    },
    {
     "name": "MkAnchoredPosition",
     "description": "Resolved coordinates (viewport-relative, for `position: fixed`).",
     "file": "projects/core/src/anchor.ts",
     "kind": "interface",
     "members": [
      {
       "name": "top",
       "type": "number",
       "description": ""
      },
      {
       "name": "left",
       "type": "number",
       "description": ""
      },
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": "The placement actually used after any flip."
      }
     ]
    },
    {
     "name": "MkAnchoredPositionOptions",
     "description": "Options controlling `mkComputeAnchoredPosition`.",
     "file": "projects/core/src/anchor.ts",
     "kind": "interface",
     "members": [
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": ""
      },
      {
       "name": "gap",
       "type": "number",
       "description": ""
      },
      {
       "name": "flip",
       "type": "boolean",
       "description": ""
      },
      {
       "name": "clamp",
       "type": "boolean",
       "description": ""
      },
      {
       "name": "rtl",
       "type": "boolean | undefined",
       "description": "Resolve `-start`/`-end` alignment against a right-to-left anchor.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkBlockEditorStrings",
     "description": "Strings used by the block editor's chrome.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "interface",
     "members": [
      {
       "name": "addBlock",
       "type": "string",
       "description": ""
      },
      {
       "name": "addFirstBlock",
       "type": "string",
       "description": ""
      },
      {
       "name": "insertBlockHere",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockInserter",
       "type": "string",
       "description": ""
      },
      {
       "name": "searchBlocks",
       "type": "string",
       "description": ""
      },
      {
       "name": "blocks",
       "type": "string",
       "description": ""
      },
      {
       "name": "moveBlockUp",
       "type": "string",
       "description": ""
      },
      {
       "name": "moveBlockDown",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockOptions",
       "type": "string",
       "description": ""
      },
      {
       "name": "duplicate",
       "type": "string",
       "description": ""
      },
      {
       "name": "remove",
       "type": "string",
       "description": ""
      },
      {
       "name": "textFormatting",
       "type": "string",
       "description": ""
      },
      {
       "name": "altText",
       "type": "string",
       "description": ""
      },
      {
       "name": "caption",
       "type": "string",
       "description": ""
      },
      {
       "name": "alignment",
       "type": "string",
       "description": ""
      },
      {
       "name": "replaceImage",
       "type": "string",
       "description": ""
      },
      {
       "name": "imageUrl",
       "type": "string",
       "description": ""
      },
      {
       "name": "externalContent",
       "type": "string",
       "description": ""
      },
      {
       "name": "embedUrl",
       "type": "string",
       "description": ""
      },
      {
       "name": "columnSettings",
       "type": "string",
       "description": ""
      },
      {
       "name": "columns",
       "type": "string",
       "description": ""
      },
      {
       "name": "ratio",
       "type": "string",
       "description": ""
      },
      {
       "name": "gap",
       "type": "string",
       "description": ""
      },
      {
       "name": "align",
       "type": "string",
       "description": ""
      },
      {
       "name": "justify",
       "type": "string",
       "description": ""
      },
      {
       "name": "headingLevel",
       "type": "(level: number) => string",
       "description": ""
      },
      {
       "name": "editorLabel",
       "type": "string",
       "description": "Editor region label + empty-block placeholder defaults."
      },
      {
       "name": "emptyBlockPlaceholder",
       "type": "string",
       "description": ""
      },
      {
       "name": "dragHandle",
       "type": "string",
       "description": "Drag handle tooltip."
      },
      {
       "name": "turnInto",
       "type": "(label: string) => string",
       "description": "\"Turn into …\" transform menu item; receives the target block's label."
      },
      {
       "name": "unknownBlock",
       "type": "(type: string) => string",
       "description": "Shown for a block whose type has no registered definition."
      },
      {
       "name": "blockAdded",
       "type": "(label: string) => string",
       "description": "Structural-change screen-reader announcements."
      },
      {
       "name": "blockDuplicated",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockDeleted",
       "type": "(label: string) => string",
       "description": ""
      },
      {
       "name": "blockMovedUp",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockMovedDown",
       "type": "string",
       "description": ""
      },
      {
       "name": "turnedInto",
       "type": "(label: string) => string",
       "description": ""
      },
      {
       "name": "noBlocksMatch",
       "type": "(query: string) => string",
       "description": "Inserter empty state; receives the search query."
      },
      {
       "name": "groupText",
       "type": "string",
       "description": "Built-in palette group headings."
      },
      {
       "name": "groupMedia",
       "type": "string",
       "description": ""
      },
      {
       "name": "groupLayout",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockParagraph",
       "type": "string",
       "description": "Built-in block labels + inserter descriptions."
      },
      {
       "name": "blockParagraphDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockHeading",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockHeadingDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockList",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockListDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockQuote",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockQuoteDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockCode",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockCodeDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockImage",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockImageDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockEmbed",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockEmbedDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockButton",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockButtonDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockDivider",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockDividerDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockColumns",
       "type": "string",
       "description": ""
      },
      {
       "name": "blockColumnsDesc",
       "type": "string",
       "description": ""
      },
      {
       "name": "bold",
       "type": "string",
       "description": "Rich-text inline toolbar."
      },
      {
       "name": "italic",
       "type": "string",
       "description": ""
      },
      {
       "name": "underline",
       "type": "string",
       "description": ""
      },
      {
       "name": "strikethrough",
       "type": "string",
       "description": ""
      },
      {
       "name": "inlineCode",
       "type": "string",
       "description": ""
      },
      {
       "name": "link",
       "type": "string",
       "description": ""
      },
      {
       "name": "clearFormatting",
       "type": "string",
       "description": ""
      },
      {
       "name": "linkUrlPrompt",
       "type": "string",
       "description": "Prompt asking for a link URL."
      },
      {
       "name": "editableText",
       "type": "string",
       "description": "Default label of the editable rich-text region."
      },
      {
       "name": "headingPlaceholder",
       "type": "(level: number) => string",
       "description": "Heading block."
      },
      {
       "name": "headingLevelGroup",
       "type": "string",
       "description": ""
      },
      {
       "name": "listStyle",
       "type": "string",
       "description": "List block."
      },
      {
       "name": "bulleted",
       "type": "string",
       "description": ""
      },
      {
       "name": "numbered",
       "type": "string",
       "description": ""
      },
      {
       "name": "listItem",
       "type": "string",
       "description": ""
      },
      {
       "name": "quoteText",
       "type": "string",
       "description": "Quote block."
      },
      {
       "name": "citation",
       "type": "string",
       "description": ""
      },
      {
       "name": "addCitation",
       "type": "string",
       "description": ""
      },
      {
       "name": "codeLanguage",
       "type": "string",
       "description": "Code block."
      },
      {
       "name": "codeLanguagePlaceholder",
       "type": "string",
       "description": ""
      },
      {
       "name": "enterCode",
       "type": "string",
       "description": ""
      },
      {
       "name": "imageWidth",
       "type": "(percent: number) => string",
       "description": "Image block."
      },
      {
       "name": "uploading",
       "type": "string",
       "description": ""
      },
      {
       "name": "dropImagePrompt",
       "type": "string",
       "description": ""
      },
      {
       "name": "chooseFile",
       "type": "string",
       "description": ""
      },
      {
       "name": "pasteImageUrl",
       "type": "string",
       "description": ""
      },
      {
       "name": "notAnImage",
       "type": "string",
       "description": ""
      },
      {
       "name": "uploadFailed",
       "type": "string",
       "description": ""
      },
      {
       "name": "imageAdded",
       "type": "string",
       "description": ""
      },
      {
       "name": "pasteEmbedUrl",
       "type": "string",
       "description": "Embed block."
      },
      {
       "name": "embedFallbackNote",
       "type": "string",
       "description": ""
      },
      {
       "name": "embedTitle",
       "type": "(provider: string) => string",
       "description": ""
      },
      {
       "name": "embedAdded",
       "type": "(provider: string) => string",
       "description": ""
      },
      {
       "name": "embeddedContent",
       "type": "string",
       "description": ""
      },
      {
       "name": "buttonLabel",
       "type": "string",
       "description": "Button block settings."
      },
      {
       "name": "buttonLink",
       "type": "string",
       "description": ""
      },
      {
       "name": "buttonTone",
       "type": "string",
       "description": ""
      },
      {
       "name": "buttonVariant",
       "type": "string",
       "description": ""
      },
      {
       "name": "buttonDefaultLabel",
       "type": "string",
       "description": "Label a freshly inserted Button block starts with."
      },
      {
       "name": "alignLeft",
       "type": "string",
       "description": "Alignment option captions (image + button blocks)."
      },
      {
       "name": "alignCenter",
       "type": "string",
       "description": ""
      },
      {
       "name": "alignRight",
       "type": "string",
       "description": ""
      },
      {
       "name": "tonePrimary",
       "type": "string",
       "description": "Tone option captions (button block swatches)."
      },
      {
       "name": "toneNeutral",
       "type": "string",
       "description": ""
      },
      {
       "name": "toneSuccess",
       "type": "string",
       "description": ""
      },
      {
       "name": "toneWarning",
       "type": "string",
       "description": ""
      },
      {
       "name": "toneDanger",
       "type": "string",
       "description": ""
      },
      {
       "name": "toneInfo",
       "type": "string",
       "description": ""
      },
      {
       "name": "variantSolid",
       "type": "string",
       "description": "Variant option captions (button block)."
      },
      {
       "name": "variantSoft",
       "type": "string",
       "description": ""
      },
      {
       "name": "variantOutline",
       "type": "string",
       "description": ""
      },
      {
       "name": "ratioEqual",
       "type": "string",
       "description": "Columns settings option captions."
      },
      {
       "name": "alignStretch",
       "type": "string",
       "description": ""
      },
      {
       "name": "alignTop",
       "type": "string",
       "description": ""
      },
      {
       "name": "alignMiddle",
       "type": "string",
       "description": ""
      },
      {
       "name": "alignBottom",
       "type": "string",
       "description": ""
      },
      {
       "name": "justifyStart",
       "type": "string",
       "description": ""
      },
      {
       "name": "justifyCenter",
       "type": "string",
       "description": ""
      },
      {
       "name": "justifyEnd",
       "type": "string",
       "description": ""
      },
      {
       "name": "justifyBetween",
       "type": "string",
       "description": ""
      }
     ]
    },
    {
     "name": "MkDateNames",
     "description": "Localised month and weekday name tables (the shape `MK_I18N` carries).",
     "file": "projects/core/src/dates.ts",
     "kind": "interface",
     "members": [
      {
       "name": "months",
       "type": "readonly string[]",
       "description": "Full month names, January-first (12)."
      },
      {
       "name": "monthsShort",
       "type": "readonly string[]",
       "description": "Abbreviated month names (12)."
      },
      {
       "name": "weekdays",
       "type": "readonly string[]",
       "description": "Full weekday names, Sunday-first (7)."
      },
      {
       "name": "weekdaysShort",
       "type": "readonly string[]",
       "description": "Abbreviated weekday names (7)."
      },
      {
       "name": "weekdaysNarrow",
       "type": "readonly string[]",
       "description": "One/two-letter weekday names for calendar headers (7)."
      }
     ]
    },
    {
     "name": "MkI18nStrings",
     "description": "All user-facing strings the library renders itself (aria-labels, empty-state\ntext, control captions and screen-reader announcements). Consumers localise\nthe library by overriding any subset via `provideMkI18n`. Interpolated\nstrings are functions so translators control word order.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "interface",
     "members": [
      {
       "name": "locale",
       "type": "string | undefined",
       "description": "BCP 47 locale tag (`'pl-PL'`, `'de'`) used by the formatting pipes\n(`mkCurrency`, `mkRelativeTime`, `mkFileSize`, `mkPluralize`) and any\nother `Intl`-based formatting that has no explicit locale of its own.\nUnset → the runtime (browser / Node) default locale.",
       "optional": true
      },
      {
       "name": "currency",
       "type": "string | undefined",
       "description": "ISO 4217 currency code the `mkCurrency` pipe falls back to when the\ntemplate passes none. Unset → `'USD'`.",
       "optional": true
      },
      {
       "name": "validation",
       "type": "MkValidationStrings",
       "description": "Validation messages (deep-merged by provideMkI18n)."
      },
      {
       "name": "close",
       "type": "string",
       "description": "Generic \"Close\" control (dialog, drawer, bottom-sheet)."
      },
      {
       "name": "dismiss",
       "type": "string",
       "description": "Generic \"Dismiss\" control (alert, banner, toast, snackbar)."
      },
      {
       "name": "clear",
       "type": "string",
       "description": "Clear-input control (autocomplete, pickers, tag inputs)."
      },
      {
       "name": "confirm",
       "type": "string",
       "description": "Generic confirm action (confirm dialog, popconfirm)."
      },
      {
       "name": "cancel",
       "type": "string",
       "description": "Generic cancel action (dialogs, inline edit)."
      },
      {
       "name": "ok",
       "type": "string",
       "description": "Generic acknowledge action (alert/prompt dialogs)."
      },
      {
       "name": "save",
       "type": "string",
       "description": "Generic save action (inline edit)."
      },
      {
       "name": "submit",
       "type": "string",
       "description": "Default action-button caption (submit input)."
      },
      {
       "name": "edit",
       "type": "string",
       "description": "Generic edit affordance (inline edit trigger)."
      },
      {
       "name": "remove",
       "type": "string",
       "description": "Generic remove control (chip)."
      },
      {
       "name": "removeItem",
       "type": "(name: string) => string",
       "description": "Remove a named item (tag input chips, file upload rows)."
      },
      {
       "name": "empty",
       "type": "string",
       "description": "Placeholder shown for an empty editable value (inline edit, mini date)."
      },
      {
       "name": "optional",
       "type": "string",
       "description": "\"Optional\" marker (stepper)."
      },
      {
       "name": "filter",
       "type": "string",
       "description": "Filter/search field placeholder (transfer list)."
      },
      {
       "name": "confirmMessage",
       "type": "string",
       "description": "Default confirmation question (popconfirm)."
      },
      {
       "name": "decrease",
       "type": "string",
       "description": "Decrease control (number input)."
      },
      {
       "name": "increase",
       "type": "string",
       "description": "Increase control (number input)."
      },
      {
       "name": "loading",
       "type": "string",
       "description": "Async loading row (autocomplete, multi-select)."
      },
      {
       "name": "noOptions",
       "type": "string",
       "description": "Empty listbox with no options (select, time picker)."
      },
      {
       "name": "noResults",
       "type": "string",
       "description": "Empty async/filtered results (autocomplete, multi-select, command palette)."
      },
      {
       "name": "noData",
       "type": "string",
       "description": "Empty data table / list."
      },
      {
       "name": "translationEditorSearch",
       "type": "string",
       "description": "Translation editor (`@mk-kit/ui/translate/editor`)."
      },
      {
       "name": "translationEditorAll",
       "type": "string",
       "description": ""
      },
      {
       "name": "translationEditorOverridden",
       "type": "string",
       "description": ""
      },
      {
       "name": "translationEditorMissing",
       "type": "string",
       "description": ""
      },
      {
       "name": "translationEditorKey",
       "type": "string",
       "description": ""
      },
      {
       "name": "translationEditorReset",
       "type": "string",
       "description": ""
      },
      {
       "name": "translationEditorExport",
       "type": "string",
       "description": ""
      },
      {
       "name": "translationEditorKeys",
       "type": "string",
       "description": ""
      },
      {
       "name": "sessionExpiryTitle",
       "type": "string",
       "description": "Session-expiry dialog (`@mk-kit/ui/attention`)."
      },
      {
       "name": "sessionExpiryExtend",
       "type": "string",
       "description": ""
      },
      {
       "name": "sessionExpiryExtending",
       "type": "string",
       "description": ""
      },
      {
       "name": "sessionExpiryLogout",
       "type": "string",
       "description": ""
      },
      {
       "name": "sessionExpiryBody",
       "type": "(countdown: string) => string",
       "description": ""
      },
      {
       "name": "scannerTitle",
       "type": "string",
       "description": "Barcode scanner (`@mk-kit/ui/media/scanner`)."
      },
      {
       "name": "scannerHint",
       "type": "string",
       "description": ""
      },
      {
       "name": "scannerCameraError",
       "type": "string",
       "description": ""
      },
      {
       "name": "resultsCount",
       "type": "(count: number) => string",
       "description": "Announced when a filterable list updates (autocomplete, multi-select, command palette)."
      },
      {
       "name": "previousPage",
       "type": "string",
       "description": "Pagination: previous page control."
      },
      {
       "name": "nextPage",
       "type": "string",
       "description": "Pagination: next page control."
      },
      {
       "name": "goToPage",
       "type": "(page: number) => string",
       "description": "Pagination: jump to a page."
      },
      {
       "name": "paginationLabel",
       "type": "string",
       "description": "Pagination landmark label."
      },
      {
       "name": "previousSlide",
       "type": "string",
       "description": "Carousel: previous slide control."
      },
      {
       "name": "nextSlide",
       "type": "string",
       "description": "Carousel: next slide control."
      },
      {
       "name": "goToSlide",
       "type": "(slide: number) => string",
       "description": "Carousel: jump to a slide."
      },
      {
       "name": "carouselLabel",
       "type": "string",
       "description": "Carousel region label."
      },
      {
       "name": "pauseSlideshow",
       "type": "string",
       "description": "Carousel: pause / resume automatic rotation."
      },
      {
       "name": "playSlideshow",
       "type": "string",
       "description": ""
      },
      {
       "name": "slideOf",
       "type": "(slide: number, total: number) => string",
       "description": "Carousel: slide position (slide labels + live announcements)."
      },
      {
       "name": "dateNames",
       "type": "MkDateNames",
       "description": "Localised month/weekday name tables (deep-merged by provideMkI18n)."
      },
      {
       "name": "previousMonth",
       "type": "string",
       "description": "Calendar: previous month control."
      },
      {
       "name": "nextMonth",
       "type": "string",
       "description": "Calendar: next month control."
      },
      {
       "name": "previousYear",
       "type": "string",
       "description": "Month picker: previous/next year (month mode)."
      },
      {
       "name": "nextYear",
       "type": "string",
       "description": ""
      },
      {
       "name": "previousYears",
       "type": "string",
       "description": "Month picker: previous/next decade page (year mode)."
      },
      {
       "name": "nextYears",
       "type": "string",
       "description": ""
      },
      {
       "name": "selectDate",
       "type": "string",
       "description": "Field placeholders."
      },
      {
       "name": "selectRange",
       "type": "string",
       "description": ""
      },
      {
       "name": "selectTime",
       "type": "string",
       "description": ""
      },
      {
       "name": "selectMonth",
       "type": "string",
       "description": ""
      },
      {
       "name": "selectYear",
       "type": "string",
       "description": ""
      },
      {
       "name": "selectWeek",
       "type": "string",
       "description": ""
      },
      {
       "name": "selectPlaceholder",
       "type": "string",
       "description": ""
      },
      {
       "name": "chooseDate",
       "type": "string",
       "description": "Popover dialog labels."
      },
      {
       "name": "chooseDateRange",
       "type": "string",
       "description": ""
      },
      {
       "name": "chooseMonth",
       "type": "string",
       "description": ""
      },
      {
       "name": "chooseYear",
       "type": "string",
       "description": ""
      },
      {
       "name": "chooseWeek",
       "type": "string",
       "description": ""
      },
      {
       "name": "openCalendar",
       "type": "string",
       "description": ""
      },
      {
       "name": "openTimeList",
       "type": "string",
       "description": ""
      },
      {
       "name": "moreActions",
       "type": "string",
       "description": "Accessible name of the chevron segment of `mk-split-button`."
      },
      {
       "name": "selectDateTime",
       "type": "string",
       "description": "Placeholder of `mk-datetime-picker`."
      },
      {
       "name": "chooseDateTime",
       "type": "string",
       "description": "Dialog label of the `mk-datetime-picker` panel."
      },
      {
       "name": "chooseTime",
       "type": "string",
       "description": "Listbox label of the time list inside `mk-datetime-picker`."
      },
      {
       "name": "openDateTimePicker",
       "type": "string",
       "description": "Toggle-button label of `mk-datetime-picker`."
      },
      {
       "name": "daySegment",
       "type": "string",
       "description": "Mini-date segment names."
      },
      {
       "name": "monthSegment",
       "type": "string",
       "description": ""
      },
      {
       "name": "yearSegment",
       "type": "string",
       "description": ""
      },
      {
       "name": "countdownDays",
       "type": "string",
       "description": "Countdown unit captions."
      },
      {
       "name": "countdownHours",
       "type": "string",
       "description": ""
      },
      {
       "name": "countdownMinutes",
       "type": "string",
       "description": ""
      },
      {
       "name": "countdownSeconds",
       "type": "string",
       "description": ""
      },
      {
       "name": "countdownFinished",
       "type": "string",
       "description": "Announced when a countdown reaches zero."
      },
      {
       "name": "dayEvents",
       "type": "(count: number, titles: string) => string",
       "description": "Event-calendar day label suffix, e.g. `2 events: Standup, Demo`."
      },
      {
       "name": "moreEvents",
       "type": "(count: number) => string",
       "description": "Event-calendar overflow pill for events beyond `maxPerDay`, e.g. `+2 more`."
      },
      {
       "name": "selectAllRows",
       "type": "string",
       "description": "Select-all header checkbox."
      },
      {
       "name": "selectRow",
       "type": "(row: string) => string",
       "description": "Per-row checkbox; receives the row's leading cell text."
      },
      {
       "name": "expandHeader",
       "type": "string",
       "description": "Hidden expander column header."
      },
      {
       "name": "expandRow",
       "type": "string",
       "description": "Row expander toggle labels."
      },
      {
       "name": "collapseRow",
       "type": "string",
       "description": ""
      },
      {
       "name": "expandTreeRow",
       "type": "string",
       "description": "Tree-row toggle labels (`childrenKey`)."
      },
      {
       "name": "collapseTreeRow",
       "type": "string",
       "description": ""
      },
      {
       "name": "expandGroup",
       "type": "string",
       "description": "aria-label of a group header's toggle when the group is collapsed."
      },
      {
       "name": "collapseGroup",
       "type": "string",
       "description": "aria-label of a group header's toggle when the group is expanded."
      },
      {
       "name": "groupCount",
       "type": "(count: number) => string",
       "description": "Row count shown on a group header, e.g. \"4 items\"."
      },
      {
       "name": "resizeColumn",
       "type": "string",
       "description": "Column resize separator label."
      },
      {
       "name": "columnWidth",
       "type": "(column: string, width: number) => string",
       "description": "Announced while a column is resized by keyboard."
      },
      {
       "name": "columnMoved",
       "type": "(column: string, position: number, total: number) => string",
       "description": "Announced when a column is reordered."
      },
      {
       "name": "editCell",
       "type": "string",
       "description": "Hint suffix + announcement for editable cells."
      },
      {
       "name": "cellSaved",
       "type": "(value: string) => string",
       "description": ""
      },
      {
       "name": "sortedBy",
       "type": "(column: string, direction: MkSortAnnounceDirection) => string",
       "description": "Announced when a column is sorted."
      },
      {
       "name": "sortingCleared",
       "type": "(column: string) => string",
       "description": "Announced when sorting is removed from a column."
      },
      {
       "name": "showPassword",
       "type": "string",
       "description": "Password reveal toggle."
      },
      {
       "name": "hidePassword",
       "type": "string",
       "description": ""
      },
      {
       "name": "passwordRuleMinLength",
       "type": "(length: number) => string",
       "description": "Password rule captions."
      },
      {
       "name": "passwordRuleUppercase",
       "type": "string",
       "description": ""
      },
      {
       "name": "passwordRuleNumber",
       "type": "string",
       "description": ""
      },
      {
       "name": "passwordRuleSymbol",
       "type": "string",
       "description": ""
      },
      {
       "name": "passwordStrength",
       "type": "(score: number) => string",
       "description": "Password strength label for a 0–4 score."
      },
      {
       "name": "passwordStrengthLabel",
       "type": "string",
       "description": "Visible prefix before the strength label."
      },
      {
       "name": "ruleMet",
       "type": "string",
       "description": "Rule-state prefixes announced to screen readers."
      },
      {
       "name": "ruleNotMet",
       "type": "string",
       "description": ""
      },
      {
       "name": "oneTimeCode",
       "type": "string",
       "description": "OTP field labels."
      },
      {
       "name": "otpDigit",
       "type": "(position: number) => string",
       "description": ""
      },
      {
       "name": "numericKeypadLabel",
       "type": "string",
       "description": "Numeric keypad labels + masked-PIN progress announcement."
      },
      {
       "name": "keypadClear",
       "type": "string",
       "description": ""
      },
      {
       "name": "keypadBackspace",
       "type": "string",
       "description": ""
      },
      {
       "name": "keypadDigitsEntered",
       "type": "(count: number, length: number) => string",
       "description": ""
      },
      {
       "name": "onScreenKeyboardLabel",
       "type": "string",
       "description": "On-screen keyboard label + action-key labels."
      },
      {
       "name": "keyboardShift",
       "type": "string",
       "description": ""
      },
      {
       "name": "keyboardSpace",
       "type": "string",
       "description": ""
      },
      {
       "name": "keyboardEnter",
       "type": "string",
       "description": ""
      },
      {
       "name": "keyboardAltLayer",
       "type": "string",
       "description": ""
      },
      {
       "name": "keyboardBaseLayer",
       "type": "string",
       "description": ""
      },
      {
       "name": "ratingLabel",
       "type": "string",
       "description": "Rating slider label + value text."
      },
      {
       "name": "ratingValueText",
       "type": "(value: number, max: number) => string",
       "description": ""
      },
      {
       "name": "minimum",
       "type": "string",
       "description": "Range slider thumb labels."
      },
      {
       "name": "maximum",
       "type": "string",
       "description": ""
      },
      {
       "name": "chooseColor",
       "type": "string",
       "description": "Color picker labels."
      },
      {
       "name": "hexValue",
       "type": "string",
       "description": ""
      },
      {
       "name": "presetColors",
       "type": "string",
       "description": ""
      },
      {
       "name": "chooseCountry",
       "type": "string",
       "description": "Phone input: country-prefix trigger label."
      },
      {
       "name": "searchCountries",
       "type": "string",
       "description": "Phone input: search field placeholder inside the country list."
      },
      {
       "name": "phoneNumber",
       "type": "string",
       "description": "Phone input: default accessible label of the national-number field."
      },
      {
       "name": "postalCode",
       "type": "string",
       "description": "Postal-code input: default accessible label."
      },
      {
       "name": "amount",
       "type": "string",
       "description": "Currency input: default accessible label."
      },
      {
       "name": "cardNumber",
       "type": "string",
       "description": "Card-number input: default accessible label."
      },
      {
       "name": "cardBrand",
       "type": "(brand: string) => string",
       "description": "Card-number input: announced/badge text for a detected brand."
      },
      {
       "name": "iban",
       "type": "string",
       "description": "IBAN input: default accessible label."
      },
      {
       "name": "taxId",
       "type": "string",
       "description": "Tax-ID input: default accessible label."
      },
      {
       "name": "signature",
       "type": "string",
       "description": "Signature pad: default accessible label of the drawing surface."
      },
      {
       "name": "jsonLabel",
       "type": "string",
       "description": "JSON viewer: default accessible label of the tree."
      },
      {
       "name": "logViewerLabel",
       "type": "string",
       "description": "Log viewer: default accessible label of the log region."
      },
      {
       "name": "logFollow",
       "type": "string",
       "description": "Log viewer: re-attach-to-tail button."
      },
      {
       "name": "logCopyAll",
       "type": "string",
       "description": "Log viewer: copy-the-whole-buffer toolbar button."
      },
      {
       "name": "logWrapLines",
       "type": "string",
       "description": "Log viewer: soft-wrap toolbar toggle."
      },
      {
       "name": "orgChartLabel",
       "type": "string",
       "description": "Org chart: default accessible label of the tree."
      },
      {
       "name": "orgChartExpand",
       "type": "string",
       "description": "Org chart: aria-label of a collapsed node's toggle (`{label}` = node label)."
      },
      {
       "name": "orgChartCollapse",
       "type": "string",
       "description": "Org chart: aria-label of an expanded node's toggle (`{label}` = node label)."
      },
      {
       "name": "chatLabel",
       "type": "string",
       "description": "Chat: accessible name of the message log."
      },
      {
       "name": "chatComposerLabel",
       "type": "string",
       "description": "Chat: accessible name of the composer textarea."
      },
      {
       "name": "chatPlaceholder",
       "type": "string",
       "description": "Chat: composer placeholder."
      },
      {
       "name": "chatSend",
       "type": "string",
       "description": "Chat: send button."
      },
      {
       "name": "chatStop",
       "type": "string",
       "description": "Chat: stop-generating button (replaces send while busy)."
      },
      {
       "name": "chatAttach",
       "type": "string",
       "description": "Chat: attach-files button."
      },
      {
       "name": "chatRemoveAttachment",
       "type": "string",
       "description": "Chat: remove one pending attachment."
      },
      {
       "name": "chatAttachments",
       "type": "string",
       "description": "Chat: group label of pending / shown attachments."
      },
      {
       "name": "chatSuggestions",
       "type": "string",
       "description": "Chat: group label of quick-reply suggestions."
      },
      {
       "name": "chatCopy",
       "type": "string",
       "description": "Chat: copy-message button."
      },
      {
       "name": "chatRetry",
       "type": "string",
       "description": "Chat: retry a failed message."
      },
      {
       "name": "chatTyping",
       "type": "string",
       "description": "Chat: typing indicator."
      },
      {
       "name": "chatStreaming",
       "type": "string",
       "description": "Chat: screen-reader text while a reply streams in."
      },
      {
       "name": "chatJumpToLatest",
       "type": "string",
       "description": "Chat: scroll-to-newest button."
      },
      {
       "name": "chatEmpty",
       "type": "string",
       "description": "Chat: empty-state text."
      },
      {
       "name": "chatYou",
       "type": "string",
       "description": "Chat: author fallback for the user's own messages."
      },
      {
       "name": "chatAssistant",
       "type": "string",
       "description": "Chat: author fallback for assistant messages."
      },
      {
       "name": "chatToolRunning",
       "type": "string",
       "description": "Chat: tool call in progress."
      },
      {
       "name": "chatToolDone",
       "type": "string",
       "description": "Chat: tool call finished."
      },
      {
       "name": "chatToolError",
       "type": "string",
       "description": "Chat: tool call failed."
      },
      {
       "name": "dynamicFormAdd",
       "type": "string",
       "description": "Dynamic form: add an item to an array field."
      },
      {
       "name": "dynamicFormRemove",
       "type": "(index: number) => string",
       "description": "Dynamic form: remove one item of an array field (index is 1-based)."
      },
      {
       "name": "queryBuilderLabel",
       "type": "string",
       "description": "Query builder: accessible name of the whole builder."
      },
      {
       "name": "queryAddRule",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryAddGroup",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryRemoveRule",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryRemoveGroup",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryAnd",
       "type": "string",
       "description": "Combinator labels — also used by `mkQueryToText`."
      },
      {
       "name": "queryOr",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryNot",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryField",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOperator",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryValue",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryValueFrom",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryValueTo",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryEmptyGroup",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryTrue",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryFalse",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpEq",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNeq",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpContains",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNotContains",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpStartsWith",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpEndsWith",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpGt",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpGte",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpLt",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpLte",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpBetween",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpIn",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNotIn",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpBefore",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpAfter",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpEmpty",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNotEmpty",
       "type": "string",
       "description": ""
      },
      {
       "name": "dialogMove",
       "type": "string",
       "description": "Dialog: label of the move grip (arrow keys move, Home resets)."
      },
      {
       "name": "dialogResize",
       "type": "string",
       "description": "Dialog: label of the resize grip (arrow keys resize, Home resets)."
      },
      {
       "name": "listboxFilter",
       "type": "string",
       "description": "Listbox: filter box placeholder / label."
      },
      {
       "name": "listboxEmpty",
       "type": "string",
       "description": "Listbox: shown when the filter matches nothing."
      },
      {
       "name": "eventCalendarGrabbed",
       "type": "(title: string, from: string, to: string) => string",
       "description": "Announced when an event is picked up in keyboard move mode."
      },
      {
       "name": "eventCalendarPosition",
       "type": "(title: string, day: string, from: string, to: string) => string",
       "description": "Announced after each keyboard step: current day + time range."
      },
      {
       "name": "eventCalendarMoved",
       "type": "(title: string, day: string, from: string, to: string) => string",
       "description": "Announced when a move commits."
      },
      {
       "name": "eventCalendarResized",
       "type": "(title: string, to: string) => string",
       "description": "Announced when a resize commits."
      },
      {
       "name": "eventCalendarEditCancelled",
       "type": "string",
       "description": "Announced when an edit is aborted."
      },
      {
       "name": "eventCalendarMovableEvent",
       "type": "string",
       "description": "`aria-roledescription` of an editable event pill."
      },
      {
       "name": "previousImage",
       "type": "string",
       "description": "Lightbox / gallery: previous-image control."
      },
      {
       "name": "nextImage",
       "type": "string",
       "description": "Lightbox / gallery: next-image control."
      },
      {
       "name": "imageOf",
       "type": "(index: number, total: number) => string",
       "description": "Lightbox counter + per-image aria label, e.g. `Image 2 of 8`."
      },
      {
       "name": "viewImage",
       "type": "(alt: string) => string",
       "description": "Gallery tile label; receives the image's alt text."
      },
      {
       "name": "imageFailed",
       "type": "string",
       "description": "Shown in an image block whose source failed to load."
      },
      {
       "name": "zoom",
       "type": "string",
       "description": "Cropper zoom controls."
      },
      {
       "name": "zoomIn",
       "type": "string",
       "description": ""
      },
      {
       "name": "zoomOut",
       "type": "string",
       "description": ""
      },
      {
       "name": "mediaLibrary",
       "type": "string",
       "description": "Media gallery region label."
      },
      {
       "name": "dropzoneLabel",
       "type": "string",
       "description": "File upload dropzone + states."
      },
      {
       "name": "uploadFailed",
       "type": "string",
       "description": ""
      },
      {
       "name": "retryUpload",
       "type": "string",
       "description": ""
      },
      {
       "name": "errorSummaryTitle",
       "type": "string",
       "description": "Form error summary heading."
      },
      {
       "name": "available",
       "type": "string",
       "description": "Default column titles."
      },
      {
       "name": "selected",
       "type": "string",
       "description": ""
      },
      {
       "name": "transferSelected",
       "type": "(target: string) => string",
       "description": "Move-button labels; receive the target list's title."
      },
      {
       "name": "transferAll",
       "type": "(target: string) => string",
       "description": ""
      },
      {
       "name": "itemsMoved",
       "type": "(count: number, target: string) => string",
       "description": "Announced after a move."
      },
      {
       "name": "notificationsTitle",
       "type": "string",
       "description": ""
      },
      {
       "name": "allCaughtUp",
       "type": "string",
       "description": ""
      },
      {
       "name": "markAllRead",
       "type": "string",
       "description": ""
      },
      {
       "name": "notificationsUnread",
       "type": "(count: number) => string",
       "description": ""
      },
      {
       "name": "unread",
       "type": "string",
       "description": "Unread state announced per row."
      },
      {
       "name": "tourStepOf",
       "type": "(step: number, total: number) => string",
       "description": ""
      },
      {
       "name": "tourSkip",
       "type": "string",
       "description": ""
      },
      {
       "name": "tourPrevious",
       "type": "string",
       "description": ""
      },
      {
       "name": "tourNext",
       "type": "string",
       "description": ""
      },
      {
       "name": "tourDone",
       "type": "string",
       "description": ""
      },
      {
       "name": "commandPalettePlaceholder",
       "type": "string",
       "description": "Command palette input placeholder."
      },
      {
       "name": "commandPaletteLabel",
       "type": "string",
       "description": "Command palette dialog label."
      },
      {
       "name": "stepCompleted",
       "type": "string",
       "description": "Stepper: step state, appended to the step's accessible name."
      },
      {
       "name": "stepError",
       "type": "string",
       "description": ""
      },
      {
       "name": "diffAddedLine",
       "type": "string",
       "description": "Diff: screen-reader prefix for changed lines."
      },
      {
       "name": "diffRemovedLine",
       "type": "string",
       "description": ""
      },
      {
       "name": "itemAdded",
       "type": "(name: string) => string",
       "description": "Chip collections (tag input, multi-select): announced on add/remove."
      },
      {
       "name": "itemRemoved",
       "type": "(name: string) => string",
       "description": ""
      },
      {
       "name": "resizePanes",
       "type": "string",
       "description": "Splitter separator label."
      },
      {
       "name": "backToTop",
       "type": "string",
       "description": "Back-to-top button label."
      },
      {
       "name": "breadcrumbLabel",
       "type": "string",
       "description": "Breadcrumb nav landmark label."
      },
      {
       "name": "fabLabel",
       "type": "string",
       "description": "FAB default label."
      },
      {
       "name": "appSwitcherLabel",
       "type": "string",
       "description": "App switcher: trigger / panel label, and the note when the registry cannot be fetched."
      },
      {
       "name": "appSwitcherError",
       "type": "string",
       "description": ""
      },
      {
       "name": "diffBefore",
       "type": "string",
       "description": "Diff view labels."
      },
      {
       "name": "diffAfter",
       "type": "string",
       "description": ""
      },
      {
       "name": "diffChanges",
       "type": "string",
       "description": ""
      },
      {
       "name": "skipToContent",
       "type": "string",
       "description": "App shell."
      },
      {
       "name": "primaryNav",
       "type": "string",
       "description": ""
      },
      {
       "name": "dndPickedUp",
       "type": "(position: number, total: number) => string",
       "description": "Announced when an item is lifted for keyboard dragging."
      },
      {
       "name": "dndMoved",
       "type": "(position: number, total: number) => string",
       "description": "Announced as the item moves within its list."
      },
      {
       "name": "dndMovedToList",
       "type": "(list: string, position: number, total: number) => string",
       "description": "Announced as the item moves into another list."
      },
      {
       "name": "dndDropped",
       "type": "(position: number) => string",
       "description": "Announced when the item is dropped."
      },
      {
       "name": "dndMovedToZone",
       "type": "(zone: string) => string",
       "description": "Announced as a lifted item reaches a drop zone (a target that is not a list)."
      },
      {
       "name": "dndDroppedInZone",
       "type": "(zone: string) => string",
       "description": "Announced when the item is dropped on a zone."
      },
      {
       "name": "dndCancelled",
       "type": "string",
       "description": "Announced when the drag is cancelled."
      },
      {
       "name": "repeaterAddRow",
       "type": "string",
       "description": "Repeater add-row button caption (default when no `addLabel` is given)."
      },
      {
       "name": "repeaterRemoveRow",
       "type": "(index: number) => string",
       "description": "Repeater per-row remove button label (1-based row number)."
      },
      {
       "name": "repeaterReorderRow",
       "type": "(index: number) => string",
       "description": "Repeater per-row drag-handle label (1-based row number)."
      },
      {
       "name": "repeaterRowMoved",
       "type": "(from: number, to: number) => string",
       "description": "Announced after a repeater row is reordered (1-based positions)."
      },
      {
       "name": "fileRejectedType",
       "type": "(name: string) => string",
       "description": ""
      },
      {
       "name": "fileRejectedSize",
       "type": "(name: string, limit: string) => string",
       "description": ""
      },
      {
       "name": "fileRejectedCount",
       "type": "(name: string, max: number) => string",
       "description": ""
      },
      {
       "name": "chartCategory",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartValue",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartSeries",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartSlice",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartStage",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartConversion",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartAxis",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartShare",
       "type": "string",
       "description": ""
      },
      {
       "name": "chartLabel",
       "type": "string",
       "description": ""
      },
      {
       "name": "qrCodeLabel",
       "type": "(text: string) => string",
       "description": "Default accessible label of a QR code, carrying its encoded content."
      },
      {
       "name": "sortableListLabel",
       "type": "string",
       "description": "Default accessible name of `mk-sortable-list` when no `label` is given."
      },
      {
       "name": "filterColumn",
       "type": "(column: string) => string",
       "description": "Table filter row: accessible name of a column's filter control."
      },
      {
       "name": "clearFilter",
       "type": "(column: string) => string",
       "description": "Table filter row: the per-control clear (×) button."
      },
      {
       "name": "filterAny",
       "type": "string",
       "description": "Table filter row: the \"no filter\" option of a select filter."
      },
      {
       "name": "filterMin",
       "type": "string",
       "description": "Table filter row: placeholder of a number / date filter (matches values ≥ the entry)."
      },
      {
       "name": "blockEditor",
       "type": "MkBlockEditorStrings",
       "description": "Block editor chrome (deep-merged by provideMkI18n)."
      }
     ]
    },
    {
     "name": "MkOverlayConfig",
     "description": "",
     "file": "projects/mk-kit/core/overlay/overlay.service.ts",
     "kind": "interface",
     "typeParams": "<TData = unknown>",
     "members": [
      {
       "name": "data",
       "type": "TData | undefined",
       "description": "Arbitrary data injected via `MK_OVERLAY_DATA`.",
       "optional": true
      },
      {
       "name": "hasBackdrop",
       "type": "boolean | undefined",
       "description": "Render a dimmed scrim behind the panel. Default `true`.",
       "optional": true
      },
      {
       "name": "closeOnBackdropClick",
       "type": "boolean | undefined",
       "description": "Close when the backdrop is clicked. Default `true`.",
       "optional": true
      },
      {
       "name": "closeOnEscape",
       "type": "boolean | undefined",
       "description": "Close when Escape is pressed. Default `true`.",
       "optional": true
      },
      {
       "name": "trapFocus",
       "type": "boolean | undefined",
       "description": "Trap focus within the panel and restore it on close. Default `true`.",
       "optional": true
      },
      {
       "name": "autoFocus",
       "type": "boolean | undefined",
       "description": "Move focus to the panel's first focusable element on open. Default `true`.\nSet `false` to focus the panel itself instead — for content-led surfaces\n(a product sheet, a preview) where focusing the close button first reads\nas \"dismiss me\". Tab containment and focus restore are unaffected; turn\n`trapFocus` off only if you want neither.",
       "optional": true
      },
      {
       "name": "panelClass",
       "type": "string | string[] | undefined",
       "description": "Extra class(es) applied to the panel host element.",
       "optional": true
      },
      {
       "name": "role",
       "type": "\"dialog\" | \"alertdialog\" | \"menu\" | \"listbox\" | undefined",
       "description": "Accessible role for the panel. Default `dialog`.",
       "optional": true
      },
      {
       "name": "ariaLabel",
       "type": "string | undefined",
       "description": "`aria-label` for the panel when no visible title is wired up.",
       "optional": true
      },
      {
       "name": "injector",
       "type": "Injector | undefined",
       "description": "A custom injector to use as the parent for the rendered component.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkQueryField",
     "description": "A field the user can filter on.",
     "file": "projects/core/src/query.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": "Property key on the row objects / the API's filter name."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Label shown in the field picker."
      },
      {
       "name": "type",
       "type": "MkQueryValueType | undefined",
       "description": "Default `string`.",
       "optional": true
      },
      {
       "name": "options",
       "type": "readonly MkQueryFieldOption[] | undefined",
       "description": "Choices for `select` fields.",
       "optional": true
      },
      {
       "name": "operators",
       "type": "readonly MkQueryOperator[] | undefined",
       "description": "Restrict / reorder the operators offered (default: all for the type).",
       "optional": true
      },
      {
       "name": "placeholder",
       "type": "string | undefined",
       "description": "Placeholder of the value editor.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkQueryFieldOption",
     "description": "A choice for `select` fields.",
     "file": "projects/core/src/query.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": ""
      },
      {
       "name": "value",
       "type": "unknown",
       "description": ""
      }
     ]
    },
    {
     "name": "MkQueryGroup",
     "description": "A group of rules and nested groups joined by one combinator, optionally negated.",
     "file": "projects/core/src/query.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": ""
      },
      {
       "name": "combinator",
       "type": "MkQueryCombinator",
       "description": ""
      },
      {
       "name": "not",
       "type": "boolean | undefined",
       "description": "Negate the whole group.",
       "optional": true
      },
      {
       "name": "rules",
       "type": "MkQueryNode[]",
       "description": ""
      }
     ]
    },
    {
     "name": "MkQueryRule",
     "description": "A leaf condition. `value` is `[from, to]` for `between`, an array for `in` / `notIn`, absent for `empty` / `notEmpty`. Dates are ISO strings.",
     "file": "projects/core/src/query.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": ""
      },
      {
       "name": "field",
       "type": "string",
       "description": ""
      },
      {
       "name": "operator",
       "type": "MkQueryOperator",
       "description": ""
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkQueryTextStrings",
     "description": "The strings `mkQueryToText` and `mkQueryOperatorLabel` render\nwith. A structural subset of mk-kit's `MkI18nStrings`, so the UI's full\ni18n map can be passed directly; defaults to `MK_QUERY_TEXT_EN`.",
     "file": "projects/core/src/query.ts",
     "kind": "interface",
     "members": [
      {
       "name": "queryTrue",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryFalse",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryAnd",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOr",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryNot",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpEq",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNeq",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpContains",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNotContains",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpStartsWith",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpEndsWith",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpGt",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpGte",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpLt",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpLte",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpBetween",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpIn",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNotIn",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpBefore",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpAfter",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpEmpty",
       "type": "string",
       "description": ""
      },
      {
       "name": "queryOpNotEmpty",
       "type": "string",
       "description": ""
      }
     ]
    },
    {
     "name": "MkSignalValidationError",
     "description": "The shape of a Signal Forms validation error as `mk-kit` reads it — the\n`{ kind, message? }` contract of `ValidationError` from\n`@angular/forms/signals`, plus whatever payload the error class carries\n(`min`, `maxLength`, `pattern`, …). Declared structurally so `@mk-kit/ui/core`\nstays free of a runtime dependency on the signals entry point.",
     "file": "projects/mk-kit/core/forms/signal-forms.ts",
     "kind": "interface",
     "members": [
      {
       "name": "kind",
       "type": "string",
       "description": "Identifies the kind of error (`'required'`, `'minLength'`, …).",
       "readonly": true
      },
      {
       "name": "message",
       "type": "string | undefined",
       "description": "Human-readable message, when the schema supplied one.",
       "optional": true,
       "readonly": true
      }
     ]
    },
    {
     "name": "MkValidationStrings",
     "description": "Messages rendered by `mk-form-field` for the validation errors the library's\nown controls produce, plus the standard Angular `Validators` keys, so a\nfield wrapping any control shows something sensible without per-form wiring.\n\nKeys match the `ValidationErrors` keys exactly and each entry receives that\nkey's error payload. Override any subset through\n`provideMkI18n({ validation: … })`, or a whole map per field via\n`mk-form-field`'s `errorMessages` input.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "interface",
     "members": [
      {
       "name": "required",
       "type": "string",
       "description": "`Validators.required` — also emitted by checkbox and radio-group."
      },
      {
       "name": "email",
       "type": "string",
       "description": "`Validators.email`."
      },
      {
       "name": "min",
       "type": "(err: { min: number; actual: number; }) => string",
       "description": "`Validators.min`, and the numeric controls' `[min]`."
      },
      {
       "name": "max",
       "type": "(err: { max: number; actual: number; }) => string",
       "description": "`Validators.max`, and the numeric controls' `[max]`."
      },
      {
       "name": "minlength",
       "type": "(err: { requiredLength: number; actualLength: number; }) => string",
       "description": "`Validators.minLength` — also emitted by password-input and OTP."
      },
      {
       "name": "maxlength",
       "type": "(err: { requiredLength: number; actualLength: number; }) => string",
       "description": "`Validators.maxLength`."
      },
      {
       "name": "pattern",
       "type": "string",
       "description": "`Validators.pattern`."
      },
      {
       "name": "mkMinDate",
       "type": "(err: { min: Date; actual: Date; }) => string",
       "description": "A date/month/week picker's `[min]`."
      },
      {
       "name": "mkMaxDate",
       "type": "(err: { max: Date; actual: Date; }) => string",
       "description": "A date/month/week picker's `[max]`."
      },
      {
       "name": "mkDateFilter",
       "type": "string",
       "description": "A date rejected by a calendar's `[disabledDate]` predicate."
      },
      {
       "name": "mkDateRangeIncomplete",
       "type": "string",
       "description": "A range picker with only one end filled in."
      },
      {
       "name": "mkMinTime",
       "type": "(err: { min: string; actual: string; }) => string",
       "description": "The time-picker's `[min]`."
      },
      {
       "name": "mkMaxTime",
       "type": "(err: { max: string; actual: string; }) => string",
       "description": "The time-picker's `[max]`."
      },
      {
       "name": "mkMaxItems",
       "type": "(err: { max: number; actual: number; }) => string",
       "description": "More items than a multi-select's, tag-input's or upload's `[max*]` allows."
      },
      {
       "name": "mkFileSize",
       "type": "(err: { max: number; maxLabel: string; name: string; }) => string",
       "description": "A file larger than a file-upload's `[maxSize]`."
      },
      {
       "name": "mkFileType",
       "type": "(err: { accept: string; name: string; }) => string",
       "description": "A file not matching a file-upload's `[accept]` filter."
      },
      {
       "name": "cardNumber",
       "type": "string",
       "description": "A card number failing the Luhn checksum."
      },
      {
       "name": "iban",
       "type": "(err: { country: string; expectedLength: number | null; }) => string",
       "description": "An IBAN failing the mod-97 checksum."
      },
      {
       "name": "postalCode",
       "type": "(err: { country: string; example: string; }) => string",
       "description": "A postal code not matching the country's format."
      },
      {
       "name": "taxId",
       "type": "(err: { country: string; label: string; example: string; }) => string",
       "description": "A tax identifier not matching the country's format or checksum."
      },
      {
       "name": "unknown",
       "type": "string",
       "description": "Fallback for an error key with no message of its own."
      }
     ]
    },
    {
     "name": "MkValidatorChangeRef",
     "description": "Handle returned by `mkValidatorChange`, wiring a component's\n`registerOnValidatorChange` callback to a set of reactive dependencies.",
     "file": "projects/mk-kit/core/forms/validator-change.ts",
     "kind": "interface",
     "members": [
      {
       "name": "register",
       "type": "(fn: () => void): void",
       "description": "Store the callback Angular hands to `registerOnValidatorChange`."
      },
      {
       "name": "notify",
       "type": "(): void",
       "description": "Ask the bound control to re-run `validate()` now."
      }
     ]
    },
    {
     "name": "MkAccentKey",
     "description": "One of the eight kit accents (the Momentum palette).",
     "file": "projects/mk-kit/core/theme/accent.service.ts",
     "kind": "type",
     "definition": "'indigo' | 'blue' | 'teal' | 'violet' | 'coral' | 'lime' | 'pink' | 'bumblebee'"
    },
    {
     "name": "MkAriaLivePoliteness",
     "description": "",
     "file": "projects/mk-kit/core/a11y/live-announcer.service.ts",
     "kind": "type",
     "definition": "'polite' | 'assertive'"
    },
    {
     "name": "MkBreakpoint",
     "description": "Named viewport ranges, mobile-first: each starts at its min-width.",
     "file": "projects/mk-kit/core/layout/breakpoint.service.ts",
     "kind": "type",
     "definition": "'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'"
    },
    {
     "name": "MkBreakpoints",
     "description": "Min-widths (px) at which each named breakpoint begins; `xs` is everything below `sm`.",
     "file": "projects/mk-kit/core/layout/breakpoint.service.ts",
     "kind": "type",
     "definition": "Record<Exclude<MkBreakpoint, 'xs'>, number>"
    },
    {
     "name": "MkCodeLanguage",
     "description": "Languages with built-in highlighting. Unknown values render plain text.",
     "file": "projects/core/src/highlight.ts",
     "kind": "type",
     "definition": "'json' | 'plaintext'"
    },
    {
     "name": "MkContrastPreference",
     "description": "Contrast preference.\n\n`high` applies the high-contrast token preset (`data-mk-contrast=\"high\"`):\npure text colours, line-like borders, opaque interaction washes, a thicker\nfocus ring. `system` (the default) writes no attribute and lets the\nstylesheet follow the OS `prefers-contrast: more` setting; `normal` opts\nout of that even when the OS asks for more contrast.",
     "file": "projects/mk-kit/core/theme/theme.service.ts",
     "kind": "type",
     "definition": "'normal' | 'high' | 'system'"
    },
    {
     "name": "MkDensity",
     "description": "Global control-density mode.\n\n`touch` sizes controls for fingers (48px default) rather than a cursor —\ntablets, kiosks, order screens. It is usually applied per-subtree with the\n`data-mk-density` attribute rather than globally, since one app often has\nboth a mouse-driven admin and a touch-driven screen.",
     "file": "projects/mk-kit/core/theme/theme.service.ts",
     "kind": "type",
     "definition": "'comfortable' | 'compact' | 'touch'"
    },
    {
     "name": "MkErrorMessages",
     "description": "A per-field override map: an error key mapped either to a fixed message or\nto a function receiving that key's error payload.\n\n```html\n<mk-form-field label=\"Age\" [errorMessages]=\"{ min: 'You must be 18 or over' }\">\n```",
     "file": "projects/mk-kit/core/forms/validation-messages.ts",
     "kind": "type",
     "definition": "Readonly<Record<string, string | ((err: any) => string)>>"
    },
    {
     "name": "MkI18nOverrides",
     "description": "Any subset of `MkI18nStrings`; the nested `dateNames`, `blockEditor`\nand `validation` groups may be partial too (they are merged deeply).",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "type",
     "definition": "Partial< Omit<MkI18nStrings, 'dateNames' | 'blockEditor' | 'validation'> > & { dateNames?: Partial<MkDateNames>; blockEditor?: Partial<MkBlockEditorStrings>; validation?: Partial<MkValidationStrings>; }"
    },
    {
     "name": "MkOverlayRootFn",
     "description": "Resolves the element overlay surfaces are appended to. A function (not an\nelement) because the root may be created lazily, after DI is set up.",
     "file": "projects/mk-kit/core/overlay/overlay-root.ts",
     "kind": "type",
     "definition": "() => HTMLElement"
    },
    {
     "name": "MkPlacement",
     "description": "Common placement values for anchored overlays (menus, tooltips, popovers).",
     "file": "projects/core/src/anchor.ts",
     "kind": "type",
     "definition": "| 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end'"
    },
    {
     "name": "MkQueryCombinator",
     "description": "",
     "file": "projects/core/src/query.ts",
     "kind": "type",
     "definition": "'and' | 'or'"
    },
    {
     "name": "MkQueryNode",
     "description": "",
     "file": "projects/core/src/query.ts",
     "kind": "type",
     "definition": "MkQueryRule | MkQueryGroup"
    },
    {
     "name": "MkQueryOperator",
     "description": "Comparison operators. Which apply depends on the field type.",
     "file": "projects/core/src/query.ts",
     "kind": "type",
     "definition": "| 'eq' | 'neq' | 'contains' | 'notContains' | 'startsWith' | 'endsWith' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'in' | 'notIn' | 'before' | 'after' | 'empty' | 'notEmpty'"
    },
    {
     "name": "MkQueryValueType",
     "description": "Value kind of a filterable field; decides the editor and the operators offered.",
     "file": "projects/core/src/query.ts",
     "kind": "type",
     "definition": "'string' | 'number' | 'boolean' | 'date' | 'select'"
    },
    {
     "name": "MkResolvedContrast",
     "description": "Concrete resolved contrast (never `system`).",
     "file": "projects/mk-kit/core/theme/theme.service.ts",
     "kind": "type",
     "definition": "'normal' | 'high'"
    },
    {
     "name": "MkResolvedTheme",
     "description": "Concrete resolved theme (never `system`).",
     "file": "projects/mk-kit/core/types.ts",
     "kind": "type",
     "definition": "'light' | 'dark'"
    },
    {
     "name": "MkResponsive",
     "description": "A value that may differ per breakpoint: either the plain value or a\nmobile-first map, `{ xs: 1, md: 2, xl: 4 }`, where each key applies from\nthat breakpoint up until the next key given.",
     "file": "projects/mk-kit/core/layout/breakpoint.service.ts",
     "kind": "type",
     "typeParams": "<T>",
     "definition": "T | Partial<Record<MkBreakpoint, T>>"
    },
    {
     "name": "MkSize",
     "description": "Control size scale. Maps to `--mk-control-height-*` tokens.",
     "file": "projects/mk-kit/core/types.ts",
     "kind": "type",
     "definition": "'sm' | 'md' | 'lg'"
    },
    {
     "name": "MkSortAnnounceDirection",
     "description": "Direction passed to the sort announcer.",
     "file": "projects/mk-kit/core/i18n/mk-i18n.ts",
     "kind": "type",
     "definition": "'asc' | 'desc'"
    },
    {
     "name": "MkThemePreference",
     "description": "Theme selection. `system` follows the OS `prefers-color-scheme`.",
     "file": "projects/mk-kit/core/types.ts",
     "kind": "type",
     "definition": "'light' | 'dark' | 'system'"
    },
    {
     "name": "MkTone",
     "description": "Semantic color tone. Each maps to a `--mk-<tone>*` token family.",
     "file": "projects/mk-kit/core/types.ts",
     "kind": "type",
     "definition": "| 'primary' | 'neutral' | 'success' | 'warning' | 'danger' | 'info'"
    },
    {
     "name": "MkVariant",
     "description": "Visual treatment for tinted/interactive surfaces.",
     "file": "projects/mk-kit/core/types.ts",
     "kind": "type",
     "definition": "'solid' | 'soft' | 'outline' | 'ghost' | 'link'"
    }
   ]
  },
  {
   "name": "core/signal-forms",
   "import": "@mk-kit/ui/core/signal-forms",
   "exports": [
    {
     "name": "mkInjectFieldTouched",
     "description": "Touched-gate for a control's `invalid` input under Signal Forms.\n\nWhen a control is bound with the `[formField]` directive, Angular writes the\nfield's `invalid()` state straight into the control's `invalid` input — from\nthe first render, before the user has reached the field. mk-kit controls\npass that input through this gate so the invalid visual (and `aria-invalid`)\nonly shows once the field is touched or dirty, matching how `mk-form-field`\nreveals its message and how `submit()` (which marks every field touched)\nsurfaces the remaining problems.\n\nReturns a signal that is always `true` for a control that is not bound with\n`[formField]`, so a standalone `[invalid]=\"true\"` keeps working as before.\nCall it in a field initializer (an injection context):\n\n```ts\nprivate readonly fieldTouched = mkInjectFieldTouched();\nprotected readonly isInvalid = computed(\n  () => (this.invalid() && this.fieldTouched()) || (this.field?.hasError() ?? false),\n);\n```\n\nThe binding is looked up lazily, on first read: the `FormField` directive\nitself injects the element's `NG_VALUE_ACCESSOR` (the control) while it is\ncreated, so resolving it from the control's constructor would be circular.",
     "file": "projects/mk-kit/core/signal-forms/signal-field.ts",
     "kind": "function",
     "signatures": [
      "(): Signal<boolean>"
     ]
    }
   ]
  },
  {
   "name": "icon",
   "import": "@mk-kit/ui/icon",
   "exports": [
    {
     "name": "MkIcon",
     "description": "Icon — renders a registered SVG by `name`, or your own projected `<svg>`.\nThe glyph inherits the current text colour (`currentColor`) and scales to the\n`size` box, so it composes cleanly inside buttons, inputs and menus.\n\nDecorative by default (`aria-hidden`); pass `label` to expose it as an image\nto assistive tech.\n\n```html\n<mk-icon name=\"search\" />\n<mk-icon name=\"trash\" size=\"lg\" label=\"Delete\" />\n<button mkButton iconOnly aria-label=\"Menu\"><mk-icon name=\"menu\" /></button>\n<mk-icon><svg viewBox=\"0 0 24 24\">…custom…</svg></mk-icon>\n```",
     "file": "projects/mk-kit/icon/icon.ts",
     "kind": "component",
     "selector": "mk-icon",
     "selectors": [
      "mk-icon"
     ],
     "inputs": [
      {
       "name": "name",
       "type": "string",
       "description": "Name of a registered icon (see `MkIconRegistry`).",
       "default": "''"
      },
      {
       "name": "size",
       "type": "number | MkSize",
       "description": "Size: `sm`/`md`/`lg`, or a pixel number for a custom dimension.",
       "default": "'md'"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible name. When set the icon becomes `role=\"img\"`; otherwise hidden.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/icon"
    },
    {
     "name": "MkIconRegistry",
     "description": "IconRegistry — the name → SVG store behind `<mk-icon name=\"…\">`. The\nhand-made `MK_DEFAULT_ICONS` are registered on construction and ship\nwith every app. Everything else is opt-in and tree-shakeable: the\nLucide-derived extended set via `provideMkExtendedIcons()` (from\n`@mk-kit/ui/icon/extended`), a themed subset or your own SVGs (from a\nsprite, a design export, anything) via `provideMkIcons()`, or at runtime\nwith `register` / `registerIcons` / `load`.\n\nSVG markup is trusted verbatim (bypassed through `DomSanitizer`), so only\nregister icons from sources you control — never user input.\n\n```ts\nconst reg = inject(MkIconRegistry);\nreg.register('logo', '<svg viewBox=\"0 0 24 24\">…</svg>');\nreg.registerIcons({ save: '<svg…>', share: '<svg…>' });\nreg.load(() => import('@mk-kit/ui/icon/extended').then((m) => m.MK_EXTENDED_ICONS_FILES));\n```",
     "file": "projects/mk-kit/icon/icon-registry.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "register",
       "signature": "(name: string, svg: string): this",
       "description": "Register (or overwrite) a single named icon from raw SVG markup."
      },
      {
       "name": "registerIcons",
       "signature": "(icons: MkIconMap): this",
       "description": "Register many icons at once from a `{ name: svg }` map — a whole set, a\nthemed subset (`MK_EXTENDED_ICONS_FILES`) or a hand-picked few. Later\nregistrations overwrite earlier ones on a shared name."
      },
      {
       "name": "registerAliases",
       "signature": "(aliases: Readonly<Record<string, string>>): this",
       "description": "Register alternative names that resolve to existing icons — e.g. map\nMaterial Symbols ligature names onto the built-in set\n(`{ delete: 'trash', expand_more: 'chevron-down' }`). A real icon\nregistered under an alias name always wins over the alias; an alias\nwhose target is not registered resolves to nothing (and, in dev mode,\nwarns once naming the missing target)."
      },
      {
       "name": "load",
       "signature": "(loader: MkIconLoader): Promise<void>",
       "description": "Load an icon map asynchronously and register it once it arrives. Icons\nalready on screen fill in when the map lands (see `changes`); the\nmissing-icon warning stays quiet while a load is pending. Server-side\nrendering waits for it (Angular's `PendingTasks`), so the HTML ships with\nthe icons in place.\n\n```ts\nregistry.load(() => import('@mk-kit/ui/icon/extended').then((m) => m.MK_EXTENDED_ICONS));\n```"
      },
      {
       "name": "get",
       "signature": "(name: string): SafeHtml | null",
       "description": "Sanitized SVG for a name (aliases resolved), or `null` when unknown."
      },
      {
       "name": "has",
       "signature": "(name: string): boolean",
       "description": "Whether an icon with this name (or alias) is registered."
      },
      {
       "name": "names",
       "signature": "(): string[]",
       "description": "All registered icon names (useful for a picker / catalogue)."
      },
      {
       "name": "warnMissing",
       "signature": "(name: string): void",
       "description": "Dev-mode only: warn once per unknown name with a hint about the opt-in\nextended set. Silent in production builds and while a `load` is\npending (the name may be on its way). Called by `<mk-icon>`."
      }
     ],
     "properties": [
      {
       "name": "changes",
       "type": "Signal<number>",
       "description": "Bumps on every registration. `<mk-icon>` reads it, so an icon that\narrives late (a lazy `load`, a runtime `register`) renders in\nplace without any re-binding.",
       "readonly": true
      },
      {
       "name": "pending",
       "type": "Signal<boolean>",
       "description": "Whether a lazy `load` is still in flight.",
       "readonly": true
      }
     ],
     "docs": "/components/icon"
    },
    {
     "name": "provideMkIcons",
     "description": "Registers extra icons at bootstrap — a themed subset of the extended set,\na hand-picked few, your own SVGs, or a lazily loaded map. Call it as many\ntimes as you like; each call adds to the `MkIconRegistry`. The\nhand-made defaults are always there; this is for everything else.\n\n```ts\nimport { provideMkIcons } from '@mk-kit/ui/icon';\nimport { MK_EXTENDED_ICONS_FILES, MK_EXTENDED_ICONS_DATA } from '@mk-kit/ui/icon/extended';\n\nbootstrapApplication(App, {\n  providers: [\n    // themed subsets — only these glyphs end up in the bundle\n    provideMkIcons(MK_EXTENDED_ICONS_FILES),\n    provideMkIcons(MK_EXTENDED_ICONS_DATA),\n    // your own\n    provideMkIcons({ logo: '<svg viewBox=\"0 0 24 24\">…</svg>' }),\n    // or the whole extended set in its own lazy chunk, off the critical path\n    provideMkIcons(() => import('@mk-kit/ui/icon/extended').then((m) => m.MK_EXTENDED_ICONS)),\n  ],\n});\n```\n\nA loader runs once at bootstrap without blocking it: icons already on\nscreen fill in when the chunk lands, and server-side rendering waits for\nit. Picking single names out of the full map\n(`{ receipt: MK_EXTENDED_ICONS['receipt'] }`) works but still bundles the\nwhole map — use a subset or copy the SVG when size matters.",
     "file": "projects/mk-kit/icon/provide-icons.ts",
     "kind": "function",
     "signatures": [
      "(icons: MkIconMap | MkIconLoader): EnvironmentProviders"
     ]
    },
    {
     "name": "provideMkMaterialIcons",
     "description": "Installs the Material Symbols name aliases into the `MkIconRegistry`,\nso `<mk-icon name=\"delete\" />`, `name=\"expand_more\"`, `name=\"visibility\"`\netc. resolve to the built-in set. Add it to your bootstrap providers when\nmigrating an app off `<mat-icon>` ligatures:\n\n```ts\nbootstrapApplication(App, {\n  providers: [provideMkMaterialIcons()],\n});\n```",
     "file": "projects/mk-kit/icon/material-aliases.ts",
     "kind": "function",
     "signatures": [
      "(): EnvironmentProviders"
     ]
    },
    {
     "name": "MK_DEFAULT_ICONS",
     "description": "Name → SVG markup map of the default icons (registered by `MkIconRegistry` on construction).",
     "file": "projects/mk-kit/icon/default-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_MATERIAL_ICON_ALIASES",
     "description": "Material Symbols ligature names → built-in mk icon names. Lets templates\nwritten against `<mat-icon>delete</mat-icon>` conventions keep their icon\nnames when migrating: `<mk-icon name=\"delete\" />` renders the `trash`\nglyph once `provideMkMaterialIcons` is installed.\n\nSeveral Material names intentionally collapse onto one mk glyph (all the\ncalendar variants → `calendar`, the delete variants → `trash`, …). Every\ntarget is a default icon, so the aliases work without the opt-in extended\nset. Names not listed here have no sensible built-in equivalent — register\nyour own SVG under the Material name via `MkIconRegistry.register`, or\nalias it onto an extended glyph with `registerAliases` once\n`provideMkExtendedIcons()` is installed (an alias whose target is missing\nrenders nothing and warns once in dev mode).",
     "file": "projects/mk-kit/icon/material-aliases.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MkIconLoader",
     "description": "Loads an icon map on demand — typically a dynamic import of the extended\nset: `() => import('@mk-kit/ui/icon/extended').then((m) => m.MK_EXTENDED_ICONS)`.",
     "file": "projects/mk-kit/icon/icon-registry.ts",
     "kind": "type",
     "definition": "() => Promise<MkIconMap>"
    },
    {
     "name": "MkIconMap",
     "description": "A `{ name: '<svg …>…</svg>' }` map — what every registration API accepts.",
     "file": "projects/mk-kit/icon/icon-registry.ts",
     "kind": "type",
     "definition": "Readonly<Record<string, string>>"
    }
   ]
  },
  {
   "name": "icon/extended",
   "import": "@mk-kit/ui/icon/extended",
   "exports": [
    {
     "name": "provideMkExtendedIcons",
     "description": "Registers the whole Lucide-derived extended set (`MK_EXTENDED_ICONS`)\nso every `<mk-icon name=\"…\">` in the catalogue resolves. Opt-in: without\nit only the hand-made defaults are available and an unknown name warns\nonce in dev mode.\n\n```ts\nimport { provideMkExtendedIcons } from '@mk-kit/ui/icon/extended';\n\nbootstrapApplication(App, {\n  providers: [provideMkExtendedIcons()],\n});\n```\n\nSize-conscious alternatives (see `provideMkIcons`): register only the\nthemed subsets you use (`provideMkIcons(MK_EXTENDED_ICONS_FILES)`), or load\nthe full set lazily in its own chunk:\n`provideMkIcons(() => import('@mk-kit/ui/icon/extended').then((m) => m.MK_EXTENDED_ICONS))`.\nThe hand-made defaults keep their names — the generated set never\noverlaps them.",
     "file": "projects/mk-kit/icon/extended/provide-extended-icons.ts",
     "kind": "function",
     "signatures": [
      "(): EnvironmentProviders"
     ]
    },
    {
     "name": "MK_EXTENDED_ICON_GROUPS",
     "description": "The themed subsets by group name — handy for a picker or for registering\nseveral groups at once: `provideMkIcons(MK_EXTENDED_ICON_GROUPS['files'])`.",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, Readonly<Record<string, string>>>>"
    },
    {
     "name": "MK_EXTENDED_ICONS",
     "description": "Every Lucide-derived icon (305 glyphs). Not registered by\ndefault — install it with `provideMkExtendedIcons()`, pass a themed subset\nto `provideMkIcons()`, or load it lazily:\n`provideMkIcons(() => import('@mk-kit/ui/icon/extended').then((m) => m.MK_EXTENDED_ICONS))`.",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_COMMERCE",
     "description": "`commerce` subset of `MK_EXTENDED_ICONS` (23 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_COMMUNICATION",
     "description": "`communication` subset of `MK_EXTENDED_ICONS` (15 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_DATA",
     "description": "`data` subset of `MK_EXTENDED_ICONS` (15 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_DEVELOPER",
     "description": "`developer` subset of `MK_EXTENDED_ICONS` (23 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_DEVICES",
     "description": "`devices` subset of `MK_EXTENDED_ICONS` (15 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_EDITING",
     "description": "`editing` subset of `MK_EXTENDED_ICONS` (34 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_FILES",
     "description": "`files` subset of `MK_EXTENDED_ICONS` (22 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_LAYOUT",
     "description": "`layout` subset of `MK_EXTENDED_ICONS` (17 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_LIFESTYLE",
     "description": "`lifestyle` subset of `MK_EXTENDED_ICONS` (40 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_MEDIA",
     "description": "`media` subset of `MK_EXTENDED_ICONS` (14 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_NAVIGATION",
     "description": "`navigation` subset of `MK_EXTENDED_ICONS` (34 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_PEOPLE",
     "description": "`people` subset of `MK_EXTENDED_ICONS` (11 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_SECURITY",
     "description": "`security` subset of `MK_EXTENDED_ICONS` (5 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_STATUS",
     "description": "`status` subset of `MK_EXTENDED_ICONS` (20 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_TIME",
     "description": "`time` subset of `MK_EXTENDED_ICONS` (8 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    },
    {
     "name": "MK_EXTENDED_ICONS_TRAVEL",
     "description": "`travel` subset of `MK_EXTENDED_ICONS` (9 icons).",
     "file": "projects/mk-kit/icon/extended/extended-icons.ts",
     "kind": "const",
     "type": "Readonly<Record<string, string>>"
    }
   ]
  },
  {
   "name": "chip",
   "import": "@mk-kit/ui/chip",
   "exports": [
    {
     "name": "MkChip",
     "description": "Chip — an interactive, optionally removable/selectable token. Use it for\nfilters, active selections or editable input tokens. For a purely decorative\nlabel use `MkTag` instead.\n\n```html\n<mk-chip removable (removed)=\"drop(item)\">{{ item.name }}</mk-chip>\n<mk-chip selectable [(selected)]=\"active\" tone=\"primary\">Filter</mk-chip>\n```",
     "file": "projects/mk-kit/chip/chip.ts",
     "kind": "component",
     "selector": "mk-chip",
     "selectors": [
      "mk-chip"
     ],
     "inputs": [
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'neutral'"
      },
      {
       "name": "variant",
       "type": "MkChipVariant",
       "description": "Visual treatment.",
       "default": "'soft'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "selectable",
       "type": "boolean",
       "description": "Make the chip toggle a selected state on click / Enter / Space.",
       "default": "false"
      },
      {
       "name": "removable",
       "type": "boolean",
       "description": "Show a trailing remove button and enable Delete/Backspace removal.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable all interaction.",
       "default": "false"
      },
      {
       "name": "removeLabel",
       "type": "string",
       "description": "Accessible label for the remove button.",
       "default": "this.i18n.remove"
      },
      {
       "name": "selected",
       "type": "boolean",
       "description": "Two-way selected state (only meaningful when `selectable`).",
       "model": true,
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "selectedChange",
       "type": "boolean",
       "description": "Emits when `selected` changes (two-way binding).",
       "model": true
      },
      {
       "name": "removed",
       "type": "void",
       "description": "Emitted when the chip is removed via the button or Delete/Backspace."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkChipVariant",
     "description": "Visual treatment for a `MkChip`.",
     "file": "projects/mk-kit/chip/chip.ts",
     "kind": "type",
     "definition": "'solid' | 'soft' | 'outline'"
    }
   ]
  },
  {
   "name": "checkbox",
   "import": "@mk-kit/ui/checkbox",
   "exports": [
    {
     "name": "MkCheckbox",
     "description": "Checkbox — a themed checkbox built on a visually-hidden native\n`input[type=checkbox]` (so keyboard + form semantics are native) with a\ncustom box. Supports an `indeterminate` state and projects its label.\n\nImplements `ControlValueAccessor` with a two-way `checked` model, so it works\nwith `[(ngModel)]`, reactive forms and `[(checked)]`.\n\n```html\n<mk-checkbox [(ngModel)]=\"accepted\">Accept terms</mk-checkbox>\n<mk-checkbox [(checked)]=\"all\" [indeterminate]=\"some()\" tone=\"success\">\n  Select all\n</mk-checkbox>\n```",
     "file": "projects/mk-kit/checkbox/checkbox.ts",
     "kind": "component",
     "selector": "mk-checkbox",
     "selectors": [
      "mk-checkbox"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "checked",
       "type": "boolean",
       "description": "Two-way checked state.",
       "model": true,
       "default": "false"
      },
      {
       "name": "indeterminate",
       "type": "boolean",
       "description": "Two-way indeterminate (\"mixed\") state; cleared when the user toggles.",
       "model": true,
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`).",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone for the checked box.",
       "default": "'primary'"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible label when no text content is projected.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "checkedChange",
       "type": "boolean",
       "description": "Emits when `checked` changes (two-way binding).",
       "model": true
      },
      {
       "name": "indeterminateChange",
       "type": "boolean",
       "description": "Emits when `indeterminate` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `required` for an unchecked box when `[required]` is set, so\n`required` on the element behaves like `Validators.requiredTrue`."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/toggles"
    }
   ]
  },
  {
   "name": "button",
   "import": "@mk-kit/ui/button",
   "exports": [
    {
     "name": "MkButton",
     "description": "Button — enhances a native `<button>` or `<a>` so semantics and keyboard\nbehaviour come for free. Fully themed via `--mk-*` tokens.\n\n```html\n<button mkButton tone=\"primary\">Save</button>\n<button mkButton variant=\"outline\" tone=\"danger\" [loading]=\"saving()\">Delete</button>\n<a mkButton variant=\"ghost\" href=\"/docs\">Docs</a>\n```",
     "file": "projects/mk-kit/button/button.ts",
     "kind": "component",
     "selector": "button[mkButton], a[mkButton]",
     "selectors": [
      "mkButton"
     ],
     "inputs": [
      {
       "name": "variant",
       "type": "MkVariant",
       "description": "Visual treatment.",
       "default": "'solid'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'primary'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size.",
       "default": "'md'"
      },
      {
       "name": "loading",
       "type": "boolean",
       "description": "Shows a spinner and blocks interaction without collapsing layout.",
       "default": "false"
      },
      {
       "name": "fullWidth",
       "type": "boolean",
       "description": "Stretch to fill the container width.",
       "default": "false"
      },
      {
       "name": "iconOnly",
       "type": "boolean",
       "description": "Square, icon-only button (ensure an `aria-label` is provided).",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the button (native `disabled` for `<button>`, aria for `<a>`).",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/buttons"
    }
   ]
  },
  {
   "name": "directives",
   "import": "@mk-kit/ui/directives",
   "exports": [
    {
     "name": "MkAutofocus",
     "description": "Focuses the host element once it renders. Handy for dialogs, drawers and\nnewly-revealed forms. Disable conditionally with `[mkAutofocus]=\"cond\"`.\n\n```html\n<input mkInput mkAutofocus />\n<input mkInput [mkAutofocus]=\"isEditing()\" [mkAutofocusDelay]=\"100\" />\n```",
     "file": "projects/mk-kit/directives/directives/autofocus.ts",
     "kind": "directive",
     "selector": "[mkAutofocus]",
     "selectors": [
      "mkAutofocus"
     ],
     "inputs": [
      {
       "name": "mkAutofocus",
       "type": "boolean",
       "description": "Whether to focus. Bare `mkAutofocus` = true.",
       "default": "true"
      },
      {
       "name": "mkAutofocusDelay",
       "type": "number",
       "description": "Delay before focusing, in ms (e.g. to wait out an entrance animation).",
       "default": "0"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkAutosize",
     "description": "Grows a `<textarea>` to fit its content, between `minRows` and `maxRows`\n(0 = unbounded). Resizes on input and when the bound value changes.\n\n```html\n<textarea mkInput mkAutosize [mkAutosizeMaxRows]=\"8\" [(ngModel)]=\"note\"></textarea>\n```",
     "file": "projects/mk-kit/directives/directives/autosize.ts",
     "kind": "directive",
     "selector": "textarea[mkAutosize]",
     "selectors": [
      "mkAutosize"
     ],
     "inputs": [
      {
       "name": "mkAutosizeMinRows",
       "type": "number",
       "description": "Minimum height in rows.",
       "default": "1"
      },
      {
       "name": "mkAutosizeMaxRows",
       "type": "number",
       "description": "Maximum height in rows before scrolling (0 = unbounded).",
       "default": "0"
      },
      {
       "name": "mkAutosizeValue",
       "type": "unknown",
       "description": "Bind the textarea's value so programmatic changes trigger a resize.",
       "default": "undefined"
      }
     ],
     "outputs": [],
     "methods": [
      {
       "name": "resize",
       "signature": "(): void",
       "description": "Recompute the textarea height from its content."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkCan",
     "description": "Structural directive that renders its template only while the app's\n`MkPermissionPolicy` grants the given permission. With a\nsignal-based policy the check is live — the view is created and destroyed\nas permissions change. When no policy is provided, everything is granted.\n\n```html\n<button *mkCan=\"'posts.delete'\" (click)=\"remove()\">Delete</button>\n\n<!-- With a fallback template, like *ngIf's else: -->\n<section *mkCan=\"'billing.view'; else locked\">…</section>\n<ng-template #locked><mk-empty-state title=\"No access\" /></ng-template>\n```",
     "file": "projects/mk-kit/directives/permissions/can.ts",
     "kind": "directive",
     "selector": "[mkCan]",
     "selectors": [
      "mkCan"
     ],
     "inputs": [
      {
       "name": "mkCan",
       "type": "string",
       "description": "The permission key to check, e.g. `'posts.delete'`.",
       "required": true
      },
      {
       "name": "mkCanElse",
       "type": "TemplateRef<unknown> | null",
       "description": "Template rendered while the permission is denied (`; else ref`).",
       "default": "null"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkCanDisable",
     "description": "Disables the host while the app's `MkPermissionPolicy` denies the\ngiven permission — the \"keep it visible but inert\" alternative to `*mkCan`\nfor buttons, inputs and menu items.\n\nWhile denied, the host gets `aria-disabled=\"true\"`, and — when the element\nsupports it (button, input, select, textarea, fieldset…) — its native\n`disabled` property is set too. Non-disableable elements (links, custom\nmenu items) get `aria-disabled` only; pair it with CSS / a click guard as\nneeded. The directive owns the disabled state: it also re-enables the host\nwhen the permission is granted. With a signal-based policy the state flips\nlive; with no policy provided, everything is granted.\n\n```html\n<button [mkCanDisable]=\"'posts.delete'\" (click)=\"remove()\">Delete</button>\n<a [mkCanDisable]=\"'billing.view'\" routerLink=\"/billing\">Billing</a>\n```",
     "file": "projects/mk-kit/directives/permissions/can-disable.ts",
     "kind": "directive",
     "selector": "[mkCanDisable]",
     "selectors": [
      "mkCanDisable"
     ],
     "inputs": [
      {
       "name": "mkCanDisable",
       "type": "string",
       "description": "The permission key to check, e.g. `'posts.delete'`.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkCannot",
     "description": "The negation of `MkCan`: renders its template only while the\npermission is **denied** — for upsell hints, \"ask an admin\" notes and the\nlike. With no policy provided everything is granted, so `*mkCannot`\nrenders nothing.\n\n```html\n<p *mkCannot=\"'reports.export'\">Exporting requires an admin role.</p>\n```",
     "file": "projects/mk-kit/directives/permissions/can.ts",
     "kind": "directive",
     "selector": "[mkCannot]",
     "selectors": [
      "mkCannot"
     ],
     "inputs": [
      {
       "name": "mkCannot",
       "type": "string",
       "description": "The permission key to check.",
       "required": true
      },
      {
       "name": "mkCannotElse",
       "type": "TemplateRef<unknown> | null",
       "description": "Template rendered while the permission is granted (`; else ref`).",
       "default": "null"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkClickOutside",
     "description": "Emits when a pointer press lands outside the host element — the building block\nfor dismissing menus, popovers and custom dropdowns. Listens on the document\nin the capture phase so it fires before the target handles the event.\n\n```html\n<div class=\"panel\" (mkClickOutside)=\"close()\">…</div>\n```",
     "file": "projects/mk-kit/directives/directives/click-outside.ts",
     "kind": "directive",
     "selector": "[mkClickOutside]",
     "selectors": [
      "mkClickOutside"
     ],
     "exportAs": "mkClickOutside",
     "inputs": [
      {
       "name": "mkClickOutsideEnabled",
       "type": "boolean",
       "description": "Disable the listener without removing the directive.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "mkClickOutside",
       "type": "PointerEvent",
       "description": "Emits the originating event when a pointerdown occurs outside the host."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkCopyToClipboard",
     "description": "Copies text to the clipboard when the host is clicked. Emits `(copied)` on\nsuccess and `(copyFailed)` on error, and exposes a transient `copied` signal\n(via `exportAs`) so a template can show a \"Copied!\" state without extra code.\n\n```html\n<button mkButton [mkCopyToClipboard]=\"token\" #c=\"mkCopyToClipboard\">\n  {{ c.justCopied() ? 'Copied!' : 'Copy' }}\n</button>\n```",
     "file": "projects/mk-kit/directives/directives/copy-to-clipboard.ts",
     "kind": "directive",
     "selector": "[mkCopyToClipboard]",
     "selectors": [
      "mkCopyToClipboard"
     ],
     "exportAs": "mkCopyToClipboard",
     "inputs": [
      {
       "name": "mkCopyToClipboard",
       "type": "string",
       "description": "The text to copy.",
       "required": true
      },
      {
       "name": "mkCopyFeedbackDuration",
       "type": "number",
       "description": "How long (ms) the `copied` signal stays true after a successful copy.",
       "default": "1500"
      }
     ],
     "outputs": [
      {
       "name": "copied",
       "type": "string",
       "description": "Emits the copied text on success."
      },
      {
       "name": "copyFailed",
       "type": "unknown",
       "description": "Emits the error on failure."
      }
     ],
     "methods": [
      {
       "name": "copy",
       "signature": "(): Promise<void>",
       "description": "Copy the text now. Bound to the host click, but callable directly too."
      }
     ],
     "properties": [
      {
       "name": "justCopied",
       "type": "Signal<boolean>",
       "description": "True for `feedbackDuration` ms after a successful copy.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkField",
     "description": "Field — applies the semantic mobile-keyboard and autofill attribute bundle\nfor a kind of field, so you never again ship an email input that iOS\ncapitalises or an address input the browser can't autofill.\n\nIt sets `type`, `inputmode`, `autocomplete`, `autocapitalize`, `autocorrect`,\n`spellcheck` and `enterkeyhint` (see `MK_FIELD_PRESETS`) and nothing\nelse — no styling, no value handling — so it composes with `mkInput`,\n`mk-form-field`, `[(ngModel)]` and reactive forms untouched.\n\n```html\n<input mkInput mkField=\"email\" formControlName=\"email\" />\n<input mkInput mkField=\"street\" formControlName=\"street\" />\n<input mkInput [mkField]=\"isCompany() ? 'organization' : 'name'\" />\n```\n\n## Precedence\n\nA **static** attribute you write on the element wins: the directive reads the\nseven attributes once at construction (before any host binding has run) and\nkeeps whatever was already there, filling in only what you left out. So\n`<input mkField=\"username\" type=\"password\" />` stays a password field but\nstill gets `autocomplete=\"username\"`, `autocapitalize=\"off\"`, …\n\nA **template binding** for the same attribute (`[attr.autocomplete]=\"…\"`)\ndoes *not* win — Angular applies directive host bindings after template\nbindings, so the preset overwrites it. Use a static attribute to override, or\ndrop `mkField` and set the bundle yourself.",
     "file": "projects/mk-kit/directives/directives/field.ts",
     "kind": "directive",
     "selector": "[mkField]",
     "selectors": [
      "mkField"
     ],
     "inputs": [
      {
       "name": "mkField",
       "type": "MkFieldKind",
       "description": "Which kind of field this is.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkHotkey",
     "description": "`[mkHotkey]` — declaratively bind a keyboard shortcut to a host element.\n\nWhen the combo fires, a `<button>` or `<a>` host is `click()`ed; any other\nhost emits `(mkHotkeyPressed)`. Registration is scoped to the element's\nlifetime (auto-unregistered on destroy) via `MkHotkeysService`.\n\n```html\n<button mkHotkey=\"mod+s\" (click)=\"save()\">Save</button>\n<div mkHotkey=\"?\" (mkHotkeyPressed)=\"showHelp()\">…</div>\n```",
     "file": "projects/mk-kit/directives/hotkeys/hotkey.directive.ts",
     "kind": "directive",
     "selector": "[mkHotkey]",
     "selectors": [
      "mkHotkey"
     ],
     "exportAs": "mkHotkey",
     "inputs": [
      {
       "name": "mkHotkey",
       "type": "string",
       "description": "The combo (or space-separated chord) to bind, e.g. `mod+k`, `g i`, `?`.",
       "required": true
      },
      {
       "name": "mkHotkeyAllowInInput",
       "type": "boolean",
       "description": "Fire even while an editable field is focused.",
       "default": "false"
      },
      {
       "name": "mkHotkeyPreventDefault",
       "type": "boolean",
       "description": "Call `preventDefault()` when the hotkey fires. Defaults to `true`.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "mkHotkeyPressed",
       "type": "KeyboardEvent",
       "description": "Emitted when the hotkey fires and the host is not a button/link."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkInfiniteScroll",
     "description": "InfiniteScroll — emits `(mkInfiniteScroll)` when the host scroll container is\nscrolled within `distance` px of its bottom, so a list can load its next\npage. Apply it to the scrollable element (`overflow: auto`). It fires once per\napproach and re-arms after you scroll back up past the threshold, so a single\ngesture never triggers repeated loads. Set `disabled` while a page is loading\nor once everything is loaded.\n\n```html\n<div class=\"feed\" mkInfiniteScroll [disabled]=\"loading() || done()\"\n     (mkInfiniteScroll)=\"loadMore()\">",
     "file": "projects/mk-kit/directives/directives/infinite-scroll.ts",
     "kind": "directive",
     "selector": "[mkInfiniteScroll]",
     "selectors": [
      "mkInfiniteScroll"
     ],
     "exportAs": "mkInfiniteScroll",
     "inputs": [
      {
       "name": "distance",
       "type": "number",
       "description": "Distance (px) from the bottom at which the output fires.",
       "default": "200"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Pause firing (e.g. while a page is loading or all items are loaded).",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "mkInfiniteScroll",
       "type": "void",
       "description": "Emitted when the host is scrolled near its bottom."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkIntersect",
     "description": "Intersect — a thin `IntersectionObserver` wrapper. Emits `(mkIntersect)` with\nthe host's visibility whenever it enters or leaves the viewport (or `root`),\nand exposes an `intersecting` signal via `exportAs`. Set `once` to fire a\nsingle time and disconnect — the primitive for reveal-on-scroll animations\nand lazy loading.\n\n```html\n<img [attr.src]=\"loaded() ? src : null\" mkIntersect once\n     (mkIntersect)=\"loaded.set(true)\" />\n\n<div mkIntersect #io=\"mkIntersect\" [class.in-view]=\"io.intersecting()\">…</div>\n```",
     "file": "projects/mk-kit/directives/directives/intersect.ts",
     "kind": "directive",
     "selector": "[mkIntersect]",
     "selectors": [
      "mkIntersect"
     ],
     "exportAs": "mkIntersect",
     "inputs": [
      {
       "name": "root",
       "type": "HTMLElement | null",
       "description": "Element used as the viewport for the check (defaults to the browser one).",
       "default": "null"
      },
      {
       "name": "rootMargin",
       "type": "string",
       "description": "Margin grown/shrunk around the root before computing intersection.",
       "default": "'0px'"
      },
      {
       "name": "threshold",
       "type": "number | number[]",
       "description": "Visibility ratio(s) at which the observer fires.",
       "default": "0"
      },
      {
       "name": "once",
       "type": "boolean",
       "description": "Emit the first time the host becomes visible, then disconnect.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "mkIntersect",
       "type": "boolean",
       "description": "Emits the host's `isIntersecting` state on every change."
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "intersecting",
       "type": "WritableSignal<boolean>",
       "description": "The current visibility, also readable via `exportAs`.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkMask",
     "description": "Mask — formats an `<input>` as the user types against a token pattern\n(phone, card, date, custom). Apply it to any text input; read the raw value\nvia `(unmaskedChange)` (or the exported `unmasked` getter) and the formatted\nvalue via `(maskedChange)`.\n\n```html\n<input mkInput mkMask=\"(000) 000-0000\" (unmaskedChange)=\"phone.set($event)\" />\n<input mkInput mkMask=\"0000 0000 0000 0000\" />\n```",
     "file": "projects/mk-kit/directives/directives/mask.ts",
     "kind": "directive",
     "selector": "[mkMask]",
     "selectors": [
      "mkMask"
     ],
     "exportAs": "mkMask",
     "inputs": [
      {
       "name": "mkMask",
       "type": "string",
       "description": "The mask pattern (token string).",
       "required": true
      },
      {
       "name": "mkMaskInputmode",
       "type": "string | null",
       "description": "Override the derived `inputmode` (`numeric` for digit-only masks).",
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "maskedChange",
       "type": "string",
       "description": "The formatted value, on every change."
      },
      {
       "name": "unmaskedChange",
       "type": "string",
       "description": "The raw value (token characters only), on every change."
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "value",
       "type": "string",
       "description": "The current formatted value.",
       "readonly": true
      },
      {
       "name": "unmasked",
       "type": "string",
       "description": "The current raw value (token characters only).",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkRipple",
     "description": "Ripple — a Material-style touch ripple that expands from the pointer on press.\nApply it to any pressable surface (button, list item, card). The directive\nmakes the host a positioned, clipping container and paints a short-lived wave;\nit respects `prefers-reduced-motion`.\n\n```html\n<button mkRipple>Save</button>\n<li mkRipple mkRippleColor=\"var(--mk-primary)\">Item</li>\n```",
     "file": "projects/mk-kit/directives/directives/ripple.ts",
     "kind": "directive",
     "selector": "[mkRipple]",
     "selectors": [
      "mkRipple"
     ],
     "inputs": [
      {
       "name": "mkRippleColor",
       "type": "string",
       "description": "Wave colour (any CSS colour). Defaults to the host's `currentColor`.",
       "default": "''"
      },
      {
       "name": "mkRippleCentered",
       "type": "boolean",
       "description": "Start every ripple from the centre instead of the pointer.",
       "default": "false"
      },
      {
       "name": "mkRippleDisabled",
       "type": "boolean",
       "description": "Turn the effect off.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkScrollspy",
     "description": "Scrollspy — tracks which section is currently in view and exposes its `id`,\nso a table of contents / \"on this page\" nav can highlight the active link.\n\nApply it to any element (typically the nav) and point `mkScrollspy` at a CSS\nselector matching the section elements to watch (each needs an `id`). Read the\nactive id via the exported instance, or bind `(activeChange)`:\n\n```html\n<nav mkScrollspy=\"main :is(h2, h3)[id]\" #spy=\"mkScrollspy\">\n  <a href=\"#intro\" [class.is-active]=\"spy.activeId() === 'intro'\">Intro</a>\n  …\n</nav>\n```\n\nA section activates once its top passes `offset` px below the top of the\nscroll root (default the viewport). When scrolling through a gap between\nsections the previous one stays active until the next crosses the line.",
     "file": "projects/mk-kit/directives/directives/scrollspy.ts",
     "kind": "directive",
     "selector": "[mkScrollspy]",
     "selectors": [
      "mkScrollspy"
     ],
     "exportAs": "mkScrollspy",
     "inputs": [
      {
       "name": "mkScrollspy",
       "type": "string",
       "description": "CSS selector for the section elements to track (queried within `root`).",
       "required": true
      },
      {
       "name": "root",
       "type": "HTMLElement | null",
       "description": "Scroll container. Sections are queried inside it and its top edge is the\nactivation reference. Defaults to the whole document / viewport.",
       "default": "null"
      },
      {
       "name": "offset",
       "type": "number",
       "description": "Distance (px) below the scroll root's top at which a section becomes\nactive. Raise it to account for a sticky header.",
       "default": "96"
      }
     ],
     "outputs": [
      {
       "name": "activeChange",
       "type": "string | null",
       "description": "Emitted whenever the active section changes."
      }
     ],
     "methods": [
      {
       "name": "refresh",
       "signature": "(): void",
       "description": "Re-evaluate the active section (call after sections change)."
      }
     ],
     "properties": [
      {
       "name": "activeId",
       "type": "WritableSignal<string | null>",
       "description": "The id of the currently active section (`null` before the first one).",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkCurrencyPipe",
     "description": "`mkCurrency` — format a number as money with `Intl.NumberFormat`, honouring\nthe locale and default currency from `provideMkI18n({ locale, currency })`.\nNo Angular locale data is needed. Pure: `null`, `undefined`, `''` and\nnon-numeric input render as `''`.\n\n```html\n{{ 1234.5 | mkCurrency }}                                <!-- $1,234.50 (i18n currency, default USD) -->\n{{ 1234.5 | mkCurrency:'EUR' }}                          <!-- €1,234.50 -->\n{{ 1234.5 | mkCurrency:'PLN':{ locale: 'pl-PL' } }}      <!-- 1234,50 zł -->\n{{ 1234567 | mkCurrency:'USD':{ notation: 'compact' } }} <!-- $1.2M -->\n{{ total() | mkCurrency:'GBP':{ signDisplay: 'always' } }} <!-- signals work as-is -->\n```",
     "file": "projects/mk-kit/directives/pipes/currency.pipe.ts",
     "kind": "pipe",
     "pipeName": "mkCurrency",
     "signature": "(value: number | string | null | undefined, currency?: string | null, options?: MkCurrencyOptions): string"
    },
    {
     "name": "MkFileSizePipe",
     "description": "`mkFileSize` — bytes → a human-readable size such as `1.2 MB`, with the\nnumber formatted by `Intl.NumberFormat` in the `provideMkI18n` locale.\nPure: `null`, `undefined`, `''` and non-numeric input render as `''`.\n\n```html\n{{ 1_234_567 | mkFileSize }}                        <!-- 1.2 MB -->\n{{ 1_234_567 | mkFileSize:{ base: 'binary' } }}     <!-- 1.2 MiB -->\n{{ 1_234_567 | mkFileSize:{ digits: 2, locale: 'de' } }} <!-- 1,23 MB -->\n{{ 512 | mkFileSize }}                              <!-- 512 B -->\n```",
     "file": "projects/mk-kit/directives/pipes/file-size.pipe.ts",
     "kind": "pipe",
     "pipeName": "mkFileSize",
     "signature": "(value: number | string | null | undefined, options?: MkFileSizeOptions): string"
    },
    {
     "name": "MkInitialsPipe",
     "description": "`mkInitials` — \"Ada Lovelace\" → \"AL\", the same rule `mk-avatar` uses for\nits fallback: first letter of the first and last word, upper-cased. A\nsingle word yields its first `max` letters (\"Ada\" → \"AD\"); more than two\nwords with `max` > 2 take one letter per word from the start (\"Jean\nLuc Picard\" with `max: 3` → \"JLP\"). Leading/trailing/duplicate whitespace\nis ignored, and grapheme-aware slicing keeps emoji and accents intact.\nPure: `null`, `undefined` and blank input render as `''`.\n\n```html\n{{ user.name | mkInitials }}      <!-- Grace Hopper → GH -->\n{{ user.name | mkInitials:1 }}    <!-- Grace Hopper → G -->\n{{ 'Jean Luc Picard' | mkInitials:3 }} <!-- JLP -->\n```",
     "file": "projects/mk-kit/directives/pipes/initials.pipe.ts",
     "kind": "pipe",
     "pipeName": "mkInitials",
     "signature": "(value: string | null | undefined, max?: number): string"
    },
    {
     "name": "MkPluralizePipe",
     "description": "`mkPluralize` — pick the right word for a count using the locale's plural\nrules (`Intl.PluralRules`), optionally prefixed with the formatted count.\nThe English shorthand takes a singular and an optional plural (default\n`singular + 's'`); other languages pass a `MkPluralForms` map.\nPure: `null`, `undefined`, `''` and non-numeric counts render as `''`.\n\n```html\n{{ count | mkPluralize:'item' }}                 <!-- 1 item / 3 items -->\n{{ count | mkPluralize:'entry':'entries' }}      <!-- 1 entry / 2 entries -->\n{{ count | mkPluralize:'file':null:{ withCount: false } }} <!-- files -->\n{{ n | mkPluralize:{ one: 'plik', few: 'pliki', many: 'plików', other: 'pliku' }:null:{ locale: 'pl' } }}\n```",
     "file": "projects/mk-kit/directives/pipes/pluralize.pipe.ts",
     "kind": "pipe",
     "pipeName": "mkPluralize",
     "signature": "(value: number | string | null | undefined, singular: string | MkPluralForms, plural?: string | null, options?: MkPluralizeOptions): string"
    },
    {
     "name": "MkRelativeTimePipe",
     "description": "`mkRelativeTime` — \"3 minutes ago\" / \"in 2 days\" / \"yesterday\" from a\n`Date`, timestamp or ISO string, via `Intl.RelativeTimeFormat` in the\n`provideMkI18n` locale (no Angular locale data). Pure: `null`, `undefined`\nand unparsable input render as `''`.\n\nThe pipe picks the largest unit whose magnitude is at least 1 (seconds →\nminutes → hours → days → weeks → months → years) and rounds. Pass `now`\nfor deterministic output in tests, or bind a ticking signal to keep a\nlist live — a pure pipe only re-runs when an argument changes. The second\nargument is either that `now` or the options object, so options alone\nneed no `null` placeholder; the three-argument form (`now`, then options)\nworks too:\n\n```html\n{{ comment.createdAt | mkRelativeTime }}                    <!-- 3 minutes ago -->\n{{ due | mkRelativeTime:now() }}                            <!-- in 2 days (now() ticks) -->\n{{ due | mkRelativeTime:{ style: 'short' } }}               <!-- in 2 days -->\n{{ ts | mkRelativeTime:{ locale: 'pl', numeric: 'always' } }} <!-- 3 minuty temu -->\n{{ due | mkRelativeTime:now():{ style: 'short' } }}         <!-- in 2 days (ticking) -->\n```",
     "file": "projects/mk-kit/directives/pipes/relative-time.pipe.ts",
     "kind": "pipe",
     "pipeName": "mkRelativeTime",
     "signature": "(value: Date | number | string | null | undefined, nowOrOptions?: Date | number | string | MkRelativeTimeOptions | null, options?: MkRelativeTimeOptions): string"
    },
    {
     "name": "MkTruncatePipe",
     "description": "`mkTruncate` — shorten text to `length` characters and append an ellipsis.\nThe ellipsis counts toward the limit, so the output never exceeds\n`length` characters; counting is grapheme-aware (emoji and accented\nletters are one character). Text that already fits is returned as-is.\nPure: `null` and `undefined` render as `''`.\n\n```html\n{{ post.body | mkTruncate:80 }}                          <!-- hard cut at 80 -->\n{{ post.body | mkTruncate:80:{ wordBoundary: true } }}   <!-- cut at the last space -->\n{{ hash | mkTruncate:12:{ ellipsis: '...' } }}\n```",
     "file": "projects/mk-kit/directives/pipes/truncate.pipe.ts",
     "kind": "pipe",
     "pipeName": "mkTruncate",
     "signature": "(value: string | null | undefined, length?: number, options?: MkTruncateOptions): string"
    },
    {
     "name": "MkHistoryService",
     "description": "MkHistoryService — the app-wide `MkHistoryStack` singleton. Inject it\nanywhere; call `MkHistoryStack.createScope` for an isolated local\nstack, or wire `mod+z` / `mod+shift+z` / `mod+y` with\n`registerHistoryHotkeys`.\n\n### Recipe — undoable `mk-table` cell edits\nWire the table's `(cellEdit)` output so each saved cell becomes one\nundoable step. Apply the edit yourself first (`push()` records an action\nthat already happened), and match rows by a stable id — the row object is\nreplaced by the immutable update:\n\n```ts\n// <mk-table [rows]=\"rows()\" [columns]=\"columns\" (cellEdit)=\"onCellEdit($event)\" />\nprivate readonly history = inject(MkHistoryService);\nreadonly rows = signal<Order[]>([...]);\n\nonCellEdit(edit: MkCellEdit<Order>): void {\n  const previous = edit.row[edit.key as keyof Order];\n  const apply = (value: unknown) =>\n    this.rows.update((rows) =>\n      rows.map((r) => (r.id === edit.row.id ? { ...r, [edit.key]: value } : r)),\n    );\n  apply(edit.value); // first execution is the caller's job\n  this.history.push({\n    label: `Edit ${edit.key}`,\n    undo: () => apply(previous),\n    redo: () => apply(edit.value),\n  });\n}\n```\n\nUndoing replays the old value through the same `apply` function; if your\nchange pipeline re-emits into `onCellEdit` during that replay, the\nre-entrancy guard drops the spurious `push()` (see `MkHistoryStack`).",
     "file": "projects/mk-kit/directives/history/history.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [],
     "properties": [],
     "docs": "/core-services"
    },
    {
     "name": "MkHotkeysService",
     "description": "MkHotkeysService — app-wide keyboard shortcuts. Register a combo string and a\nhandler; a single `keydown` listener (attached lazily on the first\nregistration, browser only) dispatches to every match.\n\nSupports single combos (`'mod+k'`, `'ctrl+shift+p'`, `'?'`) and simple\ntwo-step chords (`'g i'`). By default hotkeys are ignored while an editable\nfield is focused — pass `allowInInput` to opt in per registration.\n\n```ts\nconst off = hotkeys.register('mod+k', (e) => openPalette(), { preventDefault: true });\n// …later\noff();\n```",
     "file": "projects/mk-kit/directives/hotkeys/hotkeys.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "register",
       "signature": "(combo: string, handler: (e: KeyboardEvent) => void, options?: MkHotkeyOptions): () => void",
       "description": "Register `combo` → `handler`. Returns a disposer that unregisters it.\n`combo` may be a single combo or a space-separated two-step chord."
      },
      {
       "name": "unregisterAll",
       "signature": "(): void",
       "description": "Remove every registration and detach the listener."
      }
     ],
     "properties": [],
     "docs": "/components/utilities"
    },
    {
     "name": "MkHistoryStack",
     "description": "MkHistoryStack — a pure, signal-based, linear undo/redo command stack with\nno Angular DI involved. Instantiate it directly for a local editing session\n(a dialog, a canvas, a form wizard), or use the app-wide singleton\n`MkHistoryService`.\n\n```ts\nconst stack = new MkHistoryStack();\ndeleteRow(row);                                  // 1. do the work yourself\nstack.push({                                     // 2. record how to revert/redo it\n  label: 'Delete row',\n  undo: () => insertRow(row),\n  redo: () => deleteRow(row),\n});\nstack.undo();                                    // row is back\n```\n\n### Linear history\n`push()` clears the redo branch — after undoing twice and pushing a new\nentry, the two undone entries are gone (the standard editor model).\n\n### ⚠️ Re-entrancy guard — the classic footgun\nPushes made **while** `undo()` or `redo()` is executing are **silently\nignored**. Naive consumers often record history from a generic change\nhandler (`(cellEdit)`, `valueChanges`, …); when an undo replays the old\nvalue, that same handler fires again and would push a mirror entry,\ncorrupting the stack into an undo/redo ping-pong. The guard makes that\npattern safe by construction. If you need to record something new in\nresponse to an undo, do it after `undo()` returns.",
     "file": "projects/mk-kit/directives/history/history.service.ts",
     "kind": "class",
     "methods": [
      {
       "name": "push",
       "signature": "(entry: MkHistoryEntry): void",
       "description": "Record an already-performed action. Clears the redo branch and evicts the\noldest entry beyond `limit`. Ignored while `undo()`/`redo()` is\nexecuting (see the re-entrancy note on the class) — inside a `batch()` the\nentry is collected into the composite instead."
      },
      {
       "name": "undo",
       "signature": "(): boolean",
       "description": "Undo the most recent entry. Returns `false` when there is nothing to undo."
      },
      {
       "name": "redo",
       "signature": "(): boolean",
       "description": "Redo the most recently undone entry. Returns `false` when there is nothing to redo."
      },
      {
       "name": "clear",
       "signature": "(): void",
       "description": "Drop all entries (both branches) and any in-flight batch collection."
      },
      {
       "name": "batch",
       "signature": "<T>(label: string, work: () => T): T",
       "description": "Group every `push()` made during `work()` into **one** undoable step.\nUndo runs the children in reverse order; redo runs them forward. Nested\n`batch()` calls flatten into the outermost batch (its label wins). An\nempty batch records nothing. Returns `work()`'s result; if `work()`\nthrows, entries pushed before the throw are still committed."
      },
      {
       "name": "createScope",
       "signature": "(): MkHistoryStack",
       "description": "Create an **independent** stack with the same API — e.g. for a dialog's\nlocal editing session that should not pollute the app-wide history.\nDiscard it (or `clear()` it) when the session ends."
      }
     ],
     "properties": [
      {
       "name": "canUndo",
       "type": "Signal<boolean>",
       "description": "True when at least one entry can be undone.",
       "readonly": true
      },
      {
       "name": "canRedo",
       "type": "Signal<boolean>",
       "description": "True when at least one undone entry can be redone.",
       "readonly": true
      },
      {
       "name": "undoLabel",
       "type": "Signal<string | null>",
       "description": "Label of the entry `undo()` would revert, or `null` (\"Undo *Delete row*\").",
       "readonly": true
      },
      {
       "name": "redoLabel",
       "type": "Signal<string | null>",
       "description": "Label of the entry `redo()` would re-apply, or `null`.",
       "readonly": true
      },
      {
       "name": "size",
       "type": "Signal<number>",
       "description": "Number of undoable entries currently on the stack.",
       "readonly": true
      },
      {
       "name": "limit",
       "type": "number",
       "description": "Maximum number of undoable entries kept (default `100`). When exceeded the\n**oldest** entries are dropped. Settable at any time; lowering it trims\nthe stack immediately. Values below 1 are clamped to 1.",
       "readonly": true
      }
     ]
    },
    {
     "name": "MkPermissionPolicy",
     "description": "Permission policy — the contract the permission directives (`*mkCan`,\n`*mkCannot`, `[mkCanDisable]`) check against. Provide an implementation\nonce at bootstrap; the directives inject it optionally and, when no policy\nis provided at all, treat every permission as **granted** — an app that\nnever wires permissions must not have its whole UI hidden.\n\n`can` may return a plain `boolean` (static role checks) or a\n`Signal<boolean>` (live permissions). The directives normalise both, and a\nsignal-returning policy re-evaluates reactively: views appear/disappear and\ncontrols enable/disable the moment the underlying permissions change.\n\n```ts\n// A signal-based policy fed from an auth service:",
     "file": "projects/mk-kit/directives/permissions/permission-policy.ts",
     "kind": "class",
     "methods": [
      {
       "name": "can",
       "signature": "(permission: string): boolean | Signal<boolean>",
       "description": "Whether the current user holds `permission`. Return a `Signal<boolean>`\nto make the verdict live; a plain boolean is treated as static."
      }
     ],
     "properties": [],
     "docs": "/components/utilities"
    },
    {
     "name": "mkApplyMask",
     "description": "Format `value` against a mask `pattern`. Pattern tokens: `0` = digit,\n`A` = letter, `*` = alphanumeric; any other character is a literal that is\ninserted automatically. Characters that don't fit the current token are\nskipped, so pasted / mistyped input is coerced into shape.\n\nReturns the `masked` (display) string and the `unmasked` string (only the\ntoken characters — the value you usually store).",
     "file": "projects/mk-kit/directives/directives/mask.ts",
     "kind": "function",
     "signatures": [
      "(value: string, pattern: string): MkMaskResult"
     ]
    },
    {
     "name": "mkMaskCaret",
     "description": "Compute where the caret belongs after re-masking: after the same number of\nvalue (alphanumeric) characters the caret used to sit behind, absorbing any\nliteral(s) that immediately follow — so typing \"1\" in \"(0)\" lands the caret\nafter the \"(\". Shared by `MkMask` and the masked form controls.",
     "file": "projects/mk-kit/directives/directives/mask.ts",
     "kind": "function",
     "signatures": [
      "(oldValue: string, oldCaret: number, masked: string): number"
     ]
    },
    {
     "name": "mkMatchesHotkey",
     "description": "Does a `keydown` event satisfy a hotkey? `combo` may be a raw string (parsed\non the fly) or an already-parsed `MkParsedHotkey`.\n\nThe key is compared case-insensitively; modifier flags must match exactly.\n`mod` resolves to Meta on macOS and Ctrl elsewhere. Shift is not enforced for\nsymbol keys (e.g. `'?'`), whose shifted state varies by keyboard layout.",
     "file": "projects/mk-kit/directives/hotkeys/hotkeys.service.ts",
     "kind": "function",
     "signatures": [
      "(event: KeyboardEvent, combo: string | MkParsedHotkey): boolean"
     ]
    },
    {
     "name": "mkParseHotkey",
     "description": "Parse a single hotkey combo (e.g. `'mod+k'`, `'ctrl+shift+p'`, `'?'`) into a\nstructured `MkParsedHotkey`. Tokens are joined by `+`; the last\nnon-modifier token is the trigger key. Pure and SSR-safe.\n\nFor a chord (space-separated sequence like `'g i'`), split on whitespace and\nparse each step — `MkHotkeysService` does this for you.",
     "file": "projects/mk-kit/directives/hotkeys/hotkeys.service.ts",
     "kind": "function",
     "signatures": [
      "(combo: string): MkParsedHotkey"
     ]
    },
    {
     "name": "mkPermissionGranted",
     "description": "Resolve a policy verdict to a boolean, unwrapping signal-based results.\nCall it inside a reactive context (`computed` / `effect`) so a\nsignal-returning policy stays live. A missing policy grants everything.",
     "file": "projects/mk-kit/directives/permissions/permission-policy.ts",
     "kind": "function",
     "signatures": [
      "(policy: MkPermissionPolicy | null, permission: string): boolean"
     ]
    },
    {
     "name": "registerHistoryHotkeys",
     "description": "Opt-in helper wiring the standard editor shortcuts to a history stack\nthrough `MkHotkeysService`:\n\n- `mod+z` → `undo()`\n- `mod+shift+z` **and** `mod+y` → `redo()`\n\nMust be called in an **injection context** (constructor, field initializer,\nor `runInInjectionContext`). Nothing is registered automatically — apps own\ntheir shortcuts and call this where (and if) they want them:\n\n```ts\nexport class AppShell {\n  private readonly disposeHistoryKeys = registerHistoryHotkeys();\n}\n```\n\nPass a specific stack (e.g. a `createScope()` stack for a dialog) to bind\nthe shortcuts to it instead of the app-wide `MkHistoryService`.\n\nReturns a dispose function that unregisters all three shortcuts; it is also\ncalled automatically when the current injection context is destroyed.\n\nNotes:\n- `MkHotkeysService` ignores keydowns while an editable element\n  (input/textarea/select/contentEditable) is focused, so native text-field\n  undo keeps working — no extra handling needed here.\n- The shortcuts register with `preventDefault` so the browser's own\n  history/document undo does not fire alongside yours.",
     "file": "projects/mk-kit/directives/history/history-hotkeys.ts",
     "kind": "function",
     "signatures": [
      "(history?: MkHistoryStack): () => void"
     ]
    },
    {
     "name": "MK_FIELD_PRESETS",
     "description": "The attribute bundle per field kind. Exported so hosts can inspect what a\nkind resolves to, or spread an entry into their own preset table.\n\n`autocorrect` (non-standard, honoured by iOS Safari) is set to `off`\nwherever `spellcheck` is `false`.",
     "file": "projects/mk-kit/directives/directives/field.ts",
     "kind": "const",
     "type": "Readonly<Record<MkFieldKind, Partial<Record<\"type\" | \"inputmode\" | \"autocomplete\" | \"autocapitalize\" | \"autocorrect\" | \"spellcheck\" | \"enterkeyhint\", string>>>>"
    },
    {
     "name": "MkCurrencyOptions",
     "description": "Options accepted by `MkCurrencyPipe`. They map onto\n`Intl.NumberFormat` currency options; `locale` overrides the i18n /\nruntime locale for this call only.",
     "file": "projects/mk-kit/directives/pipes/currency.pipe.ts",
     "kind": "interface",
     "members": [
      {
       "name": "locale",
       "type": "string | undefined",
       "description": "BCP 47 locale for this call; defaults to `provideMkI18n({ locale })`, then the runtime locale.",
       "optional": true
      },
      {
       "name": "display",
       "type": "\"symbol\" | \"name\" | \"narrowSymbol\" | \"code\" | undefined",
       "description": "How the currency is shown. Default `'symbol'` (`€`, `$`, `zł`).",
       "optional": true
      },
      {
       "name": "minimumFractionDigits",
       "type": "number | undefined",
       "description": "Fraction digits; both default to the currency's own (2 for EUR, 0 for JPY).",
       "optional": true
      },
      {
       "name": "maximumFractionDigits",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "signDisplay",
       "type": "\"auto\" | \"never\" | \"always\" | \"exceptZero\" | undefined",
       "description": "Sign display, e.g. `'always'` for `+€10.00` or `'exceptZero'`.",
       "optional": true
      },
      {
       "name": "notation",
       "type": "\"compact\" | \"standard\" | undefined",
       "description": "Compact notation for dashboards (`$1.2M`). Default `'standard'`.",
       "optional": true
      },
      {
       "name": "useGrouping",
       "type": "boolean | undefined",
       "description": "Thousands grouping; default `true`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkFileSizeOptions",
     "description": "Options accepted by `MkFileSizePipe`.",
     "file": "projects/mk-kit/directives/pipes/file-size.pipe.ts",
     "kind": "interface",
     "members": [
      {
       "name": "locale",
       "type": "string | undefined",
       "description": "BCP 47 locale for the number part (decimal separator); defaults to the i18n / runtime locale.",
       "optional": true
      },
      {
       "name": "base",
       "type": "\"decimal\" | \"binary\" | undefined",
       "description": "`'decimal'` (default) divides by 1000 and labels `kB MB GB …` (what\noperating systems and file dialogs show); `'binary'` divides by 1024\nand labels `KiB MiB GiB …`.",
       "optional": true
      },
      {
       "name": "digits",
       "type": "number | undefined",
       "description": "Maximum fraction digits. Default `1`; bytes never get fractions.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkHistoryEntry",
     "description": "A single undoable step recorded in an `MkHistoryStack`.\n\nThe **first** execution of an action is the caller's job — `push()` records\nan action that has *already happened*. `undo()` reverts it; `redo()` applies\nit again after an undo.",
     "file": "projects/mk-kit/directives/history/history.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Human label for menus/tooltips (\"Delete row\", \"Move card\")."
      },
      {
       "name": "undo",
       "type": "(): void",
       "description": "Revert the action."
      },
      {
       "name": "redo",
       "type": "(): void",
       "description": "Re-apply the action after an undo."
      }
     ]
    },
    {
     "name": "MkHotkeyOptions",
     "description": "Options accepted by `MkHotkeysService.register`.",
     "file": "projects/mk-kit/directives/hotkeys/hotkeys.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "preventDefault",
       "type": "boolean | undefined",
       "description": "Call `preventDefault()` on the event when the hotkey fires. Default `false`.",
       "optional": true
      },
      {
       "name": "allowInInput",
       "type": "boolean | undefined",
       "description": "Also fire while a text field (text-like input/textarea/select/contentEditable) is focused. Default `false`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkMaskResult",
     "description": "Result of applying a mask: the formatted string and its raw token chars.",
     "file": "projects/mk-kit/directives/directives/mask.ts",
     "kind": "interface",
     "members": [
      {
       "name": "masked",
       "type": "string",
       "description": ""
      },
      {
       "name": "unmasked",
       "type": "string",
       "description": ""
      }
     ]
    },
    {
     "name": "MkParsedHotkey",
     "description": "A single hotkey combo parsed into a normalized key + modifier flags.\nProduced by `mkParseHotkey`; consumed by `mkMatchesHotkey`.",
     "file": "projects/mk-kit/directives/hotkeys/hotkeys.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": "The non-modifier key, lowercased and alias-normalized (e.g. `k`, `escape`, `?`)."
      },
      {
       "name": "mod",
       "type": "boolean",
       "description": "`mod` — Cmd on macOS, Ctrl elsewhere."
      },
      {
       "name": "ctrl",
       "type": "boolean",
       "description": "The Control key."
      },
      {
       "name": "meta",
       "type": "boolean",
       "description": "The Meta / Command / Windows key."
      },
      {
       "name": "alt",
       "type": "boolean",
       "description": "The Alt / Option key."
      },
      {
       "name": "shift",
       "type": "boolean",
       "description": "The Shift key."
      }
     ]
    },
    {
     "name": "MkPluralizeOptions",
     "description": "Options accepted by `MkPluralizePipe`.",
     "file": "projects/mk-kit/directives/pipes/pluralize.pipe.ts",
     "kind": "interface",
     "members": [
      {
       "name": "locale",
       "type": "string | undefined",
       "description": "BCP 47 locale for the plural rules and number; defaults to the i18n / runtime locale.",
       "optional": true
      },
      {
       "name": "withCount",
       "type": "boolean | undefined",
       "description": "Prefix the formatted count (`\"3 items\"`); `false` gives just the word. Default `true`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkRelativeTimeOptions",
     "description": "Options accepted by `MkRelativeTimePipe`.",
     "file": "projects/mk-kit/directives/pipes/relative-time.pipe.ts",
     "kind": "interface",
     "members": [
      {
       "name": "locale",
       "type": "string | undefined",
       "description": "BCP 47 locale for this call; defaults to `provideMkI18n({ locale })`, then the runtime locale.",
       "optional": true
      },
      {
       "name": "numeric",
       "type": "\"auto\" | \"always\" | undefined",
       "description": "`'auto'` (default) uses phrases like \"yesterday\" / \"now\" where the locale\nhas them; `'always'` sticks to \"1 day ago\" / \"in 0 seconds\".",
       "optional": true
      },
      {
       "name": "style",
       "type": "\"long\" | \"short\" | \"narrow\" | undefined",
       "description": "Length of the unit word: `'long'` (default, \"minutes\"), `'short'` (\"min.\"), `'narrow'` (\"m\").",
       "optional": true
      },
      {
       "name": "maxUnit",
       "type": "Intl.RelativeTimeFormatUnit | undefined",
       "description": "Largest unit to use. Default `'year'`; e.g. `'day'` keeps \"45 days ago\"\ninstead of \"1 month ago\".",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTruncateOptions",
     "description": "Options accepted by `MkTruncatePipe`.",
     "file": "projects/mk-kit/directives/pipes/truncate.pipe.ts",
     "kind": "interface",
     "members": [
      {
       "name": "ellipsis",
       "type": "string | undefined",
       "description": "Suffix appended when text is cut. Default `'…'` (a single ellipsis character).",
       "optional": true
      },
      {
       "name": "wordBoundary",
       "type": "boolean | undefined",
       "description": "Cut at the last whitespace before the limit instead of mid-word\n(falls back to a hard cut when the first word alone is longer).\nDefault `false`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkFieldKind",
     "description": "Semantic field kinds understood by `MkField`.",
     "file": "projects/mk-kit/directives/directives/field.ts",
     "kind": "type",
     "definition": "| 'email' | 'tel' | 'url' | 'search' | 'numeric' | 'given-name' | 'family-name' | 'name' | 'organization' | 'street' | 'address-line1' | 'address-line2' | 'city' | 'region' | 'country' | 'postal-code' | 'username' | 'one-time-code'"
    },
    {
     "name": "MkFieldPreset",
     "description": "The attribute bundle applied for one `MkFieldKind`. Omitted = not set.",
     "file": "projects/mk-kit/directives/directives/field.ts",
     "kind": "type",
     "definition": "Partial<Record<MkFieldAttr, string>>"
    },
    {
     "name": "MkPluralForms",
     "description": "Per-category word forms for `MkPluralizePipe`, keyed by the CLDR\nplural categories `Intl.PluralRules` returns. `other` is required; the\npipe falls back to it for any category you leave out.\n\n```ts\nconst files: MkPluralForms = { one: 'plik', few: 'pliki', many: 'plików', other: 'pliku' };\n```",
     "file": "projects/mk-kit/directives/pipes/pluralize.pipe.ts",
     "kind": "type",
     "definition": "{ other: string } & Partial<Record<Intl.LDMLPluralRule, string>>"
    }
   ]
  },
  {
   "name": "dnd",
   "import": "@mk-kit/ui/dnd",
   "exports": [
    {
     "name": "MkDrag",
     "description": "Makes an item inside a `[mkDropList]` draggable — by pointer (mouse / touch /\npen) **and** by keyboard (WCAG 2.1.1). Every move is announced via\n`MkLiveAnnouncer`. Which element carries the keyboard interaction\ndepends on the handle:\n\n- **No handle, or a decorative one** (`<span mkDragHandle aria-hidden>`):\n  the item itself is focusable and exposes `aria-roledescription=\"Draggable\n  item\"` with `role=\"button\"` — or `role=\"option\"` when it is an `<li>` of a\n  `<ul mkDropList>`, which then becomes a labelled `listbox` (an `<li>` may\n  not take the `button` role).\n- **A focusable handle** (`<button mkDragHandle aria-label=\"…\">`, or any\n  handle with `tabindex`): the handle is the keyboard target and receives\n  the `aria-roledescription` / `aria-pressed` / `aria-grabbed` state; the\n  item stays a plain container with no role and no `tabindex`, so it can hold\n  inputs, links and buttons of its own (no nested interactive controls) and\n  `<li>` items keep their list semantics.\n\nKeyboard: focus the item (or its handle) and press **Space/Enter** to pick\nit up, **Arrow** keys to move it (crossing into connected lists at the ends /\nacross the perpendicular axis), **Space/Enter** to drop, **Escape** to cancel.\n\nBesides lists, an item can be released on a connected `[mkDropZone]` — a\ntarget that reports *where* it was dropped instead of an index (a timeline,\na priority band, a \"focus on this\" pane). Zones sit in the same keyboard\ntravel group as lists, in document order; while an item hovers a zone no\nplaceholder is shown and the zone streams `mkDropZoneMoved` events.\n\nTouch: a swipe scrolls the page as usual — the drag only arms after a\nlong-press (`mkDragTouchDelay`, default 300 ms). While armed the item\ngets the `mk-drag--armed` class so consumers can style the lift moment.\nMouse and pen drags start immediately, as before.\n\nPerformance: pointer moves are rAF-coalesced (one hit-test + one set of\nstyle/DOM writes per frame) against list/item rects snapshotted when the\ndrag lifts, so a move never forces layout. The pending frame is flushed\nsynchronously on release so drops land exactly where the pointer ended.\n\n```html\n<div mkDrag [mkDragData]=\"row\" [mkDragDisabled]=\"row.locked\">\n  <span mkDragHandle aria-hidden=\"true\">⠿</span> {{ row.title }}\n</div>\n```",
     "file": "projects/mk-kit/dnd/drag.ts",
     "kind": "component",
     "selector": "[mkDrag]",
     "selectors": [
      "mkDrag"
     ],
     "exportAs": "mkDrag",
     "inputs": [
      {
       "name": "mkDragData",
       "type": "T | undefined",
       "description": "Arbitrary payload associated with this item."
      },
      {
       "name": "mkDragDisabled",
       "type": "boolean",
       "description": "Disable dragging this specific item.",
       "default": "false"
      },
      {
       "name": "mkDragTouchDelay",
       "type": "number",
       "description": "Long-press delay (ms) before a *touch* pointer arms the drag. Until it\nelapses a swipe scrolls natively; moving more than `TOUCH_SLOP`\npixels abandons the pending drag. `0` arms immediately (legacy behavior).\nMouse and pen are never delayed.",
       "default": "300"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "element",
       "type": "HTMLElement",
       "description": "The item's host element.",
       "readonly": true
      },
      {
       "name": "keyboardHandle",
       "type": "Signal<MkDragHandle | null>",
       "description": "The handle that carries the keyboard drag — the first of this item's\nhandles that is focusable on its own (a `<button mkDragHandle>`, say).\n`null` when the item itself is the keyboard target.",
       "readonly": true
      },
      {
       "name": "disabled",
       "type": "Signal<boolean>",
       "description": "Effective disabled state (item- or list-level).",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/drag-drop"
    },
    {
     "name": "MkDropList",
     "description": "A drop container for reorderable `[mkDrag]` items.\n\n- **Sort list:** a single `[mkDropList]` over an array — items reorder within it.\n- **Buckets / kanban:** several `[mkDropList]`s wired together with\n  `mkDropListConnectedTo` so items transfer between them (both by pointer and\n  by keyboard at the ends of a list).\n\nThe array bound to `mkDropListData` is **not** mutated for you — handle\n`mkDropListDropped` and call `mkMoveItemInArray` / `mkTransferArrayItem`.\n\nSemantics follow the host element and its items, so the tree is always\nvalid ARIA:\n\n- any host other than `<ul>`/`<ol>` is a `role=\"group\"` (named by\n  `mkDropListLabel`) of `role=\"button\"` items;\n- a `<ul>`/`<ol>` whose `<li mkDrag>` items all carry a *focusable*\n  `[mkDragHandle]` stays a plain list — the handles are the controls;\n- a `<ul>`/`<ol>` whose items are themselves the keyboard targets becomes a\n  `listbox` of `option`s (an `<li>` may not be a `button`); give it a\n  `mkDropListLabel`, listboxes need a name.\n\nA `role` you set in the template is kept, and `aria-orientation` is only\nexposed on roles that allow it (`listbox`, `toolbar`, `tree`, …) — the\nkeyboard model handles both axes regardless.\n\n```html\n<div mkDropList [mkDropListData]=\"todo()\" mkDropListLabel=\"To do\"\n     mkDropListId=\"todo\" [mkDropListConnectedTo]=\"['done']\"\n     (mkDropListDropped)=\"drop($event)\">",
     "file": "projects/mk-kit/dnd/drop-list.ts",
     "kind": "component",
     "selector": "[mkDropList]",
     "selectors": [
      "mkDropList"
     ],
     "exportAs": "mkDropList",
     "inputs": [
      {
       "name": "mkDropListData",
       "type": "readonly T[]",
       "description": "The array backing the list. Bound, never mutated by the directive.",
       "default": "[]"
      },
      {
       "name": "mkDropListId",
       "type": "string | undefined",
       "description": "Stable id used to connect lists. Auto-generated when omitted."
      },
      {
       "name": "mkDropListConnectedTo",
       "type": "readonly string[]",
       "description": "Ids of other lists items may be transferred into.",
       "default": "[]"
      },
      {
       "name": "mkDropListLabel",
       "type": "string",
       "description": "Human-readable name used in screen-reader announcements when an item is\nmoved into this list (e.g. `\"In progress\"`). Falls back to the list `id`\n— which may be auto-generated gibberish — so set it wherever users can\nmove items across lists by keyboard.",
       "default": "''"
      },
      {
       "name": "mkDropListLabelledBy",
       "type": "string",
       "description": "Id of the element that names the list (`aria-labelledby`), e.g. a\nvisible heading. Takes precedence over `mkDropListLabel` as the\naccessible name; the label is still used in announcements.",
       "default": "''"
      },
      {
       "name": "mkDropListOrientation",
       "type": "MkDropListOrientation",
       "description": "Layout axis; controls pointer hit-testing and arrow-key direction.",
       "default": "'vertical'"
      },
      {
       "name": "mkDropListDisabled",
       "type": "boolean",
       "description": "Disable dropping into (and dragging out of) this list.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "mkDropListDropped",
       "type": "MkDropEvent<T>",
       "description": "Fires when an item is dropped into this list (pointer or keyboard)."
      }
     ],
     "methods": [
      {
       "name": "size",
       "signature": "(): number",
       "description": "Number of drag items currently in the list."
      },
      {
       "name": "indexOf",
       "signature": "(drag: MkDrag<any>): number",
       "description": "Index of `drag` among this list's items, or -1."
      },
      {
       "name": "itemElementsExcept",
       "signature": "(exclude: MkDrag<any>): HTMLElement[]",
       "description": "Host elements of this list's items, excluding `exclude`, in DOM order."
      },
      {
       "name": "setReceiving",
       "signature": "(value: boolean): void",
       "description": "Toggle the \"receiving\" highlight (called by the active drag)."
      },
      {
       "name": "emitDrop",
       "signature": "(event: MkDropEvent<any>): void",
       "description": "Emit a drop into this list. Called by the active `MkDrag`."
      }
     ],
     "properties": [
      {
       "name": "element",
       "type": "HTMLElement",
       "description": "The list's host element (drop target bounds).",
       "readonly": true
      },
      {
       "name": "id",
       "type": "Signal<string>",
       "description": "Resolved id (input or generated).",
       "readonly": true
      },
      {
       "name": "label",
       "type": "Signal<string>",
       "description": "Announceable name: the label when set, otherwise the resolved id.",
       "readonly": true
      },
      {
       "name": "role",
       "type": "Signal<string | null>",
       "description": "The role the host exposes. One set in the template wins. A `<ul>`/`<ol>`\nkeeps its implicit `list` role (`null` — nothing is written) while every\nitem hands the keyboard drag to a focusable handle, and becomes a\n`listbox` (its items `option`s) otherwise. Any other element is a `group`.",
       "readonly": true
      },
      {
       "name": "connectedTo",
       "type": "Signal<readonly string[]>",
       "description": "Connected-list ids, normalised to a plain array.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/drag-drop"
    },
    {
     "name": "MkDropZone",
     "description": "A drop **target** that is not a list: an item dragged out of a connected\n`[mkDropList]` can be released anywhere on it, and the zone reports *where*\n— client coordinates, the offset inside the zone and the 0–1 fraction along\neach axis — so the consumer can turn a position into meaning: a time on a\ntimeline, a priority band, a \"focus on this\" pane, a trash can.\n\nNothing reorders and no placeholder is shown while an item hovers a zone;\nthe zone gets the `mk-drop-zone--receiving` class and a stream of\n`mkDropZoneMoved` events instead. Zones and lists can overlap — the\ninnermost target under the pointer wins, so a column can hold three\npriority bands and still accept plain drops between the bands.\n\nWire a zone exactly like another list: give it an id and name that id in\nthe source list's `mkDropListConnectedTo`.\n\nKeyboard: a lifted item reaches zones with the arrow keys that cross lists\n(Left/Right in a vertical list, Up/Down in a horizontal one) — zones sit in\nthe same DOM-ordered travel group as connected lists; Space/Enter drops at\nthe zone's centre. Every step is announced.\n\n```html\n<ul mkDropList mkDropListId=\"backlog\" [mkDropListConnectedTo]=\"['now', 'rail']\" …>\n<section mkDropZone mkDropZoneId=\"now\" mkDropZoneLabel=\"Focus now\"\n         (mkDropZoneDropped)=\"focus($event.item.mkDragData())\">\n<div mkDropZone mkDropZoneId=\"rail\" mkDropZoneLabel=\"Today\"\n     (mkDropZoneMoved)=\"preview($event.fractionY)\"\n     (mkDropZoneDropped)=\"schedule($event.item.mkDragData(), $event.fractionY)\">\n```",
     "file": "projects/mk-kit/dnd/drop-zone.ts",
     "kind": "component",
     "selector": "[mkDropZone]",
     "selectors": [
      "mkDropZone"
     ],
     "exportAs": "mkDropZone",
     "inputs": [
      {
       "name": "mkDropZoneId",
       "type": "string | undefined",
       "description": "Stable id source lists name in `mkDropListConnectedTo`. Auto-generated when omitted."
      },
      {
       "name": "mkDropZoneLabel",
       "type": "string",
       "description": "Human-readable name, used in screen-reader announcements when a lifted\nitem reaches the zone (\"Moved to Focus now\") and as the zone's accessible\nname. Set it: the fallback is the id, which may be generated gibberish.",
       "default": "''"
      },
      {
       "name": "mkDropZoneLabelledBy",
       "type": "string",
       "description": "Id of a visible element that names the zone (`aria-labelledby`); wins over the label as the accessible name.",
       "default": "''"
      },
      {
       "name": "mkDropZoneData",
       "type": "Z | undefined",
       "description": "Arbitrary payload handed back on every hover and drop event."
      },
      {
       "name": "mkDropZoneDisabled",
       "type": "boolean",
       "description": "Disable dropping onto this zone (it leaves the travel group too).",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "mkDropZoneEntered",
       "type": "MkDropZoneHover<T, Z>",
       "description": "An item entered the zone (pointer or keyboard)."
      },
      {
       "name": "mkDropZoneMoved",
       "type": "MkDropZoneHover<T, Z>",
       "description": "The pointer moved while over the zone (one per frame, pointer only)."
      },
      {
       "name": "mkDropZoneLeft",
       "type": "MkDrag<T>",
       "description": "The item left the zone without dropping (moved on, or the drag was cancelled)."
      },
      {
       "name": "mkDropZoneDropped",
       "type": "MkDropZoneEvent<T, Z>",
       "description": "The item was released on the zone."
      }
     ],
     "methods": [
      {
       "name": "setReceiving",
       "signature": "(value: boolean): void",
       "description": "Toggle the \"receiving\" highlight (called by the active drag)."
      },
      {
       "name": "emitEntered",
       "signature": "(event: MkDropZoneHover<T, Z>): void",
       "description": "Called by the active `MkDrag` — not part of the consumer API."
      },
      {
       "name": "emitMoved",
       "signature": "(event: MkDropZoneHover<T, Z>): void",
       "description": ""
      },
      {
       "name": "emitLeft",
       "signature": "(item: MkDrag<T>): void",
       "description": ""
      },
      {
       "name": "emitDrop",
       "signature": "(event: MkDropZoneEvent<T, Z>): void",
       "description": ""
      }
     ],
     "properties": [
      {
       "name": "element",
       "type": "HTMLElement",
       "description": "The zone's host element (drop target bounds).",
       "readonly": true
      },
      {
       "name": "id",
       "type": "Signal<string>",
       "description": "Resolved id (input or generated).",
       "readonly": true
      },
      {
       "name": "label",
       "type": "Signal<string>",
       "description": "Announceable name: the label when set, otherwise the resolved id.",
       "readonly": true
      }
     ],
     "queries": []
    },
    {
     "name": "MkSortableList",
     "description": "Thin convenience wrapper over a single `[mkDropList]` for the common\n\"reorderable list\" case. Bind `items` two-way and provide an `<ng-template>`\nto render each row; drops are applied to the model for you (via\n`mkMoveItemInArray`).\n\nFor connected buckets / kanban, use `[mkDropList]` + `[mkDrag]` directly.\n\nThe list renders as a named `group` of `button` items: pass `label` (or\n`labelledBy` pointing at a visible heading) so screen readers say what is\nbeing reordered — the i18n `sortableListLabel` (\"Sortable list\") is the\nfallback.\n\n```html\n<mk-sortable-list [(items)]=\"rows\" label=\"Steps\">\n  <ng-template let-row let-i=\"index\">\n    <span mkDragHandle aria-hidden=\"true\">⠿</span> {{ i + 1 }}. {{ row.name }}\n  </ng-template>\n</mk-sortable-list>\n```",
     "file": "projects/mk-kit/dnd/sortable-list.ts",
     "kind": "component",
     "selector": "mk-sortable-list",
     "selectors": [
      "mk-sortable-list"
     ],
     "inputs": [
      {
       "name": "items",
       "type": "T[]",
       "description": "The ordered items (two-way). Reordered in place on drop.",
       "model": true,
       "default": "[]"
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "Accessible name of the list (`aria-label`), also used in the\n\"moved into …\" announcements. Defaults to the i18n `sortableListLabel`."
      },
      {
       "name": "labelledBy",
       "type": "string | undefined",
       "description": "Id of an element that names the list (`aria-labelledby`), e.g. a visible\nheading. Wins over `label` as the accessible name."
      },
      {
       "name": "orientation",
       "type": "MkDropListOrientation",
       "description": "Layout axis of the list.",
       "default": "'vertical'"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable reordering.",
       "default": "false"
      },
      {
       "name": "trackBy",
       "type": "(index: number, item: T) => unknown",
       "description": "`@for` tracking function. Defaults to identity (track by item).",
       "default": "(_, item) => item"
      }
     ],
     "outputs": [
      {
       "name": "itemsChange",
       "type": "T[]",
       "description": "Emits when `items` changes (two-way binding).",
       "model": true
      },
      {
       "name": "sorted",
       "type": "MkDropEvent<T>",
       "description": "Emitted after the model has been reordered."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/drag-drop"
    },
    {
     "name": "MkDragHandle",
     "description": "Optional grip that restricts where a pointer drag of the enclosing\n`[mkDrag]` may begin. Place it on the element the user should press to drag;\nwithout any handle the whole item is draggable.\n\nA directive (not a component), so it composes onto anything — a `<span>`,\na `<button>`, or another component's host such as `<mk-icon mkDragHandle />`.\nIts look (grab cursor, muted colour, `touch-action: none`) ships as the\nglobal `.mk-drag-handle` class in the theme stylesheet.\n\n**Decorative grip** — a non-focusable element (`<span>`, `<mk-icon>`): the\nitem itself stays the keyboard target (`role=\"button\"`, focusable), so the\ngrip should be `aria-hidden`:\n\n```html\n<div mkDrag [mkDragData]=\"row\">\n  <span mkDragHandle aria-hidden=\"true\">⠿</span>\n  {{ row.name }}\n</div>\n```\n\n**Focusable grip** — a `<button>` (or any element with `tabindex`): the\nhandle becomes the keyboard target instead. The item is then a plain\ncontainer (no role, not focusable), so rows may hold inputs, links and\nother buttons without nesting interactive controls, and `<li>` items keep\nvalid list semantics. Give it an accessible name:\n\n```html\n<li mkDrag [mkDragData]=\"row\">\n  <button type=\"button\" mkDragHandle [attr.aria-label]=\"'Reorder ' + row.name\">⠿</button>\n  <input mkInput [(ngModel)]=\"row.name\" />\n</li>\n```",
     "file": "projects/mk-kit/dnd/drag-handle.ts",
     "kind": "directive",
     "selector": "[mkDragHandle]",
     "selectors": [
      "mkDragHandle"
     ],
     "exportAs": "mkDragHandle",
     "inputs": [],
     "outputs": [],
     "methods": [
      {
       "name": "isFocusable",
       "signature": "(): boolean",
       "description": "Whether the handle can take keyboard focus itself — a native control\n(`<button>`, …), a link with `href`, or any element with a `tabindex`.\nA focusable handle carries the keyboard drag for its `[mkDrag]`."
      }
     ],
     "properties": [
      {
       "name": "element",
       "type": "HTMLElement",
       "description": "The handle's host element.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/drag-drop"
    },
    {
     "name": "MkDragDropRegistry",
     "description": "Central registry of every live `[mkDropList]` on the page, keyed by id.\n\nConnected lists (kanban \"buckets\") use it to resolve the sibling lists named\nin `mkDropListConnectedTo`, and both pointer and keyboard dragging use it to\nfind the group of lists an item may travel between.\n\nRegistration is automatic — you never call this service directly; it is\ndocumented so tooling/tests can inspect the wiring.",
     "file": "projects/mk-kit/dnd/drag-drop-registry.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "register",
       "signature": "(id: string, list: MkDropList<any>): void",
       "description": "Register (or replace) the list published under `id`."
      },
      {
       "name": "unregister",
       "signature": "(id: string, list: MkDropList<any>): void",
       "description": "Remove `list` from the registry if it is still the holder of `id`."
      },
      {
       "name": "get",
       "signature": "(id: string): MkDropList<any> | undefined",
       "description": "Look up a list by its `mkDropListId`."
      },
      {
       "name": "all",
       "signature": "(): MkDropList<any>[]",
       "description": "All registered lists, in registration order."
      },
      {
       "name": "connectedGroup",
       "signature": "(list: MkDropList<any>): MkDropList<any>[]",
       "description": "The ordered travel group for `list`: `list` itself plus every enabled list\nit is `mkDropListConnectedTo`, in registration (roughly DOM) order. Used to\nresolve \"adjacent\" lists for keyboard column-to-column movement and to\nhit-test the pointer against candidate targets."
      },
      {
       "name": "registerZone",
       "signature": "(id: string, zone: MkDropZone<any>): void",
       "description": "Register (or replace) the zone published under `id`."
      },
      {
       "name": "unregisterZone",
       "signature": "(id: string, zone: MkDropZone<any>): void",
       "description": "Remove `zone` from the registry if it is still the holder of `id`."
      },
      {
       "name": "getZone",
       "signature": "(id: string): MkDropZone<any> | undefined",
       "description": "Look up a zone by its `mkDropZoneId`."
      },
      {
       "name": "connectedZones",
       "signature": "(list: MkDropList<any>): MkDropZone<any>[]",
       "description": "Every enabled zone named in `list`'s `mkDropListConnectedTo`, in registration order."
      },
      {
       "name": "travelGroup",
       "signature": "(list: MkDropList<any>): MkDropTarget[]",
       "description": "The keyboard travel group for `list`: its connected lists **and** zones,\nin document order, so arrow keys walk targets the way they appear on\nscreen regardless of when each registered."
      }
     ],
     "properties": []
    },
    {
     "name": "mkMoveItemInArray",
     "description": "Move an item within a single array from `fromIndex` to `toIndex`.\nMutates and returns `array`.\n\n```ts\nmkMoveItemInArray(rows, e.previousIndex, e.currentIndex);\n```",
     "file": "projects/mk-kit/dnd/drag-drop-utils.ts",
     "kind": "function",
     "signatures": [
      "<T>(array: T[], fromIndex: number, toIndex: number): T[]"
     ]
    },
    {
     "name": "mkTransferArrayItem",
     "description": "Move an item from one array (`from`) to another (`to`), removing it from\n`from[fromIndex]` and inserting it at `to[toIndex]`. Mutates both arrays and\nreturns the target (`to`) array.\n\n```ts\nmkTransferArrayItem(todo, done, e.previousIndex, e.currentIndex);\n```",
     "file": "projects/mk-kit/dnd/drag-drop-utils.ts",
     "kind": "function",
     "signatures": [
      "<T>(from: T[], to: T[], fromIndex: number, toIndex: number): T[]"
     ]
    },
    {
     "name": "MkDropEvent",
     "description": "Emitted by `[mkDropList]` (`mkDropListDropped`) when an item is dropped.\n\nMirrors the shape of Angular CDK's `CdkDragDrop` so the exported\n`mkMoveItemInArray` / `mkTransferArrayItem` helpers can be used\nexactly as their CDK counterparts:\n\n```ts\nonDrop(e: MkDropEvent) {\n  if (e.previousContainer === e.container) {\n    mkMoveItemInArray(e.container.mkDropListData(), e.previousIndex, e.currentIndex);\n  } else {\n    mkTransferArrayItem(\n      e.previousContainer.mkDropListData(),\n      e.container.mkDropListData(),\n      e.previousIndex, e.currentIndex,\n    );\n  }\n}\n```",
     "file": "projects/mk-kit/dnd/drag-drop.types.ts",
     "kind": "interface",
     "typeParams": "<T = unknown>",
     "members": [
      {
       "name": "previousIndex",
       "type": "number",
       "description": "Index of the item within `previousContainer`'s data before the drop."
      },
      {
       "name": "currentIndex",
       "type": "number",
       "description": "Index the item should occupy within `container`'s data after the drop."
      },
      {
       "name": "item",
       "type": "MkDrag<T>",
       "description": "The `MkDrag` directive instance that was moved."
      },
      {
       "name": "previousContainer",
       "type": "MkDropList<T>",
       "description": "The list the item came from."
      },
      {
       "name": "container",
       "type": "MkDropList<T>",
       "description": "The list the item was dropped into (same as `previousContainer` for a re-sort)."
      },
      {
       "name": "isPointerEvent",
       "type": "boolean",
       "description": "`true` for pointer (mouse/touch/pen) drops, `false` for keyboard drops."
      }
     ]
    },
    {
     "name": "MkDropZoneEvent",
     "description": "Emitted by `[mkDropZone]` (`mkDropZoneDropped`) when an item is released on\nit. Carries the same position fields as `MkDropZoneHover` plus where\nthe item came from — the consumer removes it from that list (or not: a\n\"focus on this\" zone may leave the card where it is).",
     "file": "projects/mk-kit/dnd/drag-drop.types.ts",
     "kind": "interface",
     "typeParams": "<T = unknown, Z = unknown>",
     "extends": [
      "MkDropZoneHover<T, Z>"
     ],
     "members": [
      {
       "name": "previousContainer",
       "type": "MkDropList<T>",
       "description": "The list the item came from."
      },
      {
       "name": "previousIndex",
       "type": "number",
       "description": "Index of the item within `previousContainer`'s data."
      }
     ]
    },
    {
     "name": "MkDropZoneHover",
     "description": "Where an item is over a `[mkDropZone]`, emitted on enter and on every\npointer frame (`mkDropZoneEntered` / `mkDropZoneMoved`). Keyboard entries\nreport the zone's centre.",
     "file": "projects/mk-kit/dnd/drag-drop.types.ts",
     "kind": "interface",
     "typeParams": "<T = unknown, Z = unknown>",
     "members": [
      {
       "name": "item",
       "type": "MkDrag<T>",
       "description": "The `MkDrag` directive instance being dragged."
      },
      {
       "name": "zone",
       "type": "MkDropZone<Z, any>",
       "description": "The zone under the pointer."
      },
      {
       "name": "x",
       "type": "number",
       "description": "Pointer position in client (viewport) coordinates."
      },
      {
       "name": "y",
       "type": "number",
       "description": ""
      },
      {
       "name": "offsetX",
       "type": "number",
       "description": "Pointer position relative to the zone's top-left corner, in CSS pixels."
      },
      {
       "name": "offsetY",
       "type": "number",
       "description": ""
      },
      {
       "name": "fractionX",
       "type": "number",
       "description": "Pointer position as a 0–1 fraction of the zone's width / height (clamped)."
      },
      {
       "name": "fractionY",
       "type": "number",
       "description": ""
      },
      {
       "name": "isPointerEvent",
       "type": "boolean",
       "description": "`true` for pointer (mouse/touch/pen) hovers, `false` for keyboard steps."
      }
     ]
    },
    {
     "name": "MkDropListOrientation",
     "description": "Layout axis a drop list lays its items along.",
     "file": "projects/mk-kit/dnd/drag-drop.types.ts",
     "kind": "type",
     "definition": "'vertical' | 'horizontal'"
    },
    {
     "name": "MkDropTarget",
     "description": "A keyboard-reachable drop target: a connected list or a connected zone.",
     "file": "projects/mk-kit/dnd/drag-drop-registry.ts",
     "kind": "type",
     "definition": "MkDropList<any> | MkDropZone<any>"
    }
   ]
  },
  {
   "name": "navigation",
   "import": "@mk-kit/ui/navigation",
   "exports": [
    {
     "name": "MkAccordion",
     "description": "Groups `<mk-accordion-item>`s. By default only one item can be open at a\ntime (single-open); set `multi` to allow several. Coordinates its children\nthrough their two-way `open` models.\n\n```html\n<mk-accordion [multi]=\"false\">\n  <mk-accordion-item header=\"One\">…</mk-accordion-item>\n  <mk-accordion-item header=\"Two\">…</mk-accordion-item>\n</mk-accordion>\n```",
     "file": "projects/mk-kit/navigation/accordion/accordion.ts",
     "kind": "component",
     "selector": "mk-accordion",
     "selectors": [
      "mk-accordion"
     ],
     "inputs": [
      {
       "name": "multi",
       "type": "boolean",
       "description": "Allow multiple items open simultaneously.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [
      {
       "name": "onItemToggle",
       "signature": "(source: MkAccordionItem, opening: boolean): void",
       "description": "Called by an item just before its open state changes."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkAccordionItem",
     "description": "A collapsible section within an `<mk-accordion>`. The header is a button that\ntoggles a smoothly animated body region wired with `aria-expanded` /\n`aria-controls`. Open state is two-way bindable via `open`.\n\n```html\n<mk-accordion-item header=\"Shipping\" [(open)]=\"shippingOpen\">\n  …body…\n</mk-accordion-item>\n```",
     "file": "projects/mk-kit/navigation/accordion/accordion-item.ts",
     "kind": "component",
     "selector": "mk-accordion-item",
     "selectors": [
      "mk-accordion-item"
     ],
     "inputs": [
      {
       "name": "header",
       "type": "string",
       "description": "Plain-text header (ignored when `[mkAccordionHeader]` is projected).",
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable toggling of this item.",
       "default": "false"
      },
      {
       "name": "open",
       "type": "boolean",
       "description": "Whether the item is expanded (two-way).",
       "model": true,
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "openChange",
       "type": "boolean",
       "description": "Emits when `open` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "triggerId",
       "type": "string",
       "description": "Stable id for the trigger button.",
       "readonly": true
      },
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id for the panel region.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkAppShell",
     "description": "Admin dashboard layout with a fixed header, a collapsible/responsive sidebar\nand a main content area. On small screens the sidebar becomes a focus-trapped\noff-canvas drawer with a scrim (Escape to close). Includes a skip-to-content\nlink for keyboard users.\n\n```html\n<mk-app-shell [(sidebarOpen)]=\"open\" [(sidebarCollapsed)]=\"collapsed\">\n  <div mkAppHeader>\n    <button mkButton iconOnly (click)=\"shell.toggleSidebar()\">☰</button>\n  </div>\n  <mk-nav-list mkAppSidebar [collapsed]=\"collapsed()\">…</mk-nav-list>\n  <router-outlet />\n</mk-app-shell>\n```",
     "file": "projects/mk-kit/navigation/app-shell/app-shell.ts",
     "kind": "component",
     "selector": "mk-app-shell",
     "selectors": [
      "mk-app-shell"
     ],
     "inputs": [
      {
       "name": "sidebarOpen",
       "type": "boolean",
       "description": "Whether the mobile drawer is open (two-way).",
       "model": true,
       "default": "false"
      },
      {
       "name": "sidebarCollapsed",
       "type": "boolean",
       "description": "Whether the desktop sidebar is collapsed to icons (two-way).",
       "model": true,
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "sidebarOpenChange",
       "type": "boolean",
       "description": "Emits when `sidebarOpen` changes (two-way binding).",
       "model": true
      },
      {
       "name": "sidebarCollapsedChange",
       "type": "boolean",
       "description": "Emits when `sidebarCollapsed` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "toggleSidebar",
       "signature": "(): void",
       "description": "Toggle the mobile drawer open/closed. Handy for a hamburger button."
      },
      {
       "name": "openSidebar",
       "signature": "(): void",
       "description": "Open the mobile drawer."
      },
      {
       "name": "closeSidebar",
       "signature": "(): void",
       "description": "Close the mobile drawer."
      },
      {
       "name": "toggleCollapsed",
       "signature": "(): void",
       "description": "Toggle the desktop collapsed (icon-only) state."
      }
     ],
     "properties": [
      {
       "name": "isMobile",
       "type": "WritableSignal<boolean>",
       "description": "True when the viewport is at/below the mobile breakpoint.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkAppSwitcher",
     "description": "The \"apps grid\" of a family of applications: a header button that opens a\ngrid of links to the other apps, the current one marked. Give it the list\n(`apps`) or a registry to fetch it from (`src` — JSON, either an array or\n`{ apps: [...] }`), so every app of a suite shows the same switcher from one\nshared file.\n\n```html\n<mk-app-shell>\n  <ng-container mkAppHeader>\n    <mk-app-switcher src=\"https://home.example.com/apps.json\" current=\"sales\" />\n  </ng-container>\n</mk-app-shell>\n```\n\nThe registry is fetched lazily, the first time the panel opens, and once\nper page. The panel is a disclosure (a labelled group of links, not a menu):\nTab moves through the tiles, arrows too, Escape closes and returns focus.",
     "file": "projects/mk-kit/navigation/app-switcher/app-switcher.ts",
     "kind": "component",
     "selector": "mk-app-switcher",
     "selectors": [
      "mk-app-switcher"
     ],
     "exportAs": "mkAppSwitcher",
     "inputs": [
      {
       "name": "apps",
       "type": "MkAppLink[]",
       "description": "The apps, when the host has the list.",
       "default": "[]"
      },
      {
       "name": "src",
       "type": "string",
       "description": "A registry URL to fetch the apps from (JSON: an array or `{ apps }`). Used when `apps` is empty.",
       "default": "''"
      },
      {
       "name": "current",
       "type": "string",
       "description": "The app this switcher is shown in — its `id` or `url`; marked as current and listed first.",
       "default": "''"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible name of the trigger. Defaults to the i18n `appSwitcherLabel`.",
       "default": "''"
      },
      {
       "name": "columns",
       "type": "number",
       "description": "Tiles per row.",
       "default": "3"
      },
      {
       "name": "newTab",
       "type": "boolean",
       "description": "Open links in a new tab.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "openChange",
       "type": "boolean",
       "description": "Emits when the panel opens or closes."
      }
     ],
     "methods": [
      {
       "name": "toggle",
       "signature": "(): void",
       "description": ""
      },
      {
       "name": "show",
       "signature": "(): void",
       "description": ""
      },
      {
       "name": "close",
       "signature": "(restoreFocus?: boolean): void",
       "description": ""
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkBackToTop",
     "description": "BackToTop — a floating button that appears once the page (or a scroll target)\nhas scrolled past `threshold`, and smooth-scrolls back to the top on click.\n\n```html\n<mk-back-to-top [threshold]=\"600\" />\n```\nPass `[target]` to watch/scroll a specific scroll container instead of the\nwindow.",
     "file": "projects/mk-kit/navigation/back-to-top/back-to-top.ts",
     "kind": "component",
     "selector": "mk-back-to-top",
     "selectors": [
      "mk-back-to-top"
     ],
     "inputs": [
      {
       "name": "threshold",
       "type": "number",
       "description": "Scroll distance (px) before the button appears.",
       "default": "400"
      },
      {
       "name": "target",
       "type": "HTMLElement | null",
       "description": "Optional scroll container; defaults to the window.",
       "default": "null"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label.",
       "default": "this.i18n.backToTop"
      },
      {
       "name": "smooth",
       "type": "boolean",
       "description": "Smooth-scroll on click. Ignored under `prefers-reduced-motion: reduce`\n(programmatic `scrollTo` is not toned down by browsers, so the component\nfalls back to an instant jump itself).",
       "default": "true"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkBreadcrumb",
     "description": "Breadcrumb trail. Renders `nav[aria-label=\"Breadcrumb\"] > ol` and marks the\nfinal `<mk-breadcrumb-item>` as the current page. The separator is drawn in\nCSS and can be customised via `separator`.\n\n```html\n<mk-breadcrumb separator=\"›\">\n  <mk-breadcrumb-item href=\"/\">Home</mk-breadcrumb-item>\n  <mk-breadcrumb-item href=\"/users\">Users</mk-breadcrumb-item>\n  <mk-breadcrumb-item>Jane</mk-breadcrumb-item>\n</mk-breadcrumb>\n```",
     "file": "projects/mk-kit/navigation/breadcrumb/breadcrumb.ts",
     "kind": "component",
     "selector": "mk-breadcrumb",
     "selectors": [
      "mk-breadcrumb"
     ],
     "inputs": [
      {
       "name": "label",
       "type": "string",
       "description": "Accessible label for the navigation landmark.",
       "default": "this.i18n.breadcrumbLabel"
      },
      {
       "name": "separator",
       "type": "string",
       "description": "Separator character rendered between crumbs.",
       "default": "'/'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkBreadcrumbItem",
     "description": "A single crumb inside `<mk-breadcrumb>`. Renders a link when `href` is set,\notherwise plain text. The last item is automatically marked\n`aria-current=\"page\"` by the parent.\n\n```html\n<mk-breadcrumb-item href=\"/\">Home</mk-breadcrumb-item>\n<mk-breadcrumb-item>Current page</mk-breadcrumb-item>\n```",
     "file": "projects/mk-kit/navigation/breadcrumb/breadcrumb-item.ts",
     "kind": "component",
     "selector": "mk-breadcrumb-item",
     "selectors": [
      "mk-breadcrumb-item"
     ],
     "inputs": [
      {
       "name": "href",
       "type": "string | undefined",
       "description": "Optional link target. Rendered as text when omitted or when it is last."
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "last",
       "type": "WritableSignal<boolean>",
       "description": "Whether this is the final crumb. Set by the parent `MkBreadcrumb`.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkCommandPalette",
     "description": "CommandPalette — a modal ⌘K/Ctrl+K menu for fast, keyboard-first actions and\nnavigation. Supply a flat `commands` list (optionally grouped); the palette\nfilters as you type, groups results, and runs the chosen command. Implements\nthe ARIA combobox + listbox pattern with full keyboard support and focus\ntrapping.\n\nMount it once near your app root and bind `open` (the built-in hotkey toggles\nit, or open it yourself).\n\n```html\n<mk-command-palette [(open)]=\"paletteOpen\" [commands]=\"commands\"\n  (commandSelected)=\"run($event)\" />\n```",
     "file": "projects/mk-kit/navigation/command-palette/command-palette.ts",
     "kind": "component",
     "selector": "mk-command-palette",
     "selectors": [
      "mk-command-palette"
     ],
     "inputs": [
      {
       "name": "open",
       "type": "boolean",
       "description": "Whether the palette is open (two-way).",
       "model": true,
       "default": "false"
      },
      {
       "name": "commands",
       "type": "readonly MkCommand[]",
       "description": "The commands to search and run.",
       "default": "[]"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Search field placeholder.",
       "default": "this.i18n.commandPalettePlaceholder"
      },
      {
       "name": "emptyMessage",
       "type": "string",
       "description": "Message shown when nothing matches.",
       "default": "this.i18n.noResults"
      },
      {
       "name": "hotkey",
       "type": "boolean",
       "description": "Toggle open with ⌘K / Ctrl+K anywhere.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "openChange",
       "type": "boolean",
       "description": "Emits when `open` changes (two-way binding).",
       "model": true
      },
      {
       "name": "commandSelected",
       "type": "MkCommand",
       "description": "Emits the chosen command (its own `run` callback also fires)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/command-nav"
    },
    {
     "name": "MkDrawer",
     "description": "Drawer — a declarative slide-out panel anchored to a viewport edge, driven by\na two-way `open`. Ideal for admin/CMS side panels: filters, entity details,\nsettings, quick-create forms. Traps focus while open, closes on backdrop\nclick or Escape, restores focus on close, and locks body scroll when modal.\n\nSlots: `[mkDrawerHeader]` (extra header content), default content (body),\n`[mkDrawerFooter]` (sticky footer).\n\n```html\n<button mkButton (click)=\"filters.set(true)\">Filters</button>\n<mk-drawer [(open)]=\"filters\" side=\"end\" heading=\"Filters\">\n  …filter form…\n  <div mkDrawerFooter>\n    <button mkButton variant=\"ghost\" (click)=\"filters.set(false)\">Close</button>\n    <button mkButton (click)=\"apply()\">Apply</button>\n  </div>\n</mk-drawer>\n```",
     "file": "projects/mk-kit/navigation/drawer/drawer.ts",
     "kind": "component",
     "selector": "mk-drawer",
     "selectors": [
      "mk-drawer"
     ],
     "inputs": [
      {
       "name": "open",
       "type": "boolean",
       "description": "Whether the drawer is open (two-way).",
       "model": true,
       "default": "false"
      },
      {
       "name": "side",
       "type": "MkDrawerSide",
       "description": "Viewport edge to anchor to.",
       "default": "'end'"
      },
      {
       "name": "size",
       "type": "string",
       "description": "Panel width (start/end) or height (top/bottom) — any CSS length.",
       "default": "'20rem'"
      },
      {
       "name": "hasBackdrop",
       "type": "boolean",
       "description": "Render a dimmed backdrop and lock body scroll (modal).",
       "default": "true"
      },
      {
       "name": "closeOnBackdrop",
       "type": "boolean",
       "description": "Close when the backdrop is clicked.",
       "default": "true"
      },
      {
       "name": "closeOnEscape",
       "type": "boolean",
       "description": "Close on the Escape key.",
       "default": "true"
      },
      {
       "name": "trapFocus",
       "type": "boolean",
       "description": "Trap Tab focus inside the panel while open.",
       "default": "true"
      },
      {
       "name": "heading",
       "type": "string",
       "description": "Optional heading rendered in the header.",
       "default": "''"
      },
      {
       "name": "hideClose",
       "type": "boolean",
       "description": "Hide the header close button.",
       "default": "false"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when no `heading` is provided.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "openChange",
       "type": "boolean",
       "description": "Emits when `open` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "close",
       "signature": "(): void",
       "description": "Close the drawer."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/drawer"
    },
    {
     "name": "MkFab",
     "description": "FAB — a floating action button, fixed to a corner (or `static` for inline\nuse). Project the icon as content and set `label` for the accessible name\n(shown too when `extended`). Add `mkFabAction` buttons to turn it into a\nspeed-dial that reveals them on toggle.\n\n```html\n<mk-fab label=\"Create\" position=\"bottom-end\">\n  <svg>…</svg>\n  <button mkFabAction (click)=\"newDoc()\">Doc</button>\n  <button mkFabAction (click)=\"newFolder()\">Folder</button>\n</mk-fab>\n```",
     "file": "projects/mk-kit/navigation/fab/fab.ts",
     "kind": "component",
     "selector": "mk-fab",
     "selectors": [
      "mk-fab"
     ],
     "inputs": [
      {
       "name": "position",
       "type": "MkFabPosition",
       "description": "Corner placement (or `static` to render inline).",
       "default": "'bottom-end'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic tone.",
       "default": "'primary'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible label (and visible text when `extended`).",
       "default": "this.i18n.fabLabel"
      },
      {
       "name": "extended",
       "type": "boolean",
       "description": "Render as a pill with the label beside the icon.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the button.",
       "default": "false"
      },
      {
       "name": "open",
       "type": "boolean",
       "description": "Two-way open state of the speed-dial.",
       "model": true,
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "openChange",
       "type": "boolean",
       "description": "Emits when `open` changes (two-way binding).",
       "model": true
      },
      {
       "name": "action",
       "type": "void",
       "description": "Emitted when the FAB is activated (only when it has no actions)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkMenu",
     "description": "Dropdown menu implementing the ARIA menu pattern (roving focus, Arrow / Home\n/ End / typeahead, Enter/Space to activate). Attach it to a trigger with the\n`mkMenuTriggerFor` directive; the trigger controls opening and positioning.\n\nThe panel is rendered in the browser top layer via `MkAnchoredPanel`, so\nit is never clipped by an ancestor's `overflow`/`transform` and always flips\nback on-screen near a viewport edge.\n\n```html\n<button mkButton [mkMenuTriggerFor]=\"menu\">Actions</button>\n<mk-menu #menu>\n  <mk-menu-item (action)=\"edit()\">Edit</mk-menu-item>\n  <mk-menu-item danger (action)=\"del()\">Delete</mk-menu-item>\n</mk-menu>\n```\n\n**Submenus.** Point an item at a nested menu with `[mkSubmenuFor]`; declare\nthe nested `<mk-menu>` anywhere inside the parent menu. The submenu opens\nbeside its item on hover (after a short delay), on ArrowRight / Enter /\nSpace / click, and closes with ArrowLeft or Escape (returning focus to the\nitem) — only that level, per the APG menu pattern. Activating any leaf item\ncloses the whole chain. In RTL the submenu opens on the left and the arrow\nkeys swap.\n\n```html\n<mk-menu #menu>\n  <mk-menu-item [mkSubmenuFor]=\"exportMenu\">Export</mk-menu-item>\n  <mk-menu #exportMenu>\n    <mk-menu-item (action)=\"csv()\">CSV</mk-menu-item>\n    <mk-menu-item (action)=\"pdf()\">PDF</mk-menu-item>\n  </mk-menu>\n</mk-menu>\n```",
     "file": "projects/mk-kit/navigation/menu/menu.ts",
     "kind": "component",
     "selector": "mk-menu",
     "selectors": [
      "mk-menu"
     ],
     "exportAs": "mkMenu",
     "inputs": [],
     "outputs": [],
     "methods": [
      {
       "name": "open",
       "signature": "(trigger: HTMLElement, focus?: boolean | \"first\" | \"last\", placement?: MkPlacement): void",
       "description": "Open the menu anchored to `trigger`. `focus` picks the item that receives\nfocus once the panel is painted: `true`/`'first'` for the first enabled\nitem, `'last'` for the last (ArrowUp on a menu button, per the APG\nmenu-button pattern), `false` to leave focus where it is (mouse open).\n`placement` overrides the default `bottom-start` (submenus pass\n`right-start` / `left-start`)."
      },
      {
       "name": "openAt",
       "signature": "(x: number, y: number, restoreFocusEl?: HTMLElement): void",
       "description": "Open the menu at viewport coordinates — e.g. a right-click point from a\n`contextmenu` event. Positioning (and flip/shift back on-screen) is handled\nby `MkAnchoredPanel` via the point anchor. Focus moves to the first\nitem; `restoreFocusEl` (when provided) regains focus on close."
      },
      {
       "name": "close",
       "signature": "(restoreFocus?: boolean): void",
       "description": "Close this menu (and any submenu open under it); optionally restore focus\nto the trigger — for a submenu that is the item it hangs off."
      },
      {
       "name": "closeAll",
       "signature": "(restoreFocus?: boolean): void",
       "description": "Close the whole menu chain from the root down — what activating a leaf\nitem does, wherever in the tree it sits. Focus returns to the root\ntrigger when `restoreFocus` is set."
      },
      {
       "name": "closeChildren",
       "signature": "(keep?: MkMenu): void",
       "description": "Close every submenu open under this menu, except `keep`."
      },
      {
       "name": "toggle",
       "signature": "(trigger: HTMLElement, focusFirst?: boolean): void",
       "description": "Toggle open/closed from a trigger."
      },
      {
       "name": "focusFirstItem",
       "signature": "(): void",
       "description": "Move focus to the first enabled item. Used by the trigger when the menu is\nalready open (e.g. ArrowDown after a mouse open), so arrow keys always\nreach the items even though focus never left the trigger."
      },
      {
       "name": "focusLastItem",
       "signature": "(): void",
       "description": "Move focus to the last enabled item (ArrowUp from the trigger)."
      },
      {
       "name": "containsTarget",
       "signature": "(node: Node | null): boolean",
       "description": "Whether `node` lives inside this menu's panel or any submenu open under\nit. Submenu panels are separate top-layer elements, so a plain\n`contains` on the parent panel would treat clicks in them as outside."
      },
      {
       "name": "itemHovered",
       "signature": "(item: MkMenuItem): void",
       "description": "An item was hovered: close sibling submenus so only the hovered branch\nstays open (the item opens its own submenu after a delay)."
      },
      {
       "name": "submenuPlacement",
       "signature": "(): MkPlacement",
       "description": "Placement for a submenu hanging off `item`, honouring text direction."
      }
     ],
     "properties": [
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id for `aria-controls` on the trigger.",
       "readonly": true
      },
      {
       "name": "opened",
       "type": "Signal<boolean>",
       "description": "Whether the menu is currently open.",
       "readonly": true
      },
      {
       "name": "ariaLabel",
       "type": "WritableSignal<string | undefined>",
       "description": "Accessible label for the menu (defaults via the trigger if unset).",
       "readonly": true
      },
      {
       "name": "isSubmenu",
       "type": "boolean",
       "description": "Whether this menu is a submenu of another `mk-menu`. Submenus open\nsideways, close a single level on Escape, and swap ArrowLeft/ArrowRight.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkMenuItem",
     "description": "An item within an `<mk-menu>`. Renders as an ARIA `menuitem` with an optional\nicon slot (`[mkMenuItemIcon]`), disabled and danger states, and either emits\n`action` or navigates when `href` is set. Activating closes the menu.\n\nWith `[mkSubmenuFor]` pointing at a nested `<mk-menu>` the item becomes a\nsubmenu trigger instead: it shows a chevron, exposes `aria-haspopup` /\n`aria-expanded`, opens the submenu beside itself on hover, ArrowRight,\nEnter, Space or click, and never emits `action`.\n\n```html\n<mk-menu-item (action)=\"rename()\">\n  <svg mkMenuItemIcon>…</svg> Rename\n</mk-menu-item>\n<mk-menu-item danger (action)=\"remove()\">Delete</mk-menu-item>\n<mk-menu-item href=\"/help\">Help</mk-menu-item>\n<mk-menu-item [mkSubmenuFor]=\"more\">More</mk-menu-item>\n```",
     "file": "projects/mk-kit/navigation/menu/menu-item.ts",
     "kind": "component",
     "selector": "mk-menu-item",
     "selectors": [
      "mk-menu-item"
     ],
     "inputs": [
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Prevent selection and focus.",
       "default": "false"
      },
      {
       "name": "danger",
       "type": "boolean",
       "description": "Destructive styling (e.g. Delete).",
       "default": "false"
      },
      {
       "name": "href",
       "type": "string | undefined",
       "description": "When set, activating the item navigates here."
      },
      {
       "name": "mkSubmenuFor",
       "type": "MkMenu | undefined",
       "description": "A nested `mk-menu` this item opens as a submenu.",
       "default": "undefined"
      }
     ],
     "outputs": [
      {
       "name": "action",
       "type": "void",
       "description": "Emitted when the item is activated (not for disabled or submenu items)."
      }
     ],
     "methods": [
      {
       "name": "activate",
       "signature": "(event?: Event): void",
       "description": ""
      },
      {
       "name": "openSubmenu",
       "signature": "(focus: boolean): void",
       "description": "Open the submenu beside this item; `focus` moves focus to its first item."
      },
      {
       "name": "focusEl",
       "signature": "(): void",
       "description": "Move DOM focus to this item (roving focus)."
      },
      {
       "name": "contains",
       "signature": "(node: Node | null): boolean",
       "description": "Whether `node` lives inside this item."
      },
      {
       "name": "text",
       "signature": "(): string",
       "description": "Lowercased text content, used for typeahead matching."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkNavGroup",
     "description": "A titled section within an `<mk-nav-list>` — the \"MAIN\" / \"SETTINGS\" groupings\ncommon in admin/CMS sidebars. Static by default; set `collapsible` to make\nthe label a toggle that expands/collapses its items (`aria-expanded` +\nregion). In a collapsed icon rail the label becomes a divider.\n\n```html\n<mk-nav-list>\n  <mk-nav-group label=\"Main\">\n    <mk-nav-item label=\"Dashboard\" href=\"/\" />\n  </mk-nav-group>\n  <mk-nav-group label=\"Settings\" collapsible>\n    <mk-nav-item label=\"Team\" href=\"/team\" />\n  </mk-nav-group>\n</mk-nav-list>\n```",
     "file": "projects/mk-kit/navigation/nav-list/nav-group.ts",
     "kind": "component",
     "selector": "mk-nav-group",
     "selectors": [
      "mk-nav-group"
     ],
     "inputs": [
      {
       "name": "label",
       "type": "string",
       "description": "Section title.",
       "default": "''"
      },
      {
       "name": "collapsible",
       "type": "boolean",
       "description": "Make the label a toggle that shows/hides the items.",
       "default": "false"
      },
      {
       "name": "expanded",
       "type": "boolean",
       "description": "Whether the section is expanded (two-way; only meaningful when collapsible).",
       "model": true,
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "expandedChange",
       "type": "boolean",
       "description": "Emits when `expanded` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "regionId",
       "type": "string",
       "description": "Id of the items region (for `aria-controls`).",
       "readonly": true
      },
      {
       "name": "headerId",
       "type": "string",
       "description": "Id of the header, used to name the nested item list.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/command-nav"
    },
    {
     "name": "MkNavItem",
     "description": "A single sidebar entry: icon slot (`[mkNavIcon]`), label, optional badge and\nactive state. Renders a link when `href` is set, otherwise a button that\nemits `action`. If it contains nested `<mk-nav-item>`s it becomes an\nexpandable disclosure (`aria-expanded`). Collapses to an icon in a collapsed\nlist, exposing the label as a tooltip — and because a sub-list can't be shown\nat rail width, a parent item there emits `action` (navigate) instead of\ntoggling, so it never becomes a dead button.\n\n```html\n<mk-nav-item label=\"Reports\" active href=\"/reports\" badge=\"3\">\n  <svg mkNavIcon>…</svg>\n</mk-nav-item>\n<mk-nav-item label=\"Settings\">\n  <svg mkNavIcon>…</svg>\n  <mk-nav-item label=\"Team\" href=\"/team\" />\n</mk-nav-item>\n```",
     "file": "projects/mk-kit/navigation/nav-list/nav-item.ts",
     "kind": "component",
     "selector": "mk-nav-item",
     "selectors": [
      "mk-nav-item"
     ],
     "inputs": [
      {
       "name": "label",
       "type": "string",
       "description": "Visible label. Also used as the tooltip when collapsed.",
       "default": "''"
      },
      {
       "name": "href",
       "type": "string | undefined",
       "description": "Link target. Renders an anchor instead of a button."
      },
      {
       "name": "active",
       "type": "boolean",
       "description": "Marks the current page (`aria-current=\"page\"`).",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable interaction.",
       "default": "false"
      },
      {
       "name": "badge",
       "type": "string | number | undefined",
       "description": "Optional badge (count or short text)."
      },
      {
       "name": "expanded",
       "type": "boolean",
       "description": "Whether nested children are expanded (two-way).",
       "model": true,
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "expandedChange",
       "type": "boolean",
       "description": "Emits when `expanded` changes (two-way binding).",
       "model": true
      },
      {
       "name": "action",
       "type": "void",
       "description": "Emitted when a button-style item is activated."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/command-nav"
    },
    {
     "name": "MkNavList",
     "description": "Sidebar navigation list. Hosts `<mk-nav-item>`s and, when `collapsed`, drives\nthem into an icon-only rail (labels hidden, exposed via `title` tooltips).\nDesigned to sit inside the `mkAppSidebar` slot of `<mk-app-shell>`.\n\n```html\n<mk-nav-list [collapsed]=\"collapsed()\">\n  <mk-nav-item label=\"Dashboard\" href=\"/\" active>\n    <svg mkNavIcon>…</svg>\n  </mk-nav-item>\n</mk-nav-list>\n```",
     "file": "projects/mk-kit/navigation/nav-list/nav-list.ts",
     "kind": "component",
     "selector": "mk-nav-list",
     "selectors": [
      "mk-nav-list"
     ],
     "inputs": [
      {
       "name": "collapsed",
       "type": "boolean",
       "description": "Collapse items to icon-only. Read by descendant `MkNavItem`s.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/command-nav"
    },
    {
     "name": "MkPageHeader",
     "description": "PageHeader — the standard heading block at the top of an admin/CMS page: an\noptional breadcrumb, a page title with optional description and inline meta\n(badges/status), a right-aligned actions cluster, and an optional tab row\nbeneath. Everything but the title/description is projected, so it composes\nwith `mk-breadcrumb`, `mk-tabs`, buttons, badges, etc.\n\nSlots: `[mkPageHeaderBreadcrumb]`, `[mkPageHeaderMeta]` (beside the title),\n`[mkPageHeaderActions]` (right), `[mkPageHeaderTabs]` (below).\n\n```html\n<mk-page-header heading=\"Articles\" description=\"Manage your published posts.\">\n  <mk-breadcrumb mkPageHeaderBreadcrumb …></mk-breadcrumb>\n  <mk-badge mkPageHeaderMeta tone=\"success\">Live</mk-badge>\n  <div mkPageHeaderActions>\n    <button mkButton variant=\"outline\">Import</button>\n    <button mkButton>New article</button>\n  </div>\n</mk-page-header>\n```",
     "file": "projects/mk-kit/navigation/page-header/page-header.ts",
     "kind": "component",
     "selector": "mk-page-header",
     "selectors": [
      "mk-page-header"
     ],
     "inputs": [
      {
       "name": "heading",
       "type": "string",
       "description": "The page title (rendered as an `<h1>`).",
       "default": "''"
      },
      {
       "name": "description",
       "type": "string",
       "description": "Supporting description under the title.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/structure"
    },
    {
     "name": "MkPagination",
     "description": "Page navigation with previous/next controls and numbered pages that collapse\nto ellipses for large ranges. Provide either `total` (+ `pageSize`) or a\ndirect `pageCount`. `page` is 1-based and two-way bindable.\n\n```html\n<mk-pagination\n  [total]=\"240\"\n  [pageSize]=\"20\"\n  [(page)]=\"page\"\n  (pageChange)=\"load($event)\"\n/>\n```",
     "file": "projects/mk-kit/navigation/pagination/pagination.ts",
     "kind": "component",
     "selector": "mk-pagination",
     "selectors": [
      "mk-pagination"
     ],
     "inputs": [
      {
       "name": "total",
       "type": "number",
       "description": "Total number of items (used with `pageSize` when `pageCount` is unset).",
       "default": "0"
      },
      {
       "name": "pageSize",
       "type": "number",
       "description": "Items per page.",
       "default": "10"
      },
      {
       "name": "pageCount",
       "type": "number",
       "description": "Explicit page count; overrides `total`/`pageSize` when > 0.",
       "default": "0"
      },
      {
       "name": "page",
       "type": "number",
       "description": "Current 1-based page (two-way).",
       "model": true,
       "default": "1"
      },
      {
       "name": "siblingCount",
       "type": "number",
       "description": "Number of page buttons to keep on each side of the current page.",
       "default": "1"
      },
      {
       "name": "boundaryCount",
       "type": "number",
       "description": "Number of page buttons pinned at each end.",
       "default": "1"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible label for the navigation landmark.",
       "default": "this.i18n.paginationLabel"
      }
     ],
     "outputs": [
      {
       "name": "pageChange",
       "type": "number",
       "description": "Emits when `page` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkScrollArea",
     "description": "ScrollArea — a scroll container that hides the native scrollbar and renders\nits own themed overlay bars (à la Radix ScrollArea). The projected content\nscrolls inside a real, keyboard-focusable viewport, so native wheel / arrow\nscrolling keeps working; the custom bars are decorative (`aria-hidden`) and\ndraggable.\n\n```html\n<mk-scroll-area maxHeight=\"20rem\">\n  <p>…lots of content…</p>\n</mk-scroll-area>\n```\n\nSet `orientation` to `horizontal` / `both` for a horizontal bar, and\n`hideDelay` to auto-hide the bars after inactivity (`0` = always visible).",
     "file": "projects/mk-kit/navigation/scroll-area/scroll-area.ts",
     "kind": "component",
     "selector": "mk-scroll-area",
     "selectors": [
      "mk-scroll-area"
     ],
     "inputs": [
      {
       "name": "maxHeight",
       "type": "string",
       "description": "Optional CSS max-height for the viewport, e.g. `'20rem'`.",
       "default": "''"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible name for the scrollable viewport. When set, the viewport is\nexposed as a labelled `region` landmark — recommended, since the viewport\nis keyboard-focusable (`tabindex=\"0\"`) and a focusable scroll container\nshould have an accessible name. When empty, no role / label is added.",
       "default": "''"
      },
      {
       "name": "orientation",
       "type": "MkScrollAreaOrientation",
       "description": "Which axes render a custom bar.",
       "default": "'vertical'"
      },
      {
       "name": "hideDelay",
       "type": "number",
       "description": "Auto-hide the bars after this many ms of inactivity (`0` = always on).",
       "default": "1000"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/structure"
    },
    {
     "name": "MkSplitButton",
     "description": "SplitButton — a primary action with an attached menu of alternatives.\nThe main segment emits `action`; the chevron segment is a menu button\n(`mkMenuTriggerFor`) for the `mk-menu` passed in `[menu]`, with the full\nkeyboard model of the menu trigger (ArrowDown / Enter / Space open and focus\nthe first item, ArrowUp the last, Escape closes).\n\nBoth segments share `variant`, `tone` and `size`; `disabled` disables both,\n`loading` shows the main segment's spinner and disables the chevron.\n\n```html\n<mk-split-button [menu]=\"saveMenu\" tone=\"primary\" (action)=\"save()\">\n  Save\n</mk-split-button>\n<mk-menu #saveMenu>\n  <mk-menu-item (action)=\"saveAs()\">Save as…</mk-menu-item>\n  <mk-menu-item (action)=\"saveTemplate()\">Save as template</mk-menu-item>\n</mk-menu>\n```",
     "file": "projects/mk-kit/navigation/split-button/split-button.ts",
     "kind": "component",
     "selector": "mk-split-button",
     "selectors": [
      "mk-split-button"
     ],
     "inputs": [
      {
       "name": "menu",
       "type": "MkMenu",
       "description": "The menu the chevron segment opens.",
       "required": true
      },
      {
       "name": "variant",
       "type": "MkVariant",
       "description": "Visual treatment shared by both segments.",
       "default": "'solid'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone shared by both segments.",
       "default": "'primary'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size shared by both segments.",
       "default": "'md'"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable both segments.",
       "default": "false"
      },
      {
       "name": "loading",
       "type": "boolean",
       "description": "Spinner on the main segment; the menu segment is disabled meanwhile.",
       "default": "false"
      },
      {
       "name": "fullWidth",
       "type": "boolean",
       "description": "Stretch to the container width (the main segment grows).",
       "default": "false"
      },
      {
       "name": "type",
       "type": "\"submit\" | \"button\"",
       "description": "`type` of the main segment — `submit` to submit the enclosing form.",
       "default": "'button'"
      },
      {
       "name": "menuLabel",
       "type": "string",
       "description": "Accessible name of the chevron segment.",
       "default": "this.i18n.moreActions"
      }
     ],
     "outputs": [
      {
       "name": "action",
       "type": "void",
       "description": "Emitted when the main segment is activated (not while disabled/loading)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/buttons"
    },
    {
     "name": "MkSplitter",
     "description": "Splitter — two resizable panes with a draggable, keyboard-operable separator\n(ARIA `separator` with `aria-valuenow`). `horizontal` places the panes\nside-by-side (a vertical handle); `vertical` stacks them (a horizontal\nhandle). The start pane's size is a two-way `position` model (percent).\n\nProject the panes with `mkSplitterStart` / `mkSplitterEnd`:\n```html\n<mk-splitter [(position)]=\"split\" [min]=\"20\">\n  <nav mkSplitterStart>…</nav>\n  <main mkSplitterEnd>…</main>\n</mk-splitter>\n```\nDrag the handle, or focus it and use Arrow keys (Home/End jump to min/max).",
     "file": "projects/mk-kit/navigation/splitter/splitter.ts",
     "kind": "component",
     "selector": "mk-splitter",
     "selectors": [
      "mk-splitter"
     ],
     "inputs": [
      {
       "name": "orientation",
       "type": "MkSplitterOrientation",
       "description": "`horizontal` = side-by-side; `vertical` = stacked.",
       "default": "'horizontal'"
      },
      {
       "name": "position",
       "type": "number",
       "description": "Two-way position of the separator = start-pane size, in percent (0–100).",
       "model": true,
       "default": "50"
      },
      {
       "name": "min",
       "type": "number",
       "description": "Minimum start-pane size (percent).",
       "default": "10"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Maximum start-pane size (percent).",
       "default": "90"
      },
      {
       "name": "step",
       "type": "number",
       "description": "Keyboard resize increment (percent).",
       "default": "5"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable resizing.",
       "default": "false"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the separator.",
       "default": "this.i18n.resizePanes"
      }
     ],
     "outputs": [
      {
       "name": "positionChange",
       "type": "number",
       "description": "Emits when `position` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/structure"
    },
    {
     "name": "MkStep",
     "description": "A single step + its content panel. Declared inside `<mk-stepper>`; the\nprojected content becomes the step body while `label` (and optional\n`description`) render in the step header.\n\n`completed` is a two-way model so a parent can gate a `linear` stepper:\n`<mk-step label=\"Details\" [(completed)]=\"detailsValid()\">`.\n\n```html\n<mk-stepper linear>\n  <mk-step label=\"Account\" [completed]=\"form.valid\">…</mk-step>\n  <mk-step label=\"Payment\" optional>…</mk-step>\n</mk-stepper>\n```",
     "file": "projects/mk-kit/navigation/stepper/step.ts",
     "kind": "component",
     "selector": "mk-step",
     "selectors": [
      "mk-step"
     ],
     "inputs": [
      {
       "name": "label",
       "type": "string",
       "description": "Title shown in the step header.",
       "default": "''"
      },
      {
       "name": "description",
       "type": "string",
       "description": "Optional secondary line under the label.",
       "default": "''"
      },
      {
       "name": "optional",
       "type": "boolean",
       "description": "Marks the step optional (skippable in a `linear` stepper).",
       "default": "false"
      },
      {
       "name": "completed",
       "type": "boolean",
       "description": "Whether the step is complete (two-way; drives `linear` gating + the ✓).",
       "model": true,
       "default": "false"
      },
      {
       "name": "hasError",
       "type": "boolean",
       "description": "Show the error state in the header (e.g. failed validation).",
       "default": "false"
      },
      {
       "name": "editable",
       "type": "boolean",
       "description": "Allow returning to this step after it is completed.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "completedChange",
       "type": "boolean",
       "description": "Emits when `completed` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "headerId",
       "type": "string",
       "description": "Stable id for the header button (wires `aria-labelledby`).",
       "readonly": true
      },
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id for the panel (wires `aria-controls`).",
       "readonly": true
      },
      {
       "name": "active",
       "type": "WritableSignal<boolean>",
       "description": "Whether this step is currently selected. Set by the parent `MkStepper`.",
       "readonly": true
      }
     ],
     "queries": [
      {
       "name": "content",
       "kind": "viewChild",
       "type": "TemplateRef<any>",
       "description": "The step body, captured so `MkStepper` can render it in the position the\norientation calls for. The host element itself stays empty — the panel\nwrapper (and its role/aria) belongs to the stepper, which is the only\nplace that knows whether this is a tab panel or a disclosure region."
      }
     ],
     "docs": "/components/stepper"
    },
    {
     "name": "MkStepper",
     "description": "Stepper — walks a user through an ordered sequence of `<mk-step>`s with an\naccessible header rail (ARIA `tablist` + roving tabindex, Arrow/Home/End\nnavigation) and a single visible panel.\n\nIn `linear` mode a step is only reachable once every preceding required\n(non-`optional`) step reports `completed`. Drive completion from your form\nstate and move with the `next()` / `previous()` / `reset()` API or by\nclicking a reachable header.\n\n```html\n<mk-stepper #s linear [(selectedIndex)]=\"index\">\n  <mk-step label=\"Account\" [completed]=\"accountValid()\">…</mk-step>\n  <mk-step label=\"Address\" [completed]=\"addressValid()\">…</mk-step>\n  <mk-step label=\"Review\">…</mk-step>\n</mk-stepper>\n<button mkButton (click)=\"s.previous()\">Back</button>\n<button mkButton (click)=\"s.next()\">Next</button>\n```",
     "file": "projects/mk-kit/navigation/stepper/stepper.ts",
     "kind": "component",
     "selector": "mk-stepper",
     "selectors": [
      "mk-stepper"
     ],
     "inputs": [
      {
       "name": "selectedIndex",
       "type": "number",
       "description": "Zero-based index of the active step (two-way).",
       "model": true,
       "default": "0"
      },
      {
       "name": "orientation",
       "type": "MkStepperOrientation",
       "description": "Header rail orientation.",
       "default": "'horizontal'"
      },
      {
       "name": "linear",
       "type": "boolean",
       "description": "Enforce sequential completion before a step becomes reachable.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "selectedIndexChange",
       "type": "number",
       "description": "Emits when `selectedIndex` changes (two-way binding).",
       "model": true
      },
      {
       "name": "selectionChange",
       "type": "number",
       "description": "Emits the newly selected index whenever the active step changes."
      }
     ],
     "methods": [
      {
       "name": "isReachable",
       "signature": "(index: number): boolean",
       "description": "Whether a step can be selected. In linear mode every earlier required step\nmust be completed; a completed step is reachable only when `editable`."
      },
      {
       "name": "next",
       "signature": "(): void",
       "description": "Advance to the next reachable step, if any."
      },
      {
       "name": "previous",
       "signature": "(): void",
       "description": "Return to the previous step, if any."
      },
      {
       "name": "reset",
       "signature": "(): void",
       "description": "Reset to the first step and clear every step's completed flag."
      }
     ],
     "properties": [],
     "queries": [
      {
       "name": "steps",
       "kind": "contentChildren",
       "type": "readonly MkStep[]",
       "description": "Projected steps, kept live via a signal content query."
      }
     ],
     "docs": "/components/stepper"
    },
    {
     "name": "MkTab",
     "description": "A single tab + its panel. Declared inside `<mk-tabs>`; the projected content\nbecomes the tab panel body while `label` is rendered in the tablist.\n\n```html\n<mk-tabs>\n  <mk-tab label=\"Overview\">…panel content…</mk-tab>\n  <mk-tab label=\"Settings\" [disabled]=\"locked()\">…</mk-tab>\n</mk-tabs>\n```",
     "file": "projects/mk-kit/navigation/tabs/tab.ts",
     "kind": "component",
     "selector": "mk-tab",
     "selectors": [
      "mk-tab"
     ],
     "inputs": [
      {
       "name": "label",
       "type": "string",
       "description": "Text shown on the tab button in the tablist.",
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable selection of this tab.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "tabId",
       "type": "string",
       "description": "Stable id for the tab button (wires `aria-labelledby`).",
       "readonly": true
      },
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id for the panel (wires `aria-controls`).",
       "readonly": true
      },
      {
       "name": "active",
       "type": "WritableSignal<boolean>",
       "description": "Whether this tab is currently selected. Set by the parent `MkTabs`.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkTabs",
     "description": "Accessible tabs implementing the ARIA tabs pattern: a `role=\"tablist\"` with\nroving tabindex, Arrow/Home/End keyboard navigation and an animated active\nindicator. Selection is two-way bindable via `selectedIndex`.\n\n```html\n<mk-tabs [(selectedIndex)]=\"tab\" variant=\"line\">\n  <mk-tab label=\"Profile\">…</mk-tab>\n  <mk-tab label=\"Billing\">…</mk-tab>\n</mk-tabs>\n```",
     "file": "projects/mk-kit/navigation/tabs/tabs.ts",
     "kind": "component",
     "selector": "mk-tabs",
     "selectors": [
      "mk-tabs"
     ],
     "inputs": [
      {
       "name": "selectedIndex",
       "type": "number",
       "description": "Zero-based index of the active tab (two-way).",
       "model": true,
       "default": "0"
      },
      {
       "name": "variant",
       "type": "MkTabsVariant",
       "description": "`line` shows an underline indicator; `pill` uses filled pills.",
       "default": "'line'"
      }
     ],
     "outputs": [
      {
       "name": "selectedIndexChange",
       "type": "number",
       "description": "Emits when `selectedIndex` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [
      {
       "name": "tabs",
       "kind": "contentChildren",
       "type": "readonly MkTab[]",
       "description": "Projected tabs, kept live via a signal content query."
      }
     ],
     "docs": "/components/navigation"
    },
    {
     "name": "MkToolbar",
     "description": "Toolbar — a horizontal action bar: content flows on the start side, anything\nmarked `mkToolbarEnd` is pushed to the end. Handy above tables and lists for\na title/search on the left and actions on the right.\n\nThe projected controls are ordinary tab stops (no roving focus), so this is a\nlayout container, not an ARIA `toolbar` widget.\n\n```html\n<mk-toolbar bordered aria-label=\"Users actions\">\n  <strong>Users</strong>\n  <span mkToolbarEnd>\n    <button mkButton variant=\"outline\">Export</button>\n    <button mkButton>New user</button>\n  </span>\n</mk-toolbar>\n```",
     "file": "projects/mk-kit/navigation/toolbar/toolbar.ts",
     "kind": "component",
     "selector": "mk-toolbar",
     "selectors": [
      "mk-toolbar"
     ],
     "inputs": [
      {
       "name": "bordered",
       "type": "boolean",
       "description": "Wrap the bar in a themed, bordered surface.",
       "default": "false"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name (also promotes the bar to an ARIA `group`).",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/structure"
    },
    {
     "name": "MkTree",
     "description": "Tree — renders hierarchical data following the ARIA tree pattern\n(`role=\"tree\"` / `treeitem` with `aria-level`, `aria-expanded`,\n`aria-selected`). Supply `nodes`; expansion is managed internally.\n\nKeyboard: Up/Down move between visible rows, Right expands (or steps into the\nfirst child), Left collapses (or steps out to the parent), Home/End jump, and\nEnter/Space toggles expansion and selects (when `selectable`). A single\nroving tabindex keeps the whole tree one tab stop.\n\n```html\n<mk-tree selectable [nodes]=\"tree\" [(selected)]=\"picked\"\n  (selectionChange)=\"onPick($event)\" />\n```",
     "file": "projects/mk-kit/navigation/tree/tree.ts",
     "kind": "component",
     "selector": "mk-tree",
     "selectors": [
      "mk-tree"
     ],
     "inputs": [
      {
       "name": "nodes",
       "type": "readonly MkTreeNode[]",
       "description": "The hierarchical data to render.",
       "default": "[]"
      },
      {
       "name": "selectable",
       "type": "boolean",
       "description": "Allow choosing a node (adds selection styling + `aria-selected`).",
       "default": "false"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name for the tree.",
       "default": "''"
      },
      {
       "name": "selected",
       "type": "unknown",
       "description": "Two-way selected value (a node's `value`, or the node itself if unset).",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "selectedChange",
       "type": "unknown",
       "description": "Emits when `selected` changes (two-way binding).",
       "model": true
      },
      {
       "name": "selectionChange",
       "type": "unknown",
       "description": "Emits the selected value whenever the selection changes."
      },
      {
       "name": "nodeToggle",
       "type": "MkTreeNode",
       "description": "Emits a node whenever it is expanded or collapsed."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/tree"
    },
    {
     "name": "MkAccordionHeader",
     "description": "Marks projected content as the header of an `<mk-accordion-item>`. Use when\nthe header needs rich markup instead of the plain-text `header` input.\n\n```html\n<mk-accordion-item>\n  <span mkAccordionHeader><mk-icon name=\"user\" /> Account</span>\n  …body…\n</mk-accordion-item>\n```",
     "file": "projects/mk-kit/navigation/accordion/accordion-header.ts",
     "kind": "directive",
     "selector": "[mkAccordionHeader]",
     "selectors": [
      "mkAccordionHeader"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkFabAction",
     "description": "A speed-dial action button projected into `MkFab`.",
     "file": "projects/mk-kit/navigation/fab/fab.ts",
     "kind": "directive",
     "selector": "[mkFabAction]",
     "selectors": [
      "mkFabAction"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkMenuTrigger",
     "description": "Turns its host button into a trigger for an `<mk-menu>`. Wires\n`aria-haspopup=\"menu\"` / `aria-expanded` / `aria-controls`, toggles on click,\nopens on ArrowDown / Enter / Space (focusing the first item) and on ArrowUp\n(focusing the last item, per the APG menu-button pattern), and closes on\nEscape. When the menu is already open — e.g. after a mouse click, which\ndeliberately leaves focus on the trigger — ArrowDown moves focus to the\nfirst item and ArrowUp to the last, so the keyboard is never dead.\n\n```html\n<button mkButton [mkMenuTriggerFor]=\"menu\">Actions</button>\n<mk-menu #menu>…</mk-menu>\n```",
     "file": "projects/mk-kit/navigation/menu/menu-trigger.ts",
     "kind": "directive",
     "selector": "[mkMenuTriggerFor]",
     "selectors": [
      "mkMenuTriggerFor"
     ],
     "exportAs": "mkMenuTrigger",
     "inputs": [
      {
       "name": "mkMenuTriggerFor",
       "type": "MkMenu",
       "description": "The menu instance to control.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/navigation"
    },
    {
     "name": "MkAppLink",
     "description": "One app in the switcher.",
     "file": "projects/mk-kit/navigation/app-switcher/app-switcher.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": "Stable id; `current` matches on it (or on `url`)."
      },
      {
       "name": "name",
       "type": "string",
       "description": ""
      },
      {
       "name": "url",
       "type": "string",
       "description": ""
      },
      {
       "name": "description",
       "type": "string | undefined",
       "description": "One line under the name.",
       "optional": true
      },
      {
       "name": "icon",
       "type": "string | undefined",
       "description": "A short glyph for the tile — an emoji or one or two letters. Defaults to the name's initial.",
       "optional": true
      },
      {
       "name": "color",
       "type": "string | undefined",
       "description": "Tile colour; any CSS colour. Defaults to the primary tone.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkCommand",
     "description": "A single actionable entry in the `MkCommandPalette`.",
     "file": "projects/mk-kit/navigation/command-palette/command-palette.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": "Stable unique id."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Text shown (and the primary search target)."
      },
      {
       "name": "group",
       "type": "string | undefined",
       "description": "Optional section heading this command is grouped under.",
       "optional": true
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "Secondary text shown after the label.",
       "optional": true
      },
      {
       "name": "icon",
       "type": "string | undefined",
       "description": "Name of a registered icon (see `MkIconRegistry`).",
       "optional": true
      },
      {
       "name": "keywords",
       "type": "string | undefined",
       "description": "Extra search terms (not shown).",
       "optional": true
      },
      {
       "name": "shortcut",
       "type": "string | undefined",
       "description": "Display-only shortcut hint, e.g. `⌘S`.",
       "optional": true
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Disable the command (skipped by keyboard, not runnable).",
       "optional": true
      },
      {
       "name": "run",
       "type": "(() => void) | undefined",
       "description": "Invoked when the command is chosen.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTreeNode",
     "description": "A node in an `MkTree`. `children` makes it expandable.",
     "file": "projects/mk-kit/navigation/tree/tree.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Text shown for the node."
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Value bound to the selection when the node is chosen (defaults to the node).",
       "optional": true
      },
      {
       "name": "children",
       "type": "MkTreeNode[] | undefined",
       "description": "Child nodes; a non-empty array makes the node a parent (expandable).",
       "optional": true
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Disable selection/toggling of this node (still focusable).",
       "optional": true
      },
      {
       "name": "expanded",
       "type": "boolean | undefined",
       "description": "Expand this node initially.",
       "optional": true
      },
      {
       "name": "icon",
       "type": "string | undefined",
       "description": "Optional leading glyph (any short string / emoji).",
       "optional": true
      },
      {
       "name": "iconName",
       "type": "string | undefined",
       "description": "Name of a registered icon (see `MkIconRegistry`), rendered with `mk-icon`; wins over `icon`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDrawerSide",
     "description": "Edge the drawer slides in from.",
     "file": "projects/mk-kit/navigation/drawer/drawer.ts",
     "kind": "type",
     "definition": "'start' | 'end' | 'top' | 'bottom'"
    },
    {
     "name": "MkFabPosition",
     "description": "Corner placement for a fixed `MkFab`. `static` renders it inline.",
     "file": "projects/mk-kit/navigation/fab/fab.ts",
     "kind": "type",
     "definition": "| 'bottom-end' | 'bottom-start' | 'top-end' | 'top-start' | 'static'"
    },
    {
     "name": "MkPageItem",
     "description": "A rendered pagination cell: a real page number or a gap marker.",
     "file": "projects/mk-kit/navigation/pagination/pagination.ts",
     "kind": "type",
     "definition": "number | 'ellipsis'"
    },
    {
     "name": "MkScrollAreaOrientation",
     "description": "Which axes get a custom scrollbar for `MkScrollArea`.",
     "file": "projects/mk-kit/navigation/scroll-area/scroll-area.ts",
     "kind": "type",
     "definition": "'vertical' | 'horizontal' | 'both'"
    },
    {
     "name": "MkSplitterOrientation",
     "description": "Split direction for `MkSplitter`.",
     "file": "projects/mk-kit/navigation/splitter/splitter.ts",
     "kind": "type",
     "definition": "'horizontal' | 'vertical'"
    },
    {
     "name": "MkStepperOrientation",
     "description": "Orientation of the step header rail.",
     "file": "projects/mk-kit/navigation/stepper/stepper.ts",
     "kind": "type",
     "definition": "'horizontal' | 'vertical'"
    },
    {
     "name": "MkTabsVariant",
     "description": "Visual style for the tablist.",
     "file": "projects/mk-kit/navigation/tabs/tabs.ts",
     "kind": "type",
     "definition": "'line' | 'pill'"
    }
   ]
  },
  {
   "name": "forms",
   "import": "@mk-kit/ui/forms",
   "exports": [
    {
     "name": "MkAutocomplete",
     "description": "Autocomplete — an accessible text input that suggests options as the user\ntypes, implementing the ARIA combobox (`aria-autocomplete=\"list\"`) pattern\nwith a popup listbox.\n\nFiltering is built in (`contains` / `startsWith`); set `filterMode=\"none\"`\nand drive `options` yourself from the `search` output for async/server-side\nsuggestions. Typing arbitrary text is allowed unless `requireSelection` is\nset, in which case the field clears on blur if it doesn't match an option.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so it\nworks with `[(ngModel)]`, reactive forms and `[(value)]`. When nested in an\n`mk-form-field` it inherits size, label, hint/error and required wiring.\n\n```html\n<mk-autocomplete placeholder=\"Search users\"\n  [options]=\"filtered()\"\n  filterMode=\"none\"\n  (search)=\"query.set($event)\"\n  [(value)]=\"userId\" />\n```",
     "file": "projects/mk-kit/forms/autocomplete/autocomplete.ts",
     "kind": "component",
     "selector": "mk-autocomplete",
     "selectors": [
      "mk-autocomplete"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when the control is used without an `mk-form-field` label.",
       "default": "''"
      },
      {
       "name": "options",
       "type": "readonly MkAutocompleteOption[]",
       "description": "",
       "default": "[]"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when the input is empty.",
       "default": "''"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "filterMode",
       "type": "MkAutocompleteFilterMode",
       "description": "How the option list is filtered against the typed text.",
       "default": "'contains'"
      },
      {
       "name": "minChars",
       "type": "number",
       "description": "Only open the list once this many characters have been typed.",
       "default": "0"
      },
      {
       "name": "loading",
       "type": "boolean",
       "description": "Show a loading row instead of \"no results\" (for async fetches).",
       "default": "false"
      },
      {
       "name": "requireSelection",
       "type": "boolean",
       "description": "Clear the input on blur unless the text matches a selectable option.",
       "default": "false"
      },
      {
       "name": "emptyMessage",
       "type": "string",
       "description": "Message shown when there are no matching options.",
       "default": "this.i18n.noResults"
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Two-way selected value (the `value` of the chosen option, or `null`).",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "search",
       "type": "string",
       "description": "Emits the current input text on every keystroke — drive async loading."
      },
      {
       "name": "optionSelected",
       "type": "MkAutocompleteOption",
       "description": "Emits the option whenever one is committed by click or Enter."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/selection"
    },
    {
     "name": "MkButtonToggle",
     "description": "A single segment inside an `mk-button-toggle-group`. Projected content is the\nlabel (text, an icon, or both). Its selected state and keyboard behaviour are\ndriven by the parent group.\n\n```html\n<mk-button-toggle value=\"bold\" aria-label=\"Bold\"><b>B</b></mk-button-toggle>\n```",
     "file": "projects/mk-kit/forms/button-toggle/button-toggle.ts",
     "kind": "component",
     "selector": "mk-button-toggle",
     "selectors": [
      "mk-button-toggle"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "unknown",
       "description": "The value contributed to the group's selection when this item is on.",
       "default": "undefined"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable just this item.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [
      {
       "name": "focus",
       "signature": "(): void",
       "description": "Move focus to this item's button. Called by the parent group."
      }
     ],
     "properties": [
      {
       "name": "selected",
       "type": "Signal<boolean>",
       "description": "Whether this item is currently selected (owned by the parent group).",
       "readonly": true
      },
      {
       "name": "isDisabled",
       "type": "Signal<boolean>",
       "description": "Disabled if the item or the whole group is disabled.",
       "readonly": true
      }
     ],
     "queries": []
    },
    {
     "name": "MkButtonToggleGroup",
     "description": "ButtonToggleGroup — a segmented control grouping one or more\n`mk-button-toggle` items into a single, keyboard-operable selection.\n\nIn single-select mode (default) the group is an ARIA `radiogroup`: exactly\none item is selected, Arrow keys move and select, and the selected item is\nthe tab stop. Set `multiple` to allow any number of items — the group\nbecomes a toolbar of independent `aria-pressed` buttons.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model. In\nsingle mode `value` is the chosen item's `value`; in multiple mode it is an\narray of the selected values.\n\n```html\n<mk-button-toggle-group [(value)]=\"view\" aria-label=\"View\">\n  <mk-button-toggle value=\"grid\">Grid</mk-button-toggle>\n  <mk-button-toggle value=\"list\">List</mk-button-toggle>\n</mk-button-toggle-group>\n```",
     "file": "projects/mk-kit/forms/button-toggle/button-toggle-group.ts",
     "kind": "component",
     "selector": "mk-button-toggle-group",
     "selectors": [
      "mk-button-toggle-group"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "multiple",
       "type": "boolean",
       "description": "Allow selecting any number of items (toolbar of `aria-pressed` buttons).",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size, applied to every item. Ignored inside an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone used for the selected fill.",
       "default": "'primary'"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the whole group.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name for the group (recommended).",
       "default": "''"
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Two-way selected value. Single mode: the chosen item's `value` (or `null`).\nMultiple mode: an array of selected values.",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "isSelected",
       "signature": "(toggle: MkButtonToggle): boolean",
       "description": "Whether a given item is part of the current selection."
      },
      {
       "name": "tabIndexFor",
       "signature": "(toggle: MkButtonToggle): number",
       "description": "`0` for the item that owns the tab stop, `-1` for the rest."
      },
      {
       "name": "select",
       "signature": "(toggle: MkButtonToggle): void",
       "description": "Toggle (multiple) or set (single) the selection for an item."
      },
      {
       "name": "onKeydown",
       "signature": "(event: KeyboardEvent, toggle: MkButtonToggle): void",
       "description": ""
      }
     ],
     "properties": [
      {
       "name": "effectiveSize",
       "type": "Signal<MkSize>",
       "description": "The size actually applied (the form field's when nested).",
       "readonly": true
      }
     ],
     "queries": [
      {
       "name": "toggles",
       "kind": "contentChildren",
       "type": "readonly MkButtonToggle[]",
       "description": "Live list of projected toggle items, in DOM order."
      }
     ],
     "docs": "/components/selection"
    },
    {
     "name": "MkCardNumberInput",
     "description": "CardNumberInput — a payment-card number field that groups digits with the\ndetected network's layout (16-digit `0000 0000 0000 0000`, Amex\n`0000 000000 00000`, Diners `0000 000000 0000`), shows the brand as a\nbadge, and validates the complete number with the Luhn checksum.\n\nThe form value is the raw digit string (no spaces). `brand()` exposes the\ndetected network (also via `(brandChange)`), and `valid()` reports\n`true`/`false` for a complete number passing/failing Luhn and `null` while\nempty or incomplete; invalid styling engages after the field was touched.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so\n`[(ngModel)]`, reactive forms and `[(value)]` all work.\n\n```html\n<mk-card-number-input [(ngModel)]=\"cardNumber\" />\n```",
     "file": "projects/mk-kit/forms/card-number-input/card-number-input.ts",
     "kind": "component",
     "selector": "mk-card-number-input",
     "selectors": [
      "mk-card-number-input"
     ],
     "exportAs": "mkCardNumberInput",
     "formControl": true,
     "inputs": [
      {
       "name": "showBrand",
       "type": "boolean",
       "description": "Show the detected brand as a badge inside the field.",
       "default": "true"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "'0000 0000 0000 0000'"
      },
      {
       "name": "value",
       "type": "string",
       "description": "Two-way card number, digits only (no spaces).",
       "model": true,
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "brandChange",
       "type": "MkCardBrand | null",
       "description": "Emits whenever the detected brand changes."
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `cardNumber` for a number failing the Luhn checksum (which\nincludes a half-typed one). An empty value passes; compose with\n`Validators.required` to reject it."
      }
     ],
     "properties": [
      {
       "name": "brand",
       "type": "Signal<MkCardBrand | null>",
       "description": "The detected card network, `null` while unrecognised.",
       "readonly": true
      },
      {
       "name": "valid",
       "type": "Signal<boolean | null>",
       "description": "`true` for a complete number passing Luhn, `false` for a complete number\nfailing it, `null` while empty or incomplete.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/payment"
    },
    {
     "name": "MkCascader",
     "description": "Cascader — a select whose choices are a hierarchy shown as side-by-side\ncolumns (region → country → city, category → subcategory, org unit → team).\nEach pick opens the next column; picking a leaf commits the whole path.\n\nThe value is the **path** of option values (`['eu', 'pl', 'krk']`) by\ndefault, or just the leaf's value with `valueMode=\"leaf\"`. Parents are only\nselectable with `selectParents` (a click on one then commits, and its\nchildren stay reachable).\n\nKeyboard: Up / Down move within a column, Right opens the children, Left\ngoes back, Enter / Space selects, typing jumps to a label, Escape closes.\n`expandTrigger=\"hover\"` opens columns on pointer hover as well as click.\n\nImplements `ControlValueAccessor` and a two-way `value` model.\n\n```html\n<mk-cascader [options]=\"regions\" [(value)]=\"location\" placeholder=\"Where?\" clearable />\n```",
     "file": "projects/mk-kit/forms/cascader/cascader.ts",
     "kind": "component",
     "selector": "mk-cascader",
     "selectors": [
      "mk-cascader"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "options",
       "type": "readonly MkCascaderOption[]",
       "description": "The hierarchy to choose from.",
       "default": "[]"
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Two-way value: the path of values (default) or the leaf value (`valueMode=\"leaf\"`).",
       "model": true,
       "default": "null"
      },
      {
       "name": "valueMode",
       "type": "\"path\" | \"leaf\"",
       "description": "Bind the full path of values (default) or only the chosen option's value.",
       "default": "'path'"
      },
      {
       "name": "selectParents",
       "type": "boolean",
       "description": "Allow committing a parent option (click / Enter on it) instead of leaves only.",
       "default": "false"
      },
      {
       "name": "expandTrigger",
       "type": "\"click\" | \"hover\"",
       "description": "Open the next column on click (default) or also on pointer hover.",
       "default": "'click'"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "",
       "default": "this.i18n.selectPlaceholder"
      },
      {
       "name": "separator",
       "type": "string",
       "description": "Text between the labels of the chosen path.",
       "default": "' / '"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "change",
       "type": "unknown",
       "description": "Emitted after the user commits or clears a value."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/selection"
    },
    {
     "name": "MkCheckbox",
     "description": "Checkbox — a themed checkbox built on a visually-hidden native\n`input[type=checkbox]` (so keyboard + form semantics are native) with a\ncustom box. Supports an `indeterminate` state and projects its label.\n\nImplements `ControlValueAccessor` with a two-way `checked` model, so it works\nwith `[(ngModel)]`, reactive forms and `[(checked)]`.\n\n```html\n<mk-checkbox [(ngModel)]=\"accepted\">Accept terms</mk-checkbox>\n<mk-checkbox [(checked)]=\"all\" [indeterminate]=\"some()\" tone=\"success\">\n  Select all\n</mk-checkbox>\n```",
     "file": "projects/mk-kit/checkbox/checkbox.ts",
     "kind": "component",
     "selector": "mk-checkbox",
     "selectors": [
      "mk-checkbox"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "checked",
       "type": "boolean",
       "description": "Two-way checked state.",
       "model": true,
       "default": "false"
      },
      {
       "name": "indeterminate",
       "type": "boolean",
       "description": "Two-way indeterminate (\"mixed\") state; cleared when the user toggles.",
       "model": true,
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`).",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone for the checked box.",
       "default": "'primary'"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible label when no text content is projected.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "checkedChange",
       "type": "boolean",
       "description": "Emits when `checked` changes (two-way binding).",
       "model": true
      },
      {
       "name": "indeterminateChange",
       "type": "boolean",
       "description": "Emits when `indeterminate` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `required` for an unchecked box when `[required]` is set, so\n`required` on the element behaves like `Validators.requiredTrue`."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/toggles"
    },
    {
     "name": "MkCodeEditor",
     "description": "CodeEditor — a lightweight, dependency-free code field with syntax\nhighlighting, JSON validation and pretty-printing. A `<textarea>` provides\nediting and a synced highlight layer sits behind it, so it stays fully\naccessible (real textarea semantics, `aria-invalid`, form-field wiring)\nwithout pulling in a heavyweight editor.\n\nWith `language=\"json\"` it validates on every change (exposing an inline error\n+ `(validate)` output) and offers `format()` to pretty-print. Ideal for a CMS\n`json` field or plugin/settings JSONB editing.\n\nKeyboard: Tab inserts `tabSize` spaces; press Escape then Tab to move focus\nout (so it is never a keyboard trap). Implements `ControlValueAccessor` over a\nstring value with a two-way `value` model.\n\n```html\n<mk-code-editor #editor language=\"json\" [(value)]=\"config\" [rows]=\"10\" />\n<button mkButton (click)=\"editor.format()\">Format</button>\n```",
     "file": "projects/mk-kit/forms/code-editor/code-editor.ts",
     "kind": "component",
     "selector": "mk-code-editor",
     "selectors": [
      "mk-code-editor"
     ],
     "exportAs": "mkCodeEditor",
     "formControl": true,
     "inputs": [
      {
       "name": "language",
       "type": "MkCodeLanguage",
       "description": "Language for highlighting + validation.",
       "default": "'plaintext'"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "''"
      },
      {
       "name": "readOnly",
       "type": "boolean",
       "description": "Render read-only (still focusable/selectable).",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling when used standalone.",
       "default": "false"
      },
      {
       "name": "rows",
       "type": "number",
       "description": "Visible rows (minimum height).",
       "default": "8"
      },
      {
       "name": "lineNumbers",
       "type": "boolean",
       "description": "Show a line-number gutter.",
       "default": "true"
      },
      {
       "name": "tabSize",
       "type": "number",
       "description": "Number of spaces inserted by Tab.",
       "default": "2"
      },
      {
       "name": "wrap",
       "type": "boolean",
       "description": "Soft-wrap long lines instead of scrolling horizontally.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label when used standalone (no form field).",
       "default": "''"
      },
      {
       "name": "value",
       "type": "string",
       "description": "Two-way editor content.",
       "model": true,
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "validate",
       "type": "MkCodeValidity",
       "description": "Emits the content validity whenever it changes (JSON only)."
      }
     ],
     "methods": [
      {
       "name": "parsed",
       "signature": "(): unknown",
       "description": "The parsed JSON value, or `undefined` when empty / invalid / plaintext."
      },
      {
       "name": "format",
       "signature": "(): void",
       "description": "Pretty-print valid JSON with `tabSize` indentation. No-op otherwise."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/forms"
    },
    {
     "name": "MkColorPicker",
     "description": "ColorPicker — a compact color control: a live swatch that opens the native OS\npicker, an editable hex field and an optional row of preset swatches.\n`ControlValueAccessor` + two-way `value` model over a hex string.\n\n```html\n<mk-color-picker [(value)]=\"brand\" [swatches]=\"palette\" />\n```",
     "file": "projects/mk-kit/forms/color-picker/color-picker.ts",
     "kind": "component",
     "selector": "mk-color-picker",
     "selectors": [
      "mk-color-picker"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "string",
       "description": "Two-way hex color value.",
       "model": true,
       "default": "'#000000'"
      },
      {
       "name": "swatches",
       "type": "readonly string[]",
       "description": "Preset swatches (hex strings).",
       "default": "[]"
      },
      {
       "name": "hexInput",
       "type": "boolean",
       "description": "Show the editable hex text field.",
       "default": "true"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling when standalone.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored inside an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the swatch trigger.",
       "default": "this.i18n.chooseColor"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/sliders"
    },
    {
     "name": "MkCurrencyInput",
     "description": "CurrencyInput — a money/amount field that formats itself with\n`Intl.NumberFormat`: thousands grouping live as the user types, the\ncurrency symbol as a fixed prefix/suffix (per locale), fraction digits\npadded to the currency's convention on blur (`1234,5` → `1 234,50 zł`).\nThe form value is always a plain `number` (or `null` when empty) — the\nlocale formatting never leaks into the data.\n\n`currency` takes an ISO 4217 code; omit it for a plain grouped decimal.\n`locale` defaults to the runtime locale. `decimals` overrides the\ncurrency's fraction digits; `min`/`max` clamp on blur.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so\n`[(ngModel)]`, reactive forms and `[(value)]` all work.\n\n```html\n<mk-currency-input currency=\"PLN\" [(ngModel)]=\"price\" />\n<mk-currency-input currency=\"USD\" [min]=\"0\" [(value)]=\"budget\" />\n```",
     "file": "projects/mk-kit/forms/currency-input/currency-input.ts",
     "kind": "component",
     "selector": "mk-currency-input",
     "selectors": [
      "mk-currency-input"
     ],
     "exportAs": "mkCurrencyInput",
     "formControl": true,
     "inputs": [
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when the control is used without an `mk-form-field` label.",
       "default": "''"
      },
      {
       "name": "currency",
       "type": "string",
       "description": "",
       "default": "''"
      },
      {
       "name": "locale",
       "type": "string | undefined",
       "description": "BCP 47 locale for separators/symbol; defaults to the runtime locale.",
       "default": "undefined"
      },
      {
       "name": "decimals",
       "type": "number | null",
       "description": "Max fraction digits; defaults to the currency's convention (else 2).",
       "default": "null"
      },
      {
       "name": "min",
       "type": "number | null",
       "description": "Clamp the value to at least this on blur.",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "number | null",
       "description": "Clamp the value to at most this on blur.",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "allowNegative",
       "type": "boolean",
       "description": "Allow a leading minus sign.",
       "default": "true"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "''"
      },
      {
       "name": "value",
       "type": "number | null",
       "description": "Two-way numeric value (`null` when empty).",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "number | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `min` / `max` against the `[min]` and `[max]` inputs, using the\nsame error shapes as `Validators.min` / `Validators.max`."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/payment"
    },
    {
     "name": "MkFileUpload",
     "description": "FileUpload — an accessible click-or-drag dropzone with multi-file support,\ntype/size/count validation, image thumbnails and per-file progress.\n\nProvide an `uploadFn` to stream each accepted file to your backend (it\nreports progress and resolves/rejects); with `autoUpload` (on by default when\nan `uploadFn` is set) files upload as soon as they are accepted. Without one,\nthe component just validates + tracks files and emits `filesSelected` for you\nto handle. The tracked list is a two-way `files` model so you can reset it.\n\nKeyboard: the dropzone is a button — Enter/Space opens the native picker.\nRejections are announced through a polite live region.\n\nImplements `ControlValueAccessor` and `Validator`, so it drops into a\nreactive form like any other control. The form value is `File[]` by default\n(`[valueFormat]=\"'item'\"` publishes the tracked `MkUploadFile[]` instead),\nand `accept` / `maxSize` / `maxFiles` are enforced as validation errors as\nwell as at pick time — a list written in from the model side is checked too.\n\n```html\n<mk-file-upload accept=\"image/*\" multiple [maxSize]=\"5_000_000\"\n  [uploadFn]=\"upload\" (filesSelected)=\"onFiles($event)\" [(files)]=\"files\" />\n\n<mk-file-upload formControlName=\"attachments\" accept=\".pdf\" [maxFiles]=\"3\" />\n```",
     "file": "projects/mk-kit/forms/file-upload/file-upload.ts",
     "kind": "component",
     "selector": "mk-file-upload",
     "selectors": [
      "mk-file-upload"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "accept",
       "type": "string",
       "description": "Native `accept` filter, e.g. `image/*` or `.pdf,.doc`.",
       "default": "''"
      },
      {
       "name": "multiple",
       "type": "boolean",
       "description": "Allow selecting more than one file.",
       "default": "false"
      },
      {
       "name": "maxSize",
       "type": "number",
       "description": "Maximum size per file in bytes (0 = unlimited).",
       "default": "0"
      },
      {
       "name": "maxFiles",
       "type": "number",
       "description": "Maximum number of files kept (0 = unlimited).",
       "default": "0"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling when used standalone.",
       "default": "false"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Primary dropzone prompt.",
       "default": "this.i18n.dropzoneLabel"
      },
      {
       "name": "hint",
       "type": "string",
       "description": "Secondary hint under the prompt (e.g. accepted types / size).",
       "default": "''"
      },
      {
       "name": "hideList",
       "type": "boolean",
       "description": "Hide the built-in file list (render your own from `files`).",
       "default": "false"
      },
      {
       "name": "uploadFn",
       "type": "MkUploadFn | null",
       "description": "Async upload handler. When set, files upload automatically.",
       "default": "null"
      },
      {
       "name": "autoUpload",
       "type": "boolean | undefined",
       "description": "Upload accepted files immediately. Defaults to true when `uploadFn` set.",
       "default": "undefined"
      },
      {
       "name": "valueFormat",
       "type": "MkUploadValueFormat",
       "description": "Shape of the value published to a bound form control.",
       "default": "'file'"
      },
      {
       "name": "files",
       "type": "MkUploadFile[]",
       "description": "The tracked files (two-way, so consumers can reset the list).",
       "model": true,
       "default": "[]"
      }
     ],
     "outputs": [
      {
       "name": "filesChange",
       "type": "MkUploadFile[]",
       "description": "Emits when `files` changes (two-way binding).",
       "model": true
      },
      {
       "name": "filesSelected",
       "type": "File[]",
       "description": "Emits the accepted `File`s each time files are added."
      },
      {
       "name": "rejected",
       "type": "MkUploadRejection[]",
       "description": "Emits rejected files with a reason."
      },
      {
       "name": "uploaded",
       "type": "MkUploadFile",
       "description": "Emits a file once its upload succeeds."
      },
      {
       "name": "removed",
       "type": "MkUploadFile",
       "description": "Emits a file when it is removed from the list."
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Applies the same `accept` / `maxSize` / `maxFiles` rules the dropzone\nenforces at pick time, so a list written in from the model side — which\nnever goes through that path — is checked too. An empty list passes;\ncompose with `Validators.required` to reject it."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/forms"
    },
    {
     "name": "MkFormErrorSummary",
     "description": "FormErrorSummary — an accessible summary of a form's validation errors,\nshown at the top of the form on a failed submit. Each entry links to its\nfield and focuses it on click. Following the WAI/GOV.UK pattern it is an\n`alert` region and, when the surrounding form is submitted with errors,\nfocus moves here automatically (opt out with `[autoFocus]=\"false\"`) so\nscreen-reader and keyboard users are taken straight to the problems. The\npublic `focus()` remains for manual flows (e.g. server-side errors).\n\n## Automatic collection\n\nPoint `form` at a `FormGroup` and the summary walks it itself: one entry per\ninvalid control, worded from the `validation` i18n table (override per key\nwith `errorMessages`). Pass `labels` to name the fields — without an entry\nthe control's path is used. Entries appear once the form is submitted;\n`showOn=\"always\"` lists them as soon as they exist.\n\nEach entry is linked to its field by locating the control in the DOM, so\n`formControlName` must be a static attribute (`formControlName=\"email\"`,\nthe usual form) rather than a binding.\n\n## Signal Forms\n\nPoint `field` at a Signal Forms root (`[field]=\"f\"`) instead of `form` and\nthe summary reads `errorSummary()` from the `FieldTree`: one entry per\ninvalid field, keyed by dotted path in `labels` / `errorMessages` like the\nreactive path. With the default `showOn=\"submit\"` an entry appears once its\nfield is touched — `submit()` marks every field touched, so a failed submit\nlists them all. Clicking an entry focuses the control bound with\n`[formField]`. When the summary sits inside the `<form>`, focus also moves\nto it after the form's `submit` event, as with `ngSubmit`.\n\n```html\n<form (submit)=\"save($event)\">\n  <mk-form-error-summary [field]=\"f\" [labels]=\"{ email: 'Email address' }\" />\n  …\n</form>\n```\n\n```html\n<!-- automatic -->\n<form [formGroup]=\"form\" (ngSubmit)=\"submit()\">\n  <mk-form-error-summary #summary [form]=\"form\"\n    [labels]=\"{ email: 'Email address', age: 'Age' }\" />\n  …\n</form>\n\n<!-- manual -->\n<mk-form-error-summary #summary [errors]=\"errors()\" />\n…\nonSubmit() { if (invalid) { this.errors.set(collect()); this.summary.focus(); } }\n```",
     "file": "projects/mk-kit/forms/form-error-summary/form-error-summary.ts",
     "kind": "component",
     "selector": "mk-form-error-summary",
     "selectors": [
      "mk-form-error-summary"
     ],
     "exportAs": "mkFormErrorSummary",
     "inputs": [
      {
       "name": "errors",
       "type": "readonly MkFormError[]",
       "description": "Errors to list explicitly. When non-empty this wins over `form`, so a form\ncan mix automatic collection with server-side errors by not setting it.",
       "default": "[]"
      },
      {
       "name": "form",
       "type": "AbstractControl<any, any, any> | null",
       "description": "Collect errors from this control tree instead of passing them in.",
       "default": "null"
      },
      {
       "name": "field",
       "type": "Field<unknown> | null",
       "description": "Collect errors from this Signal Forms field (usually the root returned by\n`form()`) instead of `form`. Entries are keyed by dotted path for `labels`.",
       "default": "null"
      },
      {
       "name": "labels",
       "type": "Readonly<Record<string, string>>",
       "description": "Field names for automatic entries, keyed by control path.",
       "default": "{}"
      },
      {
       "name": "errorMessages",
       "type": "Readonly<Record<string, string | ((err: any) => string)>> | null",
       "description": "Per-key wording for automatic entries, as on `mk-form-field`.",
       "default": "null"
      },
      {
       "name": "showOn",
       "type": "\"submit\" | \"always\"",
       "description": "When automatic entries appear. Defaults to after the form is submitted.",
       "default": "'submit'"
      },
      {
       "name": "summaryTitle",
       "type": "string",
       "description": "Heading shown above the list.",
       "default": "this.i18n.errorSummaryTitle"
      },
      {
       "name": "autoFocus",
       "type": "boolean",
       "description": "Move focus to the summary automatically when the surrounding form is\nsubmitted with errors (the WAI/GOV.UK pattern). Disable to drive focus\nyourself via the public `focus()`.",
       "default": "true"
      }
     ],
     "outputs": [],
     "methods": [
      {
       "name": "focus",
       "signature": "(): void",
       "description": "Move keyboard focus to the summary (call after a failed submit)."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/forms"
    },
    {
     "name": "MkFormField",
     "description": "FormField — an accessible wrapper that provides a real `<label>`, optional\nhint text, error text and a required indicator for any nested control\n(`input[mkInput]`, `mk-select`, `mk-checkbox`, …).\n\nIt generates stable ids (via `mkUniqueId`) and exposes them so nested\ncontrols can wire `aria-labelledby` / `aria-describedby` / `aria-invalid`\nautomatically by injecting this component. While an error shows, the hint is\nhidden and the error is announced through a `role=\"alert\"` region.\n\n## Automatic errors\n\nWhen the projected control is bound to a form (`formControlName`,\n`[formControl]` or `[(ngModel)]`) the field adopts its `NgControl` and shows\nthe first validation error by itself — no `[error]` binding needed. Messages\ncome from the `validation` i18n table and can be reworded per field with\n`errorMessages`. As with `mat-error`, an error only appears once the control\nis touched or dirty, or its form has been submitted; `errorOn` changes that.\n`required` and the disabled styling are derived from the control too.\n\n## Signal Forms\n\nThe same applies to a control bound with Signal Forms' `[formField]`\ndirective (`@angular/forms/signals`): the field adopts the projected\n`FormField` binding and reads `touched()` / `dirty()` / `invalid()` /\n`errors()` / `required()` / `disabled()` from its `FieldState`. Errors\nwritten by the schema (`required(p.email)`, `minLength(p.name, 2)`, …) are\nrendered through the same `validation` i18n table, a `message` supplied to\nthe schema rule wins over the table, and `errorMessages` / `errorOn` work\nunchanged. Calling `submit()` marks every field touched, so errors surface\non a failed submit exactly as with `formControlName`. When the control is\nnot projected (or lives deeper), point the field at it with `[field]`.\n\n```html\n<mk-form-field label=\"Email\">\n  <input mkInput type=\"email\" [formField]=\"f.email\" />\n</mk-form-field>\n\n<mk-form-field label=\"Country\" [field]=\"f.country\">\n  <mk-select [formField]=\"f.country\" [options]=\"countries\" />\n</mk-form-field>\n```\n\n```html\n<!-- automatic: message + required marker come from the validators -->\n<mk-form-field label=\"Email\">\n  <input mkInput type=\"email\" formControlName=\"email\" />\n</mk-form-field>\n\n<!-- per-field wording -->\n<mk-form-field label=\"Age\" [errorMessages]=\"{ min: 'You must be 18 or over' }\">\n  <mk-number-input formControlName=\"age\" [min]=\"18\" />\n</mk-form-field>\n\n<!-- fully manual: an explicit [error] always wins -->\n<mk-form-field label=\"Email\" hint=\"We never share it.\" required\n  [error]=\"emailError()\">\n  <input mkInput type=\"email\" [(ngModel)]=\"email\" />\n</mk-form-field>\n```",
     "file": "projects/mk-kit/forms/form-field/form-field.ts",
     "kind": "component",
     "selector": "mk-form-field",
     "selectors": [
      "mk-form-field"
     ],
     "inputs": [
      {
       "name": "label",
       "type": "string",
       "description": "Visible field label. Rendered as a real `<label for>`.",
       "default": "''"
      },
      {
       "name": "hint",
       "type": "string",
       "description": "Optional helper text shown below the control (hidden while an error shows).",
       "default": "''"
      },
      {
       "name": "error",
       "type": "string | null",
       "description": "Explicit error message. When non-null it overrides the automatic message\nderived from the projected control; `''` suppresses errors entirely.",
       "default": "null"
      },
      {
       "name": "errorMessages",
       "type": "Readonly<Record<string, string | ((err: any) => string)>> | null",
       "description": "Per-field wording for automatic errors, keyed by `ValidationErrors` key.\nEach value is either a fixed string or a function of the error payload.",
       "default": "null"
      },
      {
       "name": "errorOn",
       "type": "\"always\" | \"touched\" | \"dirty\"",
       "description": "When automatic errors become visible. `touched` (the default) matches\nMaterial: after the control is touched or dirty, or the form is submitted.\n`dirty` waits for an actual edit; `always` shows as soon as it is invalid.",
       "default": "'touched'"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Marks the field required (adds an indicator + `aria-required`). Derived\nfrom the projected control's validators when it is bound to a form.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Visually reflect a disabled control. Derived from the projected control\nwhen it is bound to a form.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size; nested controls inherit it.",
       "default": "'md'"
      },
      {
       "name": "labelPosition",
       "type": "\"top\" | \"float\"",
       "description": "Where the label sits: above the control (default), or `float` — inside\nthe control, sliding up once it is focused or has a value. Floating works\nwith `mkInput` / textarea and any control bound with `ngModel` or a\n`formControl`; the placeholder stays hidden until the label has moved.",
       "default": "'top'"
      },
      {
       "name": "field",
       "type": "Field<unknown> | null",
       "description": "Signal Forms field to read state from explicitly (`[field]=\"f.email\"`).\nNot needed when the projected control carries the `[formField]` binding —\nthe wrapper finds that itself; set it when the control is nested deeper\nor when the wrapper should follow a field it does not contain.",
       "default": "null"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "controlId",
       "type": "string",
       "description": "Id for the nested interactive control — adopt on your control element.",
       "readonly": true
      },
      {
       "name": "labelId",
       "type": "string",
       "description": "Id of the `<label>` element (for `aria-labelledby`).",
       "readonly": true
      },
      {
       "name": "hintId",
       "type": "string",
       "description": "Id of the hint element.",
       "readonly": true
      },
      {
       "name": "errorId",
       "type": "string",
       "description": "Id of the error element.",
       "readonly": true
      },
      {
       "name": "errorText",
       "type": "Signal<string | null>",
       "description": "The message actually rendered — an explicit `error` always wins.",
       "readonly": true
      },
      {
       "name": "hasError",
       "type": "Signal<boolean>",
       "description": "Whether the field currently has an error.",
       "readonly": true
      },
      {
       "name": "isRequired",
       "type": "Signal<boolean>",
       "description": "Required either explicitly or through the bound control's validators.",
       "readonly": true
      },
      {
       "name": "isDisabled",
       "type": "Signal<boolean>",
       "description": "Disabled either explicitly or through the bound control.",
       "readonly": true
      },
      {
       "name": "hintVisible",
       "type": "Signal<boolean>",
       "description": "Whether the hint should be shown (hidden while an error is present).",
       "readonly": true
      },
      {
       "name": "describedBy",
       "type": "Signal<string | null>",
       "description": "Space-separated id list for a nested control's `aria-describedby`,\nor `null` when there is nothing to describe.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/forms"
    },
    {
     "name": "MkI18nInput",
     "description": "I18nInput — one field that edits the same text in several languages.\n\nThe common alternative is stacking one input per language, which grows the\nform linearly with locale count and buries the field the author actually\ncares about. This shows a single input and a compact switcher, and marks\nwhich locales already have content so nothing is silently left untranslated.\n\nBinds a `Record<code, string>`, so it drops into reactive forms as one\ncontrol instead of a nested group:\n\n```html\n<mk-form-field label=\"Name\">\n  <mk-i18n-input formControlName=\"name\" [locales]=\"locales\" />\n</mk-form-field>\n```\n\n```ts\nlocales = [\n  { code: 'en', label: 'EN', name: 'English' },\n  { code: 'pl', label: 'PL', name: 'Polish' },\n];\n```",
     "file": "projects/mk-kit/forms/i18n-input/i18n-input.ts",
     "kind": "component",
     "selector": "mk-i18n-input",
     "selectors": [
      "mk-i18n-input"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "locales",
       "type": "readonly MkI18nLocale[]",
       "description": "Locales offered, in switcher order. The first is the initial tab.",
       "default": "[]"
      },
      {
       "name": "multiline",
       "type": "boolean",
       "description": "Render a textarea instead of a single-line input.",
       "default": "false"
      },
      {
       "name": "rows",
       "type": "number",
       "description": "Textarea rows (ignored unless `multiline`).",
       "default": "3"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder for the active locale's input.",
       "default": "''"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size, forwarded to the input and the switcher.",
       "default": "'md'"
      },
      {
       "name": "requiredLocales",
       "type": "readonly string[]",
       "description": "Locale codes that must be filled. They get a marker in the switcher while\nempty, so a missing translation is visible without switching to it.",
       "default": "[]"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the whole control.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkIbanInput",
     "description": "IbanInput — an international bank account number field: uppercases and\ngroups the number in blocks of four as the user types (`PL61 1090 1014 …`),\ncaps input at the country's exact length (65 countries built in) and\nvalidates with the ISO 13616 mod-97 checksum.\n\nThe form value is the compact electronic format (uppercase, no spaces).\n`valid()` (via `exportAs`) reports `true`/`false` for a complete number\npassing/failing validation and `null` while empty or incomplete; invalid\nstyling engages after the field was touched.\n`mkIbanValidator()` covers reactive forms.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so\n`[(ngModel)]`, reactive forms and `[(value)]` all work.\n\n```html\n<mk-iban-input [(ngModel)]=\"account\" />\n```",
     "file": "projects/mk-kit/forms/iban-input/iban-input.ts",
     "kind": "component",
     "selector": "mk-iban-input",
     "selectors": [
      "mk-iban-input"
     ],
     "exportAs": "mkIbanInput",
     "formControl": true,
     "inputs": [
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "'PL61 1090 1014 0000 0712 1981 2874'"
      },
      {
       "name": "value",
       "type": "string",
       "description": "Two-way IBAN in compact electronic format (uppercase, no spaces).",
       "model": true,
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `iban` for a number failing the mod-97 checksum — the same error\n`mkIbanValidator()` produces, so the two are interchangeable. An empty\nvalue passes; compose with `Validators.required` to reject it."
      }
     ],
     "properties": [
      {
       "name": "valid",
       "type": "Signal<boolean | null>",
       "description": "`true` for a complete IBAN passing the mod-97 check, `false` for a\ncomplete-but-wrong one (or an unknown country once 2+ chars are typed and\nthe field was left), `null` while empty or still incomplete.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/payment"
    },
    {
     "name": "MkInput",
     "description": "Input — enhances a native `<input>` or `<textarea>` with mk-kit theming and\na11y wiring. It is an attribute-selector component so all native semantics\nand keyboard behaviour come for free; this layers on tokenised styling, aria\nstate and form integration.\n\nIt provides its own `ControlValueAccessor` (over the native `value`) so\n`[(ngModel)]` and reactive forms write back to the DOM reliably — including\nwhen the bound model is reset programmatically. IME composition is buffered\nso `onChange` fires once per completed character, matching Angular's built-in\n`DefaultValueAccessor`.\n\nWhen placed inside an `mk-form-field` it automatically adopts the field's\ncontrol id (so the `<label for>` associates), `aria-describedby`,\n`aria-invalid` and `aria-required`.\n\n```html\n<input mkInput type=\"email\" placeholder=\"you@example.com\" />\n<textarea mkInput rows=\"4\" [invalid]=\"true\"></textarea>\n```",
     "file": "projects/mk-kit/forms/input/input.ts",
     "kind": "component",
     "selector": "input[mkInput], textarea[mkInput]",
     "selectors": [
      "mkInput"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field` (inherits it).",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkInputGroup",
     "description": "InputGroup — wraps a native `input[mkInput]` with leading / trailing affixes\n(icons, static text, compact buttons) inside one shared control frame. The\ngroup carries the border, background and focus ring; the nested input\ndetects the group and drops its own chrome, so the whole assembly reads as\na single field.\n\nProject affixes with the `mkInputPrefix` / `mkInputSuffix` attributes. Both\nare optional; interactive suffixes (a clear or scan button) keep their own\nfocus behaviour.\n\nInside an `mk-form-field` the group inherits the field's size and invalid\nstate, and the field's label association still targets the inner input.\n\n```html\n<mk-input-group>\n  <mk-icon mkInputPrefix name=\"search\" />\n  <input mkInput type=\"search\" placeholder=\"Search…\" />\n</mk-input-group>\n\n<mk-form-field label=\"Price\">\n  <mk-input-group>\n    <input mkInput type=\"number\" formControlName=\"price\" />\n    <span mkInputSuffix>zł</span>\n  </mk-input-group>\n</mk-form-field>\n```",
     "file": "projects/mk-kit/forms/input-group/input-group.ts",
     "kind": "component",
     "selector": "mk-input-group",
     "selectors": [
      "mk-input-group"
     ],
     "inputs": [
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field` (inherits it).",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Visually reflect a disabled inner control.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "effectiveSize",
       "type": "Signal<MkSize>",
       "description": "The size the group (and its nested input) renders at.",
       "readonly": true
      },
      {
       "name": "isInvalid",
       "type": "Signal<boolean>",
       "description": "Whether the group renders the invalid frame.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkListbox",
     "description": "Listbox — a standalone, always-visible selection list (the ARIA `listbox`\npattern) for one or many values: settings panes, \"choose a template\"\npickers, side-by-side assignments, any place a dropdown would hide choices\nthe user should see at once.\n\nKeyboard: Up / Down move, Home / End jump, PageUp / PageDown skip ten,\ntype to jump to a label, Enter / Space select (toggle when `multiple`),\nShift+Arrow / Shift+click extend a range, Ctrl/Cmd+A selects all. Focus\nstays on the list (`aria-activedescendant`). With `filterable`, a search\nbox above the list narrows it by label or description.\n\nImplements `ControlValueAccessor` and a two-way `value` model — a single\nvalue, or an array when `multiple`.\n\n```html\n<mk-listbox [options]=\"plans\" [(value)]=\"plan\" ariaLabel=\"Plan\" />\n<mk-listbox multiple filterable [options]=\"people\" [(ngModel)]=\"reviewers\" />\n```",
     "file": "projects/mk-kit/forms/listbox/listbox.ts",
     "kind": "component",
     "selector": "mk-listbox",
     "selectors": [
      "mk-listbox"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "options",
       "type": "readonly MkListboxOption[]",
       "description": "The rows to choose from.",
       "default": "[]"
      },
      {
       "name": "multiple",
       "type": "boolean",
       "description": "Allow several values; the model becomes an array.",
       "default": "false"
      },
      {
       "name": "filterable",
       "type": "boolean",
       "description": "Show a search box that narrows the list by label / description.",
       "default": "false"
      },
      {
       "name": "filterPlaceholder",
       "type": "string | undefined",
       "description": "",
       "default": "undefined"
      },
      {
       "name": "selectionFollowsFocus",
       "type": "boolean",
       "description": "Single-select only: moving with the arrow keys selects immediately\n(default `true`); `false` requires Enter / Space to commit.",
       "default": "true"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "ariaLabel",
       "type": "string | undefined",
       "description": "Accessible name when there is no visible label / form field.",
       "default": "undefined"
      },
      {
       "name": "ariaLabelledby",
       "type": "string | undefined",
       "description": "",
       "default": "undefined"
      },
      {
       "name": "emptyText",
       "type": "string | undefined",
       "description": "Text shown when no option matches the filter.",
       "default": "undefined"
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Two-way value: one value, or an array when `multiple`.",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "change",
       "type": "unknown",
       "description": "Emitted after the user changes the selection (not on programmatic writes)."
      }
     ],
     "methods": [
      {
       "name": "focus",
       "signature": "(): void",
       "description": "Focus the list."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/selection"
    },
    {
     "name": "MkMentionPanel",
     "description": "Suggestion listbox for `MkMention`. Created dynamically by the\ndirective and wired imperatively right after creation: the directive hands\nit read-only signals (options, active index, caret anchor point) plus plain\ncallbacks, so the panel re-renders reactively without `setInput` churn.\n\nThe `<ul>` is promoted to the top layer by `mkAnchoredPanel` and positioned\nat the caret point; this host element stays empty in place.\n\nNot intended for direct use — the public API is the `[mkMention]` directive.",
     "file": "projects/mk-kit/forms/mention/mention-panel.ts",
     "kind": "component",
     "selector": "mk-mention-panel",
     "selectors": [
      "mk-mention-panel"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [
      {
       "name": "optionId",
       "signature": "(index: number): string",
       "description": ""
      }
     ],
     "properties": [
      {
       "name": "anchorPoint",
       "type": "Signal<{ x: number; y: number; }>",
       "description": "Caret point (viewport px) the panel is anchored to.",
       "readonly": false
      },
      {
       "name": "anchorEl",
       "type": "HTMLElement | undefined",
       "description": "The mention control itself — passed as the anchored panel's element\nanchor so pointerdowns inside the control don't count as \"outside\"\ndismissals (the point anchor still wins for positioning).",
       "readonly": false
      }
     ],
     "queries": [
      {
       "name": "list",
       "kind": "viewChild",
       "type": "ElementRef<HTMLUListElement> | undefined",
       "description": "The teleported listbox element (used for the blur containment guard)."
      }
     ]
    },
    {
     "name": "MkMultiSelect",
     "description": "MultiSelect — an accessible combobox that commits **multiple** values,\nrendering each selection as a removable chip inside the control. Implements\nthe ARIA combobox + multiselectable listbox pattern.\n\nFiltering is built in (`contains` / `startsWith`); set `filterMode=\"none\"`\nand drive `options` from the `search` output for async / server-side sources.\nSelected options are remembered even after they leave the `options` list, so\nchips keep their labels across async pages.\n\nImplements `ControlValueAccessor` over an **array** value and exposes a\ntwo-way `value` model, so it works with `[(ngModel)]`, reactive forms and\n`[(value)]`. When nested in an `mk-form-field` it inherits size, label,\nhint/error and required wiring.\n\nKeyboard: type to filter, Up/Down to move, Home/End to jump, Enter/Space to\ntoggle the active option, Backspace on an empty query removes the last chip,\nEscape closes. The dropdown renders in the top layer via\n`MkAnchoredPanel` so it is never clipped by a container.\n\n```html\n<mk-multi-select placeholder=\"Add tags\"\n  [options]=\"tagOptions()\"\n  [(value)]=\"tags\" />\n```",
     "file": "projects/mk-kit/forms/multi-select/multi-select.ts",
     "kind": "component",
     "selector": "mk-multi-select",
     "selectors": [
      "mk-multi-select"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when the control is used without an `mk-form-field` label.",
       "default": "''"
      },
      {
       "name": "options",
       "type": "readonly MkMultiSelectOption[]",
       "description": "",
       "default": "[]"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when no value is selected.",
       "default": "''"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "filterMode",
       "type": "MkMultiSelectFilterMode",
       "description": "How the option list is filtered against the typed text.",
       "default": "'contains'"
      },
      {
       "name": "minChars",
       "type": "number",
       "description": "Only open the list once this many characters have been typed.",
       "default": "0"
      },
      {
       "name": "loading",
       "type": "boolean",
       "description": "Show a loading row instead of \"no results\" (for async fetches).",
       "default": "false"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Maximum number of selections (0 = unlimited).",
       "default": "0"
      },
      {
       "name": "closeOnSelect",
       "type": "boolean",
       "description": "Close the dropdown after each selection. Default keeps it open.",
       "default": "false"
      },
      {
       "name": "emptyMessage",
       "type": "string",
       "description": "Message shown when there are no matching options.",
       "default": "this.i18n.noResults"
      },
      {
       "name": "value",
       "type": "unknown[]",
       "description": "Two-way selected values.",
       "model": true,
       "default": "[]"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown[]",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "search",
       "type": "string",
       "description": "Emits the current query text on every keystroke — drive async loading."
      },
      {
       "name": "optionAdded",
       "type": "MkMultiSelectOption",
       "description": "Emits the option whenever one is added."
      },
      {
       "name": "optionRemoved",
       "type": "unknown",
       "description": "Emits the value whenever a selection is removed."
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMaxItems` when more options are selected than `[max]` allows."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/selection"
    },
    {
     "name": "MkNumberInput",
     "description": "NumberInput — a numeric field with −/+ stepper buttons, clamping and keyboard\nstepping (Arrow keys / Page keys). Implements the ARIA `spinbutton` pattern\nand `ControlValueAccessor` over `number | null`, with a two-way `value` model.\n\n```html\n<mk-number-input [(value)]=\"qty\" [min]=\"0\" [max]=\"99\" [step]=\"1\" />\n```",
     "file": "projects/mk-kit/forms/number-input/number-input.ts",
     "kind": "component",
     "selector": "mk-number-input",
     "selectors": [
      "mk-number-input"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when the control is used without an `mk-form-field` label.",
       "default": "''"
      },
      {
       "name": "min",
       "type": "number | null",
       "description": "",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "number | null",
       "description": "Maximum value.",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "step",
       "type": "number",
       "description": "Step increment for buttons + Arrow keys.",
       "default": "1"
      },
      {
       "name": "value",
       "type": "number | null",
       "description": "Two-way value.",
       "model": true,
       "default": "null"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder when empty.",
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling when standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored inside an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "number | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `min` / `max` against the `[min]` and `[max]` inputs, using the\nsame error shapes as `Validators.min` / `Validators.max`."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkNumericKeypad",
     "description": "Numeric keypad — a touch-first 3×4 digit pad for PIN entry, quantity entry\nand money amounts (POS-style). `ControlValueAccessor` + two-way `value`\nmodel; the value is a **string** in `pin` mode (leading zeros preserved)\nand a **number | null** in `quantity`/`amount` mode.\n\n- `pin`: masked echo row by default; `(submit)` fires automatically when\n  `length` digits are entered.\n- `quantity`: integer entry; the bottom-left key clears.\n- `amount`: decimal entry (value uses `.`; the echo shows\n  `decimalSeparator`); capped at `fractionDigits` fraction digits.\n\nA physical keyboard works anywhere inside the pad: digits, Backspace,\nDelete (clear), Enter (submit) and the decimal separator. Arrow keys move\nbetween the on-screen keys (roving tabindex).\n\n```html\n<mk-numeric-keypad mode=\"pin\" [length]=\"4\" (submit)=\"unlock($event)\" />\n<mk-numeric-keypad mode=\"quantity\" [min]=\"1\" [(value)]=\"qty\" />\n```",
     "file": "projects/mk-kit/forms/numeric-keypad/numeric-keypad.ts",
     "kind": "component",
     "selector": "mk-numeric-keypad",
     "selectors": [
      "mk-numeric-keypad"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "mode",
       "type": "MkNumericKeypadMode",
       "description": "Entry mode. Decides the value type and the bottom-left key.",
       "default": "'quantity'"
      },
      {
       "name": "length",
       "type": "number",
       "description": "PIN length (`pin` mode only). Reaching it emits `submit`.",
       "default": "4"
      },
      {
       "name": "min",
       "type": "number | null",
       "description": "Lower bound reported through the validator (`quantity`/`amount`).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "number | null",
       "description": "Upper bound reported through the validator (`quantity`/`amount`).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "mask",
       "type": "boolean",
       "description": "Mask the echo row in `pin` mode. Default `true`.",
       "default": "true"
      },
      {
       "name": "showValue",
       "type": "boolean",
       "description": "Show the echo row above the keys. Default `true`.",
       "default": "true"
      },
      {
       "name": "decimalSeparator",
       "type": "string",
       "description": "Echo-row separator for `amount` mode. The VALUE always uses `.`.",
       "default": "','"
      },
      {
       "name": "fractionDigits",
       "type": "number",
       "description": "Max fraction digits accepted in `amount` mode.",
       "default": "2"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the pad.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling.",
       "default": "false"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the pad.",
       "default": "this.i18n.numericKeypadLabel"
      },
      {
       "name": "value",
       "type": "string | number | null",
       "description": "Two-way value: `string` in `pin` mode, `number | null` otherwise.",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string | number | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "submit",
       "type": "string | number | null",
       "description": "Enter key / full PIN. Emits the current value."
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "`pin`: reports `minlength` while the code is incomplete (empty passes —\ncompose with `Validators.required`). `quantity`/`amount`: reports\n`min`/`max` against the bounds."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/touch-keys"
    },
    {
     "name": "MkOnScreenKeyboard",
     "description": "On-screen keyboard — a touch QWERTY panel for kiosk/till screens where no\nphysical keyboard exists. Anchored below its input in the browser top layer\n(via `MkAnchoredPanel`), it writes caret-aware into the target's\nnative value and dispatches `input` events, so `ngModel`/reactive forms\nstay in sync with no extra wiring.\n\nPair it with the `mkOnScreenKeyboardFor` directive, which opens the panel\non focus and suppresses the OS keyboard (`inputmode=\"none\"`):\n\n```html\n<input mkInput [mkOnScreenKeyboardFor]=\"kbd\" />\n<mk-on-screen-keyboard #kbd />\n```\n\nLayers: base (letters + digit row), shift (auto-resets after one\ncharacter) and an alternate layer (Polish diacritics + symbols in the\ndefault `MK_KEYBOARD_LAYOUT_QWERTY_PL`); pass `layout` for other\nlanguages. Enter inserts a newline in a `<textarea>` and emits `enter`\nfor single-line inputs. Keys are excluded from the tab order — physical\nkeyboards type into the input directly, the panel is a pointer surface.",
     "file": "projects/mk-kit/forms/on-screen-keyboard/on-screen-keyboard.ts",
     "kind": "component",
     "selector": "mk-on-screen-keyboard",
     "selectors": [
      "mk-on-screen-keyboard"
     ],
     "exportAs": "mkOnScreenKeyboard",
     "inputs": [
      {
       "name": "layout",
       "type": "MkKeyboardLayout",
       "description": "Key layout. Defaults to QWERTY with a Polish alternate layer.",
       "default": "MK_KEYBOARD_LAYOUT_QWERTY_PL"
      },
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": "Preferred placement relative to the input.",
       "default": "'bottom-start'"
      }
     ],
     "outputs": [
      {
       "name": "enter",
       "type": "void",
       "description": "Enter pressed on a single-line input (textareas insert a newline instead)."
      },
      {
       "name": "closed",
       "type": "void",
       "description": "Emitted whenever the keyboard closes (any reason)."
      }
     ],
     "methods": [
      {
       "name": "open",
       "signature": "(anchor: HTMLElement, target: MkOnScreenKeyboardTarget): void",
       "description": "Open anchored to `anchor`, typing into `target`."
      },
      {
       "name": "close",
       "signature": "(): void",
       "description": "Close the panel."
      }
     ],
     "properties": [
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id for `aria-controls` on the trigger.",
       "readonly": true
      },
      {
       "name": "opened",
       "type": "Signal<boolean>",
       "description": "Whether the panel is open.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/touch-keys"
    },
    {
     "name": "MkOtp",
     "description": "OTP — a segmented one-time-code input: N single-character boxes with automatic\nfocus advance, Backspace-to-previous, Arrow navigation and full-code paste.\n`ControlValueAccessor` + two-way `value` model over the concatenated string.\n\n```html\n<mk-otp [(value)]=\"code\" [length]=\"6\" />\n```",
     "file": "projects/mk-kit/forms/otp/otp.ts",
     "kind": "component",
     "selector": "mk-otp",
     "selectors": [
      "mk-otp"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "length",
       "type": "number",
       "description": "Number of character boxes.",
       "default": "6"
      },
      {
       "name": "type",
       "type": "\"number\" | \"text\"",
       "description": "Restrict input to digits (`number`) or allow any char (`text`).",
       "default": "'number'"
      },
      {
       "name": "mask",
       "type": "boolean",
       "description": "Mask entered characters (password style).",
       "default": "false"
      },
      {
       "name": "value",
       "type": "string",
       "description": "Two-way concatenated value.",
       "model": true,
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling when standalone.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored inside an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the group.",
       "default": "this.i18n.oneTimeCode"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `minlength` for a partially entered code. An empty value passes;\ncompose with `Validators.required` to reject it."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkPasswordInput",
     "description": "PasswordInput — a password field with a reveal toggle, an optional strength\nmeter and an optional rules checklist. Implements `ControlValueAccessor` over\n`string` with a two-way `value` model, and wires label / description /\nvalidity a11y automatically when nested in an `mk-form-field`.\n\n```html\n<mk-password-input [(value)]=\"pw\" showStrength showRules [minLength]=\"10\" />\n```",
     "file": "projects/mk-kit/forms/password-input/password-input.ts",
     "kind": "component",
     "selector": "mk-password-input",
     "selectors": [
      "mk-password-input"
     ],
     "exportAs": "mkPasswordInput",
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "string",
       "description": "Two-way value.",
       "model": true,
       "default": "''"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder when empty.",
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored inside an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling when standalone.",
       "default": "false"
      },
      {
       "name": "showStrength",
       "type": "boolean",
       "description": "Show the 0–4 strength meter below the field.",
       "default": "false"
      },
      {
       "name": "showRules",
       "type": "boolean",
       "description": "Show the rules checklist below the field.",
       "default": "false"
      },
      {
       "name": "minLength",
       "type": "number",
       "description": "Minimum length used by the strength score and rules.",
       "default": "8"
      },
      {
       "name": "autocomplete",
       "type": "(string & {}) | \"current-password\" | \"new-password\"",
       "description": "`autocomplete` for the native input. Use `'new-password'` on signup /\nchange-password forms (where the strength meter and rules belong) so the\nbrowser offers a generated password instead of the saved one.",
       "default": "'current-password'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `minlength` for a password shorter than `[minLength]` — the same\nrequirement the rules list shows. An empty value passes; compose with\n`Validators.required` to reject it."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/text-inputs"
    },
    {
     "name": "MkPhoneInput",
     "description": "PhoneInput — an international telephone field: a searchable country-prefix\ndropdown (flag + dial code) next to a national-number input that formats\nitself with the selected country's mask as the user types.\n\nThe form value is either a single E.164 string (`\"+48601234567\"`, default)\nor a structured object (`valueFormat=\"parts\"`) carrying the country, dial\ncode and national number separately; both modes read back either shape and\n`null` when empty. Pasting a full international number (`+44…`) into the\nnumber field switches the country automatically.\n\nImplements `ControlValueAccessor` and exposes two-way `value` and `country`\nmodels, so `[(ngModel)]`, reactive forms, `[(value)]` and `[(country)]` all\nwork.\n\n```html\n<mk-phone-input [(ngModel)]=\"phone\" country=\"PL\" />\n<mk-phone-input valueFormat=\"parts\" [preferredCountries]=\"['PL','DE','CZ']\"\n  [(value)]=\"phoneParts\" />\n```",
     "file": "projects/mk-kit/forms/phone-input/phone-input.ts",
     "kind": "component",
     "selector": "mk-phone-input",
     "selectors": [
      "mk-phone-input"
     ],
     "exportAs": "mkPhoneInput",
     "formControl": true,
     "inputs": [
      {
       "name": "countries",
       "type": "readonly MkPhoneCountry[]",
       "description": "The selectable country set (defaults to the built-in list).",
       "default": "MK_PHONE_COUNTRIES"
      },
      {
       "name": "preferredCountries",
       "type": "readonly string[]",
       "description": "ISO codes pinned, in order, to the top of the dropdown.",
       "default": "[]"
      },
      {
       "name": "valueFormat",
       "type": "\"e164\" | \"parts\"",
       "description": "Shape of the form value: an E.164 string or a structured object.",
       "default": "'e164'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder for the national-number field.",
       "default": "''"
      },
      {
       "name": "country",
       "type": "string",
       "description": "Two-way selected ISO country code.",
       "model": true,
       "default": "'US'"
      },
      {
       "name": "value",
       "type": "string | MkPhoneValue | null",
       "description": "Two-way form value (`string` in `e164` mode, `MkPhoneValue` in `parts`).",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "countryChange",
       "type": "string",
       "description": "Emits when `country` changes (two-way binding).",
       "model": true
      },
      {
       "name": "valueChange",
       "type": "string | MkPhoneValue | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/phone-postal"
    },
    {
     "name": "MkPostalCodeInput",
     "description": "PostalCodeInput — a postal/ZIP code field that masks, uppercases and\nvalidates itself for the given `country` (35+ built-in formats: `PL`\n`00-000`, `US` `00000[-0000]`, `CA` `A0A 0A0`, `NL` `0000 AA`, …).\nFree-format countries (e.g. `GB`) skip the mask and validate against the\nnational pattern instead, normalising the inward-code space on blur.\n\nThe placeholder defaults to a valid example for the country. `valid()`\n(via `exportAs`) reports `true`/`false` for a complete/incomplete code and\n`null` when empty or the country is unknown; invalid styling engages after\nthe field is touched.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so\n`[(ngModel)]`, reactive forms and `[(value)]` all work.\n\n```html\n<mk-postal-code-input country=\"PL\" [(ngModel)]=\"zip\" />\n<mk-postal-code-input [country]=\"form.value.country\" [(value)]=\"zip\" />\n```",
     "file": "projects/mk-kit/forms/postal-code-input/postal-code-input.ts",
     "kind": "component",
     "selector": "mk-postal-code-input",
     "selectors": [
      "mk-postal-code-input"
     ],
     "exportAs": "mkPostalCodeInput",
     "formControl": true,
     "inputs": [
      {
       "name": "country",
       "type": "string",
       "description": "ISO 3166-1 alpha-2 country whose format applies.",
       "default": "'US'"
      },
      {
       "name": "formats",
       "type": "readonly MkPostalFormat[]",
       "description": "The format table (defaults to the built-in set) — extend to add countries.",
       "default": "MK_POSTAL_FORMATS"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder; defaults to a valid example for the country.",
       "default": "''"
      },
      {
       "name": "value",
       "type": "string",
       "description": "Two-way formatted value (e.g. `00-950`, `K1A 0B1`).",
       "model": true,
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `postalCode` for a code not matching `[country]`'s format — the\nsame error `mkPostalCodeValidator()` produces. Empty values and countries\nwithout a built-in format pass."
      }
     ],
     "properties": [
      {
       "name": "valid",
       "type": "Signal<boolean | null>",
       "description": "`true`/`false` for a complete/incomplete code, `null` when empty or the\ncountry has no known format.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/phone-postal"
    },
    {
     "name": "MkRadio",
     "description": "Radio — a single option within an `mk-radio-group`. Rendered as\n`role=\"radio\"` with a roving tabindex managed by the parent group, so the\nwhole group is a single Tab stop and Arrow keys move between options.\n\nMust be used as a child of `mk-radio-group`.\n\n```html\n<mk-radio [value]=\"'pro'\">Pro plan</mk-radio>\n```",
     "file": "projects/mk-kit/forms/radio/radio.ts",
     "kind": "component",
     "selector": "mk-radio",
     "selectors": [
      "mk-radio"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "unknown",
       "description": "The value contributed to the group when this radio is selected.",
       "default": "null"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable just this radio.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [
      {
       "name": "focus",
       "signature": "(): void",
       "description": "Focus this radio's host element (used by the group's keyboard nav)."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/toggles"
    },
    {
     "name": "MkRadioGroup",
     "description": "RadioGroup — an ARIA `radiogroup` that coordinates projected `mk-radio`\nchildren. It manages a single selected value with roving tabindex and\nArrow-key navigation (Up/Left = previous, Down/Right = next, wrapping and\nskipping disabled radios).\n\nImplements `ControlValueAccessor` with a two-way `value` model.\n\n```html\n<mk-radio-group [(ngModel)]=\"plan\" aria-label=\"Plan\">\n  <mk-radio [value]=\"'free'\">Free</mk-radio>\n  <mk-radio [value]=\"'pro'\">Pro</mk-radio>\n</mk-radio-group>\n```",
     "file": "projects/mk-kit/forms/radio/radio-group.ts",
     "kind": "component",
     "selector": "mk-radio-group",
     "selectors": [
      "mk-radio-group"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "unknown",
       "description": "Two-way selected value.",
       "model": true,
       "default": "null"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the whole group.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`).",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size applied to all child radios.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone applied to all child radios.",
       "default": "'primary'"
      },
      {
       "name": "name",
       "type": "string",
       "description": "Shared `name` grouping (defaults to a generated unique name).",
       "default": "mkUniqueId('mk-radio')"
      },
      {
       "name": "orientation",
       "type": "\"vertical\" | \"horizontal\"",
       "description": "Layout direction; also sets arrow-key mapping expectations.",
       "default": "'vertical'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "register",
       "signature": "(radio: MkRadio): void",
       "description": "Register a child radio (called from `mk-radio` on init)."
      },
      {
       "name": "unregister",
       "signature": "(radio: MkRadio): void",
       "description": "Unregister a child radio (called on destroy)."
      },
      {
       "name": "isChecked",
       "signature": "(radio: MkRadio): boolean",
       "description": "True when `radio` matches the group's current value."
      },
      {
       "name": "select",
       "signature": "(radio: MkRadio): void",
       "description": "Select a radio's value (guarded by disabled state)."
      },
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `required` when `[required]` is set and no radio is selected."
      }
     ],
     "properties": [
      {
       "name": "hasChecked",
       "type": "Signal<boolean>",
       "description": "Whether a radio currently matches the selected value.",
       "readonly": true
      },
      {
       "name": "firstEnabled",
       "type": "Signal<MkRadio | null>",
       "description": "The radio that should be tabbable when nothing is selected.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/toggles"
    },
    {
     "name": "MkRangeSlider",
     "description": "RangeSlider — a two-thumb slider selecting a `[low, high]` range. Each thumb is\na `role=\"slider\"` (Arrow / Page / Home / End keys); the thumbs can't cross.\nImplements `ControlValueAccessor` over a `[number, number]` tuple with a\ntwo-way `value` model.\n\n```html\n<mk-range-slider [min]=\"0\" [max]=\"1000\" [step]=\"10\" [(value)]=\"priceRange\" />\n```",
     "file": "projects/mk-kit/forms/range-slider/range-slider.ts",
     "kind": "component",
     "selector": "mk-range-slider",
     "selectors": [
      "mk-range-slider"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "min",
       "type": "number",
       "description": "Minimum value.",
       "default": "0"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Maximum value.",
       "default": "100"
      },
      {
       "name": "step",
       "type": "number",
       "description": "Step increment (must be > 0).",
       "default": "1"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic tone for the filled range + thumbs.",
       "default": "'primary'"
      },
      {
       "name": "minLabel",
       "type": "string",
       "description": "Accessible label for the low thumb.",
       "default": "this.i18n.minimum"
      },
      {
       "name": "maxLabel",
       "type": "string",
       "description": "Accessible label for the high thumb.",
       "default": "this.i18n.maximum"
      },
      {
       "name": "value",
       "type": "MkRange",
       "description": "Two-way `[low, high]` value.",
       "model": true,
       "default": "[0, 100]"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "MkRange",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `min` / `max` for either endpoint falling outside the track. The\nslider clamps what the user can produce, so this only fires for a range\nwritten in from the model side."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/sliders"
    },
    {
     "name": "MkRating",
     "description": "Rating — a star rating input (and read-only display). Implements the ARIA\nslider pattern: one focusable control, Arrow keys adjust, Home/End jump.\nClick or hover a star to set the value. `ControlValueAccessor` + two-way\n`value` model over a number.\n\n```html\n<mk-rating [(value)]=\"score\" [max]=\"5\" />\n<mk-rating [value]=\"4\" readonly />\n```",
     "file": "projects/mk-kit/forms/rating/rating.ts",
     "kind": "component",
     "selector": "mk-rating",
     "selectors": [
      "mk-rating"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "max",
       "type": "number",
       "description": "Number of stars.",
       "default": "5"
      },
      {
       "name": "value",
       "type": "number",
       "description": "Two-way rating value (0–max).",
       "model": true,
       "default": "0"
      },
      {
       "name": "readonly",
       "type": "boolean",
       "description": "Read-only display (no interaction).",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label.",
       "default": "this.i18n.ratingLabel"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "number",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `max` for a rating above `[max]`. Zero means \"unrated\" and is\nleft to `Validators.required` to reject."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/sliders"
    },
    {
     "name": "MkRepeater",
     "description": "Repeater — the schema-friendly editable list: renders one instance of a\nconsumer-projected row template per item, with add / remove / (optional)\ndrag-and-drop + keyboard reorder built in.\n\n`items` is a two-way model and the component also implements\n`ControlValueAccessor` over `T[]`, so it drops into template-driven and\nreactive forms alike. **Every mutation produces a new array** — the\nconsumer's array is never mutated in place.\n\nRows are tracked by **item object identity** (stable across the repeater's\nimmutable array copies), so removing a middle row keeps the following rows'\nDOM — and any in-progress input state — intact. Consequently, arrays of\nprimitives with duplicate values (e.g. `['a', 'a']`) are not supported\ndirectly: wrap each value in an object (`{ value: 'a' }`) so every row has\na distinct identity.\n\nWith `reorderable`, each row gets a drag handle wired through the dnd\nmodule's touch-safe handle-based configuration (a swipe on the row body\nstill scrolls the page). The handle button is the only control the dnd\nlayer adds — rows stay plain list items, so the inputs and buttons inside\nthem are never nested in an interactive role. Reordering also works by\nkeyboard: focus the handle and press Space/Enter to pick up, arrows to\nmove, Space/Enter to drop, Escape to cancel. Each completed reorder is\nannounced via `MkLiveAnnouncer`.\n\n```html\n<mk-repeater [(items)]=\"rows\" [min]=\"1\" [max]=\"10\" reorderable\n             [factory]=\"newRow\" addLabel=\"Add row\">\n  <ng-template mkRepeaterRow let-item let-i=\"index\">\n    <input mkInput [(ngModel)]=\"item.name\" />\n  </ng-template>\n  <ng-template mkRepeaterEmpty>No rows yet.</ng-template>\n</mk-repeater>\n```",
     "file": "projects/mk-kit/forms/repeater/repeater.ts",
     "kind": "component",
     "selector": "mk-repeater",
     "selectors": [
      "mk-repeater"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "items",
       "type": "T[]",
       "description": "The rows (two-way). Every mutation sets a **new** array.",
       "model": true,
       "default": "[]"
      },
      {
       "name": "factory",
       "type": "() => T",
       "description": "Creates the item appended by the add button. Default: `{}` cast to `T`.",
       "default": "() => ({}) as T"
      },
      {
       "name": "min",
       "type": "number",
       "description": "Minimum number of rows — remove buttons disable at (or below) it.",
       "default": "0"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Maximum number of rows (0 = unlimited) — the add button disables at it.",
       "default": "0"
      },
      {
       "name": "reorderable",
       "type": "boolean",
       "description": "Enable per-row drag handles (pointer + keyboard reorder).",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the whole control (add, remove and reorder).",
       "default": "false"
      },
      {
       "name": "addLabel",
       "type": "string",
       "description": "Add-button caption. Defaults to the i18n `repeaterAddRow` string.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "itemsChange",
       "type": "T[]",
       "description": "Emits when `items` changes (two-way binding).",
       "model": true
      },
      {
       "name": "added",
       "type": "{ item: T; index: number; }",
       "description": "Emitted after the add button appended a factory-made item."
      },
      {
       "name": "removed",
       "type": "{ item: T; index: number; }",
       "description": "Emitted after a row was removed."
      },
      {
       "name": "moved",
       "type": "{ from: number; to: number; }",
       "description": "Emitted after a row was reordered (drag or keyboard)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/forms#repeater"
    },
    {
     "name": "MkSelect",
     "description": "Select — a fully custom, accessible single-select implementing the ARIA\nlistbox/combobox pattern. Options are supplied via the `options` input.\n\nKeyboard: Up/Down to move, Home/End to jump, Enter/Space to select, Esc to\nclose, and typeahead by typing option text. Focus stays on the trigger\n(`aria-activedescendant` pattern) for robust screen-reader behaviour.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so it\nworks with `[(ngModel)]`, reactive forms and `[(value)]`.\n\n```html\n<mk-select placeholder=\"Pick a role\"\n  [options]=\"[{label:'Admin', value:'admin'}, {label:'Editor', value:'editor'}]\"\n  [(ngModel)]=\"role\" />\n```",
     "file": "projects/mk-kit/forms/select/select.ts",
     "kind": "component",
     "selector": "mk-select",
     "selectors": [
      "mk-select"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when the control is used without an `mk-form-field` label.",
       "default": "''"
      },
      {
       "name": "options",
       "type": "readonly MkSelectOption[]",
       "description": "",
       "default": "[]"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when nothing is selected.",
       "default": "this.i18n.selectPlaceholder"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Two-way selected value.",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/forms"
    },
    {
     "name": "MkSignaturePad",
     "description": "SignaturePad — a canvas the user draws a signature on (pointer, touch or\npen). Strokes are captured as smoothed polylines, rendered crisp on hi-DPI\nscreens and re-drawn losslessly when the pad resizes. The form value is a\nPNG data-URL of the drawing (`null` while empty), so it drops straight into\nan `<img>`, a form post or an upload.\n\nA Clear control resets the pad (also available as `clear()`); `isEmpty()`\nreports whether anything is drawn. Programmatic values (`writeValue`,\n`[value]`) are painted onto the canvas as an image.\n\nDrawing is inherently pointer-based; pair the pad with an alternative flow\n(e.g. a typed-name checkbox) where WCAG requires a keyboard equivalent.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so\n`[(ngModel)]`, reactive forms and `[(value)]` all work.\n\n```html\n<mk-signature-pad [(ngModel)]=\"signature\" />\n<img [src]=\"signature\" alt=\"Captured signature\" />\n```",
     "file": "projects/mk-kit/forms/signature-pad/signature-pad.ts",
     "kind": "component",
     "selector": "mk-signature-pad",
     "selectors": [
      "mk-signature-pad"
     ],
     "exportAs": "mkSignaturePad",
     "formControl": true,
     "inputs": [
      {
       "name": "strokeWidth",
       "type": "number",
       "description": "Stroke width in CSS pixels.",
       "default": "2"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Pad height in CSS pixels (width follows the container).",
       "default": "160"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "value",
       "type": "string | null",
       "description": "Two-way PNG data-URL of the signature (`null` while empty).",
       "model": true,
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "cleared",
       "type": "void",
       "description": "Emits when the pad is cleared (via the button or `clear()`)."
      }
     ],
     "methods": [
      {
       "name": "clear",
       "signature": "(): void",
       "description": "Clear the drawing (and the form value)."
      }
     ],
     "properties": [
      {
       "name": "isEmpty",
       "type": "Signal<boolean>",
       "description": "Whether nothing is drawn yet.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/signature"
    },
    {
     "name": "MkSlider",
     "description": "Slider — a single-value range slider with `role=\"slider\"`, a filled track and\na draggable thumb (pointer events). Fully keyboard operable: Arrow keys step,\nPage Up/Down take larger steps, Home/End jump to the bounds.\n\nImplements `ControlValueAccessor` with a two-way `value` model, so it works\nwith `[(ngModel)]`, reactive forms and `[(value)]`.\n\n```html\n<mk-slider [min]=\"0\" [max]=\"100\" [step]=\"5\" [(ngModel)]=\"volume\" />\n```",
     "file": "projects/mk-kit/forms/slider/slider.ts",
     "kind": "component",
     "selector": "mk-slider",
     "selectors": [
      "mk-slider"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "min",
       "type": "number",
       "description": "Minimum value.",
       "default": "0"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Maximum value.",
       "default": "100"
      },
      {
       "name": "step",
       "type": "number",
       "description": "Step increment (must be > 0).",
       "default": "1"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size (track/thumb thickness).",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone for the filled track + thumb.",
       "default": "'primary'"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible label for the thumb.",
       "default": "''"
      },
      {
       "name": "value",
       "type": "number",
       "description": "Two-way current value.",
       "model": true,
       "default": "0"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "number",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `min` / `max` for a value outside the track. The slider clamps\nwhat the user can produce, so this only fires for a value written in\nfrom the model side."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/sliders"
    },
    {
     "name": "MkSubmitInput",
     "description": "SubmitInput — a short text entry and its action button rendered as one\nconnected control: the \"type a code and apply it\" pattern (discount codes,\ngift cards, invite codes, newsletter sign-up, quick search).\n\nThe button is disabled while the value is empty or blank, shows a spinner\nwhile `loading` and emits `submitted` with the **trimmed** value on\nclick or on Enter.\n\n## Enter never submits the surrounding form\n\nThis control is normally dropped inside a bigger form (a checkout, a\nsettings page), where triggering that form's submit would be a bug. So the\naction button is a `type=\"button\"` and, while `submitOnEnter` is on, the\nEnter keydown is `preventDefault()`-ed — implicit form submission never\nfires. Set `submitOnEnter=\"false\"` to restore the native behaviour and let\nEnter reach the enclosing form.\n\n## Button content\n\nThe button is configured, not projected: `buttonLabel` sets its text.\nPassing `buttonIcon` (a registered `MkIcon` name) switches it to the\nsquare icon-only variant, where `buttonLabel` becomes its `aria-label` — so\nthe action always has an accessible name.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so\n`[(ngModel)]`, reactive forms and `[(value)]` all work.\n\n```html\n<mk-submit-input\n  [(value)]=\"code\"\n  buttonLabel=\"Apply\"\n  [loading]=\"applying()\"\n  placeholder=\"SUMMER10\"\n  clearable\n  (submitted)=\"apply($event)\"\n/>\n\n<!-- icon-only, inside a field -->\n<mk-form-field label=\"Search\">\n  <mk-submit-input buttonIcon=\"search\" buttonLabel=\"Search\" [(ngModel)]=\"q\" />\n</mk-form-field>\n```",
     "file": "projects/mk-kit/forms/submit-input/submit-input.ts",
     "kind": "component",
     "selector": "mk-submit-input",
     "selectors": [
      "mk-submit-input"
     ],
     "exportAs": "mkSubmitInput",
     "formControl": true,
     "inputs": [
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the whole control (input + button).",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "''"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible name for the inner input when the control is used outside an\n`mk-form-field` (inside one, the field's `<label>` wins). Defaults to the\nbutton's caption.",
       "default": "''"
      },
      {
       "name": "type",
       "type": "string",
       "description": "Native `type` of the inner input (`text`, `search`, `email`, …).",
       "default": "'text'"
      },
      {
       "name": "autocomplete",
       "type": "string",
       "description": "Native `autocomplete` hint for the inner input.",
       "default": "'off'"
      },
      {
       "name": "value",
       "type": "string",
       "description": "Two-way value. `submitted` emits it trimmed; the model keeps what was typed.",
       "model": true,
       "default": "''"
      },
      {
       "name": "buttonLabel",
       "type": "string",
       "description": "Button text — or, with `buttonIcon`, the icon button's `aria-label`.",
       "default": "''"
      },
      {
       "name": "buttonIcon",
       "type": "string",
       "description": "Registered icon name; switches the button to the icon-only variant.",
       "default": "''"
      },
      {
       "name": "buttonVariant",
       "type": "MkVariant",
       "description": "Button visual treatment.",
       "default": "'solid'"
      },
      {
       "name": "buttonTone",
       "type": "MkTone",
       "description": "Button colour tone.",
       "default": "'primary'"
      },
      {
       "name": "loading",
       "type": "boolean",
       "description": "Shows a spinner in the button and blocks submitting while an action runs.",
       "default": "false"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear affix while the value is non-empty.",
       "default": "false"
      },
      {
       "name": "submitOnEnter",
       "type": "boolean",
       "description": "Submit on Enter, without submitting an enclosing `<form>`. Turn it off to\nlet Enter bubble to the form as the browser normally would.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "submitted",
       "type": "string",
       "description": "Emits the current value, trimmed, when the action is triggered."
      }
     ],
     "methods": [
      {
       "name": "submit",
       "signature": "(): void",
       "description": "Emit `submitted` with the trimmed value, when the control allows it."
      },
      {
       "name": "clear",
       "signature": "(): void",
       "description": "Clear the value and return focus to the input."
      }
     ],
     "properties": [
      {
       "name": "inputId",
       "type": "string",
       "description": "Id of the inner input — the `<label for>` target inside an `mk-form-field`.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/forms"
    },
    {
     "name": "MkSwitch",
     "description": "Switch — a toggle with `role=\"switch\"` and an animated knob. Operable with\nSpace/Enter, projects its label, and supports size + tone.\n\nImplements `ControlValueAccessor` with a two-way `checked` model, so it works\nwith `[(ngModel)]`, reactive forms and `[(checked)]`.\n\n```html\n<mk-switch [(ngModel)]=\"notify\">Email notifications</mk-switch>\n<mk-switch [(checked)]=\"dark\" tone=\"success\" size=\"lg\">Dark mode</mk-switch>\n```",
     "file": "projects/mk-kit/forms/switch/switch.ts",
     "kind": "component",
     "selector": "mk-switch",
     "selectors": [
      "mk-switch"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "checked",
       "type": "boolean",
       "description": "Two-way checked (on/off) state.",
       "model": true,
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone for the \"on\" track.",
       "default": "'primary'"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible label when no text content is projected.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "checkedChange",
       "type": "boolean",
       "description": "Emits when `checked` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/toggles"
    },
    {
     "name": "MkTagInput",
     "description": "TagInput — a freeform token input: type a value and press Enter (or a\nseparator) to add it as a removable chip. Backspace on an empty field removes\nthe last tag, and pasting a delimited string adds several at once. Unlike\n`mk-multi-select` the tags are not drawn from a fixed option list. Implements\n`ControlValueAccessor` + a two-way `value` model of `string[]`.\n\n```html\n<mk-tag-input placeholder=\"Add tags…\" [(value)]=\"tags\" />\n```",
     "file": "projects/mk-kit/forms/tag-input/tag-input.ts",
     "kind": "component",
     "selector": "mk-tag-input",
     "selectors": [
      "mk-tag-input"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "string[]",
       "description": "Two-way list of tags.",
       "model": true,
       "default": "[]"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown in the text field.",
       "default": "''"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Maximum number of tags (0 = unlimited).",
       "default": "0"
      },
      {
       "name": "allowDuplicates",
       "type": "boolean",
       "description": "Allow the same tag more than once.",
       "default": "false"
      },
      {
       "name": "addOnBlur",
       "type": "boolean",
       "description": "Commit the pending text as a tag when the field loses focus.",
       "default": "false"
      },
      {
       "name": "separators",
       "type": "readonly string[]",
       "description": "Extra characters that commit the pending text (Enter always does). A\npasted string is split on these too. Default: comma.",
       "default": "[',']"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string[]",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "added",
       "type": "string",
       "description": "Emitted when a tag is added."
      },
      {
       "name": "removed",
       "type": "string",
       "description": "Emitted when a tag is removed."
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMaxItems` when more tags are present than `[max]` allows."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/selection"
    },
    {
     "name": "MkTaxIdInput",
     "description": "TaxIdInput — a business tax-identifier field that masks and validates itself\nfor the given `country` (`PL` NIP `000-000-00-00`, `DE` USt-IdNr., `CZ` DIČ,\n`IT` Partita IVA, `SK` IČ DPH). Poland's NIP is checksum-verified; the other\nbuilt-ins are shape-verified.\n\nLike `MkIbanInput`, the form value is the **compact** identifier (digits\nonly, e.g. `1234563218`) while the field *displays* it masked\n(`123-456-32-18`) — so what is stored is what an API or invoice expects, and\n`writeValue()` accepts either form. The placeholder defaults to a valid\nexample for the country. `valid()` (via `exportAs`) reports `true`/`false`\nfor a complete identifier passing/failing validation and `null` while empty,\nstill incomplete or the country is unknown; invalid styling engages after\nthe field was touched. `mkTaxIdValidator()` covers reactive forms.\n\nImplements `ControlValueAccessor` and exposes a two-way `value` model, so\n`[(ngModel)]`, reactive forms and `[(value)]` all work.\n\n```html\n<mk-tax-id-input [(ngModel)]=\"nip\" />\n<mk-tax-id-input [country]=\"form.value.country\" [(value)]=\"taxId\" />\n```",
     "file": "projects/mk-kit/forms/tax-id-input/tax-id-input.ts",
     "kind": "component",
     "selector": "mk-tax-id-input",
     "selectors": [
      "mk-tax-id-input"
     ],
     "exportAs": "mkTaxIdInput",
     "formControl": true,
     "inputs": [
      {
       "name": "country",
       "type": "string",
       "description": "ISO 3166-1 alpha-2 country whose format applies.",
       "default": "'PL'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder; defaults to a valid example for the country.",
       "default": "''"
      },
      {
       "name": "value",
       "type": "string",
       "description": "Two-way identifier in compact form (digits only, e.g. `1234563218`).",
       "model": true,
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `taxId` for an identifier not matching `[country]`'s format or\nfailing its checksum — the same error `mkTaxIdValidator()` produces, so\nthe two are interchangeable. Empty values and unknown countries pass;\ncompose with `Validators.required` to reject an empty one."
      }
     ],
     "properties": [
      {
       "name": "valid",
       "type": "Signal<boolean | null>",
       "description": "`true` for a complete identifier passing its format (and checksum),\n`false` for a complete-but-wrong one, `null` while empty, still shorter\nthan the mask allows, or the country has no known format.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/payment"
    },
    {
     "name": "MkTransferList",
     "description": "TransferList — a dual list box (a.k.a. pick list) for moving items between an\n**available** list and a **selected** list, e.g. assigning roles or\npermissions. The user checks rows in one list then clicks the middle move\nbuttons (or presses Enter on a row) to shuttle them across.\n\nImplements `ControlValueAccessor` over an **array** value (the values in the\nselected list) and exposes a two-way `value` model, so it works with\n`[(ngModel)]`, reactive forms and `[(value)]`. When nested in an\n`mk-form-field` it inherits size and label wiring.\n\nKeyboard: each listbox is a single tab stop (roving tabindex). Arrow Up/Down\nand Home/End move between rows, Space toggles a row's check and Enter moves\nit to the opposite list.\n\n```html\n<mk-transfer-list filterable\n  [items]=\"allRoles()\"\n  [(value)]=\"assignedRoles\"\n  availableLabel=\"All roles\"\n  selectedLabel=\"Assigned\" />\n```",
     "file": "projects/mk-kit/forms/transfer-list/transfer-list.ts",
     "kind": "component",
     "selector": "mk-transfer-list",
     "selectors": [
      "mk-transfer-list"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "items",
       "type": "readonly MkTransferItem[]",
       "description": "The full set of items to shuttle between the two lists.",
       "default": "[]"
      },
      {
       "name": "availableLabel",
       "type": "string",
       "description": "Heading for the left (available) list.",
       "default": "this.i18n.available"
      },
      {
       "name": "selectedLabel",
       "type": "string",
       "description": "Heading for the right (selected) list.",
       "default": "this.i18n.selected"
      },
      {
       "name": "filterable",
       "type": "boolean",
       "description": "Show a search box over each list.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the whole control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "value",
       "type": "unknown[]",
       "description": "Two-way values currently in the selected (right) list.",
       "model": true,
       "default": "[]"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown[]",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "change",
       "type": "unknown[]",
       "description": "Emits the new selected values whenever items are moved."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/selection"
    },
    {
     "name": "MkTreeSelect",
     "description": "TreeSelect — a form field whose popover contains a hierarchical\n`MkTree`. The trigger shows the selected node's label (or a\nplaceholder); opening it reveals a selectable tree rendered in the top layer\nvia `MkAnchoredPanel`, so it is never clipped. Choosing a node sets the\nvalue to that node's `value` (or the node itself when `value` is unset),\ncloses the panel and restores focus to the trigger. Implements\n`ControlValueAccessor` and a two-way `value` model.\n\n```html\n<mk-tree-select [nodes]=\"tree\" [(value)]=\"picked\" clearable />\n```",
     "file": "projects/mk-kit/forms/tree-select/tree-select.ts",
     "kind": "component",
     "selector": "mk-tree-select",
     "selectors": [
      "mk-tree-select"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "nodes",
       "type": "readonly MkTreeNode[]",
       "description": "The hierarchical data to render in the panel.",
       "default": "[]"
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Two-way selected value (a node's `value`, or the node itself if unset).",
       "model": true,
       "default": "null"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when nothing is selected.",
       "default": "this.i18n.selectPlaceholder"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear button when a value is selected.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "unknown",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "valueId",
       "type": "string",
       "description": "Id of the rendered value/placeholder span, appended to `aria-labelledby`.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/selection"
    },
    {
     "name": "MkMention",
     "description": "Mention / hashtag autocomplete for a **native** `<textarea>` or text\n`<input>`. Typing a trigger character (`@`, `#`, …) at the start of a word\nopens a top-layer suggestion panel anchored at the caret; picking an option\nreplaces the trigger-plus-query with the completed mention and dispatches an\n`input` event so `ngModel`/reactive-forms bindings stay in sync.\n\nThe element keeps its native textbox semantics — no `role=\"combobox\"` — and\nfollows the ARIA activedescendant pattern while the panel is open\n(`aria-autocomplete=\"list\"`, `aria-controls`, `aria-expanded`,\n`aria-activedescendant`).\n\nFiltering is built in (`contains` / `startsWith` over label + value); set\n`mentionFilter=\"none\"` and drive `mentionOptions` from the `mentionSearch`\noutput for async/server-side suggestions (`mentionLoading` keeps the panel\nopen with a spinner while results are in flight).\n\n```html\n<textarea mkMention\n  [mentionTriggers]=\"['@', '#']\"\n  [mentionOptions]=\"users\"\n  (mentionSelect)=\"onPick($event)\"\n></textarea>\n```",
     "file": "projects/mk-kit/forms/mention/mention.ts",
     "kind": "directive",
     "selector": "textarea[mkMention], input[mkMention]",
     "selectors": [
      "mkMention"
     ],
     "exportAs": "mkMention",
     "inputs": [
      {
       "name": "mentionTriggers",
       "type": "readonly string[]",
       "description": "Single characters that start a mention session.",
       "default": "['@']"
      },
      {
       "name": "mentionOptions",
       "type": "readonly MkMentionOption[]",
       "description": "The suggestion pool. Update it from `mentionSearch` for async sources.",
       "default": "[]"
      },
      {
       "name": "mentionFilter",
       "type": "MkMentionFilterMode",
       "description": "How suggestions are filtered against the typed query.",
       "default": "'contains'"
      },
      {
       "name": "mentionLoading",
       "type": "boolean",
       "description": "Keep the panel open with a loading row while async results are pending.",
       "default": "false"
      },
      {
       "name": "mentionInsert",
       "type": "((option: MkMentionOption, trigger: string) => string) | null",
       "description": "Builds the text inserted for a picked option. Defaults to\n`` `${trigger}${option.label} ` `` (note the trailing space).",
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "mentionSearch",
       "type": "MkMentionSearchEvent",
       "description": "Emits `{trigger, query}` whenever the active query changes — drive async loading."
      },
      {
       "name": "mentionSelect",
       "type": "MkMentionSelectEvent",
       "description": "Emits after an option has been inserted into the control."
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "listId",
       "type": "string",
       "description": "Id of the listbox panel, wired to `aria-controls` while open.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/selection#mention"
    },
    {
     "name": "MkOnScreenKeyboardTrigger",
     "description": "Binds an `<input>`/`<textarea>` to an `MkOnScreenKeyboard`: opens the\npanel on focus/click, closes it when focus leaves, and sets\n`inputmode=\"none\"` so touch devices don't raise the OS keyboard on top of\nit. Disabled/readonly fields never open the panel.\n\n```html\n<input mkInput [mkOnScreenKeyboardFor]=\"kbd\" />\n<mk-on-screen-keyboard #kbd />\n```",
     "file": "projects/mk-kit/forms/on-screen-keyboard/on-screen-keyboard-trigger.ts",
     "kind": "directive",
     "selector": "input[mkOnScreenKeyboardFor], textarea[mkOnScreenKeyboardFor]",
     "selectors": [
      "mkOnScreenKeyboardFor"
     ],
     "exportAs": "mkOnScreenKeyboardTrigger",
     "inputs": [
      {
       "name": "mkOnScreenKeyboardFor",
       "type": "MkOnScreenKeyboard",
       "description": "The keyboard instance to open for this field.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/touch-keys"
    },
    {
     "name": "MkRepeaterEmpty",
     "description": "Marks an `<ng-template>` as `MkRepeater`'s custom empty state, shown\ninstead of the row list while there are no items.",
     "file": "projects/mk-kit/forms/repeater/repeater.ts",
     "kind": "directive",
     "selector": "[mkRepeaterEmpty]",
     "selectors": [
      "mkRepeaterEmpty"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "template",
       "type": "TemplateRef<any>",
       "description": "The projected empty-state template.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/forms#repeater"
    },
    {
     "name": "MkRepeaterRow",
     "description": "Marks an `<ng-template>` as the row template for `MkRepeater`. The\ntemplate receives the item as its implicit context plus its `index`:\n\n```html\n<ng-template mkRepeaterRow let-item let-i=\"index\">\n  <input mkInput [(ngModel)]=\"item.name\" />\n</ng-template>\n```",
     "file": "projects/mk-kit/forms/repeater/repeater.ts",
     "kind": "directive",
     "selector": "[mkRepeaterRow]",
     "selectors": [
      "mkRepeaterRow"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "template",
       "type": "TemplateRef<MkRepeaterRowContext<T>>",
       "description": "The projected row template, rendered once per item.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/forms#repeater"
    },
    {
     "name": "mkCountryFlag",
     "description": "Regional-indicator flag emoji for an ISO 3166-1 alpha-2 code.",
     "file": "projects/mk-kit/forms/phone-input/phone-countries.ts",
     "kind": "function",
     "signatures": [
      "(code: string): string"
     ]
    },
    {
     "name": "mkDetectCardBrand",
     "description": "Detect the card network from the leading digits — `detectCardBrand` from `@mk-kit/validators`.",
     "file": "projects/mk-kit/forms/card-number-input/card-number-input.ts",
     "kind": "function",
     "signatures": [
      "(digits: string): MkCardBrand | null"
     ]
    },
    {
     "name": "mkHighlight",
     "description": "Highlight `src` for `language`, falling back to escaped plain text.",
     "file": "projects/core/src/highlight.ts",
     "kind": "function",
     "signatures": [
      "(src: string, language: string): string"
     ]
    },
    {
     "name": "mkIbanChecksum",
     "description": "ISO 7064 MOD 97-10 over a compact (uppercase, no separators) IBAN.",
     "file": "projects/mk-kit/forms/iban-input/iban-input.ts",
     "kind": "function",
     "signatures": [
      "(compact: string): boolean"
     ]
    },
    {
     "name": "mkIbanIsValid",
     "description": "Shape, the registry length for the country and the checksum — delegates\nto `isIban` from `@mk-kit/validators`. Unlike that function this one keeps\nthe input kit's stricter rule that the country must be in the table.",
     "file": "projects/mk-kit/forms/iban-input/iban-input.ts",
     "kind": "function",
     "signatures": [
      "(compact: string): boolean"
     ]
    },
    {
     "name": "mkIbanValidator",
     "description": "Reactive-forms validator for an IBAN (any supported country). Empty values\npass (compose with `Validators.required`); the error carries the country\nand its expected length when known.\n\n```ts\naccount: ['', [Validators.required, mkIbanValidator()]]\n```",
     "file": "projects/mk-kit/forms/iban-input/iban-input.ts",
     "kind": "function",
     "signatures": [
      "(): ValidatorFn"
     ]
    },
    {
     "name": "mkLuhnCheck",
     "description": "Luhn (mod 10) checksum over a digit string — `isLuhn` from `@mk-kit/validators`.",
     "file": "projects/mk-kit/forms/card-number-input/card-number-input.ts",
     "kind": "function",
     "signatures": [
      "(digits: string): boolean"
     ]
    },
    {
     "name": "mkNipChecksum",
     "description": "Polish NIP checksum — delegates to `isNip` from `@mk-kit/validators`\n(weights 6-5-7-2-3-4-5-6-7 mod 11; a remainder of 10 is invalid).",
     "file": "projects/mk-kit/forms/tax-id-input/tax-id-input.ts",
     "kind": "function",
     "signatures": [
      "(compact: string): boolean"
     ]
    },
    {
     "name": "mkPostalCodeValidator",
     "description": "Reactive-forms validator for a postal code in a given country. Empty values\npass (compose with `Validators.required`); countries without a built-in\nformat pass everything.\n\n```ts\nzip: ['', [Validators.required, mkPostalCodeValidator('PL')]]\n```",
     "file": "projects/mk-kit/forms/postal-code-input/postal-code-input.ts",
     "kind": "function",
     "signatures": [
      "(country: string, formats?: readonly MkPostalFormat[]): ValidatorFn"
     ]
    },
    {
     "name": "mkPostalFormat",
     "description": "Look up the built-in format for an ISO country code (case-insensitive).",
     "file": "projects/mk-kit/forms/postal-code-input/postal-formats.ts",
     "kind": "function",
     "signatures": [
      "(code: string): MkPostalFormat | undefined"
     ]
    },
    {
     "name": "mkTaxIdFormat",
     "description": "Look up the built-in format for an ISO country code (case-insensitive).",
     "file": "projects/mk-kit/forms/tax-id-input/tax-id-input.ts",
     "kind": "function",
     "signatures": [
      "(country: string): MkTaxIdFormat | undefined"
     ]
    },
    {
     "name": "mkTaxIdIsValid",
     "description": "Full validity for a country: shape plus the national checksum when the\nformat defines one. Masked and compact input are both accepted; unknown\ncountries have no rule to fail, so they pass.",
     "file": "projects/mk-kit/forms/tax-id-input/tax-id-input.ts",
     "kind": "function",
     "signatures": [
      "(value: string, country: string): boolean"
     ]
    },
    {
     "name": "mkTaxIdValidator",
     "description": "Reactive-forms validator for a business tax identifier in a given country.\nEmpty values pass (compose with `Validators.required`); countries without a\nbuilt-in format pass everything.\n\n```ts\nnip: ['', [Validators.required, mkTaxIdValidator('PL')]]\n```",
     "file": "projects/mk-kit/forms/tax-id-input/tax-id-input.ts",
     "kind": "function",
     "signatures": [
      "(country: string): ValidatorFn"
     ]
    },
    {
     "name": "MK_CARD_BRAND_NAMES",
     "description": "Human-readable names for the recognised brands.",
     "file": "projects/mk-kit/forms/card-number-input/card-number-input.ts",
     "kind": "const",
     "type": "Record<MkCardBrand, string>"
    },
    {
     "name": "MK_IBAN_LENGTHS",
     "description": "IBAN lengths per country — re-exported from `@mk-kit/validators`\n(`IBAN_LENGTHS`, the SWIFT registry).",
     "file": "projects/mk-kit/forms/iban-input/iban-input.ts",
     "kind": "const",
     "type": "Readonly<Record<string, number>>"
    },
    {
     "name": "MK_KEYBOARD_LAYOUT_QWERTY_PL",
     "description": "QWERTY with a Polish alternate layer (programmer-Polish convention: base\nletters are plain QWERTY, diacritics sit on the `?ąę` layer along with the\ncommon symbols).",
     "file": "projects/mk-kit/forms/on-screen-keyboard/keyboard-layouts.ts",
     "kind": "const",
     "type": "MkKeyboardLayout"
    },
    {
     "name": "MK_PHONE_COUNTRIES",
     "description": "The built-in country set (alphabetical by ISO code).",
     "file": "projects/mk-kit/forms/phone-input/phone-countries.ts",
     "kind": "const",
     "type": "readonly MkPhoneCountry[]"
    },
    {
     "name": "MK_POSTAL_FORMATS",
     "description": "The built-in postal formats (alphabetical by ISO code).",
     "file": "projects/mk-kit/forms/postal-code-input/postal-formats.ts",
     "kind": "const",
     "type": "readonly MkPostalFormat[]"
    },
    {
     "name": "MK_TAX_ID_FORMATS",
     "description": "The built-in tax-identifier formats (alphabetical by ISO code). Only Poland\ncarries a checksum; the rest are length/shape checks, which is what the\nnational registries publish without ambiguity.",
     "file": "projects/mk-kit/forms/tax-id-input/tax-id-input.ts",
     "kind": "const",
     "type": "readonly MkTaxIdFormat[]"
    },
    {
     "name": "MkAutocompleteOption",
     "description": "A single suggestion for `MkAutocomplete`.",
     "file": "projects/mk-kit/forms/autocomplete/autocomplete.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Text shown to the user and used as the input display value when chosen."
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "The value bound to the form control when this option is selected."
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Disable the option (skipped by keyboard + not selectable).",
       "optional": true
      },
      {
       "name": "description",
       "type": "string | undefined",
       "description": "Muted second line under the label — the disambiguator when labels can\ncollide (two customers named Jan Kowalski, telling accounts apart by\nemail, an id under a product name).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkCascaderOption",
     "description": "One node of a cascader: a leaf, or a parent with `children`.",
     "file": "projects/mk-kit/forms/cascader/cascader.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": ""
      },
      {
       "name": "value",
       "type": "unknown",
       "description": ""
      },
      {
       "name": "children",
       "type": "readonly MkCascaderOption[] | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkCodeValidity",
     "description": "The validity of the editor's current content.",
     "file": "projects/mk-kit/forms/code-editor/code-editor.ts",
     "kind": "interface",
     "members": [
      {
       "name": "valid",
       "type": "boolean",
       "description": ""
      },
      {
       "name": "error",
       "type": "string | null",
       "description": "Parser error message, or `null` when valid / not validated."
      }
     ]
    },
    {
     "name": "MkFormError",
     "description": "One field-level error to surface in `MkFormErrorSummary`.",
     "file": "projects/mk-kit/forms/form-error-summary/form-error-summary.ts",
     "kind": "interface",
     "members": [
      {
       "name": "fieldId",
       "type": "string",
       "description": "The `id` of the control (or `mk-form-field`'s `controlId`) the message\nrefers to. Clicking the summary entry focuses this element."
      },
      {
       "name": "message",
       "type": "string",
       "description": "The human-readable error message."
      }
     ]
    },
    {
     "name": "MkI18nLocale",
     "description": "One translatable locale offered by `MkI18nInput`.",
     "file": "projects/mk-kit/forms/i18n-input/i18n-input.ts",
     "kind": "interface",
     "members": [
      {
       "name": "code",
       "type": "string",
       "description": "Value key in the bound record, e.g. `pl`."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Short switcher label, e.g. `PL`."
      },
      {
       "name": "name",
       "type": "string | undefined",
       "description": "Longer name for the accessible label, e.g. `Polish`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkKeyboardActionKey",
     "description": "Non-character keys. `span` stretches the key across extra grid columns.",
     "file": "projects/mk-kit/forms/on-screen-keyboard/keyboard-layouts.ts",
     "kind": "interface",
     "members": [
      {
       "name": "action",
       "type": "\"shift\" | \"backspace\" | \"space\" | \"enter\" | \"layer\"",
       "description": "",
       "readonly": true
      },
      {
       "name": "span",
       "type": "number | undefined",
       "description": "",
       "optional": true,
       "readonly": true
      }
     ]
    },
    {
     "name": "MkKeyboardLayout",
     "description": "",
     "file": "projects/mk-kit/forms/on-screen-keyboard/keyboard-layouts.ts",
     "kind": "interface",
     "members": [
      {
       "name": "base",
       "type": "readonly (readonly MkKeyboardKey[])[]",
       "description": "Letter layer.",
       "readonly": true
      },
      {
       "name": "alt",
       "type": "readonly (readonly MkKeyboardKey[])[]",
       "description": "Alternate layer (digits live in the base top row; this holds diacritics + symbols).",
       "readonly": true
      },
      {
       "name": "shiftMap",
       "type": "Readonly<Record<string, string>> | undefined",
       "description": "Overrides for shifted characters; missing keys fall back to `toUpperCase()`.",
       "optional": true,
       "readonly": true
      }
     ]
    },
    {
     "name": "MkListboxOption",
     "description": "One row of an `mk-listbox`.",
     "file": "projects/mk-kit/forms/listbox/listbox.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Text shown (and matched by typeahead / the filter)."
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Value committed to the model when selected."
      },
      {
       "name": "description",
       "type": "string | undefined",
       "description": "Secondary line under the label.",
       "optional": true
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Skipped by keyboard, not selectable.",
       "optional": true
      },
      {
       "name": "group",
       "type": "string | undefined",
       "description": "Options sharing a `group` render under one heading (keep them adjacent).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkMentionOption",
     "description": "A single suggestion offered by `MkMention`.",
     "file": "projects/mk-kit/forms/mention/mention.ts",
     "kind": "interface",
     "members": [
      {
       "name": "value",
       "type": "string",
       "description": "Machine identifier (username, tag slug) — also matched when filtering."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Text shown in the panel; the default insertion writes `trigger + label`."
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "Muted, single-line disambiguator shown after the label (e-mail, count…).",
       "optional": true
      },
      {
       "name": "trigger",
       "type": "string | undefined",
       "description": "Offer this option for one trigger character only (e.g. `'#'` for tags).\nOptions without a `trigger` are offered for every trigger.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkMentionSearchEvent",
     "description": "Payload of `MkMention.mentionSearch`.",
     "file": "projects/mk-kit/forms/mention/mention.ts",
     "kind": "interface",
     "members": [
      {
       "name": "trigger",
       "type": "string",
       "description": "The trigger character that opened the session (`'@'`, `'#'`, …)."
      },
      {
       "name": "query",
       "type": "string",
       "description": "Text typed between the trigger and the caret."
      }
     ]
    },
    {
     "name": "MkMentionSelectEvent",
     "description": "Payload of `MkMention.mentionSelect`.",
     "file": "projects/mk-kit/forms/mention/mention.ts",
     "kind": "interface",
     "members": [
      {
       "name": "option",
       "type": "MkMentionOption",
       "description": ""
      },
      {
       "name": "trigger",
       "type": "string",
       "description": ""
      }
     ]
    },
    {
     "name": "MkMultiSelectOption",
     "description": "A single selectable option for `MkMultiSelect`.",
     "file": "projects/mk-kit/forms/multi-select/multi-select.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Text shown to the user (and used for the chip + typeahead)."
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "The value committed to the form control when chosen."
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Disable the option (skipped by keyboard + not selectable).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkPasswordRule",
     "description": "A single password rule with its current pass/fail state.",
     "file": "projects/mk-kit/forms/password-input/password-input.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "\"number\" | \"symbol\" | \"length\" | \"uppercase\"",
       "description": "",
       "readonly": true
      },
      {
       "name": "label",
       "type": "string",
       "description": "",
       "readonly": true
      },
      {
       "name": "met",
       "type": "boolean",
       "description": "",
       "readonly": true
      }
     ]
    },
    {
     "name": "MkPhoneCountry",
     "description": "Per-country dialing metadata for `MkPhoneInput`.\n\n`mask` is an `mkApplyMask`-style pattern for the **national** number\n(`0` = digit, everything else is a literal). Masks follow the most common\nnational formatting; countries with several plan lengths use their longest\ncommon mobile format. The set covers the countries an admin product is\nlikely to meet — extend or replace it via the `countries` input.",
     "file": "projects/mk-kit/forms/phone-input/phone-countries.ts",
     "kind": "interface",
     "members": [
      {
       "name": "code",
       "type": "string",
       "description": "ISO 3166-1 alpha-2 code, uppercase (drives the flag + display name)."
      },
      {
       "name": "dialCode",
       "type": "string",
       "description": "International dialing code, digits only (no `+`)."
      },
      {
       "name": "mask",
       "type": "string",
       "description": "Mask for the national number, `0` = digit."
      }
     ]
    },
    {
     "name": "MkPhoneValue",
     "description": "Structured value emitted by `MkPhoneInput` in `parts` mode.",
     "file": "projects/mk-kit/forms/phone-input/phone-input.ts",
     "kind": "interface",
     "members": [
      {
       "name": "country",
       "type": "string",
       "description": "ISO 3166-1 alpha-2 country code, e.g. `PL`."
      },
      {
       "name": "dialCode",
       "type": "string",
       "description": "Dialing prefix with the leading `+`, e.g. `+48`."
      },
      {
       "name": "national",
       "type": "string",
       "description": "National number, digits only."
      },
      {
       "name": "e164",
       "type": "string",
       "description": "The full E.164 number, e.g. `+48601234567`."
      }
     ]
    },
    {
     "name": "MkPostalFormat",
     "description": "Per-country postal-code formats for `MkPostalCodeInput`.\n\n`mask` is an `mkApplyMask`-style pattern (`0` = digit, `A` = letter,\n`*` = alphanumeric, everything else a literal). `pattern` validates the\ncomplete formatted value. Countries whose codes vary too much for a fixed\nmask (e.g. GB) omit `mask` and rely on `pattern` + uppercasing alone.",
     "file": "projects/mk-kit/forms/postal-code-input/postal-formats.ts",
     "kind": "interface",
     "members": [
      {
       "name": "code",
       "type": "string",
       "description": "ISO 3166-1 alpha-2 code, uppercase."
      },
      {
       "name": "mask",
       "type": "string | undefined",
       "description": "Input mask; omitted for free-form (variable-length) codes.",
       "optional": true
      },
      {
       "name": "pattern",
       "type": "RegExp",
       "description": "Regex the complete formatted value must match to be valid."
      },
      {
       "name": "example",
       "type": "string",
       "description": "Example of a valid code, used as the default placeholder."
      }
     ]
    },
    {
     "name": "MkRepeaterRowContext",
     "description": "Template context for a `MkRepeaterRow` row template.",
     "file": "projects/mk-kit/forms/repeater/repeater.ts",
     "kind": "interface",
     "typeParams": "<T>",
     "members": [
      {
       "name": "$implicit",
       "type": "T",
       "description": "The row's item — destructure with `let-item`."
      },
      {
       "name": "index",
       "type": "number",
       "description": "The row's current index — destructure with `let-i=\"index\"`."
      }
     ]
    },
    {
     "name": "MkSelectOption",
     "description": "A single selectable option for `MkSelect`.",
     "file": "projects/mk-kit/forms/select/select.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Text shown to the user (and used for typeahead)."
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "The value bound to the form control when chosen."
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Disable the option (skipped by keyboard + not selectable).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTaxIdFormat",
     "description": "Per-country business tax-identifier format for `MkTaxIdInput`.\n\n`mask` is an `mkApplyMask` pattern (`0` = digit; every built-in format is\ndigits only). `compact` validates the unmasked value — the form value —\nand `validate` adds the national checksum where one exists and is\nunambiguous. Formats without a `validate` are pattern-checked only.",
     "file": "projects/mk-kit/forms/tax-id-input/tax-id-input.ts",
     "kind": "interface",
     "members": [
      {
       "name": "country",
       "type": "string",
       "description": "ISO 3166-1 alpha-2 code, uppercase."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Local name of the identifier, e.g. `NIP`."
      },
      {
       "name": "mask",
       "type": "string",
       "description": "Input mask; `0` = digit."
      },
      {
       "name": "compact",
       "type": "RegExp",
       "description": "Regex the complete unmasked (compact) value must match."
      },
      {
       "name": "example",
       "type": "string",
       "description": "Example of a valid identifier, used as the default placeholder."
      },
      {
       "name": "validate",
       "type": "((compact: string) => boolean) | undefined",
       "description": "National checksum over the compact value; omitted when there is none.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTransferItem",
     "description": "A single transferable item for `MkTransferList`.",
     "file": "projects/mk-kit/forms/transfer-list/transfer-list.ts",
     "kind": "interface",
     "members": [
      {
       "name": "value",
       "type": "unknown",
       "description": "The value committed to the form control when the item is in the selected list."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Text shown to the user."
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Disable the item (cannot be checked or moved).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTreeNode",
     "description": "A node in an `MkTree`. `children` makes it expandable.",
     "file": "projects/mk-kit/navigation/tree/tree.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Text shown for the node."
      },
      {
       "name": "value",
       "type": "unknown",
       "description": "Value bound to the selection when the node is chosen (defaults to the node).",
       "optional": true
      },
      {
       "name": "children",
       "type": "MkTreeNode[] | undefined",
       "description": "Child nodes; a non-empty array makes the node a parent (expandable).",
       "optional": true
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "Disable selection/toggling of this node (still focusable).",
       "optional": true
      },
      {
       "name": "expanded",
       "type": "boolean | undefined",
       "description": "Expand this node initially.",
       "optional": true
      },
      {
       "name": "icon",
       "type": "string | undefined",
       "description": "Optional leading glyph (any short string / emoji).",
       "optional": true
      },
      {
       "name": "iconName",
       "type": "string | undefined",
       "description": "Name of a registered icon (see `MkIconRegistry`), rendered with `mk-icon`; wins over `icon`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkUploadFile",
     "description": "A file tracked by `MkFileUpload`.",
     "file": "projects/mk-kit/forms/file-upload/file-upload.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": "Stable id for tracking + removal."
      },
      {
       "name": "file",
       "type": "File",
       "description": "The underlying browser `File`."
      },
      {
       "name": "name",
       "type": "string",
       "description": "File name."
      },
      {
       "name": "size",
       "type": "number",
       "description": "Size in bytes."
      },
      {
       "name": "status",
       "type": "MkUploadStatus",
       "description": "Upload lifecycle state."
      },
      {
       "name": "progress",
       "type": "number",
       "description": "Upload progress, 0–100."
      },
      {
       "name": "error",
       "type": "string | undefined",
       "description": "Failure reason (validation or upload error).",
       "optional": true
      },
      {
       "name": "previewUrl",
       "type": "string | undefined",
       "description": "Object URL for an image preview, when the file is an image.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkUploadRejection",
     "description": "Why a dropped/selected file was rejected.",
     "file": "projects/mk-kit/forms/file-upload/file-upload.ts",
     "kind": "interface",
     "members": [
      {
       "name": "file",
       "type": "File",
       "description": ""
      },
      {
       "name": "reason",
       "type": "\"type\" | \"size\" | \"maxFiles\"",
       "description": ""
      },
      {
       "name": "message",
       "type": "string",
       "description": ""
      }
     ]
    },
    {
     "name": "MkAutocompleteFilterMode",
     "description": "How the option list is narrowed against the typed text.",
     "file": "projects/mk-kit/forms/autocomplete/autocomplete.ts",
     "kind": "type",
     "definition": "'contains' | 'startsWith' | 'none'"
    },
    {
     "name": "MkCardBrand",
     "description": "Card networks `MkCardNumberInput` recognises.",
     "file": "projects/mk-kit/forms/card-number-input/card-number-input.ts",
     "kind": "type",
     "definition": "| 'visa' | 'mastercard' | 'amex' | 'discover' | 'diners' | 'jcb'"
    },
    {
     "name": "MkCodeLanguage",
     "description": "Languages with built-in highlighting. Unknown values render plain text.",
     "file": "projects/core/src/highlight.ts",
     "kind": "type",
     "definition": "'json' | 'plaintext'"
    },
    {
     "name": "MkI18nValue",
     "description": "The bound value: one string per locale code.",
     "file": "projects/mk-kit/forms/i18n-input/i18n-input.ts",
     "kind": "type",
     "definition": "Record<string, string>"
    },
    {
     "name": "MkKeyboardKey",
     "description": "",
     "file": "projects/mk-kit/forms/on-screen-keyboard/keyboard-layouts.ts",
     "kind": "type",
     "definition": "string | MkKeyboardActionKey"
    },
    {
     "name": "MkMentionFilterMode",
     "description": "How mention suggestions are narrowed against the typed query.",
     "file": "projects/mk-kit/forms/mention/mention.ts",
     "kind": "type",
     "definition": "'contains' | 'startsWith' | 'none'"
    },
    {
     "name": "MkMultiSelectFilterMode",
     "description": "How the option list is narrowed against the typed text.",
     "file": "projects/mk-kit/forms/multi-select/multi-select.ts",
     "kind": "type",
     "definition": "'contains' | 'startsWith' | 'none'"
    },
    {
     "name": "MkNumericKeypadMode",
     "description": "",
     "file": "projects/mk-kit/forms/numeric-keypad/numeric-keypad.ts",
     "kind": "type",
     "definition": "'pin' | 'quantity' | 'amount'"
    },
    {
     "name": "MkOnScreenKeyboardTarget",
     "description": "",
     "file": "projects/mk-kit/forms/on-screen-keyboard/on-screen-keyboard.ts",
     "kind": "type",
     "definition": "HTMLInputElement | HTMLTextAreaElement"
    },
    {
     "name": "MkRange",
     "description": "A `[low, high]` value pair.",
     "file": "projects/mk-kit/forms/range-slider/range-slider.ts",
     "kind": "type",
     "definition": "[number, number]"
    },
    {
     "name": "MkUploadFn",
     "description": "Uploads the given file, reporting progress via `onProgress` (0–100) and\nresolving on success / rejecting (optionally with an `Error`) on failure.",
     "file": "projects/mk-kit/forms/file-upload/file-upload.ts",
     "kind": "type",
     "definition": "( file: File, onProgress: (percent: number) => void, ) => Promise<void>"
    },
    {
     "name": "MkUploadStatus",
     "description": "Upload lifecycle state for a single file.",
     "file": "projects/mk-kit/forms/file-upload/file-upload.ts",
     "kind": "type",
     "definition": "'pending' | 'uploading' | 'success' | 'error'"
    },
    {
     "name": "MkUploadValueFormat",
     "description": "What `MkFileUpload` publishes as its form value: the raw browser\n`File`s (the default, and what you would send in a `FormData`), or the full\ntracked items including upload status and progress.",
     "file": "projects/mk-kit/forms/file-upload/file-upload.ts",
     "kind": "type",
     "definition": "'file' | 'item'"
    }
   ]
  },
  {
   "name": "datetime",
   "import": "@mk-kit/ui/datetime",
   "exports": [
    {
     "name": "MkCalendar",
     "description": "Calendar — an accessible month-grid date picker following the WAI-ARIA\ngrid / date-picker pattern. It is the reusable core behind\n`mk-date-picker` and `mk-date-range-picker`.\n\nKeyboard (when a day has focus): Arrow keys move by day/week (crossing month\nboundaries updates the view), Home/End jump to the start/end of the week,\nPageUp/PageDown change month, Shift+PageUp/PageDown change year, and\nEnter/Space selects the focused day. A roving tabindex keeps a single tab\nstop. Month changes are announced via `MkLiveAnnouncer`.\n\nExposes a two-way `value` model and implements `ControlValueAccessor`, so it\nalso works directly with `ngModel` / `formControl` (single-date mode).\nAdditive range inputs (`rangeMode`,\n`rangeStart`, `rangeEnd`) let it highlight an in-progress selection without\naffecting single-date use; range hosts listen to `dateSelected`.\n\n```html\n<mk-calendar [(value)]=\"date\" [min]=\"minDate\" [firstDayOfWeek]=\"1\" />\n```",
     "file": "projects/mk-kit/datetime/calendar/calendar.ts",
     "kind": "component",
     "selector": "mk-calendar",
     "selectors": [
      "mk-calendar"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "Date | null",
       "description": "Two-way selected date (single-date mode).",
       "model": true,
       "default": "null"
      },
      {
       "name": "min",
       "type": "Date | null",
       "description": "Earliest selectable date (inclusive, day granularity).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "Date | null",
       "description": "Latest selectable date (inclusive, day granularity).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "firstDayOfWeek",
       "type": "number",
       "description": "First column of the week: 0 = Sunday … 6 = Saturday.",
       "default": "0"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the whole calendar.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "disabledDate",
       "type": "((d: Date) => boolean) | null",
       "description": "Predicate marking individual days as disabled.",
       "default": "null"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size.",
       "default": "'md'"
      },
      {
       "name": "fullWidth",
       "type": "boolean",
       "description": "Stretch to fill the container instead of sizing to content.\n\nOff by default, because the common host is a date-picker popover that must\nstay a compact widget. Turn it on when the calendar is laid out as part of\na page — a sidebar or a column — where sizing to content leaves the space\nbeside it empty. Cells share the width evenly and `--_cell-size` becomes\ntheir minimum rather than their fixed size.",
       "default": "false"
      },
      {
       "name": "rangeMode",
       "type": "boolean",
       "description": "Enable range highlighting. Hosts drive selection via `dateSelected`.",
       "default": "false"
      },
      {
       "name": "rangeStart",
       "type": "Date | null",
       "description": "Range start endpoint to highlight (range mode).",
       "default": "null"
      },
      {
       "name": "rangeEnd",
       "type": "Date | null",
       "description": "Range end endpoint to highlight (range mode).",
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "Date | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "dateSelected",
       "type": "Date",
       "description": "Emitted whenever a (non-disabled) day is activated."
      },
      {
       "name": "dateHovered",
       "type": "Date | null",
       "description": "Emitted (in range mode) as the pointer hovers days — the hovered day, or\n`null` on leave. Lets hosts preview a selection (e.g. a whole-week\nhighlight in `mk-week-picker`)."
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMinDate` / `mkMaxDate` for a date outside `[min]`/`[max]`, and\n`mkDateFilter` for one rejected by `[disabledDate]`."
      }
     ],
     "properties": [
      {
       "name": "labelId",
       "type": "string",
       "description": "id of the visible month/year label — wire as the grid's label.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkDatePicker",
     "description": "DatePicker — a text field paired with a calendar popover. Type a date (parsed\non blur/Enter) or pick one from the `mk-calendar`. Implements\n`ControlValueAccessor` and a two-way `value` model, so it works with\n`[(ngModel)]`, reactive forms and `[(value)]`.\n\nThe calendar opens below the field, closes on Escape / outside click / after\na selection, and wires `aria-expanded` / `aria-haspopup` / `aria-invalid`.\nWhen nested in an `mk-form-field` it adopts the field's id and aria wiring.\n\n```html\n<mk-date-picker [(value)]=\"date\" [min]=\"minDate\" clearable />\n```",
     "file": "projects/mk-kit/datetime/date-picker/date-picker.ts",
     "kind": "component",
     "selector": "mk-date-picker",
     "selectors": [
      "mk-date-picker"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "Date | null",
       "description": "Two-way selected date.",
       "model": true,
       "default": "null"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when the picker is used without an `mk-form-field` label.",
       "default": "''"
      },
      {
       "name": "min",
       "type": "Date | null",
       "description": "",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "Date | null",
       "description": "Latest selectable date (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "disabledDate",
       "type": "((d: Date) => boolean) | null",
       "description": "Predicate marking individual days as disabled (threaded to the calendar).",
       "default": "null"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "this.i18n.selectDate"
      },
      {
       "name": "displayFormat",
       "type": "string",
       "description": "Pattern used to render the selected date in the field.",
       "default": "'MMM d, yyyy'"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear button when a date is selected.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid`.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "firstDayOfWeek",
       "type": "number",
       "description": "First column of the calendar week (0 = Sunday).",
       "default": "0"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "Date | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMinDate` / `mkMaxDate` against the `[min]` and `[max]` inputs."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkDateRangePicker",
     "description": "DateRangePicker — select a start + end date from a single calendar popover.\nThe first click sets the start, the second sets the end (endpoints are\nswapped if picked in reverse), and the hovered range is previewed live.\nImplements `ControlValueAccessor` and a two-way `value` model of\n`MkDateRange`.\n\n```html\n<mk-date-range-picker [(value)]=\"range\" [min]=\"minDate\" clearable />\n```",
     "file": "projects/mk-kit/datetime/date-range-picker/date-range-picker.ts",
     "kind": "component",
     "selector": "mk-date-range-picker",
     "selectors": [
      "mk-date-range-picker"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "MkDateRange",
       "description": "Two-way selected range.",
       "model": true,
       "default": "{ start: null, end: null }"
      },
      {
       "name": "min",
       "type": "Date | null",
       "description": "Earliest selectable date (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "Date | null",
       "description": "Latest selectable date (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "disabledDate",
       "type": "((d: Date) => boolean) | null",
       "description": "Predicate marking individual days as disabled.",
       "default": "null"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when no range is selected.",
       "default": "this.i18n.selectRange"
      },
      {
       "name": "displayFormat",
       "type": "string",
       "description": "Pattern used to render each endpoint.",
       "default": "'MMM d, yyyy'"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear button when a range is selected.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid`.",
       "default": "false"
      },
      {
       "name": "firstDayOfWeek",
       "type": "number",
       "description": "First column of the calendar week (0 = Sunday).",
       "default": "0"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "MkDateRange",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkDateRangeIncomplete` for a half-picked range, `mkMinDate` /\n`mkMaxDate` for ends outside `[min]`/`[max]`, and `mkDateFilter` for an\nend rejected by `[disabledDate]`. A fully empty range passes; compose\nwith `Validators.required` to reject it."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkDateTimePicker",
     "description": "DateTimePicker — one field for a date **and** a time of day. The panel pairs\nan `mk-calendar` with a time list generated from `step`; the value is a\nsingle `Date` carrying both parts in local time (seconds and milliseconds\nzeroed). Implements `ControlValueAccessor` and a two-way `value` model, so it\nworks with `[(ngModel)]`, reactive forms and `[(value)]`.\n\nInteraction: picking a day keeps the panel open and — when a value already\nexists — moves that value to the new day, preserving its time; picking a\ntime commits and closes. With no value yet, the day is held until a time is\nchosen (so a half-picked datetime is never emitted). Typing also works:\n`2026-08-26 14:30`, `2026-08-26T09:05`, `Aug 26, 2026 2:30 pm` and a bare\nISO date (→ midnight) are parsed on Enter/blur.\n\n`min` / `max` bound the whole instant at minute precision: the calendar\ngreys out days outside the range and the time list hides times outside it\non the boundary days. Validation reports `mkMinDate` / `mkMaxDate`.\n\nWhen nested in an `mk-form-field` it adopts the field's id and aria wiring.\n\n```html\n<mk-datetime-picker [(value)]=\"startsAt\" [step]=\"15\" [min]=\"now\" clearable />\n<mk-datetime-picker [(value)]=\"startsAt\" hour12 />\n```",
     "file": "projects/mk-kit/datetime/datetime-picker/datetime-picker.ts",
     "kind": "component",
     "selector": "mk-datetime-picker",
     "selectors": [
      "mk-datetime-picker"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "Date | null",
       "description": "Two-way selected date-time (local; seconds and ms are zero).",
       "model": true,
       "default": "null"
      },
      {
       "name": "min",
       "type": "Date | null",
       "description": "Earliest selectable instant (inclusive, minute precision).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "Date | null",
       "description": "Latest selectable instant (inclusive, minute precision).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "disabledDate",
       "type": "((d: Date) => boolean) | null",
       "description": "Predicate marking individual days as disabled (threaded to the calendar).",
       "default": "null"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "this.i18n.selectDateTime"
      },
      {
       "name": "displayFormat",
       "type": "string | null",
       "description": "Pattern used to render the value in the field. Defaults to\n`'MMM d, yyyy HH:mm'`, or `'MMM d, yyyy h:mm a'` when `hour12` is set.",
       "default": "null"
      },
      {
       "name": "step",
       "type": "number",
       "description": "Interval between generated time options, in minutes.",
       "default": "30"
      },
      {
       "name": "hour12",
       "type": "boolean",
       "description": "Display 12-hour times with AM/PM (the model is a `Date` either way).",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear button when a value is selected.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid`.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "firstDayOfWeek",
       "type": "number",
       "description": "First column of the calendar week (0 = Sunday).",
       "default": "0"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "Date | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMinDate` / `mkMaxDate` against the `[min]` and `[max]` inputs,\ncomparing whole instants at minute precision."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkEventCalendar",
     "description": "Event calendar — a month-grid scheduler view. Renders a 6×7 grid of day\ncells built from `buildMonthMatrix`; each cell lists the events whose\n`date` falls on that day as coloured pills, capped at `maxPerDay` with a\n\"+N more\" line for the remainder.\n\nShares the month-grid rendering, header navigation, and weekday header of\n`mk-calendar` but is display-only (no date selection). Exposes the viewed\nmonth as a two-way `viewDate` model plus `dayClick` / `eventClick` outputs.\n\nWith `editable`, the week/day time grids additionally support drag-to-move\nand drag-to-resize (pointer *and* keyboard — WCAG 2.5.7): times snap to\n`snapMinutes` and the would-be range is emitted via `eventMove` /\n`eventResize` — the calendar never mutates `events` itself.\n\n```html\n<mk-event-calendar [events]=\"events\" [(viewDate)]=\"month\"\n  (eventClick)=\"open($event)\" />\n```",
     "file": "projects/mk-kit/datetime/event-calendar/event-calendar.ts",
     "kind": "component",
     "selector": "mk-event-calendar",
     "selectors": [
      "mk-event-calendar"
     ],
     "inputs": [
      {
       "name": "events",
       "type": "readonly MkCalendarEvent[]",
       "description": "Events to plot onto the grid.",
       "default": "[]"
      },
      {
       "name": "viewDate",
       "type": "Date",
       "description": "Two-way month being viewed (any day within it). Defaults to today.",
       "model": true,
       "default": "new Date()"
      },
      {
       "name": "firstDayOfWeek",
       "type": "number",
       "description": "First column of the week: 0 = Sunday … 6 = Saturday.",
       "default": "0"
      },
      {
       "name": "maxPerDay",
       "type": "number",
       "description": "Max event pills per day before collapsing the rest into \"+N more\".",
       "default": "3"
      },
      {
       "name": "view",
       "type": "MkCalendarView",
       "description": "Presentation: the classic month grid, or a timed `week`/`day` grid.",
       "model": true,
       "default": "'month'"
      },
      {
       "name": "dayStartHour",
       "type": "number",
       "description": "First hour shown on the week/day time grid.",
       "default": "8"
      },
      {
       "name": "dayEndHour",
       "type": "number",
       "description": "Hour the time grid ends at (exclusive).",
       "default": "22"
      },
      {
       "name": "editable",
       "type": "boolean",
       "description": "Week/day views: allow rescheduling events by dragging a pill (move) or its\nbottom edge (resize end time), by pointer or keyboard. Off by default —\nwithout it the grid renders exactly as before (no handles, no ARIA\nadditions, no drag behavior).",
       "default": "false"
      },
      {
       "name": "snapMinutes",
       "type": "number",
       "description": "Snap grid (minutes) for drag/keyboard edits; also the minimum duration.",
       "default": "15"
      }
     ],
     "outputs": [
      {
       "name": "viewDateChange",
       "type": "Date",
       "description": "Emits when `viewDate` changes (two-way binding).",
       "model": true
      },
      {
       "name": "viewChange",
       "type": "MkCalendarView",
       "description": "Emits when `view` changes (two-way binding).",
       "model": true
      },
      {
       "name": "dayClick",
       "type": "Date",
       "description": "Emitted when a day cell is activated (click / Enter)."
      },
      {
       "name": "eventClick",
       "type": "MkCalendarEvent",
       "description": "Emitted when an event pill is clicked (does not also fire `dayClick`).\nMouse-only convenience: the pills are presentational (`aria-hidden`), so\nkeyboard / screen-reader users reach events via the day button — its label\nannounces the day's events and activating it fires `dayClick`."
      },
      {
       "name": "monthChange",
       "type": "Date",
       "description": "Emitted when the viewed range changes via the prev/next buttons."
      },
      {
       "name": "slotClick",
       "type": "Date",
       "description": "Week/day view: an empty hour slot was clicked — the slot's start instant."
      },
      {
       "name": "eventMove",
       "type": "MkCalendarEventEdit",
       "description": "Editable week/day grid: an event pill was dragged (or keyboard-moved) to a\nnew start time and/or day. Carries the would-be `start`/`end` — the\ncalendar does **not** mutate `events`; the consumer owns the data and\napplies the change, typically:\n\n```ts\nonMove = ({ event, start, end }: MkCalendarEventEdit) =>\n  (this.events = this.events.map((e) =>\n    e === event ? { ...e, date: start, start, end } : e,\n  ));\n```"
      },
      {
       "name": "eventResize",
       "type": "MkCalendarEventEdit",
       "description": "Editable week/day grid: the pill's bottom edge was dragged (or\nShift+Arrow-resized) — only `end` differs, never below `snapMinutes` of\nduration. Same consumer-owns-the-data contract as `eventMove`."
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "labelId",
       "type": "string",
       "description": "id of the visible month/year label — wired as the grid's label.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkMiniDate",
     "description": "MiniDate — a compact, popover-free inline date editor with segmented\nday / month / year spin fields (like a native `<input type=\"date\">` but\nthemed and signal-driven). Each segment is an ARIA `spinbutton`: Arrow\nUp/Down step the value (day wraps within the month), Home/End jump to the\nsegment's minimum/maximum, Arrow Left/Right move between segments, and\ntyping digits fills the focused segment and auto-advances (OTP-style). Implements `ControlValueAccessor` and a two-way\n`value` model over a real `Date | null`.\n\nA non-null `Date` is emitted only when all three segments are set and valid;\nthe day is clamped to the month's length (e.g. Feb 31 → 28/29) and the\nresult is clamped to `[min, max]`.\n\n```html\n<mk-mini-date [(value)]=\"date\" order=\"dmy\" [min]=\"minDate\" />\n```",
     "file": "projects/mk-kit/datetime/mini-date/mini-date.ts",
     "kind": "component",
     "selector": "mk-mini-date",
     "selectors": [
      "mk-mini-date"
     ],
     "exportAs": "mkMiniDate",
     "formControl": true,
     "inputs": [
      {
       "name": "min",
       "type": "Date | null",
       "description": "Minimum selectable date (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "Date | null",
       "description": "Maximum selectable date (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "value",
       "type": "Date | null",
       "description": "Two-way value — a real `Date`, or `null` while incomplete.",
       "model": true,
       "default": "null"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling when standalone.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored inside an `mk-form-field`.",
       "default": "'md'"
      },
      {
       "name": "order",
       "type": "MkMiniDateOrder",
       "description": "Segment order.",
       "default": "'dmy'"
      },
      {
       "name": "yearMin",
       "type": "number",
       "description": "Lowest selectable year (for the year spinbutton range).",
       "default": "1900"
      },
      {
       "name": "yearMax",
       "type": "number",
       "description": "Highest selectable year (for the year spinbutton range).",
       "default": "2100"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "Date | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMinDate` / `mkMaxDate` against the `[min]` and `[max]` inputs."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkMonthPicker",
     "description": "MonthPicker — a compact field + popover for picking a **month** (`MMM yyyy`)\nor a **year**. The panel shows a 12-month grid (with year nav) or a 12-year\ngrid (with decade nav). Value is a `Date` at the first day of the selection.\nImplements `ControlValueAccessor` + a two-way `value` model; the panel renders\nin the top layer so it is never clipped.\n\n```html\n<mk-month-picker [(value)]=\"month\" />\n<mk-month-picker mode=\"year\" [(value)]=\"year\" />\n```",
     "file": "projects/mk-kit/datetime/month-picker/month-picker.ts",
     "kind": "component",
     "selector": "mk-month-picker",
     "selectors": [
      "mk-month-picker"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "Date | null",
       "description": "Two-way selected date (first of the month / year).",
       "model": true,
       "default": "null"
      },
      {
       "name": "mode",
       "type": "MkMonthPickerMode",
       "description": "Pick a month or a whole year.",
       "default": "'month'"
      },
      {
       "name": "min",
       "type": "Date | null",
       "description": "Earliest selectable date.",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "Date | null",
       "description": "Latest selectable date.",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "''"
      },
      {
       "name": "displayFormat",
       "type": "string",
       "description": "Display pattern (defaults to `MMM yyyy` / `yyyy`).",
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear button when a value is selected.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "Date | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMinDate` / `mkMaxDate` against the `[min]` and `[max]` inputs,\ncompared at month granularity."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkTimePicker",
     "description": "TimePicker — a 24-hour-canonical time field with an editable input plus a\nscrollable list of times generated from `step`. The time itself is always\n24h canonical regardless of the `hour12` display. Implements\n`ControlValueAccessor` and a two-way `value` model.\n\nThe form value is either a `HH:mm` string (`\"14:30\"`, default) or a `Date`\ncarrying the time in its **local** hours/minutes (`valueFormat=\"date\"`, for\nhosts whose model is a datetime — e.g. migrating off Material's\n`mat-timepicker`); both modes read back either shape and `null` when empty.\nOnly the *emitted* value depends on `valueFormat` — internally the time is\nalways normalised to `HH:mm`, which is also what `min` / `max` compare.\n\nIn `date` mode seconds and milliseconds are zeroed, and the **date part** is\ntaken from the current model value when that is already a `Date` (so editing\nthe time repeatedly never drifts the day); otherwise today's local date is\nused. Assign a `Date` first if the day matters.\n\nType a time (`14:30`, `2:30 pm`) or pick from the ARIA listbox\n(Up/Down/Home/End/Enter/Esc; the active option scrolls into view). When\nnested in an `mk-form-field` it adopts the field's id and aria wiring.\n\n```html\n<mk-time-picker [(value)]=\"time\" [step]=\"15\" hour12 clearable />\n<mk-time-picker valueFormat=\"date\" [(value)]=\"pickupAt\" [step]=\"15\" />\n```",
     "file": "projects/mk-kit/datetime/time-picker/time-picker.ts",
     "kind": "component",
     "selector": "mk-time-picker",
     "selectors": [
      "mk-time-picker"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "string | Date | null",
       "description": "Two-way selected time: a canonical `HH:mm` (24h) string, a `Date` when\n`valueFormat=\"date\"`, or `null`. Either shape may be assigned in either\nmode; it is normalised to the configured format.",
       "model": true,
       "default": "null"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name when the picker is used without an `mk-form-field` label.",
       "default": "''"
      },
      {
       "name": "valueFormat",
       "type": "\"string\" | \"date\"",
       "description": "",
       "default": "'string'"
      },
      {
       "name": "min",
       "type": "string | null",
       "description": "Earliest selectable time `HH:mm` (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "string | null",
       "description": "Latest selectable time `HH:mm` (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "step",
       "type": "number",
       "description": "Interval between generated options, in minutes.",
       "default": "30"
      },
      {
       "name": "hour12",
       "type": "boolean",
       "description": "Display 12-hour time with AM/PM (the model stays 24h).",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "this.i18n.selectTime"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear button when a time is selected.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid`.",
       "default": "false"
      },
      {
       "name": "required",
       "type": "boolean",
       "description": "Mark required (adds `aria-required`). Set by Signal Forms' `[formField]` from the schema.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string | Date | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMinTime` / `mkMaxTime` against the `[min]` and `[max]` inputs.\nThe control value is normalised to `HH:mm` first (so a `Date` model\nvalidates too); both sides are then zero-padded `HH:mm`, so a\nlexicographic compare is a chronological one."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "MkWeekPicker",
     "description": "WeekPicker — pick a whole calendar week from a popover calendar. Hovering a\nday previews its entire week; clicking selects it. The value is an\n`MkWeek` (`{ start, end }`, aligned to `firstDayOfWeek`). Implements\n`ControlValueAccessor` and a two-way `value` model; the panel renders in the\ntop layer so it is never clipped.\n\n```html\n<mk-week-picker [(value)]=\"week\" [firstDayOfWeek]=\"1\" clearable />\n```",
     "file": "projects/mk-kit/datetime/week-picker/week-picker.ts",
     "kind": "component",
     "selector": "mk-week-picker",
     "selectors": [
      "mk-week-picker"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "MkWeek | null",
       "description": "Two-way selected week.",
       "model": true,
       "default": "null"
      },
      {
       "name": "min",
       "type": "Date | null",
       "description": "Earliest selectable date (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "max",
       "type": "Date | null",
       "description": "Latest selectable date (inclusive).",
       "default": "null",
       "transform": "(v) => v ?? null"
      },
      {
       "name": "firstDayOfWeek",
       "type": "number",
       "description": "First column of the calendar week (0 = Sunday). Also anchors the week.",
       "default": "0"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "this.i18n.selectWeek"
      },
      {
       "name": "displayFormat",
       "type": "string",
       "description": "Pattern used to render each endpoint of the week range.",
       "default": "'MMM d'"
      },
      {
       "name": "showWeekNumber",
       "type": "boolean",
       "description": "Prefix the label with the ISO week number, e.g. `W28 · …`.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "clearable",
       "type": "boolean",
       "description": "Show a clear button when a week is selected.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force invalid styling + `aria-invalid`.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "MkWeek | null",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "validate",
       "signature": "(control: AbstractControl): ValidationErrors | null",
       "description": "Reports `mkMinDate` / `mkMaxDate` when the selected week starts before\n`[min]` or ends after `[max]`."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/date-time"
    },
    {
     "name": "addDays",
     "description": "A new date `count` days after `date` (negative to subtract).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date, count: number): Date"
     ]
    },
    {
     "name": "addMonths",
     "description": "A new date `count` months after `date` (negative to subtract). Clamps the\nday of month so e.g. Jan 31 + 1 month = Feb 28/29, not Mar 3.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date, count: number): Date"
     ]
    },
    {
     "name": "buildMonthMatrix",
     "description": "Build a fixed 6×7 matrix of `Date` cells for `viewDate`'s month, including\nthe leading days from the previous month and trailing days from the next so\nevery row is full. `firstDayOfWeek` is 0 (Sunday) … 6 (Saturday).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(viewDate: Date, firstDayOfWeek?: number): Date[][]"
     ]
    },
    {
     "name": "clampDate",
     "description": "Clamp `date` into the inclusive `[min, max]` range (either bound optional).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date, min?: Date | null, max?: Date | null): Date"
     ]
    },
    {
     "name": "endOfMonth",
     "description": "Midnight on the last day of `date`'s month.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date): Date"
     ]
    },
    {
     "name": "endOfWeek",
     "description": "The last day of the week containing `date`, at midnight.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date, firstDayOfWeek?: number): Date"
     ]
    },
    {
     "name": "formatDate",
     "description": "Format `date` using a small pattern set. Supported tokens:\n`yyyy` (4-digit year), `MMMM` (full month), `MMM` (short month),\n`MM` (2-digit month), `dd` (2-digit day), `d` (day), `ddd` (short weekday),\n`HH` / `H` (24-hour, padded / bare), `hh` / `h` (12-hour, padded / bare),\n`mm` (2-digit minutes) and `a` (`AM` / `PM`). Longer tokens are matched\nfirst so `MMMM` wins over `MM`. Month/weekday names come from `names` when\ngiven, else English.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date, pattern: string, names?: MkDateNames): string"
     ]
    },
    {
     "name": "formatISODate",
     "description": "Format `date` as an ISO calendar date `YYYY-MM-DD` (local time).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date): string"
     ]
    },
    {
     "name": "getISOWeek",
     "description": "ISO-8601 week number (1–53) of `date`. Weeks start on Monday and week 1 is\nthe week containing the first Thursday of the year.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date): number"
     ]
    },
    {
     "name": "getMonthNames",
     "description": "Full month names, index 0 = January (from `names`, else English).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(names?: MkDateNames): readonly string[]"
     ]
    },
    {
     "name": "getWeekdayFullName",
     "description": "Full weekday name for `date` (for screen-reader labels).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date, names?: MkDateNames): string"
     ]
    },
    {
     "name": "getWeekdayNames",
     "description": "Weekday header labels ordered to start at `firstDayOfWeek`.\n`format` selects `'short'` (e.g. `Mon`) or `'narrow'` (e.g. `M`).\nLabels come from `names` when given, else English.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(firstDayOfWeek?: number, format?: \"short\" | \"narrow\", names?: MkDateNames): string[]"
     ]
    },
    {
     "name": "isAfter",
     "description": "True when `a` is strictly after `b` (full timestamp comparison).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(a: Date, b: Date): boolean"
     ]
    },
    {
     "name": "isBefore",
     "description": "True when `a` is strictly before `b` (full timestamp comparison).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(a: Date, b: Date): boolean"
     ]
    },
    {
     "name": "isNumericDatePattern",
     "description": "True when `pattern` writes day, month and year as numbers ('dd.MM.yyyy',\n'MM/dd/yy HH:mm') — then it, not `Date.parse`, decides how numeric text\nreads.",
     "file": "projects/mk-kit/datetime/datetime/date-utils.ts",
     "kind": "function",
     "signatures": [
      "(pattern: string): boolean"
     ]
    },
    {
     "name": "isSameDay",
     "description": "True when both dates fall on the same calendar day (local time).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(a: Date, b: Date): boolean"
     ]
    },
    {
     "name": "isSameMonth",
     "description": "True when both dates fall in the same calendar month of the same year.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(a: Date, b: Date): boolean"
     ]
    },
    {
     "name": "parseDateByPattern",
     "description": "Parse `text` by the numeric day/month/year order of a display `pattern` —\n`dd.MM.yyyy` reads day first, `MM/dd/yyyy` month first. `Date.parse` must\nnever see such text: it reads '09.10.2026' as September 10 in every engine.\n\nReturns `null` when the pattern has no numeric `d`/`M`/`y` triple (e.g.\n'MMM d, yyyy'), when `text` is not three numbers, or when they do not form\na real date ('31.02.2026' is rejected, not rolled over). Two-digit years\nare 20xx. The result is local midnight.",
     "file": "projects/mk-kit/datetime/datetime/date-utils.ts",
     "kind": "function",
     "signatures": [
      "(text: string, pattern: string): Date | null"
     ]
    },
    {
     "name": "parseISODate",
     "description": "Parse a `YYYY-MM-DD` string into a local-time `Date`, or `null` if invalid.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(value: string | null | undefined): Date | null"
     ]
    },
    {
     "name": "startOfDay",
     "description": "Midnight (00:00:00.000) on `date`'s calendar day.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date): Date"
     ]
    },
    {
     "name": "startOfMonth",
     "description": "Midnight (00:00:00.000) on the first day of `date`'s month.",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date): Date"
     ]
    },
    {
     "name": "startOfWeek",
     "description": "The first day of the week containing `date`, at midnight. `firstDayOfWeek`\nis the week's starting weekday (0 = Sunday … 6 = Saturday).",
     "file": "projects/core/src/dates.ts",
     "kind": "function",
     "signatures": [
      "(date: Date, firstDayOfWeek?: number): Date"
     ]
    },
    {
     "name": "MkCalendarEvent",
     "description": "A single event plotted onto the `MkEventCalendar`.",
     "file": "projects/mk-kit/datetime/event-calendar/event-calendar.ts",
     "kind": "interface",
     "members": [
      {
       "name": "date",
       "type": "Date",
       "description": "The day the event falls on. Month view places by this alone; in week/day\nview an event with no `start` renders in the all-day strip."
      },
      {
       "name": "start",
       "type": "Date | undefined",
       "description": "Start instant — positions the event on the week/day time grid.",
       "optional": true
      },
      {
       "name": "end",
       "type": "Date | undefined",
       "description": "End instant; defaults to 30 minutes after `start`.",
       "optional": true
      },
      {
       "name": "title",
       "type": "string",
       "description": "Short label shown inside the event pill."
      },
      {
       "name": "color",
       "type": "string | undefined",
       "description": "Optional pill background colour; falls back to `--mk-primary`.",
       "optional": true
      },
      {
       "name": "id",
       "type": "unknown",
       "description": "Optional caller-supplied identifier, echoed back on `eventClick`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkCalendarEventEdit",
     "description": "Payload of `eventMove` / `eventResize`: the untouched source event plus the\nwould-be new time range. The calendar itself never mutates `events` — the\nconsumer owns the data and applies (or rejects) the change.",
     "file": "projects/mk-kit/datetime/event-calendar/event-calendar.ts",
     "kind": "interface",
     "members": [
      {
       "name": "event",
       "type": "MkCalendarEvent",
       "description": "The event that was dragged — the exact object from the `events` input."
      },
      {
       "name": "start",
       "type": "Date",
       "description": "New start instant (snapped to `snapMinutes`)."
      },
      {
       "name": "end",
       "type": "Date",
       "description": "New end instant (snapped; never closer than `snapMinutes` to `start`)."
      }
     ]
    },
    {
     "name": "MkDateRange",
     "description": "A selected date range. Either endpoint may be `null` while incomplete.",
     "file": "projects/mk-kit/datetime/date-range-picker/date-range-picker.ts",
     "kind": "interface",
     "members": [
      {
       "name": "start",
       "type": "Date | null",
       "description": ""
      },
      {
       "name": "end",
       "type": "Date | null",
       "description": ""
      }
     ]
    },
    {
     "name": "MkWeek",
     "description": "A selected calendar week (its first and last day, at midnight).",
     "file": "projects/mk-kit/datetime/week-picker/week-picker.ts",
     "kind": "interface",
     "members": [
      {
       "name": "start",
       "type": "Date",
       "description": ""
      },
      {
       "name": "end",
       "type": "Date",
       "description": ""
      }
     ]
    },
    {
     "name": "MkCalendarView",
     "description": "The calendar's presentation: month grid, or a timed week/day grid.",
     "file": "projects/mk-kit/datetime/event-calendar/event-calendar.ts",
     "kind": "type",
     "definition": "'month' | 'week' | 'day'"
    },
    {
     "name": "MkMiniDateOrder",
     "description": "Segment display order.",
     "file": "projects/mk-kit/datetime/mini-date/mini-date.ts",
     "kind": "type",
     "definition": "'dmy' | 'mdy' | 'ymd'"
    },
    {
     "name": "MkMonthPickerMode",
     "description": "Selection granularity for `MkMonthPicker`.",
     "file": "projects/mk-kit/datetime/month-picker/month-picker.ts",
     "kind": "type",
     "definition": "'month' | 'year'"
    },
    {
     "name": "MkWeekday",
     "description": "Day-of-week index 0 (Sunday) … 6 (Saturday).",
     "file": "projects/core/src/dates.ts",
     "kind": "type",
     "definition": "0 | 1 | 2 | 3 | 4 | 5 | 6"
    }
   ]
  },
  {
   "name": "table",
   "import": "@mk-kit/ui/table",
   "exports": [
    {
     "name": "MkSortHeader",
     "description": "Sort header — attach `mkSortHeader` to a header cell (`<th>`) inside an\nelement carrying `mkSort`. It wraps the projected header text in a real\n`<button>` (so assistive tech hears an operable control), adds a directional\narrow (faint on hover, solid when active), reflects `aria-sort` on the cell,\nand toggles the sort on click or Enter/Space.\n\n```html\n<th mkSortHeader=\"email\" mkSortHeaderLabel=\"Email address\">Email</th>\n```",
     "file": "projects/mk-kit/table/sort/sort-header.ts",
     "kind": "component",
     "selector": "[mkSortHeader]",
     "selectors": [
      "mkSortHeader"
     ],
     "inputs": [
      {
       "name": "mkSortHeader",
       "type": "string",
       "description": "Column id this header sorts by (the `mkSortHeader` value).",
       "default": "''"
      },
      {
       "name": "mkSortHeaderStart",
       "type": "\"asc\" | \"desc\" | undefined",
       "description": "Per-header override for the initial sort direction.",
       "default": "undefined"
      },
      {
       "name": "mkSortHeaderDisabled",
       "type": "boolean",
       "description": "Disable sorting for just this header.",
       "default": "false"
      },
      {
       "name": "mkSortHeaderLabel",
       "type": "string",
       "description": "Accessible label used in sort announcements (defaults to the id).",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "isDisabled",
       "type": "Signal<boolean>",
       "description": "Disabled if this header or the whole `mkSort` is disabled.",
       "readonly": true
      },
      {
       "name": "isActive",
       "type": "Signal<boolean>",
       "description": "Whether this header is the active, non-cleared sort.",
       "readonly": true
      },
      {
       "name": "direction",
       "type": "Signal<MkSortDirection>",
       "description": "Active direction, or `none` when this header is not the active sort.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/sort"
    },
    {
     "name": "MkTable",
     "description": "",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "component",
     "selector": "mk-table",
     "selectors": [
      "mk-table"
     ],
     "inputs": [
      {
       "name": "columns",
       "type": "MkTableColumn<T>[]",
       "description": "Column definitions (order = display order).",
       "required": true
      },
      {
       "name": "data",
       "type": "T[]",
       "description": "Row objects to render.",
       "default": "[]"
      },
      {
       "name": "stickyHeader",
       "type": "boolean",
       "description": "Pin the header to the top of the scroll container.",
       "default": "false"
      },
      {
       "name": "zebra",
       "type": "boolean",
       "description": "Alternate row background for readability.",
       "default": "false"
      },
      {
       "name": "hover",
       "type": "boolean",
       "description": "Highlight rows on hover.",
       "default": "true"
      },
      {
       "name": "density",
       "type": "MkTableDensity",
       "description": "Row density.",
       "default": "'comfortable'"
      },
      {
       "name": "stackAt",
       "type": "number",
       "description": "Width in px below which each row renders as a CARD instead of a table row.\n`0` (default) never stacks.\n\nMeasured on the table's own container, not the viewport — a table in a\nnarrow sidebar should stack on a desktop, and a table on a tablet in\nlandscape should not. Per-column behaviour is set with\n`MkTableColumn.stack`.\n\nA grid cannot survive a phone: eight columns become eight unreadable\nslivers, and horizontal scrolling loses the row you were reading. Cards\nkeep one record together and put its header beside each value.",
       "default": "0"
      },
      {
       "name": "clickableRows",
       "type": "boolean",
       "description": "Style rows as clickable and emit `rowClick`.",
       "default": "false"
      },
      {
       "name": "emptyMessage",
       "type": "string",
       "description": "Message shown when there are no rows.",
       "default": "this.i18n.noData"
      },
      {
       "name": "selectable",
       "type": "boolean",
       "description": "Render a leading checkbox column for row selection.",
       "default": "false"
      },
      {
       "name": "selected",
       "type": "T[]",
       "description": "Two-way bound array of selected rows. Use `[(selected)]` to bind, or read\n`selectionChange`. Rows are compared by `trackKey` when set, else by\nreferential identity.",
       "model": true,
       "default": "[]"
      },
      {
       "name": "trackKey",
       "type": "string | undefined",
       "description": "Property name identifying a row for selection equality. When omitted rows\nare matched by reference."
      },
      {
       "name": "rowClass",
       "type": "((row: T) => string | null | undefined) | null",
       "description": "Optional per-row CSS class: called with each row, the returned string is\nappended to the row's class list (falsy → none). For state the consumer\nowns — an \"active in the side panel\" highlight, an unread accent — that\n`selectable`'s own selected style doesn't cover.",
       "default": "null"
      },
      {
       "name": "expandable",
       "type": "boolean",
       "description": "Render a leading expander column. Each row can reveal a detail panel\nsupplied via an `<ng-template mkTableRowDetail let-row>`.",
       "default": "false"
      },
      {
       "name": "singleExpand",
       "type": "boolean",
       "description": "Allow only one row expanded at a time (accordion).",
       "default": "false"
      },
      {
       "name": "resizableColumns",
       "type": "boolean",
       "description": "Enable drag-to-resize on columns marked `resizable` (data-grid pro).",
       "default": "false"
      },
      {
       "name": "reorderableColumns",
       "type": "boolean",
       "description": "Enable drag-to-reorder of column headers (data-grid pro).",
       "default": "false"
      },
      {
       "name": "groupBy",
       "type": "string | ((row: T) => unknown) | null",
       "description": "Group rows by a column key or an accessor. Renders a collapsible group\nheader row (sticky, with a row count) above each group. Sorting still\napplies within groups; groups follow their first row's sorted position.",
       "default": "null"
      },
      {
       "name": "groupLabel",
       "type": "((value: unknown, rows: T[]) => string) | null",
       "description": "Formats a group header label; defaults to `String(value)`.",
       "default": "null"
      },
      {
       "name": "virtual",
       "type": "boolean",
       "description": "Render only the rows in view (plus `overscan`) — for tables of\nthousands of rows. The `<table>` scrolls inside its own box sized by\n`height` / `maxHeight` (`max-height: 60vh` when neither is\nset) with the header pinned; spacer rows keep the scrollbar honest.\n\nWorks with sorting, selection (select-all still covers every row), tree\nrows, grouping (group headers are rows too), expandable detail rows (their\nheight is measured once rendered; an unmeasured detail counts as one row)\nand the header filter row. Falls back to the full render while stacked\ninto cards. Export and select-all always see every row, not the window.",
       "default": "false"
      },
      {
       "name": "rowHeight",
       "type": "number | null",
       "description": "Height (px) of one row in virtual mode. Leave unset to have it measured\nfrom the first rendered row — which follows `density` and\n`data-mk-density` automatically — starting from 44 (comfortable).",
       "default": "null",
       "transform": "(v) => (v == null || v === '' ? null : numberAttribute(v))"
      },
      {
       "name": "overscan",
       "type": "number",
       "description": "Rows rendered beyond each edge of the viewport in virtual mode.",
       "default": "6"
      },
      {
       "name": "height",
       "type": "string | number | null",
       "description": "Fixed height of the scroll box (CSS length, or px as a number).",
       "default": "null"
      },
      {
       "name": "maxHeight",
       "type": "string | number | null",
       "description": "Maximum height of the scroll box (CSS length, or px as a number).",
       "default": "null"
      },
      {
       "name": "filterable",
       "type": "boolean",
       "description": "Render a second header row with a filter control per column — a text\nbox, a select, a number or a date field as the column's\n`MkTableColumn.filter` says. Values live in `filters`.",
       "default": "false"
      },
      {
       "name": "filters",
       "type": "MkTableFilters",
       "description": "The active filters, keyed by column key (`[(filters)]`; `filtersChange`\nemits the whole map on every edit). Text filters hold the typed string,\nselect filters the chosen option value, number / date filters the lower\nbound or a `{ min, max }` range. Set programmatically to pre-filter.",
       "model": true,
       "default": "{}"
      },
      {
       "name": "clientFilter",
       "type": "boolean",
       "description": "Filter rows in the browser (default). Turn off when the server applies\nthe filters — `MkTableDataSource.setFilters($event)` on `filtersChange` —\nso the page it returns is shown as-is.",
       "default": "true"
      },
      {
       "name": "childrenKey",
       "type": "string | null",
       "description": "Tree rows: the property on each row holding its child rows (`T[]`). When\nset, the table renders a tree grid — child rows are indented under their\nparent behind an expand toggle in the first column, sorting applies per\nsibling group, and ArrowRight / ArrowLeft on a row open / close it.",
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "selectedChange",
       "type": "T[]",
       "description": "Emits when `selected` changes (two-way binding).",
       "model": true
      },
      {
       "name": "filtersChange",
       "type": "MkTableFilters",
       "description": "Emits when `filters` changes (two-way binding).",
       "model": true
      },
      {
       "name": "sortChange",
       "type": "MkSortChange",
       "description": "Emitted when the sort column/direction changes."
      },
      {
       "name": "rowClick",
       "type": "T",
       "description": "Emitted when a row is clicked (enable via `clickableRows`)."
      },
      {
       "name": "selectionChange",
       "type": "T[]",
       "description": "Emitted with the new selection whenever it changes (enable via `selectable`)."
      },
      {
       "name": "expandedChange",
       "type": "T[]",
       "description": "Emitted with the currently expanded rows whenever they change."
      },
      {
       "name": "columnResize",
       "type": "MkColumnResize",
       "description": "Emitted when a column is resized (px)."
      },
      {
       "name": "columnReorder",
       "type": "string[]",
       "description": "Emitted with the new column key order after a reorder."
      },
      {
       "name": "cellEdit",
       "type": "MkCellEdit<T>",
       "description": "Emitted when an inline-editable cell is saved."
      },
      {
       "name": "groupToggle",
       "type": "MkGroupToggle",
       "description": "Emitted when a group header is expanded or collapsed."
      },
      {
       "name": "treeToggle",
       "type": "MkTreeToggle<T>",
       "description": "Emitted when a parent row is expanded or collapsed (tree mode)."
      }
     ],
     "methods": [
      {
       "name": "setFilter",
       "signature": "(key: string, value: unknown): void",
       "description": "Set one column's filter (`null` / `''` clears it). Updates\n`filters` and emits `filtersChange`; a no-op when unchanged."
      },
      {
       "name": "clearFilter",
       "signature": "(key: string): void",
       "description": "Clear one column's filter."
      },
      {
       "name": "clearFilters",
       "signature": "(): void",
       "description": "Clear every filter."
      },
      {
       "name": "scrollToRow",
       "signature": "(target: unknown, by?: \"index\" | \"key\"): boolean",
       "description": "Scroll a row into view. A number is the row's **display index** — its\nposition among the rendered rows, group headers included, after sorting,\nfiltering and tree expansion; anything else is a row key (the `trackKey`\nvalue, or the row object when there is none). Pass `'key'` to look a\nnumeric key up. Returns `false` when the row is not currently displayed\n(filtered out, under a collapsed parent or group).\n\nIn virtual mode the row lands at the top of the viewport, just under the\nheader; otherwise it is scrolled to the nearest edge."
      },
      {
       "name": "isTreeExpanded",
       "signature": "(row: T): boolean",
       "description": "Whether a parent row's children are currently shown (tree mode)."
      },
      {
       "name": "toggleTreeRow",
       "signature": "(row: T, event?: Event): void",
       "description": "Show or hide a parent row's children (tree mode)."
      },
      {
       "name": "expandAllRows",
       "signature": "(): void",
       "description": "Expand every parent row (tree mode)."
      },
      {
       "name": "collapseAllRows",
       "signature": "(): void",
       "description": "Collapse every parent row (tree mode)."
      },
      {
       "name": "getExportRows",
       "signature": "(options?: MkTableExportRowsOptions): MkTableExportRows<T>",
       "description": "The rows and columns an export writes — exactly what `exportCsv`\nserialises, for other formats (XLSX, PDF, the clipboard, …): rows in\ndisplay order with the current sort and header `filters` applied\n(every matching row, never just the virtual window) and tree children\n(`childrenKey`) flattened under their parent whether or not they are\nexpanded, optionally only the selected ones; columns in the table's\ncurrent order, restricted to `options.columns` when given, each carrying\nits header and `format` so what the user saw is what gets written.\n\n```ts\nconst { rows, columns } = table.getExportRows({ selectedOnly: true });\nconst sheet = rows.map((row) =>\n  Object.fromEntries(columns.map((c) => [c.header ?? c.key, c.format ? c.format(row[c.key], row) : row[c.key]])),\n);\n```"
      },
      {
       "name": "exportCsv",
       "signature": "(options?: MkTableExportOptions): string",
       "description": "The table's rows as CSV: current column order, column formatters applied,\nsorted and filtered the way they are shown, tree children flattened under\ntheir parent whether or not they are expanded. Downloads the file (default name\n`table.csv`) and returns the text. Built on `getExportRows`."
      },
      {
       "name": "collapseAllGroups",
       "signature": "(): void",
       "description": "Collapse every group."
      },
      {
       "name": "expandAllGroups",
       "signature": "(): void",
       "description": "Expand every group."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/table"
    },
    {
     "name": "MkSort",
     "description": "Sort coordinator — apply `mkSort` to a table (or any container) to track\nwhich column is sorted and in which direction. It holds no data: register\nheaders with `mkSortHeader`, then re-sort your rows in the\n`(mkSortChange)` handler. Mirrors the Angular Material `matSort` model but\nsignal-based.\n\nClicking a header cycles asc → desc → unsorted (set `mkSortDisableClear` to\ncycle asc ↔ desc only). `mkSortStart` flips the initial direction.\n\n```html\n<table mkSort mkSortActive=\"name\" mkSortDirection=\"asc\"\n       (mkSortChange)=\"sortData($event)\">\n  <thead><tr>\n    <th mkSortHeader=\"name\">Name</th>\n    <th mkSortHeader=\"size\" mkSortHeaderStart=\"desc\">Size</th>\n  </tr></thead>\n  …\n</table>\n```",
     "file": "projects/mk-kit/table/sort/sort.ts",
     "kind": "directive",
     "selector": "[mkSort]",
     "selectors": [
      "mkSort"
     ],
     "exportAs": "mkSort",
     "inputs": [
      {
       "name": "active",
       "type": "string",
       "description": "Id of the currently sorted column (two-way; empty when unsorted).",
       "model": true,
       "default": "''"
      },
      {
       "name": "direction",
       "type": "MkSortDirection",
       "description": "Current sort direction (two-way).",
       "model": true,
       "default": "'none'"
      },
      {
       "name": "mkSortStart",
       "type": "\"asc\" | \"desc\"",
       "description": "Direction the first click on a header applies. Default `asc`.",
       "default": "'asc'"
      },
      {
       "name": "mkSortDisabled",
       "type": "boolean",
       "description": "Disable sorting for every header.",
       "default": "false"
      },
      {
       "name": "mkSortDisableClear",
       "type": "boolean",
       "description": "Remove the \"unsorted\" step so headers cycle asc ↔ desc only.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "activeChange",
       "type": "string",
       "description": "Emits when `active` changes (two-way binding).",
       "model": true
      },
      {
       "name": "directionChange",
       "type": "MkSortDirection",
       "description": "Emits when `direction` changes (two-way binding).",
       "model": true
      },
      {
       "name": "sortChange",
       "type": "MkSortState",
       "description": "Emits the new sort state whenever a header is activated."
      }
     ],
     "methods": [
      {
       "name": "sort",
       "signature": "(header: MkSortable): void",
       "description": "Advance the sort state for the given header (called on click/keyboard)."
      },
      {
       "name": "isActive",
       "signature": "(id: string): boolean",
       "description": "Whether the given column id is the active, non-cleared sort."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/sort"
    },
    {
     "name": "MkTableCell",
     "description": "Marks an `<ng-template>` as the renderer for one column's cells, named by the\ncolumn `key`. Without it a cell can only be text — `MkTableColumn.format`\nreturns a string — so anything richer (a status tag, an avatar, a progress\nbar, an action button) meant abandoning `mk-table` for a hand-rolled\n`<table>`.\n\nThe value is the template's implicit context and the row is available as\n`let-row`:\n\n```html\n<mk-table [columns]=\"cols\" [data]=\"rows()\">\n  <ng-template mkTableCell=\"status\" let-value let-row=\"row\">\n    <mk-tag [tone]=\"toneFor(value)\">{{ label(value) }}</mk-tag>\n  </ng-template>\n</mk-table>\n```\n\nA column with both a template and a `format` uses the template; `format`\nstill applies to sorting/export paths that need a string.",
     "file": "projects/mk-kit/table/table/table-cell.ts",
     "kind": "directive",
     "selector": "[mkTableCell]",
     "selectors": [
      "mkTableCell"
     ],
     "inputs": [
      {
       "name": "mkTableCell",
       "type": "string",
       "description": "Column key whose cells this template renders.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "template",
       "type": "TemplateRef<MkTableCellContext<T>>",
       "description": "The projected template, rendered once per cell in that column.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/table"
    },
    {
     "name": "MkTableRowDetail",
     "description": "Marks an `<ng-template>` as the expandable detail content for `MkTable`\nrows. The template's implicit context is the row object, so consumers can\ndestructure it with `let-row`:\n\n```html\n<mk-table [columns]=\"cols\" [data]=\"rows()\" expandable>\n  <ng-template mkTableRowDetail let-row>\n    <dl>… {{ row.notes }} …</dl>\n  </ng-template>\n</mk-table>\n```",
     "file": "projects/mk-kit/table/table/table-row-detail.ts",
     "kind": "directive",
     "selector": "[mkTableRowDetail]",
     "selectors": [
      "mkTableRowDetail"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "template",
       "type": "TemplateRef<{ $implicit: T; }>",
       "description": "The projected detail template, rendered once per expanded row.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/table"
    },
    {
     "name": "MkTableDataSource",
     "description": "Server-side data adapter for `mk-table` — the page/sort/filter plumbing every\nadmin screen otherwise hand-rolls. A plain class (no component, no injection\nrequired): give it a fetcher and bind its signals; every setter re-queries\nthe server and **stale responses never overwrite newer state** (latest-wins).\n\n- `setFilter` is debounced (default 300 ms); page, sort and page size load\n  immediately. Sort, filter and page-size changes reset to page 1.\n- `rows` keeps its previous value while loading and on error, so the table\n  never blanks mid-transition; `error` is cleared by the next successful\n  load.\n- Created in an injection context (a component field initialiser) it hooks\n  `DestroyRef` and cleans up automatically; anywhere else, call\n  `destroy` yourself.\n\n```ts\ninterface User { id: number; name: string; email: string; }",
     "file": "projects/mk-kit/table/data-source.ts",
     "kind": "class",
     "typeParams": "<T>",
     "methods": [
      {
       "name": "setPage",
       "signature": "(page: number): void",
       "description": "Jump to a 1-based page and load it immediately."
      },
      {
       "name": "setPageSize",
       "signature": "(size: number): void",
       "description": "Change the page size; resets to page 1 and loads immediately."
      },
      {
       "name": "setSort",
       "signature": "(sort: MkSortState | MkSortChange | null): void",
       "description": "Change the sort; resets to page 1 and loads immediately. Accepts either\nthe `mkSort` directive's `MkSortState` or `mk-table`'s\n`MkSortChange` payload; a cleared sort (`direction: 'none'` or an\nempty column id) normalises to `null`. A no-op when the sort is unchanged."
      },
      {
       "name": "setFilter",
       "signature": "(query: string): void",
       "description": "Change the free-text filter. The `filter` signal updates (and the page\nresets to 1) immediately, but the request is debounced — `refresh()`\nflushes it early. A no-op when the query is unchanged."
      },
      {
       "name": "setQuery",
       "signature": "(query: MkQueryGroup | null): void",
       "description": "Set (or clear with `null`) the structured query from `mk-query-builder`.\nEmpty groups and unfinished rules are dropped before the request; a query\nwith nothing left is sent as `null`. Resets to page 1 and loads at once."
      },
      {
       "name": "setFilters",
       "signature": "(filters: MkTableFilters | null): void",
       "description": "Set (or clear with `null` / `{}`) the per-column filters from `mk-table`'s\nheader filter row — bind `(filtersChange)=\"ds.setFilters($event)\"` and\nturn the table's `clientFilter` off. Empty entries are dropped before the\nrequest; nothing left is sent as `null`. Resets to page 1 and loads at\nonce (the table already debounces nothing, so debounce the fetcher if\nyour API needs it). A no-op when unchanged."
      },
      {
       "name": "refresh",
       "signature": "(): void",
       "description": "Re-run the current request immediately (e.g. after a mutation). Flushes a\npending debounced filter, since the request reads the live filter value."
      },
      {
       "name": "reload",
       "signature": "(): void",
       "description": "Back to page 1 and load — the \"filters changed outside the search box\"\ncase. Unlike `setPage`, this loads even when already on page 1, so\ncallers no longer need `page() === 1 ? refresh() : setPage(1)`."
      },
      {
       "name": "connectSort",
       "signature": "(sort: MkSort): void",
       "description": "Pipe an `mkSort` directive's changes into `setSort`. Idempotent per\ndirective instance; all subscriptions are released by `destroy`."
      },
      {
       "name": "destroy",
       "signature": "(): void",
       "description": "Cancel pending work: the debounce timer, any in-flight Observable fetch,\nand `connectSort` subscriptions. In-flight Promise settles are discarded.\nCalled automatically on host destroy when created in an injection context."
      }
     ],
     "properties": [
      {
       "name": "rows",
       "type": "Signal<T[]>",
       "description": "Rows of the current page (`[]` until the first load lands).",
       "readonly": true
      },
      {
       "name": "total",
       "type": "Signal<number>",
       "description": "Total row count across all pages (feed to `mk-pagination`'s `total`).",
       "readonly": true
      },
      {
       "name": "loading",
       "type": "Signal<boolean>",
       "description": "True while the LATEST request is in flight.",
       "readonly": true
      },
      {
       "name": "error",
       "type": "Signal<unknown>",
       "description": "The last load's error, or `null`; cleared by the next successful load.",
       "readonly": true
      },
      {
       "name": "page",
       "type": "Signal<number>",
       "description": "Current 1-based page.",
       "readonly": true
      },
      {
       "name": "pageSize",
       "type": "Signal<number>",
       "description": "Current page size.",
       "readonly": true
      },
      {
       "name": "sort",
       "type": "Signal<MkSortState | null>",
       "description": "Current sort, or `null` when unsorted.",
       "readonly": true
      },
      {
       "name": "filter",
       "type": "Signal<string>",
       "description": "Current filter query (updates immediately, even while debouncing).",
       "readonly": true
      },
      {
       "name": "query",
       "type": "Signal<MkQueryGroup | null>",
       "description": "Current structured query, or `null`.",
       "readonly": true
      },
      {
       "name": "filters",
       "type": "Signal<MkTableFilters | null>",
       "description": "Current per-column filters, or `null`.",
       "readonly": true
      },
      {
       "name": "empty",
       "type": "Signal<boolean>",
       "description": "True when a settled load reported no rows at all.",
       "readonly": true
      }
     ],
     "docs": "/components/table#data-source"
    },
    {
     "name": "mkClientFetcher",
     "description": "In-memory `MkDataFetcher`: filter, sort and slice a full row set that\nthe app already holds (an API that returns everything). Lets a client-side\nlist use `MkTableDataSource` — same pager, footer and API as a\nserver-paged one — without hand-rolling `filtered/sorted/paged` computeds.\n\n```ts\nds = new MkTableDataSource(mkClientFetcher(() => this.rows()));\n```",
     "file": "projects/mk-kit/table/data-source.ts",
     "kind": "function",
     "signatures": [
      "<T>(rows: () => readonly T[], opts?: MkClientFetcherOptions<T>): (req: MkDataRequest) => Promise<MkDataPage<T>>"
     ]
    },
    {
     "name": "mkCompactFilters",
     "description": "Drop the empty entries of a filter map (`null` when nothing is left).",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "function",
     "signatures": [
      "(filters: MkTableFilters | null | undefined): MkTableFilters | null"
     ]
    },
    {
     "name": "mkDownloadText",
     "description": "Trigger a browser download of `text` as a file. No-op outside a DOM\n(server-side rendering); returns whether a download was started.",
     "file": "projects/mk-kit/table/export.ts",
     "kind": "function",
     "signatures": [
      "(text: string, filename: string, type?: string): boolean"
     ]
    },
    {
     "name": "mkExportCsv",
     "description": "Serialise `rows` as CSV and download it. Returns the CSV text so callers\ncan also keep it (tests, previews, uploads).",
     "file": "projects/mk-kit/table/export.ts",
     "kind": "function",
     "signatures": [
      "<T>(rows: readonly T[], columns?: readonly MkCsvColumn<T>[], options?: MkCsvExportOptions): string"
     ]
    },
    {
     "name": "mkToCsv",
     "description": "Serialise `rows` as CSV text.\n\nWithout `columns` every key of the first row is exported in its own order.\nColumn formatters are applied, so what the user saw in the table is what\nlands in the file.",
     "file": "projects/mk-kit/table/export.ts",
     "kind": "function",
     "signatures": [
      "<T>(rows: readonly T[], columns?: readonly MkCsvColumn<T>[], options?: MkCsvOptions): string"
     ]
    },
    {
     "name": "MkCellEdit",
     "description": "Payload emitted by `MkTable.cellEdit` when an editable cell is saved.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "typeParams": "<T = Record<string, unknown>>",
     "members": [
      {
       "name": "row",
       "type": "T",
       "description": "The edited row."
      },
      {
       "name": "key",
       "type": "string",
       "description": "The column key that was edited."
      },
      {
       "name": "value",
       "type": "string",
       "description": "The new (string) value the user entered."
      }
     ]
    },
    {
     "name": "MkClientFetcherOptions",
     "description": "Options for `mkClientFetcher`.",
     "file": "projects/mk-kit/table/data-source.ts",
     "kind": "interface",
     "typeParams": "<T>",
     "members": [
      {
       "name": "match",
       "type": "((row: T, query: string) => boolean) | undefined",
       "description": "Row matcher for `setFilter` text; default: case-insensitive substring over every string/number field.",
       "optional": true
      },
      {
       "name": "compare",
       "type": "((a: T, b: T, sort: MkSortState) => number) | undefined",
       "description": "Comparator for an active sort; default: locale compare on `row[sort.active]`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkColumnResize",
     "description": "Payload emitted by `MkTable.columnResize` after a column resize.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": "The resized column's key."
      },
      {
       "name": "width",
       "type": "number",
       "description": "The new width in pixels."
      }
     ]
    },
    {
     "name": "MkCsvColumn",
     "description": "A column to export: the row property, its header, and an optional formatter.",
     "file": "projects/mk-kit/table/export.ts",
     "kind": "interface",
     "typeParams": "<T = Record<string, unknown>>",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": "Property key on each row object supplying the cell value."
      },
      {
       "name": "header",
       "type": "string | undefined",
       "description": "Header text; defaults to `key`.",
       "optional": true
      },
      {
       "name": "format",
       "type": "((value: unknown, row: T) => string) | undefined",
       "description": "Formatter turning the raw value into cell text (same shape as `MkTableColumn.format`).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkCsvExportOptions",
     "description": "Options for `mkExportCsv`.",
     "file": "projects/mk-kit/table/export.ts",
     "kind": "interface",
     "extends": [
      "MkCsvOptions"
     ],
     "members": [
      {
       "name": "filename",
       "type": "string | undefined",
       "description": "File name for the download (default `export.csv`; `.csv` is appended if missing).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkCsvOptions",
     "description": "",
     "file": "projects/mk-kit/table/export.ts",
     "kind": "interface",
     "members": [
      {
       "name": "delimiter",
       "type": "string | undefined",
       "description": "Field separator (default `,`; use `;` for locales whose Excel expects it).",
       "optional": true
      },
      {
       "name": "header",
       "type": "boolean | undefined",
       "description": "Emit the header row first (default `true`).",
       "optional": true
      },
      {
       "name": "newline",
       "type": "string | undefined",
       "description": "Line terminator (default `\\r\\n`, per RFC 4180).",
       "optional": true
      },
      {
       "name": "bom",
       "type": "boolean | undefined",
       "description": "Prefix a UTF-8 byte-order mark (default `true`) so Excel reads accented\ncharacters correctly. Only affects the downloaded file / returned text.",
       "optional": true
      },
      {
       "name": "sanitize",
       "type": "boolean | undefined",
       "description": "Neutralise spreadsheet formula injection (default `true`): a text cell\nstarting with `=`, `+`, `-`, `@`, tab or CR is prefixed with `'` so a\nmalicious value cannot execute when opened in Excel / Sheets. Numbers\nare never touched, so `-5` stays `-5`.",
       "optional": true
      },
      {
       "name": "childrenKey",
       "type": "string | undefined",
       "description": "Property holding child rows; when set, trees are flattened depth-first.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDataPage",
     "description": "One page of server data returned by a `MkDataFetcher`.",
     "file": "projects/mk-kit/table/data-source.ts",
     "kind": "interface",
     "typeParams": "<T>",
     "members": [
      {
       "name": "rows",
       "type": "T[]",
       "description": "The rows for the requested page."
      },
      {
       "name": "total",
       "type": "number",
       "description": "Total number of rows across ALL pages (drives the pager)."
      }
     ]
    },
    {
     "name": "MkDataRequest",
     "description": "The request handed to a `MkDataFetcher` on every load.",
     "file": "projects/mk-kit/table/data-source.ts",
     "kind": "interface",
     "members": [
      {
       "name": "page",
       "type": "number",
       "description": "1-based page index, matching `mk-pagination`."
      },
      {
       "name": "pageSize",
       "type": "number",
       "description": "Number of rows per page."
      },
      {
       "name": "sort",
       "type": "MkSortState | null",
       "description": "Active sort, or `null` when unsorted (cleared sorts normalise to `null`)."
      },
      {
       "name": "filter",
       "type": "string",
       "description": "Free-text filter query (`''` = none)."
      },
      {
       "name": "query",
       "type": "MkQueryGroup | null",
       "description": "Structured filter from `mk-query-builder` (`null` = none). Compacted: no empty groups or unfinished rules."
      },
      {
       "name": "filters",
       "type": "MkTableFilters | null",
       "description": "Per-column filters from `mk-table`'s header filter row (`null` = none),\nkeyed by column key with empty entries dropped — see\n`MkTableDataSource.setFilters`."
      }
     ]
    },
    {
     "name": "MkGroupToggle",
     "description": "",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "unknown",
       "description": "The toggled group's value."
      },
      {
       "name": "collapsed",
       "type": "boolean",
       "description": "Whether the group is now collapsed."
      }
     ]
    },
    {
     "name": "MkSortable",
     "description": "The minimal shape `MkSort` needs from a header. Implemented by\n`MkSortHeader`; declared separately so the coordinator does not depend\non the header's concrete type (avoids a circular import).",
     "file": "projects/mk-kit/table/sort/sort.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "(): string",
       "description": ""
      },
      {
       "name": "start",
       "type": "(): \"asc\" | \"desc\" | undefined",
       "description": ""
      },
      {
       "name": "disabled",
       "type": "(): boolean",
       "description": ""
      },
      {
       "name": "sortLabel",
       "type": "(): string",
       "description": ""
      }
     ]
    },
    {
     "name": "MkSortChange",
     "description": "Payload emitted by `MkTable.sortChange`.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": "Column key sorted by."
      },
      {
       "name": "direction",
       "type": "MkSortDirection",
       "description": "Resulting direction (`none` when sorting was cleared)."
      }
     ]
    },
    {
     "name": "MkSortState",
     "description": "Current sort state emitted by `MkSort.mkSortChange`.",
     "file": "projects/mk-kit/table/sort/sort.ts",
     "kind": "interface",
     "members": [
      {
       "name": "active",
       "type": "string",
       "description": "Id of the column being sorted by (empty when cleared)."
      },
      {
       "name": "direction",
       "type": "MkSortDirection",
       "description": "Sort direction (`none` when cleared)."
      }
     ]
    },
    {
     "name": "MkTableCellContext",
     "description": "Context handed to an `[mkTableCell]` template.",
     "file": "projects/mk-kit/table/table/table-cell.ts",
     "kind": "interface",
     "typeParams": "<T = unknown>",
     "members": [
      {
       "name": "$implicit",
       "type": "unknown",
       "description": "The cell's raw value (the row's property named by the column key)."
      },
      {
       "name": "row",
       "type": "T",
       "description": "The whole row, for cells that need more than one field."
      }
     ]
    },
    {
     "name": "MkTableColumn",
     "description": "Column definition for `MkTable`.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "typeParams": "<T = Record<string, unknown>>",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": "Property key on each row object supplying the cell value."
      },
      {
       "name": "header",
       "type": "string",
       "description": "Visible column header text."
      },
      {
       "name": "sortable",
       "type": "boolean | undefined",
       "description": "Allow sorting by this column.",
       "optional": true
      },
      {
       "name": "align",
       "type": "MkTableAlign | undefined",
       "description": "Cell/header alignment (default `start`).",
       "optional": true
      },
      {
       "name": "width",
       "type": "string | undefined",
       "description": "Fixed column width (any CSS length).",
       "optional": true
      },
      {
       "name": "format",
       "type": "((value: unknown, row: T) => string) | undefined",
       "description": "Optional formatter turning the raw value into display text.",
       "optional": true
      },
      {
       "name": "resizable",
       "type": "boolean | undefined",
       "description": "Allow the user to drag-resize this column (needs `resizableColumns`).",
       "optional": true
      },
      {
       "name": "editable",
       "type": "boolean | undefined",
       "description": "Make this column's cells inline-editable (double-click / Enter).",
       "optional": true
      },
      {
       "name": "pinned",
       "type": "\"left\" | \"right\" | undefined",
       "description": "Pin (freeze) this column to a side while the body scrolls horizontally.",
       "optional": true
      },
      {
       "name": "minWidth",
       "type": "number | undefined",
       "description": "Minimum width in px when resizing (default 60).",
       "optional": true
      },
      {
       "name": "stack",
       "type": "\"footer\" | \"title\" | \"hide\" | undefined",
       "description": "What becomes of this column when the table stacks into cards\n(see `MkTable.stackAt`). Omitted, the column renders as a labelled\nfield: its `header` on one side, its value on the other.\n\n- `'title'` — the card's heading. No label; the value identifies the\n  record at a glance (an order number, a product name). Mark one, or two\n  if something short belongs beside it such as a status or a total.\n- `'footer'` — pinned to the bottom of the card, full width and unlabelled.\n  Where an actions cell belongs: buttons read as buttons, rather than as\n  the answer to a label.\n- `'hide'` — not rendered at all. Not merely invisible: the cell is never\n  created, so a screen reader does not read it either. For columns that\n  only earn their place while scanning a grid, and especially for anything\n  an expandable row detail already repeats.",
       "optional": true
      },
      {
       "name": "filter",
       "type": "false | MkTableFilterKind | undefined",
       "description": "The header-row filter control for this column (rendered when the table is\n`MkTable.filterable`). Omitted, a filterable table gives the column a\ntext filter; `false` leaves its filter cell empty.\n\n- `'text'` — case-insensitive *contains* on the displayed (formatted) text.\n- `'select'` — equality against one of `filterOptions`; without\n  options, the distinct values found in `data`.\n- `'number'` / `'date'` — the control keeps rows whose value is **≥** the\n  entry. Set `{ min, max }` through `MkTable.filters` for an\n  inclusive range. Dates compare by local calendar day.",
       "optional": true
      },
      {
       "name": "filterOptions",
       "type": "readonly (string | number | MkTableFilterOption)[] | undefined",
       "description": "Options of a `select` filter — strings / numbers, or `{ value, label }`.\nOmitted: every distinct value of the column in `data`, sorted.",
       "optional": true
      },
      {
       "name": "filterPlaceholder",
       "type": "string | undefined",
       "description": "Placeholder of the filter control (text: `i18n.filter`; number / date: `i18n.filterMin`).",
       "optional": true
      },
      {
       "name": "compare",
       "type": "((a: T, b: T) => number) | undefined",
       "description": "Custom ordering for this column, used instead of the built-in\nvalue comparison whenever it sorts. Return a negative number when `a`\ncomes first. The table negates it for descending order, so keep the\nfunction pure. Lets a file list keep folders first, or a status column\nsort by rank rather than alphabet.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTableDataSourceOptions",
     "description": "Construction options for `MkTableDataSource`.",
     "file": "projects/mk-kit/table/data-source.ts",
     "kind": "interface",
     "members": [
      {
       "name": "pageSize",
       "type": "number | undefined",
       "description": "Initial rows per page (default 10, matching `mk-pagination`).",
       "optional": true
      },
      {
       "name": "filterDebounce",
       "type": "number | undefined",
       "description": "Debounce for `MkTableDataSource.setFilter` in ms (default 300).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTableExportOptions",
     "description": "Options for `MkTable.exportCsv`.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "extends": [
      "MkCsvExportOptions",
      "MkTableExportRowsOptions"
     ],
     "members": [
      {
       "name": "download",
       "type": "boolean | undefined",
       "description": "Start the browser download (default `true`); `false` just returns the text.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTableExportRows",
     "description": "What `MkTable.getExportRows` returns: the rows and the columns to write them with.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "typeParams": "<T>",
     "members": [
      {
       "name": "rows",
       "type": "T[]",
       "description": "The rows in display order — sorted the way they are shown, tree children\nflattened under their parent (expanded or not), selection applied when\n`selectedOnly` was set."
      },
      {
       "name": "columns",
       "type": "MkCsvColumn<T>[]",
       "description": "The columns in the table's current (user-reordered) order, restricted to\nthe requested keys, each with its header and formatter."
      }
     ]
    },
    {
     "name": "MkTableExportRowsOptions",
     "description": "Options for `MkTable.getExportRows` — which rows and columns to export.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "members": [
      {
       "name": "selectedOnly",
       "type": "boolean | undefined",
       "description": "Export only the selected rows (default: every row).",
       "optional": true
      },
      {
       "name": "columns",
       "type": "readonly string[] | undefined",
       "description": "Restrict to these column keys, in table order (default: every column).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTableFilterOption",
     "description": "One option of a `select` header filter.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "members": [
      {
       "name": "value",
       "type": "unknown",
       "description": "The value compared against the cell (by `String()` equality)."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Visible option text."
      }
     ]
    },
    {
     "name": "MkTableFilterRange",
     "description": "An inclusive range accepted as the value of a `number` or `date` filter\n(dates as `YYYY-MM-DD`, `Date` or a timestamp). Either bound may be omitted.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "typeParams": "<V = number | string | Date>",
     "members": [
      {
       "name": "min",
       "type": "V | null | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "max",
       "type": "V | null | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTableGroup",
     "description": "A group of rows produced by `MkTable.groupBy`.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "typeParams": "<T = Record<string, unknown>>",
     "members": [
      {
       "name": "key",
       "type": "unknown",
       "description": "The shared group value."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Display label for the group header."
      },
      {
       "name": "rows",
       "type": "T[]",
       "description": "The rows in this group, in display (sorted) order."
      }
     ]
    },
    {
     "name": "MkTreeToggle",
     "description": "Payload of `(treeToggle)`: a parent row was expanded or collapsed.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "interface",
     "typeParams": "<T = Record<string, unknown>>",
     "members": [
      {
       "name": "row",
       "type": "T",
       "description": "The parent row."
      },
      {
       "name": "expanded",
       "type": "boolean",
       "description": "Whether its child rows are now shown."
      }
     ]
    },
    {
     "name": "MkDataFetcher",
     "description": "Loads one page of data for a `MkDataRequest`. May return a `Promise`\n(e.g. `fetch`) or an `Observable` (e.g. `HttpClient`); an Observable is\ntreated as single-shot — the first emission wins and the subscription is\nreleased.",
     "file": "projects/mk-kit/table/data-source.ts",
     "kind": "type",
     "typeParams": "<T>",
     "definition": "( req: MkDataRequest, ) => Promise<MkDataPage<T>> | Observable<MkDataPage<T>>"
    },
    {
     "name": "MkSortDirection",
     "description": "Sort direction; `none` means unsorted.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "type",
     "definition": "'asc' | 'desc' | 'none'"
    },
    {
     "name": "MkTableAlign",
     "description": "Horizontal text alignment for a table column.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "type",
     "definition": "'start' | 'center' | 'end'"
    },
    {
     "name": "MkTableDensity",
     "description": "Row vertical density.",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "type",
     "definition": "'comfortable' | 'compact'"
    },
    {
     "name": "MkTableFilterKind",
     "description": "Which control a column's header filter renders (see `MkTableColumn.filter`).",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "type",
     "definition": "'text' | 'select' | 'number' | 'date'"
    },
    {
     "name": "MkTableFilters",
     "description": "Active header filters keyed by column key: a string for `text`, an option\nvalue for `select`, a number / date (`>=`) or a `MkTableFilterRange`\nfor `number` and `date`. Empty strings and `null` mean \"no filter\".",
     "file": "projects/mk-kit/table/table/table.ts",
     "kind": "type",
     "definition": "Record<string, unknown>"
    }
   ]
  },
  {
   "name": "status",
   "import": "@mk-kit/ui/status",
   "exports": [
    {
     "name": "MkBadge",
     "description": "Badge — a compact status pill, typically for counts or short state labels.\nSet `dot` for a minimal notification indicator with no text.\n\n```html\n<mk-badge tone=\"success\">Active</mk-badge>\n<mk-badge tone=\"danger\" variant=\"solid\">3</mk-badge>\n<mk-badge tone=\"danger\" dot aria-label=\"Unread messages\" />\n```",
     "file": "projects/mk-kit/status/badge/badge.ts",
     "kind": "component",
     "selector": "mk-badge",
     "selectors": [
      "mk-badge"
     ],
     "inputs": [
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'primary'"
      },
      {
       "name": "variant",
       "type": "MkBadgeVariant",
       "description": "Visual treatment.",
       "default": "'soft'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "dot",
       "type": "boolean",
       "description": "Render as a tiny dot (no text) for notification indicators.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkEmptyState",
     "description": "EmptyState — a centered placeholder for \"nothing here yet\" situations: empty\ntables, no search results, a fresh dashboard, a cleared inbox. Provide a\n`title` (and usually a `description`), an `icon` or projected media, and\ncall-to-action buttons via the actions slot.\n\nSlots: `[mkEmptyStateMedia]` (custom illustration, overrides `icon`), default\ncontent (extra body), `[mkEmptyStateActions]` (buttons).\n\n```html\n<mk-empty-state icon=\"search\" title=\"No results\"\n  description=\"Try adjusting your filters.\">\n  <button mkButton mkEmptyStateActions variant=\"outline\">Clear filters</button>\n</mk-empty-state>\n```",
     "file": "projects/mk-kit/status/empty-state/empty-state.ts",
     "kind": "component",
     "selector": "mk-empty-state",
     "selectors": [
      "mk-empty-state"
     ],
     "inputs": [
      {
       "name": "icon",
       "type": "string",
       "description": "Name of a registered icon shown above the title (ignored if media is projected).",
       "default": "''"
      },
      {
       "name": "title",
       "type": "string",
       "description": "Main heading, e.g. \"No invoices yet\".",
       "default": "''"
      },
      {
       "name": "description",
       "type": "string",
       "description": "Supporting sentence under the title.",
       "default": "''"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Overall scale of the block.",
       "default": "'md'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/empty-timeline"
    },
    {
     "name": "MkSpinner",
     "description": "Spinner — a circular indeterminate loading indicator. Exposes `role=\"status\"`\nwith a visually-hidden label so assistive tech announces the loading state.\nThe animation slows under `prefers-reduced-motion`.\n\n```html\n<mk-spinner />\n<mk-spinner size=\"lg\" tone=\"neutral\" label=\"Fetching results\" />\n```",
     "file": "projects/mk-kit/status/spinner/spinner.ts",
     "kind": "component",
     "selector": "mk-spinner",
     "selectors": [
      "mk-spinner"
     ],
     "inputs": [
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'primary'"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Visually-hidden status label announced to screen readers.",
       "default": "this.i18n.loading"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/loading"
    },
    {
     "name": "MkBadgeOverlay",
     "description": "Badge overlay — anchors a small badge (count, dot or short text) to a corner\nof ANY element: an icon button, an avatar, a tab label. The host stays a\nsingle tab stop; the badge is a decorative, non-focusable child.\n\n- Numbers above `mkBadgeOverlayMax` (default 99) collapse to `99+`.\n- `mkBadgeOverlayDot` renders a textless dot (\"something is new\").\n- `mkBadgeOverlayAriaLabel` is the screen-reader text (\"3 unread\"). It is\n  rendered in a visually hidden span and wired to the host with\n  `aria-describedby`, so it is announced after the host's own name even\n  when the host has an `aria-label`. When it is given, the visible badge is\n  `aria-hidden` so the count is not read twice.\n- Positions use logical insets, so `top-end` sits at the top-right in LTR\n  and the top-left in RTL.\n\nThe badge is painted with the global `.mk-badge-overlay` styles from\n`@mk-kit/ui/styles.css` and follows the `--mk-*` tone tokens.\n\n```html\n<button mkButton iconOnly aria-label=\"Notifications\"\n        [mkBadgeOverlay]=\"unread()\" mkBadgeOverlayTone=\"danger\"\n        [mkBadgeOverlayAriaLabel]=\"unread() + ' unread'\">\n  <mk-icon name=\"bell\" />\n</button>\n\n<mk-avatar name=\"Ada Lovelace\" mkBadgeOverlay mkBadgeOverlayDot\n           mkBadgeOverlayTone=\"success\" mkBadgeOverlayPosition=\"bottom-end\" />\n```",
     "file": "projects/mk-kit/status/badge/badge-overlay.ts",
     "kind": "directive",
     "selector": "[mkBadgeOverlay]",
     "selectors": [
      "mkBadgeOverlay"
     ],
     "inputs": [
      {
       "name": "mkBadgeOverlay",
       "type": "string | number | null | undefined",
       "description": "Badge content — a count or a short label. `null` / empty hides the badge\nunless `mkBadgeOverlayDot` is set. Numeric strings are treated as numbers\nso `mkBadgeOverlay=\"120\"` also collapses to `99+`.",
       "default": "null"
      },
      {
       "name": "mkBadgeOverlayPosition",
       "type": "MkBadgeOverlayPosition",
       "description": "Corner the badge is anchored to (logical: `end` flips in RTL).",
       "default": "'top-end'"
      },
      {
       "name": "mkBadgeOverlayTone",
       "type": "MkTone",
       "description": "Semantic color tone (same scale as `mk-badge`).",
       "default": "'primary'"
      },
      {
       "name": "mkBadgeOverlayDot",
       "type": "boolean",
       "description": "Render a textless dot instead of the content.",
       "default": "false"
      },
      {
       "name": "mkBadgeOverlayMax",
       "type": "number",
       "description": "Numbers above this render as `<max>+`. `0` disables the cap.",
       "default": "99"
      },
      {
       "name": "mkBadgeOverlayHidden",
       "type": "boolean",
       "description": "Hide the badge while keeping the directive (and its aria wiring) in place.",
       "default": "false"
      },
      {
       "name": "mkBadgeOverlayAriaLabel",
       "type": "string",
       "description": "Screen-reader text for the badge, e.g. `\"3 unread\"`. Announced as the\nhost's description; the visible badge becomes `aria-hidden`.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "label",
       "type": "Signal<string>",
       "description": "The text painted in the badge (`''` in dot mode).",
       "readonly": true
      },
      {
       "name": "visible",
       "type": "Signal<boolean>",
       "description": "Whether the badge is currently rendered.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkBadgeOverlayPosition",
     "description": "Corner of the host an `MkBadgeOverlay` is anchored to.",
     "file": "projects/mk-kit/status/badge/badge-overlay.ts",
     "kind": "type",
     "definition": "| 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start'"
    },
    {
     "name": "MkBadgeVariant",
     "description": "Visual treatment for a `MkBadge`.",
     "file": "projects/mk-kit/status/badge/badge.ts",
     "kind": "type",
     "definition": "'solid' | 'soft' | 'outline'"
    }
   ]
  },
  {
   "name": "data",
   "import": "@mk-kit/ui/data",
   "exports": [
    {
     "name": "MkAvatar",
     "description": "Avatar — a user/entity image that gracefully falls back to initials derived\nfrom `name`, or to a projected icon. The whole avatar is exposed as a single\nlabelled image to assistive tech.\n\n```html\n<mk-avatar name=\"Ada Lovelace\" src=\"/ada.jpg\" status=\"online\" />\n<mk-avatar name=\"Grace Hopper\" />          <!-- initials fallback -->\n<mk-avatar><svg>…</svg></mk-avatar>        <!-- icon fallback -->\n```",
     "file": "projects/mk-kit/data/avatar/avatar.ts",
     "kind": "component",
     "selector": "mk-avatar",
     "selectors": [
      "mk-avatar"
     ],
     "inputs": [
      {
       "name": "src",
       "type": "string | undefined",
       "description": "Image URL. When it fails to load the avatar falls back automatically."
      },
      {
       "name": "name",
       "type": "string | undefined",
       "description": "Display name; drives the initials fallback and the default alt text."
      },
      {
       "name": "alt",
       "type": "string | undefined",
       "description": "Explicit accessible label. Defaults to `name`, else \"Avatar\"."
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "shape",
       "type": "MkAvatarShape",
       "description": "Outline shape.",
       "default": "'circle'"
      },
      {
       "name": "status",
       "type": "MkAvatarStatus | undefined",
       "description": "Presence indicator dot; omit for none."
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkAvatarGroup",
     "description": "Avatar group — overlaps a set of `MkAvatar` children and, when `max`\nis set, collapses the overflow into a trailing \"+N\" bubble.\n\n```html\n<mk-avatar-group [max]=\"3\">\n  <mk-avatar name=\"Ada Lovelace\" />\n  <mk-avatar name=\"Grace Hopper\" />\n  <mk-avatar name=\"Alan Turing\" />\n  <mk-avatar name=\"Katherine Johnson\" />\n</mk-avatar-group>\n```",
     "file": "projects/mk-kit/data/avatar/avatar-group.ts",
     "kind": "component",
     "selector": "mk-avatar-group",
     "selectors": [
      "mk-avatar-group"
     ],
     "inputs": [
      {
       "name": "max",
       "type": "number",
       "description": "Maximum avatars to show before collapsing the rest into \"+N\".",
       "default": "undefined"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size of the overflow bubble (match your avatars' size).",
       "default": "'md'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkBadge",
     "description": "Badge — a compact status pill, typically for counts or short state labels.\nSet `dot` for a minimal notification indicator with no text.\n\n```html\n<mk-badge tone=\"success\">Active</mk-badge>\n<mk-badge tone=\"danger\" variant=\"solid\">3</mk-badge>\n<mk-badge tone=\"danger\" dot aria-label=\"Unread messages\" />\n```",
     "file": "projects/mk-kit/status/badge/badge.ts",
     "kind": "component",
     "selector": "mk-badge",
     "selectors": [
      "mk-badge"
     ],
     "inputs": [
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'primary'"
      },
      {
       "name": "variant",
       "type": "MkBadgeVariant",
       "description": "Visual treatment.",
       "default": "'soft'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "dot",
       "type": "boolean",
       "description": "Render as a tiny dot (no text) for notification indicators.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkBarChart",
     "description": "BarChart — compares a measure across categories with one or more series\n(grouped or `stacked`), `vertical` (default) or `horizontal`. Dependency-free\nSVG on the validated `--mk-chart-*` palette; ships a legend for ≥ 2 series, a\nvalue axis with gridlines, per-bar hover tooltips and a screen-reader table.\n\n```html\n<mk-bar-chart orientation=\"horizontal\"\n  [categories]=\"['Q1','Q2','Q3','Q4']\"\n  [series]=\"[{ name: 'Revenue', data: [12,19,15,22] }]\" />\n```",
     "file": "projects/mk-kit/data/charts/bar-chart.ts",
     "kind": "component",
     "selector": "mk-bar-chart",
     "selectors": [
      "mk-bar-chart"
     ],
     "inputs": [
      {
       "name": "categories",
       "type": "readonly string[]",
       "description": "Category labels along the category axis.",
       "default": "[]"
      },
      {
       "name": "series",
       "type": "readonly MkChartSeries[]",
       "description": "One or more data series (values align to `categories`).",
       "default": "[]"
      },
      {
       "name": "orientation",
       "type": "MkBarOrientation",
       "description": "Bar direction.",
       "default": "'vertical'"
      },
      {
       "name": "width",
       "type": "number",
       "description": "Intrinsic width in viewBox units — the fallback before the host is\nmeasured, and the fixed drawing width when `responsive` is off.",
       "default": "480"
      },
      {
       "name": "responsive",
       "type": "boolean",
       "description": "Match the viewBox width to the host's actual width so `height` means\npixels and a wide container no longer stretches the chart vertically.\nSet false to pin the drawing to `width` (the pre-0.8 behaviour).",
       "default": "true"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Intrinsic height.",
       "default": "260"
      },
      {
       "name": "stacked",
       "type": "boolean",
       "description": "Stack series into one bar per category instead of grouping.",
       "default": "false"
      },
      {
       "name": "showGrid",
       "type": "boolean",
       "description": "Show gridlines behind the bars.",
       "default": "true"
      },
      {
       "name": "showLegend",
       "type": "boolean | undefined",
       "description": "Force the legend on/off (defaults to on when there are ≥ 2 series).",
       "default": "undefined"
      },
      {
       "name": "labelAngle",
       "type": "number | \"auto\"",
       "description": "Category-label tilt in degrees. `'auto'` (the default) leaves labels flat\nwhile they fit and tilts them 45° when they would collide — the axis of a\nnarrow chart is otherwise an unreadable smear. A number pins the angle\n(0 = always flat, 30/45 = always tilted); values are clamped to 0…90.\n\nTilting reserves the extra vertical room it needs, so `height` still means\nthe height you asked for. When even tilted labels cannot fit, the chart\nthins them — every Nth label is dropped rather than overlapped.",
       "default": "'auto'"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      },
      {
       "name": "interactive",
       "type": "boolean",
       "description": "Make bars clickable + keyboard-focusable (`role=\"button\"`, accessible name) and emit `barClick`.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "barClick",
       "type": "{ series: MkChartSeries; seriesIndex: number; category: string; categoryIndex: number; value: number; }",
       "description": "A bar was clicked or activated with Enter / Space (needs `interactive`)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/charts"
    },
    {
     "name": "MkCalendarHeatmap",
     "description": "Calendar heatmap — a GitHub-style year of daily squares: weeks as columns,\nweekdays as rows, each day shaded by its value. Rendered as a semantic\n`<table>` (month headers span their week columns, weekday names are row\nheaders, every cell carries its formatted value for screen readers) with\nintensities mixed from `color` over the surface via `color-mix`, so it\ntracks the theme. Values are bucketed linearly against the range maximum\ninto `levels` steps; days with value 0 (or no entry) render transparent.\n\nShows the last 12 months ending today by default; set `year` for a fixed\ncalendar year.\n\n```html\n<mk-calendar-heatmap\n  [data]=\"contributions\"\n  [year]=\"2026\"\n  (cellClick)=\"openDay($event.date)\"\n/>\n```",
     "file": "projects/mk-kit/data/charts/calendar-heatmap.ts",
     "kind": "component",
     "selector": "mk-calendar-heatmap",
     "selectors": [
      "mk-calendar-heatmap"
     ],
     "inputs": [
      {
       "name": "data",
       "type": "readonly MkCalendarHeatmapEntry[]",
       "description": "The daily values. Days without an entry count as 0.",
       "default": "[]"
      },
      {
       "name": "year",
       "type": "number | null",
       "description": "Show a fixed calendar year; unset shows the last 12 months ending today.",
       "default": "null",
       "transform": "(value) => {\n      if (value == null || value === '') return null;\n      const parsed = numberAttribute(value);\n      return Number.isFinite(parsed) ? parsed : null;\n    }"
      },
      {
       "name": "firstDayOfWeek",
       "type": "number",
       "description": "First weekday of the columns: 0 = Sunday … 6 = Saturday.",
       "default": "1"
      },
      {
       "name": "color",
       "type": "string",
       "description": "Base colour mixed over the surface for intensity.",
       "default": "'var(--mk-primary)'"
      },
      {
       "name": "levels",
       "type": "number",
       "description": "Number of intensity buckets in the ramp.",
       "default": "5"
      },
      {
       "name": "format",
       "type": "((date: Date, value: number) => string) | null",
       "description": "Formatter for each cell's title / screen-reader text (and legend max).",
       "default": "null"
      },
      {
       "name": "showScale",
       "type": "boolean",
       "description": "Show the less→more colour ramp legend.",
       "default": "true"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "cellClick",
       "type": "MkCalendarHeatmapCell",
       "description": "Emits the clicked day and its value."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/charts"
    },
    {
     "name": "MkCard",
     "description": "Card — a themed surface container that groups related content. Compose it\nwith the projected `mk-card-header`, `mk-card-title` and `mk-card-footer`\nparts, or drop plain content straight into the body.\n\n```html\n<mk-card variant=\"elevated\">\n  <mk-card-header>\n    <mk-card-title>Monthly revenue</mk-card-title>\n  </mk-card-header>\n  Body content goes here.\n  <mk-card-footer>\n    <button mkButton variant=\"ghost\">Details</button>\n  </mk-card-footer>\n</mk-card>\n```",
     "file": "projects/mk-kit/data/card/card.ts",
     "kind": "component",
     "selector": "mk-card",
     "selectors": [
      "mk-card"
     ],
     "inputs": [
      {
       "name": "variant",
       "type": "MkCardVariant",
       "description": "Surface treatment: raised shadow, hairline border, or tinted fill.",
       "default": "'elevated'"
      },
      {
       "name": "padding",
       "type": "MkCardPadding",
       "description": "Internal spacing applied to the body, header and footer.",
       "default": "'md'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkCardFooter",
     "description": "Card footer region — a padded band separated from the body by a hairline\nborder, usually holding actions aligned to the end.",
     "file": "projects/mk-kit/data/card/card-parts.ts",
     "kind": "component",
     "selector": "mk-card-footer, [mkCardFooter]",
     "selectors": [
      "mk-card-footer",
      "mkCardFooter"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkCardHeader",
     "description": "Card header region — a padded band separated from the body by a hairline\nborder. Typically wraps a `MkCardTitle` and optional actions.",
     "file": "projects/mk-kit/data/card/card-parts.ts",
     "kind": "component",
     "selector": "mk-card-header, [mkCardHeader]",
     "selectors": [
      "mk-card-header",
      "mkCardHeader"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkCardTitle",
     "description": "Card title — semantic heading text for a card header. Renders as bold,\nemphasised text; wrap the projected content in your own heading element if a\nspecific heading level is required for the document outline.",
     "file": "projects/mk-kit/data/card/card-parts.ts",
     "kind": "component",
     "selector": "mk-card-title",
     "selectors": [
      "mk-card-title"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkCarousel",
     "description": "Carousel — an accessible slides/gallery. Project slides marked with\n`mkCarouselSlide`; get prev/next arrows, dot indicators, Arrow-key\nnavigation, pointer swipe (touch or mouse drag; vertical page scroll stays\nnative) and optional autoplay that pauses on hover/focus. The current slide\nis a two-way `index` model.\n\n```html\n<mk-carousel ariaLabel=\"Featured\" autoplay>\n  <div mkCarouselSlide>…</div>\n  <div mkCarouselSlide>…</div>\n</mk-carousel>\n```",
     "file": "projects/mk-kit/data/carousel/carousel.ts",
     "kind": "component",
     "selector": "mk-carousel",
     "selectors": [
      "mk-carousel"
     ],
     "inputs": [
      {
       "name": "index",
       "type": "number",
       "description": "Two-way current slide index.",
       "model": true,
       "default": "0"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the carousel region.",
       "default": "this.i18n.carouselLabel"
      },
      {
       "name": "loop",
       "type": "boolean",
       "description": "Wrap around at the ends.",
       "default": "true"
      },
      {
       "name": "showDots",
       "type": "boolean",
       "description": "Show the dot indicators.",
       "default": "true"
      },
      {
       "name": "showArrows",
       "type": "boolean",
       "description": "Show the prev/next arrows.",
       "default": "true"
      },
      {
       "name": "autoplay",
       "type": "boolean",
       "description": "Advance automatically. Pauses transiently on hover/focus/pointer-down and\nshows a persistent pause/play toggle (`userPaused`). Never runs when the\nuser prefers reduced motion.",
       "default": "false"
      },
      {
       "name": "interval",
       "type": "number",
       "description": "Autoplay interval in ms.",
       "default": "5000"
      },
      {
       "name": "userPaused",
       "type": "boolean",
       "description": "Persistent, user-controlled pause (WCAG 2.2.2). Latched by the pause/play\ntoggle; the transient hover/focus pause never overrides it. Two-way so\nconsumers can bind or preset it.",
       "model": true,
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "indexChange",
       "type": "number",
       "description": "Emits when `index` changes (two-way binding).",
       "model": true
      },
      {
       "name": "userPausedChange",
       "type": "boolean",
       "description": "Emits when `userPaused` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "goTo",
       "signature": "(i: number): void",
       "description": "Go to slide `i` (clamped, or wrapped when `loop`)."
      },
      {
       "name": "next",
       "signature": "(): void",
       "description": ""
      },
      {
       "name": "prev",
       "signature": "(): void",
       "description": ""
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkCode",
     "description": "Code — a read-only, themed code block with syntax highlighting, an optional\nfilename header, line numbers and a copy button. Highlighting reuses the same\ndependency-free tokenizer as `MkCodeEditor`. For an editable field use\n`mk-code-editor` instead.\n\n```html\n<mk-code language=\"json\" filename=\"config.json\" [code]=\"json\" />\n```",
     "file": "projects/mk-kit/data/code/code.ts",
     "kind": "component",
     "selector": "mk-code",
     "selectors": [
      "mk-code"
     ],
     "inputs": [
      {
       "name": "code",
       "type": "string",
       "description": "The source to display.",
       "default": "''"
      },
      {
       "name": "language",
       "type": "MkCodeLanguage",
       "description": "Language for highlighting.",
       "default": "'plaintext'"
      },
      {
       "name": "filename",
       "type": "string",
       "description": "Optional filename shown in a header bar.",
       "default": "''"
      },
      {
       "name": "lineNumbers",
       "type": "boolean",
       "description": "Show a line-number gutter.",
       "default": "false"
      },
      {
       "name": "copyable",
       "type": "boolean",
       "description": "Show the copy button.",
       "default": "true"
      },
      {
       "name": "wrap",
       "type": "boolean",
       "description": "Soft-wrap long lines instead of scrolling horizontally.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkCountdown",
     "description": "Countdown — ticks every second and shows the time remaining until a target\ninstant as days / hours / minutes / seconds. Emits `finished` once when\nthe target passes and then keeps showing zeros (or `finishedText`).\n\n```html\n<mk-countdown [to]=\"launchDate\" (finished)=\"onLaunch()\" />\n```",
     "file": "projects/mk-kit/data/countdown/countdown.ts",
     "kind": "component",
     "selector": "mk-countdown",
     "selectors": [
      "mk-countdown"
     ],
     "inputs": [
      {
       "name": "to",
       "type": "Date | null",
       "description": "The target instant to count down to.",
       "default": "null"
      },
      {
       "name": "showDays",
       "type": "boolean",
       "description": "Show the days segment; when false, days roll into the hours value.",
       "default": "true"
      },
      {
       "name": "showLabels",
       "type": "boolean",
       "description": "Show the textual label beneath each value.",
       "default": "true"
      },
      {
       "name": "pad",
       "type": "boolean",
       "description": "Zero-pad values to two digits.",
       "default": "true"
      },
      {
       "name": "finishedText",
       "type": "string",
       "description": "Text to show instead of zeros once the countdown finishes.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "finished",
       "type": "void",
       "description": "Fires exactly once when the target instant is reached."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkDescItem",
     "description": "A single term/detail row of `MkDescriptionList`: `term` becomes the\n`<dt>`, the projected content the `<dd>`. The row itself renders nothing —\nthe list reads its rows and writes `<dt>`/`<dd>` as direct children of the\n`<dl>`, which is what HTML and assistive tech require (a wrapper element\nbetween `<dl>` and `<dt>` fails axe `definition-list` / `dlitem`).",
     "file": "projects/mk-kit/data/description-list/description-list.ts",
     "kind": "component",
     "selector": "mk-desc-item",
     "selectors": [
      "mk-desc-item"
     ],
     "inputs": [
      {
       "name": "term",
       "type": "string",
       "description": "The term (label) shown in the `<dt>`.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkDescriptionList",
     "description": "DescriptionList — a semantic `<dl>` of term/detail pairs for entity-detail and\nmetadata panels. Project `MkDescItem` rows; values may be rich content\n(badges, links, …). In `grid` layout terms align in a shared column; in\n`stacked` each term sits above its value.\n\n```html\n<mk-description-list>\n  <mk-desc-item term=\"Status\"><mk-badge tone=\"success\">Active</mk-badge></mk-desc-item>\n  <mk-desc-item term=\"Owner\">Ada Lovelace</mk-desc-item>\n</mk-description-list>\n```\n\nOnly `mk-desc-item` children are rendered; the `<dl>` always contains plain\n`<dt>`/`<dd>` pairs.",
     "file": "projects/mk-kit/data/description-list/description-list.ts",
     "kind": "component",
     "selector": "mk-description-list",
     "selectors": [
      "mk-description-list"
     ],
     "inputs": [
      {
       "name": "layout",
       "type": "MkDescriptionLayout",
       "description": "`grid` aligns terms in a column; `stacked` puts each term above its value.",
       "default": "'grid'"
      },
      {
       "name": "divided",
       "type": "boolean",
       "description": "Draw a divider between rows.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkDiff",
     "description": "Diff — a text comparison view for revisions (before ⇄ after). Computes an LCS\nline diff with optional intra-line word highlighting and renders a `unified`\n(single-column, +/-) or `split` (side-by-side) view with line numbers and an\nadd/remove summary.\n\n```html\n<mk-diff [before]=\"v1\" [after]=\"v2\" mode=\"split\" />\n```",
     "file": "projects/mk-kit/data/diff/diff.ts",
     "kind": "component",
     "selector": "mk-diff",
     "selectors": [
      "mk-diff"
     ],
     "inputs": [
      {
       "name": "before",
       "type": "string",
       "description": "The original (\"before\") text.",
       "default": "''"
      },
      {
       "name": "after",
       "type": "string",
       "description": "The new (\"after\") text.",
       "default": "''"
      },
      {
       "name": "mode",
       "type": "MkDiffMode",
       "description": "Layout: single-column `unified` or side-by-side `split`.",
       "default": "'unified'"
      },
      {
       "name": "wordHighlight",
       "type": "boolean",
       "description": "Highlight the specific words that changed within a line.",
       "default": "true"
      },
      {
       "name": "lineNumbers",
       "type": "boolean",
       "description": "Show line-number gutters.",
       "default": "true"
      },
      {
       "name": "ignoreTrailingWhitespace",
       "type": "boolean",
       "description": "Ignore trailing whitespace when comparing lines.",
       "default": "false"
      },
      {
       "name": "showStats",
       "type": "boolean",
       "description": "Show the +added / −removed summary header.",
       "default": "true"
      },
      {
       "name": "beforeLabel",
       "type": "string",
       "description": "Column labels (split view header / a11y).",
       "default": "this.i18n.diffBefore"
      },
      {
       "name": "afterLabel",
       "type": "string",
       "description": "",
       "default": "this.i18n.diffAfter"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkDivider",
     "description": "Divider — a themed separator rule. Renders horizontally by default; set\n`orientation=\"vertical\"` for an inline vertical rule. Project content to\nlabel a horizontal divider (the label sits centred between two rules).\n\n```html\n<mk-divider />\n<mk-divider>OR</mk-divider>\n<mk-divider orientation=\"vertical\" />\n```",
     "file": "projects/mk-kit/data/divider/divider.ts",
     "kind": "component",
     "selector": "mk-divider",
     "selectors": [
      "mk-divider"
     ],
     "inputs": [
      {
       "name": "orientation",
       "type": "MkDividerOrientation",
       "description": "Axis the rule is drawn along.",
       "default": "'horizontal'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkDonutChart",
     "description": "DonutChart — proportions of a whole as a ring (or a full pie when\n`thickness` covers the radius). Dependency-free SVG on the validated\n`--mk-chart-*` palette; ships a value/percent legend, per-slice hover\ntooltips, an optional centre label, and a screen-reader data table.\n\n```html\n<mk-donut-chart centerLabel=\"1,240\" centerSublabel=\"Total\"\n  [slices]=\"[{ name: 'Direct', value: 540 }, { name: 'Search', value: 700 }]\" />\n```",
     "file": "projects/mk-kit/data/charts/donut-chart.ts",
     "kind": "component",
     "selector": "mk-donut-chart",
     "selectors": [
      "mk-donut-chart"
     ],
     "inputs": [
      {
       "name": "slices",
       "type": "readonly MkChartSlice[]",
       "description": "The slices; each `value` contributes to the whole.",
       "default": "[]"
      },
      {
       "name": "size",
       "type": "number",
       "description": "Diameter in viewBox units (the SVG scales to its container).",
       "default": "220"
      },
      {
       "name": "thickness",
       "type": "number",
       "description": "Ring thickness. Set `0` (or ≥ radius) for a full pie.",
       "default": "34"
      },
      {
       "name": "showLegend",
       "type": "boolean",
       "description": "Show the legend with values + percentages.",
       "default": "true"
      },
      {
       "name": "centerLabel",
       "type": "string",
       "description": "Big centre label (e.g. a total). Donut only.",
       "default": "''"
      },
      {
       "name": "centerSublabel",
       "type": "string",
       "description": "Small centre caption under the label.",
       "default": "''"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      },
      {
       "name": "interactive",
       "type": "boolean",
       "description": "Make slices (and legend rows) clickable and keyboard-focusable: they get\n`role=\"button\"` + an accessible name and emit `sliceClick`. Off by default —\nthe chart stays a static picture with its screen-reader table.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "sliceClick",
       "type": "{ slice: MkChartSlice; index: number; }",
       "description": "A slice was clicked or activated with Enter / Space (needs `interactive`)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/proportion-charts"
    },
    {
     "name": "MkEmptyState",
     "description": "EmptyState — a centered placeholder for \"nothing here yet\" situations: empty\ntables, no search results, a fresh dashboard, a cleared inbox. Provide a\n`title` (and usually a `description`), an `icon` or projected media, and\ncall-to-action buttons via the actions slot.\n\nSlots: `[mkEmptyStateMedia]` (custom illustration, overrides `icon`), default\ncontent (extra body), `[mkEmptyStateActions]` (buttons).\n\n```html\n<mk-empty-state icon=\"search\" title=\"No results\"\n  description=\"Try adjusting your filters.\">\n  <button mkButton mkEmptyStateActions variant=\"outline\">Clear filters</button>\n</mk-empty-state>\n```",
     "file": "projects/mk-kit/status/empty-state/empty-state.ts",
     "kind": "component",
     "selector": "mk-empty-state",
     "selectors": [
      "mk-empty-state"
     ],
     "inputs": [
      {
       "name": "icon",
       "type": "string",
       "description": "Name of a registered icon shown above the title (ignored if media is projected).",
       "default": "''"
      },
      {
       "name": "title",
       "type": "string",
       "description": "Main heading, e.g. \"No invoices yet\".",
       "default": "''"
      },
      {
       "name": "description",
       "type": "string",
       "description": "Supporting sentence under the title.",
       "default": "''"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Overall scale of the block.",
       "default": "'md'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/empty-timeline"
    },
    {
     "name": "MkFunnelChart",
     "description": "FunnelChart — decreasing stacked trapezoids visualising conversion through a\nsequence of stages. Each band's top width tracks its own value and its bottom\nwidth tracks the next stage's value, so consecutive bands connect into a\nfunnel. Dependency-free SVG on the validated `--mk-chart-*` palette; each band\nis labelled with its value and its conversion relative to the top stage, and a\nscreen-reader table mirrors the data.\n\n```html\n<mk-funnel-chart\n  [segments]=\"[\n    { label: 'Visits', value: 1000 },\n    { label: 'Signups', value: 400 },\n    { label: 'Paid', value: 120 },\n  ]\" />\n```",
     "file": "projects/mk-kit/data/charts/funnel-chart.ts",
     "kind": "component",
     "selector": "mk-funnel-chart",
     "selectors": [
      "mk-funnel-chart"
     ],
     "inputs": [
      {
       "name": "segments",
       "type": "readonly MkFunnelSegment[]",
       "description": "The funnel stages, ordered largest → smallest conceptually.",
       "default": "[]"
      },
      {
       "name": "width",
       "type": "number",
       "description": "Intrinsic width (viewBox units; the SVG scales to its container).",
       "default": "420"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Intrinsic height.",
       "default": "300"
      },
      {
       "name": "showLegend",
       "type": "boolean | undefined",
       "description": "Force the legend on/off (funnels label each band, so off by default).",
       "default": "undefined"
      },
      {
       "name": "showValues",
       "type": "boolean",
       "description": "Render the value + conversion text on each band.",
       "default": "true"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/proportion-charts"
    },
    {
     "name": "MkGauge",
     "description": "Gauge — a single-metric radial dial (a KPI: \"68% of quota\"). Dependency-free\nSVG: a track arc with a value arc filled proportionally to `value` on the\n`[min, max]` scale, and a centred value + label. The sweep is configurable\n(`arc`, default 270°). Exposes `role=\"meter\"` for assistive tech.\n\n```html\n<mk-gauge [value]=\"68\" label=\"of quota\" unit=\"%\" />\n```",
     "file": "projects/mk-kit/data/charts/gauge.ts",
     "kind": "component",
     "selector": "mk-gauge",
     "selectors": [
      "mk-gauge"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "number",
       "description": "The current value.",
       "default": "0"
      },
      {
       "name": "min",
       "type": "number",
       "description": "Scale minimum.",
       "default": "0"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Scale maximum.",
       "default": "100"
      },
      {
       "name": "arc",
       "type": "number",
       "description": "Sweep of the arc in degrees (30–360).",
       "default": "270"
      },
      {
       "name": "size",
       "type": "number",
       "description": "Intrinsic size (viewBox units; the SVG scales to its container).",
       "default": "180"
      },
      {
       "name": "thickness",
       "type": "number",
       "description": "Arc thickness.",
       "default": "14"
      },
      {
       "name": "color",
       "type": "string",
       "description": "Value-arc colour.",
       "default": "'var(--mk-primary)'"
      },
      {
       "name": "trackColor",
       "type": "string",
       "description": "Track (background arc) colour.",
       "default": "'var(--mk-border-subtle)'"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Label under the value.",
       "default": "''"
      },
      {
       "name": "unit",
       "type": "string",
       "description": "Unit appended to the value (e.g. `%`).",
       "default": "''"
      },
      {
       "name": "valueText",
       "type": "string",
       "description": "Override the centred value text.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/proportion-charts"
    },
    {
     "name": "MkHeatmap",
     "description": "Heatmap — a matrix of cells shaded by value intensity, for correlation\ngrids, activity-by-time tables and the like. Rendered as a semantic\n`<table>` (so it is inherently screen-reader friendly) with cell colours\nmixed from `accent` over the surface via `color-mix`, so it tracks the theme.\n\nPrinted values (`showValues`) pick `--mk-text` or `--mk-text-inverse` per\ncell by contrast against that cell's actual colour, in both themes — see\n`mkHeatmapCellColors`.\n\n```html\n<mk-heatmap\n  [xLabels]=\"hours\" [yLabels]=\"days\" [data]=\"matrix()\" showValues />\n```",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "component",
     "selector": "mk-heatmap",
     "selectors": [
      "mk-heatmap"
     ],
     "inputs": [
      {
       "name": "xLabels",
       "type": "readonly string[]",
       "description": "Column labels (x axis).",
       "default": "[]"
      },
      {
       "name": "yLabels",
       "type": "readonly string[]",
       "description": "Row labels (y axis).",
       "default": "[]"
      },
      {
       "name": "data",
       "type": "readonly (readonly (number | null)[])[]",
       "description": "Row-major matrix: `data[row][col]`. Use `null` for a blank cell.",
       "default": "[]"
      },
      {
       "name": "min",
       "type": "number | null",
       "description": "Override the low end of the colour domain (defaults to the data min).",
       "default": "null"
      },
      {
       "name": "max",
       "type": "number | null",
       "description": "Override the high end of the colour domain (defaults to the data max).",
       "default": "null"
      },
      {
       "name": "accent",
       "type": "string",
       "description": "Base colour mixed over the surface for intensity.",
       "default": "'var(--mk-primary)'"
      },
      {
       "name": "showValues",
       "type": "boolean",
       "description": "Print each cell's value inside it.",
       "default": "false"
      },
      {
       "name": "showScale",
       "type": "boolean",
       "description": "Show the min→max colour scale legend.",
       "default": "true"
      },
      {
       "name": "format",
       "type": "(value: number) => string",
       "description": "Formatter for cell + legend values.",
       "default": "mkFormatCompact"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/charts"
    },
    {
     "name": "MkInlineEdit",
     "description": "InlineEdit — click a piece of text to edit it in place. The display is a\nbutton that swaps to an input on click (or Enter/Space); Enter or blur saves,\nEscape reverts. Ideal for editable labels in tables and detail panels.\nImplements `ControlValueAccessor` + a two-way `value` model of `string`.\n\n```html\n<mk-inline-edit [(value)]=\"title\" placeholder=\"Untitled\" />\n<mk-inline-edit multiline [(value)]=\"notes\" />\n```",
     "file": "projects/mk-kit/data/inline-edit/inline-edit.ts",
     "kind": "component",
     "selector": "mk-inline-edit",
     "selectors": [
      "mk-inline-edit"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "string",
       "description": "Two-way edited value.",
       "model": true,
       "default": "''"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Shown (muted) when the value is empty.",
       "default": "this.i18n.empty"
      },
      {
       "name": "multiline",
       "type": "boolean",
       "description": "Use a multi-line textarea; Enter inserts a newline, blur/✓ saves.",
       "default": "false"
      },
      {
       "name": "saveOnBlur",
       "type": "boolean",
       "description": "Save when the field loses focus (otherwise blur cancels).",
       "default": "true"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the edit trigger + field.",
       "default": "this.i18n.edit"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable editing.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size. Ignored when nested in an `mk-form-field`.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "saved",
       "type": "string",
       "description": "Emitted with the new value when an edit is saved."
      },
      {
       "name": "cancelled",
       "type": "void",
       "description": "Emitted when an edit is cancelled."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/table"
    },
    {
     "name": "MkJsonViewer",
     "description": "JsonViewer — a read-only, collapsible tree for JSON-ish data: objects and\narrays fold behind disclosure buttons (with a `{…} n items` preview),\nprimitives are colour-coded by type, and circular references render as\n`[Circular]` instead of recursing. `expandDepth` controls how much is open\ninitially; `expandAll()` / `collapseAll()` are available on the component.\n\nThe complement of `mk-code-editor`: the editor edits JSON text, this\nexplores JSON *data* (API responses, entity payloads, config dumps).\n\n```html\n<mk-json-viewer [data]=\"response\" [expandDepth]=\"2\" />\n```",
     "file": "projects/mk-kit/data/json-viewer/json-viewer.ts",
     "kind": "component",
     "selector": "mk-json-viewer",
     "selectors": [
      "mk-json-viewer"
     ],
     "exportAs": "mkJsonViewer",
     "inputs": [
      {
       "name": "data",
       "type": "unknown",
       "description": "The value to display (any JSON-serialisable data).",
       "required": true
      },
      {
       "name": "expandDepth",
       "type": "number",
       "description": "How many levels start expanded (root = level 1).",
       "default": "1"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible label of the tree region.",
       "default": "this.i18n.jsonLabel"
      }
     ],
     "outputs": [],
     "methods": [
      {
       "name": "expandAll",
       "signature": "(): void",
       "description": "Expand every object/array node."
      },
      {
       "name": "collapseAll",
       "signature": "(): void",
       "description": "Collapse everything (the root stays visible)."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkLineChart",
     "description": "LineChart — a line (or `area`) chart for change over time / ordered\ncategories, with one or more series. Dependency-free SVG on the validated\n`--mk-chart-*` palette; ships a legend for ≥ 2 series, a value axis, a\nhover crosshair with a shared tooltip, and a screen-reader data table.\n\n```html\n<mk-line-chart area\n  [categories]=\"months\"\n  [series]=\"[{ name: 'Sessions', data: sessions() }]\" />\n```",
     "file": "projects/mk-kit/data/charts/line-chart.ts",
     "kind": "component",
     "selector": "mk-line-chart",
     "selectors": [
      "mk-line-chart"
     ],
     "inputs": [
      {
       "name": "categories",
       "type": "readonly string[]",
       "description": "Ordered category labels along the x axis.",
       "default": "[]"
      },
      {
       "name": "series",
       "type": "readonly MkChartSeries[]",
       "description": "One or more data series (values align to `categories`).",
       "default": "[]"
      },
      {
       "name": "width",
       "type": "number",
       "description": "Intrinsic width in viewBox units — the fallback before the host is\nmeasured, and the fixed drawing width when `responsive` is off.",
       "default": "480"
      },
      {
       "name": "responsive",
       "type": "boolean",
       "description": "Match the viewBox width to the host's actual width so `height` means\npixels and a wide container no longer stretches the chart vertically.\nSet false to pin the drawing to `width` (the pre-0.8 behaviour).",
       "default": "true"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Intrinsic height.",
       "default": "260"
      },
      {
       "name": "area",
       "type": "boolean",
       "description": "Fill the area under each line.",
       "default": "false"
      },
      {
       "name": "stacked",
       "type": "boolean",
       "description": "Stack the series (cumulative bands) — implies filled areas.",
       "default": "false"
      },
      {
       "name": "showDots",
       "type": "boolean",
       "description": "Draw a dot at every data point.",
       "default": "false"
      },
      {
       "name": "showGrid",
       "type": "boolean",
       "description": "Show gridlines.",
       "default": "true"
      },
      {
       "name": "showLegend",
       "type": "boolean | undefined",
       "description": "Force the legend on/off (defaults to on when there are ≥ 2 series).",
       "default": "undefined"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      },
      {
       "name": "interactive",
       "type": "boolean",
       "description": "Make x positions keyboard-focusable (`role=\"button\"`, accessible name) and emit `pointClick`.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "pointClick",
       "type": "{ index: number; category: string; values: Array<{ series: MkChartSeries; value: number; }>; }",
       "description": "A category (x position) was clicked or activated with Enter / Space (needs `interactive`)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/charts"
    },
    {
     "name": "MkList",
     "description": "List — a vertical stack of `MkListItem`s with `role=\"list\"` semantics.\n\n```html\n<mk-list>\n  <mk-list-item>Dashboard</mk-list-item>\n  <mk-list-item interactive (activated)=\"open()\">Settings</mk-list-item>\n</mk-list>\n```",
     "file": "projects/mk-kit/data/list/list.ts",
     "kind": "component",
     "selector": "mk-list",
     "selectors": [
      "mk-list"
     ],
     "inputs": [
      {
       "name": "bordered",
       "type": "boolean",
       "description": "Draw hairline separators between items.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkListItem",
     "description": "List item — a row inside `MkList`. Project leading/trailing adornments\nwith the `mkListLeading` / `mkListTrailing` attributes. Set `interactive`\nto make the row focusable and clickable (Enter/Space activate it).\n\n```html\n<mk-list-item interactive [selected]=\"active()\" (activated)=\"pick()\">\n  <mk-avatar mkListLeading name=\"Ada\" />\n  Ada Lovelace\n  <mk-badge mkListTrailing tone=\"success\">New</mk-badge>\n</mk-list-item>\n```",
     "file": "projects/mk-kit/data/list/list-item.ts",
     "kind": "component",
     "selector": "mk-list-item",
     "selectors": [
      "mk-list-item"
     ],
     "inputs": [
      {
       "name": "interactive",
       "type": "boolean",
       "description": "Make the row focusable/clickable with hover + keyboard activation.",
       "default": "false"
      },
      {
       "name": "selected",
       "type": "boolean",
       "description": "Highlight the row as the current selection.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable interaction and dim the row.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "activated",
       "type": "void",
       "description": "Emitted on click / Enter / Space when `interactive`."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkLogViewer",
     "description": "LogViewer — a virtualized, tail-following log / terminal pane. Renders only\nthe visible window of a (ring-buffered) line array, parses ANSI SGR colour\ncodes into theme-aware spans, follows new output at the bottom until the\nuser scrolls away, and highlights plain-string search matches.\n\n```html\n<mk-log-viewer\n  [lines]=\"lines()\"\n  [(follow)]=\"follow\"\n  [query]=\"search()\"\n  (matches)=\"count.set($event)\"\n/>\n```\n\nWrap mode (`[wrap]=\"true\"` or the toolbar toggle) soft-wraps long lines;\nbecause wrapped rows have no fixed height, wrap mode renders **without**\nvirtualization — fine up to a few thousand lines, so keep `maxLines`\nmodest when wrapping is expected.\n\n`query` is matched as a case-insensitive plain string — no regex.",
     "file": "projects/mk-kit/data/log-viewer/log-viewer.ts",
     "kind": "component",
     "selector": "mk-log-viewer",
     "selectors": [
      "mk-log-viewer"
     ],
     "exportAs": "mkLogViewer",
     "inputs": [
      {
       "name": "lines",
       "type": "readonly string[]",
       "description": "The log lines (may contain ANSI SGR escape sequences).",
       "default": "[]"
      },
      {
       "name": "follow",
       "type": "boolean",
       "description": "Stick to the bottom as new lines arrive (two-way; detaches on scroll-up).",
       "model": true,
       "default": "true"
      },
      {
       "name": "wrap",
       "type": "boolean",
       "description": "Soft-wrap long lines (two-way; disables virtualization — see class docs).",
       "model": true,
       "default": "false"
      },
      {
       "name": "ansi",
       "type": "boolean",
       "description": "Parse ANSI SGR colour codes; `false` renders lines verbatim.",
       "default": "true"
      },
      {
       "name": "query",
       "type": "string",
       "description": "Case-insensitive plain-string search; matches are highlighted.",
       "default": "''"
      },
      {
       "name": "maxLines",
       "type": "number",
       "description": "Ring buffer size: oldest lines are dropped beyond this.",
       "default": "10_000"
      },
      {
       "name": "itemHeight",
       "type": "number",
       "description": "Fixed row height in px (drives virtualization; also sets line-height).",
       "default": "20"
      },
      {
       "name": "hideToolbar",
       "type": "boolean",
       "description": "Hide the built-in toolbar row.",
       "default": "false"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible label of the log region.",
       "default": "this.i18n.logViewerLabel"
      }
     ],
     "outputs": [
      {
       "name": "followChange",
       "type": "boolean",
       "description": "Emits when `follow` changes (two-way binding).",
       "model": true
      },
      {
       "name": "wrapChange",
       "type": "boolean",
       "description": "Emits when `wrap` changes (two-way binding).",
       "model": true
      },
      {
       "name": "matches",
       "type": "number",
       "description": "Emits the total number of `query` matches whenever it changes."
      }
     ],
     "methods": [],
     "properties": [
      {
       "name": "matchCount",
       "type": "Signal<number>",
       "description": "Total number of case-insensitive plain-string matches of `query`.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/markdown"
    },
    {
     "name": "MkMarkdown",
     "description": "Markdown — renders a CommonMark subset (see `mkParseMarkdown` for the\nexact syntax list) with zero runtime dependencies. Built for admin-app\ncontent: changelogs, AI output, user notes.\n\nSECURITY MODEL: raw HTML in the source is never passed through — it is\nalways escaped and shown as text, and link/image URLs are restricted to\nhttp/https/mailto/relative, so the rendered string contains only markup the\nrenderer itself generates. It is bound via `[innerHTML]` and additionally\npasses through Angular's `DomSanitizer` (no `bypassSecurityTrustHtml`),\nwhich keeps every element and attribute the renderer emits.\n\n```html\n<mk-markdown [source]=\"changelog\" linkTarget=\"_blank\" />\n```",
     "file": "projects/mk-kit/data/markdown/markdown.ts",
     "kind": "component",
     "selector": "mk-markdown",
     "selectors": [
      "mk-markdown"
     ],
     "inputs": [
      {
       "name": "source",
       "type": "string",
       "description": "Markdown source text.",
       "default": "''"
      },
      {
       "name": "autolink",
       "type": "boolean",
       "description": "Turn bare `http(s)://…` URLs into links. Off by default.",
       "default": "false"
      },
      {
       "name": "linkTarget",
       "type": "\"\" | \"_blank\"",
       "description": "Link target; `'_blank'` also adds `rel=\"noopener noreferrer\"`.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/markdown"
    },
    {
     "name": "MkOrgChart",
     "description": "Organisation chart — a reporting-line hierarchy drawn with plain nested\nlists and CSS connectors (no canvas, prints and themes like everything\nelse). Feed it a tree (`nodes`) or convert a flat `parentId` list with\n`mkOrgChartFromFlat`. Nodes render as a default card (avatar /\ninitials, label, `data.title`) or through an `mkOrgChartNodeDef` template.\n\nFollows the ARIA tree pattern (`role=\"tree\"` / `treeitem` / `group`, one\nroving tab stop). Keyboard (top-down; the axes swap for `orientation=\"left\"`\nand in RTL): Down = first child (expands a collapsed node first), Up =\nparent, Left/Right = previous/next sibling, Home/End = first/last visible\nnode, Enter/Space = select (or toggle when not selectable), `*` = expand\nall siblings, `+`/`-` = expand/collapse.\n\n```html\n<mk-org-chart\n  [nodes]=\"company\"\n  selectable\n  [(selected)]=\"personId\"\n  collapsible\n  (nodeClick)=\"open($event)\"\n/>\n```",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "component",
     "selector": "mk-org-chart",
     "selectors": [
      "mk-org-chart"
     ],
     "exportAs": "mkOrgChart",
     "inputs": [
      {
       "name": "nodes",
       "type": "readonly MkOrgChartNode<T>[]",
       "description": "The hierarchy to render (roots first).",
       "default": "[]"
      },
      {
       "name": "orientation",
       "type": "MkOrgChartOrientation",
       "description": "Root at the top (children below) or at the inline start (children to the side).",
       "default": "'top'"
      },
      {
       "name": "selectable",
       "type": "boolean",
       "description": "Allow choosing a node (adds selection styling + `aria-selected`).",
       "default": "false"
      },
      {
       "name": "collapsible",
       "type": "boolean",
       "description": "Show a toggle on every parent so branches can be hidden.",
       "default": "false"
      },
      {
       "name": "zoom",
       "type": "number",
       "description": "Scale factor applied to the whole chart (clamped to 0.5–2).",
       "default": "1"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible name for the tree.",
       "default": "this.i18n.orgChartLabel"
      },
      {
       "name": "selected",
       "type": "string | null",
       "description": "Two-way selected node id (`null` = nothing selected).",
       "model": true,
       "default": "null"
      },
      {
       "name": "expanded",
       "type": "readonly string[] | undefined",
       "description": "Two-way ids of the expanded parents. Leave unbound to let the chart\nmanage expansion itself (seeded from each node's `expanded` flag).",
       "model": true,
       "default": "undefined"
      }
     ],
     "outputs": [
      {
       "name": "selectedChange",
       "type": "string | null",
       "description": "Emits when `selected` changes (two-way binding).",
       "model": true
      },
      {
       "name": "expandedChange",
       "type": "readonly string[] | undefined",
       "description": "Emits when `expanded` changes (two-way binding).",
       "model": true
      },
      {
       "name": "nodeClick",
       "type": "MkOrgChartNode<T>",
       "description": "Emits the node whose card was clicked or activated with Enter/Space."
      },
      {
       "name": "nodeToggle",
       "type": "MkOrgChartToggleEvent<T>",
       "description": "Emits whenever a node is expanded or collapsed."
      }
     ],
     "methods": [
      {
       "name": "toggle",
       "signature": "(node: MkOrgChartNode<T>): void",
       "description": "Expand or collapse a parent (no-op for leaves / non-collapsible charts)."
      },
      {
       "name": "setExpanded",
       "signature": "(node: MkOrgChartNode<T>, expanded: boolean): void",
       "description": "Expand or collapse a parent explicitly."
      },
      {
       "name": "select",
       "signature": "(node: MkOrgChartNode<T>): void",
       "description": "Select a node by reference (no-op unless `selectable`)."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/org-chart"
    },
    {
     "name": "MkProfileActions",
     "description": "Profile actions row — buttons projected into the footer area of a\n`MkProfileCard`. Centred in vertical orientation; pinned to the end\nin horizontal orientation.\n\n```html\n<div mkProfileActions>\n  <button mkButton>Follow</button>\n  <button mkButton variant=\"outline\">Message</button>\n</div>\n```",
     "file": "projects/mk-kit/data/profile-card/profile-card.ts",
     "kind": "component",
     "selector": "[mkProfileActions]",
     "selectors": [
      "mkProfileActions"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkProfileCard",
     "description": "Profile card — a person/entity summary on a bordered surface: an optional\ncover banner, an `MkAvatar` (with automatic initials fallback derived\nfrom `name`), the display name, a muted subtitle, free-form body content and\ntwo optional slots for a meta/stats row and an actions row.\n\nOrientations:\n- `vertical` (default) — centred column; when `coverSrc` is set a 3:1 banner\n  spans the card top and the avatar overlaps its bottom edge with a\n  surface-coloured ring.\n- `horizontal` — avatar on the left, text in the middle, actions pinned to\n  the end. The cover banner is intentionally NOT rendered in this\n  orientation (a side-by-side row has no top edge for it to crown).\n\nThe name renders as emphasised generic text (like `mk-card-title`, no\nhard-coded heading level) so the card never disrupts the document outline.\n\n```html\n<mk-profile-card\n  name=\"Ada Lovelace\"\n  subtitle=\"Analytical Engine Programmer\"\n  avatarSrc=\"/ada.jpg\"\n  coverSrc=\"/cover.jpg\">\n  First programmer. Wrote notes G through... well, all of them.\n  <div mkProfileMeta>\n    <div><strong>128</strong> posts</div>\n    <div><strong>2.4k</strong> followers</div>\n    <div><strong>310</strong> following</div>\n  </div>\n  <div mkProfileActions>\n    <button mkButton>Follow</button>\n    <button mkButton variant=\"outline\">Message</button>\n  </div>\n</mk-profile-card>\n```",
     "file": "projects/mk-kit/data/profile-card/profile-card.ts",
     "kind": "component",
     "selector": "mk-profile-card",
     "selectors": [
      "mk-profile-card"
     ],
     "exportAs": "mkProfileCard",
     "inputs": [
      {
       "name": "name",
       "type": "string",
       "description": "Display name. Also drives the avatar's initials fallback and alt text.",
       "required": true
      },
      {
       "name": "subtitle",
       "type": "string",
       "description": "Muted supporting line under the name (role, handle, email…).",
       "default": "''"
      },
      {
       "name": "avatarSrc",
       "type": "string",
       "description": "Avatar image URL; when empty the avatar falls back to initials.",
       "default": "''"
      },
      {
       "name": "coverSrc",
       "type": "string",
       "description": "Cover banner image URL rendered as a ~3:1 band across the card top\n(vertical orientation only). When set, the avatar overlaps the banner's\nbottom edge with a surface-coloured ring.",
       "default": "''"
      },
      {
       "name": "orientation",
       "type": "MkProfileCardOrientation",
       "description": "Layout: centred column (`vertical`) or avatar-left row (`horizontal`).",
       "default": "'vertical'"
      },
      {
       "name": "avatarSize",
       "type": "MkSize",
       "description": "Avatar size scale, forwarded to `MkAvatar`.",
       "default": "'lg'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkProfileMeta",
     "description": "Profile meta row — a stats strip projected into a `MkProfileCard`\nbetween the body and the actions. Direct children are laid out as\nevenly-spaced, centre-aligned cells with subtle separators between them.\n\n```html\n<div mkProfileMeta>\n  <div><strong>128</strong> posts</div>\n  <div><strong>2.4k</strong> followers</div>\n</div>\n```",
     "file": "projects/mk-kit/data/profile-card/profile-card.ts",
     "kind": "component",
     "selector": "[mkProfileMeta]",
     "selectors": [
      "mkProfileMeta"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkProgressBar",
     "description": "Progress bar — a determinate (0–100) or indeterminate progress indicator\nwith `role=\"progressbar\"`. `aria-valuenow` is omitted while indeterminate.\nThe indeterminate animation respects `prefers-reduced-motion`.\n\n```html\n<mk-progress-bar [value]=\"uploaded()\" label=\"Uploading\" showValue />\n<mk-progress-bar indeterminate label=\"Loading\" />\n```",
     "file": "projects/mk-kit/data/progress-bar/progress-bar.ts",
     "kind": "component",
     "selector": "mk-progress-bar",
     "selectors": [
      "mk-progress-bar"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "number",
       "description": "Completion percentage 0–100 (ignored while indeterminate).",
       "default": "0"
      },
      {
       "name": "indeterminate",
       "type": "boolean",
       "description": "Show an animated indeterminate bar with no known completion.",
       "default": "false"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone of the fill.",
       "default": "'primary'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Track thickness.",
       "default": "'md'"
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "Optional visible caption; also labels the bar for assistive tech."
      },
      {
       "name": "showValue",
       "type": "boolean",
       "description": "Show the numeric percentage next to the label (determinate only).",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/loading"
    },
    {
     "name": "MkProgressRing",
     "description": "ProgressRing — a circular progress indicator. Determinate by default (an arc\nproportional to `value`); set `indeterminate` for a spinner-style preloader\nwhen progress is unknown. Themed by `tone`, sized by `size`.\n\n```html\n<mk-progress-ring [value]=\"uploaded()\" showLabel />\n<mk-progress-ring indeterminate tone=\"neutral\" [size]=\"24\" />\n<mk-progress-ring [value]=\"72\" tone=\"success\"><mk-icon name=\"check\" /></mk-progress-ring>\n```",
     "file": "projects/mk-kit/data/progress-ring/progress-ring.ts",
     "kind": "component",
     "selector": "mk-progress-ring",
     "selectors": [
      "mk-progress-ring"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "number",
       "description": "Current progress value (clamped to `[0, max]`). Ignored when indeterminate.",
       "default": "0"
      },
      {
       "name": "max",
       "type": "number",
       "description": "Maximum value. Default `100`.",
       "default": "100"
      },
      {
       "name": "size",
       "type": "number",
       "description": "Diameter in px. Default `48`.",
       "default": "48"
      },
      {
       "name": "thickness",
       "type": "number",
       "description": "Ring thickness in px. Default `4`.",
       "default": "4"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic colour of the progress arc.",
       "default": "'primary'"
      },
      {
       "name": "indeterminate",
       "type": "boolean",
       "description": "Show a rotating arc for unknown-duration work (a circular preloader).",
       "default": "false"
      },
      {
       "name": "showLabel",
       "type": "boolean",
       "description": "Show the percentage in the centre.",
       "default": "false"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible label (recommended, especially when indeterminate).",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/proportion-charts"
    },
    {
     "name": "MkQrCode",
     "description": "QR Code — a dependency-free QR generator rendered as an SVG. The entire\nencoding (byte mode, Reed–Solomon ECC, masking, format info) is implemented\nfrom scratch in `mkEncodeQr`; no npm library is used. Dark modules are\ndrawn as `<rect>`s over a background rectangle that also fills the quiet zone,\nso the code is theme-aware (`var(--mk-text)` on `var(--mk-surface)`) and\nfully overridable. Exposes `role=\"img\"` with an `aria-label` for assistive\ntech.\n\nSupports versions 1–10 and ECC levels L/M/Q/H (byte mode / UTF-8).\n\n```html\n<mk-qr-code value=\"https://example.com\" ecc=\"M\" [size]=\"200\" />\n```",
     "file": "projects/mk-kit/data/qr-code/qr-code.ts",
     "kind": "component",
     "selector": "mk-qr-code",
     "selectors": [
      "mk-qr-code"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "string",
       "description": "The text to encode (UTF-8, byte mode).",
       "required": true
      },
      {
       "name": "ecc",
       "type": "MkQrEcc",
       "description": "Error-correction level: `L` (~7%), `M` (~15%), `Q` (~25%), `H` (~30%).",
       "default": "'M'"
      },
      {
       "name": "size",
       "type": "number",
       "description": "Rendered pixel size of the (square) SVG.",
       "default": "160"
      },
      {
       "name": "quietZone",
       "type": "number",
       "description": "Width of the light margin around the code, in modules (spec recommends 4).",
       "default": "4"
      },
      {
       "name": "color",
       "type": "string",
       "description": "Dark-module colour.",
       "default": "'var(--mk-text)'"
      },
      {
       "name": "background",
       "type": "string",
       "description": "Background / quiet-zone colour.",
       "default": "'var(--mk-surface)'"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible label for the image. When omitted, the label carries the\nencoded content (`QR code: <value>`) so AT users learn what the code says.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkRadarChart",
     "description": "RadarChart — a radar / spider chart comparing several series across the same\nset of axes (skills, product profiles, survey dimensions). Dependency-free\nSVG on the validated `--mk-chart-*` palette; ships concentric grid rings, a\nlegend for ≥ 2 series and a screen-reader data table.\n\n```html\n<mk-radar-chart\n  [axes]=\"['Speed','Power','Range','Cost','Ease']\"\n  [series]=\"[{ name: 'Model A', data: [8,6,7,5,9] }]\" />\n```",
     "file": "projects/mk-kit/data/charts/radar-chart.ts",
     "kind": "component",
     "selector": "mk-radar-chart",
     "selectors": [
      "mk-radar-chart"
     ],
     "inputs": [
      {
       "name": "axes",
       "type": "readonly string[]",
       "description": "Axis labels (one spoke each). Series data align to this order.",
       "default": "[]"
      },
      {
       "name": "series",
       "type": "readonly MkChartSeries[]",
       "description": "One or more series (values align to `axes`).",
       "default": "[]"
      },
      {
       "name": "max",
       "type": "number | null",
       "description": "Domain maximum (defaults to a nice value above the data max).",
       "default": "null"
      },
      {
       "name": "levels",
       "type": "number",
       "description": "Number of concentric grid rings.",
       "default": "4"
      },
      {
       "name": "width",
       "type": "number",
       "description": "Intrinsic width (viewBox units; the SVG scales to its container).",
       "default": "360"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Intrinsic height.",
       "default": "360"
      },
      {
       "name": "showDots",
       "type": "boolean",
       "description": "Draw a dot at each vertex.",
       "default": "true"
      },
      {
       "name": "showLegend",
       "type": "boolean | undefined",
       "description": "Force the legend on/off (defaults to on when there are ≥ 2 series).",
       "default": "undefined"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/proportion-charts"
    },
    {
     "name": "MkScatterChart",
     "description": "ScatterChart — plot (x, y) points across two numeric axes to reveal\ncorrelation and clusters. Give each point a `size` to render a bubble chart.\nDependency-free SVG on the validated `--mk-chart-*` palette; ships nice-tick\naxes, a legend for ≥ 2 series, a per-point hover tooltip and a screen-reader\ndata table.\n\n```html\n<mk-scatter-chart\n  xLabel=\"Spend\" yLabel=\"Revenue\"\n  [series]=\"[{ name: 'Q3', points: pts() }]\" />\n```",
     "file": "projects/mk-kit/data/charts/scatter-chart.ts",
     "kind": "component",
     "selector": "mk-scatter-chart",
     "selectors": [
      "mk-scatter-chart"
     ],
     "inputs": [
      {
       "name": "series",
       "type": "readonly MkScatterSeries[]",
       "description": "One or more point series.",
       "default": "[]"
      },
      {
       "name": "width",
       "type": "number",
       "description": "Intrinsic width (viewBox units; the SVG scales to its container).",
       "default": "480"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Intrinsic height.",
       "default": "300"
      },
      {
       "name": "pointRadius",
       "type": "number",
       "description": "Radius of each point when not sizing by `size`.",
       "default": "4"
      },
      {
       "name": "bubble",
       "type": "boolean",
       "description": "Size points by their `size` value (bubble chart).",
       "default": "false"
      },
      {
       "name": "maxRadius",
       "type": "number",
       "description": "Largest bubble radius when `bubble` is on.",
       "default": "20"
      },
      {
       "name": "showGrid",
       "type": "boolean",
       "description": "Show gridlines.",
       "default": "true"
      },
      {
       "name": "showLegend",
       "type": "boolean | undefined",
       "description": "Force the legend on/off (defaults to on when there are ≥ 2 series).",
       "default": "undefined"
      },
      {
       "name": "xLabel",
       "type": "string",
       "description": "x-axis title.",
       "default": "''"
      },
      {
       "name": "yLabel",
       "type": "string",
       "description": "y-axis title.",
       "default": "''"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/charts"
    },
    {
     "name": "MkSkeleton",
     "description": "Skeleton — a shimmering placeholder shown while content loads. It is\n`aria-hidden`; mark the surrounding region `aria-busy=\"true\"` so assistive\ntech knows content is pending. The shimmer stops under\n`prefers-reduced-motion`.\n\n```html\n<mk-skeleton shape=\"circle\" [width]=\"40\" [height]=\"40\" />\n<mk-skeleton shape=\"text\" [lines]=\"3\" />\n<mk-skeleton shape=\"rect\" width=\"100%\" [height]=\"180\" />\n```",
     "file": "projects/mk-kit/data/skeleton/skeleton.ts",
     "kind": "component",
     "selector": "mk-skeleton",
     "selectors": [
      "mk-skeleton"
     ],
     "inputs": [
      {
       "name": "shape",
       "type": "MkSkeletonShape",
       "description": "Placeholder geometry.",
       "default": "'text'"
      },
      {
       "name": "width",
       "type": "string | number | undefined",
       "description": "Width — a number (px) or any CSS length/percentage string."
      },
      {
       "name": "height",
       "type": "string | number | undefined",
       "description": "Height — a number (px) or any CSS length/percentage string."
      },
      {
       "name": "lines",
       "type": "number",
       "description": "Number of lines to render for `shape=\"text\"`.",
       "default": "1"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/loading"
    },
    {
     "name": "MkSkeletonPreset",
     "description": "SkeletonPreset — composite loading placeholders assembled from\n`MkSkeleton`: a `paragraph`, a media `card`, an avatar `list` or a\n`table`. Announces \"Loading\" to assistive tech; swap it for real content once\nloaded.\n\n```html\n<mk-skeleton-preset preset=\"card\" />\n<mk-skeleton-preset preset=\"list\" [rows]=\"5\" />\n<mk-skeleton-preset preset=\"table\" [rows]=\"4\" [columns]=\"5\" />\n```",
     "file": "projects/mk-kit/data/skeleton/skeleton-preset.ts",
     "kind": "component",
     "selector": "mk-skeleton-preset",
     "selectors": [
      "mk-skeleton-preset"
     ],
     "inputs": [
      {
       "name": "preset",
       "type": "MkSkeletonPresetKind",
       "description": "Which layout to render.",
       "default": "'paragraph'"
      },
      {
       "name": "rows",
       "type": "number",
       "description": "Number of rows (paragraph lines / list items / table body rows).",
       "default": "3"
      },
      {
       "name": "columns",
       "type": "number",
       "description": "Number of columns (table only).",
       "default": "4"
      },
      {
       "name": "loadingLabel",
       "type": "string",
       "description": "Accessible loading label.",
       "default": "this.i18n.loading"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/loading"
    },
    {
     "name": "MkSparkline",
     "description": "Sparkline — a tiny, axis-less trend chart sized to sit inline in a table\ncell, stat card or list row. Single series only; it's a *mark*, so it carries\nno legend or tooltip (give context with the surrounding label + `label`).\n\n```html\n<mk-sparkline [data]=\"[3,5,4,7,6,9,8]\" type=\"area\" />\n<mk-sparkline [data]=\"visits()\" [width]=\"80\" showDot\n  color=\"var(--mk-success)\" label=\"Weekly visits\" />\n```",
     "file": "projects/mk-kit/data/charts/sparkline.ts",
     "kind": "component",
     "selector": "mk-sparkline",
     "selectors": [
      "mk-sparkline"
     ],
     "inputs": [
      {
       "name": "data",
       "type": "readonly number[]",
       "description": "The values to plot (left → right).",
       "default": "[]"
      },
      {
       "name": "type",
       "type": "MkSparklineType",
       "description": "Visual form.",
       "default": "'line'"
      },
      {
       "name": "color",
       "type": "string",
       "description": "Any CSS colour; defaults to the first chart hue.",
       "default": "'var(--mk-chart-1)'"
      },
      {
       "name": "width",
       "type": "number",
       "description": "Intrinsic width in px (the SVG scales with its box).",
       "default": "120"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Intrinsic height in px.",
       "default": "32"
      },
      {
       "name": "strokeWidth",
       "type": "number",
       "description": "Line/area stroke width.",
       "default": "2"
      },
      {
       "name": "showDot",
       "type": "boolean",
       "description": "Draw a dot on the last point (line/area only).",
       "default": "false"
      },
      {
       "name": "min",
       "type": "number | undefined",
       "description": "Fixed domain minimum (defaults to the data min).",
       "default": "undefined"
      },
      {
       "name": "max",
       "type": "number | undefined",
       "description": "Fixed domain maximum (defaults to the data max).",
       "default": "undefined"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible label; a data summary is generated when omitted.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/charts"
    },
    {
     "name": "MkSpinner",
     "description": "Spinner — a circular indeterminate loading indicator. Exposes `role=\"status\"`\nwith a visually-hidden label so assistive tech announces the loading state.\nThe animation slows under `prefers-reduced-motion`.\n\n```html\n<mk-spinner />\n<mk-spinner size=\"lg\" tone=\"neutral\" label=\"Fetching results\" />\n```",
     "file": "projects/mk-kit/status/spinner/spinner.ts",
     "kind": "component",
     "selector": "mk-spinner",
     "selectors": [
      "mk-spinner"
     ],
     "inputs": [
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'primary'"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Visually-hidden status label announced to screen readers.",
       "default": "this.i18n.loading"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/loading"
    },
    {
     "name": "MkStatCard",
     "description": "Stat card — a compact KPI tile for dashboards. Shows a label, a primary\nvalue and an optional trend delta. The trend is conveyed by an arrow glyph\nand a screen-reader phrase in addition to colour, so it never relies on\ncolour alone.\n\n```html\n<mk-stat-card\n  label=\"Revenue\"\n  value=\"$48.2k\"\n  [delta]=\"'+12%'\"\n  deltaTrend=\"up\"\n  hint=\"vs. last month\">\n  <svg mkStatIcon>…</svg>\n</mk-stat-card>\n```",
     "file": "projects/mk-kit/data/stat-card/stat-card.ts",
     "kind": "component",
     "selector": "mk-stat-card",
     "selectors": [
      "mk-stat-card"
     ],
     "inputs": [
      {
       "name": "label",
       "type": "string",
       "description": "Metric name shown above the value.",
       "default": "''"
      },
      {
       "name": "value",
       "type": "string | number",
       "description": "The primary metric value.",
       "default": "''"
      },
      {
       "name": "delta",
       "type": "string | number | undefined",
       "description": "Change indicator (e.g. `'+12%'` or `-4`). Omit to hide the delta row."
      },
      {
       "name": "deltaTrend",
       "type": "MkStatTrend",
       "description": "Trend direction; colourises the delta and picks the arrow glyph.",
       "default": "'neutral'"
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "Small supporting note under the delta (e.g. \"vs. last month\")."
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/cards-lists"
    },
    {
     "name": "MkTag",
     "description": "Tag — a non-interactive label for categories, keywords or metadata. Unlike\n`MkChip` it carries no interaction; use it purely for display.\n\n```html\n<mk-tag>Design</mk-tag>\n<mk-tag tone=\"info\" variant=\"outline\">Beta</mk-tag>\n```",
     "file": "projects/mk-kit/data/tag/tag.ts",
     "kind": "component",
     "selector": "mk-tag",
     "selectors": [
      "mk-tag"
     ],
     "inputs": [
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'neutral'"
      },
      {
       "name": "variant",
       "type": "MkTagVariant",
       "description": "Visual treatment.",
       "default": "'soft'"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Size scale.",
       "default": "'md'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkTimeline",
     "description": "Timeline — a vertical sequence of chronological events (activity feeds, order\nstatus, audit logs). A container for `<mk-timeline-item>`s that draws the\nconnecting rail; exposed to assistive tech as a list.\n\n```html\n<mk-timeline>\n  <mk-timeline-item tone=\"success\" time=\"09:30\" heading=\"Order placed\">\n    Payment confirmed.\n  </mk-timeline-item>\n  <mk-timeline-item time=\"10:15\" heading=\"Packed\">In the warehouse.</mk-timeline-item>\n</mk-timeline>\n```",
     "file": "projects/mk-kit/data/timeline/timeline.ts",
     "kind": "component",
     "selector": "mk-timeline",
     "selectors": [
      "mk-timeline"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/empty-timeline"
    },
    {
     "name": "MkTimelineItem",
     "description": "A single event in an `<mk-timeline>`: a tone-coloured marker (optionally an\nicon), an optional time/label and heading, and projected body content.\n\n```html\n<mk-timeline-item tone=\"danger\" icon=\"error\" time=\"2m ago\" heading=\"Build failed\">\n  3 tests failed on <code>main</code>.\n</mk-timeline-item>\n```",
     "file": "projects/mk-kit/data/timeline/timeline-item.ts",
     "kind": "component",
     "selector": "mk-timeline-item",
     "selectors": [
      "mk-timeline-item"
     ],
     "inputs": [
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic colour of the marker dot.",
       "default": "'primary'"
      },
      {
       "name": "icon",
       "type": "string",
       "description": "Name of a registered icon rendered inside the marker.",
       "default": "''"
      },
      {
       "name": "time",
       "type": "string",
       "description": "Time or label shown above the heading (e.g. \"09:30\", \"2m ago\").",
       "default": "''"
      },
      {
       "name": "heading",
       "type": "string",
       "description": "Event title.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/empty-timeline"
    },
    {
     "name": "MkTreemap",
     "description": "Treemap — nested rectangles sized by value, using a squarified layout that\nkeeps tiles close to square. Dependency-free SVG on the validated\n`--mk-chart-*` palette; ships in-tile labels (hidden when a tile is too\nsmall), a hover tooltip with the share of total, and a screen-reader table.\n\n```html\n<mk-treemap [items]=\"[{ label: 'Ads', value: 40 }, { label: 'SEO', value: 25 }]\" />\n```",
     "file": "projects/mk-kit/data/charts/treemap.ts",
     "kind": "component",
     "selector": "mk-treemap",
     "selectors": [
      "mk-treemap"
     ],
     "inputs": [
      {
       "name": "items",
       "type": "readonly MkTreemapItem[]",
       "description": "The tiles to pack, largest first (order-independent — sorted internally).",
       "default": "[]"
      },
      {
       "name": "width",
       "type": "number",
       "description": "Intrinsic width (viewBox units; the SVG scales to its container).",
       "default": "480"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Intrinsic height.",
       "default": "320"
      },
      {
       "name": "showValues",
       "type": "boolean",
       "description": "Draw each tile's value beneath its label when the tile is tall enough.",
       "default": "true"
      },
      {
       "name": "label",
       "type": "string",
       "description": "Accessible summary; generated from the data when omitted.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/proportion-charts"
    },
    {
     "name": "MkVirtualScroll",
     "description": "VirtualScroll — renders only the rows visible in the viewport (plus a small\noverscan), so a list of thousands of fixed-height items stays smooth. Give\nthe host a height and provide a row template:\n\n```html\n<mk-virtual-scroll [items]=\"rows\" [itemHeight]=\"40\" style=\"height: 20rem;\">\n  <ng-template let-row let-i=\"index\">{{ i }} — {{ row.name }}</ng-template>\n</mk-virtual-scroll>\n```",
     "file": "projects/mk-kit/data/virtual-scroll/virtual-scroll.ts",
     "kind": "component",
     "selector": "mk-virtual-scroll",
     "selectors": [
      "mk-virtual-scroll"
     ],
     "inputs": [
      {
       "name": "items",
       "type": "readonly unknown[]",
       "description": "The full list of items.",
       "default": "[]"
      },
      {
       "name": "itemHeight",
       "type": "number",
       "description": "Fixed height of each row in px.",
       "default": "40"
      },
      {
       "name": "overscan",
       "type": "number",
       "description": "Extra rows rendered above/below the viewport to smooth fast scrolls.",
       "default": "4"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkBadgeOverlay",
     "description": "Badge overlay — anchors a small badge (count, dot or short text) to a corner\nof ANY element: an icon button, an avatar, a tab label. The host stays a\nsingle tab stop; the badge is a decorative, non-focusable child.\n\n- Numbers above `mkBadgeOverlayMax` (default 99) collapse to `99+`.\n- `mkBadgeOverlayDot` renders a textless dot (\"something is new\").\n- `mkBadgeOverlayAriaLabel` is the screen-reader text (\"3 unread\"). It is\n  rendered in a visually hidden span and wired to the host with\n  `aria-describedby`, so it is announced after the host's own name even\n  when the host has an `aria-label`. When it is given, the visible badge is\n  `aria-hidden` so the count is not read twice.\n- Positions use logical insets, so `top-end` sits at the top-right in LTR\n  and the top-left in RTL.\n\nThe badge is painted with the global `.mk-badge-overlay` styles from\n`@mk-kit/ui/styles.css` and follows the `--mk-*` tone tokens.\n\n```html\n<button mkButton iconOnly aria-label=\"Notifications\"\n        [mkBadgeOverlay]=\"unread()\" mkBadgeOverlayTone=\"danger\"\n        [mkBadgeOverlayAriaLabel]=\"unread() + ' unread'\">\n  <mk-icon name=\"bell\" />\n</button>\n\n<mk-avatar name=\"Ada Lovelace\" mkBadgeOverlay mkBadgeOverlayDot\n           mkBadgeOverlayTone=\"success\" mkBadgeOverlayPosition=\"bottom-end\" />\n```",
     "file": "projects/mk-kit/status/badge/badge-overlay.ts",
     "kind": "directive",
     "selector": "[mkBadgeOverlay]",
     "selectors": [
      "mkBadgeOverlay"
     ],
     "inputs": [
      {
       "name": "mkBadgeOverlay",
       "type": "string | number | null | undefined",
       "description": "Badge content — a count or a short label. `null` / empty hides the badge\nunless `mkBadgeOverlayDot` is set. Numeric strings are treated as numbers\nso `mkBadgeOverlay=\"120\"` also collapses to `99+`.",
       "default": "null"
      },
      {
       "name": "mkBadgeOverlayPosition",
       "type": "MkBadgeOverlayPosition",
       "description": "Corner the badge is anchored to (logical: `end` flips in RTL).",
       "default": "'top-end'"
      },
      {
       "name": "mkBadgeOverlayTone",
       "type": "MkTone",
       "description": "Semantic color tone (same scale as `mk-badge`).",
       "default": "'primary'"
      },
      {
       "name": "mkBadgeOverlayDot",
       "type": "boolean",
       "description": "Render a textless dot instead of the content.",
       "default": "false"
      },
      {
       "name": "mkBadgeOverlayMax",
       "type": "number",
       "description": "Numbers above this render as `<max>+`. `0` disables the cap.",
       "default": "99"
      },
      {
       "name": "mkBadgeOverlayHidden",
       "type": "boolean",
       "description": "Hide the badge while keeping the directive (and its aria wiring) in place.",
       "default": "false"
      },
      {
       "name": "mkBadgeOverlayAriaLabel",
       "type": "string",
       "description": "Screen-reader text for the badge, e.g. `\"3 unread\"`. Announced as the\nhost's description; the visible badge becomes `aria-hidden`.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "label",
       "type": "Signal<string>",
       "description": "The text painted in the badge (`''` in dot mode).",
       "readonly": true
      },
      {
       "name": "visible",
       "type": "Signal<boolean>",
       "description": "Whether the badge is currently rendered.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/badges-avatars"
    },
    {
     "name": "MkCarouselSlide",
     "description": "A single slide inside `MkCarousel`. Mark each slide element with\n`mkCarouselSlide`; the carousel wires ARIA + visibility.",
     "file": "projects/mk-kit/data/carousel/carousel.ts",
     "kind": "directive",
     "selector": "[mkCarouselSlide]",
     "selectors": [
      "mkCarouselSlide"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkOrgChartNodeDef",
     "description": "Custom node card for `mk-org-chart`:\n\n```html\n<mk-org-chart [nodes]=\"nodes\">\n  <ng-template mkOrgChartNodeDef let-node let-selected=\"selected\">\n    <strong>{{ node.label }}</strong> — {{ node.data?.title }}\n  </ng-template>\n</mk-org-chart>\n```\n\nBind the same array you pass to `nodes` to get a typed `node.data` in the\ntemplate: `<ng-template [mkOrgChartNodeDef]=\"nodes\" let-node>`.",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "directive",
     "selector": "ng-template[mkOrgChartNodeDef]",
     "selectors": [
      "mkOrgChartNodeDef"
     ],
     "inputs": [
      {
       "name": "mkOrgChartNodeDef",
       "type": "\"\" | readonly MkOrgChartNode<T>[] | undefined",
       "description": "Type-inference hook only (the value is not used at runtime): bind the\n`nodes` array so `let-node` is typed as `MkOrgChartNode<T>`.",
       "default": "undefined"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "mkArcPath",
     "description": "SVG arc path for a donut/pie slice between two angles (radians, clockwise\nfrom 12 o'clock). `inner` of 0 yields a pie wedge; > 0 yields a ring segment.",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "function",
     "signatures": [
      "(cx: number, cy: number, outer: number, inner: number, startAngle: number, endAngle: number): string"
     ]
    },
    {
     "name": "mkAreaPath",
     "description": "Closed area path under a line: the line, dropped to `baselineY` at each end.",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "function",
     "signatures": [
      "(points: readonly MkPoint[], baselineY: number): string"
     ]
    },
    {
     "name": "mkBuildJsonTree",
     "description": "Build the node tree for a JSON-ish value (circular refs marked).",
     "file": "projects/mk-kit/data/json-viewer/json-viewer.ts",
     "kind": "function",
     "signatures": [
      "(value: unknown): MkJsonNode"
     ]
    },
    {
     "name": "mkChartColor",
     "description": "Categorical colour for a series index — a CSS reference to the validated\n`--mk-chart-N` token. Assigned in fixed order and wrapped past 8 (prefer\nfolding a 9th series into \"Other\" over relying on the wrap).",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "function",
     "signatures": [
      "(index: number): string"
     ]
    },
    {
     "name": "mkComputeDiff",
     "description": "Compute a line diff between `before` and `after`. Returns one `MkDiffRow`\nper line in document order, with `equal` / `insert` / `delete` ops and 1-based\nbefore/after line numbers. With `wordHighlight` (default true) changed lines\nalso carry word-level `segments`.",
     "file": "projects/core/src/diff.ts",
     "kind": "function",
     "signatures": [
      "(before: string, after: string, options?: MkDiffOptions): MkDiffRow[]"
     ]
    },
    {
     "name": "mkContrastRatio",
     "description": "WCAG 2.x contrast ratio (1–21) between two colours.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "function",
     "signatures": [
      "(a: MkRgb, b: MkRgb): number"
     ]
    },
    {
     "name": "mkDiffStats",
     "description": "Summary counts (added / removed / unchanged lines) for a diff.",
     "file": "projects/core/src/diff.ts",
     "kind": "function",
     "signatures": [
      "(rows: MkDiffRow[]): MkDiffStats"
     ]
    },
    {
     "name": "mkEncodeQr",
     "description": "Encode `text` (UTF-8, byte mode) as a QR code module matrix.",
     "file": "projects/mk-kit/data/qr-code/qr-encode.ts",
     "kind": "function",
     "signatures": [
      "(text: string, ecc: MkQrEcc): boolean[][]"
     ]
    },
    {
     "name": "mkFormatCompact",
     "description": "Compact number formatting for axes/tooltips (1.2k, 3.4M).",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "function",
     "signatures": [
      "(value: number): string"
     ]
    },
    {
     "name": "mkHeatmapCellColors",
     "description": "Choose the text token for a cell at intensity `t` (0–1) — light text on\ndark cells, dark text on light cells, decided by contrast against the\nactual blend rather than a fixed threshold.\n\nEvery accent ramp has a crossover band where neither `--mk-text` nor\n`--mk-text-inverse` reaches 4.5:1 (the cell is mid-luminance). When values\nare printed in the cells, a cell in that band is painted at the nearest\nintensity just outside it, so its value stays readable; the shift is a few\npercent of the ramp and the cell keeps its order relative to its\nneighbours. Without a resolved palette (server rendering, tests) a plain\nthreshold is used.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "function",
     "signatures": [
      "(t: number, palette: MkHeatmapPalette | null, showValues: boolean): MkHeatmapCellColors"
     ]
    },
    {
     "name": "mkLinearScale",
     "description": "Build a linear scale mapping `[d0,d1]` (domain) onto `[r0,r1]` (range).",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "function",
     "signatures": [
      "(d0: number, d1: number, r0: number, r1: number): (value: number) => number"
     ]
    },
    {
     "name": "mkLinePath",
     "description": "Straight-segment SVG path (`M … L …`) through the given points.",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "function",
     "signatures": [
      "(points: readonly MkPoint[]): string"
     ]
    },
    {
     "name": "mkMixRgb",
     "description": "What `color-mix(in srgb, a t%, b)` yields: a linear blend in gamma-encoded sRGB.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "function",
     "signatures": [
      "(a: MkRgb, b: MkRgb, t: number): MkRgb"
     ]
    },
    {
     "name": "mkNiceTicks",
     "description": "\"Nice\" rounded tick values covering `[min,max]` with roughly `count` steps —\nused for value axes so gridlines land on human numbers.",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "function",
     "signatures": [
      "(min: number, max: number, count?: number): number[]"
     ]
    },
    {
     "name": "mkOrgChartFromFlat",
     "description": "Build the nested `nodes` input from a flat `parentId` list (the shape most\nHR / directory APIs return). Row order is preserved among siblings; rows\nwhose `parentId` does not match any row become roots.\n\n```ts\nconst nodes = mkOrgChartFromFlat([\n  { id: 'ceo', label: 'Ada' },\n  { id: 'cto', label: 'Grace', parentId: 'ceo' },\n]);\n```",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "function",
     "signatures": [
      "<T = unknown>(list: readonly MkOrgChartFlatNode<T>[]): MkOrgChartNode<T>[]"
     ]
    },
    {
     "name": "mkParseAnsi",
     "description": "Parse one log line into styled spans. Pure — same input, same output.\nAdjacent runs with identical styling are merged, so a plain line yields a\nsingle span (or none when empty).",
     "file": "projects/core/src/ansi.ts",
     "kind": "function",
     "signatures": [
      "(line: string): MkAnsiSpan[]"
     ]
    },
    {
     "name": "mkParseMarkdown",
     "description": "Parse markdown source into a typed AST. Pure and dependency-free — safe to\nrun on a server. Unsafe link/image URLs are already dropped at this stage,\nso the AST never carries a `javascript:` (or other non-allow-listed) URL.",
     "file": "projects/core/src/markdown.ts",
     "kind": "function",
     "signatures": [
      "(src: string, options?: MkMarkdownParseOptions): MkMarkdownBlock[]"
     ]
    },
    {
     "name": "mkParseRgb",
     "description": "Parse a CSS colour as the CSSOM serialises it — `rgb(r, g, b)` /\n`rgba(r, g, b, a)` — or a `#rgb` / `#rrggbb` literal. `null` for anything\nelse (an unresolved `var()`, `color(...)`, …).",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "function",
     "signatures": [
      "(text: string | null | undefined): MkRgb | null"
     ]
    },
    {
     "name": "mkRelativeLuminance",
     "description": "WCAG 2.x relative luminance of an sRGB colour.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "function",
     "signatures": [
      "([r, g, b]: MkRgb): number"
     ]
    },
    {
     "name": "mkRenderMarkdown",
     "description": "Render a parsed AST to an HTML string. The output contains only tags this\nrenderer generates (all source text is escaped), so it is safe to bind to\n`[innerHTML]` — Angular's sanitizer keeps every element/attribute used here.\nFenced code is highlighted via `mkHighlight` for its known languages.",
     "file": "projects/core/src/markdown.ts",
     "kind": "function",
     "signatures": [
      "(blocks: MkMarkdownBlock[], options?: MkMarkdownRenderOptions): string"
     ]
    },
    {
     "name": "mkSplitDuration",
     "description": "Split a positive millisecond duration into whole days, hours, minutes and\nseconds. Negative inputs clamp to zero.\n\n```ts\nmkSplitDuration(90_061_000); // { days: 1, hours: 1, minutes: 1, seconds: 1 }\n```",
     "file": "projects/mk-kit/data/countdown/countdown.ts",
     "kind": "function",
     "signatures": [
      "(ms: number): MkDurationParts"
     ]
    },
    {
     "name": "mkSquarify",
     "description": "Squarified treemap layout — pack `items` into the rectangle `(x, y, w, h)` as\nnested tiles whose areas are proportional to `value`, greedily building rows\nalong the shorter side so tiles stay close to square. Returns exactly one\nrect per input item, tagged with its original `index` (so callers can render\nin input order). Framework-agnostic and pure.",
     "file": "projects/mk-kit/data/charts/treemap.ts",
     "kind": "function",
     "signatures": [
      "(items: readonly { value: number; }[], x: number, y: number, w: number, h: number): MkTreemapRect[]"
     ]
    },
    {
     "name": "mkStripAnsi",
     "description": "Remove every ANSI escape sequence from a line (for copy / search).",
     "file": "projects/core/src/ansi.ts",
     "kind": "function",
     "signatures": [
      "(line: string): string"
     ]
    },
    {
     "name": "MK_CHART_PALETTE_SIZE",
     "description": "Number of hues in the validated categorical palette (`--mk-chart-1..8`).",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "const",
     "type": "8"
    },
    {
     "name": "MK_HEATMAP_MIN_CONTRAST",
     "description": "WCAG AA minimum contrast for normal text — what cell values are held to.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "const",
     "type": "4.5"
    },
    {
     "name": "MkAnsiSpan",
     "description": "One styled run of text within a parsed line.",
     "file": "projects/core/src/ansi.ts",
     "kind": "interface",
     "members": [
      {
       "name": "text",
       "type": "string",
       "description": "The plain text of the run (escape sequences removed)."
      },
      {
       "name": "classes",
       "type": "readonly string[]",
       "description": "`mk-ansi--*` class names styling the run; empty for plain text."
      }
     ]
    },
    {
     "name": "MkCalendarHeatmapCell",
     "description": "Payload of `mk-calendar-heatmap`'s `cellClick`.",
     "file": "projects/mk-kit/data/charts/calendar-heatmap.ts",
     "kind": "interface",
     "members": [
      {
       "name": "date",
       "type": "Date",
       "description": "The clicked day (local midnight)."
      },
      {
       "name": "value",
       "type": "number",
       "description": "The day's aggregated value (0 when no entry exists)."
      }
     ]
    },
    {
     "name": "MkCalendarHeatmapEntry",
     "description": "One day's datum for `mk-calendar-heatmap`.",
     "file": "projects/mk-kit/data/charts/calendar-heatmap.ts",
     "kind": "interface",
     "members": [
      {
       "name": "date",
       "type": "string | Date",
       "description": "The day — a `Date`, or a string. `YYYY-MM-DD` strings are parsed as\n**local** dates (never UTC-shifted); other strings go through `new Date()`."
      },
      {
       "name": "value",
       "type": "number",
       "description": "The day's value (e.g. an activity count). Multiple entries for the same day are summed."
      }
     ]
    },
    {
     "name": "MkChartSeries",
     "description": "A named data series for multi-series charts.",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "interface",
     "members": [
      {
       "name": "name",
       "type": "string",
       "description": "Legend/tooltip label (identity — always shown, never colour-alone)."
      },
      {
       "name": "data",
       "type": "number[]",
       "description": "The values, one per category/x position."
      },
      {
       "name": "color",
       "type": "string | undefined",
       "description": "Optional explicit colour; defaults to the validated palette by index.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkChartSlice",
     "description": "A single slice for the donut/pie chart.",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "interface",
     "members": [
      {
       "name": "name",
       "type": "string",
       "description": "Slice label."
      },
      {
       "name": "value",
       "type": "number",
       "description": "Slice value (summed to compute proportions)."
      },
      {
       "name": "color",
       "type": "string | undefined",
       "description": "Optional explicit colour; defaults to the palette by index.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDiffOptions",
     "description": "Options for `mkComputeDiff`.",
     "file": "projects/core/src/diff.ts",
     "kind": "interface",
     "members": [
      {
       "name": "wordHighlight",
       "type": "boolean | undefined",
       "description": "Highlight the specific words that changed within paired lines.",
       "optional": true
      },
      {
       "name": "ignoreTrailingWhitespace",
       "type": "boolean | undefined",
       "description": "Treat trailing whitespace as insignificant when comparing lines.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDiffRow",
     "description": "One line of a computed diff.",
     "file": "projects/core/src/diff.ts",
     "kind": "interface",
     "members": [
      {
       "name": "op",
       "type": "MkDiffOp",
       "description": ""
      },
      {
       "name": "text",
       "type": "string",
       "description": ""
      },
      {
       "name": "beforeNo",
       "type": "number | null",
       "description": "1-based line number in the \"before\" text (null for inserts)."
      },
      {
       "name": "afterNo",
       "type": "number | null",
       "description": "1-based line number in the \"after\" text (null for deletes)."
      },
      {
       "name": "segments",
       "type": "MkDiffSegment[] | undefined",
       "description": "Word segments for changed lines (present when word highlighting runs).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDiffSegment",
     "description": "A word-level segment within a changed line.",
     "file": "projects/core/src/diff.ts",
     "kind": "interface",
     "members": [
      {
       "name": "text",
       "type": "string",
       "description": ""
      },
      {
       "name": "changed",
       "type": "boolean",
       "description": "True when this word differs from the paired line."
      }
     ]
    },
    {
     "name": "MkDiffStats",
     "description": "Summary counts for a diff.",
     "file": "projects/core/src/diff.ts",
     "kind": "interface",
     "members": [
      {
       "name": "added",
       "type": "number",
       "description": ""
      },
      {
       "name": "removed",
       "type": "number",
       "description": ""
      },
      {
       "name": "unchanged",
       "type": "number",
       "description": ""
      }
     ]
    },
    {
     "name": "MkDurationParts",
     "description": "A duration split into whole day/hour/minute/second parts.",
     "file": "projects/mk-kit/data/countdown/countdown.ts",
     "kind": "interface",
     "members": [
      {
       "name": "days",
       "type": "number",
       "description": ""
      },
      {
       "name": "hours",
       "type": "number",
       "description": ""
      },
      {
       "name": "minutes",
       "type": "number",
       "description": ""
      },
      {
       "name": "seconds",
       "type": "number",
       "description": ""
      }
     ]
    },
    {
     "name": "MkFunnelSegment",
     "description": "A single stage of the funnel (ordered largest → smallest conceptually).",
     "file": "projects/mk-kit/data/charts/funnel-chart.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Stage label (e.g. \"Visits\")."
      },
      {
       "name": "value",
       "type": "number",
       "description": "Stage value; drives the band width."
      },
      {
       "name": "color",
       "type": "string | undefined",
       "description": "Optional explicit colour; defaults to the palette by index.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkHeatmapCellColors",
     "description": "Which text token a cell value is drawn with, and the intensity to paint the cell at.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "interface",
     "members": [
      {
       "name": "intensity",
       "type": "number",
       "description": "Accent share of the cell background, 0–1."
      },
      {
       "name": "inverse",
       "type": "boolean",
       "description": "`true` → `--mk-text-inverse`, `false` → `--mk-text`."
      },
      {
       "name": "contrast",
       "type": "number",
       "description": "Contrast ratio of the chosen text against the cell background (1–21)."
      }
     ]
    },
    {
     "name": "MkHeatmapPalette",
     "description": "The resolved colours a heatmap picks its cell text against.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "interface",
     "members": [
      {
       "name": "accent",
       "type": "MkRgb",
       "description": "The `accent` input, resolved to sRGB."
      },
      {
       "name": "surface",
       "type": "MkRgb",
       "description": "`--mk-surface-2` — the zero-intensity cell colour."
      },
      {
       "name": "text",
       "type": "MkRgb",
       "description": "`--mk-text`."
      },
      {
       "name": "textInverse",
       "type": "MkRgb",
       "description": "`--mk-text-inverse`."
      }
     ]
    },
    {
     "name": "MkJsonNode",
     "description": "One rendered node of the JSON tree.",
     "file": "projects/mk-kit/data/json-viewer/json-viewer.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "string | null",
       "description": "Property name / array index; `null` for the root."
      },
      {
       "name": "type",
       "type": "\"string\" | \"number\" | \"boolean\" | \"object\" | \"array\" | \"null\" | \"circular\"",
       "description": "Node kind (drives colouring + expandability)."
      },
      {
       "name": "display",
       "type": "string",
       "description": "Display text for primitives."
      },
      {
       "name": "children",
       "type": "MkJsonNode[]",
       "description": "Children for objects/arrays."
      },
      {
       "name": "path",
       "type": "string",
       "description": "Unique path (e.g. `$.users[0].name`) used for expansion tracking."
      },
      {
       "name": "depth",
       "type": "number",
       "description": "Nesting depth (root = 0)."
      }
     ]
    },
    {
     "name": "MkLogToken",
     "description": "One render token of a log line: a styled run, optionally a search match.",
     "file": "projects/mk-kit/data/log-viewer/log-viewer.ts",
     "kind": "interface",
     "members": [
      {
       "name": "text",
       "type": "string",
       "description": ""
      },
      {
       "name": "cls",
       "type": "string",
       "description": "Space-joined `mk-ansi--*` classes ('' for plain text)."
      },
      {
       "name": "mark",
       "type": "boolean",
       "description": "True when the token is part of a search-query match."
      }
     ]
    },
    {
     "name": "MkMarkdownList",
     "description": "An ordered or unordered (tight) list block.",
     "file": "projects/core/src/markdown.ts",
     "kind": "interface",
     "members": [
      {
       "name": "kind",
       "type": "\"list\"",
       "description": ""
      },
      {
       "name": "ordered",
       "type": "boolean",
       "description": ""
      },
      {
       "name": "start",
       "type": "number",
       "description": "First ordinal of an ordered list (`3.` starts at 3). Always 1 for bullets."
      },
      {
       "name": "items",
       "type": "MkMarkdownListItem[]",
       "description": ""
      }
     ]
    },
    {
     "name": "MkMarkdownListItem",
     "description": "One `<li>`: tight inline content plus an optional nested list.",
     "file": "projects/core/src/markdown.ts",
     "kind": "interface",
     "members": [
      {
       "name": "children",
       "type": "MkMarkdownInline[]",
       "description": ""
      },
      {
       "name": "sublist",
       "type": "MkMarkdownList | null",
       "description": ""
      }
     ]
    },
    {
     "name": "MkMarkdownParseOptions",
     "description": "",
     "file": "projects/core/src/markdown.ts",
     "kind": "interface",
     "members": [
      {
       "name": "autolink",
       "type": "boolean | undefined",
       "description": "Turn bare `http(s)://…` URLs into links. Off by default.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkMarkdownRenderOptions",
     "description": "",
     "file": "projects/core/src/markdown.ts",
     "kind": "interface",
     "members": [
      {
       "name": "linkTarget",
       "type": "\"\" | \"_blank\" | undefined",
       "description": "`'_blank'` renders `target=\"_blank\" rel=\"noopener noreferrer\"` on links.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkOrgChartFlatNode",
     "description": "One row of a flat list accepted by `mkOrgChartFromFlat`.",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "interface",
     "typeParams": "<T = unknown>",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": ""
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "data",
       "type": "T | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "parentId",
       "type": "string | null | undefined",
       "description": "Id of the parent row; `null` / `undefined` / unknown id = root.",
       "optional": true
      },
      {
       "name": "expanded",
       "type": "boolean | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkOrgChartNode",
     "description": "A node in an `MkOrgChart` tree. `children` makes it a parent.",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "interface",
     "typeParams": "<T = unknown>",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": "Unique id — drives selection (`[(selected)]`) and expansion (`[(expanded)]`)."
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "Primary text of the default card (and the initials fallback).",
       "optional": true
      },
      {
       "name": "data",
       "type": "T | undefined",
       "description": "Arbitrary payload handed to the node template. The default card reads\n`data.title` (sub-label) and `data.avatar` (image URL) when present.",
       "optional": true
      },
      {
       "name": "children",
       "type": "MkOrgChartNode<T>[] | undefined",
       "description": "Direct reports; a non-empty array makes the node collapsible.",
       "optional": true
      },
      {
       "name": "expanded",
       "type": "boolean | undefined",
       "description": "Initial expansion (default `true`). Only consulted when `[(expanded)]` is not bound.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkOrgChartNodeContext",
     "description": "Template context of `ng-template[mkOrgChartNodeDef]`.",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "interface",
     "typeParams": "<T = unknown>",
     "members": [
      {
       "name": "$implicit",
       "type": "MkOrgChartNode<MkOrgChartTemplateData<T>>",
       "description": "The node (also available as `let-node`)."
      },
      {
       "name": "node",
       "type": "MkOrgChartNode<MkOrgChartTemplateData<T>>",
       "description": ""
      },
      {
       "name": "depth",
       "type": "number",
       "description": "1-based depth (roots are 1)."
      },
      {
       "name": "expanded",
       "type": "boolean",
       "description": "Whether the node's children are currently shown."
      },
      {
       "name": "selected",
       "type": "boolean",
       "description": "Whether the node is the selected one."
      }
     ]
    },
    {
     "name": "MkOrgChartToggleEvent",
     "description": "Payload of `(nodeToggle)`.",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "interface",
     "typeParams": "<T = unknown>",
     "members": [
      {
       "name": "node",
       "type": "MkOrgChartNode<T>",
       "description": ""
      },
      {
       "name": "expanded",
       "type": "boolean",
       "description": ""
      }
     ]
    },
    {
     "name": "MkPoint",
     "description": "A resolved 2-D point in SVG user space.",
     "file": "projects/mk-kit/data/charts/chart-utils.ts",
     "kind": "interface",
     "members": [
      {
       "name": "x",
       "type": "number",
       "description": ""
      },
      {
       "name": "y",
       "type": "number",
       "description": ""
      }
     ]
    },
    {
     "name": "MkScatterPoint",
     "description": "A single plotted point. `size` (optional) turns it into a bubble.",
     "file": "projects/mk-kit/data/charts/scatter-chart.ts",
     "kind": "interface",
     "members": [
      {
       "name": "x",
       "type": "number",
       "description": ""
      },
      {
       "name": "y",
       "type": "number",
       "description": ""
      },
      {
       "name": "size",
       "type": "number | undefined",
       "description": "Value driving the bubble radius when `bubble` sizing is used.",
       "optional": true
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "Optional label shown in the tooltip.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkScatterSeries",
     "description": "A named group of scatter points sharing a colour.",
     "file": "projects/mk-kit/data/charts/scatter-chart.ts",
     "kind": "interface",
     "members": [
      {
       "name": "name",
       "type": "string",
       "description": ""
      },
      {
       "name": "color",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "points",
       "type": "readonly MkScatterPoint[]",
       "description": ""
      }
     ]
    },
    {
     "name": "MkTreemapItem",
     "description": "A single treemap tile: a labelled rectangle sized by `value`.",
     "file": "projects/mk-kit/data/charts/treemap.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Tile label (identity — shown on the tile when it fits, and in the tooltip)."
      },
      {
       "name": "value",
       "type": "number",
       "description": "Positive magnitude driving the tile's area."
      },
      {
       "name": "color",
       "type": "string | undefined",
       "description": "Optional explicit colour; defaults to the validated palette by index.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTreemapRect",
     "description": "A positioned tile in SVG user space, tagged with its source `index`.",
     "file": "projects/mk-kit/data/charts/treemap.ts",
     "kind": "interface",
     "members": [
      {
       "name": "x",
       "type": "number",
       "description": ""
      },
      {
       "name": "y",
       "type": "number",
       "description": ""
      },
      {
       "name": "w",
       "type": "number",
       "description": ""
      },
      {
       "name": "h",
       "type": "number",
       "description": ""
      },
      {
       "name": "index",
       "type": "number",
       "description": ""
      }
     ]
    },
    {
     "name": "MkAvatarShape",
     "description": "Outline shape of an `MkAvatar`.",
     "file": "projects/mk-kit/data/avatar/avatar.ts",
     "kind": "type",
     "definition": "'circle' | 'rounded'"
    },
    {
     "name": "MkAvatarStatus",
     "description": "Presence status shown as a corner dot on an `MkAvatar`.",
     "file": "projects/mk-kit/data/avatar/avatar.ts",
     "kind": "type",
     "definition": "'online' | 'offline' | 'away' | 'busy'"
    },
    {
     "name": "MkBadgeOverlayPosition",
     "description": "Corner of the host an `MkBadgeOverlay` is anchored to.",
     "file": "projects/mk-kit/status/badge/badge-overlay.ts",
     "kind": "type",
     "definition": "| 'top-end' | 'top-start' | 'bottom-end' | 'bottom-start'"
    },
    {
     "name": "MkBadgeVariant",
     "description": "Visual treatment for a `MkBadge`.",
     "file": "projects/mk-kit/status/badge/badge.ts",
     "kind": "type",
     "definition": "'solid' | 'soft' | 'outline'"
    },
    {
     "name": "MkBarOrientation",
     "description": "Bar orientation.",
     "file": "projects/mk-kit/data/charts/bar-chart.ts",
     "kind": "type",
     "definition": "'vertical' | 'horizontal'"
    },
    {
     "name": "MkCardPadding",
     "description": "Internal padding scale for a `MkCard`.",
     "file": "projects/mk-kit/data/card/card.ts",
     "kind": "type",
     "definition": "'none' | 'sm' | 'md' | 'lg'"
    },
    {
     "name": "MkCardVariant",
     "description": "Surface treatment for a `MkCard`.",
     "file": "projects/mk-kit/data/card/card.ts",
     "kind": "type",
     "definition": "'elevated' | 'outlined' | 'filled'"
    },
    {
     "name": "MkDescriptionLayout",
     "description": "Layout for `MkDescriptionList`.",
     "file": "projects/mk-kit/data/description-list/description-list.ts",
     "kind": "type",
     "definition": "'grid' | 'stacked'"
    },
    {
     "name": "MkDiffMode",
     "description": "How `MkDiff` lays out the comparison.",
     "file": "projects/mk-kit/data/diff/diff.ts",
     "kind": "type",
     "definition": "'unified' | 'split'"
    },
    {
     "name": "MkDiffOp",
     "description": "The kind of change for a diff row/segment.",
     "file": "projects/core/src/diff.ts",
     "kind": "type",
     "definition": "'equal' | 'insert' | 'delete'"
    },
    {
     "name": "MkDividerOrientation",
     "description": "Axis a `MkDivider` is drawn along.",
     "file": "projects/mk-kit/data/divider/divider.ts",
     "kind": "type",
     "definition": "'horizontal' | 'vertical'"
    },
    {
     "name": "MkMarkdownAlign",
     "description": "Column alignment of a table, from the delimiter row's colons.",
     "file": "projects/core/src/markdown.ts",
     "kind": "type",
     "definition": "'left' | 'center' | 'right' | null"
    },
    {
     "name": "MkMarkdownBlock",
     "description": "Block-level node of the markdown AST.",
     "file": "projects/core/src/markdown.ts",
     "kind": "type",
     "definition": "| { kind: 'heading'; level: 1 | 2 | 3 | 4 | 5 | 6; children: MkMarkdownInline[] } | { kind: 'paragraph'; children: MkMarkdownInline[] } | { kind: 'code'; language: string; code: string } | { kind: 'blockquote'; children: MkMarkdownBlock[] } | { kind: 'hr' } | MkMarkdownList | { kind: 'table'; align: MkMarkdownAlign[]; header: MkMarkdownInline[][]; rows: MkMarkdownInline[][][]; }"
    },
    {
     "name": "MkMarkdownInline",
     "description": "Inline (phrasing) node of the markdown AST.",
     "file": "projects/core/src/markdown.ts",
     "kind": "type",
     "definition": "| { kind: 'text'; text: string } | { kind: 'softbreak' } | { kind: 'break' } | { kind: 'code'; code: string } | { kind: 'strong'; children: MkMarkdownInline[] } | { kind: 'em'; children: MkMarkdownInline[] } | { kind: 'del'; children: MkMarkdownInline[] } | { kind: 'link'; href: string; children: MkMarkdownInline[] } | { kind: 'image'; src: string; alt: string }"
    },
    {
     "name": "MkOrgChartOrientation",
     "description": "Chart direction: `top` = root at the top, `left` = root at the inline start.",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "type",
     "definition": "'top' | 'left'"
    },
    {
     "name": "MkOrgChartTemplateData",
     "description": "`data` type seen by a node template: `T` when it could be inferred (the\ntemplate binds `[mkOrgChartNodeDef]=\"nodes\"`), otherwise `any` so an\nuntyped `<ng-template mkOrgChartNodeDef>` can still read `node.data?.title`.",
     "file": "projects/mk-kit/data/org-chart/org-chart.ts",
     "kind": "type",
     "typeParams": "<T>",
     "definition": "keyof T extends never ? any : T"
    },
    {
     "name": "MkProfileCardOrientation",
     "description": "Layout direction of a `MkProfileCard`.",
     "file": "projects/mk-kit/data/profile-card/profile-card.ts",
     "kind": "type",
     "definition": "'vertical' | 'horizontal'"
    },
    {
     "name": "MkQrEcc",
     "description": "Dependency-free QR Code encoder.\n\nA from-scratch implementation of the QR encoding algorithm (ISO/IEC 18004):\nbyte-mode (UTF-8) data encoding, Reed–Solomon error correction over GF(256),\nmatrix construction with function patterns, all eight data masks scored by\nthe four penalty rules, and BCH format/version information.\n\nScope: byte mode only, versions 1–10 (module counts 21…57), ECC levels\nL/M/Q/H. That covers roughly 7–271 UTF-8 bytes depending on the ECC level.\nNumeric/alphanumeric/kanji modes and versions ≥ 11 are intentionally out of\nscope — everything is encoded as UTF-8 bytes, which is always valid.\n\nThe single public entry point is `mkEncodeQr`, a pure function.",
     "file": "projects/mk-kit/data/qr-code/qr-encode.ts",
     "kind": "type",
     "definition": "'L' | 'M' | 'Q' | 'H'"
    },
    {
     "name": "MkRgb",
     "description": "An sRGB colour as 0–255 channels.",
     "file": "projects/mk-kit/data/charts/heatmap.ts",
     "kind": "type",
     "definition": "readonly [number, number, number]"
    },
    {
     "name": "MkSkeletonPresetKind",
     "description": "Ready-made loading layouts for `MkSkeletonPreset`.",
     "file": "projects/mk-kit/data/skeleton/skeleton-preset.ts",
     "kind": "type",
     "definition": "'paragraph' | 'card' | 'list' | 'table'"
    },
    {
     "name": "MkSkeletonShape",
     "description": "Placeholder geometry for a `MkSkeleton`.",
     "file": "projects/mk-kit/data/skeleton/skeleton.ts",
     "kind": "type",
     "definition": "'text' | 'rect' | 'circle'"
    },
    {
     "name": "MkSparklineType",
     "description": "Visual form of a `MkSparkline`.",
     "file": "projects/mk-kit/data/charts/sparkline.ts",
     "kind": "type",
     "definition": "'line' | 'area' | 'bar'"
    },
    {
     "name": "MkStatTrend",
     "description": "Direction of a `MkStatCard` delta.",
     "file": "projects/mk-kit/data/stat-card/stat-card.ts",
     "kind": "type",
     "definition": "'up' | 'down' | 'neutral'"
    },
    {
     "name": "MkTagVariant",
     "description": "Visual treatment for a `MkTag`.",
     "file": "projects/mk-kit/data/tag/tag.ts",
     "kind": "type",
     "definition": "'solid' | 'soft' | 'outline'"
    }
   ]
  },
  {
   "name": "kanban",
   "import": "@mk-kit/ui/kanban",
   "exports": [
    {
     "name": "MkKanban",
     "description": "Kanban board — a horizontal row of columns whose cards can be dragged and\nreordered within a column or transferred between columns. Built on the dnd\ngroup's connected `[mkDropList]` / `[mkDrag]` directives, so it inherits both\npointer and keyboard dragging (WCAG 2.1.1) for free.\n\nBind `columns` two-way; the model is updated immutably on each drop. Project\nan `<ng-template>` to render custom card content — it receives the card as\n`$implicit` and the owning column as `column`. Column headers and footers\ntake their own templates (`mkKanbanColumnHeader` / `mkKanbanColumnFooter`,\ncontext `{ $implicit: column, index, count }`):\n\n```html\n<mk-kanban [(columns)]=\"board\" (cardMoved)=\"onMoved($event)\">\n  <ng-template mkKanbanColumnHeader let-column let-count=\"count\">\n    <strong>{{ column.title }}</strong> {{ count }}\n    <button (click)=\"rename(column)\">Rename</button>\n  </ng-template>\n  <ng-template mkKanbanCard let-card let-column=\"column\">\n    <strong>{{ card.title }}</strong>\n  </ng-template>\n  <ng-template mkKanbanColumnFooter let-column>\n    <button (click)=\"add(column)\">+ Card</button>\n  </ng-template>\n</mk-kanban>\n```",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "component",
     "selector": "mk-kanban",
     "selectors": [
      "mk-kanban"
     ],
     "inputs": [
      {
       "name": "columns",
       "type": "MkKanbanColumn[]",
       "description": "The board's columns and their cards (two-way). Updated on every drop.",
       "model": true,
       "default": "[]"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable all dragging on the board.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "columnsChange",
       "type": "MkKanbanColumn[]",
       "description": "Emits when `columns` changes (two-way binding).",
       "model": true
      },
      {
       "name": "cardMoved",
       "type": "MkKanbanCardMovedEvent",
       "description": "Emitted after the model is updated when a card is moved."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/data"
    },
    {
     "name": "MkKanbanCardDef",
     "description": "Marks the projected card renderer explicitly:\n`<ng-template mkKanbanCard let-card let-column=\"column\">`. Without it the\nfirst plain `<ng-template>` inside `<mk-kanban>` is used, as before 0.54.",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "directive",
     "selector": "ng-template[mkKanbanCard]",
     "selectors": [
      "mkKanbanCard"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkKanbanColumnFooterDef",
     "description": "Rendered under each column's card list — a \"quick add\" input, say:\n`<ng-template mkKanbanColumnFooter let-column>`.",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "directive",
     "selector": "ng-template[mkKanbanColumnFooter]",
     "selectors": [
      "mkKanbanColumnFooter"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkKanbanColumnHeaderDef",
     "description": "Replaces the default column header (title + count):\n`<ng-template mkKanbanColumnHeader let-column let-count=\"count\">`.",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "directive",
     "selector": "ng-template[mkKanbanColumnHeader]",
     "selectors": [
      "mkKanbanColumnHeader"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkKanbanCard",
     "description": "A single draggable card on a `MkKanban` board.",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "unknown",
       "description": "Stable identity used for tracking and move events."
      },
      {
       "name": "title",
       "type": "string",
       "description": "Text shown by the default card renderer."
      }
     ]
    },
    {
     "name": "MkKanbanCardMovedEvent",
     "description": "Emitted by `MkKanban` after a card has been moved (between or within\ncolumns) and the two-way `columns` model has been updated.",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "interface",
     "members": [
      {
       "name": "card",
       "type": "MkKanbanCard",
       "description": "The card that was moved."
      },
      {
       "name": "from",
       "type": "unknown",
       "description": "`id` of the column the card came from."
      },
      {
       "name": "to",
       "type": "unknown",
       "description": "`id` of the column the card was dropped into."
      },
      {
       "name": "fromIndex",
       "type": "number",
       "description": "The card's index within the source column before the move."
      },
      {
       "name": "toIndex",
       "type": "number",
       "description": "The card's index within the destination column after the move."
      }
     ]
    },
    {
     "name": "MkKanbanColumn",
     "description": "A column (bucket) of `MkKanbanCard`s on a `MkKanban` board.",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "unknown",
       "description": "Stable identity used for tracking and move events."
      },
      {
       "name": "title",
       "type": "string",
       "description": "Heading shown in the column header and used as its aria-label."
      },
      {
       "name": "cards",
       "type": "MkKanbanCard[]",
       "description": "The ordered cards contained in this column."
      }
     ]
    },
    {
     "name": "MkKanbanColumnContext",
     "description": "Context handed to the column header / footer templates.",
     "file": "projects/mk-kit/kanban/kanban.ts",
     "kind": "interface",
     "members": [
      {
       "name": "$implicit",
       "type": "MkKanbanColumn",
       "description": "The column being rendered."
      },
      {
       "name": "index",
       "type": "number",
       "description": "Its position in `columns`."
      },
      {
       "name": "count",
       "type": "number",
       "description": "`column.cards.length`, for a count badge."
      }
     ]
    }
   ]
  },
  {
   "name": "translate",
   "import": "@mk-kit/ui/translate",
   "exports": [
    {
     "name": "MkTranslatePipe",
     "description": "`translate` — the key's string in the active language, with `{{name}}`\nplaceholders filled from `params`. Impure so a language switch (or a\n`patch()`) re-renders every use; the signal reads inside `instant()` mark\nthe host view dirty, so this stays cheap under OnPush and zoneless.\n\n```html\n{{ 'menu.title' | translate }}\n{{ 'cart.items' | translate: { count: 3 } }}\n```",
     "file": "projects/mk-kit/translate/translate.pipe.ts",
     "kind": "pipe",
     "pipeName": "translate",
     "signature": "(key: string | null | undefined, params?: MkTranslateParams): string"
    },
    {
     "name": "MkTranslatePluralPipe",
     "description": "`translatePlural` — the CLDR plural form under `keyBase` for a count\n(see `MkTranslate.plural`), interpolated with `{ count, ...params }`.\n\n```html\n{{ guests | translatePlural: 'reservation.guests' }}   <!-- 2 osoby / 5 osób -->\n```",
     "file": "projects/mk-kit/translate/translate.pipe.ts",
     "kind": "pipe",
     "pipeName": "translatePlural",
     "signature": "(count: number | string | null | undefined, keyBase: string, params?: MkTranslateParams): string"
    },
    {
     "name": "MkTranslate",
     "description": "App translations as signals: a `lang` you switch with `use()`, `instant()`\nfor code, the `translate` pipe for templates, and `plural()` for CLDR\ncount forms. Dictionaries are the plain nested JSON you already have; an\noptional overrides loader (a database of edits, say) is merged on top per\nlanguage. On the server the loaded strings ride to the browser through\n`TransferState`, so hydration never refetches or flashes raw keys.\n\n```ts\nprovideMkTranslate({\n  lang: 'pl',\n  fallbackLang: 'pl',\n  loader: mkHttpTranslateLoader({ prefix: '/assets/i18n/' }),\n});\n```\n```html\n{{ 'checkout.cart.total' | translate }}\n{{ 'checkout.cart.freeDeliveryMissing' | translate: { amount: 12 } }}\n```",
     "file": "projects/mk-kit/translate/translate.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "getCurrentLang",
       "signature": "(): string",
       "description": "The active language as a plain string (for non-reactive call sites)."
      },
      {
       "name": "getLangs",
       "signature": "(): string[]",
       "description": "Languages known to the service: loaded ones plus any added with `addLangs`."
      },
      {
       "name": "addLangs",
       "signature": "(langs: string[]): void",
       "description": "Declare languages up front (a switcher's list); loading still happens on `use()`."
      },
      {
       "name": "setTranslation",
       "signature": "(lang: string, strings: MkTranslationTree | MkFlatTranslations, shouldMerge?: boolean): void",
       "description": "ngx-translate-compatible alias: `setTranslation(lang, strings, true)`\nmerges like `patch`, `false` (the default there) replaces like\n`set`."
      },
      {
       "name": "use",
       "signature": "(lang: string): Promise<void>",
       "description": "Load `lang` (once — later calls are cached) and make it active. Resolves\nwhen the strings are in memory; a failed load rejects and leaves the\nprevious language active."
      },
      {
       "name": "load",
       "signature": "(lang: string): Promise<void>",
       "description": "Load a language into memory without switching to it."
      },
      {
       "name": "instant",
       "signature": "(key: string, params?: MkTranslateParams): string",
       "description": "Translate `key` in the active language, then the fallback; `{{name}}`\nplaceholders come from `params`. A missing key renders as the key\nitself (or whatever `onMissing` returns) and is recorded in\n`missingKeys`. Reactive: reading it inside a template or a\n`computed()` re-runs on language switch and after `patch()`."
      },
      {
       "name": "has",
       "signature": "(key: string, lang?: string): boolean",
       "description": "Whether `key` exists in `lang` (default: the active language) or its fallback."
      },
      {
       "name": "plural",
       "signature": "(keyBase: string, count: number, params?: MkTranslateParams): string",
       "description": "CLDR plural form: `keyBase.{zero|one|two|few|many|other}` picked with\n`Intl.PluralRules` for the active language, `other` as the fallback,\ninterpolated with `{ count, ...params }`.\n\n```json\n{ \"guests\": { \"one\": \"{{count}} osoba\", \"few\": \"{{count}} osoby\", \"many\": \"{{count}} osób\", \"other\": \"{{count}} osoby\" } }\n```"
      },
      {
       "name": "translations",
       "signature": "(lang?: string): MkFlatTranslations",
       "description": "The flat dictionary of `lang` (default: active), `{}` before it loads."
      },
      {
       "name": "loadedLangs",
       "signature": "(): string[]",
       "description": "Languages currently in memory."
      },
      {
       "name": "patch",
       "signature": "(lang: string, strings: MkTranslationTree | MkFlatTranslations): void",
       "description": "Merge strings into `lang` at runtime — a translation editor previewing\nan edit, or a late-arriving overrides payload. Nested or flat."
      },
      {
       "name": "set",
       "signature": "(lang: string, strings: MkTranslationTree | MkFlatTranslations): void",
       "description": "Replace `lang` entirely (tests, editors reloading from source)."
      },
      {
       "name": "isPartial",
       "signature": "(lang?: string): boolean",
       "description": "`true` while `lang` holds only a server render's keys and the rest is still loading."
      }
     ],
     "properties": [
      {
       "name": "lang",
       "type": "WritableSignal<string>",
       "description": "The active language. Read it in a `computed()` to follow switches.",
       "readonly": true
      },
      {
       "name": "ready",
       "type": "Signal<boolean>",
       "description": "`true` once the active language's strings are in memory.",
       "readonly": true
      },
      {
       "name": "langChange",
       "type": "Observable<string>",
       "description": "`lang` as an observable, for code still written around streams.",
       "readonly": true
      },
      {
       "name": "missingKeys",
       "type": "Signal<string[]>",
       "description": "Keys asked for that neither the active nor the fallback language has.",
       "readonly": true
      },
      {
       "name": "currentLang",
       "type": "string",
       "description": "ngx-translate-compatible alias of `getCurrentLang`.",
       "readonly": true
      }
     ],
     "docs": "/components/translate"
    },
    {
     "name": "mkFlattenTranslations",
     "description": "`{ a: { b: 'x' } }` → `{ 'a.b': 'x' }`; already-dotted keys pass through.",
     "file": "projects/mk-kit/translate/translate.service.ts",
     "kind": "function",
     "signatures": [
      "(tree: MkTranslationTree | null | undefined, prefix?: string, out?: MkFlatTranslations): MkFlatTranslations"
     ]
    },
    {
     "name": "mkHttpTranslateLoader",
     "description": "Fetch `<prefix><lang><suffix>` with `HttpClient` — the bundled JSON files\nin `assets/i18n/`. Needs `provideHttpClient()`; SSR apps that read the\nfiles from disk can supply their own `MkTranslateLoader` instead.",
     "file": "projects/mk-kit/translate/translate.loaders.ts",
     "kind": "function",
     "signatures": [
      "(options?: MkHttpTranslateLoaderOptions): MkTranslateLoaderFactory"
     ]
    },
    {
     "name": "mkInterpolate",
     "description": "Replace `{{name}}` placeholders; unknown names are left in place.",
     "file": "projects/mk-kit/translate/translate.service.ts",
     "kind": "function",
     "signatures": [
      "(template: string, params?: MkTranslateParams): string"
     ]
    },
    {
     "name": "mkStaticTranslateLoader",
     "description": "Strings given up front, keyed by language — tests, storybooks, tiny apps.\nA language not in the map resolves to `{}`.",
     "file": "projects/mk-kit/translate/translate.loaders.ts",
     "kind": "function",
     "signatures": [
      "(byLang: Record<string, MkTranslationTree>): MkTranslateLoaderFactory"
     ]
    },
    {
     "name": "mkUnflattenTranslations",
     "description": "`{ 'a.b': 'x' }` → `{ a: { b: 'x' } }` — for editors that write files back.",
     "file": "projects/mk-kit/translate/translate.service.ts",
     "kind": "function",
     "signatures": [
      "(flat: MkFlatTranslations): MkTranslationTree"
     ]
    },
    {
     "name": "provideMkTranslate",
     "description": "Register app translations. By default the initial language is loaded\nbefore the first render (`preload`), so no view ever shows raw keys and\nnothing caches them.\n\n```ts\nproviders: [\n  provideHttpClient(withFetch()),\n  provideMkTranslate({\n    lang: 'pl',\n    fallbackLang: 'pl',\n    loader: mkHttpTranslateLoader(),\n    overrides: () => inject(TranslationOverridesApi), // optional\n  }),\n]\n```",
     "file": "projects/mk-kit/translate/translate.providers.ts",
     "kind": "function",
     "signatures": [
      "(config: MkTranslateConfig): EnvironmentProviders"
     ]
    },
    {
     "name": "MK_TRANSLATE_CONFIG",
     "description": "Configuration token; set by `provideMkTranslate`.",
     "file": "projects/mk-kit/translate/translate.service.ts",
     "kind": "token",
     "type": "InjectionToken<MkTranslateConfig>"
    },
    {
     "name": "MkTranslateImports",
     "description": "Everything a template needs, for `imports: [...MkTranslateImports]` — the\none-line replacement for an ngx-translate `TranslateModule` import.",
     "file": "projects/mk-kit/translate/translate.pipe.ts",
     "kind": "const",
     "type": "readonly [typeof MkTranslatePipe, typeof MkTranslatePluralPipe]"
    },
    {
     "name": "MkHttpTranslateLoaderOptions",
     "description": "Options for `mkHttpTranslateLoader`.",
     "file": "projects/mk-kit/translate/translate.loaders.ts",
     "kind": "interface",
     "members": [
      {
       "name": "prefix",
       "type": "string | undefined",
       "description": "URL prefix; the language code is appended. Default `/assets/i18n/`.",
       "optional": true
      },
      {
       "name": "suffix",
       "type": "string | undefined",
       "description": "URL suffix after the language code. Default `.json`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTranslateConfig",
     "description": "Options for `provideMkTranslate`.",
     "file": "projects/mk-kit/translate/translate.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "lang",
       "type": "string",
       "description": "Language loaded first and used until `use()` switches it."
      },
      {
       "name": "fallbackLang",
       "type": "string | undefined",
       "description": "Looked up when the active language lacks a key. Default: none.",
       "optional": true
      },
      {
       "name": "loader",
       "type": "MkTranslateLoaderFactory",
       "description": "Base strings — the bundled JSON, typically (`mkHttpTranslateLoader`)."
      },
      {
       "name": "overrides",
       "type": "MkTranslateLoaderFactory | undefined",
       "description": "Optional second source merged OVER the base per language: edits kept in\na database, a tenant's wording, a translator's work in progress. A\nloader that throws or resolves `{}` leaves the base untouched.",
       "optional": true
      },
      {
       "name": "preload",
       "type": "boolean | undefined",
       "description": "Block application bootstrap until the initial language is loaded, so the\nfirst render never shows raw keys and `instant()` calls inside\n`computed()` never cache them. Default `true`.",
       "optional": true
      },
      {
       "name": "transfer",
       "type": "\"none\" | \"used\" | \"all\" | undefined",
       "description": "What a server render hands to the browser through `TransferState`:\n- `'used'` (default): only the keys read while rendering this page —\n  a few KB — so hydration never flashes raw keys, while the full\n  dictionary loads in the background right after;\n- `'all'`: the whole dictionary (no second request, but every page\n  carries it);\n- `'none'`: nothing; the browser loads the file itself before bootstrap.",
       "optional": true
      },
      {
       "name": "documentLang",
       "type": "boolean | undefined",
       "description": "Mirror the active language onto `<html lang>` (server and browser), so\nscreen readers, hyphenation and search engines follow `use()`. Default\n`true`.",
       "optional": true
      },
      {
       "name": "onMissing",
       "type": "((key: string, lang: string) => string | undefined | void) | undefined",
       "description": "Called for a key missing in both the active and the fallback language.\nReturn a string to render instead of the key. Missing keys are also\ncollected in `MkTranslate.missingKeys`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkTranslateLoader",
     "description": "Where a language's strings come from. Return the tree (or a promise of\nit); the service flattens, caches per language and merges overrides.",
     "file": "projects/mk-kit/translate/translate.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "load",
       "type": "(lang: string): Promise<MkTranslationTree> | MkTranslationTree",
       "description": ""
      }
     ]
    },
    {
     "name": "MkTranslationTree",
     "description": "A translation file: nested objects of strings. Keys are addressed with\ndots (`checkout.cart.total`), so `{ checkout: { cart: { total: '…' } } }`\nand `{ 'checkout.cart.total': '…' }` are the same dictionary. This is the\nplain JSON most apps already ship (ngx-translate's format included).",
     "file": "projects/mk-kit/translate/translate.types.ts",
     "kind": "interface",
     "members": []
    },
    {
     "name": "MkFlatTranslations",
     "description": "Flattened dictionary: dotted key → string.",
     "file": "projects/mk-kit/translate/translate.types.ts",
     "kind": "type",
     "definition": "Record<string, string>"
    },
    {
     "name": "MkTranslateLoaderFactory",
     "description": "A loader factory; runs inside an injection context, so `inject()` works.",
     "file": "projects/mk-kit/translate/translate.types.ts",
     "kind": "type",
     "definition": "() => MkTranslateLoader"
    },
    {
     "name": "MkTranslateParams",
     "description": "Values interpolated into `{{name}}` placeholders.",
     "file": "projects/mk-kit/translate/translate.types.ts",
     "kind": "type",
     "definition": "Record<string, unknown>"
    }
   ]
  },
  {
   "name": "attention",
   "import": "@mk-kit/ui/attention",
   "exports": [
    {
     "name": "MkSessionExpiryDialog",
     "description": "Last call before a session ends: counts down and offers to extend.\nReaching zero ends the session, so doing nothing still produces a definite,\nvisible outcome. Opened by `MkSessionExpiry`; usable on its own.",
     "file": "projects/mk-kit/attention/session-expiry.ts",
     "kind": "component",
     "selector": "mk-session-expiry-dialog",
     "selectors": [
      "mk-session-expiry-dialog"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/attention"
    },
    {
     "name": "MkNotificationSound",
     "description": "Alert sounds for incoming work (orders, messages, tickets) with the\nbrowser's autoplay rules handled: an `AudioContext` stays suspended until a\nuser gesture, so a sound fired by a WebSocket message would be silent. The\ncontext is unlocked when the user enables sound (a click) and lazily on the\nfirst interaction anywhere in the app. The default sound is synthesised\n(a short C–E–G chime) — nothing to ship, no CORS, lowest latency; file\npresets are fetched and decoded once and fall back to the chime when they\nfail. The on/off preference lives in localStorage under a configurable key.\n\n```ts\nprovideMkNotificationSound({ presets: [MK_CHIME_PRESET, { id: 'ding', label: 'Ding', url: '/assets/ding.wav' }] })\nsound.primeOnFirstInteraction();          // at app start\nsound.play(settings.newOrderSound);       // on an event, honours the device mute\nsound.preview('ding');                    // settings page test button\n```",
     "file": "projects/mk-kit/attention/notification-sound.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "isEnabled",
       "signature": "(): boolean",
       "description": "Whether the device has sound on."
      },
      {
       "name": "hasBeenAsked",
       "signature": "(): boolean",
       "description": "Whether the user ever answered the \"enable sound?\" question on this device."
      },
      {
       "name": "setEnabled",
       "signature": "(enabled: boolean): void",
       "description": "Persist the preference; call from a click so audio unlocks at once."
      },
      {
       "name": "primeOnFirstInteraction",
       "signature": "(): void",
       "description": "Arm a one-time listener so the first pointer/key interaction unlocks audio."
      },
      {
       "name": "chime",
       "signature": "(): void",
       "description": "The default chime, if the device has sound on."
      },
      {
       "name": "play",
       "signature": "(soundId: string, customUrl?: string | null): void",
       "description": "Play the sound configured for an event: a preset id, `custom` (with\n`customUrl`) or `none` (silent). Unknown ids and failed loads fall back\nto the chime. Honours the device mute."
      },
      {
       "name": "preview",
       "signature": "(soundId: string, customUrl?: string | null): void",
       "description": "Same as `play()` but ignores the device mute — for settings test buttons."
      }
     ],
     "properties": [
      {
       "name": "presets",
       "type": "MkSoundPreset[]",
       "description": "The selectable presets (always includes the chime).",
       "readonly": true
      }
     ],
     "docs": "/components/attention"
    },
    {
     "name": "MkSessionExpiry",
     "description": "Watches `expiresAt()` and warns BEFORE the session lapses, so a session\nnever ends silently: the dialog offers to extend, or signs out at zero.\nRe-arms itself whenever `expiresAt()` changes (every token rotation),\nruns the timer outside the Angular zone and only in the browser. Started\nautomatically by `provideMkSessionExpiry`.",
     "file": "projects/mk-kit/attention/session-expiry.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "start",
       "signature": "(): void",
       "description": "Begin watching. Idempotent; called by the provider's initializer."
      }
     ],
     "properties": [
      {
       "name": "open",
       "type": "WritableSignal<boolean>",
       "description": "Whether the dialog is currently open.",
       "readonly": true
      }
     ],
     "docs": "/components/attention"
    },
    {
     "name": "MkTabAttention",
     "description": "Messenger-style tab attention: while unhandled work exists the favicon\ncarries a red counter badge, and — only while the tab is hidden — the\ntitle alternates with \"(N) label\" so a pinned tab flashes in the tab strip.\nFocusing the tab stops the blinking (someone is looking) but keeps the\nbadge until the count reaches zero. SSR-safe: every entry point bails\nwithout a `document`; the blink timer runs outside the Angular zone.\n\n```ts\nprivate attention = inject(MkTabAttention);\neffect(() => this.attention.set(this.pending().length, 'new orders'));\n```",
     "file": "projects/mk-kit/attention/tab-attention.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "set",
       "signature": "(count: number, label?: string): void",
       "description": "Update the pending count and the label used in the blinking title."
      },
      {
       "name": "clear",
       "signature": "(): void",
       "description": "Drop the badge and the blinking entirely and stop listening."
      }
     ],
     "properties": [
      {
       "name": "count",
       "type": "WritableSignal<number>",
       "description": "The count currently shown (0 = nothing pending).",
       "readonly": true
      }
     ],
     "docs": "/components/attention"
    },
    {
     "name": "provideMkNotificationSound",
     "description": "Register presets / storage key for `MkNotificationSound`. Optional.",
     "file": "projects/mk-kit/attention/notification-sound.ts",
     "kind": "function",
     "signatures": [
      "(config: MkNotificationSoundConfig): { provide: InjectionToken<MkNotificationSoundConfig>; useValue: MkNotificationSoundConfig; }"
     ]
    },
    {
     "name": "provideMkSessionExpiry",
     "description": "Register the session-expiry watcher; it starts with the application.\n\n```ts\nprovideMkSessionExpiry({\n  expiresAt: () => auth.tokenExpiresAt(),\n  extend: () => firstValueFrom(auth.refresh()),\n  onExpire: () => auth.logout(),\n  warnBeforeMs: 2 * 60_000,\n})\n```",
     "file": "projects/mk-kit/attention/session-expiry.ts",
     "kind": "function",
     "signatures": [
      "(config: MkSessionExpiryConfig): EnvironmentProviders"
     ]
    },
    {
     "name": "provideMkTabAttention",
     "description": "Register options for `MkTabAttention`. Optional — the defaults work.",
     "file": "projects/mk-kit/attention/tab-attention.ts",
     "kind": "function",
     "signatures": [
      "(config: MkTabAttentionConfig): { provide: InjectionToken<MkTabAttentionConfig>; useValue: MkTabAttentionConfig; }"
     ]
    },
    {
     "name": "MK_NOTIFICATION_SOUND_CONFIG",
     "description": "",
     "file": "projects/mk-kit/attention/notification-sound.ts",
     "kind": "token",
     "type": "InjectionToken<MkNotificationSoundConfig>"
    },
    {
     "name": "MK_SESSION_EXPIRY_CONFIG",
     "description": "",
     "file": "projects/mk-kit/attention/session-expiry.ts",
     "kind": "token",
     "type": "InjectionToken<MkSessionExpiryConfig>"
    },
    {
     "name": "MK_TAB_ATTENTION_CONFIG",
     "description": "",
     "file": "projects/mk-kit/attention/tab-attention.ts",
     "kind": "token",
     "type": "InjectionToken<MkTabAttentionConfig>"
    },
    {
     "name": "MK_CHIME_PRESET",
     "description": "The always-available synthesised sound.",
     "file": "projects/mk-kit/attention/notification-sound.ts",
     "kind": "const",
     "type": "MkSoundPreset"
    },
    {
     "name": "MkNotificationSoundConfig",
     "description": "Options for `MkNotificationSound`.",
     "file": "projects/mk-kit/attention/notification-sound.ts",
     "kind": "interface",
     "members": [
      {
       "name": "presets",
       "type": "MkSoundPreset[] | undefined",
       "description": "Selectable sounds; the ids `custom` and `none` are reserved. Default: the chime only.",
       "optional": true
      },
      {
       "name": "storageKey",
       "type": "(() => string) | undefined",
       "description": "localStorage key for the on/off preference — a function so it can vary per tenant / user.",
       "optional": true
      },
      {
       "name": "volume",
       "type": "number | undefined",
       "description": "Output gain for file presets (0–1). Default `0.8`.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkSessionExpiryConfig",
     "description": "Options for `provideMkSessionExpiry`.",
     "file": "projects/mk-kit/attention/session-expiry.ts",
     "kind": "interface",
     "members": [
      {
       "name": "expiresAt",
       "type": "() => number | null",
       "description": "Epoch ms when the session lapses, or `null` when there is none. Read reactively."
      },
      {
       "name": "warnBeforeMs",
       "type": "number | undefined",
       "description": "How long before the lapse the dialog appears. Default 2 minutes.",
       "optional": true
      },
      {
       "name": "extend",
       "type": "() => Promise<unknown>",
       "description": "Extend the session (refresh the token). Resolve = extended, reject = nothing to extend."
      },
      {
       "name": "onExpire",
       "type": "() => void",
       "description": "End the session (sign out, navigate)."
      },
      {
       "name": "enabled",
       "type": "(() => boolean) | undefined",
       "description": "Read reactively; `false` suspends the watcher (a kiosk / PIN mode, say).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkSessionExpiryDialogData",
     "description": "Data handed to `MkSessionExpiryDialog`.",
     "file": "projects/mk-kit/attention/session-expiry.ts",
     "kind": "interface",
     "members": [
      {
       "name": "expiresAt",
       "type": "number",
       "description": ""
      },
      {
       "name": "extend",
       "type": "() => Promise<unknown>",
       "description": ""
      },
      {
       "name": "onExpire",
       "type": "() => void",
       "description": ""
      }
     ]
    },
    {
     "name": "MkSoundPreset",
     "description": "One selectable alert sound. `url: null` = the synthesised chime.",
     "file": "projects/mk-kit/attention/notification-sound.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": ""
      },
      {
       "name": "label",
       "type": "string",
       "description": ""
      },
      {
       "name": "url",
       "type": "string | null",
       "description": ""
      }
     ]
    },
    {
     "name": "MkTabAttentionConfig",
     "description": "Options for `MkTabAttention`, set with `provideMkTabAttention`.",
     "file": "projects/mk-kit/attention/tab-attention.ts",
     "kind": "interface",
     "members": [
      {
       "name": "badgeColor",
       "type": "string | undefined",
       "description": "Badge fill colour (any CSS colour). Default `#e53935`.",
       "optional": true
      },
      {
       "name": "blinkMs",
       "type": "number | undefined",
       "description": "Title blink period in ms while the tab is hidden. Default `1200`.",
       "optional": true
      }
     ]
    }
   ]
  },
  {
   "name": "feedback",
   "import": "@mk-kit/ui/feedback",
   "exports": [
    {
     "name": "MkAlert",
     "description": "Alert — an inline banner that communicates a contextual status message.\nFully themed via `--mk-*` tokens using the same tone/local-var pattern as\nthe Button. Danger/warning alerts use `role=\"alert\"` (assertive), all other\ntones use `role=\"status\"` (polite).\n\n```html\n<mk-alert tone=\"success\" title=\"Saved\">Your changes were saved.</mk-alert>\n\n<mk-alert tone=\"danger\" variant=\"outline\" dismissible (dismissed)=\"hide()\">\n  <svg mkAlertIcon>…</svg>\n  Could not reach the server.\n</mk-alert>\n```",
     "file": "projects/mk-kit/feedback/alert/alert.ts",
     "kind": "component",
     "selector": "mk-alert",
     "selectors": [
      "mk-alert"
     ],
     "inputs": [
      {
       "name": "tone",
       "type": "MkAlertTone",
       "description": "Semantic color tone.",
       "default": "'info'"
      },
      {
       "name": "variant",
       "type": "MkAlertVariant",
       "description": "Visual treatment.",
       "default": "'soft'"
      },
      {
       "name": "title",
       "type": "string | undefined",
       "description": "Optional bold heading rendered above the message."
      },
      {
       "name": "dismissible",
       "type": "boolean",
       "description": "When set, renders a keyboard-accessible close button that emits `dismissed`.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "dismissed",
       "type": "void",
       "description": "Emitted when the user activates the close button."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/feedback"
    },
    {
     "name": "MkBanner",
     "description": "Banner — a persistent, full-width page/section message with a tone, optional\ntitle, an actions slot and optional dismiss. Heavier than an inline\n`MkAlert` toast; use it for standing notices (\"Trial ends in 3 days\").\n\nProject an icon with `[mkBannerIcon]` and buttons with `[mkBannerActions]`.\nDanger/warning banners announce assertively (`role=\"alert\"`).\n\n```html\n<mk-banner tone=\"warning\" title=\"Storage almost full\" dismissible>\n  You've used 90% of your quota.\n  <button mkButton size=\"sm\" mkBannerActions>Upgrade</button>\n</mk-banner>\n```",
     "file": "projects/mk-kit/feedback/banner/banner.ts",
     "kind": "component",
     "selector": "mk-banner",
     "selectors": [
      "mk-banner"
     ],
     "inputs": [
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Semantic color tone.",
       "default": "'info'"
      },
      {
       "name": "title",
       "type": "string",
       "description": "Optional bold title above the message.",
       "default": "''"
      },
      {
       "name": "dismissible",
       "type": "boolean",
       "description": "Show a dismiss (×) button.",
       "default": "false"
      },
      {
       "name": "open",
       "type": "boolean",
       "description": "Two-way open state; set false to hide.",
       "model": true,
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "openChange",
       "type": "boolean",
       "description": "Emits when `open` changes (two-way binding).",
       "model": true
      },
      {
       "name": "dismissed",
       "type": "void",
       "description": "Emitted when the banner is dismissed."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/feedback"
    },
    {
     "name": "MkBlockUiOverlay",
     "description": "The translucent panel with a spinner that `mkBlockUi` and\n`MkBlockUiService` drop over a region or the page.",
     "file": "projects/mk-kit/feedback/block-ui/block-ui.ts",
     "kind": "component",
     "selector": "mk-block-ui-overlay",
     "selectors": [
      "mk-block-ui-overlay"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkBottomSheet",
     "description": "BottomSheet layout — the surface rendered inside an `MkOverlayService`\npanel by `MkBottomSheetService`. Provides a drag handle (swipe down to\ndismiss), an optional titled header with a close button, and a scrollable\nbody for projected content.\n\nSlots: `[mkBottomSheetHeader]` (extra header content), default content\n(body), `[mkBottomSheetFooter]` (sticky footer).\n\n```html\n<mk-bottom-sheet sheetTitle=\"Share\">\n  <button mkButton fullWidth variant=\"ghost\">Copy link</button>\n  <button mkButton fullWidth variant=\"ghost\">Email</button>\n</mk-bottom-sheet>\n```",
     "file": "projects/mk-kit/feedback/bottom-sheet/bottom-sheet.ts",
     "kind": "component",
     "selector": "mk-bottom-sheet",
     "selectors": [
      "mk-bottom-sheet"
     ],
     "inputs": [
      {
       "name": "sheetTitle",
       "type": "string | undefined",
       "description": "Optional plain-text title rendered in the header."
      },
      {
       "name": "titleId",
       "type": "string",
       "description": "Stable id for the built-in title element.",
       "default": "mkUniqueId('mk-bottom-sheet-title')"
      },
      {
       "name": "hideHandle",
       "type": "boolean",
       "description": "Hide the drag handle (also disables swipe-to-dismiss).",
       "default": "false"
      },
      {
       "name": "hideClose",
       "type": "boolean",
       "description": "Hide the header close button.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/bottom-sheet"
    },
    {
     "name": "MkConfirmDialog",
     "description": "Internal component backing `MkDialogService.confirm`. Renders a title,\nmessage, and cancel/confirm buttons. Resolves the overlay ref with `true`\non confirm and `false` on cancel. Uses `alertdialog` semantics for the\n`danger` tone (set on the panel by the service).",
     "file": "projects/mk-kit/feedback/dialog/confirm-dialog.ts",
     "kind": "component",
     "selector": "mk-confirm-dialog",
     "selectors": [
      "mk-confirm-dialog"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/dialogs"
    },
    {
     "name": "MkDialog",
     "description": "Dialog layout — a surface with a sticky header, scrollable body, and sticky\nfooter, designed to be rendered inside an `MkOverlayService` panel. The\nheader exposes a close button wired to the injected `MkOverlayRef` and\nthe dialog's title is linked to the panel via `aria-labelledby`.\n\nSlots: `[mkDialogHeader]` / `<mk-dialog-title>` (header), default content\n(body), `[mkDialogFooter]` (footer).\n\n```html\n<mk-dialog>\n  <mk-dialog-title>Rename</mk-dialog-title>\n  <p>Choose a new name.</p>\n  <div mkDialogFooter>\n    <button mkButton variant=\"ghost\">Cancel</button>\n    <button mkButton>Save</button>\n  </div>\n</mk-dialog>\n```",
     "file": "projects/mk-kit/feedback/dialog/dialog.ts",
     "kind": "component",
     "selector": "mk-dialog",
     "selectors": [
      "mk-dialog"
     ],
     "inputs": [
      {
       "name": "dialogTitle",
       "type": "string | undefined",
       "description": "Optional plain-text title. Ignored when a `<mk-dialog-title>` is projected."
      },
      {
       "name": "titleId",
       "type": "string",
       "description": "Stable id for the built-in title element.",
       "default": "mkUniqueId('mk-dialog-title')"
      },
      {
       "name": "hideClose",
       "type": "boolean",
       "description": "Hide the header close button.",
       "default": "false"
      },
      {
       "name": "draggable",
       "type": "boolean",
       "description": "Let the user move the dialog by dragging its header (pointer / touch) or\nwith the arrow keys on the grip that appears in the header. Double-click\nthe header or press Home on the grip to snap back to the centre.",
       "default": "false"
      },
      {
       "name": "resizable",
       "type": "boolean",
       "description": "Let the user resize the dialog from the corner grip (pointer / touch, or\narrow keys on the grip; Home resets). The panel never grows past the\nviewport or shrinks below a usable minimum.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [
      {
       "name": "reset",
       "signature": "(): void",
       "description": "Snap back to the centred, preset-sized panel."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/dialogs"
    },
    {
     "name": "MkDialogTitle",
     "description": "Accessible heading for a dialog. Renders as a level-2 heading and exposes a\nstable id that `MkDialog` wires to the panel's `aria-labelledby`.\n\n```html\n<mk-dialog>\n  <mk-dialog-title>Delete workspace</mk-dialog-title>\n  …\n</mk-dialog>\n```",
     "file": "projects/mk-kit/feedback/dialog/dialog.ts",
     "kind": "component",
     "selector": "mk-dialog-title",
     "selectors": [
      "mk-dialog-title"
     ],
     "inputs": [
      {
       "name": "id",
       "type": "string",
       "description": "Stable id used for `aria-labelledby` wiring.",
       "default": "mkUniqueId('mk-dialog-title')"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/dialogs"
    },
    {
     "name": "MkHovercard",
     "description": "Hovercard — a rich hover-preview panel anchored to a trigger, in the spirit of\nGitHub's user hovercards. Unlike `MkTooltip` (short text) it projects\narbitrary content, and unlike `MkPopover` (click) it opens on hover/focus\nafter a short delay and closes when the pointer leaves both the trigger and the\ncard. It is driven by the `mkHovercardFor` directive (or the `open`/`close` API).\n\nThe panel renders in the browser top layer through `MkAnchoredPanel`, so\nit is never clipped by an ancestor's `overflow`/`transform`. It is non-modal —\nno focus trap. Moving the pointer from the trigger onto the card keeps it open;\nEscape closes it.\n\n```html\n<a href=\"/u/ada\" [mkHovercardFor]=\"ada\">@ada</a>\n<mk-hovercard #ada ariaLabel=\"Ada Lovelace\">\n  <img src=\"/ada.png\" alt=\"\" /><strong>Ada Lovelace</strong>\n</mk-hovercard>\n```",
     "file": "projects/mk-kit/feedback/hovercard/hovercard.ts",
     "kind": "component",
     "selector": "mk-hovercard",
     "selectors": [
      "mk-hovercard"
     ],
     "exportAs": "mkHovercard",
     "inputs": [
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": "Preferred placement relative to the trigger.",
       "default": "'bottom-start'"
      },
      {
       "name": "ariaLabel",
       "type": "string | undefined",
       "description": "Accessible label for the panel."
      },
      {
       "name": "openDelay",
       "type": "number",
       "description": "Delay in ms before the card opens on hover/focus. Default `300`.",
       "default": "300"
      },
      {
       "name": "closeDelay",
       "type": "number",
       "description": "Delay in ms before the card closes after the pointer leaves. Default `200`.",
       "default": "200"
      },
      {
       "name": "closeOnEscape",
       "type": "boolean",
       "description": "Close the card when Escape is pressed while it is open. Default `true`.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "closed",
       "type": "void",
       "description": "Emitted whenever the hovercard closes (any reason)."
      }
     ],
     "methods": [
      {
       "name": "scheduleOpen",
       "signature": "(trigger: HTMLElement): void",
       "description": "Open the card anchored to `trigger` after `openDelay` (cancels a pending close)."
      },
      {
       "name": "scheduleClose",
       "signature": "(): void",
       "description": "Close the card after `closeDelay` (cancels a pending open)."
      },
      {
       "name": "keepOpen",
       "signature": "(): void",
       "description": "Keep the card open: cancel any pending open/close. Called when the pointer\nenters the card itself, so moving from the trigger to the card is seamless."
      },
      {
       "name": "open",
       "signature": "(trigger: HTMLElement): void",
       "description": "Open the card immediately, anchored to `trigger`."
      },
      {
       "name": "close",
       "signature": "(): void",
       "description": "Close the card immediately."
      }
     ],
     "properties": [
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id for `aria-controls` on the trigger.",
       "readonly": true
      },
      {
       "name": "opened",
       "type": "Signal<boolean>",
       "description": "Whether the hovercard is open.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/popovers"
    },
    {
     "name": "MkLoadingBar",
     "description": "LoadingBar — a thin progress bar fixed to the top of the viewport, driven by\n`MkLoadingBarService`. Place it once (e.g. in the app shell) and call\n`start()` / `complete()` on navigation or async work.\n\n```html\n<mk-loading-bar />\n```",
     "file": "projects/mk-kit/feedback/loading-bar/loading-bar.ts",
     "kind": "component",
     "selector": "mk-loading-bar",
     "selectors": [
      "mk-loading-bar"
     ],
     "inputs": [
      {
       "name": "color",
       "type": "string",
       "description": "Bar colour.",
       "default": "'var(--mk-primary)'"
      },
      {
       "name": "height",
       "type": "number",
       "description": "Bar thickness in px.",
       "default": "3"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/feedback"
    },
    {
     "name": "MkNotificationCenter",
     "description": "NotificationCenter — a bell trigger with an unread-count badge that opens a\ndropdown panel listing notifications, each markable as read.\n\nThe panel renders in the browser top layer through `MkAnchoredPanel`,\nso it is never clipped by an ancestor's `overflow`/`transform`. Clicking the\nbell toggles it; an outside click, Tabbing out or Escape closes it and\nrestores focus to the bell. Clicking a row marks that one read (updating the\ntwo-way `notifications` immutably); \"Mark all read\" clears every unread item.\n\n```html\n<mk-notification-center\n  [(notifications)]=\"items\"\n  (itemClick)=\"open($event)\"\n  (markedAllRead)=\"sync()\" />\n```",
     "file": "projects/mk-kit/feedback/notification-center/notification-center.ts",
     "kind": "component",
     "selector": "mk-notification-center",
     "selectors": [
      "mk-notification-center"
     ],
     "inputs": [
      {
       "name": "notifications",
       "type": "MkNotification[]",
       "description": "Two-way list of notifications rendered in the panel.",
       "model": true,
       "default": "[]"
      },
      {
       "name": "panelTitle",
       "type": "string",
       "description": "Heading shown at the top of the panel.",
       "default": "this.i18n.notificationsTitle"
      },
      {
       "name": "emptyText",
       "type": "string",
       "description": "Message shown by the empty state when there are no notifications.",
       "default": "this.i18n.allCaughtUp"
      },
      {
       "name": "maxHeight",
       "type": "string",
       "description": "Max height of the scrollable list (any CSS length).",
       "default": "'24rem'"
      }
     ],
     "outputs": [
      {
       "name": "notificationsChange",
       "type": "MkNotification[]",
       "description": "Emits when `notifications` changes (two-way binding).",
       "model": true
      },
      {
       "name": "itemClick",
       "type": "MkNotification",
       "description": "Emitted with a notification when its row is clicked."
      },
      {
       "name": "read",
       "type": "MkNotification",
       "description": "Emitted with a notification when it transitions to read."
      },
      {
       "name": "markedAllRead",
       "type": "void",
       "description": "Emitted when every notification is marked read at once."
      }
     ],
     "methods": [
      {
       "name": "toggle",
       "signature": "(): void",
       "description": "Toggle the panel open/closed."
      },
      {
       "name": "openPanel",
       "signature": "(): void",
       "description": "Open the panel, moving focus into it on the next render."
      },
      {
       "name": "close",
       "signature": "(restoreFocus?: boolean): void",
       "description": "Close the panel; optionally restore focus to the bell trigger."
      },
      {
       "name": "markAllRead",
       "signature": "(): void",
       "description": "Mark every notification read and emit `markedAllRead`."
      }
     ],
     "properties": [
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id linking the trigger to the panel via `aria-controls`.",
       "readonly": true
      },
      {
       "name": "titleId",
       "type": "string",
       "description": "Stable id for the panel's labelling heading.",
       "readonly": true
      },
      {
       "name": "open",
       "type": "Signal<boolean>",
       "description": "Whether the panel is open.",
       "readonly": true
      },
      {
       "name": "unreadCount",
       "type": "Signal<number>",
       "description": "Count of notifications that are not yet read.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/status"
    },
    {
     "name": "MkPopconfirm",
     "description": "Popconfirm — an inline confirmation popover (e.g. a row-level \"Delete?\").\nComposes `MkPopover` with a message and cancel/confirm buttons, so it\ninherits the top-layer positioning + focus behaviour. Attach it with the\n`mkPopconfirmFor` directive.\n\n```html\n<button mkButton tone=\"danger\" [mkPopconfirmFor]=\"del\">Delete</button>\n<mk-popconfirm #del message=\"Delete this item?\" (confirm)=\"remove()\" />\n```",
     "file": "projects/mk-kit/feedback/popover/popconfirm.ts",
     "kind": "component",
     "selector": "mk-popconfirm",
     "selectors": [
      "mk-popconfirm"
     ],
     "exportAs": "mkPopconfirm",
     "inputs": [
      {
       "name": "message",
       "type": "string",
       "description": "Confirmation message.",
       "default": "this.i18n.confirmMessage"
      },
      {
       "name": "title",
       "type": "string | undefined",
       "description": "Optional bold heading above the message."
      },
      {
       "name": "confirmText",
       "type": "string",
       "description": "Confirm button label.",
       "default": "this.i18n.confirm"
      },
      {
       "name": "cancelText",
       "type": "string",
       "description": "Cancel button label.",
       "default": "this.i18n.cancel"
      },
      {
       "name": "tone",
       "type": "MkTone",
       "description": "Tone of the confirm button (destructive actions use `danger`).",
       "default": "'danger'"
      },
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": "Preferred placement relative to the trigger.",
       "default": "'top'"
      }
     ],
     "outputs": [
      {
       "name": "confirm",
       "type": "void",
       "description": "Emitted when the user confirms."
      },
      {
       "name": "cancel",
       "type": "void",
       "description": "Emitted when the user cancels (button, Escape or outside click)."
      }
     ],
     "methods": [
      {
       "name": "opened",
       "signature": "(): boolean",
       "description": "Whether the popconfirm is open."
      },
      {
       "name": "open",
       "signature": "(trigger: HTMLElement): void",
       "description": "Open anchored to `trigger`."
      },
      {
       "name": "toggle",
       "signature": "(trigger: HTMLElement): void",
       "description": "Toggle from a trigger."
      },
      {
       "name": "close",
       "signature": "(): void",
       "description": "Close the popconfirm."
      }
     ],
     "properties": [
      {
       "name": "panelId",
       "type": "string | null",
       "description": "Id of the underlying dialog panel (for the trigger's `aria-controls`).",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/popovers"
    },
    {
     "name": "MkPopover",
     "description": "Popover — a non-modal floating panel for rich (non-text) content, anchored to\na trigger. Unlike `MkTooltip` (text, hover) it holds arbitrary projected\ncontent and is opened by click via the `mkPopoverTriggerFor` directive (or the\n`open`/`toggle` API).\n\nThe panel renders in the browser top layer through `MkAnchoredPanel`, so\nit is never clipped by an ancestor's `overflow`/`transform`. On open, focus\nmoves into the panel; Escape closes and restores focus to the trigger, an\noutside click or Tabbing out closes it (non-modal — no keyboard trap).\n\n```html\n<button mkButton [mkPopoverTriggerFor]=\"info\">Details</button>\n<mk-popover #info ariaLabel=\"Details\">\n  <h4>Shipping</h4><p>Ships in 2–3 business days.</p>\n</mk-popover>\n```",
     "file": "projects/mk-kit/feedback/popover/popover.ts",
     "kind": "component",
     "selector": "mk-popover",
     "selectors": [
      "mk-popover"
     ],
     "exportAs": "mkPopover",
     "inputs": [
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": "Preferred placement relative to the trigger.",
       "default": "'bottom'"
      },
      {
       "name": "ariaLabel",
       "type": "string | undefined",
       "description": "Accessible label for the dialog panel."
      },
      {
       "name": "autoFocus",
       "type": "boolean",
       "description": "Move focus into the panel on open. Default `true`.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "closed",
       "type": "void",
       "description": "Emitted whenever the popover closes (any reason)."
      }
     ],
     "methods": [
      {
       "name": "open",
       "signature": "(trigger: HTMLElement): void",
       "description": "Open the popover anchored to `trigger`."
      },
      {
       "name": "close",
       "signature": "(restoreFocus?: boolean): void",
       "description": "Close the popover; optionally restore focus to the trigger."
      },
      {
       "name": "toggle",
       "signature": "(trigger: HTMLElement): void",
       "description": "Toggle open/closed from a trigger."
      }
     ],
     "properties": [
      {
       "name": "panelId",
       "type": "string",
       "description": "Stable id for `aria-controls` on the trigger.",
       "readonly": true
      },
      {
       "name": "opened",
       "type": "Signal<boolean>",
       "description": "Whether the popover is open.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/popovers"
    },
    {
     "name": "MkResult",
     "description": "Result — a centred, full-page status state: a success confirmation, an error,\nan empty 404/403/500 page. Renders a large status icon (chosen from\n`status`), a title, a muted subtitle, projected body content, and a row of\naction buttons at the bottom.\n\nSlots: `[mkResultIcon]` (custom icon, overrides the built-in glyph),\n`[mkResultTitle]` (custom heading, used when `resultTitle` is unset), default\ncontent (extra body), `[mkResultActions]` (buttons).\n\n```html\n<mk-result status=\"success\" resultTitle=\"Payment complete\"\n  subtitle=\"Your order is on its way.\">\n  <button mkButton mkResultActions>Back home</button>\n</mk-result>\n```",
     "file": "projects/mk-kit/feedback/result/result.ts",
     "kind": "component",
     "selector": "mk-result",
     "selectors": [
      "mk-result"
     ],
     "inputs": [
      {
       "name": "status",
       "type": "MkResultStatus",
       "description": "Status preset that selects the built-in icon glyph and its tone colour.",
       "default": "'info'"
      },
      {
       "name": "resultTitle",
       "type": "string",
       "description": "Main heading rendered as an `<h2>` (falls back to the `[mkResultTitle]` slot).",
       "default": "''"
      },
      {
       "name": "subtitle",
       "type": "string",
       "description": "Supporting muted sentence under the title.",
       "default": "''"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/status"
    },
    {
     "name": "MkSnackbar",
     "description": "The visual snackbar bar. Internal to the snackbar system — rendered by\n`MkSnackbarContainer`. Shows a message, an optional action button and\n(when `dismissible`) a close button. Auto-dismiss pauses on hover/focus.",
     "file": "projects/mk-kit/feedback/snackbar/snackbar.ts",
     "kind": "component",
     "selector": "mk-snackbar",
     "selectors": [
      "mk-snackbar"
     ],
     "inputs": [
      {
       "name": "item",
       "type": "MkSnackbarItem",
       "description": "The snackbar model to render.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkSnackbarContainer",
     "description": "Fixed, bottom-centre host that renders the single active snackbar from\n`MkSnackbarService`. Mounted once, lazily, into `document.body` by the\nservice — not intended for direct template use.",
     "file": "projects/mk-kit/feedback/snackbar/snackbar-container.ts",
     "kind": "component",
     "selector": "mk-snackbar-container",
     "selectors": [
      "mk-snackbar-container"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkToast",
     "description": "A single toast card. Internal to the toast system — rendered by\n`MkToastContainer`. Displays a tone accent, optional title, message,\noptional action button, and (when dismissible) a close button. Auto-dismiss\npauses while the toast is hovered or focused.",
     "file": "projects/mk-kit/feedback/toast/toast.ts",
     "kind": "component",
     "selector": "mk-toast",
     "selectors": [
      "mk-toast"
     ],
     "inputs": [
      {
       "name": "item",
       "type": "MkToastItem",
       "description": "The toast model to render.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkToastContainer",
     "description": "Fixed, bottom-right stack that renders the active toasts from\n`MkToastService`. Mounted once, lazily, into `document.body` by the\nservice — not intended for direct template use.",
     "file": "projects/mk-kit/feedback/toast/toast-container.ts",
     "kind": "component",
     "selector": "mk-toast-container",
     "selectors": [
      "mk-toast-container"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkTooltipPanel",
     "description": "Body-level presentation surface for `MkTooltip`. Rendered imperatively\nby the directive; not intended for direct template use.",
     "file": "projects/mk-kit/feedback/tooltip/tooltip.ts",
     "kind": "component",
     "selector": "mk-tooltip",
     "selectors": [
      "mk-tooltip"
     ],
     "inputs": [
      {
       "name": "text",
       "type": "string",
       "description": "Text content shown inside the tooltip.",
       "default": "''"
      },
      {
       "name": "id",
       "type": "string | undefined",
       "description": "DOM id used to wire `aria-describedby` on the trigger."
      },
      {
       "name": "placement",
       "type": "MkPlacement",
       "description": "Resolved placement relative to the trigger.",
       "default": "'top'"
      },
      {
       "name": "visible",
       "type": "boolean",
       "description": "Drives the entrance/exit transition.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkTourPopup",
     "description": "The floating coach-mark popover for one tour step. Rendered dynamically by\n`MkTourService` (one instance per step) and anchored to the step's\ntarget through `MkAnchoredPanel`, so it lives in the browser top layer\nand is never clipped by an ancestor's `overflow`/`transform`.",
     "file": "projects/mk-kit/feedback/tour/tour-popup.ts",
     "kind": "component",
     "selector": "mk-tour-popup",
     "selectors": [
      "mk-tour-popup"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkBlockUi",
     "description": "Block UI — cover the host element with a translucent panel and spinner\nwhile something loads, so its contents can neither be read nor operated:\na card refreshing, a form submitting, a table re-fetching.\n\nChildren get `inert` (no clicks, no Tab stops) and the host `aria-busy`.\n`mkBlockUiDelay` (ms) holds the overlay back for quick operations so the\nscreen does not flash.\n\n```html\n<mk-card [mkBlockUi]=\"saving()\" mkBlockUiMessage=\"Saving…\">…</mk-card>\n<form [mkBlockUi]=\"submitting()\" [mkBlockUiDelay]=\"300\">…</form>\n```",
     "file": "projects/mk-kit/feedback/block-ui/block-ui.ts",
     "kind": "directive",
     "selector": "[mkBlockUi]",
     "selectors": [
      "mkBlockUi"
     ],
     "inputs": [
      {
       "name": "mkBlockUi",
       "type": "boolean",
       "description": "Block while `true`.",
       "default": "false"
      },
      {
       "name": "mkBlockUiMessage",
       "type": "string",
       "description": "Text under the spinner (also its accessible label).",
       "default": "''"
      },
      {
       "name": "mkBlockUiDelay",
       "type": "number",
       "description": "Wait this many ms before showing, to avoid a flash on fast operations.",
       "default": "0"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/loading"
    },
    {
     "name": "MkHovercardTrigger",
     "description": "Turns its host element into a hover/focus trigger for an `<mk-hovercard>`.\nOn `mouseenter`/`focus` it opens the card (after the card's `openDelay`),\nanchored to the host; on `mouseleave`/`blur` it schedules a close (after the\ncard's `closeDelay`). Moving the pointer — or keyboard focus — from the host\nonto the card cancels that close, so the card stays open and its content is\nreachable with Tab. Escape closes it.\n\nOn touch there is no hover, so a tap toggles instead: tap opens the card\nimmediately, tapping the trigger again closes it, and a tap anywhere else\ncloses it through the panel's outside-pointerdown dismissal.\n\n```html\n<a href=\"/u/ada\" [mkHovercardFor]=\"ada\">@ada</a>\n<mk-hovercard #ada>…</mk-hovercard>\n```",
     "file": "projects/mk-kit/feedback/hovercard/hovercard-trigger.ts",
     "kind": "directive",
     "selector": "[mkHovercardFor]",
     "selectors": [
      "mkHovercardFor"
     ],
     "exportAs": "mkHovercardTrigger",
     "inputs": [
      {
       "name": "mkHovercardFor",
       "type": "MkHovercard",
       "description": "The hovercard instance to control.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/popovers"
    },
    {
     "name": "MkPopconfirmTrigger",
     "description": "Turns its host element into a click trigger for an `<mk-popconfirm>`. Wires\n`aria-haspopup=\"dialog\"` / `aria-expanded` / `aria-controls`, toggles on click\nand closes on Escape.\n\n```html\n<button mkButton tone=\"danger\" [mkPopconfirmFor]=\"del\">Delete</button>\n<mk-popconfirm #del message=\"Delete this item?\" (confirm)=\"remove()\" />\n```",
     "file": "projects/mk-kit/feedback/popover/popconfirm-trigger.ts",
     "kind": "directive",
     "selector": "[mkPopconfirmFor]",
     "selectors": [
      "mkPopconfirmFor"
     ],
     "exportAs": "mkPopconfirmTrigger",
     "inputs": [
      {
       "name": "mkPopconfirmFor",
       "type": "MkPopconfirm",
       "description": "The popconfirm instance to control.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/popovers"
    },
    {
     "name": "MkPopoverTrigger",
     "description": "Turns its host element into a click trigger for an `<mk-popover>`. Wires\n`aria-haspopup=\"dialog\"` / `aria-expanded` / `aria-controls`, toggles on click\nand closes on Escape.\n\n```html\n<button mkButton [mkPopoverTriggerFor]=\"info\">Details</button>\n<mk-popover #info>…</mk-popover>\n```",
     "file": "projects/mk-kit/feedback/popover/popover-trigger.ts",
     "kind": "directive",
     "selector": "[mkPopoverTriggerFor]",
     "selectors": [
      "mkPopoverTriggerFor"
     ],
     "exportAs": "mkPopoverTrigger",
     "inputs": [
      {
       "name": "mkPopoverTriggerFor",
       "type": "MkPopover",
       "description": "The popover instance to control.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/popovers"
    },
    {
     "name": "MkTooltip",
     "description": "Tooltip directive — shows a themed tooltip on hover AND keyboard focus, and\nhides on blur, mouse-leave (after a short grace period — the pointer may\nmove onto the tooltip itself, which keeps it open, per WCAG 1.4.13), or\nEscape pressed anywhere while it is visible. The tooltip is appended to\n`document.body`, positioned relative to the host, and wired to the host via\n`aria-describedby` for screen-reader users. Respects `prefers-reduced-motion`.\n\n```html\n<button mkButton [mkTooltip]=\"'Delete row'\" mkTooltipPlacement=\"bottom\">\n  <svg>…</svg>\n</button>\n```",
     "file": "projects/mk-kit/feedback/tooltip/tooltip.ts",
     "kind": "directive",
     "selector": "[mkTooltip]",
     "selectors": [
      "mkTooltip"
     ],
     "inputs": [
      {
       "name": "mkTooltip",
       "type": "string",
       "description": "Tooltip text. When empty the tooltip is suppressed.",
       "default": "''"
      },
      {
       "name": "mkTooltipPlacement",
       "type": "MkPlacement",
       "description": "Preferred placement relative to the host.",
       "default": "'top'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/popovers"
    },
    {
     "name": "MkBlockUiService",
     "description": "Block the whole page. Reference-counted: every `block()` returns a release\nfunction, and the overlay disappears once all of them have been called.\n\n```ts\nconst release = this.blockUi.block('Exporting…');\ntry { await this.api.export(); } finally { release(); }\n```",
     "file": "projects/mk-kit/feedback/block-ui/block-ui.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "block",
       "signature": "(message?: string): () => void",
       "description": "Show the page overlay (or update its message); call the returned function to release."
      },
      {
       "name": "isBlocked",
       "signature": "(): boolean",
       "description": "True while the page is blocked."
      }
     ],
     "properties": [
      {
       "name": "count",
       "type": "Signal<number>",
       "description": "Number of active blocks.",
       "readonly": true
      }
     ],
     "docs": "/components/loading"
    },
    {
     "name": "MkBottomSheetService",
     "description": "BottomSheet service — a thin layer over `MkOverlayService` that renders\na component in a panel anchored to the bottom edge of the viewport: full\nwidth on small screens, a centred card capped at ~42rem on large ones. It\nslides up on open and can be swiped down to dismiss (via `MkBottomSheet`).\n\nUse it for contextual actions, pickers and mobile-style menus. For a centred\nmodal use `MkDialogService` instead.\n\n```ts\nconst ref = bottomSheet.open(ShareSheet, { data: { url } });\nconst choice = await ref.afterClosed;\n```",
     "file": "projects/mk-kit/feedback/bottom-sheet/bottom-sheet.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "open",
       "signature": "<TComponent, TResult = unknown, TData = unknown>(component: Type<TComponent>, config?: MkBottomSheetConfig<TData>): MkOverlayRef<TResult, TComponent>",
       "description": "Open `component` inside a bottom-anchored sheet panel."
      }
     ],
     "properties": [],
     "docs": "/components/bottom-sheet"
    },
    {
     "name": "MkDialogService",
     "description": "Dialog service — a thin, opinionated layer over `MkOverlayService` that\nrenders content on a themed `--mk-surface` panel (shadow, radius, entrance\nanimation) and adds a `confirm()` convenience.\n\n```ts\nconst ref = dialog.open(EditUserDialog, { data: user });\nconst saved = await ref.afterClosed;\n\nif (await dialog.confirm({ title: 'Delete?', message: 'This cannot be undone.', tone: 'danger' })) {\n  remove();\n}\n```",
     "file": "projects/mk-kit/feedback/dialog/dialog.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "open",
       "signature": "<TComponent, TResult = unknown, TData = unknown>(component: Type<TComponent>, config?: MkDialogConfig<TData>): MkOverlayRef<TResult, TComponent>",
       "description": "Open `component` inside a themed dialog panel."
      },
      {
       "name": "confirm",
       "signature": "(data: MkConfirmDialogData): Promise<boolean>",
       "description": "Open a confirmation dialog. Resolves `true` if confirmed, `false` if the\nuser cancels, presses Escape, or clicks the backdrop."
      },
      {
       "name": "alert",
       "signature": "(data: Omit<MkConfirmDialogData, \"hideCancel\" | \"cancelText\">): Promise<void>",
       "description": "Open a single-button acknowledgement dialog. Resolves when the user\ndismisses it (button, Escape, or backdrop)."
      },
      {
       "name": "prompt",
       "signature": "(data: MkPromptDialogData): Promise<string | null>",
       "description": "Open a single-field prompt dialog. Resolves with the entered string, or\n`null` if the user cancels, presses Escape, or clicks the backdrop."
      }
     ],
     "properties": [],
     "docs": "/components/dialogs"
    },
    {
     "name": "MkLoadingBarService",
     "description": "Drives a global `MkLoadingBar` — the thin top-of-page progress bar for\nroute changes and background work. `start()` shows it and trickles toward 90%;\n`complete()` finishes and hides it. Also supports a determinate `set(value)`.\n\n```ts\nconst bar = inject(MkLoadingBarService);\nrouter.events.subscribe(e => {\n  if (e instanceof NavigationStart) bar.start();\n  if (e instanceof NavigationEnd) bar.complete();\n});\n```",
     "file": "projects/mk-kit/feedback/loading-bar/loading-bar.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "start",
       "signature": "(): void",
       "description": "Show the bar and start trickling toward 90%."
      },
      {
       "name": "set",
       "signature": "(value: number): void",
       "description": "Set an explicit determinate value (0–100)."
      },
      {
       "name": "inc",
       "signature": "(amount?: number): void",
       "description": "Nudge progress up by `amount` (default 5), capped at 90%."
      },
      {
       "name": "complete",
       "signature": "(): void",
       "description": "Finish (jump to 100%) then fade out."
      },
      {
       "name": "stop",
       "signature": "(): void",
       "description": "Hide immediately without finishing."
      }
     ],
     "properties": [
      {
       "name": "progress",
       "type": "Signal<number>",
       "description": "Current progress, 0–100.",
       "readonly": true
      },
      {
       "name": "active",
       "type": "Signal<boolean>",
       "description": "Whether the bar is visible.",
       "readonly": true
      },
      {
       "name": "finishing",
       "type": "Signal<boolean>",
       "description": "True while finishing (progress full but not yet hidden).",
       "readonly": true
      }
     ],
     "docs": "/components/feedback"
    },
    {
     "name": "MkSnackbarService",
     "description": "Snackbar service — shows a single, brief message at the bottom-centre of the\nviewport with an optional action button, following the Material snackbar\nmodel: only one is visible at a time, and opening a new one replaces the\ncurrent. For stacked, persistent notifications use `MkToastService` instead.\n\n```ts\nconst ref = snackbar.open('Message archived', 'Undo');\nref.onAction().then(() => restore());\n\nsnackbar.open('Changes saved', undefined, { tone: 'success' });\n```",
     "file": "projects/mk-kit/feedback/snackbar/snackbar.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "open",
       "signature": "(message: string, action?: string, config?: MkSnackbarConfig): MkSnackbarRef",
       "description": "Open a snackbar. `action` is the (optional) button label — react to it via\nthe returned ref's `MkSnackbarRef.onAction`."
      },
      {
       "name": "dismiss",
       "signature": "(id: number): void",
       "description": "Dismiss the snackbar with the given id (if it is the active one)."
      },
      {
       "name": "runAction",
       "signature": "(id: number): void",
       "description": "Run the action for the active snackbar, then close it."
      },
      {
       "name": "pause",
       "signature": "(): void",
       "description": "Pause the auto-dismiss countdown (e.g. on hover/focus)."
      },
      {
       "name": "resume",
       "signature": "(): void",
       "description": "Resume a paused countdown."
      }
     ],
     "properties": [
      {
       "name": "active",
       "type": "Signal<MkSnackbarItem | null>",
       "description": "The currently visible snackbar, or `null`.",
       "readonly": true
      }
     ],
     "docs": "/components/snackbar"
    },
    {
     "name": "MkToastService",
     "description": "Toast service — enqueues transient notifications rendered by a single,\nlazily-mounted `MkToastContainer` at the bottom-right of the viewport.\nEach rendered toast is itself a live region (`role=\"alert\"` for `danger`,\nelse `role=\"status\"`), so assistive tech announces it exactly once. Toasts\nauto-dismiss after `duration` ms unless it is `0`.\n\n```ts\ntoasts.success('Saved');\ntoasts.show({ title: 'Upload failed', message: 'Retry?', tone: 'danger',\n  duration: 0, action: { label: 'Retry', handler: () => retry() } });\n```",
     "file": "projects/mk-kit/feedback/toast/toast.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "show",
       "signature": "(config: MkToastConfig): number",
       "description": "Show a toast, returning its id (usable with `dismiss`)."
      },
      {
       "name": "info",
       "signature": "(message: string, config?: Partial<MkToastConfig>): number",
       "description": "Show an `info` toast."
      },
      {
       "name": "success",
       "signature": "(message: string, config?: Partial<MkToastConfig>): number",
       "description": "Show a `success` toast."
      },
      {
       "name": "warning",
       "signature": "(message: string, config?: Partial<MkToastConfig>): number",
       "description": "Show a `warning` toast."
      },
      {
       "name": "danger",
       "signature": "(message: string, config?: Partial<MkToastConfig>): number",
       "description": "Show a `danger` toast."
      },
      {
       "name": "neutral",
       "signature": "(message: string, config?: Partial<MkToastConfig>): number",
       "description": "Show a `neutral` toast."
      },
      {
       "name": "dismiss",
       "signature": "(id: number): void",
       "description": "Dismiss a toast by id."
      },
      {
       "name": "clear",
       "signature": "(): void",
       "description": "Dismiss every visible toast."
      },
      {
       "name": "runAction",
       "signature": "(item: MkToastItem): void",
       "description": "Run a toast action, then dismiss it."
      },
      {
       "name": "pause",
       "signature": "(id: number): void",
       "description": "Pause a toast's auto-dismiss countdown (e.g. on hover/focus)."
      },
      {
       "name": "resume",
       "signature": "(id: number): void",
       "description": "Resume a paused countdown."
      }
     ],
     "properties": [
      {
       "name": "toasts",
       "type": "Signal<readonly MkToastItem[]>",
       "description": "Reactive list of currently visible toasts.",
       "readonly": true
      }
     ],
     "docs": "/components/snackbar"
    },
    {
     "name": "MkTourService",
     "description": "Product-onboarding tour service — walks the user through a sequence of\n`MkTourStep`s. For each step it scrolls the target into view, dims the\npage behind a scrim, highlights the target with a bright ring, and anchors a\ncoach-mark popover (`MkTourPopup`) to it in the browser top layer via\n`MkAnchoredPanel`.\n\n```ts\nconst tour = inject(MkTourService);\nawait tour.start([\n  { target: '#new-btn', title: 'Create', body: 'Start a project here.' },\n  { target: '#inbox', body: 'Your notifications land here.', placement: 'left' },\n]);\n```",
     "file": "projects/mk-kit/feedback/tour/tour.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "start",
       "signature": "(steps: MkTourStep[]): Promise<void>",
       "description": "Begin a tour at step 0. Returns a promise that resolves when the tour ends\n(finished, skipped, or Escaped)."
      },
      {
       "name": "afterEnd",
       "signature": "(): Promise<void>",
       "description": "Resolves when the active (or next) tour ends."
      },
      {
       "name": "next",
       "signature": "(): void",
       "description": "Advance to the next step, or finish on the last step."
      },
      {
       "name": "prev",
       "signature": "(): void",
       "description": "Return to the previous step (no-op at the first step)."
      },
      {
       "name": "end",
       "signature": "(): void",
       "description": "End the tour and clean up all DOM, highlight, and listeners."
      }
     ],
     "properties": [
      {
       "name": "index",
       "type": "Signal<number>",
       "description": "Zero-based index of the current step, or `-1` when no tour is running.",
       "readonly": true
      },
      {
       "name": "running",
       "type": "Signal<boolean>",
       "description": "Whether a tour is currently active.",
       "readonly": true
      },
      {
       "name": "total",
       "type": "Signal<number>",
       "description": "Total number of steps in the active tour.",
       "readonly": true
      },
      {
       "name": "currentStep",
       "type": "Signal<MkTourStep | null>",
       "description": "The current step, or `null`.",
       "readonly": true
      }
     ],
     "docs": "/components/status"
    },
    {
     "name": "MkSnackbarRef",
     "description": "Handle to an opened snackbar. Await `onAction` to react to the action\nbutton, or `afterDismissed` to run code once it closes.",
     "file": "projects/mk-kit/feedback/snackbar/snackbar.service.ts",
     "kind": "class",
     "methods": [
      {
       "name": "dismiss",
       "signature": "(): void",
       "description": "Dismiss the snackbar programmatically."
      },
      {
       "name": "onAction",
       "signature": "(): Promise<void>",
       "description": "Resolves when the action button is activated."
      },
      {
       "name": "afterDismissed",
       "signature": "(): Promise<MkSnackbarDismissReason>",
       "description": "Resolves when the snackbar has closed, with the reason it closed."
      }
     ],
     "properties": []
    },
    {
     "name": "MK_TOUR_DATA",
     "description": "DI token carrying the current `MkTourData` to the popup.",
     "file": "projects/mk-kit/feedback/tour/tour-popup.ts",
     "kind": "token",
     "type": "InjectionToken<MkTourData>"
    },
    {
     "name": "MkBottomSheetConfig",
     "description": "Configuration for `MkBottomSheetService.open`. Extends the overlay config.",
     "file": "projects/mk-kit/feedback/bottom-sheet/bottom-sheet.service.ts",
     "kind": "interface",
     "typeParams": "<TData = unknown>",
     "extends": [
      "MkOverlayConfig<TData>"
     ],
     "members": []
    },
    {
     "name": "MkConfirmDialogData",
     "description": "Data contract for `MkConfirmDialog` / `MkDialogService.confirm`.",
     "file": "projects/mk-kit/feedback/dialog/confirm-dialog.ts",
     "kind": "interface",
     "members": [
      {
       "name": "title",
       "type": "string",
       "description": "Heading text."
      },
      {
       "name": "message",
       "type": "string",
       "description": "Body message."
      },
      {
       "name": "confirmText",
       "type": "string | undefined",
       "description": "Confirm button label. Default `Confirm`.",
       "optional": true
      },
      {
       "name": "cancelText",
       "type": "string | undefined",
       "description": "Cancel button label. Default `Cancel`.",
       "optional": true
      },
      {
       "name": "tone",
       "type": "\"primary\" | \"success\" | \"warning\" | \"danger\" | undefined",
       "description": "Tone of the confirm button (and `alertdialog` semantics when `danger`).",
       "optional": true
      },
      {
       "name": "icon",
       "type": "string | undefined",
       "description": "Optional registered icon name shown beside the message. Useful when the\naction is destructive and the wording alone carries no visual weight\n(`trash`, `alert-triangle`, `user-x`).",
       "optional": true
      },
      {
       "name": "hideCancel",
       "type": "boolean | undefined",
       "description": "Hide the cancel button — a single-button acknowledgement (`alert`).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDialogConfig",
     "description": "Configuration for `MkDialogService.open`. Extends the raw overlay config.",
     "file": "projects/mk-kit/feedback/dialog/dialog.service.ts",
     "kind": "interface",
     "typeParams": "<TData = unknown>",
     "extends": [
      "MkOverlayConfig<TData>"
     ],
     "members": [
      {
       "name": "size",
       "type": "MkDialogSize | undefined",
       "description": "Panel width preset. Defaults to `sm`, matching pre-0.9 behaviour.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkNotification",
     "description": "A single notification shown in the `MkNotificationCenter` panel.",
     "file": "projects/mk-kit/feedback/notification-center/notification-center.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "unknown",
       "description": "Stable identity, used for `track` and immutable updates."
      },
      {
       "name": "title",
       "type": "string",
       "description": "Headline line, always shown."
      },
      {
       "name": "body",
       "type": "string | undefined",
       "description": "Optional supporting text under the title.",
       "optional": true
      },
      {
       "name": "time",
       "type": "string | undefined",
       "description": "Optional relative/absolute timestamp label (e.g. \"2m ago\").",
       "optional": true
      },
      {
       "name": "read",
       "type": "boolean | undefined",
       "description": "Whether the user has already read this item.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkPromptDialogData",
     "description": "Data contract for `MkPromptDialog` / `MkDialogService.prompt`.",
     "file": "projects/mk-kit/feedback/dialog/prompt-dialog.ts",
     "kind": "interface",
     "members": [
      {
       "name": "title",
       "type": "string",
       "description": "Heading text."
      },
      {
       "name": "message",
       "type": "string | undefined",
       "description": "Optional body message shown above the input.",
       "optional": true
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "Field label.",
       "optional": true
      },
      {
       "name": "value",
       "type": "string | undefined",
       "description": "Pre-filled value.",
       "optional": true
      },
      {
       "name": "placeholder",
       "type": "string | undefined",
       "description": "Input placeholder.",
       "optional": true
      },
      {
       "name": "confirmText",
       "type": "string | undefined",
       "description": "Confirm button label. Default `OK`.",
       "optional": true
      },
      {
       "name": "cancelText",
       "type": "string | undefined",
       "description": "Cancel button label. Default `Cancel`.",
       "optional": true
      },
      {
       "name": "required",
       "type": "boolean | undefined",
       "description": "Require a non-empty value before the confirm button enables.",
       "optional": true
      },
      {
       "name": "inputType",
       "type": "string | undefined",
       "description": "Native input type (e.g. `text`, `email`, `number`, `password`).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkSnackbarConfig",
     "description": "Options for `MkSnackbarService.open`.",
     "file": "projects/mk-kit/feedback/snackbar/snackbar.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "tone",
       "type": "MkSnackbarTone | undefined",
       "description": "Semantic tone. Default `neutral`.",
       "optional": true
      },
      {
       "name": "duration",
       "type": "number | undefined",
       "description": "Auto-dismiss delay in ms. `0` keeps it open until dismissed. Default `5000`.",
       "optional": true
      },
      {
       "name": "dismissible",
       "type": "boolean | undefined",
       "description": "Show a close (×) button. Default `false` (dismiss via action/timeout).",
       "optional": true
      },
      {
       "name": "politeness",
       "type": "\"polite\" | \"assertive\" | undefined",
       "description": "",
       "deprecated": "The snackbar element is itself the live region — its\npoliteness is derived from `tone` (`alert` for danger/warning, else\n`status`). This option is ignored.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkSnackbarItem",
     "description": "The live snackbar model rendered by the container.",
     "file": "projects/mk-kit/feedback/snackbar/snackbar.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "number",
       "description": "",
       "readonly": true
      },
      {
       "name": "message",
       "type": "string",
       "description": "",
       "readonly": true
      },
      {
       "name": "actionLabel",
       "type": "string | undefined",
       "description": "",
       "optional": true,
       "readonly": true
      },
      {
       "name": "tone",
       "type": "MkSnackbarTone",
       "description": "",
       "readonly": true
      },
      {
       "name": "dismissible",
       "type": "boolean",
       "description": "",
       "readonly": true
      }
     ]
    },
    {
     "name": "MkToastAction",
     "description": "An optional action button rendered inside a toast.",
     "file": "projects/mk-kit/feedback/toast/toast.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": "Button label."
      },
      {
       "name": "handler",
       "type": "(() => void) | undefined",
       "description": "Invoked when the action is activated. The toast is dismissed afterwards.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkToastConfig",
     "description": "Options accepted by `MkToastService.show`.",
     "file": "projects/mk-kit/feedback/toast/toast.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "title",
       "type": "string | undefined",
       "description": "Optional bold heading.",
       "optional": true
      },
      {
       "name": "message",
       "type": "string",
       "description": "Body message (required)."
      },
      {
       "name": "tone",
       "type": "MkToastTone | undefined",
       "description": "Semantic tone. Default `info`.",
       "optional": true
      },
      {
       "name": "duration",
       "type": "number | undefined",
       "description": "Auto-dismiss delay in ms. `0` keeps the toast until dismissed. Default `5000`.",
       "optional": true
      },
      {
       "name": "dismissible",
       "type": "boolean | undefined",
       "description": "Show a close button. Default `true`.",
       "optional": true
      },
      {
       "name": "action",
       "type": "MkToastAction | undefined",
       "description": "Optional action button.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkToastItem",
     "description": "A live toast rendered by the container.",
     "file": "projects/mk-kit/feedback/toast/toast.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "number",
       "description": "",
       "readonly": true
      },
      {
       "name": "title",
       "type": "string | undefined",
       "description": "",
       "optional": true,
       "readonly": true
      },
      {
       "name": "message",
       "type": "string",
       "description": "",
       "readonly": true
      },
      {
       "name": "tone",
       "type": "MkToastTone",
       "description": "",
       "readonly": true
      },
      {
       "name": "duration",
       "type": "number",
       "description": "",
       "readonly": true
      },
      {
       "name": "dismissible",
       "type": "boolean",
       "description": "",
       "readonly": true
      },
      {
       "name": "action",
       "type": "MkToastAction | undefined",
       "description": "",
       "optional": true,
       "readonly": true
      }
     ]
    },
    {
     "name": "MkTourController",
     "description": "Navigation callbacks the popup invokes on the owning `MkTourService`.",
     "file": "projects/mk-kit/feedback/tour/tour-popup.ts",
     "kind": "interface",
     "members": [
      {
       "name": "next",
       "type": "(): void",
       "description": ""
      },
      {
       "name": "prev",
       "type": "(): void",
       "description": ""
      },
      {
       "name": "end",
       "type": "(): void",
       "description": ""
      }
     ]
    },
    {
     "name": "MkTourData",
     "description": "Per-step data injected into `MkTourPopup` via `MK_TOUR_DATA`.",
     "file": "projects/mk-kit/feedback/tour/tour-popup.ts",
     "kind": "interface",
     "members": [
      {
       "name": "step",
       "type": "MkTourStep",
       "description": "The step being shown."
      },
      {
       "name": "index",
       "type": "number",
       "description": "Zero-based index of this step."
      },
      {
       "name": "total",
       "type": "number",
       "description": "Total number of steps in the tour."
      },
      {
       "name": "anchor",
       "type": "HTMLElement",
       "description": "The resolved target element to anchor against."
      },
      {
       "name": "controller",
       "type": "MkTourController",
       "description": "Navigation handle back to the service."
      }
     ]
    },
    {
     "name": "MkTourStep",
     "description": "A single coach-mark step in a product tour. The `target` is the element the\nstep points at — either a live `HTMLElement` or a CSS selector resolved\nagainst the document when the step is shown.",
     "file": "projects/mk-kit/feedback/tour/tour-popup.ts",
     "kind": "interface",
     "members": [
      {
       "name": "target",
       "type": "string | HTMLElement",
       "description": "Element (or selector) the popover anchors to and highlights."
      },
      {
       "name": "title",
       "type": "string | undefined",
       "description": "Optional heading shown above the body.",
       "optional": true
      },
      {
       "name": "body",
       "type": "string",
       "description": "The explanatory copy for this step."
      },
      {
       "name": "placement",
       "type": "MkPlacement | undefined",
       "description": "Preferred placement of the popover relative to the target.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkAlertTone",
     "description": "Semantic tones supported by `MkAlert`.",
     "file": "projects/mk-kit/feedback/alert/alert.ts",
     "kind": "type",
     "definition": "'info' | 'success' | 'warning' | 'danger' | 'neutral'"
    },
    {
     "name": "MkAlertVariant",
     "description": "Visual treatments supported by `MkAlert`.",
     "file": "projects/mk-kit/feedback/alert/alert.ts",
     "kind": "type",
     "definition": "'soft' | 'solid' | 'outline'"
    },
    {
     "name": "MkDialogSize",
     "description": "Panel width preset. The panel is always `min(target, 92vw)`, so it shrinks to\nfit a phone and grows to its target on a desktop.\n\n- `sm` (32rem) — the default; confirmations, single-field prompts\n- `md` (45rem) — two-column forms\n- `lg` (56rem) — forms with nested sections\n- `xl` (75rem) — tables or side-by-side content inside a modal",
     "file": "projects/mk-kit/feedback/dialog/dialog.service.ts",
     "kind": "type",
     "definition": "'sm' | 'md' | 'lg' | 'xl'"
    },
    {
     "name": "MkResultIconVariant",
     "description": "Built-in icon glyph chosen for a status.",
     "file": "projects/mk-kit/feedback/result/result.ts",
     "kind": "type",
     "definition": "'check' | 'x' | 'alert' | 'info' | 'search'"
    },
    {
     "name": "MkResultStatus",
     "description": "Status presets supported by `MkResult`.",
     "file": "projects/mk-kit/feedback/result/result.ts",
     "kind": "type",
     "definition": "| 'success' | 'error' | 'info' | 'warning' | '404' | '403' | '500'"
    },
    {
     "name": "MkResultTone",
     "description": "Tone colour applied to the status icon.",
     "file": "projects/mk-kit/feedback/result/result.ts",
     "kind": "type",
     "definition": "'success' | 'danger' | 'warning' | 'info' | 'muted'"
    },
    {
     "name": "MkSnackbarDismissReason",
     "description": "Why a snackbar closed.",
     "file": "projects/mk-kit/feedback/snackbar/snackbar.service.ts",
     "kind": "type",
     "definition": "'action' | 'timeout' | 'dismiss'"
    },
    {
     "name": "MkSnackbarTone",
     "description": "Semantic tone of a snackbar. `neutral` is the default dark bar.",
     "file": "projects/mk-kit/feedback/snackbar/snackbar.service.ts",
     "kind": "type",
     "definition": "| 'neutral' | 'info' | 'success' | 'warning' | 'danger'"
    },
    {
     "name": "MkToastTone",
     "description": "Semantic tones supported by toasts.",
     "file": "projects/mk-kit/feedback/toast/toast.service.ts",
     "kind": "type",
     "definition": "'info' | 'success' | 'warning' | 'danger' | 'neutral'"
    }
   ]
  },
  {
   "name": "rich-text",
   "import": "@mk-kit/ui/rich-text",
   "exports": [
    {
     "name": "MkRichText",
     "description": "Rich text — a small WYSIWYG form control over a sanitised HTML string, for\nsingle \"description\"-style fields where the full block editor is overkill.\nRenders a textarea-like surface with the floating inline formatting toolbar\n(Bold, Italic, Underline, Strikethrough, Inline code, Link, Clear) on text\nselection; Enter inserts a line break.\n\nImplements `ControlValueAccessor` with a two-way `value` model, so it works\nwith `[(ngModel)]`, reactive forms and `[(value)]`. Every value — written or\nemitted — passes through `sanitizeInlineHtml`, and a visually empty\nsurface (whitespace / lone `<br>`s) normalises to `''` so `required`\nvalidation behaves.\n\n```html\n<mk-rich-text [(ngModel)]=\"description\" placeholder=\"Describe it…\" />\n<mk-rich-text [(value)]=\"html\" minHeight=\"8rem\" />\n```",
     "file": "projects/mk-kit/rich-text/rich-text.ts",
     "kind": "component",
     "selector": "mk-rich-text",
     "selectors": [
      "mk-rich-text"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "string",
       "description": "Two-way HTML string value (sanitised; `''` when visually empty).",
       "model": true,
       "default": "''"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the control.",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "minHeight",
       "type": "string",
       "description": "Minimum height of the editable area (any CSS length).",
       "default": "'4.5em'"
      },
      {
       "name": "aria-label",
       "type": "string",
       "description": "Accessible label when not labelled by an `mk-form-field`.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/rich-text"
    },
    {
     "name": "MkRichTextEngine",
     "description": "Rich-text engine — an accessible contenteditable surface with a floating\ninline formatting toolbar (Bold, Italic, Underline, Strikethrough, Inline\ncode, Link, Clear). Built on the native Selection API +\n`document.execCommand` (deprecated but universally supported and\ndependency-free — the only practical way to do inline formatting without a\nheavyweight editor engine).\n\nThis is the low-level building block: it emits HTML via `contentChange`, and\nstructural intents (`splitAt`, `removeEmpty`, `arrowOut`) so a block-editor\nhost can create, merge or navigate blocks. For a standalone form control use\n`MkRichText` (`<mk-rich-text>`), which wraps this engine in a CVA over\na sanitised HTML string.",
     "file": "projects/mk-kit/rich-text/rich-text-engine.ts",
     "kind": "component",
     "selector": "mk-rich-text-engine",
     "selectors": [
      "mk-rich-text-engine"
     ],
     "inputs": [
      {
       "name": "html",
       "type": "string",
       "description": "Current HTML content.",
       "default": "''"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder shown when empty.",
       "default": "''"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable editing.",
       "default": "false"
      },
      {
       "name": "multiline",
       "type": "boolean",
       "description": "Allow soft line breaks (Shift+Enter). Plain Enter always splits.",
       "default": "true"
      },
      {
       "name": "splitOnEnter",
       "type": "boolean",
       "description": "Emit `splitAt` on Enter (block-editor hosts). When `false` — standalone\nfield usage — Enter inserts a line break inside this surface instead.",
       "default": "true"
      },
      {
       "name": "minHeight",
       "type": "string | null",
       "description": "Minimum height of the editable surface (any CSS length).",
       "default": "null"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the editable region.",
       "default": "this.i18n.blockEditor.editableText"
      },
      {
       "name": "labelledBy",
       "type": "string | null",
       "description": "Id of an external label element, for `aria-labelledby`.",
       "default": "null"
      },
      {
       "name": "describedBy",
       "type": "string | null",
       "description": "Space-separated id list for `aria-describedby`.",
       "default": "null"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Reflect an invalid state via `aria-invalid`.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "contentChange",
       "type": "string",
       "description": "Fired on every edit with the sanitised-by-construction HTML."
      },
      {
       "name": "splitAt",
       "type": "MkRichTextSplit",
       "description": "Enter pressed: `before` stays in this block, `after` starts a new one."
      },
      {
       "name": "removeEmpty",
       "type": "void",
       "description": "Backspace at the very start of an empty block."
      },
      {
       "name": "arrowOut",
       "type": "\"up\" | \"down\"",
       "description": "Caret tried to leave the top/bottom edge with an arrow key."
      },
      {
       "name": "focusChange",
       "type": "boolean",
       "description": "Focus/blur bubbled so the wrapper can show selection chrome."
      }
     ],
     "methods": [
      {
       "name": "focus",
       "signature": "(position?: \"start\" | \"end\"): void",
       "description": "Places the caret and focuses (called by the host for navigation)."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/rich-text"
    },
    {
     "name": "sanitizeInlineHtml",
     "description": "Allow-list cleaner for inline rich text. Keeps a small set of formatting\ntags, strips everything else's tags (preserving their text), removes event\nhandler attributes and unsafe `href`s. Not a substitute for `DomSanitizer`,\nbut makes the serialised string safe by construction.",
     "file": "projects/mk-kit/rich-text/sanitize.ts",
     "kind": "function",
     "signatures": [
      "(html: string): string"
     ]
    },
    {
     "name": "MkRichTextSplit",
     "description": "Payload for a split (Enter) event: text before/after the caret.",
     "file": "projects/mk-kit/rich-text/rich-text-engine.ts",
     "kind": "interface",
     "members": [
      {
       "name": "before",
       "type": "string",
       "description": ""
      },
      {
       "name": "after",
       "type": "string",
       "description": ""
      }
     ]
    }
   ]
  },
  {
   "name": "block-editor",
   "import": "@mk-kit/ui/block-editor",
   "exports": [
    {
     "name": "MkBlockEditor",
     "description": "Block editor — a configurable, Gutenberg-style block content editor. Renders\nan ordered document of blocks (paragraph, heading, image, columns, embed,\nlist, quote, button, divider, code) with a filterable inserter, per-block\nchrome (move/duplicate/transform/delete) and inline rich-text formatting.\n\nThe palette is fully customisable: pass definitions via the `blocks` input or\nthe `MK_BLOCK_DEFINITIONS` token (mirrors `registerBlockType`). Both are\nmerged over `MK_DEFAULT_BLOCKS`.\n\nImplements `ControlValueAccessor` AND a two-way `value` model, so it works\nwith `[(ngModel)]`, reactive forms and `[(value)]`.\n\n```html\n<mk-block-editor [(value)]=\"doc\" [uploadHandler]=\"upload\" />\n```",
     "file": "projects/mk-kit/block-editor/block-editor.ts",
     "kind": "component",
     "selector": "mk-block-editor",
     "selectors": [
      "mk-block-editor"
     ],
     "formControl": true,
     "inputs": [
      {
       "name": "value",
       "type": "MkBlockDocument",
       "description": "Two-way document value (always an `MkBlockDocument`, regardless of format).",
       "model": true,
       "default": "mkEmptyDocument()"
      },
      {
       "name": "valueFormat",
       "type": "MkBlockValueFormat",
       "description": "Form/CVA exchange format. `document` (default) reads/writes an\n`MkBlockDocument`; `html` reads/writes an **HTML string** — so the editor\ncan back a string-typed richtext field (`[(ngModel)]=\"htmlString\"`). The\ntwo-way `value` model stays an `MkBlockDocument` either way.",
       "default": "'document'"
      },
      {
       "name": "blocks",
       "type": "MkBlockDefinition[] | null",
       "description": "Custom / extended block definitions (merged over the defaults + token).",
       "default": "null"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder for empty text blocks.",
       "default": "this.i18n.blockEditor.emptyBlockPlaceholder"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible label for the editor region.",
       "default": "this.i18n.blockEditor.editorLabel"
      },
      {
       "name": "readonly",
       "type": "boolean",
       "description": "Read-only: renders content without editing chrome.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disabled (form-level).",
       "default": "false"
      },
      {
       "name": "invalid",
       "type": "boolean",
       "description": "Force the invalid visual + `aria-invalid` when used standalone.",
       "default": "false"
      },
      {
       "name": "uploadHandler",
       "type": "MkBlockUploadHandler | null",
       "description": "Async upload handler (overrides the `MK_BLOCK_UPLOAD_HANDLER` token).",
       "default": "null"
      },
      {
       "name": "embedProviders",
       "type": "MkEmbedProvider[] | null",
       "description": "Extra embed providers (merged with defaults + token).",
       "default": "null"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "MkBlockDocument",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "change",
       "type": "MkBlockDocument",
       "description": "Fires on any document change (in addition to the `value` model)."
      },
      {
       "name": "htmlChange",
       "type": "string",
       "description": "Fires the serialised HTML on any change — convenient in `html` mode."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/content-editor"
    },
    {
     "name": "MkBlockRenderer",
     "description": "Block renderer — read-only, themed display of a `MkBlockDocument` for\npublished content pages and blog posts. Reuses the same layout CSS as the\neditor so authored columns look identical when published.\n\nSECURITY MODEL: rich-text HTML is passed through `sanitizeInlineHtml`\nand then bound with `[innerHTML]`, so Angular's `DomSanitizer` sanitises it\nagain at render time (never bypassed for author HTML). The ONLY bypass is for\na stored embed's `embedUrl`, which came from an allow-listed provider.",
     "file": "projects/mk-kit/block-editor/block-renderer.ts",
     "kind": "component",
     "selector": "mk-block-renderer",
     "selectors": [
      "mk-block-renderer"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "MkBlockDocument | null",
       "description": "The document to render.",
       "default": "null"
      },
      {
       "name": "blocks",
       "type": "MkBlock[] | null",
       "description": "Internal: a block subtree (used when recursing into columns).",
       "default": "null"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/content-editor"
    },
    {
     "name": "mkBlockId",
     "description": "Generates a reasonably unique, JSON-safe block id. Combines a monotonic\ncounter with a short random suffix so ids are unique even across documents\nmerged at runtime.",
     "file": "projects/mk-kit/block-editor/block-model.ts",
     "kind": "function",
     "signatures": [
      "(prefix?: string): string"
     ]
    },
    {
     "name": "mkBlocksToHtml",
     "description": "Serialises a document to clean, semantic, self-contained HTML — the \"rich\nHTML content\" you persist and publish for a blog post or content page.\nLayout blocks become responsive grid wrappers with inline styles.",
     "file": "projects/mk-kit/block-editor/block-serializer.ts",
     "kind": "function",
     "signatures": [
      "(doc: MkBlockDocument | null | undefined): string"
     ],
     "docs": "/components/content-editor"
    },
    {
     "name": "mkBlocksToText",
     "description": "Serialises a document to plain text — handy for previews, excerpts, search\nindexes and meta descriptions.",
     "file": "projects/mk-kit/block-editor/block-serializer.ts",
     "kind": "function",
     "signatures": [
      "(doc: MkBlockDocument | null | undefined): string"
     ]
    },
    {
     "name": "mkCloneBlock",
     "description": "Deep-clones a block (and its subtree), assigning fresh ids.",
     "file": "projects/mk-kit/block-editor/block-model.ts",
     "kind": "function",
     "signatures": [
      "(block: MkBlock): MkBlock"
     ]
    },
    {
     "name": "mkEmptyDocument",
     "description": "An empty, valid document.",
     "file": "projects/mk-kit/block-editor/block-model.ts",
     "kind": "function",
     "signatures": [
      "(): MkBlockDocument"
     ]
    },
    {
     "name": "mkEscapeAttr",
     "description": "Escapes a value for safe placement in a double-quoted attribute.",
     "file": "projects/mk-kit/block-editor/block-serializer.ts",
     "kind": "function",
     "signatures": [
      "(value: string): string"
     ]
    },
    {
     "name": "mkEscapeHtml",
     "description": "Escapes text for safe placement in element content.",
     "file": "projects/mk-kit/block-editor/block-serializer.ts",
     "kind": "function",
     "signatures": [
      "(value: string): string"
     ]
    },
    {
     "name": "mkHtmlToBlocks",
     "description": "Parse an HTML string into a `MkBlockDocument`. Empty / whitespace input\nyields an empty document.",
     "file": "projects/mk-kit/block-editor/block-parser.ts",
     "kind": "function",
     "signatures": [
      "(html: string): MkBlockDocument"
     ],
     "docs": "/components/content-editor"
    },
    {
     "name": "mkIsSafeUrl",
     "description": "True for URL schemes safe to place in `href`/`src`.",
     "file": "projects/mk-kit/block-editor/block-serializer.ts",
     "kind": "function",
     "signatures": [
      "(url: string): boolean"
     ]
    },
    {
     "name": "mkMergeBlockDefinitions",
     "description": "Merges default definitions with app-token definitions and per-editor input,\nde-duplicating by `type` (later sources win).",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "function",
     "signatures": [
      "(defaults: MkBlockDefinition[], ...sources: (MkBlockDefinition[] | null | undefined)[]): MkBlockDefinition[]"
     ]
    },
    {
     "name": "sanitizeInlineHtml",
     "description": "Allow-list cleaner for inline rich text. Keeps a small set of formatting\ntags, strips everything else's tags (preserving their text), removes event\nhandler attributes and unsafe `href`s. Not a substitute for `DomSanitizer`,\nbut makes the serialised string safe by construction.",
     "file": "projects/mk-kit/rich-text/sanitize.ts",
     "kind": "function",
     "signatures": [
      "(html: string): string"
     ]
    },
    {
     "name": "MK_BLOCK_DEFINITIONS",
     "description": "Multi-provider injection token for adding block definitions app-wide. Each\nprovided array is merged over `MK_DEFAULT_BLOCKS` (by `type`). The\neditor's `blocks` input takes final precedence.\n\n```ts\nproviders: [\n  { provide: MK_BLOCK_DEFINITIONS, multi: true, useValue: [myCalloutBlock] },\n]\n```",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "token",
     "type": "InjectionToken<MkBlockDefinition[][]>",
     "docs": "/components/content-editor"
    },
    {
     "name": "MK_BLOCK_EMBED_PROVIDERS",
     "description": "App-wide embed providers token (merged with the editor's input).",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "token",
     "type": "InjectionToken<MkEmbedProvider[][]>"
    },
    {
     "name": "MK_BLOCK_UPLOAD_HANDLER",
     "description": "App-wide upload handler token (overridable by the editor's input).",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "token",
     "type": "InjectionToken<MkBlockUploadHandler>"
    },
    {
     "name": "MK_BLOCK_DOCUMENT_VERSION",
     "description": "Current document schema version.",
     "file": "projects/mk-kit/block-editor/block-model.ts",
     "kind": "const",
     "type": "1"
    },
    {
     "name": "MK_DEFAULT_BLOCKS",
     "description": "The default palette of built-in block definitions. Grouped for the inserter.\nConsumers can spread this and append custom definitions, or replace it.\n\nThe English `label`/`group`/`description` text here is only a base: the\neditor resolves the built-in types' display text from the `blockEditor`\ni18n strings (see `provideMkI18n`) before merging custom definitions.",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "const",
     "type": "MkBlockDefinition[]"
    },
    {
     "name": "MK_DEFAULT_EMBED_PROVIDERS",
     "description": "Default embed providers: YouTube + Vimeo.",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "const",
     "type": "MkEmbedProvider[]"
    },
    {
     "name": "MkBlock",
     "description": "A single content block.\n\n`type` keys into the `MkBlockDefinition` registry that knows how to\nedit, serialise and render it. `data` is a free-form, JSON-safe bag of the\nblock's own state (e.g. `{ html }` for a paragraph, `{ src, alt }` for an\nimage). `children` enables nested layout blocks (a Columns block stores its\ncolumns' contents here).",
     "file": "projects/mk-kit/block-editor/block-model.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": "Stable unique id (used for keying, focus and drag/move)."
      },
      {
       "name": "type",
       "type": "string",
       "description": "Registry type key, e.g. `paragraph`, `heading`, `columns`."
      },
      {
       "name": "data",
       "type": "Record<string, any>",
       "description": "JSON-serialisable per-block state."
      },
      {
       "name": "children",
       "type": "MkBlock[] | undefined",
       "description": "Nested blocks for layout/container blocks (e.g. columns).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkBlockDefinition",
     "description": "Describes one registerable block type — the extensibility layer of the\neditor. Mirrors Gutenberg's `registerBlockType`: consumers supply an array of\nthese (via the `blocks` input or the `MK_BLOCK_DEFINITIONS` token) to\nadd, remove or reconfigure the palette. The built-in set is\n`MK_DEFAULT_BLOCKS`.",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "interface",
     "members": [
      {
       "name": "type",
       "type": "string",
       "description": "Unique type key that `MkBlock.type` references."
      },
      {
       "name": "label",
       "type": "string",
       "description": "Human label shown in the inserter and block toolbar."
      },
      {
       "name": "icon",
       "type": "string | undefined",
       "description": "Optional icon (emoji or short text glyph) shown in the inserter.",
       "optional": true
      },
      {
       "name": "group",
       "type": "string | undefined",
       "description": "Inserter grouping heading, e.g. `Text`, `Media`, `Layout`.",
       "optional": true
      },
      {
       "name": "description",
       "type": "string | undefined",
       "description": "Short description shown in the inserter.",
       "optional": true
      },
      {
       "name": "create",
       "type": "(): MkBlock",
       "description": "Factory returning a fresh, ready-to-edit block of this type."
      },
      {
       "name": "allowedInColumns",
       "type": "boolean | undefined",
       "description": "May this block be placed inside a Columns column? Default `true`.",
       "optional": true
      },
      {
       "name": "keywords",
       "type": "string[] | undefined",
       "description": "Keywords to match against when filtering the inserter.",
       "optional": true
      },
      {
       "name": "transforms",
       "type": "string[] | undefined",
       "description": "Block types this one can transform into (by type key).",
       "optional": true
      }
     ]
    },
    {
     "name": "MkBlockDocument",
     "description": "A full editor document: a version stamp plus an ordered list of blocks.",
     "file": "projects/mk-kit/block-editor/block-model.ts",
     "kind": "interface",
     "members": [
      {
       "name": "version",
       "type": "number",
       "description": "Schema version, bumped when the persisted shape changes."
      },
      {
       "name": "blocks",
       "type": "MkBlock[]",
       "description": "Top-level blocks, in document order."
      }
     ]
    },
    {
     "name": "MkEmbedProvider",
     "description": "An allow-listed embed provider. `test` matches a pasted URL; `toEmbedUrl`\nreturns the safe iframe `src` (which is the ONLY value ever passed to\n`DomSanitizer.bypassSecurityTrustResourceUrl`). Non-matching URLs fall back\nto a plain link card — raw HTML is never injected.",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "interface",
     "members": [
      {
       "name": "name",
       "type": "string",
       "description": "Display name, e.g. `YouTube`."
      },
      {
       "name": "test",
       "type": "RegExp",
       "description": "Matches URLs this provider handles."
      },
      {
       "name": "toEmbedUrl",
       "type": "(url: string): string | null",
       "description": "Transforms a matched page URL into an embeddable iframe `src`."
      },
      {
       "name": "aspectRatio",
       "type": "number | undefined",
       "description": "Aspect ratio `width / height` for the responsive frame. Default 16/9.",
       "optional": true
      },
      {
       "name": "sandbox",
       "type": "string | undefined",
       "description": "Allow list for the iframe `sandbox` attribute.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkBlockUploadHandler",
     "description": "Async handler that persists an uploaded `File` and resolves to its URL.\nProvide app-wide via this token, or per-editor via the `uploadHandler` input.\nWhen absent, the Image block falls back to an inline `data:` URL.",
     "file": "projects/mk-kit/block-editor/block-registry.ts",
     "kind": "type",
     "definition": "(file: File) => Promise<string>"
    },
    {
     "name": "MkBlockValueFormat",
     "description": "How the form/CVA value is exchanged: a document object or an HTML string.",
     "file": "projects/mk-kit/block-editor/block-editor.ts",
     "kind": "type",
     "definition": "'document' | 'html'"
    }
   ]
  },
  {
   "name": "context-menu",
   "import": "@mk-kit/ui/context-menu",
   "exports": [
    {
     "name": "MkContextMenuTrigger",
     "description": "Turns its host element into a right-click trigger for an `<mk-menu>`, reusing\nthe same `MkMenu` instance as `mkMenuTriggerFor`. On `contextmenu` it\nprevents the native menu and opens the menu at the pointer coordinates via\n`MkMenu.openAt`, restoring focus to the host on close.\n\nOn touch devices a long-press (~500ms hold with a touch pointer) opens the\nmenu at the touch point — iOS Safari never fires `contextmenu`, so this is\nthe only way to reach a context menu on iPhones. Moving the finger beyond a\nsmall slop, or lifting it early, cancels the press. On platforms that do\nsynthesize a `contextmenu` after a long-press (Android), that follow-up\nevent is suppressed so the menu doesn't open twice. While the directive is\nattached it disables the iOS press callout and text selection on the host\n(inline host styles — the directive has no stylesheet).\n\nFor keyboard users (WCAG) the dedicated <kbd>ContextMenu</kbd> key and\n<kbd>Shift</kbd>+<kbd>F10</kbd> open the menu anchored to the host element;\n<kbd>Escape</kbd> closes it. The host advertises `aria-haspopup=\"menu\"`.\nThe menu closes on selection, Escape or an outside click (handled by\n`MkMenu`).\n\n```html\n<tr [mkContextMenuTriggerFor]=\"rowMenu\" tabindex=\"0\">…</tr>\n<mk-menu #rowMenu>\n  <mk-menu-item (action)=\"edit()\">Edit</mk-menu-item>\n  <mk-menu-item danger (action)=\"del()\">Delete</mk-menu-item>\n</mk-menu>\n```",
     "file": "projects/mk-kit/context-menu/context-menu-trigger.ts",
     "kind": "directive",
     "selector": "[mkContextMenuTriggerFor]",
     "selectors": [
      "mkContextMenuTriggerFor"
     ],
     "exportAs": "mkContextMenuTrigger",
     "inputs": [
      {
       "name": "mkContextMenuTriggerFor",
       "type": "MkMenu",
       "description": "The menu instance to open on right-click / context-menu key.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/context-menu"
    }
   ]
  },
  {
   "name": "layout",
   "import": "@mk-kit/ui/layout",
   "exports": [
    {
     "name": "MkFlex",
     "description": "Flex — a flexbox container with its options as inputs, horizontal by default\nand no gap unless asked. Reach for it when a stack's \"one after another\"\nisn't the point: space-between toolbars, centring, wrapping tag clouds.\nChildren can fine-tune themselves with `mkFlexItem`.\n\n```html\n<mk-flex align=\"center\" justify=\"between\" gap=\"3\">\n  <h2>Orders</h2>\n  <button mkButton>New order</button>\n</mk-flex>\n<mk-flex wrap gap=\"2\">@for (tag of tags; track tag) { <mk-chip>{{ tag }}</mk-chip> }</mk-flex>\n```",
     "file": "projects/mk-kit/layout/flex.ts",
     "kind": "component",
     "selector": "mk-flex",
     "selectors": [
      "mk-flex"
     ],
     "inputs": [
      {
       "name": "gap",
       "type": "MkResponsiveSpace",
       "description": "Space between children (default none).",
       "default": "0"
      },
      {
       "name": "direction",
       "type": "MkResponsive<MkFlexDirection>",
       "description": "Direction (default `row`).",
       "default": "'row'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/layout"
    },
    {
     "name": "MkGrid",
     "description": "Grid — a CSS grid with the common cases as inputs.\n\n- `columns` — a count (`3` → three equal tracks) or a raw\n  `grid-template-columns` string (`'240px 1fr'`); responsive maps work for\n  both: `[columns]=\"{ xs: 1, md: 2, xl: 4 }\"`.\n- `minColumnWidth` — auto-responsive without breakpoints: as many\n  `≥ 16rem` columns as fit (`auto-fill`; add `autoFit` to stretch the last\n  row's items instead of leaving empty tracks). Wins over `columns`.\n- `gap`, `rowGap`, `columnGap` — `--mk-space-*` steps or CSS lengths.\n\nChildren can span tracks with `mkGridItem`.\n\n```html\n<mk-grid [columns]=\"{ xs: 1, md: 2, xl: 4 }\" gap=\"4\">",
     "file": "projects/mk-kit/layout/grid.ts",
     "kind": "component",
     "selector": "mk-grid",
     "selectors": [
      "mk-grid"
     ],
     "inputs": [
      {
       "name": "columns",
       "type": "MkResponsive<string | number>",
       "description": "Column count or `grid-template-columns` value; responsive allowed (default `1`).",
       "default": "1"
      },
      {
       "name": "rows",
       "type": "MkResponsive<string | number> | null",
       "description": "Row count or `grid-template-rows` value; responsive allowed.",
       "default": "null"
      },
      {
       "name": "minColumnWidth",
       "type": "MkResponsive<string> | null",
       "description": "Minimum column width for an auto-filling grid, e.g. `16rem`. Overrides `columns`.",
       "default": "null"
      },
      {
       "name": "autoFit",
       "type": "boolean",
       "description": "With `minColumnWidth`: use `auto-fit` so items stretch when a row is short.",
       "default": "false"
      },
      {
       "name": "gap",
       "type": "MkResponsiveSpace",
       "description": "Gap between both rows and columns (default `4` = 16px).",
       "default": "4"
      },
      {
       "name": "rowGap",
       "type": "MkResponsiveSpace | null",
       "description": "Row gap override.",
       "default": "null"
      },
      {
       "name": "columnGap",
       "type": "MkResponsiveSpace | null",
       "description": "Column gap override.",
       "default": "null"
      },
      {
       "name": "align",
       "type": "MkResponsive<MkAlign> | null",
       "description": "`align-items` for every cell.",
       "default": "null"
      },
      {
       "name": "justify",
       "type": "MkResponsive<MkGridJustify> | null",
       "description": "`justify-items` for every cell.",
       "default": "null"
      },
      {
       "name": "flow",
       "type": "\"row\" | \"column\" | \"dense\" | \"row dense\" | \"column dense\" | null",
       "description": "`grid-auto-flow` (e.g. `dense` to backfill holes left by spanning items).",
       "default": "null"
      },
      {
       "name": "inline",
       "type": "boolean",
       "description": "Render as `inline-grid`.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/layout"
    },
    {
     "name": "MkStack",
     "description": "Stack — children laid out one after another with a consistent gap, vertical\nby default. The everyday layout primitive: form sections, card bodies,\nsidebars, a row of buttons (`direction=\"row\"`).\n\n```html\n<mk-stack gap=\"4\">\n  <mk-input … />\n  <mk-input … />\n  <mk-stack direction=\"row\" gap=\"2\" justify=\"end\">\n    <button mkButton variant=\"ghost\">Cancel</button>\n    <button mkButton>Save</button>\n  </mk-stack>\n</mk-stack>\n\n<!-- Stack on phones, side by side from md up -->\n<mk-stack [direction]=\"{ xs: 'column', md: 'row' }\" [gap]=\"{ xs: 3, md: 6 }\">…</mk-stack>\n```",
     "file": "projects/mk-kit/layout/stack.ts",
     "kind": "component",
     "selector": "mk-stack",
     "selectors": [
      "mk-stack"
     ],
     "inputs": [
      {
       "name": "gap",
       "type": "MkResponsiveSpace",
       "description": "Space between children (default `4` = 16px).",
       "default": "4"
      },
      {
       "name": "direction",
       "type": "MkResponsive<MkFlexDirection>",
       "description": "Direction (default `column`).",
       "default": "'column'"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/layout"
    },
    {
     "name": "MkFlexBase",
     "description": "Shared inputs and host style bindings of `mk-stack` and `mk-flex`.\nResponsive inputs re-resolve when the viewport crosses a breakpoint.",
     "file": "projects/mk-kit/layout/flex-base.ts",
     "kind": "directive",
     "selector": "",
     "selectors": [],
     "inputs": [
      {
       "name": "align",
       "type": "MkResponsive<MkAlign> | null",
       "description": "Cross-axis alignment of children.",
       "default": "null"
      },
      {
       "name": "justify",
       "type": "MkResponsive<MkJustify> | null",
       "description": "Main-axis distribution of children.",
       "default": "null"
      },
      {
       "name": "wrap",
       "type": "boolean",
       "description": "Let children wrap onto new lines.",
       "default": "false"
      },
      {
       "name": "inline",
       "type": "boolean",
       "description": "Render as `inline-flex` (sits in a line of text) instead of a block.",
       "default": "false"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "gap",
       "type": "InputSignal<MkResponsiveSpace>",
       "description": "Space between children — a `--mk-space-*` step, a CSS length, or a per-breakpoint map.",
       "readonly": true
      },
      {
       "name": "direction",
       "type": "InputSignal<MkResponsive<MkFlexDirection>>",
       "description": "Main-axis direction; may be responsive, e.g. `{ xs: 'column', md: 'row' }`.",
       "readonly": true
      }
     ],
     "queries": []
    },
    {
     "name": "MkFlexItem",
     "description": "Per-child flex options inside `mk-flex` / `mk-stack` (or any flex parent).\n\n```html\n<mk-flex gap=\"3\">\n  <mk-input mkFlexItem grow />      <!-- takes the remaining width -->\n  <button mkButton>Search</button>\n</mk-flex>\n```",
     "file": "projects/mk-kit/layout/flex-item.ts",
     "kind": "directive",
     "selector": "[mkFlexItem]",
     "selectors": [
      "mkFlexItem"
     ],
     "inputs": [
      {
       "name": "grow",
       "type": "number | null",
       "description": "`flex-grow`; a bare `grow` attribute means `1`.",
       "default": "null",
       "transform": "(v) => (v === '' || v === true ? 1 : v == null || v === false ? null : numberAttribute(v))"
      },
      {
       "name": "shrink",
       "type": "number | null",
       "description": "`flex-shrink`; a bare `shrink` attribute means `1`, `[shrink]=\"0\"` pins the size.",
       "default": "null",
       "transform": "(v) => (v === '' || v === true ? 1 : v == null || v === false ? null : numberAttribute(v))"
      },
      {
       "name": "basis",
       "type": "MkResponsive<string> | null",
       "description": "`flex-basis` — any CSS length or `auto`; may be responsive.",
       "default": "null"
      },
      {
       "name": "alignSelf",
       "type": "MkResponsive<MkAlign> | null",
       "description": "Override the parent's `align` for this child.",
       "default": "null"
      },
      {
       "name": "order",
       "type": "MkResponsive<string | number> | null",
       "description": "Visual order; may be responsive (e.g. move a sidebar first on phones).",
       "default": "null"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkGridItem",
     "description": "Per-cell placement inside `mk-grid`: span several tracks, or pin a start\nline. All inputs accept responsive maps, so a hero card can span the full\nrow on phones and two of four columns on desktop.\n\n```html\n<mk-grid [columns]=\"{ xs: 1, lg: 4 }\" gap=\"4\">\n  <mk-card mkGridItem [colSpan]=\"{ xs: 1, lg: 2 }\">Revenue</mk-card>\n  …\n</mk-grid>\n```",
     "file": "projects/mk-kit/layout/grid-item.ts",
     "kind": "directive",
     "selector": "[mkGridItem]",
     "selectors": [
      "mkGridItem"
     ],
     "inputs": [
      {
       "name": "colSpan",
       "type": "MkResponsive<string | number> | null",
       "description": "Number of columns to span (`'all'` = the full row).",
       "default": "null"
      },
      {
       "name": "rowSpan",
       "type": "MkResponsive<string | number> | null",
       "description": "Number of rows to span.",
       "default": "null"
      },
      {
       "name": "colStart",
       "type": "MkResponsive<string | number> | null",
       "description": "Column line to start at (1-based).",
       "default": "null"
      },
      {
       "name": "rowStart",
       "type": "MkResponsive<string | number> | null",
       "description": "Row line to start at (1-based).",
       "default": "null"
      },
      {
       "name": "alignSelf",
       "type": "MkResponsive<\"start\" | \"end\" | \"center\" | \"stretch\"> | null",
       "description": "`align-self` for this cell.",
       "default": "null"
      },
      {
       "name": "justifySelf",
       "type": "MkResponsive<\"start\" | \"end\" | \"center\" | \"stretch\"> | null",
       "description": "`justify-self` for this cell.",
       "default": "null"
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "mkAlignToCss",
     "description": "`align-items` / `align-self` value for a `MkAlign` keyword (`null` when unset).",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "function",
     "signatures": [
      "(value: MkAlign | null | undefined): string | null"
     ]
    },
    {
     "name": "mkJustifyToCss",
     "description": "`justify-content` value for a `MkJustify` keyword (`null` when unset).",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "function",
     "signatures": [
      "(value: MkJustify | null | undefined): string | null"
     ]
    },
    {
     "name": "mkNumeric",
     "description": "A number, or a numeric string as it arrives from a plain attribute\n(`gap=\"4\"`, `colSpan=\"2\"`), as a number; anything else unchanged.",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "function",
     "signatures": [
      "<T>(value: T): T | number"
     ]
    },
    {
     "name": "mkSpaceToCss",
     "description": "Translate a `MkSpace` into CSS (`null` when unset).",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "function",
     "signatures": [
      "(value: MkSpace | null | undefined): string | null"
     ]
    },
    {
     "name": "MkAlign",
     "description": "Cross-axis alignment keywords.",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "type",
     "definition": "'start' | 'center' | 'end' | 'stretch' | 'baseline'"
    },
    {
     "name": "MkFlexDirection",
     "description": "Flex direction keywords.",
     "file": "projects/mk-kit/layout/flex-base.ts",
     "kind": "type",
     "definition": "'row' | 'column' | 'row-reverse' | 'column-reverse'"
    },
    {
     "name": "MkGridJustify",
     "description": "`justify-items` keywords.",
     "file": "projects/mk-kit/layout/grid.ts",
     "kind": "type",
     "definition": "'start' | 'center' | 'end' | 'stretch'"
    },
    {
     "name": "MkJustify",
     "description": "Flex / grid main-axis distribution keywords, in plain words.",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "type",
     "definition": "'start' | 'center' | 'end' | 'between' | 'around' | 'evenly' | 'stretch'"
    },
    {
     "name": "MkResponsiveSpace",
     "description": "Per-breakpoint spacing, e.g. `{ xs: 2, md: 4 }`.",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "type",
     "definition": "MkResponsive<MkSpace>"
    },
    {
     "name": "MkSpace",
     "description": "A spacing value: a step on the `--mk-space-*` scale (`0 1 2 3 4 5 6 8 10 12\n16`, so `4` = `var(--mk-space-4)` = 16px and follows the density modes) or\nany CSS length such as `'1.5rem'` / `'clamp(1rem, 2vw, 2rem)'`.",
     "file": "projects/mk-kit/layout/space.ts",
     "kind": "type",
     "definition": "number | string"
    }
   ]
  },
  {
   "name": "chat",
   "import": "@mk-kit/ui/chat",
   "exports": [
    {
     "name": "MkChat",
     "description": "Chat — a conversation: a scrolling, screen-reader-announced log of\n`mk-chat-message` bubbles that stays pinned to the newest message while\ntext streams in (with a *jump to latest* button once the reader scrolls\nup), a typing indicator, and an `mk-prompt-box` composer.\n\nThe component is presentational: hand it `messages` (replace the array or\na message object to update — signals compare by reference) and react to\n`(send)` / `(stop)` / `(retry)` with your own transport.\n\n```html\n<mk-chat\n  [messages]=\"messages()\"\n  [busy]=\"generating()\"\n  [typing]=\"peerTyping()\"\n  attachments\n  [suggestions]=\"starters\"\n  (send)=\"ask($event)\"\n  (stop)=\"abort()\"\n  (retry)=\"resend($event)\"\n  style=\"height: 32rem\"\n>\n  <div mkChatHeader>…title, model picker…</div>\n  <div mkChatEmpty>…first-run hint…</div>\n</mk-chat>\n```\n\nSlots: `[mkChatHeader]`, `[mkChatEmpty]`, `[mkChatFooter]` (under the composer).",
     "file": "projects/mk-kit/chat/chat/chat.ts",
     "kind": "component",
     "selector": "mk-chat",
     "selectors": [
      "mk-chat"
     ],
     "inputs": [
      {
       "name": "messages",
       "type": "readonly MkChatMessage[]",
       "description": "The conversation, oldest first.",
       "default": "[]"
      },
      {
       "name": "ownRole",
       "type": "MkChatRole",
       "description": "Which role renders on the \"own\" side (default `user`).",
       "default": "'user'"
      },
      {
       "name": "markdown",
       "type": "boolean",
       "description": "Render assistant text as Markdown.",
       "default": "true"
      },
      {
       "name": "showAvatars",
       "type": "boolean",
       "description": "",
       "default": "true"
      },
      {
       "name": "showTimestamps",
       "type": "boolean",
       "description": "",
       "default": "true"
      },
      {
       "name": "typing",
       "type": "boolean",
       "description": "Someone else is typing (shows the dots indicator).",
       "default": "false"
      },
      {
       "name": "busy",
       "type": "boolean",
       "description": "A reply is being generated: composer shows *stop*.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable the composer.",
       "default": "false"
      },
      {
       "name": "readonly",
       "type": "boolean",
       "description": "Hide the composer entirely (read-only transcript).",
       "default": "false"
      },
      {
       "name": "placeholder",
       "type": "string | undefined",
       "description": "",
       "default": "undefined"
      },
      {
       "name": "attachments",
       "type": "boolean",
       "description": "Allow attachments in the composer.",
       "default": "false"
      },
      {
       "name": "accept",
       "type": "string",
       "description": "",
       "default": "''"
      },
      {
       "name": "maxFiles",
       "type": "number",
       "description": "",
       "default": "0"
      },
      {
       "name": "maxLength",
       "type": "number",
       "description": "",
       "default": "0"
      },
      {
       "name": "suggestions",
       "type": "readonly string[]",
       "description": "Quick replies above the composer; each click sends its text.",
       "default": "[]"
      },
      {
       "name": "emptyMessage",
       "type": "string | undefined",
       "description": "Text shown when there are no messages (or project `[mkChatEmpty]`).",
       "default": "undefined"
      },
      {
       "name": "autoScroll",
       "type": "boolean",
       "description": "Keep the log pinned to the newest message while the reader is at the bottom.",
       "default": "true"
      },
      {
       "name": "ariaLabel",
       "type": "string | undefined",
       "description": "Accessible name of the log region.",
       "default": "undefined"
      }
     ],
     "outputs": [
      {
       "name": "send",
       "type": "MkChatSend",
       "description": ""
      },
      {
       "name": "stop",
       "type": "void",
       "description": ""
      },
      {
       "name": "retry",
       "type": "MkChatMessage",
       "description": ""
      }
     ],
     "methods": [
      {
       "name": "scrollToBottom",
       "signature": "(): void",
       "description": "Scroll the log to the newest message."
      },
      {
       "name": "focus",
       "signature": "(): void",
       "description": "Focus the composer."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/chat"
    },
    {
     "name": "MkChatMessageComponent",
     "description": "ChatMessage — one bubble: avatar, author and time, attachment previews,\ntool-call cards, the text (Markdown for assistants) with a streaming\ncursor, and copy / retry actions. `mk-chat` renders these for you; use it\ndirectly to build your own list.",
     "file": "projects/mk-kit/chat/chat-message/chat-message.ts",
     "kind": "component",
     "selector": "mk-chat-message",
     "selectors": [
      "mk-chat-message"
     ],
     "inputs": [
      {
       "name": "message",
       "type": "MkChatMessage",
       "description": "The message to render.",
       "required": true
      },
      {
       "name": "own",
       "type": "boolean",
       "description": "Render on the \"own\" (end) side — `mk-chat` sets this from `ownRole`.",
       "default": "false"
      },
      {
       "name": "markdown",
       "type": "boolean",
       "description": "Render `text` as Markdown (assistants only; user text is always plain).",
       "default": "true"
      },
      {
       "name": "showAvatar",
       "type": "boolean",
       "description": "",
       "default": "true"
      },
      {
       "name": "showTimestamp",
       "type": "boolean",
       "description": "",
       "default": "true"
      },
      {
       "name": "copyable",
       "type": "boolean",
       "description": "Offer a copy button on hover / focus.",
       "default": "true"
      }
     ],
     "outputs": [
      {
       "name": "retry",
       "type": "MkChatMessage",
       "description": "The retry button of a failed message was pressed."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/chat"
    },
    {
     "name": "MkPromptBox",
     "description": "PromptBox — the composer of a chat: an auto-growing textarea, attachments\n(button, drop, paste), quick-reply suggestions and a send button that turns\ninto *stop* while a reply is being generated.\n\nEnter sends, Shift+Enter breaks the line (`sendOnEnter=\"false\"` to swap).\n\n```html\n<mk-prompt-box\n  [(value)]=\"draft\"\n  [busy]=\"generating()\"\n  attachments\n  [suggestions]=\"['Summarise this page', 'Draft a reply']\"\n  (send)=\"ask($event)\"\n  (stop)=\"abort()\"\n/>\n```",
     "file": "projects/mk-kit/chat/prompt-box/prompt-box.ts",
     "kind": "component",
     "selector": "mk-prompt-box",
     "selectors": [
      "mk-prompt-box"
     ],
     "inputs": [
      {
       "name": "value",
       "type": "string",
       "description": "The draft text (two-way).",
       "model": true,
       "default": "''"
      },
      {
       "name": "placeholder",
       "type": "string",
       "description": "Placeholder of the textarea.",
       "default": "this.i18n.chatPlaceholder"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable everything (e.g. while offline).",
       "default": "false"
      },
      {
       "name": "busy",
       "type": "boolean",
       "description": "A reply is being generated: the send button becomes *stop*, sending is paused.",
       "default": "false"
      },
      {
       "name": "attachments",
       "type": "boolean",
       "description": "Allow attaching files (button, drag & drop, paste).",
       "default": "false"
      },
      {
       "name": "accept",
       "type": "string",
       "description": "Accepted file types for the picker (`accept` attribute syntax).",
       "default": "''"
      },
      {
       "name": "maxFiles",
       "type": "number",
       "description": "Maximum number of attached files (0 = unlimited).",
       "default": "0"
      },
      {
       "name": "maxLength",
       "type": "number",
       "description": "Maximum draft length; shows a counter when set.",
       "default": "0"
      },
      {
       "name": "rows",
       "type": "number",
       "description": "Minimum visible rows.",
       "default": "1"
      },
      {
       "name": "maxRows",
       "type": "number",
       "description": "Rows the textarea grows to before scrolling.",
       "default": "8"
      },
      {
       "name": "sendOnEnter",
       "type": "boolean",
       "description": "Enter sends and Shift+Enter breaks the line (default); `false` swaps them.",
       "default": "true"
      },
      {
       "name": "suggestions",
       "type": "readonly string[]",
       "description": "Quick replies shown above the box; clicking one sends it.",
       "default": "[]"
      },
      {
       "name": "autofocus",
       "type": "boolean",
       "description": "Focus the textarea on render.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "string",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "send",
       "type": "MkChatSend",
       "description": "The user submitted the draft (and any files)."
      },
      {
       "name": "stop",
       "type": "void",
       "description": "The user pressed *stop* while `busy`."
      }
     ],
     "methods": [
      {
       "name": "focus",
       "signature": "(): void",
       "description": "Focus the textarea."
      },
      {
       "name": "clear",
       "signature": "(): void",
       "description": "Empty the draft and the attachment list."
      },
      {
       "name": "submit",
       "signature": "(): void",
       "description": "Submit the current draft (no-op when there is nothing to send or while busy)."
      },
      {
       "name": "addFiles",
       "signature": "(list: ArrayLike<File> | null | undefined): void",
       "description": "Add files, honouring `maxFiles` and `accept`."
      },
      {
       "name": "removeFile",
       "signature": "(index: number): void",
       "description": ""
      }
     ],
     "properties": [
      {
       "name": "files",
       "type": "WritableSignal<File[]>",
       "description": "Files waiting to be sent.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/chat"
    },
    {
     "name": "MkChatMessageDef",
     "description": "Custom message rendering for `mk-chat`:\n\n```html\n<mk-chat [messages]=\"messages()\">\n  <ng-template mkChatMessageDef let-message let-own=\"own\">\n    <my-bubble [message]=\"message\" [mine]=\"own\" />\n  </ng-template>\n</mk-chat>\n```",
     "file": "projects/mk-kit/chat/chat/chat.ts",
     "kind": "directive",
     "selector": "ng-template[mkChatMessageDef]",
     "selectors": [
      "mkChatMessageDef"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkChatAttachment",
     "description": "A file shown with a message (an image when `type` is `image/*` and `url` is set).",
     "file": "projects/mk-kit/chat/chat.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "name",
       "type": "string",
       "description": ""
      },
      {
       "name": "type",
       "type": "string | undefined",
       "description": "MIME type, e.g. `image/png`.",
       "optional": true
      },
      {
       "name": "size",
       "type": "number | undefined",
       "description": "Size in bytes, shown formatted.",
       "optional": true
      },
      {
       "name": "url",
       "type": "string | undefined",
       "description": "Link / image source.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkChatAuthor",
     "description": "Display identity of a message author.",
     "file": "projects/mk-kit/chat/chat.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "name",
       "type": "string",
       "description": "Shown beside the message and used for avatar initials."
      },
      {
       "name": "avatar",
       "type": "string | undefined",
       "description": "Avatar image URL; initials from `name` when omitted.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkChatMessage",
     "description": "One message in the conversation. Replace the object (new reference) to update it.",
     "file": "projects/mk-kit/chat/chat.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": ""
      },
      {
       "name": "role",
       "type": "MkChatRole",
       "description": ""
      },
      {
       "name": "text",
       "type": "string",
       "description": "Message body — Markdown for assistants (when `markdown` is on), plain text otherwise."
      },
      {
       "name": "author",
       "type": "MkChatAuthor | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "timestamp",
       "type": "string | number | Date | undefined",
       "description": "When it was sent; a `Date`, ISO string or epoch ms.",
       "optional": true
      },
      {
       "name": "streaming",
       "type": "boolean | undefined",
       "description": "Still receiving text: shows a cursor and keeps the log pinned to the bottom.",
       "optional": true
      },
      {
       "name": "error",
       "type": "string | undefined",
       "description": "Delivery / generation failed; shown under the bubble with a retry button.",
       "optional": true
      },
      {
       "name": "attachments",
       "type": "MkChatAttachment[] | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "tools",
       "type": "MkChatToolCall[] | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkChatMessageContext",
     "description": "Context handed to an `*mkChatMessageDef` template.",
     "file": "projects/mk-kit/chat/chat/chat.ts",
     "kind": "interface",
     "members": [
      {
       "name": "$implicit",
       "type": "MkChatMessage",
       "description": ""
      },
      {
       "name": "own",
       "type": "boolean",
       "description": ""
      },
      {
       "name": "index",
       "type": "number",
       "description": ""
      }
     ]
    },
    {
     "name": "MkChatSend",
     "description": "Payload of the `send` output.",
     "file": "projects/mk-kit/chat/chat.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "text",
       "type": "string",
       "description": ""
      },
      {
       "name": "files",
       "type": "File[]",
       "description": ""
      }
     ]
    },
    {
     "name": "MkChatToolCall",
     "description": "A tool call card rendered above the message text.",
     "file": "projects/mk-kit/chat/chat.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "name",
       "type": "string",
       "description": "Tool name, e.g. `search_orders`."
      },
      {
       "name": "status",
       "type": "MkChatToolStatus",
       "description": ""
      },
      {
       "name": "summary",
       "type": "string | undefined",
       "description": "One-line human summary, e.g. `3 orders found`.",
       "optional": true
      },
      {
       "name": "input",
       "type": "string | undefined",
       "description": "Raw input, shown under the disclosure.",
       "optional": true
      },
      {
       "name": "output",
       "type": "string | undefined",
       "description": "Raw output, shown under the disclosure.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkChatRole",
     "description": "Who a message comes from. `system` renders as a centred note.",
     "file": "projects/mk-kit/chat/chat.types.ts",
     "kind": "type",
     "definition": "'user' | 'assistant' | 'system'"
    },
    {
     "name": "MkChatToolStatus",
     "description": "Lifecycle of a tool / function call an assistant made while answering.",
     "file": "projects/mk-kit/chat/chat.types.ts",
     "kind": "type",
     "definition": "'running' | 'done' | 'error'"
    }
   ]
  },
  {
   "name": "query-builder",
   "import": "@mk-kit/ui/query-builder",
   "exports": [
    {
     "name": "MkQueryBuilder",
     "description": "QueryBuilder — a rule / group tree the user assembles from your `fields`,\nheld as plain JSON (`MkQueryGroup`) in the two-way `query` model. Pair it\nwith `mkQueryToPredicate()` to filter rows in the browser, with\n`MkTableDataSource.setQuery()` to send it to the server, or with\n`mkQueryToText()` for a readable summary.\n\n```html\n<mk-query-builder [fields]=\"fields\" [(query)]=\"query\" allowNot />\n\nfields: MkQueryField[] = [\n  { key: 'name', label: 'Name' },\n  { key: 'orders', label: 'Orders', type: 'number' },\n  { key: 'status', label: 'Status', type: 'select', options: [{ label: 'Active', value: 'active' }, …] },\n  { key: 'since', label: 'Customer since', type: 'date' },\n  { key: 'vip', label: 'VIP', type: 'boolean' },\n];\nrows = computed(() => this.all.filter(mkQueryToPredicate(this.query(), this.fields)));\n```",
     "file": "projects/mk-kit/query-builder/query-builder.ts",
     "kind": "component",
     "selector": "mk-query-builder",
     "selectors": [
      "mk-query-builder"
     ],
     "inputs": [
      {
       "name": "fields",
       "type": "readonly MkQueryField[]",
       "description": "The filterable fields, in picker order.",
       "required": true
      },
      {
       "name": "query",
       "type": "MkQueryGroup",
       "description": "The query tree (two-way). Starts as an empty `and` group.",
       "model": true,
       "default": "mkCreateQueryGroup()"
      },
      {
       "name": "maxDepth",
       "type": "number",
       "description": "How deep groups may nest (0 = rules only).",
       "default": "3"
      },
      {
       "name": "allowNot",
       "type": "boolean",
       "description": "Offer a *Not* toggle on every group.",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "Control size (default `sm`).",
       "default": "'sm'"
      },
      {
       "name": "ariaLabel",
       "type": "string | undefined",
       "description": "",
       "default": "undefined"
      }
     ],
     "outputs": [
      {
       "name": "queryChange",
       "type": "MkQueryGroup",
       "description": "Emits when `query` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "clear",
       "signature": "(): void",
       "description": "Reset to an empty group."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/query-builder"
    },
    {
     "name": "MkQueryGroupComponent",
     "description": "One group of the builder — its combinator toggle, rules, nested groups and\nthe add / remove actions. Used by `mk-query-builder`; every edit emits a\nnew immutable group upward.",
     "file": "projects/mk-kit/query-builder/query-group.ts",
     "kind": "component",
     "selector": "mk-query-group",
     "selectors": [
      "mk-query-group"
     ],
     "inputs": [
      {
       "name": "group",
       "type": "MkQueryGroup",
       "description": "",
       "required": true
      },
      {
       "name": "fields",
       "type": "readonly MkQueryField[]",
       "description": "",
       "required": true
      },
      {
       "name": "depth",
       "type": "number",
       "description": "",
       "default": "0"
      },
      {
       "name": "maxDepth",
       "type": "number",
       "description": "",
       "default": "3"
      },
      {
       "name": "allowNot",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "root",
       "type": "boolean",
       "description": "",
       "default": "false"
      },
      {
       "name": "size",
       "type": "MkSize",
       "description": "",
       "default": "'sm'"
      }
     ],
     "outputs": [
      {
       "name": "groupChange",
       "type": "MkQueryGroup",
       "description": "A new version of this group after an edit."
      },
      {
       "name": "remove",
       "type": "void",
       "description": "The user removed this (non-root) group."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": []
    }
   ]
  },
  {
   "name": "dynamic-form",
   "import": "@mk-kit/ui/dynamic-form",
   "exports": [
    {
     "name": "MkDynamicFields",
     "description": "Renders one field list (the root, a group, or one array item) as a grid.\nInternal — projected by `MkDynamicForm`; recursive for groups/arrays.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.ts",
     "kind": "component",
     "selector": "mk-dynamic-fields",
     "selectors": [
      "mk-dynamic-fields"
     ],
     "inputs": [
      {
       "name": "fields",
       "type": "readonly MkDynamicField[]",
       "description": "",
       "required": true
      },
      {
       "name": "group",
       "type": "FormGroup<any>",
       "description": "",
       "required": true
      },
      {
       "name": "columns",
       "type": "number",
       "description": "",
       "default": "1"
      },
      {
       "name": "scope",
       "type": "Record<string, unknown>",
       "description": "Value the conditions of this level are evaluated against.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "MkDynamicForm",
     "description": "Dynamic form — renders a form from a JSON schema and manages one reactive\n`FormGroup` for it. Every value field renders inside `mk-form-field`, so\nlabels, hints, required marks and localised validation messages come from\nthe schema alone.\n\n```html\n<mk-dynamic-form [schema]=\"schema\" [(value)]=\"user\" (formSubmit)=\"save($event)\">\n  <button mkButton type=\"submit\">Save</button>\n</mk-dynamic-form>\n```\n\n```ts\nschema: MkDynamicSchema = {\n  columns: 2,\n  fields: [\n    { key: 'name', type: 'text', label: 'Name', required: true },\n    { key: 'role', type: 'select', label: 'Role', options: roles },\n    { key: 'company', type: 'text', label: 'Company', showWhen: { field: 'role', eq: 'b2b' } },\n  ],\n};\n```\n\n- Hidden fields (`showWhen` false) are disabled, so `value` only carries\n  what the user can see; `form.getRawValue()` has everything.\n- `form` is the live `FormGroup` for anything the schema does not cover.\n- Custom field types: project an `ng-template[mkDynamicField]`.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.ts",
     "kind": "component",
     "selector": "mk-dynamic-form",
     "selectors": [
      "mk-dynamic-form"
     ],
     "inputs": [
      {
       "name": "schema",
       "type": "MkDynamicSchema",
       "description": "The schema. Changing it rebuilds the form (values of surviving keys are kept).",
       "required": true
      },
      {
       "name": "value",
       "type": "Record<string, unknown>",
       "description": "Two-way form value (visible, enabled fields only).",
       "model": true,
       "default": "{}"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable every control.",
       "default": "false"
      },
      {
       "name": "labelPosition",
       "type": "\"top\" | \"float\"",
       "description": "Label placement forwarded to every `mk-form-field`.",
       "default": "'top'"
      },
      {
       "name": "size",
       "type": "\"sm\" | \"md\" | \"lg\"",
       "description": "Control size forwarded to the fields.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "valueChange",
       "type": "Record<string, unknown>",
       "description": "Emits when `value` changes (two-way binding).",
       "model": true
      },
      {
       "name": "formSubmit",
       "type": "Record<string, unknown>",
       "description": "Emits the value when the form is submitted and valid."
      },
      {
       "name": "invalidSubmit",
       "type": "FormGroup<any>",
       "description": "Emits when a submit is attempted while invalid (every control is marked touched)."
      }
     ],
     "methods": [
      {
       "name": "patch",
       "signature": "(value: Record<string, unknown>): void",
       "description": "Patch part of the value."
      },
      {
       "name": "reset",
       "signature": "(value?: Record<string, unknown>): void",
       "description": "Reset to the schema defaults (or the given value)."
      },
      {
       "name": "touchAll",
       "signature": "(): void",
       "description": "Mark every control touched so validation messages show."
      }
     ],
     "properties": [
      {
       "name": "form",
       "type": "FormGroup<any>",
       "description": "The live reactive form.",
       "readonly": true
      },
      {
       "name": "valid",
       "type": "Signal<boolean>",
       "description": "`true` while every control passes validation.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/dynamic-form"
    },
    {
     "name": "MkDynamicFieldDef",
     "description": "Registers a renderer for a custom field type:\n\n```html\n<mk-dynamic-form [schema]=\"schema\">\n  <ng-template mkDynamicField=\"signature\" let-field let-control=\"control\">\n    <mk-signature-pad [formControl]=\"control\" />\n  </ng-template>\n</mk-dynamic-form>\n```\n\nA field `{ type: 'custom', key: 'sig', props: { renderer: 'signature' } }`\n(or any built-in `type` you want to override) then renders this template\ninside the usual `mk-form-field`.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.ts",
     "kind": "directive",
     "selector": "ng-template[mkDynamicField]",
     "selectors": [
      "mkDynamicField"
     ],
     "inputs": [
      {
       "name": "mkDynamicField",
       "type": "string",
       "description": "The type (or `props.renderer` name) this template renders.",
       "required": true
      }
     ],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": []
    },
    {
     "name": "mkDynamicCondition",
     "description": "Evaluate a condition against a form value. `value` is normally the whole\nform value; inside an array item the item's own value is used, with the\nroot available under `$root`.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(cond: MkDynamicCondition | undefined, value: Record<string, unknown>): boolean"
     ]
    },
    {
     "name": "mkDynamicControl",
     "description": "Build the `FormControl` / `FormGroup` / `FormArray` for one field.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(field: MkDynamicField, value?: unknown): AbstractControl"
     ]
    },
    {
     "name": "mkDynamicDefaults",
     "description": "Default value object of a field list (groups nested, arrays as item lists).",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(fields: readonly MkDynamicField[]): Record<string, unknown>"
     ]
    },
    {
     "name": "mkDynamicEmptyValue",
     "description": "The empty value a field type starts with when no `default` is given.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(field: MkDynamicFieldBase): unknown"
     ]
    },
    {
     "name": "mkDynamicFlatten",
     "description": "Depth-first list of every value field with its dotted path.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(fields: readonly MkDynamicField[], prefix?: string): Array<{ path: string; field: MkDynamicFieldBase | MkDynamicGroup | MkDynamicArray; }>"
     ]
    },
    {
     "name": "mkDynamicForm",
     "description": "Build the reactive form of a whole schema.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(schema: MkDynamicSchema, value?: Record<string, unknown>): FormGroup"
     ]
    },
    {
     "name": "mkDynamicFormToSignalSchema",
     "description": "Converts an `mk-dynamic-form` schema into a Signal Forms `Schema`, so the\nsame JSON definition can drive `form()` from `@angular/forms/signals`:\n\n```ts\nconst definition: MkDynamicSchema = { fields: [ … ] };\nconst model = signal(mkDynamicDefaults(definition.fields));\nconst f = form(model, mkDynamicFormToSignalSchema(definition));\n```\n\nWhat maps:\n- `required` → `required()` (for `checkbox` / `switch` this means \"must be\n  on\", as Signal Forms treats `false` as empty — the `requiredTrue`\n  behaviour of the renderer);\n- `validators.min` / `max` / `minLength` / `maxLength` / `pattern` / `email`\n  (and `type: 'email'`) → the matching built-in rules, so the field's\n  `min()` / `maxLength()` / `pattern()` state is set as well;\n- `validators.custom` → `validate()` running each `ValidatorFn` against a\n  throw-away `FormControl` holding the field's value; the reactive error\n  keys become error `kind`s with their payload attached, so\n  `mk-form-field` renders them through the same i18n table;\n- `disabled: true` and `disabledWhen` → `disabled()`, `showWhen` →\n  `hidden()` — the condition is evaluated against the form value exactly as\n  the renderer does it (dotted paths, `and` / `or` / `not`, and inside an\n  array item the item's own value with the root under `$root` and the\n  position under `$index`);\n- `group` → the nested fields under the group's key, `array` → `applyEach`\n  over the items plus `minItems` / `maxItems` errors from `min` / `max`.\n\nWhat differs from the renderer: a hidden Signal Forms field is skipped for\nvalidation and touched / dirty state but **keeps its value in the model**\n(the model is your data — nothing is stripped), so remove hidden controls\nfrom the template with `@if (!f.company().hidden())` and drop the value\nyourself before saving if it must not be sent. Layout properties (`span`,\n`columns`), `options`, `props` and `section` entries have no schema\nequivalent and are ignored.",
     "file": "projects/mk-kit/dynamic-form/signal-schema.ts",
     "kind": "function",
     "signatures": [
      "<TModel extends object = Record<string, unknown>>(definition: MkDynamicSchema | readonly MkDynamicField[]): Schema<TModel>"
     ],
     "docs": "/components/signal-forms"
    },
    {
     "name": "mkDynamicGroup",
     "description": "A `FormGroup` for a field list; `value` (partial) overrides the defaults.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(fields: readonly MkDynamicField[], value?: Record<string, unknown>): FormGroup"
     ]
    },
    {
     "name": "mkDynamicSpan",
     "description": "Column span a field takes in a grid of `columns`.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(field: MkDynamicField, columns: number): number"
     ]
    },
    {
     "name": "mkDynamicValidators",
     "description": "Angular validators for one value field, from its declarative `validators` + `required`.",
     "file": "projects/mk-kit/dynamic-form/schema.ts",
     "kind": "function",
     "signatures": [
      "(field: MkDynamicFieldBase): ValidatorFn[]"
     ]
    },
    {
     "name": "mkIsArray",
     "description": "",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "function",
     "signatures": [
      "(f: MkDynamicField): f is MkDynamicArray"
     ]
    },
    {
     "name": "mkIsGroup",
     "description": "",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "function",
     "signatures": [
      "(f: MkDynamicField): f is MkDynamicGroup"
     ]
    },
    {
     "name": "mkIsSection",
     "description": "",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "function",
     "signatures": [
      "(f: MkDynamicField): f is MkDynamicSection"
     ]
    },
    {
     "name": "mkIsValueField",
     "description": "",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "function",
     "signatures": [
      "(f: MkDynamicField): f is MkDynamicFieldBase"
     ]
    },
    {
     "name": "MkDynamicArray",
     "description": "A list of objects: a `FormArray` of groups with add / remove controls.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "type",
       "type": "\"array\"",
       "description": ""
      },
      {
       "name": "key",
       "type": "string",
       "description": ""
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "fields",
       "type": "MkDynamicField[]",
       "description": "Fields of one item."
      },
      {
       "name": "min",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "max",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "addLabel",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "default",
       "type": "Record<string, unknown>[] | undefined",
       "description": "Initial items (each is patched over the item defaults).",
       "optional": true
      },
      {
       "name": "span",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "columns",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "showWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "disabledWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicFieldBase",
     "description": "Properties shared by every field that holds a value.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": "Key in the form value."
      },
      {
       "name": "type",
       "type": "MkDynamicFieldType",
       "description": ""
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "placeholder",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "required",
       "type": "boolean | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "default",
       "type": "unknown",
       "description": "Initial value when the form (or a new array item) is created.",
       "optional": true
      },
      {
       "name": "validators",
       "type": "MkDynamicValidators | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "options",
       "type": "readonly MkDynamicOption[] | undefined",
       "description": "Options for select / multi-select / radio / toggle / autocomplete.",
       "optional": true
      },
      {
       "name": "props",
       "type": "Record<string, unknown> | undefined",
       "description": "Extra inputs forwarded to the underlying control — the subset each type\nunderstands (`rows`, `min`, `max`, `step`, `currency`, `accept`,\n`multiple`, `swatches`, `language`, …). See the docs table.",
       "optional": true
      },
      {
       "name": "span",
       "type": "number | undefined",
       "description": "Grid columns (1–12) the field spans. Default: the form's `columns` split.",
       "optional": true
      },
      {
       "name": "showWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "Render (and enable) only when the condition holds. Hidden fields are excluded from the value.",
       "optional": true
      },
      {
       "name": "disabledWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "Disable while the condition holds.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicFieldContext",
     "description": "Context handed to a custom field template.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.ts",
     "kind": "interface",
     "members": [
      {
       "name": "$implicit",
       "type": "MkDynamicFieldBase",
       "description": ""
      },
      {
       "name": "field",
       "type": "MkDynamicFieldBase",
       "description": ""
      },
      {
       "name": "control",
       "type": "FormControl<any>",
       "description": "The field's `FormControl` — bind it with `[formControl]`."
      },
      {
       "name": "value",
       "type": "Record<string, unknown>",
       "description": "The current value of the whole form (or array item)."
      }
     ]
    },
    {
     "name": "MkDynamicGroup",
     "description": "A nested object: its fields become a child `FormGroup` under `key`.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "type",
       "type": "\"group\"",
       "description": ""
      },
      {
       "name": "key",
       "type": "string",
       "description": ""
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "fields",
       "type": "MkDynamicField[]",
       "description": ""
      },
      {
       "name": "span",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "columns",
       "type": "number | undefined",
       "description": "Columns for the group's own grid (default: inherits the form's).",
       "optional": true
      },
      {
       "name": "showWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "disabledWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicGroupField",
     "description": "A nested object: its fields become a child `FormGroup` under `key`.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "type",
       "type": "\"group\"",
       "description": ""
      },
      {
       "name": "key",
       "type": "string",
       "description": ""
      },
      {
       "name": "label",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "fields",
       "type": "MkDynamicField[]",
       "description": ""
      },
      {
       "name": "span",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "columns",
       "type": "number | undefined",
       "description": "Columns for the group's own grid (default: inherits the form's).",
       "optional": true
      },
      {
       "name": "showWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "disabledWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicOption",
     "description": "One option of a select / radio / toggle / autocomplete field.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": ""
      },
      {
       "name": "value",
       "type": "unknown",
       "description": ""
      },
      {
       "name": "disabled",
       "type": "boolean | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicSchema",
     "description": "The whole form.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "fields",
       "type": "MkDynamicField[]",
       "description": ""
      },
      {
       "name": "columns",
       "type": "number | undefined",
       "description": "Default number of columns fields are laid out in (1–12). Default 1.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicSection",
     "description": "A heading + description with no value of its own.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "type",
       "type": "\"section\"",
       "description": ""
      },
      {
       "name": "label",
       "type": "string",
       "description": ""
      },
      {
       "name": "hint",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "span",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "showWhen",
       "type": "MkDynamicCondition | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicValidators",
     "description": "Declarative validators — plain data so a schema can be stored as JSON.\n`custom` takes Angular validator functions for anything else.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "interface",
     "members": [
      {
       "name": "min",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "max",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "minLength",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "maxLength",
       "type": "number | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "pattern",
       "type": "string | RegExp | undefined",
       "description": "A RegExp or its source string.",
       "optional": true
      },
      {
       "name": "email",
       "type": "boolean | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "custom",
       "type": "ValidatorFn[] | undefined",
       "description": "Angular validator functions appended after the declarative ones.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkDynamicCondition",
     "description": "A serialisable condition over the form value (dotted paths reach into\ngroups: `address.country`). Combine with `and` / `or`; a function is the\nescape hatch for TypeScript-only schemas.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "type",
     "definition": "| { field: string; eq?: unknown; neq?: unknown; in?: unknown[]; notIn?: unknown[]; truthy?: boolean; empty?: boolean } | { and: MkDynamicCondition[] } | { or: MkDynamicCondition[] } | { not: MkDynamicCondition } | ((value: Record<string, unknown>) => boolean)"
    },
    {
     "name": "MkDynamicField",
     "description": "",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "type",
     "definition": "MkDynamicFieldBase | MkDynamicGroup | MkDynamicArray | MkDynamicSection"
    },
    {
     "name": "MkDynamicFieldType",
     "description": "Field kinds `mk-dynamic-form` renders out of the box. Each maps to one\nmk-kit control; `custom` renders a projected `mkDynamicField` template.",
     "file": "projects/mk-kit/dynamic-form/dynamic-form.types.ts",
     "kind": "type",
     "definition": "| 'text' | 'email' | 'password' | 'url' | 'tel' | 'search' | 'textarea' | 'number' | 'currency' | 'date' | 'time' | 'datetime' | 'select' | 'multi-select' | 'autocomplete' | 'radio' | 'toggle' | 'checkbox' | 'switch' | 'slider' | 'rating' | 'color' | 'tags' | 'phone' | 'file' | 'code' | 'custom'"
    }
   ]
  },
  {
   "name": "media",
   "import": "@mk-kit/ui/media",
   "exports": [
    {
     "name": "MkImage",
     "description": "Image — an enhanced image block. While the picture loads it shows a skeleton\nshimmer, and when loading fails it swaps to a localised fallback panel\n(icon + text, never colour alone). The picture is wrapped in a `<figure>`\nwith an optional `<figcaption>`, and changing `src` restarts the whole load\ncycle.\n\n```html\n<mk-image\n  src=\"/photos/harbour.jpg\"\n  alt=\"Harbour at dawn\"\n  aspectRatio=\"16 / 9\"\n  caption=\"The old harbour, photographed at dawn\"\n  (loaded)=\"onLoaded()\"\n  (errored)=\"onErrored()\"\n/>\n\n<!-- The hero: eager, high priority, and sized per breakpoint so a phone\n     does not download the desktop file. -->\n<mk-image\n  src=\"/photos/hero-1600.jpg\"\n  srcset=\"/photos/hero-800.jpg 800w, /photos/hero-1600.jpg 1600w\"\n  sizes=\"100vw\"\n  alt=\"\"\n  aspectRatio=\"16 / 9\"\n  priority\n/>\n```\n\n`aspectRatio` is what keeps this from shifting layout: the frame reserves\nits box before the picture arrives, so nothing below it moves.",
     "file": "projects/mk-kit/media/image/image.ts",
     "kind": "component",
     "selector": "mk-image",
     "selectors": [
      "mk-image"
     ],
     "exportAs": "mkImage",
     "inputs": [
      {
       "name": "src",
       "type": "string",
       "description": "Image URL. Changing it resets the block to its loading state.",
       "required": true
      },
      {
       "name": "alt",
       "type": "string",
       "description": "Alt text, always reflected onto the `<img>`. Keep `''` for decorative images.",
       "default": "''"
      },
      {
       "name": "aspectRatio",
       "type": "string",
       "description": "Any CSS `aspect-ratio` value for the frame, e.g. `'1 / 1'` or `'16 / 9'`.",
       "default": "'auto'"
      },
      {
       "name": "fit",
       "type": "MkImageFit",
       "description": "How the picture fills the frame.",
       "default": "'cover'"
      },
      {
       "name": "rounded",
       "type": "MkImageRounded",
       "description": "Corner rounding of the frame.",
       "default": "'md'"
      },
      {
       "name": "caption",
       "type": "string",
       "description": "Caption rendered in a `<figcaption>` below the picture.",
       "default": "''"
      },
      {
       "name": "lazy",
       "type": "boolean",
       "description": "Defer fetching until near the viewport (`loading=\"lazy\"` vs `\"eager\"`).",
       "default": "true"
      },
      {
       "name": "priority",
       "type": "boolean",
       "description": "Mark this as the page's LCP image: fetched eagerly at high priority and\ndecoded synchronously, and `lazy` is ignored. Use it on exactly ONE image\nper page — the hero. Marking several is worse than marking none, because\nthey then compete for the same bandwidth the real LCP image needs.\n\nThis does NOT emit a `<link rel=preload>`; the tag has to be in the HTML\nthe server sends to beat the preload scanner, which a component rendered\nlater cannot guarantee. Pair it with a preload hint for a background or\nlate-rendered hero.",
       "default": "false"
      },
      {
       "name": "srcset",
       "type": "string",
       "description": "Responsive candidates, passed through verbatim to the `<img>`. Serving a\n2048px file into a 600px slot is one of the most common LCP mistakes, and\nthis is the fix; pair with `sizes`.",
       "default": "''"
      },
      {
       "name": "sizes",
       "type": "string",
       "description": "`sizes` attribute — how wide the image renders at each breakpoint.",
       "default": "''"
      }
     ],
     "outputs": [
      {
       "name": "loaded",
       "type": "void",
       "description": "Emits once the picture has finished loading."
      },
      {
       "name": "errored",
       "type": "void",
       "description": "Emits when the picture fails to load and the fallback panel is shown."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/images"
    },
    {
     "name": "MkImageCropper",
     "description": "ImageCropper — pan-and-zoom crop control for avatars, covers and media uploads.\nThe image covers a fixed-aspect viewport (object-fit-cover style); the user\ndrags to pan, scrolls / pinch-zooms via the slider or `+`/`−` controls, and\n`crop()` renders the visible region to a data-URL on an offscreen canvas.\n\nPan is always clamped so the image keeps covering the viewport, a\nrule-of-thirds grid appears while dragging, and `round` overlays a circular\nscrim for avatar crops (the exported bitmap stays rectangular). The crop\narea is keyboard operable: Arrow keys pan by 10px (1px with Shift), `+`/`-`\nzoom.\n\n```html\n<mk-image-cropper #cropper src=\"/assets/photo.jpg\" [aspect]=\"1\" round />\n<button mkButton (click)=\"avatar = cropper.crop({ size: 512 })\">Save</button>\n```",
     "file": "projects/mk-kit/media/image-cropper/image-cropper.ts",
     "kind": "component",
     "selector": "mk-image-cropper",
     "selectors": [
      "mk-image-cropper"
     ],
     "exportAs": "mkImageCropper",
     "inputs": [
      {
       "name": "src",
       "type": "string",
       "description": "Image URL or data-URL to crop.",
       "required": true
      },
      {
       "name": "aspect",
       "type": "number | null",
       "description": "Aspect ratio (width / height) of the crop viewport, e.g. `1` for a\nsquare or `16 / 9`. `null` makes the viewport fill its container.",
       "default": "1"
      },
      {
       "name": "round",
       "type": "boolean",
       "description": "Circular mask overlay for avatar crops. Purely visual — the exported\nbitmap from `crop()` stays rectangular.",
       "default": "false"
      },
      {
       "name": "minZoom",
       "type": "number",
       "description": "Lowest allowed zoom factor.",
       "default": "1"
      },
      {
       "name": "maxZoom",
       "type": "number",
       "description": "Highest allowed zoom factor.",
       "default": "4"
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": "Disable panning and zooming.",
       "default": "false"
      },
      {
       "name": "crossOrigin",
       "type": "\"anonymous\" | \"use-credentials\" | null",
       "description": "`crossorigin` for the internal `<img>`. Set to `'anonymous'` when\ncropping CORS-enabled remote images — without it the canvas is tainted\nand `crop()` returns `null`. Same-origin and data-URL sources don't\nneed it.",
       "default": "null"
      },
      {
       "name": "ariaLabel",
       "type": "string | null",
       "description": "Accessible name for the crop area (defaults to the i18n `zoom` label).",
       "default": "null"
      },
      {
       "name": "zoom",
       "type": "number",
       "description": "Two-way zoom factor, clamped to `[minZoom, maxZoom]`.",
       "model": true,
       "default": "1"
      }
     ],
     "outputs": [
      {
       "name": "changed",
       "type": "void",
       "description": "Emits on any pan or zoom change."
      },
      {
       "name": "imageError",
       "type": "void",
       "description": "Emits when the image fails to load."
      },
      {
       "name": "zoomChange",
       "type": "number",
       "description": "Emits when `zoom` changes (two-way binding).",
       "model": true
      }
     ],
     "methods": [
      {
       "name": "reset",
       "signature": "(): void",
       "description": "Centre the image and reset zoom to 1 (clamped to `minZoom`)."
      },
      {
       "name": "cropRect",
       "signature": "(): { sx: number; sy: number; sw: number; sh: number; } | null",
       "description": "The visible crop region in natural image pixels — what `crop()` would\nrasterise, without touching a canvas. Use it when the backend performs\nthe actual crop from the master image (no client-side quality loss).\nReturns `null` until the image has loaded and the viewport is measured."
      },
      {
       "name": "crop",
       "signature": "(options?: { type?: string; quality?: number; size?: number; }): string | null",
       "description": ""
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/media-manager"
    },
    {
     "name": "MkImageGallery",
     "description": "Image gallery — a wall of clickable picture tiles built on `MkImage`.\nChoose a uniform `grid`, a natural-ratio `masonry` flow, or a snap-scrolling\nhorizontal `strip`. Clicking a tile opens the shared `MkLightboxService`\nat that picture (full-size `src`, not the thumb) and always emits\n`itemClick`. With `max` set, only the first `max` tiles render and the last\none carries a \"+N\" overflow scrim that opens the rest in the lightbox.\n\n```html\n<mk-image-gallery\n  [items]=\"[\n    { src: '/photos/1.jpg', thumb: '/thumbs/1.jpg', alt: 'Harbour at dawn' },\n    { src: '/photos/2.jpg', alt: 'Old town square', caption: 'Kraków' },\n  ]\"\n  [columns]=\"4\"\n  [max]=\"8\"\n  aspectRatio=\"4 / 3\"\n  (itemClick)=\"onItemClick($event)\"\n/>\n```",
     "file": "projects/mk-kit/media/image-gallery/image-gallery.ts",
     "kind": "component",
     "selector": "mk-image-gallery",
     "selectors": [
      "mk-image-gallery"
     ],
     "exportAs": "mkImageGallery",
     "inputs": [
      {
       "name": "items",
       "type": "readonly MkGalleryItem[]",
       "description": "Pictures to show.",
       "required": true
      },
      {
       "name": "layout",
       "type": "MkImageGalleryLayout",
       "description": "Tile arrangement.",
       "default": "'grid'"
      },
      {
       "name": "columns",
       "type": "number",
       "description": "Grid/masonry column count; also sets the visible tile count of a strip.",
       "default": "3"
      },
      {
       "name": "max",
       "type": "number | null",
       "description": "When set, show only the first `max` tiles plus a \"+N\" overflow tile.",
       "default": "null"
      },
      {
       "name": "lightbox",
       "type": "boolean",
       "description": "Open the shared lightbox on tile click.",
       "default": "true"
      },
      {
       "name": "aspectRatio",
       "type": "string",
       "description": "CSS aspect-ratio of grid/strip tiles (masonry keeps natural ratios).",
       "default": "'1 / 1'"
      },
      {
       "name": "rounded",
       "type": "MkImageRounded",
       "description": "Corner rounding of the tiles.",
       "default": "'md'"
      }
     ],
     "outputs": [
      {
       "name": "itemClick",
       "type": "MkGalleryItemClick",
       "description": "Emits on every tile click (also when the lightbox opens)."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/images"
    },
    {
     "name": "MkLightbox",
     "description": "Internal overlay component backing `MkLightboxService`. Renders the\ncurrent image near-fullscreen over the overlay scrim with a caption bar,\nan `imageOf` counter, a close button and looping previous/next navigation.\n\nKeyboard: `ArrowLeft`/`ArrowRight` navigate, `Home`/`End` jump to the first\nor last image. `Escape` and backdrop clicks are handled by the overlay\nitself (`closeOnEscape` / `closeOnBackdropClick`), so they are deliberately\nnot re-handled here.\n\nOpen it via the service — not by placing `<mk-lightbox>` in a template:\n\n```ts\ninject(MkLightboxService).open(items, 2);\n```",
     "file": "projects/mk-kit/media/lightbox/lightbox.ts",
     "kind": "component",
     "selector": "mk-lightbox",
     "selectors": [
      "mk-lightbox"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/images"
    },
    {
     "name": "MkMediaGallery",
     "description": "Media gallery — a management grid of image tiles for admin media libraries.\nEach tile shows a square thumbnail (a labelled preview button emitting\n`itemClick`), the item's name and optional meta line, an optional\nselection checkbox (two-way `selection` model of selected ids) and an\noptional consumer-projected action bar (`MkMediaActions`).\n\nWith `reorderable`, tiles become draggable via the dnd group's\n`[mkDropList]` / `[mkDrag]` directives — pointer and keyboard dragging\n(WCAG 2.1.1) both included. Each drop immutably updates the two-way `items`\nmodel and emits `reordered`.\n\nClicking a tile always means \"open/preview\" — selection only toggles through\nthe checkbox, never on tile click.\n\n```html\n<mk-media-gallery\n  [(items)]=\"assets\"\n  [(selection)]=\"selectedIds\"\n  selectable\n  reorderable\n  [columns]=\"5\"\n  (itemClick)=\"openPreview($event)\"\n  (reordered)=\"persistOrder($event)\"\n>\n  <ng-template mkMediaActions let-item>\n    <button mkButton size=\"sm\" variant=\"ghost\" (click)=\"edit(item)\">Edit</button>\n    <button mkButton size=\"sm\" variant=\"ghost\" tone=\"danger\" (click)=\"remove(item)\">\n      Delete\n    </button>\n  </ng-template>\n</mk-media-gallery>\n```",
     "file": "projects/mk-kit/media/media-gallery/media-gallery.ts",
     "kind": "component",
     "selector": "mk-media-gallery",
     "selectors": [
      "mk-media-gallery"
     ],
     "exportAs": "mkMediaGallery",
     "inputs": [
      {
       "name": "items",
       "type": "MkMediaItem[]",
       "description": "The gallery's items (two-way). Replaced immutably on every reorder drop.",
       "model": true,
       "default": "[]"
      },
      {
       "name": "selection",
       "type": "string[]",
       "description": "Ids of the currently selected items (two-way).",
       "model": true,
       "default": "[]"
      },
      {
       "name": "selectable",
       "type": "boolean",
       "description": "Show a selection checkbox on every tile.",
       "default": "false"
      },
      {
       "name": "reorderable",
       "type": "boolean",
       "description": "Allow drag-and-drop (pointer + keyboard) reordering of the tiles.",
       "default": "false"
      },
      {
       "name": "columns",
       "type": "number",
       "description": "Number of grid columns.",
       "default": "4"
      },
      {
       "name": "ariaLabel",
       "type": "string",
       "description": "Accessible name of the gallery region. Defaults to `i18n.mediaLibrary`.",
       "default": "this.i18n.mediaLibrary"
      }
     ],
     "outputs": [
      {
       "name": "itemsChange",
       "type": "MkMediaItem[]",
       "description": "Emits when `items` changes (two-way binding).",
       "model": true
      },
      {
       "name": "selectionChange",
       "type": "string[]",
       "description": "Emits when `selection` changes (two-way binding).",
       "model": true
      },
      {
       "name": "itemClick",
       "type": "MkMediaItem",
       "description": "Emitted when a tile's preview button is activated (click/Enter/Space)."
      },
      {
       "name": "reordered",
       "type": "MkMediaReorderEvent",
       "description": "Emitted after a drop has updated the `items` model."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/media-manager"
    },
    {
     "name": "MkMediaActions",
     "description": "Marks an `<ng-template>` as the per-tile action bar for `MkMediaGallery`.\nThe template's implicit context is the `MkMediaItem`, so consumers can\ndestructure it with `let-item`. The gallery renders it into each tile's\ntop-right action bar (revealed on hover / focus-within, always visible on\ntouch devices); the consumer supplies the buttons and their handlers.\n\n```html\n<mk-media-gallery [items]=\"assets()\">\n  <ng-template mkMediaActions let-item>\n    <button mkButton size=\"sm\" variant=\"ghost\" (click)=\"edit(item)\">Edit</button>\n  </ng-template>\n</mk-media-gallery>\n```",
     "file": "projects/mk-kit/media/media-gallery/media-gallery.ts",
     "kind": "directive",
     "selector": "[mkMediaActions]",
     "selectors": [
      "mkMediaActions"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [
      {
       "name": "template",
       "type": "TemplateRef<{ $implicit: MkMediaItem; }>",
       "description": "The projected action-bar template, rendered once per tile.",
       "readonly": true
      }
     ],
     "queries": [],
     "docs": "/components/media-manager"
    },
    {
     "name": "MkLightboxService",
     "description": "Fullscreen image lightbox — opens a set of images in a modal overlay with\nlooping previous/next navigation, captions, a counter, keyboard support\n(Arrow keys, Home/End, Escape) and focus trapping, all powered by\n`MkOverlayService`.\n\n```ts\nprivate readonly lightbox = inject(MkLightboxService);\n\nviewPhoto(index: number): void {\n  this.lightbox.open(\n    [\n      { src: '/photos/1.jpg', alt: 'Harbour at dawn', caption: 'Dawn' },\n      { src: '/photos/2.jpg', alt: 'Old town square' },\n    ],\n    index,\n  );\n}\n```",
     "file": "projects/mk-kit/media/lightbox/lightbox.service.ts",
     "kind": "service",
     "providedIn": "root",
     "methods": [
      {
       "name": "open",
       "signature": "(items: readonly MkLightboxItem[], startIndex?: number): void",
       "description": "Open the lightbox over the page. Does nothing when `items` is empty.\n`startIndex` is clamped into `[0, items.length - 1]`."
      }
     ],
     "properties": [],
     "docs": "/components/images"
    },
    {
     "name": "mkClampPan",
     "description": "Clamp a pan offset (CSS px, measured from the viewport centre to the image\ncentre) so the image scaled by `scale` still covers the viewport — no empty\nedges. When the scaled image is not larger than the viewport on an axis the\noffset collapses to `0` (centred).",
     "file": "projects/mk-kit/media/image-cropper/image-cropper.ts",
     "kind": "function",
     "signatures": [
      "(x: number, y: number, imgW: number, imgH: number, vpW: number, vpH: number, scale: number): { x: number; y: number; }"
     ]
    },
    {
     "name": "mkCoverScale",
     "description": "Base cover scale for an image in a viewport — the smallest scale at which\n`imgW × imgH` fully covers `vpW × vpH` (object-fit: cover). Returns `1`\nfor degenerate (non-positive) dimensions.",
     "file": "projects/mk-kit/media/image-cropper/image-cropper.ts",
     "kind": "function",
     "signatures": [
      "(imgW: number, imgH: number, vpW: number, vpH: number): number"
     ]
    },
    {
     "name": "mkCropRect",
     "description": "Source rect (in natural image pixels) of the crop region visible through\nthe viewport. `scale` maps natural pixels to CSS pixels (cover scale ×\nzoom); `panX`/`panY` are the CSS-px offsets of the image centre from the\nviewport centre. The rect is clamped inside the image bounds.",
     "file": "projects/mk-kit/media/image-cropper/image-cropper.ts",
     "kind": "function",
     "signatures": [
      "(imgNaturalW: number, imgNaturalH: number, vpW: number, vpH: number, scale: number, panX: number, panY: number): { sx: number; sy: number; sw: number; sh: number; }"
     ]
    },
    {
     "name": "MkGalleryItem",
     "description": "A single picture inside an `MkImageGallery`.",
     "file": "projects/mk-kit/media/image-gallery/image-gallery.ts",
     "kind": "interface",
     "members": [
      {
       "name": "src",
       "type": "string",
       "description": "Full-size image URL (what the lightbox opens)."
      },
      {
       "name": "thumb",
       "type": "string | undefined",
       "description": "Optional smaller thumbnail URL for the tile; falls back to `src`.",
       "optional": true
      },
      {
       "name": "alt",
       "type": "string | undefined",
       "description": "Alt text; also drives the tile's accessible label.",
       "optional": true
      },
      {
       "name": "caption",
       "type": "string | undefined",
       "description": "Optional caption forwarded to the lightbox.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkGalleryItemClick",
     "description": "Payload of the `MkImageGallery.itemClick` output.",
     "file": "projects/mk-kit/media/image-gallery/image-gallery.ts",
     "kind": "interface",
     "members": [
      {
       "name": "item",
       "type": "MkGalleryItem",
       "description": "The clicked picture."
      },
      {
       "name": "index",
       "type": "number",
       "description": "Its index within `items`."
      }
     ]
    },
    {
     "name": "MkLightboxData",
     "description": "Data injected into `MkLightbox` via `MK_OVERLAY_DATA`.",
     "file": "projects/mk-kit/media/lightbox/lightbox.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "items",
       "type": "readonly MkLightboxItem[]",
       "description": "The images to page through."
      },
      {
       "name": "startIndex",
       "type": "number",
       "description": "Index of the image shown first (already clamped into range)."
      }
     ]
    },
    {
     "name": "MkLightboxItem",
     "description": "A single image shown by `MkLightboxService`.",
     "file": "projects/mk-kit/media/lightbox/lightbox.service.ts",
     "kind": "interface",
     "members": [
      {
       "name": "src",
       "type": "string",
       "description": "Image URL."
      },
      {
       "name": "alt",
       "type": "string | undefined",
       "description": "Alternative text for the image.",
       "optional": true
      },
      {
       "name": "caption",
       "type": "string | undefined",
       "description": "Optional caption rendered below the image.",
       "optional": true
      }
     ]
    },
    {
     "name": "MkMediaItem",
     "description": "A single asset displayed as a tile in `MkMediaGallery`.",
     "file": "projects/mk-kit/media/media-gallery/media-gallery.ts",
     "kind": "interface",
     "members": [
      {
       "name": "id",
       "type": "string",
       "description": "Stable identity used for tracking, selection and reorder events."
      },
      {
       "name": "src",
       "type": "string",
       "description": "Full-size image URL (used for the thumbnail when `thumb` is omitted)."
      },
      {
       "name": "thumb",
       "type": "string | undefined",
       "description": "Optional dedicated thumbnail URL shown in the grid.",
       "optional": true
      },
      {
       "name": "name",
       "type": "string",
       "description": "Display name shown under the thumbnail; also names the selection checkbox."
      },
      {
       "name": "alt",
       "type": "string | undefined",
       "description": "Alternative text describing the image; falls back to `name` for labels.",
       "optional": true
      },
      {
       "name": "meta",
       "type": "string | undefined",
       "description": "Optional caption/meta line shown under the name (e.g. \"1.2 MB · JPG\").",
       "optional": true
      }
     ]
    },
    {
     "name": "MkMediaReorderEvent",
     "description": "Emitted by `MkMediaGallery` after a tile has been reordered.",
     "file": "projects/mk-kit/media/media-gallery/media-gallery.ts",
     "kind": "interface",
     "members": [
      {
       "name": "from",
       "type": "number",
       "description": "Index the item was dragged from."
      },
      {
       "name": "to",
       "type": "number",
       "description": "Index the item was dropped at."
      },
      {
       "name": "items",
       "type": "MkMediaItem[]",
       "description": "The full item array after the move (same reference as the updated model)."
      }
     ]
    },
    {
     "name": "MkImageFit",
     "description": "How the picture is scaled inside its frame (`object-fit`).",
     "file": "projects/mk-kit/media/image/image.ts",
     "kind": "type",
     "definition": "'cover' | 'contain'"
    },
    {
     "name": "MkImageGalleryLayout",
     "description": "Tile arrangement of an `MkImageGallery`.",
     "file": "projects/mk-kit/media/image-gallery/image-gallery.ts",
     "kind": "type",
     "definition": "'grid' | 'masonry' | 'strip'"
    },
    {
     "name": "MkImageRounded",
     "description": "Corner rounding applied to the frame of an `MkImage`.",
     "file": "projects/mk-kit/media/image/image.ts",
     "kind": "type",
     "definition": "'none' | 'md' | 'lg' | 'circle'"
    },
    {
     "name": "MkImageState",
     "description": "Load lifecycle of an `MkImage`.",
     "file": "projects/mk-kit/media/image/image.ts",
     "kind": "type",
     "definition": "'loading' | 'loaded' | 'error'"
    }
   ]
  },
  {
   "name": "embed",
   "import": "@mk-kit/ui/embed",
   "exports": [
    {
     "name": "MkEmbedApp",
     "description": "One shared embed application. Create it with `mkEmbed`.",
     "file": "projects/mk-kit/embed/embed.ts",
     "kind": "class",
     "methods": [
      {
       "name": "element",
       "signature": "(tag: string, component: Type<unknown>): this",
       "description": "Defines `tag` as a custom element rendering `component`. Chainable; a\nno-op when the tag is already defined (hot reload, duplicate script) or\noutside a browser."
      },
      {
       "name": "ready",
       "signature": "(): Promise<void>",
       "description": "Resolves when the shared application is running (created on demand)."
      },
      {
       "name": "whenStable",
       "signature": "(): Promise<void>",
       "description": "Resolves when the application has no pending change detection."
      },
      {
       "name": "destroy",
       "signature": "(): void",
       "description": "Destroys the shared application, every mounted component and the overlay\nhost. Defined tags remain registered (the platform cannot undefine them)\nbut render nothing afterwards."
      }
     ],
     "properties": []
    },
    {
     "name": "mkEmbed",
     "description": "Creates an embed application: a factory for custom elements that render\nmk-kit-based Angular components behind shadow DOM.\n\n- **Lazy**: `element()` only defines the tag; the Angular application is\n  created on the first element actually connected to a document.\n- **Shared**: every element of one `mkEmbed()` call runs in one zoneless\n  `ApplicationRef` with one provider set.\n- **Isolated but themable**: the host page's CSS cannot reach the widget\n  internals, while `--mk-*` custom properties still inherit through the\n  shadow boundary — set them on the element (or any ancestor) to theme it.\n- **Styled**: Angular routes each component's own styles into the shadow\n  root it renders in; the `styles` option supplies the token/theme layer.\n\n```ts\nimport { mkEmbed, mkShadowCss } from '@mk-kit/ui/embed';\nimport themeCss from '@mk-kit/ui/styles.css' with { type: 'text' };\n\nmkEmbed({ styles: mkShadowCss(themeCss) })\n  .element('acme-reviews', ReviewsWidget)\n  .element('acme-signup', SignupWidget);\n```\n\n```html\n<acme-reviews product-id=\"42\" style=\"--mk-primary: #7c3aed\"></acme-reviews>\n```\n\nInputs are exposed as dash-cased attributes (string values go through the\ninput's `transform`, so `booleanAttribute` / `numberAttribute` inputs coerce\nas usual) and as camel-cased element properties (any value); outputs become\nbubbling, composed `CustomEvent`s named after the output, with the emitted\nvalue as `detail`.",
     "file": "projects/mk-kit/embed/embed.ts",
     "kind": "function",
     "signatures": [
      "(init?: MkEmbedInit): MkEmbedApp"
     ]
    },
    {
     "name": "mkShadowCss",
     "description": "Rewrites a document-level stylesheet for adoption into a shadow root:\n`:root` never matches inside one, so token blocks like mk-kit's\n`:root { --mk-primary: … }` are retargeted to `:host`. Theme opt-ins keep\nworking — `:root:not([data-mk-theme='light'])` becomes\n`:host:not([data-mk-theme='light'])`, so `<my-widget data-mk-theme=\"dark\">`\nswitches one embedded element to the dark palette.\n\n```ts\nimport themeCss from '@mk-kit/ui/styles.css' with { type: 'text' };\nmkEmbed({ styles: mkShadowCss(themeCss) });\n```",
     "file": "projects/mk-kit/embed/shadow-css.ts",
     "kind": "function",
     "signatures": [
      "(css: string): string"
     ]
    },
    {
     "name": "MkEmbedInit",
     "description": "Options for `mkEmbed`.",
     "file": "projects/mk-kit/embed/embed.ts",
     "kind": "interface",
     "members": [
      {
       "name": "styles",
       "type": "string | readonly string[] | undefined",
       "description": "CSS text adopted into every element's shadow root (and the overlay host).\nPass the mk-kit theme through `mkShadowCss` so its `:root` token\nblocks target `:host`; append your own widget CSS after it. Shared as\nconstructable stylesheets when the browser supports them (one parse for\nany number of instances), `<style>` elements otherwise.",
       "optional": true
      },
      {
       "name": "styleUrls",
       "type": "readonly string[] | undefined",
       "description": "Stylesheet URLs loaded as `<link rel=\"stylesheet\">` into every shadow\nroot (and the overlay host) — an alternative to inlining `styles` when\nthe theme lives on a CDN. Loaded per shadow root by the browser's cache,\nso the network cost is paid once.",
       "optional": true
      },
      {
       "name": "nonce",
       "type": "string | undefined",
       "description": "CSP nonce applied to every style and link element this app creates —\nincluding Angular's own component styles (provided as `CSP_NONCE`) and\nthe `<style>` fallback when constructable stylesheets are unavailable.\nFor host pages with a `style-src` policy that forbids `'unsafe-inline'`.",
       "optional": true
      },
      {
       "name": "providers",
       "type": "(Provider | EnvironmentProviders)[] | undefined",
       "description": "Extra providers for the shared application — `provideMkI18n(…)`,\n`provideMkExtendedIcons()`, `provideHttpClient()`, your services.",
       "optional": true
      },
      {
       "name": "overlays",
       "type": "boolean | undefined",
       "description": "Mount mk-kit overlays (dialogs, anchored panels, toasts, tours) inside a\npage-level shadow host that carries the same `styles`, instead of bare\n`document.body`. Default `true`; set `false` to keep the application\ndefault (overlays styled by the page's own stylesheets).",
       "optional": true
      }
     ]
    }
   ]
  },
  {
   "name": "locales/de",
   "import": "@mk-kit/ui/locales/de",
   "exports": [
    {
     "name": "mkPluralDe",
     "description": "Picks the German plural form for a count — CLDR's `de` rules for integers:\n`one` for 1, `other` for everything else.\n\n```ts\nmkPluralDe(1, 'Ergebnis', 'Ergebnisse'); // 'Ergebnis'\nmkPluralDe(3, 'Ergebnis', 'Ergebnisse'); // 'Ergebnisse'\n```",
     "file": "projects/mk-kit/locales/de/de.ts",
     "kind": "function",
     "signatures": [
      "(count: number, one: string, other: string): string"
     ]
    },
    {
     "name": "provideMkI18nDe",
     "description": "Provides the German strings — `MK_DE_I18N` with any `overrides`\nmerged on top (deep for `dateNames`, `blockEditor` and `validation`, like\n`provideMkI18n`).\n\n```ts\nbootstrapApplication(App, {\n  providers: [provideMkI18nDe({ noData: 'Nichts zu sehen' })],\n});\n```",
     "file": "projects/mk-kit/locales/de/de.ts",
     "kind": "function",
     "signatures": [
      "(overrides?: MkI18nOverrides): Provider"
     ]
    },
    {
     "name": "MK_DE_BLOCK_EDITOR",
     "description": "German strings of the block editor's chrome.",
     "file": "projects/mk-kit/locales/de/de.ts",
     "kind": "const",
     "type": "MkBlockEditorStrings"
    },
    {
     "name": "MK_DE_DATE_NAMES",
     "description": "German month and weekday names (Sunday-first, as in `Intl`).",
     "file": "projects/mk-kit/locales/de/de.ts",
     "kind": "const",
     "type": "MkDateNames"
    },
    {
     "name": "MK_DE_I18N",
     "description": "The complete German string map — every key of `MkI18nStrings`,\n`locale: 'de-DE'` and `currency: 'EUR'` for the formatting pipes.\nProvide it whole with `provideMkI18nDe`, or pass it as the base of\n`provideMkI18n(overrides, MK_DE_I18N)`.",
     "file": "projects/mk-kit/locales/de/de.ts",
     "kind": "const",
     "type": "MkI18nStrings"
    },
    {
     "name": "MK_DE_VALIDATION",
     "description": "German validation messages rendered by `mk-form-field`.",
     "file": "projects/mk-kit/locales/de/de.ts",
     "kind": "const",
     "type": "MkValidationStrings"
    }
   ]
  },
  {
   "name": "locales/es",
   "import": "@mk-kit/ui/locales/es",
   "exports": [
    {
     "name": "mkPluralEs",
     "description": "Picks the Spanish plural form for a count — CLDR's `es` rules for integers:\n`one` for 1, `other` for everything else.\n\n```ts\nmkPluralEs(1, 'resultado', 'resultados'); // 'resultado'\nmkPluralEs(3, 'resultado', 'resultados'); // 'resultados'\n```",
     "file": "projects/mk-kit/locales/es/es.ts",
     "kind": "function",
     "signatures": [
      "(count: number, one: string, other: string): string"
     ]
    },
    {
     "name": "provideMkI18nEs",
     "description": "Provides the Spanish strings — `MK_ES_I18N` with any `overrides`\nmerged on top (deep for `dateNames`, `blockEditor` and `validation`, like\n`provideMkI18n`).\n\n```ts\nbootstrapApplication(App, {\n  providers: [provideMkI18nEs({ noData: 'No hay nada aquí' })],\n});\n```",
     "file": "projects/mk-kit/locales/es/es.ts",
     "kind": "function",
     "signatures": [
      "(overrides?: MkI18nOverrides): Provider"
     ]
    },
    {
     "name": "MK_ES_BLOCK_EDITOR",
     "description": "Spanish strings of the block editor's chrome.",
     "file": "projects/mk-kit/locales/es/es.ts",
     "kind": "const",
     "type": "MkBlockEditorStrings"
    },
    {
     "name": "MK_ES_DATE_NAMES",
     "description": "Spanish month and weekday names (Sunday-first, lowercase as in `Intl`).",
     "file": "projects/mk-kit/locales/es/es.ts",
     "kind": "const",
     "type": "MkDateNames"
    },
    {
     "name": "MK_ES_I18N",
     "description": "The complete Spanish string map — every key of `MkI18nStrings`,\n`locale: 'es-ES'` and `currency: 'EUR'` for the formatting pipes.\nProvide it whole with `provideMkI18nEs`, or pass it as the base of\n`provideMkI18n(overrides, MK_ES_I18N)`.",
     "file": "projects/mk-kit/locales/es/es.ts",
     "kind": "const",
     "type": "MkI18nStrings"
    },
    {
     "name": "MK_ES_VALIDATION",
     "description": "Spanish validation messages rendered by `mk-form-field`.",
     "file": "projects/mk-kit/locales/es/es.ts",
     "kind": "const",
     "type": "MkValidationStrings"
    }
   ]
  },
  {
   "name": "locales/fr",
   "import": "@mk-kit/ui/locales/fr",
   "exports": [
    {
     "name": "mkPluralFr",
     "description": "Picks the French plural form for a count — CLDR's `fr` rules for integers:\n`one` for 0 and 1, `other` for everything else.\n\n```ts\nmkPluralFr(1, 'résultat', 'résultats'); // 'résultat'\nmkPluralFr(0, 'résultat', 'résultats'); // 'résultat'\nmkPluralFr(3, 'résultat', 'résultats'); // 'résultats'\n```",
     "file": "projects/mk-kit/locales/fr/fr.ts",
     "kind": "function",
     "signatures": [
      "(count: number, one: string, other: string): string"
     ]
    },
    {
     "name": "provideMkI18nFr",
     "description": "Provides the French strings — `MK_FR_I18N` with any `overrides`\nmerged on top (deep for `dateNames`, `blockEditor` and `validation`, like\n`provideMkI18n`).\n\n```ts\nbootstrapApplication(App, {\n  providers: [provideMkI18nFr({ noData: 'Rien à afficher ici' })],\n});\n```",
     "file": "projects/mk-kit/locales/fr/fr.ts",
     "kind": "function",
     "signatures": [
      "(overrides?: MkI18nOverrides): Provider"
     ]
    },
    {
     "name": "MK_FR_BLOCK_EDITOR",
     "description": "French strings of the block editor's chrome.",
     "file": "projects/mk-kit/locales/fr/fr.ts",
     "kind": "const",
     "type": "MkBlockEditorStrings"
    },
    {
     "name": "MK_FR_DATE_NAMES",
     "description": "French month and weekday names (Sunday-first, lowercase as in `Intl`).",
     "file": "projects/mk-kit/locales/fr/fr.ts",
     "kind": "const",
     "type": "MkDateNames"
    },
    {
     "name": "MK_FR_I18N",
     "description": "The complete French string map — every key of `MkI18nStrings`,\n`locale: 'fr-FR'` and `currency: 'EUR'` for the formatting pipes.\nProvide it whole with `provideMkI18nFr`, or pass it as the base of\n`provideMkI18n(overrides, MK_FR_I18N)`.",
     "file": "projects/mk-kit/locales/fr/fr.ts",
     "kind": "const",
     "type": "MkI18nStrings"
    },
    {
     "name": "MK_FR_VALIDATION",
     "description": "French validation messages rendered by `mk-form-field`.",
     "file": "projects/mk-kit/locales/fr/fr.ts",
     "kind": "const",
     "type": "MkValidationStrings"
    }
   ]
  },
  {
   "name": "locales/pl",
   "import": "@mk-kit/ui/locales/pl",
   "exports": [
    {
     "name": "mkPluralPl",
     "description": "Picks the Polish plural form for a count: `one` for 1, `few` for 2–4\n(except 12–14), `many` otherwise — CLDR's `pl` rules for integers, which is\nall the library's counts ever are.\n\n```ts\nmkPluralPl(1, 'wynik', 'wyniki', 'wyników');  // 'wynik'\nmkPluralPl(3, 'wynik', 'wyniki', 'wyników');  // 'wyniki'\nmkPluralPl(12, 'wynik', 'wyniki', 'wyników'); // 'wyników'\n```",
     "file": "projects/mk-kit/locales/pl/pl.ts",
     "kind": "function",
     "signatures": [
      "(count: number, one: string, few: string, many: string): string"
     ]
    },
    {
     "name": "provideMkI18nPl",
     "description": "Provides the Polish strings — `MK_PL_I18N` with any `overrides`\nmerged on top (deep for `dateNames`, `blockEditor` and `validation`, like\n`provideMkI18n`).\n\n```ts\nbootstrapApplication(App, {\n  providers: [provideMkI18nPl({ noData: 'Nic tu nie ma' })],\n});\n```",
     "file": "projects/mk-kit/locales/pl/pl.ts",
     "kind": "function",
     "signatures": [
      "(overrides?: MkI18nOverrides): Provider"
     ]
    },
    {
     "name": "MK_PL_BLOCK_EDITOR",
     "description": "Polish strings of the block editor's chrome.",
     "file": "projects/mk-kit/locales/pl/pl.ts",
     "kind": "const",
     "type": "MkBlockEditorStrings"
    },
    {
     "name": "MK_PL_DATE_NAMES",
     "description": "Polish month and weekday names (Sunday-first, lowercase as in `Intl`).",
     "file": "projects/mk-kit/locales/pl/pl.ts",
     "kind": "const",
     "type": "MkDateNames"
    },
    {
     "name": "MK_PL_I18N",
     "description": "The complete Polish string map — every key of `MkI18nStrings`,\n`locale: 'pl-PL'` and `currency: 'PLN'` for the formatting pipes.\nProvide it whole with `provideMkI18nPl`, or pass it as the base of\n`provideMkI18n(overrides, MK_PL_I18N)`.",
     "file": "projects/mk-kit/locales/pl/pl.ts",
     "kind": "const",
     "type": "MkI18nStrings"
    },
    {
     "name": "MK_PL_VALIDATION",
     "description": "Polish validation messages rendered by `mk-form-field`.",
     "file": "projects/mk-kit/locales/pl/pl.ts",
     "kind": "const",
     "type": "MkValidationStrings"
    }
   ]
  },
  {
   "name": "locales/uk",
   "import": "@mk-kit/ui/locales/uk",
   "exports": [
    {
     "name": "mkPluralUk",
     "description": "Picks the Ukrainian plural form for a count — CLDR's `uk` rules for\nintegers: `one` when the number ends in 1 (but not 11), `few` when it ends\nin 2–4 (but not 12–14), `many` otherwise.\n\n```ts\nmkPluralUk(1, 'результат', 'результати', 'результатів');  // 'результат'\nmkPluralUk(3, 'результат', 'результати', 'результатів');  // 'результати'\nmkPluralUk(11, 'результат', 'результати', 'результатів'); // 'результатів'\n```",
     "file": "projects/mk-kit/locales/uk/uk.ts",
     "kind": "function",
     "signatures": [
      "(count: number, one: string, few: string, many: string): string"
     ]
    },
    {
     "name": "provideMkI18nUk",
     "description": "Provides the Ukrainian strings — `MK_UK_I18N` with any `overrides`\nmerged on top (deep for `dateNames`, `blockEditor` and `validation`, like\n`provideMkI18n`).\n\n```ts\nbootstrapApplication(App, {\n  providers: [provideMkI18nUk({ noData: 'Тут нічого немає' })],\n});\n```",
     "file": "projects/mk-kit/locales/uk/uk.ts",
     "kind": "function",
     "signatures": [
      "(overrides?: MkI18nOverrides): Provider"
     ]
    },
    {
     "name": "MK_UK_BLOCK_EDITOR",
     "description": "Ukrainian strings of the block editor's chrome.",
     "file": "projects/mk-kit/locales/uk/uk.ts",
     "kind": "const",
     "type": "MkBlockEditorStrings"
    },
    {
     "name": "MK_UK_DATE_NAMES",
     "description": "Ukrainian month and weekday names (Sunday-first, lowercase as in `Intl`).",
     "file": "projects/mk-kit/locales/uk/uk.ts",
     "kind": "const",
     "type": "MkDateNames"
    },
    {
     "name": "MK_UK_I18N",
     "description": "The complete Ukrainian string map — every key of `MkI18nStrings`,\n`locale: 'uk-UA'` and `currency: 'UAH'` for the formatting pipes.\nProvide it whole with `provideMkI18nUk`, or pass it as the base of\n`provideMkI18n(overrides, MK_UK_I18N)`.",
     "file": "projects/mk-kit/locales/uk/uk.ts",
     "kind": "const",
     "type": "MkI18nStrings"
    },
    {
     "name": "MK_UK_VALIDATION",
     "description": "Ukrainian validation messages rendered by `mk-form-field`.",
     "file": "projects/mk-kit/locales/uk/uk.ts",
     "kind": "const",
     "type": "MkValidationStrings"
    }
   ]
  },
  {
   "name": "media/scanner",
   "import": "@mk-kit/ui/media/scanner",
   "exports": [
    {
     "name": "MkBarcodeScanner",
     "description": "Camera barcode / QR reader. Starts the rear camera when it appears, emits\n`scanned` once with the first decoded text and stops. The decoder\n(`html5-qrcode`, an optional peer dependency) is loaded on demand, so pages\nthat only *offer* scanning ship nothing extra until a scan starts. Use\ninline, or through `MkBarcodeScannerDialog`.\n\n```html\n<mk-barcode-scanner (scanned)=\"onCode($event)\" (failed)=\"show($event)\" />\n```",
     "file": "projects/mk-kit/media/scanner/barcode-scanner.ts",
     "kind": "component",
     "selector": "mk-barcode-scanner",
     "selectors": [
      "mk-barcode-scanner"
     ],
     "inputs": [
      {
       "name": "formats",
       "type": "MkBarcodeFormat[]",
       "description": "Symbologies to decode. Default: QR + the retail 1-D codes.",
       "default": "MK_BARCODE_DEFAULT_FORMATS"
      },
      {
       "name": "fps",
       "type": "number",
       "description": "Frames per second offered to the decoder. Default 10.",
       "default": "10"
      },
      {
       "name": "hint",
       "type": "boolean",
       "description": "Show the built-in hint line above the viewfinder. Default `true`.",
       "default": "true"
      },
      {
       "name": "continuous",
       "type": "boolean",
       "description": "Keep scanning after a hit instead of stopping. Default `false`.",
       "default": "false"
      }
     ],
     "outputs": [
      {
       "name": "scanned",
       "type": "string",
       "description": "Decoded text."
      },
      {
       "name": "failed",
       "type": "string",
       "description": "The camera could not start (permission, no device, insecure context)."
      }
     ],
     "methods": [
      {
       "name": "stop",
       "signature": "(): Promise<void>",
       "description": "Stop the camera and release it. Safe to call twice."
      }
     ],
     "properties": [],
     "queries": [],
     "docs": "/components/images"
    },
    {
     "name": "MkBarcodeScannerDialog",
     "description": "The scanner in a dialog: resolves with the decoded text, or `null` when\ncancelled. Open it with `MkDialogService`:\n\n```ts\nconst code = await dialog.open<MkBarcodeScannerDialog, string | null>(MkBarcodeScannerDialog, { size: 'sm' }).afterClosed;\nif (code) this.search.setValue(code);\n```",
     "file": "projects/mk-kit/media/scanner/barcode-scanner-dialog.ts",
     "kind": "component",
     "selector": "mk-barcode-scanner-dialog",
     "selectors": [
      "mk-barcode-scanner-dialog"
     ],
     "inputs": [],
     "outputs": [],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/images"
    },
    {
     "name": "MK_BARCODE_DEFAULT_FORMATS",
     "description": "",
     "file": "projects/mk-kit/media/scanner/barcode-scanner.ts",
     "kind": "const",
     "type": "MkBarcodeFormat[]"
    },
    {
     "name": "MkBarcodeScannerDialogData",
     "description": "Optional data for `MkBarcodeScannerDialog`.",
     "file": "projects/mk-kit/media/scanner/barcode-scanner-dialog.ts",
     "kind": "interface",
     "members": [
      {
       "name": "title",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "formats",
       "type": "MkBarcodeFormat[] | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkBarcodeFormat",
     "description": "Symbologies the scanner reads; names follow `Html5QrcodeSupportedFormats`.",
     "file": "projects/mk-kit/media/scanner/barcode-scanner.ts",
     "kind": "type",
     "definition": "| 'QR_CODE' | 'EAN_13' | 'EAN_8' | 'CODE_128' | 'CODE_39' | 'UPC_A' | 'UPC_E' | 'DATA_MATRIX' | 'ITF' | 'CODABAR'"
    }
   ]
  },
  {
   "name": "testing",
   "import": "@mk-kit/ui/testing",
   "exports": [
    {
     "name": "MkButtonHarness",
     "description": "`button[mkButton]` / `a[mkButton]`.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "text",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "click",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "focus",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isLoading",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "tone",
       "signature": "(): string | null",
       "description": ""
      },
      {
       "name": "variant",
       "signature": "(): string | null",
       "description": "`solid` | `soft` | `outline` | `ghost` | `link`."
      },
      {
       "name": "size",
       "signature": "(): string | null",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "MkCheckboxHarness",
     "description": "`mk-checkbox`.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "label",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "isChecked",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isIndeterminate",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isRequired",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "toggle",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "check",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "uncheck",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "focus",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "blur",
       "signature": "(): Promise<void>",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "MkDialogHarness",
     "description": "A dialog opened by `MkDialogService` (`open()`, `confirm()`, `alert()`,\n`prompt()`). Dialogs live in `document.body`, so look them up through\n`loader.document()`.",
     "file": "projects/mk-kit/testing/harnesses/overlays.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "title",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "bodyText",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "buttons",
       "signature": "(): string[]",
       "description": "Texts of every button in the dialog (header close excluded)."
      },
      {
       "name": "clickButton",
       "signature": "(which: number | string | RegExp): Promise<void>",
       "description": "Click a button by index, exact text or RegExp."
      },
      {
       "name": "close",
       "signature": "(): Promise<void>",
       "description": "The header × button."
      },
      {
       "name": "pressEscape",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "input",
       "signature": "(): MkTestElement | null",
       "description": "The prompt dialog's text field, if any."
      }
     ],
     "properties": []
    },
    {
     "name": "MkFormFieldHarness",
     "description": "`mk-form-field` — label / hint / error around any control.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "label",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "hint",
       "signature": "(): string | null",
       "description": ""
      },
      {
       "name": "error",
       "signature": "(): string | null",
       "description": "The visible validation message, or `null` when the field is valid/untouched."
      },
      {
       "name": "hasError",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isRequired",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "control",
       "signature": "<T extends MkHarness>(type: Parameters<typeof this.loader.get<T>>[0]): Promise<T>",
       "description": "The control inside the field, as a harness of the given type."
      }
     ],
     "properties": []
    },
    {
     "name": "MkHarness",
     "description": "Base class of every mk-kit harness. Subclasses declare `hostSelector`\nand expose user-level actions (`click()`, `selectOption()`, …) and reads\n(`isChecked()`, `text()`), so specs never depend on the component's DOM.",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "class",
     "methods": [],
     "properties": []
    },
    {
     "name": "MkHarnessLoader",
     "description": "Finds harnesses under a root element. Create one with\n`MkHarnessLoader.fromFixture(fixture)`; use `.document()` for content that\nmk-kit teleports into `document.body` (dialogs, toasts, menus, select\npanels) and `.within(el)` to scope lookups.",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "document",
       "signature": "(): MkHarnessLoader",
       "description": "Same settle function, rooted at `document.body` — for overlays."
      },
      {
       "name": "within",
       "signature": "(root: Element | MkTestElement): MkHarnessLoader",
       "description": ""
      },
      {
       "name": "rootElement",
       "signature": "(): MkTestElement",
       "description": "Wrap the root element itself."
      },
      {
       "name": "element",
       "signature": "(selector: string): MkTestElement",
       "description": ""
      },
      {
       "name": "elements",
       "signature": "(selector: string): MkTestElement[]",
       "description": ""
      },
      {
       "name": "get",
       "signature": "<T extends MkHarness>(type: MkHarnessType<T>, filters?: MkHarnessFilters): Promise<T>",
       "description": "First matching harness; throws when there is none. Retries for a short\nwhile first: overlays such as `MkDialogService.prompt()` render after a\nlazy chunk resolves, so the host may appear a few ticks after the call.\n`has()` / `getOrNull()` stay immediate so absence can be asserted."
      },
      {
       "name": "getOrNull",
       "signature": "<T extends MkHarness>(type: MkHarnessType<T>, filters?: MkHarnessFilters): Promise<T | null>",
       "description": ""
      },
      {
       "name": "has",
       "signature": "<T extends MkHarness>(type: MkHarnessType<T>, filters?: MkHarnessFilters): Promise<boolean>",
       "description": ""
      },
      {
       "name": "getAll",
       "signature": "<T extends MkHarness>(type: MkHarnessType<T>, filters?: MkHarnessFilters): Promise<T[]>",
       "description": ""
      }
     ],
     "properties": [],
     "docs": "/testing"
    },
    {
     "name": "MkInputHarness",
     "description": "Native `input[mkInput]` / `textarea[mkInput]`.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "value",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "setValue",
       "signature": "(value: string): Promise<void>",
       "description": "Replace the value (fires `input` + `change`)."
      },
      {
       "name": "type",
       "signature": "(text: string): Promise<void>",
       "description": "Append text one character at a time (keydown / input / keyup)."
      },
      {
       "name": "clear",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "focus",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "blur",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "placeholder",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "type_",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isInvalid",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isRequired",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isFocused",
       "signature": "(): boolean",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "MkMenuHarness",
     "description": "A `[mkMenuTriggerFor]` trigger and the `mk-menu` panel it opens. The host\nis matched by the trigger's `aria-haspopup=\"menu\"` (the directive's\nattribute is an input binding, so it is not in the DOM).",
     "file": "projects/mk-kit/testing/harnesses/navigation.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "isOpen",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "open",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "close",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "panel",
       "signature": "(): MkTestElement | null",
       "description": "The teleported panel (`[role=\"menu\"]`), or `null` while closed."
      },
      {
       "name": "items",
       "signature": "(): Promise<string[]>",
       "description": "Item texts of the open menu (opens it if needed). Submenu panels excluded."
      },
      {
       "name": "clickItem",
       "signature": "(which: number | string | RegExp): Promise<void>",
       "description": "Click an item by index, exact text or RegExp (opens the menu first)."
      },
      {
       "name": "isItemDisabled",
       "signature": "(which: number | string | RegExp): Promise<boolean>",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "MkRadioGroupHarness",
     "description": "`mk-radio-group`.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "radios",
       "signature": "(): Promise<MkRadioHarness[]>",
       "description": ""
      },
      {
       "name": "labels",
       "signature": "(): Promise<string[]>",
       "description": ""
      },
      {
       "name": "checkedLabel",
       "signature": "(): Promise<string | null>",
       "description": "Label of the checked radio, or `null`."
      },
      {
       "name": "checkedIndex",
       "signature": "(): Promise<number>",
       "description": ""
      },
      {
       "name": "select",
       "signature": "(which: number | string | RegExp): Promise<void>",
       "description": "Select by index, exact label or RegExp."
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "MkRadioHarness",
     "description": "One `mk-radio` inside a group.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "label",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "isChecked",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "select",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "focus",
       "signature": "(): Promise<void>",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "MkSelectHarness",
     "description": "`mk-select` — opens the teleported listbox and picks options like a user.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "valueText",
       "signature": "(): string",
       "description": "Label of the selected option, or `''` when only the placeholder shows."
      },
      {
       "name": "placeholder",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "isOpen",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isInvalid",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "open",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "close",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "focus",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "options",
       "signature": "(): Promise<MkSelectOptionState[]>",
       "description": "Options of the (opened) listbox. Opens it if needed."
      },
      {
       "name": "selectOption",
       "signature": "(which: number | string | RegExp): Promise<void>",
       "description": "Pick an option by index, exact label or RegExp (opens the list first)."
      }
     ],
     "properties": []
    },
    {
     "name": "MkSwitchHarness",
     "description": "`mk-switch`.",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "label",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "isChecked",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "toggle",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "check",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "uncheck",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "focus",
       "signature": "(): Promise<void>",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "MkTableHarness",
     "description": "`mk-table`.",
     "file": "projects/mk-kit/testing/harnesses/table.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "headers",
       "signature": "(): string[]",
       "description": "Header labels of the data columns, in display order."
      },
      {
       "name": "rows",
       "signature": "(): Promise<MkTableRowHarness[]>",
       "description": ""
      },
      {
       "name": "rowCount",
       "signature": "(): Promise<number>",
       "description": ""
      },
      {
       "name": "cellTexts",
       "signature": "(): Promise<string[][]>",
       "description": "Every data cell as text: `rows()[r].cells()`."
      },
      {
       "name": "sortBy",
       "signature": "(which: number | string | RegExp): Promise<void>",
       "description": "Click a sortable header (by index, exact label or RegExp)."
      },
      {
       "name": "sortDirection",
       "signature": "(which: number | string | RegExp): string | null",
       "description": "`'ascending' | 'descending' | 'none' | null` (null = not sortable)."
      },
      {
       "name": "selectedRowCount",
       "signature": "(): Promise<number>",
       "description": ""
      },
      {
       "name": "toggleAll",
       "signature": "(): Promise<void>",
       "description": "Toggle the header \"select all\" checkbox."
      },
      {
       "name": "isEmpty",
       "signature": "(): boolean",
       "description": "True when the table shows no data rows (an `emptyMessage` row does not count)."
      },
      {
       "name": "emptyMessage",
       "signature": "(): string | null",
       "description": "The rendered `emptyMessage`, or `null` while the table has rows."
      },
      {
       "name": "setFilter",
       "signature": "(key: string, value: string): Promise<void>",
       "description": "Set a header-row filter (table is `filterable`). `value` is typed into\na text / number / date box, or picked from a select by option label or\nvalue; `''` clears that filter."
      },
      {
       "name": "filterValue",
       "signature": "(key: string): string",
       "description": "The current value of a header-row filter control (`''` when unset)."
      },
      {
       "name": "clearFilters",
       "signature": "(): Promise<void>",
       "description": "Clear every header-row filter."
      },
      {
       "name": "scrollToRow",
       "signature": "(index: number): Promise<void>",
       "description": "Scroll a `virtual` table so the row at display `index` is at the top of\nthe viewport (drives the scroll box, so only the rows around it render)."
      }
     ],
     "properties": []
    },
    {
     "name": "MkTableRowHarness",
     "description": "One data row of `mk-table` (the `emptyMessage` placeholder row is not one).",
     "file": "projects/mk-kit/testing/harnesses/table.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "cells",
       "signature": "(): string[]",
       "description": "Cell texts of the data columns (expand / select cells excluded)."
      },
      {
       "name": "cell",
       "signature": "(index: number): string",
       "description": ""
      },
      {
       "name": "isSelected",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isExpanded",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "click",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "toggleSelected",
       "signature": "(): Promise<void>",
       "description": "Toggle the selection checkbox (throws when the table is not `selectable`)."
      },
      {
       "name": "toggleExpanded",
       "signature": "(): Promise<void>",
       "description": "Toggle the expand / tree control of the row."
      }
     ],
     "properties": []
    },
    {
     "name": "MkTabsHarness",
     "description": "`mk-tabs`.",
     "file": "projects/mk-kit/testing/harnesses/navigation.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "labels",
       "signature": "(): string[]",
       "description": ""
      },
      {
       "name": "selectedIndex",
       "signature": "(): number",
       "description": ""
      },
      {
       "name": "selectedLabel",
       "signature": "(): string | null",
       "description": ""
      },
      {
       "name": "select",
       "signature": "(which: number | string | RegExp): Promise<void>",
       "description": "Select by index, exact label or RegExp."
      },
      {
       "name": "isDisabled",
       "signature": "(which: number | string | RegExp): boolean",
       "description": ""
      },
      {
       "name": "selectedPanel",
       "signature": "(): MkTestElement | null",
       "description": "The visible tab panel (`mk-tab` host)."
      },
      {
       "name": "selectedPanelText",
       "signature": "(): string",
       "description": "Text of the visible panel."
      }
     ],
     "properties": []
    },
    {
     "name": "MkTestElement",
     "description": "A DOM element wrapped for tests: reads are synchronous, every interaction\ndispatches the same events a user would and then settles change detection\n(`fixture.detectChanges()` + `whenStable()`), so the next read sees the\nupdated view.",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "text",
       "signature": "(): string",
       "description": "Trimmed text content with whitespace collapsed."
      },
      {
       "name": "attr",
       "signature": "(name: string): string | null",
       "description": ""
      },
      {
       "name": "hasClass",
       "signature": "(name: string): boolean",
       "description": ""
      },
      {
       "name": "prop",
       "signature": "<T = unknown>(name: string): T",
       "description": "Read a DOM property (`value`, `checked`, `open`, …)."
      },
      {
       "name": "matches",
       "signature": "(selector: string): boolean",
       "description": ""
      },
      {
       "name": "isFocused",
       "signature": "(): boolean",
       "description": ""
      },
      {
       "name": "isDisabled",
       "signature": "(): boolean",
       "description": "Native `disabled`, `aria-disabled=\"true\"` or a `--disabled` host class."
      },
      {
       "name": "query",
       "signature": "(selector: string): MkTestElement | null",
       "description": ""
      },
      {
       "name": "queryAll",
       "signature": "(selector: string): MkTestElement[]",
       "description": ""
      },
      {
       "name": "child",
       "signature": "(selector: string): MkTestElement",
       "description": "Like `query`, but throws a readable error when nothing matches."
      },
      {
       "name": "click",
       "signature": "(): Promise<void>",
       "description": "pointerdown → mousedown → focus → pointerup → mouseup → click, like a user."
      },
      {
       "name": "hover",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "leave",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "focus",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "blur",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "type",
       "signature": "(text: string): Promise<void>",
       "description": "Type into an input/textarea/contenteditable character by character —\nkeydown, `value` append, `input`, keyup — then settle. Use `setValue`\nto replace the value in one go."
      },
      {
       "name": "setValue",
       "signature": "(value: string): Promise<void>",
       "description": "Set the value of an input/textarea/select and fire `input` + `change`."
      },
      {
       "name": "clear",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "sendKeys",
       "signature": "(...keys: Array<MkTestKey | (string & {})>): Promise<void>",
       "description": "Dispatch keydown/keyup for each key. Printable single characters are also typed."
      },
      {
       "name": "dispatch",
       "signature": "(event: Event): Promise<void>",
       "description": "Dispatch any event on the element and settle."
      }
     ],
     "properties": []
    },
    {
     "name": "MkToastHarness",
     "description": "One toast shown by `MkToastService` (lives in `document.body` — use `loader.document()`).",
     "file": "projects/mk-kit/testing/harnesses/overlays.harness.ts",
     "kind": "class",
     "methods": [
      {
       "name": "title",
       "signature": "(): string | null",
       "description": ""
      },
      {
       "name": "message",
       "signature": "(): string",
       "description": ""
      },
      {
       "name": "tone",
       "signature": "(): string | null",
       "description": ""
      },
      {
       "name": "actionLabel",
       "signature": "(): string | null",
       "description": ""
      },
      {
       "name": "clickAction",
       "signature": "(): Promise<void>",
       "description": ""
      },
      {
       "name": "dismiss",
       "signature": "(): Promise<void>",
       "description": ""
      }
     ],
     "properties": []
    },
    {
     "name": "matchText",
     "description": "",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "function",
     "signatures": [
      "(actual: string, expected: string | RegExp): boolean"
     ]
    },
    {
     "name": "pickBy",
     "description": "Resolve \"by index or by label\" arguments shared by option-style harnesses.",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "function",
     "signatures": [
      "<T>(items: T[], which: number | string | RegExp, label: (item: T) => string, what: string): T"
     ]
    },
    {
     "name": "MkHarnessFilters",
     "description": "Filters every harness lookup accepts. `selector` narrows the host elements\nconsidered (e.g. a class or attribute your template sets); `text` matches\nthe host's trimmed text content — a string must match exactly, a RegExp\nis tested.",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "interface",
     "members": [
      {
       "name": "selector",
       "type": "string | undefined",
       "description": "",
       "optional": true
      },
      {
       "name": "text",
       "type": "string | RegExp | undefined",
       "description": "",
       "optional": true
      }
     ]
    },
    {
     "name": "MkHarnessType",
     "description": "Constructor shape of every harness class: a static `hostSelector`.",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "interface",
     "typeParams": "<T extends MkHarness>",
     "members": [
      {
       "name": "hostSelector",
       "type": "string",
       "description": "",
       "readonly": true
      }
     ]
    },
    {
     "name": "MkSelectOptionState",
     "description": "",
     "file": "projects/mk-kit/testing/harnesses/form-controls.harness.ts",
     "kind": "interface",
     "members": [
      {
       "name": "label",
       "type": "string",
       "description": ""
      },
      {
       "name": "selected",
       "type": "boolean",
       "description": ""
      },
      {
       "name": "disabled",
       "type": "boolean",
       "description": ""
      }
     ]
    },
    {
     "name": "MkTestKey",
     "description": "Keys accepted by `MkTestElement.sendKeys` besides printable characters.",
     "file": "projects/mk-kit/testing/harness.ts",
     "kind": "type",
     "definition": "| 'Enter' | 'Escape' | 'Tab' | 'Backspace' | 'Delete' | ' ' | 'ArrowUp' | 'ArrowDown' | 'ArrowLeft' | 'ArrowRight' | 'Home' | 'End' | 'PageUp' | 'PageDown'"
    }
   ]
  },
  {
   "name": "translate/editor",
   "import": "@mk-kit/ui/translate/editor",
   "exports": [
    {
     "name": "MkTranslationEditor",
     "description": "Translation editor — keys as rows, locales as columns, click a cell to\nedit. The base strings are your bundled files; edits are **overrides**\nkept apart from them, so a rebuild never loses them and a cell can be\nrestored to the file text. Search by key or text, filter to the keys a\nlocale is missing or the ones already edited, export the grid as CSV.\nPersistence is yours: every edit is emitted as `changed`, feed the result\nback through `overrides`.\n\n```html\n<mk-translation-editor\n  [locales]=\"['pl', 'en', 'ru']\"\n  [base]=\"base()\"\n  [overrides]=\"overrides()\"\n  (changed)=\"save($event)\" />\n```",
     "file": "projects/mk-kit/translate/editor/translation-editor.ts",
     "kind": "component",
     "selector": "mk-translation-editor",
     "selectors": [
      "mk-translation-editor"
     ],
     "inputs": [
      {
       "name": "locales",
       "type": "string[]",
       "description": "Locale codes, in column order. The first one is the reference language.",
       "required": true
      },
      {
       "name": "base",
       "type": "Record<string, MkFlatTranslations>",
       "description": "Bundled strings per locale, flat (`'a.b.c': 'text'`) or nested.",
       "required": true
      },
      {
       "name": "overrides",
       "type": "Record<string, MkFlatTranslations>",
       "description": "Edits per locale, flat. Missing locales are fine.",
       "default": "{}"
      },
      {
       "name": "readonly",
       "type": "boolean",
       "description": "Show but do not edit.",
       "default": "false"
      },
      {
       "name": "exportFilename",
       "type": "string",
       "description": "File name of the CSV export.",
       "default": "'translations.csv'"
      }
     ],
     "outputs": [
      {
       "name": "changed",
       "type": "MkTranslationChange",
       "description": "An edit or a restore; persist it and update `overrides`."
      }
     ],
     "methods": [],
     "properties": [],
     "queries": [],
     "docs": "/components/translate"
    },
    {
     "name": "MkTranslationChange",
     "description": "One edit made in the editor. `value: null` clears the override.",
     "file": "projects/mk-kit/translate/editor/translation-editor.ts",
     "kind": "interface",
     "members": [
      {
       "name": "locale",
       "type": "string",
       "description": ""
      },
      {
       "name": "key",
       "type": "string",
       "description": ""
      },
      {
       "name": "value",
       "type": "string | null",
       "description": ""
      },
      {
       "name": "previous",
       "type": "string | null",
       "description": "The text shown before the edit (override, or the base string)."
      }
     ]
    },
    {
     "name": "MkTranslationRow",
     "description": "A row of the editor: the key plus the effective text per locale.",
     "file": "projects/mk-kit/translate/editor/translation-editor.ts",
     "kind": "interface",
     "members": [
      {
       "name": "key",
       "type": "string",
       "description": ""
      }
     ]
    }
   ]
  },
  {
   "name": "translate/server",
   "import": "@mk-kit/ui/translate/server",
   "exports": [
    {
     "name": "mkFsTranslateLoader",
     "description": "Server-side loader that reads the translation JSON from disk instead of\nfetching the app's own HTTP endpoint during SSR — no self-request, no\nproxy hop, no interceptor ordering to get right. Register it in the\nserver config only (`app.config.server.ts`); the browser keeps\n`mkHttpTranslateLoader`. Files are parsed once per process.\n\n```ts\n// app.config.server.ts\nprovideMkTranslate({\n  ...browserTranslateConfig,\n  loader: mkFsTranslateLoader({\n    dirs: [join(import.meta.dirname, '../browser/assets/i18n'), join(process.cwd(), 'src/assets/i18n')],\n  }),\n})\n```",
     "file": "projects/mk-kit/translate/server/fs-loader.ts",
     "kind": "function",
     "signatures": [
      "(options: MkFsTranslateLoaderOptions): MkTranslateLoaderFactory"
     ]
    },
    {
     "name": "MkFsTranslateLoaderOptions",
     "description": "Options for `mkFsTranslateLoader`.",
     "file": "projects/mk-kit/translate/server/fs-loader.ts",
     "kind": "interface",
     "members": [
      {
       "name": "dirs",
       "type": "string[]",
       "description": "Directories searched in order for `<lang><suffix>`; the first readable\nfile wins. Typical: the built browser assets next to the server bundle,\nthen the source tree for `ng serve`."
      },
      {
       "name": "suffix",
       "type": "string | undefined",
       "description": "File suffix after the language code. Default `.json`.",
       "optional": true
      },
      {
       "name": "onNotFound",
       "type": "\"empty\" | \"throw\" | undefined",
       "description": "When no directory has the file: return `{}` (default) so the app boots\nwith keys as text, or throw so the failure surfaces at once.",
       "optional": true
      }
     ]
    }
   ]
  }
 ]
}
