@operato/event-view 8.0.0-beta.0 β†’ 8.0.0-beta.2

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 CHANGED
@@ -3,6 +3,24 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [8.0.0-beta.2](https://github.com/hatiolab/operato/compare/v8.0.0-beta.1...v8.0.0-beta.2) (2025-01-08)
7
+
8
+
9
+ ### :bug: Bug Fix
10
+
11
+ * typo .npmignore ([d9c0c8c](https://github.com/hatiolab/operato/commit/d9c0c8c79abc688c3c2cfb6c37fcb689483a5977))
12
+
13
+
14
+
15
+ ## [8.0.0-beta.1](https://github.com/hatiolab/operato/compare/v8.0.0-beta.0...v8.0.0-beta.1) (2025-01-08)
16
+
17
+
18
+ ### :bug: Bug Fix
19
+
20
+ * missing .npmignore ([be05985](https://github.com/hatiolab/operato/commit/be05985abfae4af53501f718dd52932099f7fbcb))
21
+
22
+
23
+
6
24
  ## [8.0.0-beta.0](https://github.com/hatiolab/operato/compare/v8.0.0-alpha.56...v8.0.0-beta.0) (2025-01-07)
7
25
 
8
26
  **Note:** Version bump only for package @operato/event-view
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@operato/event-view",
3
3
  "description": "Webcomponent event-view following open-wc recommendations",
4
4
  "author": "heartyoh@hatiolab.com",
5
- "version": "8.0.0-beta.0",
5
+ "version": "8.0.0-beta.2",
6
6
  "main": "dist/src/index.js",
7
7
  "module": "dist/src/index.js",
8
8
  "license": "MIT",
@@ -81,5 +81,5 @@
81
81
  "prettier --write"
82
82
  ]
83
83
  },
84
- "gitHead": "c4e9cc245659d050a9ffd66542083a6daad4bcb9"
84
+ "gitHead": "ee1b5124995accb99272d3b5854f3df1d8746dda"
85
85
  }
package/.editorconfig DELETED
@@ -1,29 +0,0 @@
1
- # EditorConfig helps developers define and maintain consistent
2
- # coding styles between different editors and IDEs
3
- # editorconfig.org
4
-
5
- root = true
6
-
7
-
8
- [*]
9
-
10
- # Change these settings to your own preference
11
- indent_style = space
12
- indent_size = 2
13
-
14
- # We recommend you to keep these unchanged
15
- end_of_line = lf
16
- charset = utf-8
17
- trim_trailing_whitespace = true
18
- insert_final_newline = true
19
-
20
- [*.md]
21
- trim_trailing_whitespace = false
22
-
23
- [*.json]
24
- indent_size = 2
25
-
26
- [*.{html,js,md}]
27
- block_comment_start = /**
28
- block_comment = *
29
- block_comment_end = */
@@ -1,3 +0,0 @@
1
- module.exports = {
2
- stories: ['../dist/stories/**/*.stories.{js,md,mdx}'],
3
- };
@@ -1,52 +0,0 @@
1
- import { i18next } from '@operato/i18n'
2
-
3
- export const globalTypes = {
4
- locale: {
5
- name: 'Locale',
6
- description: 'Internationalization locale',
7
- toolbar: {
8
- icon: 'globe',
9
- items: [
10
- { value: 'en', right: 'πŸ‡ΊπŸ‡Έ', title: 'English' },
11
- { value: 'ko', right: 'πŸ‡°πŸ‡·', title: 'ν•œκ΅­μ–΄' },
12
- { value: 'zh', right: 'πŸ‡¨πŸ‡³', title: 'δΈ­ζ–‡' },
13
- { value: 'ja', right: 'πŸ‡―πŸ‡΅', title: 'ζ—₯本θͺž' },
14
- { value: 'ms', right: 'πŸ‡²πŸ‡Ύ', title: 'Bahasa Melayu' }
15
- ],
16
- showName: true
17
- }
18
- },
19
- theme: {
20
- name: 'Theme',
21
- description: 'Global theme for components',
22
- toolbar: {
23
- icon: 'paintbrush',
24
- items: [
25
- { value: 'light', title: 'Light' },
26
- { value: 'dark', title: 'Dark' }
27
- ],
28
- showName: true
29
- }
30
- }
31
- }
32
-
33
- export const decorators = [
34
- (Story, context) => {
35
- const { locale, theme } = context.globals
36
-
37
- if (locale) {
38
- i18next.changeLanguage(locale)
39
- }
40
-
41
- // Set the theme class for the document
42
- if (theme === 'dark') {
43
- document.documentElement.classList.add('dark')
44
- document.documentElement.classList.remove('light')
45
- } else {
46
- document.documentElement.classList.add('light')
47
- document.documentElement.classList.remove('dark')
48
- }
49
-
50
- return Story()
51
- }
52
- ]
@@ -1,8 +0,0 @@
1
- import { storybookPlugin } from '@web/dev-server-storybook';
2
- import baseConfig from '../web-dev-server.config.mjs';
3
-
4
- export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
5
- ...baseConfig,
6
- open: '/',
7
- plugins: [storybookPlugin({ type: 'web-components' }), ...baseConfig.plugins],
8
- });
package/demo/index.html DELETED
@@ -1,40 +0,0 @@
1
- <!doctype html>
2
- <html lang="en-GB">
3
- <head>
4
- <meta charset="utf-8" />
5
- <style>
6
- body {
7
- background: #fafafa;
8
- }
9
-
10
- event-view {
11
- height: 600px;
12
- }
13
- </style>
14
-
15
- <link href="/themes/app-theme.css" rel="stylesheet" />
16
- <link href="/themes/calendar-theme.css" rel="stylesheet" />
17
- <link
18
- href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL@20..48,100..700,0..1"
19
- rel="stylesheet"
20
- />
21
- <link
22
- href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL@20..48,100..700,0..1"
23
- rel="stylesheet"
24
- />
25
- <link
26
- href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:opsz,wght,FILL@20..48,100..700,0..1"
27
- rel="stylesheet"
28
- />
29
- </head>
30
- <body>
31
- <div id="demo"></div>
32
- <script type="module">
33
- import { html, render } from 'lit'
34
- import '../dist/src/ox-event-view.js'
35
-
36
- const mode = 'monthly'
37
- render(html` <ox-event-view mode=${mode}> </ox-event-view> `, document.querySelector('#demo'))
38
- </script>
39
- </body>
40
- </html>
@@ -1,113 +0,0 @@
1
- import { css } from 'lit'
2
-
3
- export const CalendarMonthlyStyles = css`
4
- :host {
5
- display: flex;
6
- flex-direction: column;
7
-
8
- --md-text-button-container-height: 24px;
9
- }
10
-
11
- [head] {
12
- display: flex;
13
- align-items: center;
14
- }
15
-
16
- [this-month] {
17
- font-size: x-large;
18
- }
19
-
20
- [nav] {
21
- margin-left: auto;
22
- }
23
-
24
- ::slotted(*) {
25
- color: var(--md-sys-color-secondary);
26
- }
27
-
28
- ol {
29
- flex: 1;
30
-
31
- display: grid;
32
- grid-template-columns: repeat(7, 1fr);
33
- grid-template-rows: max-content;
34
-
35
- padding: 0;
36
- margin: var(--calendar-monthly-ol-margin, 9px 0);
37
- border-top: var(--calendar-monthly-ol-top-border, 3px solid #999);
38
- }
39
-
40
- li {
41
- position: relative;
42
-
43
- min-height: 10%;
44
- list-style: none;
45
- border: var(--calendar-monthly-border, 1px solid rgba(0, 0, 0, 0.1));
46
- border-width: var(--calendar-monthly-border-width, 0 1px 1px 0px);
47
- opacity: var(--calendar-monthly-opacity);
48
-
49
- user-select: none;
50
- touch-action: none;
51
- }
52
-
53
- li:nth-child(7n + 1) {
54
- border-left-width: 1px;
55
- }
56
-
57
- li[day-of-week] {
58
- opacity: 1;
59
- background-color: var(--calendar-current-week-background-color, var(--md-sys-color-surface-variant));
60
- color: var(--calendar-current-week-color, var(--md-sys-color-on-surface));
61
- padding: var(--calendar-monthly-label-padding);
62
- text-align: center;
63
- }
64
-
65
- li[current-month] {
66
- background-color: var(--calendar-current-month-background-color, var(--md-sys-color-surface-variant));
67
- color: var(--calendar-current-month-color, var(--md-sys-color-on-surface-variant));
68
- opacity: 1;
69
- }
70
-
71
- li[selected] {
72
- background-color: var(--calendar-monthly-selected-background-color, var(--md-sys-color-tertiary-container));
73
- color: var(--calendar-monthly-selected-color, var(--md-sys-color-on-tertiary-container));
74
- }
75
-
76
- li[date] {
77
- min-height: var(--calendar-monthly-date-min-height, 120px);
78
- }
79
-
80
- span[date-label] {
81
- display: block;
82
- margin: var(--calendar-monthly-date-label-margin);
83
- text-align: var(--calendar-monthly-label-align, left);
84
- }
85
-
86
- li[today] > span[date-label] {
87
- display: inline-block;
88
- background-color: var(--calendar-monthly-date-label-background-color, #cc3300);
89
- padding: var(--calendar-monthly-date-label-padding);
90
- border-radius: var(--calendar-monthly-date-label-border-radius, 999em);
91
- color: var(--calendar-monthly-date-label-color, #fff);
92
- min-width: 16px;
93
- text-align: center;
94
- }
95
-
96
- [date] div {
97
- display: block;
98
- font-size: small;
99
- }
100
-
101
- [event] {
102
- display: block;
103
- background-color: var(--calendar-monthly-background-color);
104
- color: var(--calendar-monthly-color);
105
- border: var(--calendar-monthly-event-border);
106
- border-width: var(--calendar-monthly-event-border-width);
107
- margin: var(--calendar-monthly-event-margin, 0 0 4px 0);
108
- padding: var(--calendar-monthly-event-padding, 2px 4px 2px 4px);
109
-
110
- user-select: all;
111
- touch-action: all;
112
- }
113
- `
@@ -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
- `
@@ -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
@@ -1,2 +0,0 @@
1
- export * from './types.js'
2
- export * from './ox-event-view.js'
@@ -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
- }
@@ -1,123 +0,0 @@
1
- import '../src/ox-event-view.js'
2
- import { html, TemplateResult } from 'lit'
3
- import { BizEvent, CALENDAR, EventProvider } from '../src/types.js'
4
-
5
- class SampleEventProvider implements EventProvider {
6
- async fetchEventsForCalendar(calendar: CALENDAR) {
7
- const map = new Map<Date, BizEvent[]>()
8
-
9
- calendar.forEach(({ date }) =>
10
- map.set(date, [
11
- {
12
- due: '2021-08-21',
13
- title: 'HAHAHA',
14
- color: 'yellow'
15
- },
16
- {
17
- due: '2021-08-21',
18
- title: 'HOHOHO',
19
- color: 'lime'
20
- },
21
- {
22
- due: '2021-08-21',
23
- title: 'HIHIHI',
24
- color: 'yellow'
25
- },
26
- {
27
- due: '2021-08-21',
28
- title: 'HEHEHE',
29
- color: 'white'
30
- },
31
- {
32
- due: '2021-08-21',
33
- title: 'KEKEKE',
34
- color: 'yellow'
35
- },
36
- {
37
- due: '2021-08-21',
38
- title: 'MEMEME',
39
- color: 'orange'
40
- },
41
- {
42
- due: '2021-08-21',
43
- title: 'MOMOMO',
44
- color: 'lime'
45
- },
46
- {
47
- due: '2021-08-21',
48
- title: 'QUOQUO',
49
- color: 'navy'
50
- },
51
- {
52
- due: '2021-08-21',
53
- title: 'ZZXXCC',
54
- color: 'gray'
55
- }
56
- ])
57
- )
58
-
59
- return map
60
- }
61
- }
62
-
63
- export default {
64
- title: 'EventView',
65
- component: 'ox-event-view',
66
- argTypes: {
67
- mode: { control: 'select', options: ['monthly', 'weekly'], description: 'set event view mode' }
68
- }
69
- }
70
-
71
- interface Story<T> {
72
- (args: T): TemplateResult
73
- args?: Partial<T>
74
- argTypes?: Record<string, unknown>
75
- }
76
-
77
- interface ArgTypes {
78
- mode?: 'monthly' | 'weekly'
79
- }
80
-
81
- const Template: Story<ArgTypes> = ({ mode = 'monthly' }: ArgTypes) => html`
82
- <link rel="stylesheet" href="/themes/material-theme.css" />
83
- <link rel="stylesheet" href="/themes/calendar-theme.css" />
84
-
85
- <link href="/themes/app-theme.css" rel="stylesheet" />
86
- <link href="/themes/light.css" rel="stylesheet" />
87
- <link href="/themes/dark.css" rel="stylesheet" />
88
- <link href="/themes/spacing.css" rel="stylesheet" />
89
- <link href="/themes/grist-theme.css" rel="stylesheet" />
90
- <link href="/themes/form-theme.css" rel="stylesheet" />
91
-
92
- <link
93
- href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL@20..48,100..700,0..1"
94
- rel="stylesheet"
95
- />
96
- <link
97
- href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL@20..48,100..700,0..1"
98
- rel="stylesheet"
99
- />
100
- <link
101
- href="https://fonts.googleapis.com/css2?family=Material+Symbols+Sharp:opsz,wght,FILL@20..48,100..700,0..1"
102
- rel="stylesheet"
103
- />
104
-
105
- <ox-event-view
106
- mode="${mode}"
107
- .eventProvider=${new SampleEventProvider()}
108
- @select-date=${(e: CustomEvent) => {
109
- console.log(e.detail)
110
- }}
111
- >
112
- </ox-event-view>
113
- `
114
-
115
- export const Regular = Template.bind({})
116
- Regular.args = {
117
- mode: 'monthly'
118
- }
119
-
120
- export const WeeklyEventView = Template.bind({})
121
- WeeklyEventView.args = {
122
- mode: 'weekly'
123
- }
package/tsconfig.json DELETED
@@ -1,25 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "esnext",
4
- "module": "esnext",
5
- "moduleResolution": "node",
6
- "resolveJsonModule": true,
7
- "noEmitOnError": true,
8
- "lib": ["es2017", "dom"],
9
- "strict": true,
10
- "esModuleInterop": false,
11
- "allowSyntheticDefaultImports": true,
12
- "experimentalDecorators": true,
13
- "useDefineForClassFields": false,
14
- "importHelpers": true,
15
- "outDir": "dist",
16
- "sourceMap": true,
17
- "inlineSources": true,
18
- "rootDir": "./",
19
- "declaration": true,
20
- "incremental": true,
21
- "skipLibCheck": true,
22
- "types": ["node", "mocha"]
23
- },
24
- "include": ["**/*.ts", "*.d.ts"]
25
- }
@@ -1,27 +0,0 @@
1
- // import { hmrPlugin, presets } from '@open-wc/dev-server-hmr';
2
-
3
- /** Use Hot Module replacement by adding --hmr to the start command */
4
- const hmr = process.argv.includes('--hmr');
5
-
6
- export default /** @type {import('@web/dev-server').DevServerConfig} */ ({
7
- open: '/demo/',
8
- /** Use regular watch mode if HMR is not enabled. */
9
- watch: !hmr,
10
- /** Resolve bare module imports */
11
- nodeResolve: {
12
- exportConditions: ['browser', 'development'],
13
- },
14
-
15
- /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
16
- // esbuildTarget: 'auto'
17
-
18
- /** Set appIndex to enable SPA routing */
19
- // appIndex: 'demo/index.html',
20
-
21
- plugins: [
22
- /** Use Hot Module Replacement by uncommenting. Requires @open-wc/dev-server-hmr plugin */
23
- // hmr && hmrPlugin({ exclude: ['**/*/node_modules/**/*'], presets: [presets.litElement] }),
24
- ],
25
-
26
- // See documentation for all available options
27
- });
@@ -1,41 +0,0 @@
1
- // import { playwrightLauncher } from '@web/test-runner-playwright';
2
-
3
- const filteredLogs = ['Running in dev mode', 'lit-html is in dev mode'];
4
-
5
- export default /** @type {import("@web/test-runner").TestRunnerConfig} */ ({
6
- /** Test files to run */
7
- files: 'dist/test/**/*.test.js',
8
-
9
- /** Resolve bare module imports */
10
- nodeResolve: {
11
- exportConditions: ['browser', 'development'],
12
- },
13
-
14
- /** Filter out lit dev mode logs */
15
- filterBrowserLogs(log) {
16
- for (const arg of log.args) {
17
- if (typeof arg === 'string' && filteredLogs.some(l => arg.includes(l))) {
18
- return false;
19
- }
20
- }
21
- return true;
22
- },
23
-
24
- /** Compile JS for older browsers. Requires @web/dev-server-esbuild plugin */
25
- // esbuildTarget: 'auto',
26
-
27
- /** Amount of browsers to run concurrently */
28
- // concurrentBrowsers: 2,
29
-
30
- /** Amount of test files per browser to test concurrently */
31
- // concurrency: 1,
32
-
33
- /** Browsers to run tests on */
34
- // browsers: [
35
- // playwrightLauncher({ product: 'chromium' }),
36
- // playwrightLauncher({ product: 'firefox' }),
37
- // playwrightLauncher({ product: 'webkit' }),
38
- // ],
39
-
40
- // See documentation for all available options
41
- });