@mk-kit/ui 0.34.1 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,6 +26,65 @@ declare class MkTableRowDetail<T = unknown> {
26
26
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MkTableRowDetail<any>, "[mkTableRowDetail]", never, {}, {}, never, never, true, never>;
27
27
  }
28
28
 
29
+ /**
30
+ * CSV export — turn rows into RFC 4180 text and hand it to the browser as a
31
+ * download. Framework-free so it also serves data that never touched a table.
32
+ */
33
+ /** A column to export: the row property, its header, and an optional formatter. */
34
+ interface MkCsvColumn<T = Record<string, unknown>> {
35
+ /** Property key on each row object supplying the cell value. */
36
+ key: string;
37
+ /** Header text; defaults to `key`. */
38
+ header?: string;
39
+ /** Formatter turning the raw value into cell text (same shape as `MkTableColumn.format`). */
40
+ format?: (value: unknown, row: T) => string;
41
+ }
42
+ interface MkCsvOptions {
43
+ /** Field separator (default `,`; use `;` for locales whose Excel expects it). */
44
+ delimiter?: string;
45
+ /** Emit the header row first (default `true`). */
46
+ header?: boolean;
47
+ /** Line terminator (default `\r\n`, per RFC 4180). */
48
+ newline?: string;
49
+ /**
50
+ * Prefix a UTF-8 byte-order mark (default `true`) so Excel reads accented
51
+ * characters correctly. Only affects the downloaded file / returned text.
52
+ */
53
+ bom?: boolean;
54
+ /**
55
+ * Neutralise spreadsheet formula injection (default `true`): a text cell
56
+ * starting with `=`, `+`, `-`, `@`, tab or CR is prefixed with `'` so a
57
+ * malicious value cannot execute when opened in Excel / Sheets. Numbers
58
+ * are never touched, so `-5` stays `-5`.
59
+ */
60
+ sanitize?: boolean;
61
+ /** Property holding child rows; when set, trees are flattened depth-first. */
62
+ childrenKey?: string;
63
+ }
64
+ /** Options for {@link mkExportCsv}. */
65
+ interface MkCsvExportOptions extends MkCsvOptions {
66
+ /** File name for the download (default `export.csv`; `.csv` is appended if missing). */
67
+ filename?: string;
68
+ }
69
+ /**
70
+ * Serialise `rows` as CSV text.
71
+ *
72
+ * Without `columns` every key of the first row is exported in its own order.
73
+ * Column formatters are applied, so what the user saw in the table is what
74
+ * lands in the file.
75
+ */
76
+ declare function mkToCsv<T>(rows: readonly T[], columns?: readonly MkCsvColumn<T>[], options?: MkCsvOptions): string;
77
+ /**
78
+ * Trigger a browser download of `text` as a file. No-op outside a DOM
79
+ * (server-side rendering); returns whether a download was started.
80
+ */
81
+ declare function mkDownloadText(text: string, filename: string, type?: string): boolean;
82
+ /**
83
+ * Serialise `rows` as CSV and download it. Returns the CSV text so callers
84
+ * can also keep it (tests, previews, uploads).
85
+ */
86
+ declare function mkExportCsv<T>(rows: readonly T[], columns?: readonly MkCsvColumn<T>[], options?: MkCsvExportOptions): string;
87
+
29
88
  /** Horizontal text alignment for a table column. */
30
89
  type MkTableAlign = 'start' | 'center' | 'end';
31
90
  /** Sort direction; `none` means unsorted. */
@@ -105,12 +164,28 @@ interface MkTableGroup<T = Record<string, unknown>> {
105
164
  rows: T[];
106
165
  }
107
166
  /** Payload emitted by {@link MkTable.groupToggle}. */
167
+ /** Payload of `(treeToggle)`: a parent row was expanded or collapsed. */
168
+ interface MkTreeToggle<T = Record<string, unknown>> {
169
+ /** The parent row. */
170
+ row: T;
171
+ /** Whether its child rows are now shown. */
172
+ expanded: boolean;
173
+ }
108
174
  interface MkGroupToggle {
109
175
  /** The toggled group's value. */
110
176
  key: unknown;
111
177
  /** Whether the group is now collapsed. */
112
178
  collapsed: boolean;
113
179
  }
