This repository has been archived by the owner on Jun 24, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
37 changed files
with
4,970 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<!-- | ||
If there's not enough space in the first row, create a separate label row. We mark this row as | ||
aria-hidden because we don't want it to be read out as one of the weeks in the month. | ||
--> | ||
<tr *ngIf="label && _firstRowOffset < labelMinRequiredCells" aria-hidden="true"> | ||
<td class="mat-calendar-body-label" | ||
[attr.colspan]="numCols" | ||
[style.paddingTop.%]="50 * cellAspectRatio / numCols" | ||
[style.paddingBottom.%]="50 * cellAspectRatio / numCols"> | ||
{{ label }} | ||
</td> | ||
</tr> | ||
|
||
<!-- Create the first row separately so we can include a special spacer cell. --> | ||
<tr *ngFor="let row of rows; let rowIndex = index" role="row"> | ||
<!-- | ||
We mark this cell as aria-hidden so it doesn't get read out as one of the days in the week. | ||
The aspect ratio of the table cells is maintained by setting the top and bottom padding as a | ||
percentage of the width (a variant of the trick described here: | ||
https://www.w3schools.com/howto/howto_css_aspect_ratio.asp). | ||
--> | ||
<td *ngIf="rowIndex === 0 && _firstRowOffset" | ||
aria-hidden="true" | ||
class="mat-calendar-body-label" | ||
[attr.colspan]="_firstRowOffset" | ||
[style.paddingTop.%]="50 * cellAspectRatio / numCols" | ||
[style.paddingBottom.%]="50 * cellAspectRatio / numCols"> | ||
{{ _firstRowOffset >= labelMinRequiredCells ? label : '' }} | ||
</td> | ||
<td *ngFor="let item of row; let colIndex = index" | ||
role="gridcell" | ||
class="mat-calendar-body-cell" | ||
[tabindex]="_isActiveCell(rowIndex, colIndex) ? 0 : -1" | ||
[class.mat-calendar-body-disabled]="!item.enabled" | ||
[class.mat-calendar-body-active]="_isActiveCell(rowIndex, colIndex)" | ||
[attr.aria-label]="item.ariaLabel" | ||
[attr.aria-disabled]="!item.enabled || null" | ||
(click)="_cellClicked(item)" | ||
[style.width.%]="100 / numCols" | ||
[style.paddingTop.%]="50 * cellAspectRatio / numCols" | ||
[style.paddingBottom.%]="50 * cellAspectRatio / numCols"> | ||
<div class="mat-calendar-body-cell-background" | ||
[class.mat-calendar-body-selected]="selectedValue === item.value" | ||
[class.mat-calendar-body-active]="activeValue === item.value" | ||
[class.mat-calendar-body-today]="todayValue === item.value"> | ||
</div> | ||
<span class="mat-calendar-body-cell-content"> item.displayValue }}</span> | ||
</td> | ||
</tr> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
@mixin mat-calendar-body($theme) { | ||
$primary: map-get($theme, primary); | ||
|
||
$mat-calendar-body-label-padding-start: 5% !default; | ||
// We don't want the label to jump around when we switch between month and year views, so we use | ||
// the same amount of padding regardless of the number of columns. We align the header label with | ||
// the one third mark of the first cell, this was chosen somewhat arbitrarily to make it look | ||
// roughly like the mock. Half way is too far since the cell text is center aligned. | ||
$mat-calendar-body-label-side-padding: 33% / 7 !default; | ||
$mat-calendar-body-cell-min-size: 32px !default; | ||
$mat-calendar-body-cell-content-margin: 5% !default; | ||
$mat-calendar-body-cell-content-border-width: 1px !default; | ||
|
||
$mat-calendar-body-min-size: 7 * $mat-calendar-body-cell-min-size !default; | ||
$mat-calendar-body-cell-content-size: 100% - $mat-calendar-body-cell-content-margin | ||
!default; | ||
|
||
.mat-calendar-body { | ||
min-width: $mat-calendar-body-min-size; | ||
} | ||
|
||
.mat-calendar-body-label { | ||
height: 0; | ||
line-height: 0; | ||
text-align: left; | ||
padding-left: $mat-calendar-body-label-side-padding; | ||
padding-right: $mat-calendar-body-label-side-padding; | ||
} | ||
|
||
[dir='rtl'] { | ||
.mat-calendar-body-label { | ||
text-align: right; | ||
} | ||
} | ||
|
||
.mat-calendar-body-cell { | ||
position: relative; | ||
height: 0; | ||
line-height: 0; | ||
text-align: center; | ||
outline: none; | ||
cursor: pointer; | ||
} | ||
|
||
.mat-calendar-body-cell-background { | ||
position: absolute; | ||
|
||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
|
||
box-sizing: border-box; | ||
opacity: 0; | ||
|
||
border-width: $mat-calendar-body-cell-content-border-width; | ||
border-style: solid; | ||
|
||
transform: scale(0); | ||
transition: all 350ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; | ||
|
||
// Choosing a value clearly larger than the height ensures we get the correct capsule shape. | ||
border-radius: 999px; | ||
} | ||
|
||
// Square background | ||
@media all and (orientation: portrait) { | ||
.mat-calendar-body-cell-background { | ||
top: 50%; | ||
left: $mat-calendar-body-cell-content-margin; | ||
margin-top: -$mat-calendar-body-cell-content-size / 2; | ||
|
||
padding-bottom: $mat-calendar-body-cell-content-size; | ||
width: $mat-calendar-body-cell-content-size; | ||
} | ||
} | ||
@media all and (orientation: landscape) { | ||
.mat-calendar-body-cell-background { | ||
top: $mat-calendar-body-cell-content-margin; | ||
left: 50%; | ||
margin-left: -$mat-calendar-body-cell-content-size / 3 - 2; | ||
|
||
padding-left: $mat-calendar-body-cell-content-size / 3; | ||
padding-right: $mat-calendar-body-cell-content-size / 3; | ||
height: $mat-calendar-body-cell-content-size - $mat-calendar-body-cell-content-margin; | ||
} | ||
} | ||
|
||
.mat-calendar-body-cell:hover:not(.mat-calendar-body-disabled) { | ||
.mat-calendar-body-cell-background { | ||
background: mat-color($primary, 0.5); | ||
color: mat-color($primary, 0.5); | ||
opacity: 1; | ||
transform: scale(1); | ||
} | ||
} | ||
|
||
.mat-calendar-body-active, | ||
.mat-calendar-body-selected, | ||
.mat-calendar-body-today { | ||
opacity: 1; | ||
transform: scale(1); | ||
} | ||
|
||
.mat-calendar-body-selected { | ||
background: mat-color($primary, 0.8); | ||
color: mat-color($primary, 0.8); | ||
} | ||
|
||
.mat-calendar-body-active:not(.mat-calendar-body-today) { | ||
color: mat-color($primary, 0.5); | ||
} | ||
|
||
.mat-calendar-body-disabled { | ||
cursor: default; | ||
} | ||
|
||
.mat-calendar-body-cell-content { | ||
font-weight: 400; | ||
position: relative; | ||
|
||
// Prevents text being off-center on Android. | ||
line-height: 1; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import { | ||
ChangeDetectionStrategy, | ||
Component, | ||
EventEmitter, | ||
Input, | ||
Output, | ||
ViewEncapsulation | ||
} from '@angular/core'; | ||
|
||
/** | ||
* An internal class that represents the data corresponding to a single calendar cell. | ||
* @docs-private | ||
*/ | ||
export class MatCalendarCell { | ||
constructor( | ||
public value: number, | ||
public displayValue: string, | ||
public ariaLabel: string, | ||
public enabled: boolean | ||
) {} | ||
} | ||
|
||
/** | ||
* An internal component used to display calendar data in a table. | ||
* @docs-private | ||
*/ | ||
@Component({ | ||
selector: '[mat-calendar-body]', | ||
templateUrl: 'calendar-body.html', | ||
// styleUrls: ['calendar-body.scss'], | ||
host: { | ||
class: 'mat-calendar-body' | ||
}, | ||
encapsulation: ViewEncapsulation.None, | ||
preserveWhitespaces: false, | ||
changeDetection: ChangeDetectionStrategy.OnPush | ||
}) | ||
export class MatCalendarBody { | ||
/** The label for the table. (e.g. "Jan 2017"). */ | ||
@Input() label: string; | ||
|
||
/** The cells to display in the table. */ | ||
@Input() rows: MatCalendarCell[][]; | ||
|
||
/** The value in the table that corresponds to today. */ | ||
@Input() todayValue: number; | ||
|
||
/** The value in the table that is active. */ | ||
@Input() activeValue: number; | ||
|
||
/** The value in the table that is currently selected. */ | ||
@Input() selectedValue: number; | ||
|
||
/** The minimum number of free cells needed to fit the label in the first row. */ | ||
@Input() labelMinRequiredCells: number; | ||
|
||
/** The number of columns in the table. */ | ||
@Input() numCols = 7; | ||
|
||
/** Whether to allow selection of disabled cells. */ | ||
@Input() allowDisabledSelection = false; | ||
|
||
/** The cell number of the active cell in the table. */ | ||
@Input() activeCell = 0; | ||
|
||
/** | ||
* The aspect ratio (width / height) to use for the cells in the table. This aspect ratio will be | ||
* maintained even as the table resizes. | ||
*/ | ||
@Input() cellAspectRatio = 0.5; | ||
|
||
/** Emits when a new value is selected. */ | ||
@Output() selectedValueChange = new EventEmitter<number>(); | ||
|
||
_cellClicked(cell: MatCalendarCell): void { | ||
if (!this.allowDisabledSelection && !cell.enabled) { | ||
return; | ||
} | ||
this.selectedValueChange.emit(cell.value); | ||
} | ||
|
||
/** The number of blank cells to put at the beginning for the first row. */ | ||
get _firstRowOffset(): number { | ||
return this.rows && this.rows.length && this.rows[0].length | ||
? this.numCols - this.rows[0].length | ||
: 0; | ||
} | ||
|
||
_isActiveCell(rowIndex: number, colIndex: number): boolean { | ||
let cellNumber = rowIndex * this.numCols + colIndex; | ||
|
||
// Account for the fact that the first row may not have as many cells. | ||
if (rowIndex) { | ||
cellNumber -= this._firstRowOffset; | ||
} | ||
|
||
return cellNumber === this.activeCell; | ||
} | ||
} |
Oops, something went wrong.