mn-angular-lib 1.0.130 → 1.0.131

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mn-angular-lib",
3
- "version": "1.0.130",
3
+ "version": "1.0.131",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^21.1.3",
6
6
  "@angular/core": "^21.1.3"
@@ -3354,7 +3354,24 @@ declare abstract class MnCollectionBase<T, DS extends MnCollectionDataSource<T>>
3354
3354
  /** Client-side search filtering shared by list and grid. */
3355
3355
  protected applySearchFilter(items: T[]): T[];
3356
3356
  protected processLoadedRows(rows: T[]): void;
3357
- protected validateDataSource(): void;
3357
+ /**
3358
+ * Reports every misconfigured pagination setting and repairs it in place.
3359
+ *
3360
+ * This deliberately does **not** throw. It runs first in {@link ngOnInit}, and a
3361
+ * throw there aborts the rest of init — the data subscription is never made and
3362
+ * {@link applyFilter} never runs, so the component renders a permanently empty
3363
+ * body that only "heals" once some later interaction happens to call
3364
+ * {@link applyFilter}. That failure mode reads as "the table is broken" rather
3365
+ * than "the data source is misconfigured", and inside a modal the thrown error
3366
+ * is easy to miss entirely. Logging loudly and degrading to the nearest working
3367
+ * mode keeps the misconfiguration visible while still rendering the rows.
3368
+ */
3369
+ protected normalizeDataSource(): void;
3370
+ /**
3371
+ * Logs a data-source configuration problem, prefixed with the component name.
3372
+ * @param message What is wrong and how it was compensated for.
3373
+ */
3374
+ private reportConfigError;
3358
3375
  static ɵfac: i0.ɵɵFactoryDeclaration<MnCollectionBase<any, any>, never>;
3359
3376
  static ɵdir: i0.ɵɵDirectiveDeclaration<MnCollectionBase<any, any>, never, never, { "dataSource": { "alias": "dataSource"; "required": false; }; }, {}, never, never, true, never>;
3360
3377
  }
@@ -3456,6 +3473,23 @@ type TableAppearance = {
3456
3473
  hover?: boolean;
3457
3474
  compact?: boolean;
3458
3475
  bordered?: boolean;
3476
+ /**
3477
+ * How column widths are computed.
3478
+ *
3479
+ * - `auto` (default): the browser sizes each column to its widest cell, so the
3480
+ * columns shift every time the content changes — a new page, a filter, a
3481
+ * search. Fine for a static table.
3482
+ * - `fixed`: widths come from the header row and each column's {@link ColumnBase.width}
3483
+ * only, never from the cell content, so they stay put across pages and
3484
+ * filters. Columns without a `width` split the remaining space evenly.
3485
+ * Overlong cell text is truncated with an ellipsis (and exposed as a
3486
+ * `title` tooltip) instead of widening the column.
3487
+ *
3488
+ * Prefer `fixed` for any table whose rows change under the user — server-side
3489
+ * paginated, filtered or searched tables, and tables inside a modal, where a
3490
+ * width change is most visible.
3491
+ */
3492
+ layout?: 'auto' | 'fixed';
3459
3493
  };
3460
3494
  /**
3461
3495
  * The control rendered for a column filter, and the shape of the value it produces:
@@ -3702,7 +3736,16 @@ declare class MnTable<T = object> extends MnSelectableCollectionBase<T, TableDat
3702
3736
  private readonly filterDebounce;
3703
3737
  /** The open filter popover, used to tell inside clicks from outside ones. */
3704
3738
  private filterPopover?;
3705
- constructor();
3739
+ /**
3740
+ * Most rows shown per page on mobile (< md). A **cap**, not an override: a data
3741
+ * source asking for fewer rows keeps its own size. Raising a small page size on
3742
+ * a phone is the opposite of what it is for — it pushes the paginator below the
3743
+ * fold, which is most damaging inside a modal, where the sheet is already short
3744
+ * and its footer is pinned over the bottom of the table.
3745
+ */
3746
+ private static readonly MOBILE_PAGE_SIZE;
3747
+ /** The component's own element, measured for every responsive decision. */
3748
+ private readonly host;
3706
3749
  /** Whether the consumer owns filtering (server-side), mirroring {@link isServerSearched}. */
3707
3750
  get isServerFiltered(): boolean;
3708
3751
  /** Every column filter that is actually set, in column order. */
@@ -3774,12 +3817,16 @@ declare class MnTable<T = object> extends MnSelectableCollectionBase<T, TableDat
3774
3817
  get clearFiltersButtonLabel(): string;
3775
3818
  /** Opens/closes the stacked filter panel shown on small screens. */
3776
3819
  toggleFiltersPanel(): void;
3777
- /** Re-evaluate responsive page size and filter layout when the viewport changes. */
3778
- protected onWindowResize(): void;
3820
+ private readonly baseTableClasses;
3821
+ constructor();
3779
3822
  /** Sets sort/filter state seeded from the data source before the first filter pass. */
3780
3823
  protected beforeInitialFilter(): void;
