@operato/event-view 8.0.0-alpha.53 → 8.0.0-beta.1
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/CHANGELOG.md +17 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/.editorconfig +0 -29
- package/.storybook/main.js +0 -3
- package/.storybook/preview.js +0 -52
- package/.storybook/server.mjs +0 -8
- package/src/calendar-monthly-styles.ts +0 -113
- package/src/calendar-monthly.ts +0 -220
- package/src/calendar-weekly-styles.ts +0 -113
- package/src/calendar-weekly.ts +0 -218
- package/src/index.ts +0 -2
- package/src/ox-event-view.ts +0 -47
- package/src/types.ts +0 -38
- package/stories/index.stories.ts +0 -123
- package/tsconfig.json +0 -25
- package/web-dev-server.config.mjs +0 -27
- package/web-test-runner.config.mjs +0 -41
package/src/calendar-monthly.ts
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import '@material/web/button/text-button.js'
|
|
2
|
-
|
|
3
|
-
import dayjs, { Dayjs } from 'dayjs/esm/index'
|
|
4
|
-
import { html, LitElement, PropertyValues } from 'lit'
|
|
5
|
-
import { customElement, property, state } from 'lit/decorators.js'
|
|
6
|
-
|
|
7
|
-
import { CalendarMonthlyStyles } from './calendar-monthly-styles'
|
|
8
|
-
import { BizEvent, CALENDAR, WEEKDAYS, EventProvider, isToday } from './types'
|
|
9
|
-
|
|
10
|
-
@customElement('calendar-monthly')
|
|
11
|
-
export class CalendarMonthly extends LitElement {
|
|
12
|
-
static styles = [CalendarMonthlyStyles]
|
|
13
|
-
|
|
14
|
-
@property({ type: Object }) eventProvider?: EventProvider
|
|
15
|
-
|
|
16
|
-
@state() year: number = dayjs().year()
|
|
17
|
-
@state() month: number = dayjs().month()
|
|
18
|
-
@state() calendar?: CALENDAR
|
|
19
|
-
@state() eventMap?: Map<Date, BizEvent[]>
|
|
20
|
-
@state() selections?: [Date, Date] | []
|
|
21
|
-
|
|
22
|
-
@state() pointerDownDate?: Date | null
|
|
23
|
-
|
|
24
|
-
render() {
|
|
25
|
-
return html`
|
|
26
|
-
<div head>
|
|
27
|
-
<div this-month><b>${dayjs(new Date(this.year, this.month)).format('MMMM')}</b> ${this.year}</div>
|
|
28
|
-
|
|
29
|
-
<div nav>
|
|
30
|
-
<md-text-button
|
|
31
|
-
@click=${() => {
|
|
32
|
-
this.moveTo(dayjs(new Date(this.year, this.month, 1)).subtract(1, 'month'))
|
|
33
|
-
}}
|
|
34
|
-
><</md-text-button
|
|
35
|
-
>
|
|
36
|
-
<md-text-button
|
|
37
|
-
@click=${() => {
|
|
38
|
-
this.moveTo(dayjs(new Date(dayjs().year(), dayjs().month(), 1)))
|
|
39
|
-
}}
|
|
40
|
-
>Today</md-text-button
|
|
41
|
-
>
|
|
42
|
-
<md-text-button
|
|
43
|
-
@click=${() => {
|
|
44
|
-
this.moveTo(dayjs(new Date(this.year, this.month, 1)).add(1, 'month'))
|
|
45
|
-
}}
|
|
46
|
-
>></md-text-button
|
|
47
|
-
>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<slot></slot>
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<ol
|
|
54
|
-
@pointerdown=${this.handlePointerDown}
|
|
55
|
-
@pointermove=${this.handlePointerMove}
|
|
56
|
-
@pointerup=${this.handlePointerUp}
|
|
57
|
-
>
|
|
58
|
-
${WEEKDAYS.map(date => html` <li day-of-week>${date}</li> `)}
|
|
59
|
-
${this.calendar?.map(date => {
|
|
60
|
-
const [from, to] = this.selections || ([] as any)
|
|
61
|
-
const { date: thisDate } = date
|
|
62
|
-
const selected = from && to && thisDate >= from && thisDate <= to
|
|
63
|
-
|
|
64
|
-
return html`
|
|
65
|
-
<li ?today=${date.today} ?current-month=${date.thisMonth} ?selected=${selected} .date=${thisDate} date>
|
|
66
|
-
<span date-label>${date.label}</span>
|
|
67
|
-
<div>
|
|
68
|
-
${(this.eventMap?.get(date?.date) || []).map(({ title, color, template }) =>
|
|
69
|
-
template ? template : html`<span event .style="border-color: ${color};">${title}</span>`
|
|
70
|
-
)}
|
|
71
|
-
</div>
|
|
72
|
-
</li>
|
|
73
|
-
`
|
|
74
|
-
})}
|
|
75
|
-
</ol>
|
|
76
|
-
`
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async updated(changes: PropertyValues<this>) {
|
|
80
|
-
if (changes.has('year') || changes.has('month') || changes.has('eventProvider')) {
|
|
81
|
-
const currentMonth = this.createDaysForCurrentMonth(this.year, this.month)
|
|
82
|
-
|
|
83
|
-
const calendar = [
|
|
84
|
-
...this.createDaysForPreviousMonth(this.year, this.month, currentMonth),
|
|
85
|
-
...currentMonth,
|
|
86
|
-
...this.createDaysForNextMonth(this.year, this.month, currentMonth)
|
|
87
|
-
]
|
|
88
|
-
|
|
89
|
-
this.eventMap = await this.eventProvider?.fetchEventsForCalendar(calendar)
|
|
90
|
-
this.calendar = calendar
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
handlePointerDown(event: PointerEvent) {
|
|
95
|
-
const target = event.target as HTMLElement
|
|
96
|
-
|
|
97
|
-
if (!target.hasAttribute('date') && !target.hasAttribute('date-label')) {
|
|
98
|
-
return
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const dateElement = target.closest('[date]') as HTMLElement
|
|
102
|
-
const from = (dateElement as any).date
|
|
103
|
-
|
|
104
|
-
this.pointerDownDate = from
|
|
105
|
-
|
|
106
|
-
// 캡처를 설정하지 않음(Touch 디바이스에서 중요)
|
|
107
|
-
target.releasePointerCapture(event.pointerId)
|
|
108
|
-
|
|
109
|
-
event.preventDefault()
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
handlePointerMove(event: PointerEvent) {
|
|
113
|
-
const from = this.pointerDownDate
|
|
114
|
-
|
|
115
|
-
if (!from) {
|
|
116
|
-
return
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const target = event.target as HTMLElement
|
|
120
|
-
const dateElement = target.closest('[date]') as HTMLElement
|
|
121
|
-
|
|
122
|
-
if (!dateElement) {
|
|
123
|
-
return
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const date = (dateElement as any).date
|
|
127
|
-
this.selections = from > date ? [date, from] : [from, date]
|
|
128
|
-
|
|
129
|
-
// 캡처를 설정하지 않음(Touch 디바이스에서 중요)
|
|
130
|
-
target.releasePointerCapture(event.pointerId)
|
|
131
|
-
|
|
132
|
-
event.preventDefault()
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
handlePointerUp(event: PointerEvent) {
|
|
136
|
-
const from = this.pointerDownDate
|
|
137
|
-
|
|
138
|
-
this.pointerDownDate = null
|
|
139
|
-
|
|
140
|
-
if (!from) {
|
|
141
|
-
return
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const target = event.target as HTMLElement
|
|
145
|
-
const dateElement = target.closest('[date]') as HTMLElement
|
|
146
|
-
|
|
147
|
-
if (!dateElement) {
|
|
148
|
-
return
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const date = (dateElement as any).date
|
|
152
|
-
this.selections = from > date ? [date, from] : [from, date]
|
|
153
|
-
|
|
154
|
-
this.dispatchEvent(
|
|
155
|
-
new CustomEvent('select-date', {
|
|
156
|
-
detail: this.selections,
|
|
157
|
-
bubbles: true,
|
|
158
|
-
composed: true
|
|
159
|
-
})
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
event.preventDefault()
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
moveTo(month: Dayjs) {
|
|
166
|
-
this.year = month.year()
|
|
167
|
-
this.month = month.month()
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
createDaysForCurrentMonth(year: number, month: number): CALENDAR {
|
|
171
|
-
return [...Array(dayjs(new Date(year, month, 1)).daysInMonth())].map((day, index) => {
|
|
172
|
-
const date = new Date(year, month, index + 1)
|
|
173
|
-
const label = index == 0 ? dayjs(date).format('MMM D') : dayjs(date).format('D')
|
|
174
|
-
return {
|
|
175
|
-
date,
|
|
176
|
-
label,
|
|
177
|
-
thisMonth: true,
|
|
178
|
-
today: isToday(date)
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
createDaysForPreviousMonth(year: number, month: number, currentMonth: CALENDAR): CALENDAR {
|
|
184
|
-
const previousMonth = dayjs(new Date(year, month, 1)).subtract(1, 'month')
|
|
185
|
-
|
|
186
|
-
const visibleNumberOfDaysFromPreviousMonth = (dayjs(currentMonth[0].date) as any).weekday()
|
|
187
|
-
|
|
188
|
-
const previousMonthLastMondayDayOfMonth = dayjs(currentMonth[0].date)
|
|
189
|
-
.subtract(visibleNumberOfDaysFromPreviousMonth, 'day')
|
|
190
|
-
.date()
|
|
191
|
-
|
|
192
|
-
return [...Array(visibleNumberOfDaysFromPreviousMonth)].map((day, index) => {
|
|
193
|
-
const date = new Date(previousMonth.year(), previousMonth.month(), previousMonthLastMondayDayOfMonth + index)
|
|
194
|
-
const label = index == 0 ? dayjs(date).format('MMM D') : dayjs(date).format('D')
|
|
195
|
-
return {
|
|
196
|
-
date,
|
|
197
|
-
label,
|
|
198
|
-
thisMonth: false,
|
|
199
|
-
today: isToday(date)
|
|
200
|
-
}
|
|
201
|
-
})
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
createDaysForNextMonth(year: number, month: number, currentMonth: CALENDAR): CALENDAR {
|
|
205
|
-
const nextMonth = dayjs(new Date(year, month, 1)).add(1, 'month')
|
|
206
|
-
|
|
207
|
-
const visibleNumberOfDaysFromNextMonth = 6 - (dayjs(new Date(year, month, currentMonth.length)) as any).weekday()
|
|
208
|
-
|
|
209
|
-
return [...Array(visibleNumberOfDaysFromNextMonth)].map((day, index) => {
|
|
210
|
-
const date = new Date(nextMonth.year(), nextMonth.month(), index + 1)
|
|
211
|
-
const label = index == 0 ? dayjs(date).format('MMM D') : dayjs(date).format('D')
|
|
212
|
-
return {
|
|
213
|
-
date,
|
|
214
|
-
label,
|
|
215
|
-
thisMonth: false,
|
|
216
|
-
today: isToday(date)
|
|
217
|
-
}
|
|
218
|
-
})
|
|
219
|
-
}
|
|
220
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { css } from 'lit'
|
|
2
|
-
|
|
3
|
-
export const CalendarWeeklyStyles = css`
|
|
4
|
-
:host {
|
|
5
|
-
display: flex;
|
|
6
|
-
flex-direction: column;
|
|
7
|
-
color: var(--calendar-weekly-text-color, #585858);
|
|
8
|
-
|
|
9
|
-
--md-text-button-container-height: 24px;
|
|
10
|
-
--md-sys-color-primary: rgba(var(--secondary-color-rgb), 0.8);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
[head] {
|
|
14
|
-
display: flex;
|
|
15
|
-
align-items: center;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
[head-week] {
|
|
19
|
-
display: flex;
|
|
20
|
-
align-items: left;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
[this-week] {
|
|
24
|
-
font-size: x-large;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
[nav] {
|
|
28
|
-
margin-left: auto;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
::slotted(*) {
|
|
32
|
-
color: var(--md-sys-color-primary);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
ol {
|
|
36
|
-
flex: 1;
|
|
37
|
-
|
|
38
|
-
display: grid;
|
|
39
|
-
grid-template-columns: repeat(7, 1fr);
|
|
40
|
-
grid-template-rows: max-content;
|
|
41
|
-
|
|
42
|
-
padding: 0;
|
|
43
|
-
margin: var(--calendar-weekly-ol-margin, 9px 0);
|
|
44
|
-
border-top: var(--calendar-weekly-ol-top-border, 3px solid #999);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
li {
|
|
48
|
-
position: relative;
|
|
49
|
-
|
|
50
|
-
list-style: none;
|
|
51
|
-
border: var(--calendar-weekly-border, 1px solid rgba(0, 0, 0, 0.1));
|
|
52
|
-
border-width: var(--calendar-weekly-border-width, 0 1px 1px 0px);
|
|
53
|
-
opacity: var(--calendar-weekly-opacity);
|
|
54
|
-
|
|
55
|
-
user-select: none;
|
|
56
|
-
touch-action: none;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
li:nth-child(7n + 1) {
|
|
60
|
-
border-left-width: 1px;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
li[day-of-week] {
|
|
64
|
-
opacity: 1;
|
|
65
|
-
background-color: var(--calendar-current-week-background-color, var(--md-sys-color-surface-variant));
|
|
66
|
-
color: var(--calendar-current-week-color, var(--md-sys-color-on-surface));
|
|
67
|
-
padding: var(--calendar-weekly-label-padding);
|
|
68
|
-
text-align: center;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
li[current-week] {
|
|
72
|
-
background-color: var(--calendar-current-week-background-color, #fff);
|
|
73
|
-
opacity: 1;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
li[selected] {
|
|
77
|
-
background-color: var(--calendar-weekly-selected-background-color, var(--md-sys-color-tertiary-container));
|
|
78
|
-
color: var(--calendar-weekly-selected-color, var(--md-sys-color-on-tertiary-container));
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
span[date-label] {
|
|
82
|
-
display: block;
|
|
83
|
-
margin: var(--calendar-weekly-date-label-margin);
|
|
84
|
-
text-align: var(--calendar-weekly-label-align, center);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
li[today] > span[date-label] {
|
|
88
|
-
display: inline-block;
|
|
89
|
-
background-color: var(--calendar-weekly-date-label-background-color, #cc3300);
|
|
90
|
-
padding: var(--calendar-weekly-date-label-padding);
|
|
91
|
-
border-radius: var(--calendar-weekly-date-label-border-radius, 999em);
|
|
92
|
-
color: var(--calendar-weekly-date-label-color, #fff);
|
|
93
|
-
min-width: 16px;
|
|
94
|
-
text-align: center;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
[date] div {
|
|
98
|
-
display: block;
|
|
99
|
-
font-size: small;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
[event] {
|
|
103
|
-
display: block;
|
|
104
|
-
background-color: var(--calendar-weekly-background-color);
|
|
105
|
-
border: var(--calendar-weekly-event-border);
|
|
106
|
-
border-width: var(--calendar-weekly-event-border-width);
|
|
107
|
-
margin: var(--calendar-weekly-event-margin, 0 0 4px 0);
|
|
108
|
-
padding: var(--calendar-weekly-event-padding, 2px 4px 2px 4px);
|
|
109
|
-
|
|
110
|
-
user-select: all;
|
|
111
|
-
touch-action: all;
|
|
112
|
-
}
|
|
113
|
-
`
|
package/src/calendar-weekly.ts
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import '@material/web/button/text-button.js'
|
|
2
|
-
|
|
3
|
-
import dayjs, { Dayjs } from 'dayjs/esm/index'
|
|
4
|
-
import { html, LitElement, PropertyValues } from 'lit'
|
|
5
|
-
import { customElement, property, state } from 'lit/decorators.js'
|
|
6
|
-
|
|
7
|
-
import { CalendarWeeklyStyles } from './calendar-weekly-styles'
|
|
8
|
-
import { BizEvent, CALENDAR, WEEKDAYS, EventProvider, isToday } from './types'
|
|
9
|
-
|
|
10
|
-
@customElement('calendar-weekly')
|
|
11
|
-
export class CalendarWeekly extends LitElement {
|
|
12
|
-
static styles = [CalendarWeeklyStyles]
|
|
13
|
-
|
|
14
|
-
@property({ type: Object }) eventProvider?: EventProvider
|
|
15
|
-
|
|
16
|
-
@state() year: number = dayjs().year()
|
|
17
|
-
@state() month: number = dayjs().month()
|
|
18
|
-
@state() week: number = dayjs().week()
|
|
19
|
-
@state() calendar?: CALENDAR
|
|
20
|
-
@state() eventMap?: Map<Date, BizEvent[]>
|
|
21
|
-
@state() selections?: [Date, Date]
|
|
22
|
-
|
|
23
|
-
@state() pointerDownDate?: Date | null
|
|
24
|
-
|
|
25
|
-
render() {
|
|
26
|
-
return html`
|
|
27
|
-
<div head>
|
|
28
|
-
<div this-week>
|
|
29
|
-
<b>${dayjs(new Date(this.year, this.month)).format('MMMM')}</b> ${this.year} <b>Week ${this.week}</b>
|
|
30
|
-
</div>
|
|
31
|
-
|
|
32
|
-
<div nav>
|
|
33
|
-
<md-text-button
|
|
34
|
-
@click=${() => {
|
|
35
|
-
const dayJs = this.getLastDateOfWeek(this.year, this.week)
|
|
36
|
-
const prevWeek = dayJs.subtract(1, 'week')
|
|
37
|
-
this.moveTo(prevWeek.year(), prevWeek.month(), prevWeek.week())
|
|
38
|
-
}}
|
|
39
|
-
><</md-text-button
|
|
40
|
-
>
|
|
41
|
-
<md-text-button
|
|
42
|
-
@click=${() => {
|
|
43
|
-
this.moveTo(dayjs().year(), dayjs().month(), dayjs().week())
|
|
44
|
-
}}
|
|
45
|
-
>Today</md-text-button
|
|
46
|
-
>
|
|
47
|
-
<md-text-button
|
|
48
|
-
@click=${() => {
|
|
49
|
-
const dayJs = this.getLastDateOfWeek(this.year, this.week)
|
|
50
|
-
const nextWeek = dayJs.add(1, 'week')
|
|
51
|
-
this.moveTo(nextWeek.year(), nextWeek.month(), nextWeek.week())
|
|
52
|
-
}}
|
|
53
|
-
>></md-text-button
|
|
54
|
-
>
|
|
55
|
-
</div>
|
|
56
|
-
|
|
57
|
-
<slot></slot>
|
|
58
|
-
</div>
|
|
59
|
-
|
|
60
|
-
<ol
|
|
61
|
-
@pointerdown=${this.handlePointerDown}
|
|
62
|
-
@pointermove=${this.handlePointerMove}
|
|
63
|
-
@pointerup=${this.handlePointerUp}
|
|
64
|
-
>
|
|
65
|
-
${this.calendar?.map((date, index) => {
|
|
66
|
-
const [from, to] = this.selections || ([] as any)
|
|
67
|
-
const { date: thisDate } = date
|
|
68
|
-
const selected = from && to && thisDate >= from && thisDate <= to
|
|
69
|
-
|
|
70
|
-
return html`
|
|
71
|
-
<li ?today=${date.today} day-of-week date .date=${thisDate} ?selected=${selected}>
|
|
72
|
-
<span date-label>${date.label}(${WEEKDAYS[index]})</span>
|
|
73
|
-
</li>
|
|
74
|
-
`
|
|
75
|
-
})}
|
|
76
|
-
${this.calendar?.map(date => {
|
|
77
|
-
const [from, to] = this.selections || ([] as any)
|
|
78
|
-
const { date: thisDate } = date
|
|
79
|
-
const selected = from && to && thisDate >= from && thisDate <= to
|
|
80
|
-
|
|
81
|
-
return html`<li date .date=${thisDate} ?selected=${selected}>
|
|
82
|
-
<div>
|
|
83
|
-
${(this.eventMap?.get(date?.date) || []).map(({ title, color, template }) =>
|
|
84
|
-
template ? template : html`<span event .style="border-color: ${color};">${title}</span>`
|
|
85
|
-
)}
|
|
86
|
-
</div>
|
|
87
|
-
</li>`
|
|
88
|
-
})}
|
|
89
|
-
</ol>
|
|
90
|
-
`
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async updated(changes: PropertyValues<this>) {
|
|
94
|
-
if (changes.has('year') || changes.has('month') || changes.has('week') || changes.has('eventProvider')) {
|
|
95
|
-
const calendar = this.createDaysForCurrentWeek(this.year, this.week)
|
|
96
|
-
|
|
97
|
-
this.eventMap = await this.eventProvider?.fetchEventsForCalendar(calendar)
|
|
98
|
-
this.calendar = calendar
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
moveTo(year: number, month: number, week: number) {
|
|
103
|
-
this.year = year
|
|
104
|
-
this.month = month
|
|
105
|
-
this.week = week
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
handlePointerDown(event: PointerEvent) {
|
|
109
|
-
const target = event.target as HTMLElement
|
|
110
|
-
|
|
111
|
-
if (!target.hasAttribute('date') && !target.hasAttribute('date-label')) {
|
|
112
|
-
return
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const dateElement = target.closest('[date]') as HTMLElement
|
|
116
|
-
const from = (dateElement as any).date
|
|
117
|
-
|
|
118
|
-
this.pointerDownDate = from
|
|
119
|
-
|
|
120
|
-
// 캡처를 설정하지 않음(Touch 디바이스에서 중요)
|
|
121
|
-
target.releasePointerCapture(event.pointerId)
|
|
122
|
-
|
|
123
|
-
event.preventDefault()
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
handlePointerMove(event: PointerEvent) {
|
|
127
|
-
const from = this.pointerDownDate
|
|
128
|
-
|
|
129
|
-
if (!from) {
|
|
130
|
-
return
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const target = event.target as HTMLElement
|
|
134
|
-
const dateElement = target.closest('[date]') as HTMLElement
|
|
135
|
-
|
|
136
|
-
if (!dateElement) {
|
|
137
|
-
return
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const date = (dateElement as any).date
|
|
141
|
-
this.selections = from > date ? [date, from] : [from, date]
|
|
142
|
-
|
|
143
|
-
// 캡처를 설정하지 않음(Touch 디바이스에서 중요)
|
|
144
|
-
target.releasePointerCapture(event.pointerId)
|
|
145
|
-
|
|
146
|
-
event.preventDefault()
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
handlePointerUp(event: PointerEvent) {
|
|
150
|
-
const from = this.pointerDownDate
|
|
151
|
-
|
|
152
|
-
this.pointerDownDate = null
|
|
153
|
-
|
|
154
|
-
if (!from) {
|
|
155
|
-
return
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
const target = event.target as HTMLElement
|
|
159
|
-
const dateElement = target.closest('[date]') as HTMLElement
|
|
160
|
-
|
|
161
|
-
if (!dateElement) {
|
|
162
|
-
return
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const date = (dateElement as any).date
|
|
166
|
-
this.selections = from > date ? [date, from] : [from, date]
|
|
167
|
-
|
|
168
|
-
this.dispatchEvent(
|
|
169
|
-
new CustomEvent('select-date', {
|
|
170
|
-
detail: this.selections,
|
|
171
|
-
bubbles: true,
|
|
172
|
-
composed: true
|
|
173
|
-
})
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
event.preventDefault()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
selectDate(date: { label: string; date: Date; thisMonth?: boolean; thisWeek?: boolean; today?: boolean }) {
|
|
180
|
-
if (date) {
|
|
181
|
-
this.selections = [date.date, date.date]
|
|
182
|
-
} else {
|
|
183
|
-
this.selections = undefined
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
this.dispatchEvent(
|
|
187
|
-
new CustomEvent('select-date', {
|
|
188
|
-
detail: date,
|
|
189
|
-
bubbles: true,
|
|
190
|
-
composed: true
|
|
191
|
-
})
|
|
192
|
-
)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
getLastDateOfWeek(year: number, week: number): Dayjs {
|
|
196
|
-
const firstWeekLastDay = dayjs(new Date(year, 0, 1)).endOf('w')
|
|
197
|
-
week -= 1 // one-based week, so need the minus-one
|
|
198
|
-
return firstWeekLastDay.add(week, 'w')
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
createDaysForCurrentWeek(year: number, week: number): CALENDAR {
|
|
202
|
-
const lastDayjs = this.getLastDateOfWeek(year, week)
|
|
203
|
-
const weekDays = 7
|
|
204
|
-
|
|
205
|
-
return [...Array(weekDays)]
|
|
206
|
-
.map((day, index) => {
|
|
207
|
-
const date = new Date(lastDayjs.year(), lastDayjs.month(), lastDayjs.date() - index)
|
|
208
|
-
const label = dayjs(date).format('MM-DD')
|
|
209
|
-
return {
|
|
210
|
-
date,
|
|
211
|
-
label,
|
|
212
|
-
thisWeek: true,
|
|
213
|
-
today: isToday(date)
|
|
214
|
-
}
|
|
215
|
-
})
|
|
216
|
-
.reverse()
|
|
217
|
-
}
|
|
218
|
-
}
|
package/src/index.ts
DELETED
package/src/ox-event-view.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import '@material/web/icon/icon.js'
|
|
2
|
-
|
|
3
|
-
import './calendar-monthly'
|
|
4
|
-
import './calendar-weekly'
|
|
5
|
-
|
|
6
|
-
import { css, html, LitElement } from 'lit'
|
|
7
|
-
import { customElement, property } from 'lit/decorators.js'
|
|
8
|
-
|
|
9
|
-
import { EventProvider } from './types'
|
|
10
|
-
|
|
11
|
-
@customElement('ox-event-view')
|
|
12
|
-
export class OxEventView extends LitElement {
|
|
13
|
-
static styles = css`
|
|
14
|
-
:host {
|
|
15
|
-
display: flex;
|
|
16
|
-
flex-direction: column;
|
|
17
|
-
|
|
18
|
-
background-color: var(--md-sys-color-background);
|
|
19
|
-
color: var(--md-sys-color-on-background);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
calendar-weekly,
|
|
23
|
-
calendar-monthly {
|
|
24
|
-
flex: 1;
|
|
25
|
-
|
|
26
|
-
padding: 0;
|
|
27
|
-
margin: 0;
|
|
28
|
-
}
|
|
29
|
-
`
|
|
30
|
-
|
|
31
|
-
@property({ type: String }) mode: 'monthly' | 'weekly' = 'monthly'
|
|
32
|
-
@property({ type: Object }) eventProvider?: EventProvider
|
|
33
|
-
|
|
34
|
-
render() {
|
|
35
|
-
return this.mode == 'weekly'
|
|
36
|
-
? html`
|
|
37
|
-
<calendar-weekly .eventProvider=${this.eventProvider}>
|
|
38
|
-
<md-icon @click=${(e: Event) => (this.mode = 'monthly')}>calendar_month</md-icon>
|
|
39
|
-
</calendar-weekly>
|
|
40
|
-
`
|
|
41
|
-
: html`
|
|
42
|
-
<calendar-monthly .eventProvider=${this.eventProvider}>
|
|
43
|
-
<md-icon @click=${(e: Event) => (this.mode = 'weekly')}>calendar_view_week</md-icon>
|
|
44
|
-
</calendar-monthly>
|
|
45
|
-
`
|
|
46
|
-
}
|
|
47
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { TemplateResult } from 'lit'
|
|
2
|
-
import dayjs from 'dayjs/esm/index'
|
|
3
|
-
import weekday from 'dayjs/esm/plugin/weekday'
|
|
4
|
-
import weekOfYear from 'dayjs/esm/plugin/weekOfYear'
|
|
5
|
-
|
|
6
|
-
dayjs.extend(weekday)
|
|
7
|
-
dayjs.extend(weekOfYear)
|
|
8
|
-
|
|
9
|
-
export type BizEvent = {
|
|
10
|
-
due?: string
|
|
11
|
-
title: string
|
|
12
|
-
color: string
|
|
13
|
-
clickEvent?: any
|
|
14
|
-
template?: TemplateResult
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export type CALENDAR = {
|
|
18
|
-
label: string
|
|
19
|
-
date: Date
|
|
20
|
-
thisMonth?: boolean
|
|
21
|
-
thisWeek?: boolean
|
|
22
|
-
today?: boolean
|
|
23
|
-
}[]
|
|
24
|
-
|
|
25
|
-
export interface EventProvider {
|
|
26
|
-
fetchEventsForCalendar(calendar: CALENDAR): Promise<Map<Date, BizEvent[]>>
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
|
30
|
-
|
|
31
|
-
export function isToday(date: Date) {
|
|
32
|
-
const today = new Date()
|
|
33
|
-
return (
|
|
34
|
-
date.getDate() == today.getDate() &&
|
|
35
|
-
date.getMonth() == today.getMonth() &&
|
|
36
|
-
date.getFullYear() == today.getFullYear()
|
|
37
|
-
)
|
|
38
|
-
}
|