@gez/date-time-kit 1.1.4 → 2.0.0-alpha.0
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/dist/assets/arrow-down.svg +1 -0
- package/dist/assets/arrow-left-double.svg +1 -0
- package/dist/assets/arrow-left.svg +1 -0
- package/dist/assets/arrow-right-double.svg +1 -0
- package/dist/assets/arrow-right.svg +1 -0
- package/dist/assets/back-arrow.svg +1 -0
- package/dist/assets/time.svg +1 -0
- package/dist/components/calendar/index.css +108 -0
- package/dist/components/calendar/index.d.ts +84 -0
- package/dist/components/calendar/index.mjs +238 -0
- package/dist/components/hhmmss-ms-list-grp/index.css +60 -0
- package/dist/components/hhmmss-ms-list-grp/index.d.ts +54 -0
- package/dist/components/hhmmss-ms-list-grp/index.mjs +226 -0
- package/dist/components/i18n/index.d.ts +13 -0
- package/dist/components/i18n/index.mjs +42 -0
- package/dist/components/num-list/index.css +35 -0
- package/dist/components/num-list/index.d.ts +68 -0
- package/dist/components/num-list/index.mjs +259 -0
- package/dist/components/period-selector/date-nav.css +92 -0
- package/dist/components/period-selector/date-nav.d.ts +64 -0
- package/dist/components/period-selector/date-nav.mjs +161 -0
- package/dist/components/period-selector/index.css +152 -0
- package/dist/components/period-selector/index.d.ts +68 -0
- package/dist/components/period-selector/index.mjs +312 -0
- package/dist/components/popover/index.d.ts +34 -0
- package/dist/components/popover/index.mjs +104 -0
- package/dist/components/quick-selector/index.css +167 -0
- package/dist/components/quick-selector/index.d.ts +74 -0
- package/dist/components/quick-selector/index.mjs +347 -0
- package/dist/components/web-component-base/index.css +9 -0
- package/dist/components/web-component-base/index.d.ts +46 -0
- package/dist/components/web-component-base/index.mjs +118 -0
- package/dist/components/web-component-base/scrollbar.css +25 -0
- package/dist/components/yyyymmdd-list-grp/index.css +32 -0
- package/dist/components/yyyymmdd-list-grp/index.d.ts +52 -0
- package/dist/components/yyyymmdd-list-grp/index.mjs +181 -0
- package/dist/i18n.d.ts +36 -0
- package/dist/i18n.mjs +368 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +15 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.mjs +21 -0
- package/package.json +37 -63
- package/src/assets/arrow-down.svg +1 -0
- package/src/assets/arrow-left-double.svg +1 -0
- package/src/assets/arrow-left.svg +1 -0
- package/src/assets/arrow-right-double.svg +1 -0
- package/src/assets/arrow-right.svg +1 -0
- package/src/assets/back-arrow.svg +1 -0
- package/src/assets/time.svg +1 -0
- package/src/components/calendar/index.scss +128 -0
- package/src/components/calendar/index.ts +453 -0
- package/src/components/hhmmss-ms-list-grp/index.scss +61 -0
- package/src/components/hhmmss-ms-list-grp/index.ts +387 -0
- package/src/components/i18n/index.ts +48 -0
- package/src/components/num-list/index.scss +38 -0
- package/src/components/num-list/index.ts +357 -0
- package/src/components/period-selector/date-nav.scss +108 -0
- package/src/components/period-selector/date-nav.ts +322 -0
- package/src/components/period-selector/index.scss +160 -0
- package/src/components/period-selector/index.ts +552 -0
- package/src/components/popover/index.ts +127 -0
- package/src/components/quick-selector/index.scss +183 -0
- package/src/components/quick-selector/index.ts +611 -0
- package/src/components/web-component-base/index.scss +11 -0
- package/src/components/web-component-base/index.ts +235 -0
- package/src/components/web-component-base/scrollbar.scss +30 -0
- package/src/components/yyyymmdd-list-grp/index.scss +33 -0
- package/src/components/yyyymmdd-list-grp/index.ts +257 -0
- package/src/i18n.ts +415 -0
- package/src/index.ts +12 -0
- package/src/utils.ts +36 -0
- package/README.md +0 -152
- package/dist/index.css +0 -1
- package/dist/index.html +0 -85
- package/dist/index.js +0 -145
- package/type.d.ts +0 -164
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
import { closestByEvent, css, debounce, html } from '../../utils';
|
|
2
|
+
import { type BaseAttrs, UiBase } from '../web-component-base';
|
|
3
|
+
// import styleStr from './index.scss?inline';
|
|
4
|
+
const styleStr = css`
|
|
5
|
+
:host {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
gap: 15px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.date-echo {
|
|
12
|
+
display: flex;
|
|
13
|
+
gap: 5px;
|
|
14
|
+
align-items: center;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.start-date-echo-wrapper,
|
|
18
|
+
.end-date-echo-wrapper {
|
|
19
|
+
width: 100%;
|
|
20
|
+
flex: 1;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
gap: 2px;
|
|
24
|
+
border-radius: 6px;
|
|
25
|
+
border: 1px solid rgba(0, 0, 0, 0.1490196078);
|
|
26
|
+
padding: 4px;
|
|
27
|
+
}
|
|
28
|
+
.start-date-echo-wrapper.active,
|
|
29
|
+
.end-date-echo-wrapper.active {
|
|
30
|
+
border-color: #333;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.date-echo .label {
|
|
34
|
+
font-size: 14px;
|
|
35
|
+
line-height: 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.start-date-echo, .end-date-echo {
|
|
39
|
+
font-size: 16px;
|
|
40
|
+
line-height: 1;
|
|
41
|
+
font-weight: bold;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.dividing-line {
|
|
45
|
+
display: block;
|
|
46
|
+
height: 1px;
|
|
47
|
+
width: 20px;
|
|
48
|
+
background-color: #eee;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
dt-date-nav::part(list-grp) {
|
|
52
|
+
height: 254px;
|
|
53
|
+
margin-top: 15px;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
dt-calendar-base.hide {
|
|
57
|
+
display: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.calendars {
|
|
61
|
+
display: flex;
|
|
62
|
+
gap: 20px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.wrapper {
|
|
66
|
+
flex: 1;
|
|
67
|
+
height: 100%;
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
gap: 15px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
dt-popover {
|
|
74
|
+
position: relative;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
[open] .time-echo-wrapper {
|
|
78
|
+
border-color: #18181B;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.time-echo-wrapper {
|
|
82
|
+
width: 100%;
|
|
83
|
+
padding: 4px;
|
|
84
|
+
display: flex;
|
|
85
|
+
gap: 5px;
|
|
86
|
+
border-radius: 4px;
|
|
87
|
+
min-height: 30px;
|
|
88
|
+
border: 1px solid rgba(0, 0, 0, 0.0666666667);
|
|
89
|
+
box-sizing: border-box;
|
|
90
|
+
align-items: center;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.time-selector {
|
|
94
|
+
position: absolute;
|
|
95
|
+
width: 100%;
|
|
96
|
+
height: 461px;
|
|
97
|
+
box-sizing: border-box;
|
|
98
|
+
background-color: #fff;
|
|
99
|
+
display: flex;
|
|
100
|
+
flex-direction: column;
|
|
101
|
+
gap: 15px;
|
|
102
|
+
padding: 15px;
|
|
103
|
+
border-radius: 6px;
|
|
104
|
+
border: 1px solid #eee;
|
|
105
|
+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
|
|
106
|
+
}
|
|
107
|
+
.time-selector .title {
|
|
108
|
+
font-size: 16px;
|
|
109
|
+
margin: 0;
|
|
110
|
+
line-height: 1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
dt-hhmmss-ms-list-grp::part(list-container) {
|
|
114
|
+
gap: 2px;
|
|
115
|
+
}
|
|
116
|
+
dt-hhmmss-ms-list-grp::part(list) {
|
|
117
|
+
scroll-behavior: smooth;
|
|
118
|
+
}
|
|
119
|
+
dt-hhmmss-ms-list-grp::part(item) {
|
|
120
|
+
font-size: 14px;
|
|
121
|
+
line-height: 17px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
#time-selector-done-btn {
|
|
125
|
+
border: none;
|
|
126
|
+
min-height: 30px;
|
|
127
|
+
border-radius: 6px;
|
|
128
|
+
padding: 5px 10px;
|
|
129
|
+
font-size: 14px;
|
|
130
|
+
background-color: #18181B;
|
|
131
|
+
color: #fff;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.time-icon {
|
|
135
|
+
display: inline-block;
|
|
136
|
+
width: 20px;
|
|
137
|
+
height: 20px;
|
|
138
|
+
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='15' fill='currentColor'%3E%3Cpath d='M7.4335 4.241a.4376.4376 0 0 0-.871.0594v3.783l.0044.0622a.4375.4375 0 0 0 .1921.3029L8.9242 9.877l.0566.0317a.4376.4376 0 0 0 .5495-.1559l.0317-.0566a.4376.4376 0 0 0-.1559-.5495L7.4375 7.8471V4.3004l-.004-.0593ZM7 1.6667c-3.2217 0-5.8333 2.6116-5.8333 5.8333 0 3.2217 2.6116 5.8333 5.8333 5.8333 3.2217 0 5.8333-2.6116 5.8333-5.8333 0-3.2217-2.6116-5.8333-5.8333-5.8333Zm0 .814c2.7721 0 5.0194 2.2472 5.0194 5.0193 0 2.7721-2.2473 5.0194-5.0194 5.0194S1.9806 10.2721 1.9806 7.5 4.228 2.4806 7 2.4806Z'/%3E%3C/svg%3E") 50%/20px 20px no-repeat;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.time-echo {
|
|
142
|
+
font-size: 14px;
|
|
143
|
+
color: #999;
|
|
144
|
+
line-height: 1;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
dt-calendar-base {
|
|
148
|
+
height: 254px;
|
|
149
|
+
}
|
|
150
|
+
dt-calendar-base::part(week) {
|
|
151
|
+
font-size: 12px;
|
|
152
|
+
line-height: 14px;
|
|
153
|
+
}
|
|
154
|
+
dt-calendar-base::part(item) {
|
|
155
|
+
font-size: 14px;
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
import { Ele as DateNavEle, type EventMap as DateNavEvent } from './date-nav';
|
|
159
|
+
DateNavEle.define();
|
|
160
|
+
import {
|
|
161
|
+
Ele as CalendarBaseEle,
|
|
162
|
+
type EventMap as CalendarBaseEvent
|
|
163
|
+
} from '../calendar';
|
|
164
|
+
CalendarBaseEle.define();
|
|
165
|
+
import { Ele as HhMmSsMsListGrpEle } from '../hhmmss-ms-list-grp';
|
|
166
|
+
HhMmSsMsListGrpEle.define();
|
|
167
|
+
import { Ele as PopoverEle, type EventMap as PopoverEvent } from '../popover';
|
|
168
|
+
PopoverEle.define();
|
|
169
|
+
|
|
170
|
+
export interface Attrs extends BaseAttrs {
|
|
171
|
+
/**
|
|
172
|
+
* The start time of the calendar display range.
|
|
173
|
+
* @type {`string | number`} A value that can be passed to the Date constructor.
|
|
174
|
+
* @default Date.now()
|
|
175
|
+
*/
|
|
176
|
+
'time-start'?: string | number;
|
|
177
|
+
/**
|
|
178
|
+
* The end time of the calendar display range.
|
|
179
|
+
* @type {`string | number`} A value that can be passed to the Date constructor.
|
|
180
|
+
* @default 'time-start'
|
|
181
|
+
*/
|
|
182
|
+
'time-end': string | number;
|
|
183
|
+
/**
|
|
184
|
+
* 选择器的粒度,表示最小可选的时间单位。默认为 millisecond。
|
|
185
|
+
* 例如设置为 'minute',则表示只能选择到分钟,秒和毫秒将被忽略。
|
|
186
|
+
*/
|
|
187
|
+
'min-granularity'?: 'day' | 'hour' | 'minute' | 'second' | 'millisecond';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export interface Emits {
|
|
191
|
+
change: {
|
|
192
|
+
oldStartTime: Date;
|
|
193
|
+
oldEndTime: Date;
|
|
194
|
+
newStartTime: Date;
|
|
195
|
+
newEndTime: Date;
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const diffInMonth = (a: Date, b: Date) => {
|
|
200
|
+
if (a > b) [a, b] = [b, a];
|
|
201
|
+
const aYear = a.getFullYear();
|
|
202
|
+
const aMonth = a.getMonth();
|
|
203
|
+
const bYear = b.getFullYear();
|
|
204
|
+
const bMonth = b.getMonth();
|
|
205
|
+
return bYear * 12 + bMonth - (aYear * 12 + aMonth);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 时间段选择器(两个日历)
|
|
210
|
+
*
|
|
211
|
+
* 存在一个 timeFormatter 方法,可以重写该方法以自定义时分秒毫秒的回显格式。
|
|
212
|
+
*/
|
|
213
|
+
export class Ele extends UiBase<Attrs, Emits> {
|
|
214
|
+
public static readonly tagName = 'dt-period-selector' as const;
|
|
215
|
+
|
|
216
|
+
static get observedAttributes(): string[] {
|
|
217
|
+
return [
|
|
218
|
+
...(super.observedAttributes as (keyof BaseAttrs)[]),
|
|
219
|
+
'time-start',
|
|
220
|
+
'time-end',
|
|
221
|
+
'min-granularity'
|
|
222
|
+
] satisfies (keyof Attrs)[];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
public get timeStart() {
|
|
226
|
+
const v = this._getAttr('time-start', '' + Date.now());
|
|
227
|
+
return new Date(Number.isNaN(+v) ? v : +v);
|
|
228
|
+
}
|
|
229
|
+
public set timeStart(val: number | string | Date) {
|
|
230
|
+
const v = new Date(val);
|
|
231
|
+
if (Number.isNaN(+v)) return;
|
|
232
|
+
this.setAttribute('time-start', +v + '');
|
|
233
|
+
}
|
|
234
|
+
public get timeEnd() {
|
|
235
|
+
const v = this._getAttr('time-end', '' + this.timeStart);
|
|
236
|
+
return new Date(Number.isNaN(+v) ? v : +v);
|
|
237
|
+
}
|
|
238
|
+
public set timeEnd(val: number | string | Date) {
|
|
239
|
+
const v = new Date(val);
|
|
240
|
+
if (Number.isNaN(+v)) return;
|
|
241
|
+
this.setAttribute('time-end', +v + '');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
protected _style = styleStr;
|
|
245
|
+
protected _template = html`
|
|
246
|
+
<div class="date-echo">
|
|
247
|
+
<div class="start-date-echo-wrapper active">
|
|
248
|
+
<span class="label">Start Date</span>
|
|
249
|
+
<span class="start-date-echo">dd/mm/yyyy</span>
|
|
250
|
+
</div>
|
|
251
|
+
<i class="dividing-line"></i>
|
|
252
|
+
<div class="end-date-echo-wrapper">
|
|
253
|
+
<span class="label">End Date</span>
|
|
254
|
+
<span class="end-date-echo">dd/mm/yyyy</span>
|
|
255
|
+
</div>
|
|
256
|
+
</div><div class="calendars">${['start', 'end']
|
|
257
|
+
.map(
|
|
258
|
+
(s) => html`
|
|
259
|
+
<div class="wrapper ${s}">
|
|
260
|
+
<dt-date-nav
|
|
261
|
+
show-ctrl-btn-month-add
|
|
262
|
+
show-ctrl-btn-month-sub
|
|
263
|
+
></dt-date-nav>
|
|
264
|
+
<dt-calendar-base data-type="${s}"></dt-calendar-base>
|
|
265
|
+
<dt-popover>
|
|
266
|
+
<div slot="trigger" class="time-echo-wrapper">
|
|
267
|
+
<i class="time-icon"></i>
|
|
268
|
+
<span class="time-echo">hh:mm:ss.sss</span>
|
|
269
|
+
</div>
|
|
270
|
+
<div slot="pop" class="time-selector">
|
|
271
|
+
<h3 class="title">${s === 'start' ? 'Start Time' : 'End Time'}</h3>
|
|
272
|
+
<dt-hhmmss-ms-list-grp></dt-hhmmss-ms-list-grp>
|
|
273
|
+
<button id="time-selector-done-btn" data-type="${s}">Done</button>
|
|
274
|
+
</div>
|
|
275
|
+
</dt-popover>
|
|
276
|
+
</div>`
|
|
277
|
+
)
|
|
278
|
+
.join('')}</div>`;
|
|
279
|
+
|
|
280
|
+
constructor() {
|
|
281
|
+
super();
|
|
282
|
+
this._applyTemplate();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private get _startNavEle() {
|
|
286
|
+
return this.shadowRoot?.querySelector(
|
|
287
|
+
'.start dt-date-nav'
|
|
288
|
+
) as DateNavEle;
|
|
289
|
+
}
|
|
290
|
+
private get _endNavEle() {
|
|
291
|
+
return this.shadowRoot?.querySelector('.end dt-date-nav') as DateNavEle;
|
|
292
|
+
}
|
|
293
|
+
private get _startCalendar() {
|
|
294
|
+
return this.shadowRoot?.querySelector(
|
|
295
|
+
'.start dt-calendar-base'
|
|
296
|
+
) as CalendarBaseEle;
|
|
297
|
+
}
|
|
298
|
+
private get _endCalendar() {
|
|
299
|
+
return this.shadowRoot?.querySelector(
|
|
300
|
+
'.end dt-calendar-base'
|
|
301
|
+
) as CalendarBaseEle;
|
|
302
|
+
}
|
|
303
|
+
private get _startTimeSelector() {
|
|
304
|
+
return this.shadowRoot?.querySelector(
|
|
305
|
+
'.start dt-hhmmss-ms-list-grp'
|
|
306
|
+
) as HhMmSsMsListGrpEle;
|
|
307
|
+
}
|
|
308
|
+
private get _endTimeSelector() {
|
|
309
|
+
return this.shadowRoot?.querySelector(
|
|
310
|
+
'.end dt-hhmmss-ms-list-grp'
|
|
311
|
+
) as HhMmSsMsListGrpEle;
|
|
312
|
+
}
|
|
313
|
+
private get _startTimePopover() {
|
|
314
|
+
return this.shadowRoot?.querySelector(
|
|
315
|
+
'.start dt-popover'
|
|
316
|
+
) as PopoverEle;
|
|
317
|
+
}
|
|
318
|
+
private get _endTimePopover() {
|
|
319
|
+
return this.shadowRoot?.querySelector('.end dt-popover') as PopoverEle;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// 存放的是结束时间点
|
|
323
|
+
private _selectedDate: Date | null = null;
|
|
324
|
+
|
|
325
|
+
public connectedCallback() {
|
|
326
|
+
if (!super.connectedCallback()) return;
|
|
327
|
+
this._selectedDate = null;
|
|
328
|
+
this._startCalendar.formatter = this._endCalendar.formatter = (
|
|
329
|
+
i: number
|
|
330
|
+
) => String(i).padStart(2, '0');
|
|
331
|
+
this._render();
|
|
332
|
+
this._startCalendar.addEventListener(
|
|
333
|
+
'select-time',
|
|
334
|
+
this._onCalendarSelect
|
|
335
|
+
);
|
|
336
|
+
this._endCalendar.addEventListener(
|
|
337
|
+
'select-time',
|
|
338
|
+
this._onCalendarSelect
|
|
339
|
+
);
|
|
340
|
+
this._startNavEle.addEventListener('change', this._onNavChange);
|
|
341
|
+
this._endNavEle.addEventListener('change', this._onNavChange);
|
|
342
|
+
this._startTimePopover.addEventListener(
|
|
343
|
+
'open-change',
|
|
344
|
+
this._onTimePopoverOpenChange
|
|
345
|
+
);
|
|
346
|
+
this._endTimePopover.addEventListener(
|
|
347
|
+
'open-change',
|
|
348
|
+
this._onTimePopoverOpenChange
|
|
349
|
+
);
|
|
350
|
+
this._startCalendar.addEventListener(
|
|
351
|
+
'hover-item',
|
|
352
|
+
this._onCalendarItemHover
|
|
353
|
+
);
|
|
354
|
+
this._endCalendar.addEventListener(
|
|
355
|
+
'hover-item',
|
|
356
|
+
this._onCalendarItemHover
|
|
357
|
+
);
|
|
358
|
+
this._startNavEle.addEventListener(
|
|
359
|
+
'popover-open-change',
|
|
360
|
+
this._onNavOpenToggle
|
|
361
|
+
);
|
|
362
|
+
this._endNavEle.addEventListener(
|
|
363
|
+
'popover-open-change',
|
|
364
|
+
this._onNavOpenToggle
|
|
365
|
+
);
|
|
366
|
+
this.shadowRoot
|
|
367
|
+
?.querySelectorAll('#time-selector-done-btn')
|
|
368
|
+
.forEach((btn) => {
|
|
369
|
+
btn.addEventListener('click', this._onTimeSelectorDoneClick);
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
public disconnectedCallback() {
|
|
373
|
+
if (!super.disconnectedCallback()) return;
|
|
374
|
+
this._startCalendar.removeEventListener(
|
|
375
|
+
'select-time',
|
|
376
|
+
this._onCalendarSelect
|
|
377
|
+
);
|
|
378
|
+
this._endCalendar.removeEventListener(
|
|
379
|
+
'select-time',
|
|
380
|
+
this._onCalendarSelect
|
|
381
|
+
);
|
|
382
|
+
this._startNavEle.removeEventListener('change', this._onNavChange);
|
|
383
|
+
this._endNavEle.removeEventListener('change', this._onNavChange);
|
|
384
|
+
this._startTimePopover.removeEventListener(
|
|
385
|
+
'open-change',
|
|
386
|
+
this._onTimePopoverOpenChange
|
|
387
|
+
);
|
|
388
|
+
this._endTimePopover.removeEventListener(
|
|
389
|
+
'open-change',
|
|
390
|
+
this._onTimePopoverOpenChange
|
|
391
|
+
);
|
|
392
|
+
this._startCalendar.removeEventListener(
|
|
393
|
+
'hover-item',
|
|
394
|
+
this._onCalendarItemHover
|
|
395
|
+
);
|
|
396
|
+
this._endCalendar.removeEventListener(
|
|
397
|
+
'hover-item',
|
|
398
|
+
this._onCalendarItemHover
|
|
399
|
+
);
|
|
400
|
+
this._startNavEle.removeEventListener(
|
|
401
|
+
'popover-open-change',
|
|
402
|
+
this._onNavOpenToggle
|
|
403
|
+
);
|
|
404
|
+
this._endNavEle.removeEventListener(
|
|
405
|
+
'popover-open-change',
|
|
406
|
+
this._onNavOpenToggle
|
|
407
|
+
);
|
|
408
|
+
this.shadowRoot
|
|
409
|
+
?.querySelectorAll('#time-selector-done-btn')
|
|
410
|
+
.forEach((btn) => {
|
|
411
|
+
btn.removeEventListener('click', this._onTimeSelectorDoneClick);
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
protected _onAttrChanged(name: string, oldValue: string, newValue: string) {
|
|
416
|
+
super._onAttrChanged(name, oldValue, newValue);
|
|
417
|
+
this._render();
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
private _updateNavCtrlBtn() {
|
|
421
|
+
const timeStart = new Date(this._startNavEle.millisecond);
|
|
422
|
+
const timeEnd = new Date(this._endNavEle.millisecond);
|
|
423
|
+
const showCtrlBtn = diffInMonth(timeStart, timeEnd) > 1;
|
|
424
|
+
this._startNavEle.showCtrlBtnMonthAdd = showCtrlBtn;
|
|
425
|
+
this._endNavEle.showCtrlBtnMonthSub = showCtrlBtn;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
private _render = debounce(() => {
|
|
429
|
+
if (!this.isConnected) return;
|
|
430
|
+
let timeStart = this.timeStart as Date;
|
|
431
|
+
let timeEnd = this.timeEnd as Date;
|
|
432
|
+
if (timeStart > timeEnd) [timeStart, timeEnd] = [timeEnd, timeStart];
|
|
433
|
+
const tz = new Date().getTimezoneOffset() * 60 * 1000;
|
|
434
|
+
this._startNavEle.millisecond =
|
|
435
|
+
this._startCalendar.showingTime =
|
|
436
|
+
this._startCalendar.timeStart =
|
|
437
|
+
this._endCalendar.timeStart =
|
|
438
|
+
+timeStart;
|
|
439
|
+
this._startTimeSelector.millisecond =
|
|
440
|
+
(+timeStart - tz) % (24 * 60 * 60 * 1000);
|
|
441
|
+
this._endCalendar.timeEnd = this._startCalendar.timeEnd = +timeEnd;
|
|
442
|
+
if (diffInMonth(timeStart, timeEnd) <= 1) {
|
|
443
|
+
const nextMonth = new Date(
|
|
444
|
+
timeStart.getFullYear(),
|
|
445
|
+
timeStart.getMonth() + 1
|
|
446
|
+
);
|
|
447
|
+
this._endCalendar.showingTime = nextMonth;
|
|
448
|
+
this._endNavEle.millisecond = +nextMonth;
|
|
449
|
+
} else {
|
|
450
|
+
this._endCalendar.showingTime = timeEnd;
|
|
451
|
+
this._endNavEle.millisecond = +timeEnd;
|
|
452
|
+
}
|
|
453
|
+
this._endTimeSelector.millisecond =
|
|
454
|
+
(+timeEnd - tz) % (24 * 60 * 60 * 1000);
|
|
455
|
+
this.shadowRoot!.querySelector(
|
|
456
|
+
'.wrapper.start .time-echo'
|
|
457
|
+
)!.textContent = this.timeFormatter(timeStart as Date);
|
|
458
|
+
this.shadowRoot!.querySelector('.wrapper.end .time-echo')!.textContent =
|
|
459
|
+
this.timeFormatter(timeEnd as Date);
|
|
460
|
+
this._updateDateEcho();
|
|
461
|
+
this._updateNavCtrlBtn();
|
|
462
|
+
}, 0);
|
|
463
|
+
|
|
464
|
+
private _updateDateEcho() {
|
|
465
|
+
let timeStart = this.timeStart as Date;
|
|
466
|
+
let timeEnd = this.timeEnd as Date;
|
|
467
|
+
if (timeStart > timeEnd) [timeStart, timeEnd] = [timeEnd, timeStart];
|
|
468
|
+
this.shadowRoot!.querySelector('.start-date-echo')!.textContent =
|
|
469
|
+
this.dateFormatter(timeStart);
|
|
470
|
+
this.shadowRoot!.querySelector('.end-date-echo')!.textContent =
|
|
471
|
+
this.dateFormatter(timeEnd);
|
|
472
|
+
this.shadowRoot!.querySelector(
|
|
473
|
+
'.start-date-echo-wrapper'
|
|
474
|
+
)!.classList.toggle('active', !this._selectedDate);
|
|
475
|
+
this.shadowRoot!.querySelector(
|
|
476
|
+
'.end-date-echo-wrapper'
|
|
477
|
+
)!.classList.toggle('active', !!this._selectedDate);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private _onCalendarSelect = (e: CalendarBaseEvent['select-time']) => {
|
|
481
|
+
if (this._selectedDate) {
|
|
482
|
+
this._selectedDate = null;
|
|
483
|
+
this.timeEnd = +e.detail + this._endTimeSelector.millisecond;
|
|
484
|
+
} else {
|
|
485
|
+
this._selectedDate = this.timeEnd as unknown as Date;
|
|
486
|
+
this.timeStart = +e.detail + this._startTimeSelector.millisecond;
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
private _onCalendarItemHover = (e: CalendarBaseEvent['hover-item']) => {
|
|
490
|
+
if (!this._selectedDate) return;
|
|
491
|
+
this.timeEnd = +e.detail + this._endTimeSelector.millisecond;
|
|
492
|
+
};
|
|
493
|
+
private _onNavChange = (e: DateNavEvent['change']) => {
|
|
494
|
+
const wrapper = closestByEvent(e, '.wrapper');
|
|
495
|
+
if (!wrapper) return;
|
|
496
|
+
const { newStartTime, newEndTime } = e.detail;
|
|
497
|
+
if (wrapper.classList.contains('start')) {
|
|
498
|
+
this._startCalendar.showingTime = +newStartTime;
|
|
499
|
+
} else {
|
|
500
|
+
this._endCalendar.showingTime = +newEndTime;
|
|
501
|
+
}
|
|
502
|
+
this._updateNavCtrlBtn();
|
|
503
|
+
};
|
|
504
|
+
private _onNavOpenToggle = (e: DateNavEvent['popover-open-change']) => {
|
|
505
|
+
if (!(e.target instanceof DateNavEle)) return;
|
|
506
|
+
e.target.nextElementSibling?.classList.toggle('hide', e.detail);
|
|
507
|
+
};
|
|
508
|
+
private _onTimePopoverOpenChange = (e: PopoverEvent['open-change']) => {
|
|
509
|
+
if (!(e.target instanceof PopoverEle)) return;
|
|
510
|
+
if (!e.detail) return this._render(); // for reset time selector value
|
|
511
|
+
e.target
|
|
512
|
+
.querySelectorAll<HhMmSsMsListGrpEle>('dt-hhmmss-ms-list-grp')
|
|
513
|
+
.forEach((ele) => {
|
|
514
|
+
ele.scrollToCurrentItem();
|
|
515
|
+
});
|
|
516
|
+
};
|
|
517
|
+
private _onTimeSelectorDoneClick = (e: Event) => {
|
|
518
|
+
const btn = closestByEvent(e, '#time-selector-done-btn');
|
|
519
|
+
if (!btn) return;
|
|
520
|
+
const type = btn.dataset.type;
|
|
521
|
+
const calcTime = (time: Date, ms: number) => {
|
|
522
|
+
time.setHours(0, 0, 0, 0);
|
|
523
|
+
time.setMilliseconds(ms);
|
|
524
|
+
return time;
|
|
525
|
+
};
|
|
526
|
+
if (type === 'start') {
|
|
527
|
+
this.timeStart = calcTime(
|
|
528
|
+
this.timeStart as Date,
|
|
529
|
+
this._startTimeSelector.millisecond
|
|
530
|
+
);
|
|
531
|
+
this._startTimePopover.open = false;
|
|
532
|
+
} else if (type === 'end') {
|
|
533
|
+
this.timeEnd = calcTime(
|
|
534
|
+
this.timeEnd as Date,
|
|
535
|
+
this._endTimeSelector.millisecond
|
|
536
|
+
);
|
|
537
|
+
this._endTimePopover.open = false;
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
|
|
541
|
+
public showCalendarDatePoint() {
|
|
542
|
+
this._render();
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
public timeFormatter = (time: Date) =>
|
|
546
|
+
new Date(+time - new Date().getTimezoneOffset() * 60 * 1000)
|
|
547
|
+
.toISOString()
|
|
548
|
+
.slice(11, 23);
|
|
549
|
+
public dateFormatter = (time: Date) => time.toLocaleDateString('en-GB');
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
Ele.define();
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { html } from '../../utils';
|
|
2
|
+
import {
|
|
3
|
+
type BaseAttrs,
|
|
4
|
+
type Emit2EventMap,
|
|
5
|
+
UiBase
|
|
6
|
+
} from '../web-component-base';
|
|
7
|
+
|
|
8
|
+
export interface Attrs extends BaseAttrs {
|
|
9
|
+
open?: boolean;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Emits {
|
|
14
|
+
'open-change': boolean;
|
|
15
|
+
}
|
|
16
|
+
export type EventMap = Emit2EventMap<Emits>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 点击触发器后气泡弹出
|
|
20
|
+
*/
|
|
21
|
+
export class Ele extends UiBase<Attrs, Emits> {
|
|
22
|
+
public static readonly tagName = 'dt-popover' as const;
|
|
23
|
+
|
|
24
|
+
static get observedAttributes(): string[] {
|
|
25
|
+
return [
|
|
26
|
+
...(super.observedAttributes as (keyof BaseAttrs)[]),
|
|
27
|
+
'open',
|
|
28
|
+
'disabled'
|
|
29
|
+
] satisfies (keyof Attrs)[];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
protected _template =
|
|
33
|
+
html`<slot name="trigger"></slot><slot name="pop" style="display:none"></slot>`;
|
|
34
|
+
|
|
35
|
+
constructor() {
|
|
36
|
+
super();
|
|
37
|
+
this._applyTemplate();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
private get _popEle() {
|
|
41
|
+
return this.shadowRoot?.querySelector(
|
|
42
|
+
'slot[name="pop"]'
|
|
43
|
+
) as HTMLDivElement;
|
|
44
|
+
}
|
|
45
|
+
private get _triggerEle() {
|
|
46
|
+
return this.shadowRoot?.querySelector(
|
|
47
|
+
'slot[name="trigger"]'
|
|
48
|
+
) as HTMLSlotElement;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public get open() {
|
|
52
|
+
return this.hasAttribute('open');
|
|
53
|
+
}
|
|
54
|
+
public set open(v: boolean) {
|
|
55
|
+
this.toggleAttribute('open', v);
|
|
56
|
+
}
|
|
57
|
+
public get disabled() {
|
|
58
|
+
return this.hasAttribute('disabled');
|
|
59
|
+
}
|
|
60
|
+
public set disabled(v: boolean) {
|
|
61
|
+
this.toggleAttribute('disabled', v);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* toggle open state
|
|
65
|
+
* @returns null if disabled, otherwise the new open state
|
|
66
|
+
*/
|
|
67
|
+
public toggleOpen = (force = !this.open) => {
|
|
68
|
+
if (this.disabled) return null;
|
|
69
|
+
return (this.open = force);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
public connectedCallback() {
|
|
73
|
+
if (!super.connectedCallback()) return;
|
|
74
|
+
this._triggerEle.addEventListener('click', this._onToggleClick);
|
|
75
|
+
}
|
|
76
|
+
public disconnectedCallback() {
|
|
77
|
+
if (!super.disconnectedCallback()) return;
|
|
78
|
+
this._triggerEle.removeEventListener('click', this._onToggleClick);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected _onAttrChanged(name: string, oldValue: string, newValue: string) {
|
|
82
|
+
super._onAttrChanged(name, oldValue, newValue);
|
|
83
|
+
if (name !== 'open') return;
|
|
84
|
+
const isOpen = newValue !== null;
|
|
85
|
+
this._popEle.style.display = !isOpen ? 'none' : '';
|
|
86
|
+
if (typeof document !== 'undefined') {
|
|
87
|
+
setTimeout(() => {
|
|
88
|
+
if (isOpen)
|
|
89
|
+
document.addEventListener('click', this._onDocClick, true);
|
|
90
|
+
else
|
|
91
|
+
document.removeEventListener(
|
|
92
|
+
'click',
|
|
93
|
+
this._onDocClick,
|
|
94
|
+
true
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
this.dispatchEvent('open-change', this.open, true);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private _onToggleClick = () => {
|
|
102
|
+
this.toggleOpen();
|
|
103
|
+
};
|
|
104
|
+
private _onDocClick = (e: MouseEvent) => {
|
|
105
|
+
const popEle = this.querySelector('[slot="pop"]');
|
|
106
|
+
if (popEle) {
|
|
107
|
+
if (e.composedPath().includes(popEle)) return;
|
|
108
|
+
if (e.composedPath().includes(this)) {
|
|
109
|
+
const popRect = popEle.getBoundingClientRect();
|
|
110
|
+
if (
|
|
111
|
+
e.clientX >= popRect.left &&
|
|
112
|
+
e.clientX <= popRect.right &&
|
|
113
|
+
e.clientY >= popRect.top &&
|
|
114
|
+
e.clientY <= popRect.bottom
|
|
115
|
+
) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
e.stopPropagation();
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
this.open = false;
|
|
123
|
+
document.removeEventListener('click', this._onDocClick, true);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
Ele.define();
|