Skip to content

Commit 8c71175

Browse files
authored
Merge branch 'master' into data-grid
2 parents 347f5e9 + 34296f5 commit 8c71175

File tree

9 files changed

+416
-73
lines changed

9 files changed

+416
-73
lines changed

package-lock.json

Lines changed: 98 additions & 73 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,9 @@
145145
"webpack-node-externals": "1.6.0",
146146
"whatwg-fetch": "2.0.3",
147147
"zone.js": "0.8.26"
148+
},
149+
"dependencies": {
150+
"flatpickr": "4.5.2",
151+
"ng2-flatpickr": "7.0.1"
148152
}
149153
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Component, Input } from "@angular/core";
2+
3+
@Component({
4+
selector: "ibm-date-picker-input",
5+
template: `
6+
<div class="bx--form-item">
7+
<div class="bx--date-picker"
8+
[ngClass]= "'bx--date-picker--' + type">
9+
<div class="bx--date-picker-container">
10+
<label [for]="id" class="bx--label">
11+
{{label}}
12+
</label>
13+
<svg *ngIf="type == 'single'"
14+
data-date-picker-icon
15+
class="bx--date-picker__icon"
16+
width="14" height="16"
17+
viewBox="0 0 14 16"
18+
data-open>
19+
<path d="M0 5h14v1H0V5zm3-5h1v4H3V0zm7 0h1v4h-1V0zM0 2.5A1.5 1.5 0 0 1 1.5 1h11A1.5 1.5 0 0 1 14 2.5v12a1.5 1.5 0 0 1-1.5
20+
1.5h-11A1.5 1.5 0 0 1 0 14.5v-12zm1 0v12a.5.5 0 0 0
21+
.5.5h11a.5.5 0 0 0 .5-.5v-12a.5.5 0 0 0-.5-.5h-11a.5.5 0 0 0-.5.5z"
22+
fill-rule="nonzero"/>
23+
</svg>
24+
<input
25+
autocomplete="off"
26+
type="text"
27+
class="bx--date-picker__input"
28+
[pattern]="pattern"
29+
[placeholder]="placeholder"
30+
data-date-picker-input
31+
[attr.data-input] = "type == 'single' || type == 'range' ? '' : null"
32+
[id]= "id"/>
33+
</div>
34+
35+
<svg *ngIf= "type == 'range' && hasIcon"
36+
data-date-picker-icon
37+
class="bx--date-picker__icon"
38+
width="14" height="16"
39+
viewBox="0 0 14 16"
40+
data-open>
41+
<path d="M0 5h14v1H0V5zm3-5h1v4H3V0zm7 0h1v4h-1V0zM0 2.5A1.5 1.5 0 0 1 1.5 1h11A1.5 1.5 0 0 1 14 2.5v12a1.5 1.5 0 0 1-1.5
42+
1.5h-11A1.5 1.5 0 0 1 0 14.5v-12zm1 0v12a.5.5 0 0 0 .5.5h11a.5.5 0 0 0 .5-.5v-12a.5.5 0 0 0-.5-.5h-11a.5.5 0 0 0-.5.5z"
43+
fill-rule="nonzero"/>
44+
</svg>
45+
</div>
46+
</div>
47+
`
48+
})
49+
export class DatePickerInput {
50+
private static datePickerCount = 0;
51+
52+
/**
53+
* Select a calendar type for the `model`.
54+
* Internal purposes only.
55+
*
56+
* @type {("simple" | "single" | "range")}
57+
* @memberof Datepicker
58+
*/
59+
@Input() type: "simple" | "single" | "range" = "simple";
60+
61+
@Input() id = `datepicker-${DatePickerInput.datePickerCount++}`;
62+
63+
@Input() hasIcon = false;
64+
65+
@Input() label: string;
66+
67+
@Input() placeholder = "mm/dd/yyyy";
68+
69+
@Input() pattern = "\d{1,2}/\d{1,2}/\d{4}";
70+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Ng2FlatpickrModule } from "ng2-flatpickr";
2+
import { NgModule } from "@angular/core";
3+
import { CommonModule } from "@angular/common";
4+
import { DatePickerInput } from "./datepicker-input.component";
5+
6+
@NgModule({
7+
declarations: [
8+
DatePickerInput
9+
],
10+
exports: [
11+
DatePickerInput
12+
],
13+
imports: [
14+
CommonModule,
15+
Ng2FlatpickrModule
16+
]
17+
})
18+
export class DatePickerInputModule { }
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { DatePickerInputModule } from "./datepicker-input.module";
2+
import { storiesOf, moduleMetadata } from "@storybook/angular";
3+
import { withKnobs } from "@storybook/addon-knobs/angular";
4+
import { ExperimentalComponenent } from "../../.storybook/experimental.component";
5+
import { ExperimentalModule } from "..";
6+
7+
storiesOf("DatePickerInput", module)
8+
.addDecorator(
9+
moduleMetadata({
10+
declarations: [ExperimentalComponenent],
11+
imports: [
12+
DatePickerInputModule,
13+
ExperimentalModule
14+
]
15+
})
16+
)
17+
.addDecorator(withKnobs)
18+
.add("Simple", () => ({
19+
template: `
20+
<app-experimental-component></app-experimental-component>
21+
<ibm-date-picker-input label="Date Picker Label"></ibm-date-picker-input>
22+
`
23+
}));
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { array } from "@storybook/addon-knobs/angular";
2+
import { Component, Input, Output, EventEmitter } from "@angular/core";
3+
import { FlatpickrOptions } from "ng2-flatpickr";
4+
import rangePlugin from "flatpickr/dist/plugins/rangePlugin";
5+
6+
@Component({
7+
selector: "ibm-date-picker",
8+
template: `
9+
<div class="bx--form-item">
10+
<ng2-flatpickr
11+
[setDate]= "value"
12+
[config]= "range ? flatpickrOptionsRange : flatpickrOptions"
13+
[hideButton]="true">
14+
<div class="bx--form-item">
15+
<div
16+
data-date-picker
17+
[attr.data-date-picker-type]= "range ? 'range' : 'single'"
18+
class="bx--date-picker"
19+
[ngClass]= "range ? 'bx--date-picker--range' : 'bx--date-picker--single'">
20+
<div class="bx--date-picker-container">
21+
<ibm-date-picker-input
22+
[label]= "label"
23+
[placeholder]= "placeholder"
24+
[pattern]= "pattern"
25+
[id]= "id"
26+
[type]= "range ? 'range' : 'single'"
27+
[hasIcon]= "range ? false : true"
28+
(valueChange)="valueChange.emit($event)">
29+
</ibm-date-picker-input>
30+
</div>
31+
32+
<div *ngIf="range" class="bx--date-picker-container">
33+
<ibm-date-picker-input
34+
[label]= "rangeLabel"
35+
[placeholder]= "placeholder"
36+
[pattern]= "pattern"
37+
[id]= "id + '-rangeInput'"
38+
[type]= "range ? 'range' : 'single'"
39+
[hasIcon]= "range ? true : null"
40+
(valueChange)="valueChange.emit($event)">
41+
</ibm-date-picker-input>
42+
</div>
43+
</div>
44+
</div>
45+
</ng2-flatpickr>
46+
</div>
47+
`
48+
})
49+
export class DatePicker {
50+
private static datePickerCount = 0;
51+
52+
/**
53+
* Select calendar range mode
54+
*
55+
* @memberof Datepicker
56+
*/
57+
@Input() range: boolean;
58+
59+
/**
60+
* Format of date
61+
*
62+
* For reference: https://flatpickr.js.org/formatting/
63+
*
64+
* @memberof Datepicker
65+
*/
66+
@Input() dateFormat = "m/d/Y";
67+
68+
@Input() label: string;
69+
70+
@Input() rangeLabel: string;
71+
72+
@Input() placeholder = "mm/dd/yyyy";
73+
74+
@Input() pattern = "\d{1,2}/\d{1,2}/\d{4}";
75+
76+
@Input() id = `datepicker-${DatePicker.datePickerCount++}`;
77+
78+
@Input() value: array;
79+
80+
@Output() valueChange: EventEmitter<any> = new EventEmitter();
81+
82+
flatpickrOptions: FlatpickrOptions = {
83+
dateFormat: this.dateFormat,
84+
allowInput: true,
85+
onChange: (selectedValue: any) => { this.doSelect(selectedValue); },
86+
onOpen: () => { this.updateClassNames(); },
87+
value: this.value
88+
};
89+
90+
flatpickrOptionsRange: FlatpickrOptions = {
91+
dateFormat: this.dateFormat,
92+
"plugins": [rangePlugin({ input: "#" + this.id + "-rangeInput"})],
93+
allowInput: true,
94+
onChange: (selectedValue: any) => { this.doSelect(selectedValue); },
95+
onOpen: () => { this.updateClassNames(); },
96+
value: this.value
97+
};
98+
99+
doSelect(selectedValue) {
100+
this.valueChange.emit(selectedValue);
101+
}
102+
103+
updateClassNames() {
104+
const calendarContainer = document.querySelector(".flatpickr-calendar");
105+
const monthContainer = document.querySelector(".flatpickr-month");
106+
const weekdaysContainer = document.querySelector(".flatpickr-weekdays");
107+
const weekdayContainer = document.querySelectorAll(".flatpickr-weekday");
108+
const daysContainer = document.querySelector(".flatpickr-days");
109+
const dayContainer = document.querySelectorAll(".flatpickr-day");
110+
111+
calendarContainer.classList.add("bx--date-picker__calendar");
112+
monthContainer.classList.add("bx--date-picker__month");
113+
weekdaysContainer.classList.add("bx--date-picker__weekdays");
114+
daysContainer.classList.add("bx--date-picker__days");
115+
116+
Array.from(weekdayContainer).forEach(item => {
117+
const currentItem = item;
118+
currentItem.innerHTML = currentItem.innerHTML.replace(/\s+/g, "");
119+
currentItem.classList.add("bx--date-picker__weekday");
120+
});
121+
122+
Array.from(dayContainer).forEach(item => {
123+
item.classList.add("bx--date-picker__day");
124+
if (item.classList.contains("today") && this.value.length > 0) {
125+
item.classList.add("no-border");
126+
} else if (item.classList.contains("today") && this.value.length === 0) {
127+
item.classList.remove("no-border");
128+
}
129+
});
130+
}
131+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { DatePickerInputModule } from "./../datepicker-input/datepicker-input.module";
2+
import { Ng2FlatpickrModule } from "ng2-flatpickr";
3+
import { NgModule } from "@angular/core";
4+
import { CommonModule } from "@angular/common";
5+
import { DatePicker } from "./datepicker.component";
6+
7+
8+
@NgModule({
9+
declarations: [
10+
DatePicker
11+
],
12+
exports: [
13+
DatePicker
14+
],
15+
imports: [
16+
CommonModule,
17+
Ng2FlatpickrModule,
18+
DatePickerInputModule
19+
]
20+
})
21+
export class DatePickerModule { }
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { storiesOf, moduleMetadata } from "@storybook/angular";
2+
import { action } from "@storybook/addon-actions";
3+
import { withKnobs, array } from "@storybook/addon-knobs/angular";
4+
import { DatePickerModule, ExperimentalModule } from "../";
5+
import { ExperimentalComponenent } from "../../.storybook/experimental.component";
6+
7+
storiesOf("Date Picker", module)
8+
.addDecorator(
9+
moduleMetadata({
10+
declarations: [ExperimentalComponenent],
11+
imports: [
12+
DatePickerModule,
13+
ExperimentalModule
14+
]
15+
})
16+
)
17+
.addDecorator(withKnobs)
18+
.add("Single", () => ({
19+
template: `
20+
<app-experimental-component></app-experimental-component>
21+
<ibm-date-picker
22+
label="Date Picker Label"
23+
[value]="value"
24+
(valueChange)="valueChange($event)">
25+
</ibm-date-picker>
26+
`,
27+
props: {
28+
value: array("value", ["01/01/2011"]),
29+
valueChange: action("Date change fired!")
30+
}
31+
}))
32+
.add("Range", () => ({
33+
template: `
34+
<app-experimental-component></app-experimental-component>
35+
<ibm-date-picker
36+
label="Date Picker Label"
37+
rangeLabel="Date Picker Label2"
38+
range="true"
39+
[value]="value"
40+
(valueChange)="valueChange($event)">
41+
</ibm-date-picker>
42+
`,
43+
props: {
44+
value: array("value", [
45+
"01/01/2011",
46+
"01/01/2012"
47+
]),
48+
valueChange: action("Date change fired!")
49+
}
50+
}));

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export * from "./checkbox/checkbox.module";
77
export * from "./code-snippet/code-snippet.module";
88
export * from "./combobox/combobox.module";
99
export * from "./content-switcher/content-switcher.module";
10+
export * from "./datepicker/datepicker.module";
1011
export * from "./dialog/dialog.module";
1112
export * from "./dropdown/dropdown.module";
1213
export * from "./experimental.module";

0 commit comments

Comments
 (0)