Skip to content

Commit 6c3a5da

Browse files
committed
create date selection
1 parent 20f0a83 commit 6c3a5da

File tree

5 files changed

+190
-55
lines changed

5 files changed

+190
-55
lines changed

docs/src/routes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const ButtonToggle = (r) => require.ensure([], () => r(require('./pages/componen
1313
const Card = (r) => require.ensure([], () => r(require('./pages/components/Card')), 'card');
1414
const Checkbox = (r) => require.ensure([], () => r(require('./pages/components/Checkbox')), 'checkbox');
1515
const Chips = (r) => require.ensure([], () => r(require('./pages/components/Chips')), 'chips');
16-
const DatePicker = (r) => require.ensure([], () => r(require('./pages/components/DatePicker')), 'date-picker');
16+
const Datepicker = (r) => require.ensure([], () => r(require('./pages/components/Datepicker')), 'date-picker');
1717
const Dialog = (r) => require.ensure([], () => r(require('./pages/components/Dialog')), 'dialog');
1818
const FileComponent = (r) => require.ensure([], () => r(require('./pages/components/File')), 'file');
1919
const Icon = (r) => require.ensure([], () => r(require('./pages/components/Icon')), 'icon');
@@ -112,7 +112,7 @@ const components = [
112112
{
113113
path: '/components/date-picker',
114114
name: 'components:date-picker',
115-
component: DatePicker
115+
component: Datepicker
116116
},
117117
{
118118
path: '/components/dialog',

src/components/mdDatePicker/mdDatePicker.scss

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
@import '../../core/stylesheets/variables.scss';
22
@import '../../core/stylesheets/mixins.scss';
33

4+
$month-width: 356px;
5+
$month-small-width: 280px;
6+
47
.md-datepicker {
58
display: flex;
69
flex: 1;
@@ -9,8 +12,27 @@
912
cursor: pointer;
1013
}
1114

12-
input::-webkit-calendar-picker-indicator{
15+
@mixin disable-input-controls {
1316
display: none;
17+
-webkit-appearance: none;
18+
}
19+
20+
input {
21+
&:-ms-clear {
22+
@include disable-input-controls;
23+
}
24+
25+
&::-webkit-clear-button {
26+
@include disable-input-controls;
27+
}
28+
29+
&::-webkit-calendar-picker-indicator {
30+
@include disable-input-controls;
31+
}
32+
33+
&::-webkit-inner-spin-button {
34+
@include disable-input-controls;
35+
}
1436
}
1537
}
1638

@@ -106,17 +128,50 @@
106128
}
107129

108130
.md-datepicker-calendar {
109-
padding: 8px;
131+
margin: 8px;
132+
overflow: hidden;
110133
text-align: center;
111134

135+
.md-button {
136+
margin: 0;
137+
}
138+
112139
.md-datepicker-controls {
113140
display: flex;
114141
justify-content: space-between;
115142
align-items: center;
143+
position: relative;
144+
z-index: 2;
116145
}
117146

118-
.md-button {
119-
margin: 0;
147+
.md-current-date {
148+
height: 40px;
149+
margin-top: -40px;
150+
display: flex;
151+
justify-content: center;
152+
align-items: center;
153+
}
154+
155+
.md-calendar-container {
156+
width: $month-width * 3;
157+
display: flex;
158+
transform: translate3d(-$month-width, 0, 0);
159+
transition: $swift-ease-out;
160+
161+
@include layout-xsmall {
162+
width: $month-small-width * 3;
163+
transform: translate3d(-$month-small-width, 0, 0);
164+
}
165+
}
166+
167+
.md-datepicker-month {
168+
width: $month-width;
169+
position: relative;
170+
z-index: 1;
171+
172+
@include layout-xsmall {
173+
width: $month-small-width;
174+
}
120175
}
121176

122177
.md-datepicker-week-days {
@@ -143,6 +198,8 @@
143198
margin: 0;
144199
}
145200

201+
202+
.md-empty,
146203
.md-button {
147204
$button-dense-height: 32px;
148205

@@ -152,10 +209,7 @@
152209
height: $button-dense-height;
153210
min-height: $button-dense-height;
154211
margin: 0 10px;
155-
padding: 0;
156212
flex: 1 1 (100% / 7);
157-
transition: $swift-ease-out;
158-
font-size: 12px;
159213
line-height: $button-dense-height;
160214

161215
@include layout-xsmall {
@@ -169,8 +223,14 @@
169223
margin: 0;
170224
line-height: $button-height;
171225
}
226+
}
227+
228+
.md-button {
229+
padding: 0;
230+
transition: $swift-ease-out;
231+
font-size: 12px;
172232

173-
&:not(.md-empty):hover,
233+
&:hover,
174234
&.md-selected,
175235
&.md-today {
176236
font-weight: 700;
@@ -192,13 +252,18 @@
192252
}
193253

194254
.md-datepicker-year {
195-
min-width: 68px;
196-
margin: 8px 0;
255+
min-width: 60px;
256+
margin: 8px 4px;
257+
padding: 0;
197258
flex: 1;
198259

199260
&.md-primary {
200261
font-weight: 900;
201262

263+
&.md-raised {
264+
box-shadow: none;
265+
}
266+
202267
@include layout-xsmall {
203268
font-size: 22px;
204269
}

src/components/mdDatePicker/mdDatePicker.theme

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
color: #{'PRIMARY-COLOR'};
4545
}
4646

47-
.md-button:not(.md-empty):hover,
47+
.md-button:hover,
4848
.md-selected {
4949
background-color: #{'PRIMARY-COLOR'};
5050
color: #{'PRIMARY-CONTRAST'};

src/components/mdDatePicker/mdDatePicker.vue

Lines changed: 104 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,24 @@
22
<div class="md-datepicker">
33
<md-icon @click.native="openPicker">event</md-icon>
44

5+
<md-input
6+
type="date"
7+
v-model="modelDate"
8+
:id="id"
9+
:name="name"
10+
:required="required"
11+
:placeholder="placeholder"
12+
:disabled="disabled"
13+
@focus.native="openOnFocus"
14+
ref="pickerInput" />
15+
516
<div class="md-datepicker-popup" :class="[themeClass, classes]" :style="styles" ref="pickerElement">
617
<div class="md-datepicker-header">
7-
<span class="md-datepicker-year-select" @click="currentView = 'year'">{{ currentDate.getFullYear() }}</span>
8-
<div class="md-datepicker-date-select" @click="currentView = 'date'">
9-
<strong class="md-datepicker-dayname">{{ locale.shortDays[currentDate.getDay()] }},</strong>
10-
<strong class="md-datepicker-monthname">{{ locale.shortMonths[currentDate.getMonth()] }}</strong>
11-
<strong class="md-datepicker-day">{{ currentDate.getDate() }}</strong>
18+
<span class="md-datepicker-year-select" @click="showYearPicker">{{ selectedDate.getFullYear() }}</span>
19+
<div class="md-datepicker-date-select" @click="showDatePicker">
20+
<strong class="md-datepicker-dayname">{{ locale.shortDays[selectedDate.getDay()] }},</strong>
21+
<strong class="md-datepicker-monthname">{{ locale.shortMonths[selectedDate.getMonth()] }}</strong>
22+
<strong class="md-datepicker-day">{{ selectedDate.getDate() }}</strong>
1223
</div>
1324
</div>
1425

@@ -19,25 +30,53 @@
1930
<md-icon>keyboard_arrow_left</md-icon>
2031
</md-button>
2132

22-
<span class="md-current-date">{{ locale.months[currentDate.getMonth()] }} {{ currentDate.getFullYear() }}</span>
23-
2433
<md-button class="md-icon-button">
2534
<md-icon>keyboard_arrow_right</md-icon>
2635
</md-button>
2736
</div>
2837

29-
<div class="md-datepicker-week-days">
30-
<span v-for="day in locale.shorterDays">{{ day }}</span>
31-
</div>
38+
<div class="md-calendar-container">
39+
<div class="md-datepicker-month" v-for="month in createdMonths">
40+
<span class="md-current-date">{{ locale.months[month.getMonth()] }} {{ month.getFullYear() }}</span>
41+
42+
<div class="md-datepicker-week-days">
43+
<span v-for="day in locale.shorterDays">{{ day }}</span>
44+
</div>
3245

33-
<div class="md-datepicker-days">
34-
<md-button class="md-icon-button md-empty" v-for="day in startOfMonth(currentDate).getDay()" disabled></md-button>
35-
<md-button class="md-icon-button" :class="{ 'md-today': isToday(day, currentDate) }" v-for="day in getDaysInMonth(currentDate)">{{ day }}</md-button>
46+
<div class="md-datepicker-days">
47+
<span class="md-empty" v-for="day in startOfMonth(month).getDay()"></span>
48+
49+
<md-button
50+
class="md-icon-button"
51+
v-for="day in getDaysInMonth(month)"
52+
:key="day"
53+
:class="{
54+
'md-today': isToday(day),
55+
'md-selected': isSelectedDay(day)
56+
}"
57+
@click.native="selectDate(day)">
58+
{{ day }}
59+
</md-button>
60+
</div>
61+
</div>
3662
</div>
3763
</div>
3864

3965
<div class="md-datepicker-years" v-show="currentView === 'year'">
40-
<md-button class="md-dense md-datepicker-year" :class="{ 'md-primary': isThisYear(year, currentDate) }" v-for="year in visibleYears()" @click="setYear(year)">{{ year }}</md-button>
66+
<md-button
67+
class="md-dense md-datepicker-year"
68+
v-for="year in visibleYears()"
69+
:key="year"
70+
:class="[
71+
{
72+
'md-primary': isThisYear(year),
73+
'md-primary md-raised': isSelectedYear(year),
74+
},
75+
'data-' + year
76+
]"
77+
@click.native="setYear(year)">
78+
{{ year }}
79+
</md-button>
4180
</div>
4281

4382
<div class="md-datepicker-actions md-dialog-actions">
@@ -48,17 +87,6 @@
4887
</div>
4988

5089
<md-backdrop class="md-datepicker-backdrop" :class="classes" @close="closePicker" ref="pickerBackdrop" />
51-
52-
<md-input
53-
type="date"
54-
v-model="value"
55-
:id="id"
56-
:name="name"
57-
:required="required"
58-
:placeholder="placeholder"
59-
:disabled="disabled"
60-
@focus.native="mdOpenOnFocus || openPicker"
61-
ref="pickerInput" />
6290
</div>
6391
</template>
6492

@@ -69,12 +97,14 @@
6997
import getClosestVueParent from '../../core/utils/getClosestVueParent';
7098
import getInViewPosition from '../../core/utils/getInViewPosition';
7199
import transitionEndEventName from '../../core/utils/transitionEndEventName';
72-
import startOfMonth from 'date-fns/start_of_month';
73100
import formatDate from 'date-fns/format';
101+
import startOfMonth from 'date-fns/start_of_month';
102+
import addMonths from 'date-fns/add_months';
74103
import getDaysInMonth from 'date-fns/get_days_in_month';
75104
import setDate from 'date-fns/set_date';
76105
import setYear from 'date-fns/set_year';
77106
import isToday from 'date-fns/is_today';
107+
import isSameDay from 'date-fns/is_same_day';
78108
import isThisYear from 'date-fns/is_this_year';
79109
80110
export default {
@@ -108,8 +138,14 @@
108138
109139
return years;
110140
},
111-
currentView: 'date',
112-
currentDate: new Date(this.value)
141+
currentDate: new Date(this.value),
142+
selectedDate: new Date(this.value),
143+
createdMonths: [
144+
addMonths(this.value, -1),
145+
this.value,
146+
addMonths(this.value, 1)
147+
],
148+
currentView: 'date'
113149
};
114150
},
115151
computed: {
@@ -126,25 +162,43 @@
126162
left: this.pickerPosition.left
127163
};
128164
},
165+
modelDate() {
166+
return formatDate(this.selectedDate, this.locale.dateFormat);
167+
},
129168
locale() {
130169
return this.$material.locale;
131170
}
132171
},
133172
methods: {
134-
startOfMonth,
135-
getDaysInMonth,
136-
isToday(day, fullDate) {
137-
return isToday(setDate(fullDate, day));
173+
startOfMonth(month) {
174+
return startOfMonth(month);
175+
},
176+
getDaysInMonth(month) {
177+
return getDaysInMonth(month);
178+
},
179+
isToday(day) {
180+
return isToday(setDate(new Date(), day));
138181
},
139-
isThisYear(year, fullDate) {
140-
return isThisYear(setYear(fullDate, year));
182+
isThisYear(year) {
183+
return isThisYear(setYear(new Date(), year));
184+
},
185+
isSelectedDay(day) {
186+
return isSameDay(this.selectedDate, setDate(this.selectedDate, day));
187+
},
188+
isSelectedYear(year) {
189+
return isSameDay(this.selectedDate, setYear(this.selectedDate, year));
141190
},
142191
setYear(year) {
143-
this.setModelValue(setYear(this.currentDate, year));
192+
this.setModelValue(setYear(this.selectedDate, year));
144193
},
145194
setModelValue(date) {
146-
this.currentDate = date;
147-
this.$emit('input', formatDate(date, this.locale.dateFormat));
195+
this.selectedDate = date;
196+
this.$emit('input', this.modelDate);
197+
},
198+
openOnFocus() {
199+
if (this.mdOpenOnFocus) {
200+
this.openPicker();
201+
}
148202
},
149203
calculatePopupPosition() {
150204
window.requestAnimationFrame(() => {
@@ -179,8 +233,21 @@
179233
window.removeEventListener('resize', this.calculatePopupPosition);
180234
this.pickerElement.removeEventListener(transitionEndEventName, cleanUp);
181235
this.pickerElement.addEventListener(transitionEndEventName, cleanUp);
236+
this.showDatePicker();
182237
this.active = false;
238+
},
239+
showDatePicker() {
183240
this.currentView = 'date';
241+
},
242+
showYearPicker() {
243+
this.currentView = 'year';
244+
245+
this.$nextTick(() => {
246+
this.pickerElement.querySelector(`.data-${this.selectedDate.getFullYear()}`).scrollIntoViewIfNeeded(true);
247+
});
248+
},
249+
selectDate(day) {
250+
this.selectedDate = setDate(this.selectedDate, day);
184251
}
185252
},
186253
mounted() {

0 commit comments

Comments
 (0)