@mk-kit/ui 0.52.1 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mk-kit-ui-status.mjs","sources":["../../../projects/mk-kit/status/spinner/spinner.ts","../../../projects/mk-kit/status/spinner/spinner.html","../../../projects/mk-kit/status/badge/badge.ts","../../../projects/mk-kit/status/badge/badge.html","../../../projects/mk-kit/status/badge/badge-overlay.ts","../../../projects/mk-kit/status/empty-state/empty-state.ts","../../../projects/mk-kit/status/empty-state/empty-state.html","../../../projects/mk-kit/status/index.ts","../../../projects/mk-kit/status/mk-kit-ui-status.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, input } from '@angular/core';\nimport { MK_I18N } from '@mk-kit/ui/core';\nimport type { MkSize, MkTone } from '@mk-kit/ui/core';\n\n/**\n * Spinner — a circular indeterminate loading indicator. Exposes `role=\"status\"`\n * with a visually-hidden label so assistive tech announces the loading state.\n * The animation slows under `prefers-reduced-motion`.\n *\n * ```html\n * <mk-spinner />\n * <mk-spinner size=\"lg\" tone=\"neutral\" label=\"Fetching results\" />\n * ```\n */\n@Component({\n selector: 'mk-spinner',\n templateUrl: './spinner.html',\n styleUrl: './spinner.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'mk-spinner',\n role: 'status',\n '[class.mk-spinner--sm]': \"size() === 'sm'\",\n '[class.mk-spinner--md]': \"size() === 'md'\",\n '[class.mk-spinner--lg]': \"size() === 'lg'\",\n '[attr.data-tone]': 'tone()',\n },\n})\nexport class MkSpinner {\n protected readonly i18n = inject(MK_I18N);\n\n /** Size scale. */\n readonly size = input<MkSize>('md');\n /** Semantic color tone. */\n readonly tone = input<MkTone>('primary');\n /** Visually-hidden status label announced to screen readers. */\n readonly label = input(this.i18n.loading);\n}\n","<span class=\"mk-spinner__circle\" aria-hidden=\"true\"></span>\n<span class=\"mk-spinner__sr\">{{ label() }}</span>\n","import {\n ChangeDetectionStrategy,\n Component,\n booleanAttribute,\n input,\n} from '@angular/core';\nimport type { MkSize, MkTone } from '@mk-kit/ui/core';\n\n/** Visual treatment for a {@link MkBadge}. */\nexport type MkBadgeVariant = 'solid' | 'soft' | 'outline';\n\n/**\n * Badge — a compact status pill, typically for counts or short state labels.\n * Set `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 * ```\n */\n@Component({\n selector: 'mk-badge',\n templateUrl: './badge.html',\n styleUrl: './badge.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'mk-badge',\n '[class.mk-badge--sm]': \"size() === 'sm'\",\n '[class.mk-badge--md]': \"size() === 'md'\",\n '[class.mk-badge--lg]': \"size() === 'lg'\",\n '[class.mk-badge--solid]': \"variant() === 'solid'\",\n '[class.mk-badge--soft]': \"variant() === 'soft'\",\n '[class.mk-badge--outline]': \"variant() === 'outline'\",\n '[class.mk-badge--dot]': 'dot()',\n '[attr.data-tone]': 'tone()',\n },\n})\nexport class MkBadge {\n /** Semantic color tone. */\n readonly tone = input<MkTone>('primary');\n /** Visual treatment. */\n readonly variant = input<MkBadgeVariant>('soft');\n /** Size scale. */\n readonly size = input<MkSize>('md');\n /** Render as a tiny dot (no text) for notification indicators. */\n readonly dot = input(false, { transform: booleanAttribute });\n}\n","@if (!dot()) {\n <ng-content />\n}\n","import {\n DOCUMENT,\n Directive,\n ElementRef,\n PLATFORM_ID,\n Renderer2,\n booleanAttribute,\n computed,\n effect,\n inject,\n input,\n numberAttribute,\n} from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { mkUniqueId, type MkTone } from '@mk-kit/ui/core';\n\n/** Corner of the host an {@link MkBadgeOverlay} is anchored to. */\nexport type MkBadgeOverlayPosition =\n | 'top-end'\n | 'top-start'\n | 'bottom-end'\n | 'bottom-start';\n\n/**\n * Badge overlay — anchors a small badge (count, dot or short text) to a corner\n * of ANY element: an icon button, an avatar, a tab label. The host stays a\n * single 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 *\n * The 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 * ```\n */\n@Directive({\n selector: '[mkBadgeOverlay]',\n})\nexport class MkBadgeOverlay {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly document = inject(DOCUMENT);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /**\n * Badge content — a count or a short label. `null` / empty hides the badge\n * unless `mkBadgeOverlayDot` is set. Numeric strings are treated as numbers\n * so `mkBadgeOverlay=\"120\"` also collapses to `99+`.\n */\n readonly content = input<string | number | null | undefined>(null, {\n alias: 'mkBadgeOverlay',\n });\n /** Corner the badge is anchored to (logical: `end` flips in RTL). */\n readonly position = input<MkBadgeOverlayPosition>('top-end', {\n alias: 'mkBadgeOverlayPosition',\n });\n /** Semantic color tone (same scale as `mk-badge`). */\n readonly tone = input<MkTone>('primary', { alias: 'mkBadgeOverlayTone' });\n /** Render a textless dot instead of the content. */\n readonly dot = input(false, {\n alias: 'mkBadgeOverlayDot',\n transform: booleanAttribute,\n });\n /** Numbers above this render as `<max>+`. `0` disables the cap. */\n readonly max = input(99, {\n alias: 'mkBadgeOverlayMax',\n transform: numberAttribute,\n });\n /** Hide the badge while keeping the directive (and its aria wiring) in place. */\n readonly hidden = input(false, {\n alias: 'mkBadgeOverlayHidden',\n transform: booleanAttribute,\n });\n /**\n * Screen-reader text for the badge, e.g. `\"3 unread\"`. Announced as the\n * host's description; the visible badge becomes `aria-hidden`.\n */\n readonly ariaLabel = input<string>('', { alias: 'mkBadgeOverlayAriaLabel' });\n\n /** The text painted in the badge (`''` in dot mode). */\n readonly label = computed<string>(() => {\n if (this.dot()) return '';\n const raw = this.content();\n if (raw === null || raw === undefined || raw === '') return '';\n const max = this.max();\n const n =\n typeof raw === 'number' ? raw : /^\\d+$/.test(raw) ? Number(raw) : NaN;\n if (Number.isFinite(n) && max > 0 && n > max) return `${max}+`;\n return String(raw);\n });\n\n /** Whether the badge is currently rendered. */\n readonly visible = computed(\n () => !this.hidden() && (this.dot() || this.label() !== ''),\n );\n\n private readonly srId = mkUniqueId('mk-badge-overlay');\n private badge: HTMLElement | null = null;\n private sr: HTMLElement | null = null;\n /** Set when WE made the host positioned, so we can undo it on removal. */\n private positionedHost = false;\n\n constructor() {\n if (!this.isBrowser) return;\n\n effect(() => {\n const visible = this.visible();\n if (!visible) {\n this.detach();\n return;\n }\n const badge = this.attach();\n const dot = this.dot();\n const srText = this.ariaLabel().trim();\n\n this.renderer.setAttribute(badge, 'data-tone', this.tone());\n this.renderer.setAttribute(badge, 'data-position', this.position());\n if (dot) {\n this.renderer.addClass(badge, 'mk-badge-overlay--dot');\n } else {\n this.renderer.removeClass(badge, 'mk-badge-overlay--dot');\n }\n this.renderer.setProperty(badge, 'textContent', this.label());\n // A dot has nothing to read; a labelled badge is described via the\n // hidden span instead — either way the visual is hidden from AT.\n if (dot || srText) {\n this.renderer.setAttribute(badge, 'aria-hidden', 'true');\n } else {\n this.renderer.removeAttribute(badge, 'aria-hidden');\n }\n this.syncSr(srText);\n });\n }\n\n private attach(): HTMLElement {\n if (this.badge) return this.badge;\n const el = this.host.nativeElement;\n const view = this.document.defaultView;\n const position = view?.getComputedStyle(el).position;\n if (!position || position === 'static') {\n this.renderer.setStyle(el, 'position', 'relative');\n this.positionedHost = true;\n }\n const badge: HTMLElement = this.renderer.createElement('span');\n this.renderer.addClass(badge, 'mk-badge-overlay');\n this.renderer.appendChild(el, badge);\n this.badge = badge;\n return badge;\n }\n\n private detach(): void {\n if (this.badge) {\n this.renderer.removeChild(this.host.nativeElement, this.badge);\n this.badge = null;\n }\n this.syncSr('');\n if (this.positionedHost) {\n this.renderer.removeStyle(this.host.nativeElement, 'position');\n this.positionedHost = false;\n }\n }\n\n /** Create / update / remove the hidden description and its aria-describedby link. */\n private syncSr(text: string): void {\n const el = this.host.nativeElement;\n if (text) {\n if (!this.sr) {\n const sr: HTMLElement = this.renderer.createElement('span');\n this.renderer.addClass(sr, 'mk-visually-hidden');\n this.renderer.setAttribute(sr, 'id', this.srId);\n this.renderer.appendChild(el, sr);\n this.sr = sr;\n const ids = (el.getAttribute('aria-describedby') ?? '').split(/\\s+/).filter(Boolean);\n if (!ids.includes(this.srId)) ids.push(this.srId);\n this.renderer.setAttribute(el, 'aria-describedby', ids.join(' '));\n }\n this.renderer.setProperty(this.sr, 'textContent', text);\n } else if (this.sr) {\n this.renderer.removeChild(el, this.sr);\n this.sr = null;\n const ids = (el.getAttribute('aria-describedby') ?? '')\n .split(/\\s+/)\n .filter((id) => id && id !== this.srId);\n if (ids.length) {\n this.renderer.setAttribute(el, 'aria-describedby', ids.join(' '));\n } else {\n this.renderer.removeAttribute(el, 'aria-describedby');\n }\n }\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n input,\n} from '@angular/core';\nimport type { MkSize } from '@mk-kit/ui/core';\nimport { MkIcon } from '@mk-kit/ui/icon';\n\n/**\n * EmptyState — a centered placeholder for \"nothing here yet\" situations: empty\n * tables, no search results, a fresh dashboard, a cleared inbox. Provide a\n * `title` (and usually a `description`), an `icon` or projected media, and\n * call-to-action buttons via the actions slot.\n *\n * Slots: `[mkEmptyStateMedia]` (custom illustration, overrides `icon`), default\n * content (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 * ```\n */\n@Component({\n selector: 'mk-empty-state',\n templateUrl: './empty-state.html',\n styleUrl: './empty-state.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [MkIcon],\n host: {\n class: 'mk-empty-state',\n '[class.mk-empty-state--sm]': \"size() === 'sm'\",\n '[class.mk-empty-state--lg]': \"size() === 'lg'\",\n },\n})\nexport class MkEmptyState {\n /** Name of a registered icon shown above the title (ignored if media is projected). */\n readonly icon = input<string>('');\n /** Main heading, e.g. \"No invoices yet\". */\n readonly title = input<string>('');\n /** Supporting sentence under the title. */\n readonly description = input<string>('');\n /** Overall scale of the block. */\n readonly size = input<MkSize>('md');\n\n protected readonly iconSize = () =>\n this.size() === 'sm' ? 28 : this.size() === 'lg' ? 48 : 36;\n}\n","@if (icon()) {\n <span class=\"mk-empty-state__icon\" aria-hidden=\"true\">\n <mk-icon [name]=\"icon()\" [size]=\"iconSize()\" />\n </span>\n}\n<ng-content select=\"[mkEmptyStateMedia]\" />\n\n@if (title()) {\n <p class=\"mk-empty-state__title\">{{ title() }}</p>\n}\n@if (description()) {\n <p class=\"mk-empty-state__description\">{{ description() }}</p>\n}\n\n<ng-content />\n\n<div class=\"mk-empty-state__actions\">\n <ng-content select=\"[mkEmptyStateActions]\" />\n</div>\n","/**\n * @mk-kit/ui/status — the small status indicators every other group leans on:\n * spinner, badge (+ overlay) and empty state. They lived in `@mk-kit/ui/data`\n * until 0.53; that entry still re-exports them, but `feedback` imports them\n * from here so a dialog or toast service no longer drags the whole data group\n * (charts, viewers, kanban → dnd) into an app's initial bundle.\n */\nexport * from './spinner';\nexport * from './badge';\nexport * from './empty-state';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -2181,6 +2181,15 @@ class MkTableDataSource {
2181
2181
  refresh() {
2182
2182
  this.load();
2183
2183
  }
2184
+ /**
2185
+ * Back to page 1 and load — the "filters changed outside the search box"
2186
+ * case. Unlike {@link setPage}, this loads even when already on page 1, so
2187
+ * callers no longer need `page() === 1 ? refresh() : setPage(1)`.
2188
+ */
2189
+ reload() {
2190
+ this._page.set(1);
2191
+ this.load();
2192
+ }
2184
2193
  /**
2185
2194
  * Pipe an `mkSort` directive's changes into {@link setSort}. Idempotent per
2186
2195
  * directive instance; all subscriptions are released by {@link destroy}.
@@ -2300,6 +2309,45 @@ class MkTableDataSource {
2300
2309
  sub.unsubscribe();
2301
2310
  }
2302
2311
  }
2312
+ /**
2313
+ * In-memory {@link MkDataFetcher}: filter, sort and slice a full row set that
2314
+ * the app already holds (an API that returns everything). Lets a client-side
2315
+ * list use {@link MkTableDataSource} — same pager, footer and API as a
2316
+ * server-paged one — without hand-rolling `filtered/sorted/paged` computeds.
2317
+ *
2318
+ * ```ts
2319
+ * ds = new MkTableDataSource(mkClientFetcher(() => this.rows()));
2320
+ * ```
2321
+ */
2322
+ function mkClientFetcher(rows, opts = {}) {
2323
+ const match = opts.match ??
2324
+ ((row, q) => Object.values(row).some((v) => (typeof v === 'string' || typeof v === 'number') &&
2325
+ String(v).toLowerCase().includes(q)));
2326
+ const compare = opts.compare ??
2327
+ ((a, b, sort) => {
2328
+ const av = a[sort.active];
2329
+ const bv = b[sort.active];
2330
+ if (av == null && bv == null)
2331
+ return 0;
2332
+ if (av == null)
2333
+ return 1;
2334
+ if (bv == null)
2335
+ return -1;
2336
+ if (typeof av === 'number' && typeof bv === 'number')
2337
+ return av - bv;
2338
+ return String(av).localeCompare(String(bv), undefined, { numeric: true, sensitivity: 'base' });
2339
+ });
2340
+ return (req) => {
2341
+ const q = req.filter.trim().toLowerCase();
2342
+ let out = q ? rows().filter((r) => match(r, q)) : [...rows()];
2343
+ if (req.sort && req.sort.direction !== 'none') {
2344
+ const dir = req.sort.direction === 'desc' ? -1 : 1;
2345
+ out = [...out].sort((a, b) => dir * compare(a, b, req.sort));
2346
+ }
2347
+ const start = (req.page - 1) * req.pageSize;
2348
+ return Promise.resolve({ rows: out.slice(start, start + req.pageSize), total: out.length });
2349
+ };
2350
+ }
2303
2351
 
2304
2352
  /**
2305
2353
  * @mk-kit/ui/table — the data table, grid features and sort directives.
@@ -2309,5 +2357,5 @@ class MkTableDataSource {
2309
2357
  * Generated bundle index. Do not edit.
2310
2358
  */
2311
2359
 
2312
- export { MkSort, MkSortHeader, MkTable, MkTableCell, MkTableDataSource, MkTableRowDetail, mkCompactFilters, mkDownloadText, mkExportCsv, mkToCsv };
2360
+ export { MkSort, MkSortHeader, MkTable, MkTableCell, MkTableDataSource, MkTableRowDetail, mkClientFetcher, mkCompactFilters, mkDownloadText, mkExportCsv, mkToCsv };
2313
2361
  //# sourceMappingURL=mk-kit-ui-table.mjs.map