180
+ /** Options for {@link MkTable.exportCsv}. */
181
+ interface MkTableExportOptions extends MkCsvExportOptions {
182
+ /** Export only the selected rows (default: every row). */
183
+ selectedOnly?: boolean;
184
+ /** Restrict to these column keys, in table order (default: every column). */
185
+ columns?: readonly string[];
186
+ /** Start the browser download (default `true`); `false` just returns the text. */
187
+ download?: boolean;
188
+ }
114
189
  /** One rendered tbody entry: either a group header or a data row. */
115
190
  type MkTableItem<T> = {
116
191
  kind: 'group';
@@ -118,6 +193,12 @@ type MkTableItem<T> = {
118
193
  } | {
119
194
  kind: 'row';
120
195
  row: T;
196
+ /** Nesting depth in tree mode (0 for roots and for flat tables). */
197
+ depth: number;
198
+ /** Whether the row has child rows (tree mode). */
199
+ hasChildren: boolean;
200
+ /** Whether its children are currently shown (tree mode). */
201
+ expanded: boolean;
121
202
  };
122
203
  /**
123
204
  * Table — a themed data table built on a native `<table>` for accessibility.
@@ -242,6 +323,15 @@ declare class MkTable<T = Record<string, unknown>> {
242
323
  readonly cellEdit: _angular_core.OutputEmitterRef<MkCellEdit<T>>;
243
324
  /** Emitted when a group header is expanded or collapsed. */
244
325
  readonly groupToggle: _angular_core.OutputEmitterRef<MkGroupToggle>;
326
+ /**
327
+ * Tree rows: the property on each row holding its child rows (`T[]`). When
328
+ * set, the table renders a tree grid — child rows are indented under their
329
+ * parent behind an expand toggle in the first column, sorting applies per
330
+ * sibling group, and ArrowRight / ArrowLeft on a row open / close it.
331
+ */
332
+ readonly childrenKey: _angular_core.InputSignal<string | null>;
333
+ /** Emitted when a parent row is expanded or collapsed (tree mode). */
334
+ readonly treeToggle: _angular_core.OutputEmitterRef<MkTreeToggle<T>>;
245
335
  /** User-set column widths (px), keyed by column key. */
246
336
  private readonly colWidths;
247
337
  /** User-set column order (keys); `null` = the input order. */
@@ -343,6 +433,8 @@ declare class MkTable<T = Record<string, unknown>> {
343
433
  private static readonly sortCollator;
344
434
  /** Data sorted by the active column, or the input order when unsorted. */
345
435
  protected readonly sortedData: _angular_core.Signal<T[]>;
436
+ /** Sort one sibling group by the active column (input order when unsorted). */
437
+ private sortRows;
346
438
  /** `aria-sort` value for a header cell. */
347
439
  protected ariaSort(col: MkTableColumn<T>): string | null;
348
440
  /** Glyph indicating a column's sort state. */
@@ -353,7 +445,7 @@ declare class MkTable<T = Record<string, unknown>> {
353
445
  protected cellText(row: T, col: MkTableColumn<T>): string;
354
446
  protected onSort(col: MkTableColumn<T>): void;
355
447
  protected onRowClick(row: T): void;
356
- /** Keyboard activation for clickable rows (Enter / Space). */
448
+ /** Keyboard activation for clickable rows (Enter / Space) and tree keys. */
357
449
  protected onRowKeydown(event: KeyboardEvent, row: T): void;
358
450
  /** Stable row identity for `@for` tracking (trackKey when set, else the row). */
359
451
  protected trackRow: (row: T) => unknown;
@@ -364,6 +456,12 @@ declare class MkTable<T = Record<string, unknown>> {
364
456
  private readonly selectedKeys;
365
457
  /** Whether `row` is currently selected. */
366
458
  protected isSelected(row: T): boolean;
459
+ /**
460
+ * Every data row, in display order, ignoring tree expansion — what
461
+ * "select all" and the header checkbox reason about. Equals `sortedData`
462
+ * for flat tables.
463
+ */
464
+ private readonly allRows;
367
465
  /** True when every visible row is selected. */
368
466
  protected readonly allSelected: _angular_core.Signal<boolean>;
369
467
  /** True when some — but not all — visible rows are selected. */
@@ -371,7 +469,7 @@ declare class MkTable<T = Record<string, unknown>> {
371
469
  private commitSelection;
372
470
  /** Toggle a single row's selection without triggering `rowClick`. */
373
471
  protected toggleRow(row: T): void;
374
- /** Select or deselect all visible rows. */
472
+ /** Select or deselect all rows (every tree row, expanded or not). */
375
473
  protected toggleAll(): void;
376
474
  /** Group values currently collapsed. */
377
475
  private readonly collapsedGroups;
@@ -382,6 +480,36 @@ declare class MkTable<T = Record<string, unknown>> {
382
480
  * rows when grouping is on, else just the sorted rows.
383
481
  */
384
482
  protected readonly displayItems: _angular_core.Signal<MkTableItem<T>[]>;
483
+ /**
484
+ * Append `rows` as render items. In tree mode each row is followed by its
485
+ * (sorted) children while it is expanded, one level deeper.
486
+ */
487
+ private pushRows;
488
+ /** The child rows of `row` (tree mode), or an empty list. */
489
+ private childrenOf;
490
+ /** Keys of parent rows whose children are shown. */
491
+ private readonly treeExpanded;
492
+ /** Whether a parent row's children are currently shown (tree mode). */
493
+ isTreeExpanded(row: T): boolean;
494
+ /** Show or hide a parent row's children (tree mode). */
495
+ toggleTreeRow(row: T, event?: Event): void;
496
+ /** Expand every parent row (tree mode). */
497
+ expandAllRows(): void;
498
+ /** Collapse every parent row (tree mode). */
499
+ collapseAllRows(): void;
500
+ /**
501
+ * The table's rows as CSV: current column order, column formatters applied,
502
+ * sorted the way they are shown, tree children flattened under their parent
503
+ * whether or not they are expanded. Downloads the file (default name
504
+ * `table.csv`) and returns the text.
505
+ */
506
+ exportCsv(options?: MkTableExportOptions): string;
507
+ private setTreeExpanded;
508
+ /**
509
+ * ArrowRight opens and ArrowLeft closes a parent row's children (swapped in
510
+ * RTL). Handled for keys pressed on the row itself or on its tree toggle.
511
+ */
512
+ protected onTreeKeydown(event: KeyboardEvent, row: T): boolean;
385
513
  /** `@for` identity: group headers by value, rows by {@link trackRow}. */
386
514
  protected trackItem: (item: MkTableItem<T>) => unknown;
387
515
  /** Whether a group is currently collapsed. */
@@ -400,7 +528,7 @@ declare class MkTable<T = Record<string, unknown>> {
400
528
  /** Toggle a row's detail panel, honouring `singleExpand`. */
401
529
  protected toggleExpand(row: T, event?: Event): void;
402
530
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MkTable<any>, never>;
403
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkTable<any>, "mk-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "stickyHeader": { "alias": "stickyHeader"; "required": false; "isSignal": true; }; "zebra": { "alias": "zebra"; "required": false; "isSignal": true; }; "hover": { "alias": "hover"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "stackAt": { "alias": "stackAt"; "required": false; "isSignal": true; }; "clickableRows": { "alias": "clickableRows"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "trackKey": { "alias": "trackKey"; "required": false; "isSignal": true; }; "rowClass": { "alias": "rowClass"; "required": false; "isSignal": true; }; "expandable": { "alias": "expandable"; "required": false; "isSignal": true; }; "singleExpand": { "alias": "singleExpand"; "required": false; "isSignal": true; }; "resizableColumns": { "alias": "resizableColumns"; "required": false; "isSignal": true; }; "reorderableColumns": { "alias": "reorderableColumns"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; "groupLabel": { "alias": "groupLabel"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "sortChange": "sortChange"; "rowClick": "rowClick"; "selectionChange": "selectionChange"; "expandedChange": "expandedChange"; "columnResize": "columnResize"; "columnReorder": "columnReorder"; "cellEdit": "cellEdit"; "groupToggle": "groupToggle"; }, ["rowDetail", "cellTemplates"], ["[mkTableEmpty]"], true, never>;
531
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MkTable<any>, "mk-table", never, { "columns": { "alias": "columns"; "required": true; "isSignal": true; }; "data": { "alias": "data"; "required": false; "isSignal": true; }; "stickyHeader": { "alias": "stickyHeader"; "required": false; "isSignal": true; }; "zebra": { "alias": "zebra"; "required": false; "isSignal": true; }; "hover": { "alias": "hover"; "required": false; "isSignal": true; }; "density": { "alias": "density"; "required": false; "isSignal": true; }; "stackAt": { "alias": "stackAt"; "required": false; "isSignal": true; }; "clickableRows": { "alias": "clickableRows"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "selected": { "alias": "selected"; "required": false; "isSignal": true; }; "trackKey": { "alias": "trackKey"; "required": false; "isSignal": true; }; "rowClass": { "alias": "rowClass"; "required": false; "isSignal": true; }; "expandable": { "alias": "expandable"; "required": false; "isSignal": true; }; "singleExpand": { "alias": "singleExpand"; "required": false; "isSignal": true; }; "resizableColumns": { "alias": "resizableColumns"; "required": false; "isSignal": true; }; "reorderableColumns": { "alias": "reorderableColumns"; "required": false; "isSignal": true; }; "groupBy": { "alias": "groupBy"; "required": false; "isSignal": true; }; "groupLabel": { "alias": "groupLabel"; "required": false; "isSignal": true; }; "childrenKey": { "alias": "childrenKey"; "required": false; "isSignal": true; }; }, { "selected": "selectedChange"; "sortChange": "sortChange"; "rowClick": "rowClick"; "selectionChange": "selectionChange"; "expandedChange": "expandedChange"; "columnResize": "columnResize"; "columnReorder": "columnReorder"; "cellEdit": "cellEdit"; "groupToggle": "groupToggle"; "treeToggle": "treeToggle"; }, ["rowDetail", "cellTemplates"], ["[mkTableEmpty]"], true, never>;
404
532
  }
405
533
 
406
534
  /** Context handed to an `[mkTableCell]` template. */
@@ -735,5 +863,5 @@ declare class MkTableDataSource<T> {
735
863
  private clearSub;
736
864
  }
737
865
 
738
- export { MkSort, MkSortHeader, MkTable, MkTableCell, MkTableDataSource, MkTableRowDetail };
739
- export type { MkCellEdit, MkColumnResize, MkDataFetcher, MkDataPage, MkDataRequest, MkGroupToggle, MkSortChange, MkSortDirection, MkSortState, MkSortable, MkTableAlign, MkTableCellContext, MkTableColumn, MkTableDataSourceOptions, MkTableDensity, MkTableGroup };
866
+ export { MkSort, MkSortHeader, MkTable, MkTableCell, MkTableDataSource, MkTableRowDetail, mkDownloadText, mkExportCsv, mkToCsv };
867
+ export type { MkCellEdit, MkColumnResize, MkCsvColumn, MkCsvExportOptions, MkCsvOptions, MkDataFetcher, MkDataPage, MkDataRequest, MkGroupToggle, MkSortChange, MkSortDirection, MkSortState, MkSortable, MkTableAlign, MkTableCellContext, MkTableColumn, MkTableDataSourceOptions, MkTableDensity, MkTableExportOptions, MkTableGroup, MkTreeToggle };
@@ -14,4 +14,5 @@ export * from '@mk-kit/ui/feedback';
14
14
  export * from '@mk-kit/ui/rich-text';
15
15
  export * from '@mk-kit/ui/block-editor';
16
16
  export * from '@mk-kit/ui/context-menu';
17
+ export * from '@mk-kit/ui/layout';
17
18
  export * from '@mk-kit/ui/media';