3781
- /** True when the viewport is below the filter-collapse breakpoint. */
3782
- private isFilterViewport;
3824
+ /**
3825
+ * Classes for the `<table>` element. `table-fixed` is added for the `fixed`
3826
+ * layout so column widths come from the header row and the declared widths
3827
+ * only, keeping them stable as the rows change.
3828
+ */
3829
+ get tableClasses(): string;
3783
3830
  /**
3784
3831
  * Recomputes whether the inline filter row should collapse into the panel.
3785
3832
  * Closes the panel when returning to the wide layout so reopened state never
@@ -3796,19 +3843,28 @@ declare class MnTable<T = object> extends MnSelectableCollectionBase<T, TableDat
3796
3843
  getColumnSkeletonData(column: ColumnDefinition<T>): Partial<MnSkeletonProps>;
3797
3844
  getSortIcon(column: ColumnDefinition<T>): string;
3798
3845
  isSortable(column: ColumnDefinition<T>): boolean;
3799
- /** Rows shown per page on mobile (< md). Forced regardless of any configured pageSize. */
3800
- private static readonly MOBILE_PAGE_SIZE;
3846
+ /** Whether column widths are content-independent (see {@link TableAppearance.layout}). */
3847
+ get isFixedLayout(): boolean;
3801
3848
  /** Page size to use at/above the `md` breakpoint (consumer's pageSize, or the user's selection). */
3802
3849
  private desktopPageSize;
3803
- /** True when the viewport is below the `md` (768px) breakpoint. */
3804
- private isMobileViewport;
3805
3850
  /**
3806
- * Applies the breakpoint-appropriate page size: {@link MOBILE_PAGE_SIZE} below `md`,
3807
- * the desktop size at/above it. When the size actually changes, client-side tables
3808
- * re-slice locally and server-side tables ask the consumer to refetch, so the
3809
- * rendered rows update in every pagination mode (used at init and on window resize).
3851
+ * The `title` tooltip for a cell, so text truncated by the fixed layout stays
3852
+ * readable. Only string cells have text to expose; template cells render their
3853
+ * own markup and are left alone.
3854
+ * @param column The column being rendered.
3855
+ * @param row The row being rendered.
3856
+ * @returns The full cell text, or `null` when there is nothing to expose.
3810
3857
  */
3811
- private applyResponsivePageSize;
3858
+ cellTitle(column: ColumnDefinition<T>, row: T): string | null;
3859
+ /**
3860
+ * Re-evaluate on a window resize too. The ResizeObserver covers every change to
3861
+ * the table's own box, but {@link isMobileViewport} reads the window, which can
3862
+ * change without the table's width following it (a fixed-width table, a modal
3863
+ * pinned to a max width).
3864
+ */
3865
+ protected onWindowResize(): void;
3866
+ /** Re-evaluate responsive page size and filter layout when the table is resized. */
3867
+ private onHostResize;
3812
3868
  /**
3813
3869
  * Resolves table-specific translation keys (column headers/filters) plus the
3814
3870
  * shared keys handled by the base.
@@ -3821,7 +3877,36 @@ declare class MnTable<T = object> extends MnSelectableCollectionBase<T, TableDat
3821
3877
  /** Returns the small-screen cell value for a column with cellSm defined. */
3822
3878
  getCellSmValue(column: ColumnDefinition<T>, row: T): string;
3823
3879
  trackByKey: (_index: number, column: ColumnDefinition<T>) => string;
3824
- readonly tableClasses = "w-full border-collapse overflow-y-hidden";
3880
+ /** True when the table is narrower than the filter-collapse breakpoint. */
3881
+ private isFilterViewport;
3882
+ /**
3883
+ * True when the **window** is below the `md` (768px) breakpoint.
3884
+ *
3885
+ * Deliberately viewport-based, unlike {@link isFilterViewport}: the forced
3886
+ * mobile page size exists to keep a phone screen scrollable, and it is paired
3887
+ * with the rows-per-page selector that mn-collection-pagination hides at the
3888
+ * same viewport breakpoint. Measuring the table's own width instead would let
3889
+ * the two disagree — a 700px table on a desktop would be pinned to the mobile
3890
+ * row count while still offering the selector that overrides it.
3891
+ */
3892
+ private isMobileViewport;
3893
+ /**
3894
+ * The table's own rendered width, which every responsive decision is made
3895
+ * against — the same width the `@container` queries in the template use, so
3896
+ * the TS and CSS halves of the responsive layout can never disagree.
3897
+ *
3898
+ * Falls back to the window width before the host has been laid out (and in
3899
+ * SSR), which is the closest available approximation at that point.
3900
+ * @returns The width in CSS pixels.
3901
+ */
3902
+ private measuredWidth;
3903
+ /**
3904
+ * Applies the breakpoint-appropriate page size: capped at {@link MOBILE_PAGE_SIZE}
3905
+ * below `md`, the desktop size at/above it. When the size actually changes, client-side tables
3906
+ * re-slice locally and server-side tables ask the consumer to refetch, so the
3907
+ * rendered rows update in every pagination mode (used at init and on window resize).
3908
+ */
3909
+ private applyResponsivePageSize;
3825
3910
  get totalColumnCount(): number;
3826
3911
  /**
3827
3912
  * Hands the active filters to the consumer. Locks the body height first so the
@@ -3889,6 +3974,11 @@ declare function matchesColumnFilter<T>(column: ColumnDefinition<T>, row: T, val
3889
3974
  * Attribute directive that applies responsive-hiding classes to table cells/headers.
3890
3975
  * Hides the element by default and shows it as `table-cell` at the specified breakpoint.
3891
3976
  *
3977
+ * The breakpoints are **container** queries against the table's own width, not the
3978
+ * viewport: a table inside a modal (or any narrow column) is far narrower than the
3979
+ * window, so viewport breakpoints would reveal columns the table has no room for.
3980
+ * mn-table marks its chrome `@container` for exactly this.
3981
+ *
3892
3982
  * Uses a static class map so Tailwind CSS can detect the full class names at build time.
3893
3983
  *
3894
3984
  * Usage: `<td [mnHiddenBelow]="column.hiddenBelow">`