grid-list.mjs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. import { T as TileCoordinator } from './public-api-BoO5eSq-.mjs';
  2. export { ɵ as ɵTileCoordinator } from './public-api-BoO5eSq-.mjs';
  3. import { s as setLines, M as MatLine, a as MatLineModule } from './line-Bm3zUbBF.mjs';
  4. import * as i0 from '@angular/core';
  5. import { InjectionToken, inject, ElementRef, Component, ViewEncapsulation, ChangeDetectionStrategy, Input, ContentChildren, Directive, NgModule } from '@angular/core';
  6. import { coerceNumberProperty } from '@angular/cdk/coercion';
  7. import { Directionality } from '@angular/cdk/bidi';
  8. import { M as MatCommonModule } from './common-module-WayjW0Pb.mjs';
  9. import 'rxjs/operators';
  10. import '@angular/cdk/a11y';
  11. /**
  12. * Injection token used to provide a grid list to a tile and to avoid circular imports.
  13. * @docs-private
  14. */
  15. const MAT_GRID_LIST = new InjectionToken('MAT_GRID_LIST');
  16. class MatGridTile {
  17. _element = inject(ElementRef);
  18. _gridList = inject(MAT_GRID_LIST, { optional: true });
  19. _rowspan = 1;
  20. _colspan = 1;
  21. constructor() { }
  22. /** Amount of rows that the grid tile takes up. */
  23. get rowspan() {
  24. return this._rowspan;
  25. }
  26. set rowspan(value) {
  27. this._rowspan = Math.round(coerceNumberProperty(value));
  28. }
  29. /** Amount of columns that the grid tile takes up. */
  30. get colspan() {
  31. return this._colspan;
  32. }
  33. set colspan(value) {
  34. this._colspan = Math.round(coerceNumberProperty(value));
  35. }
  36. /**
  37. * Sets the style of the grid-tile element. Needs to be set manually to avoid
  38. * "Changed after checked" errors that would occur with HostBinding.
  39. */
  40. _setStyle(property, value) {
  41. this._element.nativeElement.style[property] = value;
  42. }
  43. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTile, deps: [], target: i0.ɵɵFactoryTarget.Component });
  44. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: MatGridTile, isStandalone: true, selector: "mat-grid-tile", inputs: { rowspan: "rowspan", colspan: "colspan" }, host: { properties: { "attr.rowspan": "rowspan", "attr.colspan": "colspan" }, classAttribute: "mat-grid-tile" }, exportAs: ["matGridTile"], ngImport: i0, template: "<div class=\"mat-grid-tile-content\">\n <ng-content></ng-content>\n</div>\n", styles: [".mat-grid-list{display:block;position:relative}.mat-grid-tile{display:block;position:absolute;overflow:hidden}.mat-grid-tile .mat-grid-tile-header,.mat-grid-tile .mat-grid-tile-footer{display:flex;align-items:center;height:48px;color:#fff;background:rgba(0,0,0,.38);overflow:hidden;padding:0 16px;position:absolute;left:0;right:0}.mat-grid-tile .mat-grid-tile-header>*,.mat-grid-tile .mat-grid-tile-footer>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-tile-header.mat-2-line,.mat-grid-tile .mat-grid-tile-footer.mat-2-line{height:68px}.mat-grid-tile .mat-grid-list-text{display:flex;flex-direction:column;flex:auto;box-sizing:border-box;overflow:hidden}.mat-grid-tile .mat-grid-list-text>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-list-text:empty{display:none}.mat-grid-tile .mat-grid-tile-header{top:0}.mat-grid-tile .mat-grid-tile-footer{bottom:0}.mat-grid-tile .mat-grid-avatar{padding-right:16px}[dir=rtl] .mat-grid-tile .mat-grid-avatar{padding-right:0;padding-left:16px}.mat-grid-tile .mat-grid-avatar:empty{display:none}.mat-grid-tile-header{font-size:var(--mat-grid-list-tile-header-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-header .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-header .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-header-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-footer{font-size:var(--mat-grid-list-tile-footer-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-footer .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-footer .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-footer-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-content{top:0;left:0;right:0;bottom:0;position:absolute;display:flex;align-items:center;justify-content:center;height:100%;padding:0;margin:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  45. }
  46. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTile, decorators: [{
  47. type: Component,
  48. args: [{ selector: 'mat-grid-tile', exportAs: 'matGridTile', host: {
  49. 'class': 'mat-grid-tile',
  50. // Ensures that the "rowspan" and "colspan" input value is reflected in
  51. // the DOM. This is needed for the grid-tile harness.
  52. '[attr.rowspan]': 'rowspan',
  53. '[attr.colspan]': 'colspan',
  54. }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"mat-grid-tile-content\">\n <ng-content></ng-content>\n</div>\n", styles: [".mat-grid-list{display:block;position:relative}.mat-grid-tile{display:block;position:absolute;overflow:hidden}.mat-grid-tile .mat-grid-tile-header,.mat-grid-tile .mat-grid-tile-footer{display:flex;align-items:center;height:48px;color:#fff;background:rgba(0,0,0,.38);overflow:hidden;padding:0 16px;position:absolute;left:0;right:0}.mat-grid-tile .mat-grid-tile-header>*,.mat-grid-tile .mat-grid-tile-footer>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-tile-header.mat-2-line,.mat-grid-tile .mat-grid-tile-footer.mat-2-line{height:68px}.mat-grid-tile .mat-grid-list-text{display:flex;flex-direction:column;flex:auto;box-sizing:border-box;overflow:hidden}.mat-grid-tile .mat-grid-list-text>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-list-text:empty{display:none}.mat-grid-tile .mat-grid-tile-header{top:0}.mat-grid-tile .mat-grid-tile-footer{bottom:0}.mat-grid-tile .mat-grid-avatar{padding-right:16px}[dir=rtl] .mat-grid-tile .mat-grid-avatar{padding-right:0;padding-left:16px}.mat-grid-tile .mat-grid-avatar:empty{display:none}.mat-grid-tile-header{font-size:var(--mat-grid-list-tile-header-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-header .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-header .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-header-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-footer{font-size:var(--mat-grid-list-tile-footer-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-footer .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-footer .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-footer-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-content{top:0;left:0;right:0;bottom:0;position:absolute;display:flex;align-items:center;justify-content:center;height:100%;padding:0;margin:0}\n"] }]
  55. }], ctorParameters: () => [], propDecorators: { rowspan: [{
  56. type: Input
  57. }], colspan: [{
  58. type: Input
  59. }] } });
  60. class MatGridTileText {
  61. _element = inject(ElementRef);
  62. _lines;
  63. constructor() { }
  64. ngAfterContentInit() {
  65. setLines(this._lines, this._element);
  66. }
  67. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTileText, deps: [], target: i0.ɵɵFactoryTarget.Component });
  68. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: MatGridTileText, isStandalone: true, selector: "mat-grid-tile-header, mat-grid-tile-footer", queries: [{ propertyName: "_lines", predicate: MatLine, descendants: true }], ngImport: i0, template: "<ng-content select=\"[mat-grid-avatar], [matGridAvatar]\"></ng-content>\n<div class=\"mat-grid-list-text\"><ng-content select=\"[mat-line], [matLine]\"></ng-content></div>\n<ng-content></ng-content>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  69. }
  70. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTileText, decorators: [{
  71. type: Component,
  72. args: [{ selector: 'mat-grid-tile-header, mat-grid-tile-footer', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<ng-content select=\"[mat-grid-avatar], [matGridAvatar]\"></ng-content>\n<div class=\"mat-grid-list-text\"><ng-content select=\"[mat-line], [matLine]\"></ng-content></div>\n<ng-content></ng-content>\n" }]
  73. }], ctorParameters: () => [], propDecorators: { _lines: [{
  74. type: ContentChildren,
  75. args: [MatLine, { descendants: true }]
  76. }] } });
  77. /**
  78. * Directive whose purpose is to add the mat- CSS styling to this selector.
  79. * @docs-private
  80. */
  81. class MatGridAvatarCssMatStyler {
  82. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridAvatarCssMatStyler, deps: [], target: i0.ɵɵFactoryTarget.Directive });
  83. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.6", type: MatGridAvatarCssMatStyler, isStandalone: true, selector: "[mat-grid-avatar], [matGridAvatar]", host: { classAttribute: "mat-grid-avatar" }, ngImport: i0 });
  84. }
  85. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridAvatarCssMatStyler, decorators: [{
  86. type: Directive,
  87. args: [{
  88. selector: '[mat-grid-avatar], [matGridAvatar]',
  89. host: { 'class': 'mat-grid-avatar' },
  90. }]
  91. }] });
  92. /**
  93. * Directive whose purpose is to add the mat- CSS styling to this selector.
  94. * @docs-private
  95. */
  96. class MatGridTileHeaderCssMatStyler {
  97. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTileHeaderCssMatStyler, deps: [], target: i0.ɵɵFactoryTarget.Directive });
  98. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.6", type: MatGridTileHeaderCssMatStyler, isStandalone: true, selector: "mat-grid-tile-header", host: { classAttribute: "mat-grid-tile-header" }, ngImport: i0 });
  99. }
  100. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTileHeaderCssMatStyler, decorators: [{
  101. type: Directive,
  102. args: [{
  103. selector: 'mat-grid-tile-header',
  104. host: { 'class': 'mat-grid-tile-header' },
  105. }]
  106. }] });
  107. /**
  108. * Directive whose purpose is to add the mat- CSS styling to this selector.
  109. * @docs-private
  110. */
  111. class MatGridTileFooterCssMatStyler {
  112. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTileFooterCssMatStyler, deps: [], target: i0.ɵɵFactoryTarget.Directive });
  113. static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.6", type: MatGridTileFooterCssMatStyler, isStandalone: true, selector: "mat-grid-tile-footer", host: { classAttribute: "mat-grid-tile-footer" }, ngImport: i0 });
  114. }
  115. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridTileFooterCssMatStyler, decorators: [{
  116. type: Directive,
  117. args: [{
  118. selector: 'mat-grid-tile-footer',
  119. host: { 'class': 'mat-grid-tile-footer' },
  120. }]
  121. }] });
  122. /**
  123. * RegExp that can be used to check whether a value will
  124. * be allowed inside a CSS `calc()` expression.
  125. */
  126. const cssCalcAllowedValue = /^-?\d+((\.\d+)?[A-Za-z%$]?)+$/;
  127. /**
  128. * Sets the style properties for an individual tile, given the position calculated by the
  129. * Tile Coordinator.
  130. * @docs-private
  131. */
  132. class TileStyler {
  133. _gutterSize;
  134. _rows = 0;
  135. _rowspan = 0;
  136. _cols;
  137. _direction;
  138. /**
  139. * Adds grid-list layout info once it is available. Cannot be processed in the constructor
  140. * because these properties haven't been calculated by that point.
  141. *
  142. * @param gutterSize Size of the grid's gutter.
  143. * @param tracker Instance of the TileCoordinator.
  144. * @param cols Amount of columns in the grid.
  145. * @param direction Layout direction of the grid.
  146. */
  147. init(gutterSize, tracker, cols, direction) {
  148. this._gutterSize = normalizeUnits(gutterSize);
  149. this._rows = tracker.rowCount;
  150. this._rowspan = tracker.rowspan;
  151. this._cols = cols;
  152. this._direction = direction;
  153. }
  154. /**
  155. * Computes the amount of space a single 1x1 tile would take up (width or height).
  156. * Used as a basis for other calculations.
  157. * @param sizePercent Percent of the total grid-list space that one 1x1 tile would take up.
  158. * @param gutterFraction Fraction of the gutter size taken up by one 1x1 tile.
  159. * @return The size of a 1x1 tile as an expression that can be evaluated via CSS calc().
  160. */
  161. getBaseTileSize(sizePercent, gutterFraction) {
  162. // Take the base size percent (as would be if evenly dividing the size between cells),
  163. // and then subtracting the size of one gutter. However, since there are no gutters on the
  164. // edges, each tile only uses a fraction (gutterShare = numGutters / numCells) of the gutter
  165. // size. (Imagine having one gutter per tile, and then breaking up the extra gutter on the
  166. // edge evenly among the cells).
  167. return `(${sizePercent}% - (${this._gutterSize} * ${gutterFraction}))`;
  168. }
  169. /**
  170. * Gets The horizontal or vertical position of a tile, e.g., the 'top' or 'left' property value.
  171. * @param offset Number of tiles that have already been rendered in the row/column.
  172. * @param baseSize Base size of a 1x1 tile (as computed in getBaseTileSize).
  173. * @return Position of the tile as a CSS calc() expression.
  174. */
  175. getTilePosition(baseSize, offset) {
  176. // The position comes the size of a 1x1 tile plus gutter for each previous tile in the
  177. // row/column (offset).
  178. return offset === 0 ? '0' : calc(`(${baseSize} + ${this._gutterSize}) * ${offset}`);
  179. }
  180. /**
  181. * Gets the actual size of a tile, e.g., width or height, taking rowspan or colspan into account.
  182. * @param baseSize Base size of a 1x1 tile (as computed in getBaseTileSize).
  183. * @param span The tile's rowspan or colspan.
  184. * @return Size of the tile as a CSS calc() expression.
  185. */
  186. getTileSize(baseSize, span) {
  187. return `(${baseSize} * ${span}) + (${span - 1} * ${this._gutterSize})`;
  188. }
  189. /**
  190. * Sets the style properties to be applied to a tile for the given row and column index.
  191. * @param tile Tile to which to apply the styling.
  192. * @param rowIndex Index of the tile's row.
  193. * @param colIndex Index of the tile's column.
  194. */
  195. setStyle(tile, rowIndex, colIndex) {
  196. // Percent of the available horizontal space that one column takes up.
  197. let percentWidthPerTile = 100 / this._cols;
  198. // Fraction of the vertical gutter size that each column takes up.
  199. // For example, if there are 5 columns, each column uses 4/5 = 0.8 times the gutter width.
  200. let gutterWidthFractionPerTile = (this._cols - 1) / this._cols;
  201. this.setColStyles(tile, colIndex, percentWidthPerTile, gutterWidthFractionPerTile);
  202. this.setRowStyles(tile, rowIndex, percentWidthPerTile, gutterWidthFractionPerTile);
  203. }
  204. /** Sets the horizontal placement of the tile in the list. */
  205. setColStyles(tile, colIndex, percentWidth, gutterWidth) {
  206. // Base horizontal size of a column.
  207. let baseTileWidth = this.getBaseTileSize(percentWidth, gutterWidth);
  208. // The width and horizontal position of each tile is always calculated the same way, but the
  209. // height and vertical position depends on the rowMode.
  210. let side = this._direction === 'rtl' ? 'right' : 'left';
  211. tile._setStyle(side, this.getTilePosition(baseTileWidth, colIndex));
  212. tile._setStyle('width', calc(this.getTileSize(baseTileWidth, tile.colspan)));
  213. }
  214. /**
  215. * Calculates the total size taken up by gutters across one axis of a list.
  216. */
  217. getGutterSpan() {
  218. return `${this._gutterSize} * (${this._rowspan} - 1)`;
  219. }
  220. /**
  221. * Calculates the total size taken up by tiles across one axis of a list.
  222. * @param tileHeight Height of the tile.
  223. */
  224. getTileSpan(tileHeight) {
  225. return `${this._rowspan} * ${this.getTileSize(tileHeight, 1)}`;
  226. }
  227. /**
  228. * Calculates the computed height and returns the correct style property to set.
  229. * This method can be implemented by each type of TileStyler.
  230. * @docs-private
  231. */
  232. getComputedHeight() {
  233. return null;
  234. }
  235. }
  236. /**
  237. * This type of styler is instantiated when the user passes in a fixed row height.
  238. * Example `<mat-grid-list cols="3" rowHeight="100px">`
  239. * @docs-private
  240. */
  241. class FixedTileStyler extends TileStyler {
  242. fixedRowHeight;
  243. constructor(fixedRowHeight) {
  244. super();
  245. this.fixedRowHeight = fixedRowHeight;
  246. }
  247. init(gutterSize, tracker, cols, direction) {
  248. super.init(gutterSize, tracker, cols, direction);
  249. this.fixedRowHeight = normalizeUnits(this.fixedRowHeight);
  250. if (!cssCalcAllowedValue.test(this.fixedRowHeight) &&
  251. (typeof ngDevMode === 'undefined' || ngDevMode)) {
  252. throw Error(`Invalid value "${this.fixedRowHeight}" set as rowHeight.`);
  253. }
  254. }
  255. setRowStyles(tile, rowIndex) {
  256. tile._setStyle('top', this.getTilePosition(this.fixedRowHeight, rowIndex));
  257. tile._setStyle('height', calc(this.getTileSize(this.fixedRowHeight, tile.rowspan)));
  258. }
  259. getComputedHeight() {
  260. return ['height', calc(`${this.getTileSpan(this.fixedRowHeight)} + ${this.getGutterSpan()}`)];
  261. }
  262. reset(list) {
  263. list._setListStyle(['height', null]);
  264. if (list._tiles) {
  265. list._tiles.forEach(tile => {
  266. tile._setStyle('top', null);
  267. tile._setStyle('height', null);
  268. });
  269. }
  270. }
  271. }
  272. /**
  273. * This type of styler is instantiated when the user passes in a width:height ratio
  274. * for the row height. Example `<mat-grid-list cols="3" rowHeight="3:1">`
  275. * @docs-private
  276. */
  277. class RatioTileStyler extends TileStyler {
  278. /** Ratio width:height given by user to determine row height. */
  279. rowHeightRatio;
  280. baseTileHeight;
  281. constructor(value) {
  282. super();
  283. this._parseRatio(value);
  284. }
  285. setRowStyles(tile, rowIndex, percentWidth, gutterWidth) {
  286. let percentHeightPerTile = percentWidth / this.rowHeightRatio;
  287. this.baseTileHeight = this.getBaseTileSize(percentHeightPerTile, gutterWidth);
  288. // Use padding-top and margin-top to maintain the given aspect ratio, as
  289. // a percentage-based value for these properties is applied versus the *width* of the
  290. // containing block. See http://www.w3.org/TR/CSS2/box.html#margin-properties
  291. tile._setStyle('marginTop', this.getTilePosition(this.baseTileHeight, rowIndex));
  292. tile._setStyle('paddingTop', calc(this.getTileSize(this.baseTileHeight, tile.rowspan)));
  293. }
  294. getComputedHeight() {
  295. return [
  296. 'paddingBottom',
  297. calc(`${this.getTileSpan(this.baseTileHeight)} + ${this.getGutterSpan()}`),
  298. ];
  299. }
  300. reset(list) {
  301. list._setListStyle(['paddingBottom', null]);
  302. list._tiles.forEach(tile => {
  303. tile._setStyle('marginTop', null);
  304. tile._setStyle('paddingTop', null);
  305. });
  306. }
  307. _parseRatio(value) {
  308. const ratioParts = value.split(':');
  309. if (ratioParts.length !== 2 && (typeof ngDevMode === 'undefined' || ngDevMode)) {
  310. throw Error(`mat-grid-list: invalid ratio given for row-height: "${value}"`);
  311. }
  312. this.rowHeightRatio = parseFloat(ratioParts[0]) / parseFloat(ratioParts[1]);
  313. }
  314. }
  315. /**
  316. * This type of styler is instantiated when the user selects a "fit" row height mode.
  317. * In other words, the row height will reflect the total height of the container divided
  318. * by the number of rows. Example `<mat-grid-list cols="3" rowHeight="fit">`
  319. *
  320. * @docs-private
  321. */
  322. class FitTileStyler extends TileStyler {
  323. setRowStyles(tile, rowIndex) {
  324. // Percent of the available vertical space that one row takes up.
  325. let percentHeightPerTile = 100 / this._rowspan;
  326. // Fraction of the horizontal gutter size that each column takes up.
  327. let gutterHeightPerTile = (this._rows - 1) / this._rows;
  328. // Base vertical size of a column.
  329. let baseTileHeight = this.getBaseTileSize(percentHeightPerTile, gutterHeightPerTile);
  330. tile._setStyle('top', this.getTilePosition(baseTileHeight, rowIndex));
  331. tile._setStyle('height', calc(this.getTileSize(baseTileHeight, tile.rowspan)));
  332. }
  333. reset(list) {
  334. if (list._tiles) {
  335. list._tiles.forEach(tile => {
  336. tile._setStyle('top', null);
  337. tile._setStyle('height', null);
  338. });
  339. }
  340. }
  341. }
  342. /** Wraps a CSS string in a calc function */
  343. function calc(exp) {
  344. return `calc(${exp})`;
  345. }
  346. /** Appends pixels to a CSS string if no units are given. */
  347. function normalizeUnits(value) {
  348. return value.match(/([A-Za-z%]+)$/) ? value : `${value}px`;
  349. }
  350. // TODO(kara): Conditional (responsive) column count / row size.
  351. // TODO(kara): Re-layout on window resize / media change (debounced).
  352. // TODO(kara): gridTileHeader and gridTileFooter.
  353. const MAT_FIT_MODE = 'fit';
  354. class MatGridList {
  355. _element = inject(ElementRef);
  356. _dir = inject(Directionality, { optional: true });
  357. /** Number of columns being rendered. */
  358. _cols;
  359. /** Used for determining the position of each tile in the grid. */
  360. _tileCoordinator;
  361. /**
  362. * Row height value passed in by user. This can be one of three types:
  363. * - Number value (ex: "100px"): sets a fixed row height to that value
  364. * - Ratio value (ex: "4:3"): sets the row height based on width:height ratio
  365. * - "Fit" mode (ex: "fit"): sets the row height to total height divided by number of rows
  366. */
  367. _rowHeight;
  368. /** The amount of space between tiles. This will be something like '5px' or '2em'. */
  369. _gutter = '1px';
  370. /** Sets position and size styles for a tile */
  371. _tileStyler;
  372. /** Query list of tiles that are being rendered. */
  373. _tiles;
  374. constructor() { }
  375. /** Amount of columns in the grid list. */
  376. get cols() {
  377. return this._cols;
  378. }
  379. set cols(value) {
  380. this._cols = Math.max(1, Math.round(coerceNumberProperty(value)));
  381. }
  382. /** Size of the grid list's gutter in pixels. */
  383. get gutterSize() {
  384. return this._gutter;
  385. }
  386. set gutterSize(value) {
  387. this._gutter = `${value == null ? '' : value}`;
  388. }
  389. /** Set internal representation of row height from the user-provided value. */
  390. get rowHeight() {
  391. return this._rowHeight;
  392. }
  393. set rowHeight(value) {
  394. const newValue = `${value == null ? '' : value}`;
  395. if (newValue !== this._rowHeight) {
  396. this._rowHeight = newValue;
  397. this._setTileStyler(this._rowHeight);
  398. }
  399. }
  400. ngOnInit() {
  401. this._checkCols();
  402. this._checkRowHeight();
  403. }
  404. /**
  405. * The layout calculation is fairly cheap if nothing changes, so there's little cost
  406. * to run it frequently.
  407. */
  408. ngAfterContentChecked() {
  409. this._layoutTiles();
  410. }
  411. /** Throw a friendly error if cols property is missing */
  412. _checkCols() {
  413. if (!this.cols && (typeof ngDevMode === 'undefined' || ngDevMode)) {
  414. throw Error(`mat-grid-list: must pass in number of columns. ` + `Example: <mat-grid-list cols="3">`);
  415. }
  416. }
  417. /** Default to equal width:height if rowHeight property is missing */
  418. _checkRowHeight() {
  419. if (!this._rowHeight) {
  420. this._setTileStyler('1:1');
  421. }
  422. }
  423. /** Creates correct Tile Styler subtype based on rowHeight passed in by user */
  424. _setTileStyler(rowHeight) {
  425. if (this._tileStyler) {
  426. this._tileStyler.reset(this);
  427. }
  428. if (rowHeight === MAT_FIT_MODE) {
  429. this._tileStyler = new FitTileStyler();
  430. }
  431. else if (rowHeight && rowHeight.indexOf(':') > -1) {
  432. this._tileStyler = new RatioTileStyler(rowHeight);
  433. }
  434. else {
  435. this._tileStyler = new FixedTileStyler(rowHeight);
  436. }
  437. }
  438. /** Computes and applies the size and position for all children grid tiles. */
  439. _layoutTiles() {
  440. if (!this._tileCoordinator) {
  441. this._tileCoordinator = new TileCoordinator();
  442. }
  443. const tracker = this._tileCoordinator;
  444. const tiles = this._tiles.filter(tile => !tile._gridList || tile._gridList === this);
  445. const direction = this._dir ? this._dir.value : 'ltr';
  446. this._tileCoordinator.update(this.cols, tiles);
  447. this._tileStyler.init(this.gutterSize, tracker, this.cols, direction);
  448. tiles.forEach((tile, index) => {
  449. const pos = tracker.positions[index];
  450. this._tileStyler.setStyle(tile, pos.row, pos.col);
  451. });
  452. this._setListStyle(this._tileStyler.getComputedHeight());
  453. }
  454. /** Sets style on the main grid-list element, given the style name and value. */
  455. _setListStyle(style) {
  456. if (style) {
  457. this._element.nativeElement.style[style[0]] = style[1];
  458. }
  459. }
  460. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridList, deps: [], target: i0.ɵɵFactoryTarget.Component });
  461. static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.6", type: MatGridList, isStandalone: true, selector: "mat-grid-list", inputs: { cols: "cols", gutterSize: "gutterSize", rowHeight: "rowHeight" }, host: { properties: { "attr.cols": "cols" }, classAttribute: "mat-grid-list" }, providers: [
  462. {
  463. provide: MAT_GRID_LIST,
  464. useExisting: MatGridList,
  465. },
  466. ], queries: [{ propertyName: "_tiles", predicate: MatGridTile, descendants: true }], exportAs: ["matGridList"], ngImport: i0, template: "<div>\n <ng-content></ng-content>\n</div>", styles: [".mat-grid-list{display:block;position:relative}.mat-grid-tile{display:block;position:absolute;overflow:hidden}.mat-grid-tile .mat-grid-tile-header,.mat-grid-tile .mat-grid-tile-footer{display:flex;align-items:center;height:48px;color:#fff;background:rgba(0,0,0,.38);overflow:hidden;padding:0 16px;position:absolute;left:0;right:0}.mat-grid-tile .mat-grid-tile-header>*,.mat-grid-tile .mat-grid-tile-footer>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-tile-header.mat-2-line,.mat-grid-tile .mat-grid-tile-footer.mat-2-line{height:68px}.mat-grid-tile .mat-grid-list-text{display:flex;flex-direction:column;flex:auto;box-sizing:border-box;overflow:hidden}.mat-grid-tile .mat-grid-list-text>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-list-text:empty{display:none}.mat-grid-tile .mat-grid-tile-header{top:0}.mat-grid-tile .mat-grid-tile-footer{bottom:0}.mat-grid-tile .mat-grid-avatar{padding-right:16px}[dir=rtl] .mat-grid-tile .mat-grid-avatar{padding-right:0;padding-left:16px}.mat-grid-tile .mat-grid-avatar:empty{display:none}.mat-grid-tile-header{font-size:var(--mat-grid-list-tile-header-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-header .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-header .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-header-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-footer{font-size:var(--mat-grid-list-tile-footer-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-footer .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-footer .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-footer-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-content{top:0;left:0;right:0;bottom:0;position:absolute;display:flex;align-items:center;justify-content:center;height:100%;padding:0;margin:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
  467. }
  468. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridList, decorators: [{
  469. type: Component,
  470. args: [{ selector: 'mat-grid-list', exportAs: 'matGridList', host: {
  471. 'class': 'mat-grid-list',
  472. // Ensures that the "cols" input value is reflected in the DOM. This is
  473. // needed for the grid-list harness.
  474. '[attr.cols]': 'cols',
  475. }, providers: [
  476. {
  477. provide: MAT_GRID_LIST,
  478. useExisting: MatGridList,
  479. },
  480. ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<div>\n <ng-content></ng-content>\n</div>", styles: [".mat-grid-list{display:block;position:relative}.mat-grid-tile{display:block;position:absolute;overflow:hidden}.mat-grid-tile .mat-grid-tile-header,.mat-grid-tile .mat-grid-tile-footer{display:flex;align-items:center;height:48px;color:#fff;background:rgba(0,0,0,.38);overflow:hidden;padding:0 16px;position:absolute;left:0;right:0}.mat-grid-tile .mat-grid-tile-header>*,.mat-grid-tile .mat-grid-tile-footer>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-tile-header.mat-2-line,.mat-grid-tile .mat-grid-tile-footer.mat-2-line{height:68px}.mat-grid-tile .mat-grid-list-text{display:flex;flex-direction:column;flex:auto;box-sizing:border-box;overflow:hidden}.mat-grid-tile .mat-grid-list-text>*{margin:0;padding:0;font-weight:normal;font-size:inherit}.mat-grid-tile .mat-grid-list-text:empty{display:none}.mat-grid-tile .mat-grid-tile-header{top:0}.mat-grid-tile .mat-grid-tile-footer{bottom:0}.mat-grid-tile .mat-grid-avatar{padding-right:16px}[dir=rtl] .mat-grid-tile .mat-grid-avatar{padding-right:0;padding-left:16px}.mat-grid-tile .mat-grid-avatar:empty{display:none}.mat-grid-tile-header{font-size:var(--mat-grid-list-tile-header-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-header .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-header .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-header-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-footer{font-size:var(--mat-grid-list-tile-footer-primary-text-size, var(--mat-sys-body-large))}.mat-grid-tile-footer .mat-line{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block;box-sizing:border-box}.mat-grid-tile-footer .mat-line:nth-child(n+2){font-size:var(--mat-grid-list-tile-footer-secondary-text-size, var(--mat-sys-body-medium))}.mat-grid-tile-content{top:0;left:0;right:0;bottom:0;position:absolute;display:flex;align-items:center;justify-content:center;height:100%;padding:0;margin:0}\n"] }]
  481. }], ctorParameters: () => [], propDecorators: { _tiles: [{
  482. type: ContentChildren,
  483. args: [MatGridTile, { descendants: true }]
  484. }], cols: [{
  485. type: Input
  486. }], gutterSize: [{
  487. type: Input
  488. }], rowHeight: [{
  489. type: Input
  490. }] } });
  491. class MatGridListModule {
  492. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
  493. static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.6", ngImport: i0, type: MatGridListModule, imports: [MatLineModule,
  494. MatCommonModule,
  495. MatGridList,
  496. MatGridTile,
  497. MatGridTileText,
  498. MatGridTileHeaderCssMatStyler,
  499. MatGridTileFooterCssMatStyler,
  500. MatGridAvatarCssMatStyler], exports: [MatGridList,
  501. MatGridTile,
  502. MatGridTileText,
  503. MatLineModule,
  504. MatCommonModule,
  505. MatGridTileHeaderCssMatStyler,
  506. MatGridTileFooterCssMatStyler,
  507. MatGridAvatarCssMatStyler] });
  508. static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridListModule, imports: [MatLineModule,
  509. MatCommonModule, MatLineModule,
  510. MatCommonModule] });
  511. }
  512. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatGridListModule, decorators: [{
  513. type: NgModule,
  514. args: [{
  515. imports: [
  516. MatLineModule,
  517. MatCommonModule,
  518. MatGridList,
  519. MatGridTile,
  520. MatGridTileText,
  521. MatGridTileHeaderCssMatStyler,
  522. MatGridTileFooterCssMatStyler,
  523. MatGridAvatarCssMatStyler,
  524. ],
  525. exports: [
  526. MatGridList,
  527. MatGridTile,
  528. MatGridTileText,
  529. MatLineModule,
  530. MatCommonModule,
  531. MatGridTileHeaderCssMatStyler,
  532. MatGridTileFooterCssMatStyler,
  533. MatGridAvatarCssMatStyler,
  534. ],
  535. }]
  536. }] });
  537. export { MatGridAvatarCssMatStyler, MatGridList, MatGridListModule, MatGridTile, MatGridTileFooterCssMatStyler, MatGridTileHeaderCssMatStyler, MatGridTileText, MatLine };
  538. //# sourceMappingURL=grid-list.mjs.map