@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.
Files changed (77) hide show
  1. package/dist/assets/arrow-down.svg +1 -0
  2. package/dist/assets/arrow-left-double.svg +1 -0
  3. package/dist/assets/arrow-left.svg +1 -0
  4. package/dist/assets/arrow-right-double.svg +1 -0
  5. package/dist/assets/arrow-right.svg +1 -0
  6. package/dist/assets/back-arrow.svg +1 -0
  7. package/dist/assets/time.svg +1 -0
  8. package/dist/components/calendar/index.css +108 -0
  9. package/dist/components/calendar/index.d.ts +84 -0
  10. package/dist/components/calendar/index.mjs +238 -0
  11. package/dist/components/hhmmss-ms-list-grp/index.css +60 -0
  12. package/dist/components/hhmmss-ms-list-grp/index.d.ts +54 -0
  13. package/dist/components/hhmmss-ms-list-grp/index.mjs +226 -0
  14. package/dist/components/i18n/index.d.ts +13 -0
  15. package/dist/components/i18n/index.mjs +42 -0
  16. package/dist/components/num-list/index.css +35 -0
  17. package/dist/components/num-list/index.d.ts +68 -0
  18. package/dist/components/num-list/index.mjs +259 -0
  19. package/dist/components/period-selector/date-nav.css +92 -0
  20. package/dist/components/period-selector/date-nav.d.ts +64 -0
  21. package/dist/components/period-selector/date-nav.mjs +161 -0
  22. package/dist/components/period-selector/index.css +152 -0
  23. package/dist/components/period-selector/index.d.ts +68 -0
  24. package/dist/components/period-selector/index.mjs +312 -0
  25. package/dist/components/popover/index.d.ts +34 -0
  26. package/dist/components/popover/index.mjs +104 -0
  27. package/dist/components/quick-selector/index.css +167 -0
  28. package/dist/components/quick-selector/index.d.ts +74 -0
  29. package/dist/components/quick-selector/index.mjs +347 -0
  30. package/dist/components/web-component-base/index.css +9 -0
  31. package/dist/components/web-component-base/index.d.ts +46 -0
  32. package/dist/components/web-component-base/index.mjs +118 -0
  33. package/dist/components/web-component-base/scrollbar.css +25 -0
  34. package/dist/components/yyyymmdd-list-grp/index.css +32 -0
  35. package/dist/components/yyyymmdd-list-grp/index.d.ts +52 -0
  36. package/dist/components/yyyymmdd-list-grp/index.mjs +181 -0
  37. package/dist/i18n.d.ts +36 -0
  38. package/dist/i18n.mjs +368 -0
  39. package/dist/index.d.ts +7 -0
  40. package/dist/index.mjs +15 -0
  41. package/dist/utils.d.ts +12 -0
  42. package/dist/utils.mjs +21 -0
  43. package/package.json +37 -63
  44. package/src/assets/arrow-down.svg +1 -0
  45. package/src/assets/arrow-left-double.svg +1 -0
  46. package/src/assets/arrow-left.svg +1 -0
  47. package/src/assets/arrow-right-double.svg +1 -0
  48. package/src/assets/arrow-right.svg +1 -0
  49. package/src/assets/back-arrow.svg +1 -0
  50. package/src/assets/time.svg +1 -0
  51. package/src/components/calendar/index.scss +128 -0
  52. package/src/components/calendar/index.ts +453 -0
  53. package/src/components/hhmmss-ms-list-grp/index.scss +61 -0
  54. package/src/components/hhmmss-ms-list-grp/index.ts +387 -0
  55. package/src/components/i18n/index.ts +48 -0
  56. package/src/components/num-list/index.scss +38 -0
  57. package/src/components/num-list/index.ts +357 -0
  58. package/src/components/period-selector/date-nav.scss +108 -0
  59. package/src/components/period-selector/date-nav.ts +322 -0
  60. package/src/components/period-selector/index.scss +160 -0
  61. package/src/components/period-selector/index.ts +552 -0
  62. package/src/components/popover/index.ts +127 -0
  63. package/src/components/quick-selector/index.scss +183 -0
  64. package/src/components/quick-selector/index.ts +611 -0
  65. package/src/components/web-component-base/index.scss +11 -0
  66. package/src/components/web-component-base/index.ts +235 -0
  67. package/src/components/web-component-base/scrollbar.scss +30 -0
  68. package/src/components/yyyymmdd-list-grp/index.scss +33 -0
  69. package/src/components/yyyymmdd-list-grp/index.ts +257 -0
  70. package/src/i18n.ts +415 -0
  71. package/src/index.ts +12 -0
  72. package/src/utils.ts +36 -0
  73. package/README.md +0 -152
  74. package/dist/index.css +0 -1
  75. package/dist/index.html +0 -85
  76. package/dist/index.js +0 -145
  77. package/type.d.ts +0 -164
@@ -0,0 +1,453 @@
1
+ import { closestByEvent, css, debounce, html } from '../../utils';
2
+ import { Ele as I18nEle } from '../i18n';
3
+ I18nEle.define();
4
+ import {
5
+ type BaseAttrs,
6
+ type Emit2EventMap,
7
+ UiBase
8
+ } from '../web-component-base';
9
+ // import styleStr from './index.scss?inline';
10
+ const styleStr = css`
11
+ :host {
12
+ --gap: var(--calendar-item-gap, 10px 0);
13
+ --item-size: var(--calendar-item-size, 30px);
14
+ --color-disabled-text: var(--calendar-item-disabled-text, #aaa);
15
+ --color-active-bg: var(--calendar-item-active-bg, #002BE7);
16
+ --color-active-text: var(--calendar-item-active-text, #fff);
17
+ --color-in-range-bg: var(--calendar-item-in-range-bg, #002BE726);
18
+ --color-in-range-text: var(--calendar-item-in-range-text, #002BE7);
19
+ --color-hover-bg: var(--calendar-item-hover-bg, #0000000D);
20
+ --color-hover-text: var(--calendar-item-hover-text, #000);
21
+ }
22
+
23
+ .wrapper {
24
+ display: grid;
25
+ grid-template-columns: repeat(7, 1fr);
26
+ gap: var(--gap);
27
+ width: 100%;
28
+ height: 100%;
29
+ justify-content: space-between;
30
+ text-align: center;
31
+ }
32
+
33
+ .week {
34
+ min-width: var(--item-size);
35
+ }
36
+
37
+ .item {
38
+ min-width: var(--item-size);
39
+ line-height: var(--item-size);
40
+ height: var(--item-size);
41
+ position: relative;
42
+ --half-period-bg-w: calc(50% + var(--item-size) / 2);
43
+ }
44
+ .item span {
45
+ position: relative;
46
+ z-index: 2;
47
+ }
48
+ .item:not(.disabled) {
49
+ cursor: pointer;
50
+ }
51
+ :host([show-other-month]) .item.prev.disabled, :host([show-other-month]) .item.next.disabled, .item.disabled:not(.prev, .next) {
52
+ cursor: not-allowed;
53
+ color: var(--color-disabled-text);
54
+ }
55
+ .item:hover {
56
+ color: var(--color-hover-text);
57
+ }
58
+ .item.in-range {
59
+ color: var(--color-in-range-text);
60
+ }
61
+ .item:not(.disabled) .highlight {
62
+ display: block;
63
+ border-radius: 50%;
64
+ position: absolute;
65
+ top: 50%;
66
+ left: 50%;
67
+ width: var(--item-size);
68
+ height: var(--item-size);
69
+ transform: translate(-50%, -50%);
70
+ }
71
+ .item.start, .item.end {
72
+ color: var(--color-active-text);
73
+ }
74
+ .item.start .highlight, .item.end .highlight {
75
+ background-color: var(--color-active-bg);
76
+ }
77
+ .item:hover .highlight {
78
+ background-color: var(--color-hover-bg);
79
+ }
80
+ .item.in-range .bg {
81
+ display: block;
82
+ position: absolute;
83
+ top: 0;
84
+ left: 0;
85
+ width: 100%;
86
+ height: 100%;
87
+ background-color: rgba(0, 43, 231, 0.1490196078);
88
+ }
89
+ .item:nth-of-type(7n + 1) .bg {
90
+ border-radius: var(--item-size) 0 0 var(--item-size);
91
+ width: var(--half-period-bg-w);
92
+ left: calc(50% - var(--item-size) / 2);
93
+ }
94
+ .item:nth-of-type(7n) .bg {
95
+ border-radius: 0 var(--item-size) var(--item-size) 0;
96
+ width: var(--half-period-bg-w);
97
+ }
98
+ .item:nth-of-type(7n).range-start .bg {
99
+ width: var(--item-size);
100
+ left: calc(50% - var(--item-size) / 2);
101
+ }
102
+ .item.range-start .bg {
103
+ border-top-left-radius: var(--item-size);
104
+ border-bottom-left-radius: var(--item-size);
105
+ width: var(--half-period-bg-w);
106
+ left: calc(50% - var(--item-size) / 2);
107
+ }
108
+ .item.range-end .bg {
109
+ border-top-right-radius: var(--item-size);
110
+ border-bottom-right-radius: var(--item-size);
111
+ width: var(--half-period-bg-w);
112
+ }
113
+ .item.range-start.range-end .bg {
114
+ width: var(--item-size);
115
+ }
116
+ .item:nth-of-type(7n).range-start .bg, .item:nth-of-type(7n + 1).range-end .bg {
117
+ width: var(--item-size);
118
+ }
119
+ `;
120
+
121
+ export type Weeks = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat';
122
+
123
+ export const weekKey: Weeks[] = [
124
+ 'sun',
125
+ 'mon',
126
+ 'tue',
127
+ 'wed',
128
+ 'thu',
129
+ 'fri',
130
+ 'sat'
131
+ ];
132
+ export const getWeekInOrder = (startAt?: Weeks | null) => {
133
+ if (!startAt) startAt = 'sun';
134
+ const index = weekKey.indexOf(startAt);
135
+ if (index === -1) return weekKey;
136
+ return [...weekKey.slice(index), ...weekKey.slice(0, index)];
137
+ };
138
+
139
+ export interface Attrs extends BaseAttrs {
140
+ /**
141
+ * The showing time, used to determine the month to show on calendar.
142
+ * @type {`string | number`} A value that can be passed to the Date constructor.
143
+ * @default Date.now()
144
+ */
145
+ 'showing-time'?: string | number;
146
+ /**
147
+ * The start time of the calendar display range.
148
+ * @type {`string | number`} A value that can be passed to the Date constructor.
149
+ * @default 'current-time'
150
+ */
151
+ 'time-start'?: string | number;
152
+ /**
153
+ * The end time of the calendar display range.
154
+ * @type {`string | number`} A value that can be passed to the Date constructor.
155
+ * @default 'time-start'
156
+ */
157
+ 'time-end'?: string | number;
158
+ /**
159
+ * The minimum time of the calendar display range.
160
+ * @type {`string | number`} A value that can be passed to the Date constructor.
161
+ */
162
+ 'min-time'?: string | number;
163
+ /**
164
+ * The maximum time of the calendar display range.
165
+ * @type {`string | number`} A value that can be passed to the Date constructor.
166
+ */
167
+ 'max-time'?: string | number;
168
+ /**
169
+ * Set which day of the week is the first day.
170
+ * @type `'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'`
171
+ * @default 'sun'
172
+ */
173
+ 'week-start-at'?: Weeks;
174
+ /**
175
+ * Whether to show the days of the previous and next months in the current month's calendar.
176
+ * @type {boolean}
177
+ * @default false
178
+ */
179
+ 'show-other-month'?: boolean;
180
+ }
181
+
182
+ export interface Emits {
183
+ 'select-time': Date;
184
+ 'hover-item': Date;
185
+ }
186
+ export type EventMap = Emit2EventMap<Emits>;
187
+
188
+ /**
189
+ * 基础的日历显示组件。仅显示星期和数字。
190
+ */
191
+ export class Ele extends UiBase<Attrs, Emits> {
192
+ public static tagName = 'dt-calendar-base' as const;
193
+
194
+ static get observedAttributes(): string[] {
195
+ return [
196
+ ...(super.observedAttributes as (keyof BaseAttrs)[]),
197
+ 'showing-time',
198
+ 'time-start',
199
+ 'time-end',
200
+ 'min-time',
201
+ 'max-time',
202
+ 'week-start-at'
203
+ ] satisfies (keyof Attrs)[];
204
+ }
205
+
206
+ public get showingTime() {
207
+ const v = this._getAttr('showing-time', '' + Date.now());
208
+ return new Date(Number.isNaN(+v) ? v : +v);
209
+ }
210
+ public get timeStart() {
211
+ const v = this._getAttr('time-start', '' + this.showingTime);
212
+ return new Date(Number.isNaN(+v) ? v : +v);
213
+ }
214
+ public get timeEnd() {
215
+ const v = this._getAttr('time-end', '' + this.timeStart);
216
+ return new Date(Number.isNaN(+v) ? v : +v);
217
+ }
218
+ public get minTime() {
219
+ const v = this._getAttr('min-time', '');
220
+ return new Date(Number.isNaN(+v) ? v : +v);
221
+ }
222
+ public get maxTime() {
223
+ const v = this._getAttr('max-time', '');
224
+ return new Date(Number.isNaN(+v) ? v : +v);
225
+ }
226
+ private _setTimeAttr(
227
+ name: keyof Omit<
228
+ Attrs,
229
+ 'week-start-at' | 'show-other-month' | keyof BaseAttrs
230
+ >,
231
+ value: number | string | Date
232
+ ) {
233
+ const v = new Date(value);
234
+ if (Number.isNaN(+v)) return;
235
+ this.setAttribute(name, +v + '');
236
+ }
237
+ public set showingTime(val: number | string | Date) {
238
+ this._setTimeAttr('showing-time', val);
239
+ }
240
+ public set timeStart(val: number | string | Date) {
241
+ this._setTimeAttr('time-start', val);
242
+ }
243
+ public set timeEnd(val: number | string | Date) {
244
+ this._setTimeAttr('time-end', val);
245
+ }
246
+ public set minTime(val: number | string | Date) {
247
+ this._setTimeAttr('min-time', val);
248
+ }
249
+ public set maxTime(val: number | string | Date) {
250
+ this._setTimeAttr('max-time', val);
251
+ }
252
+ public get weekStartAt() {
253
+ return this._getAttr('week-start-at', 'sun');
254
+ }
255
+ public set weekStartAt(val: Weeks) {
256
+ if (weekKey.includes(val)) return;
257
+ this.setAttribute('week-start-at', val);
258
+ }
259
+ public get showOtherMonth() {
260
+ return this.hasAttribute('show-other-month');
261
+ }
262
+ public set showOtherMonth(val: boolean) {
263
+ this.setAttribute('show-other-month', '' + val);
264
+ }
265
+
266
+ protected _style = styleStr;
267
+ protected _template = html`
268
+ <div class="wrapper">${
269
+ weekKey
270
+ .map(
271
+ (key) =>
272
+ html`<dt-i18n class="week" i18n-key="date.${key}" part="week"></dt-i18n>`
273
+ )
274
+ .join('') +
275
+ [...Array(7 * 6)]
276
+ .map(
277
+ (_, i) =>
278
+ html`<div class="item" part="item"><i class="bg"></i><i class="highlight"></i><span>${(i % 31) + 1}</span></div>`
279
+ )
280
+ .join('')
281
+ }</div>`;
282
+
283
+ constructor() {
284
+ super();
285
+ this._applyTemplate();
286
+ }
287
+
288
+ public connectedCallback() {
289
+ if (!super.connectedCallback()) return;
290
+ this._onWeekStartAtChange();
291
+ this._onTimeChange();
292
+ this.addEventListener('click', this._onClick);
293
+ this.shadowRoot!.querySelector('.wrapper')!.addEventListener(
294
+ 'pointerover',
295
+ this._onPointerOver
296
+ );
297
+ }
298
+ public disconnectedCallback() {
299
+ if (!super.disconnectedCallback()) return;
300
+ this.removeEventListener('click', this._onClick);
301
+ this.shadowRoot!.querySelector('.wrapper')!.removeEventListener(
302
+ 'pointerover',
303
+ this._onPointerOver
304
+ );
305
+ }
306
+
307
+ protected _onAttrChanged(name: string, oldValue: string, newValue: string) {
308
+ super._onAttrChanged(name, oldValue, newValue);
309
+ if (name === 'week-start-at') {
310
+ this._onWeekStartAtChange();
311
+ }
312
+ if (
313
+ [
314
+ 'showing-time',
315
+ 'time-start',
316
+ 'time-end',
317
+ 'min-time',
318
+ 'max-time'
319
+ ].includes(name)
320
+ ) {
321
+ this._onTimeChange();
322
+ }
323
+ }
324
+
325
+ private _onWeekStartAtChange = debounce(() => {
326
+ if (!this.isConnected) return;
327
+ const weekOrder = getWeekInOrder(this.weekStartAt);
328
+ this.shadowRoot!.querySelectorAll('.week').forEach((ele, i) => {
329
+ ele.setAttribute('i18n-key', `date.${weekOrder[i]}`!);
330
+ });
331
+ this._onTimeChange();
332
+ }, 0);
333
+
334
+ private _onTimeChange = debounce(() => {
335
+ if (!this.isConnected) return;
336
+
337
+ const currentTime = this.showingTime as Date;
338
+ let timeStart = this.timeStart as Date;
339
+ let timeEnd = this.timeEnd as Date;
340
+ currentTime.setHours(0, 0, 0, 0);
341
+ timeStart.setHours(0, 0, 0, 0);
342
+ timeEnd.setHours(0, 0, 0, 0);
343
+
344
+ if (
345
+ Number.isNaN(+currentTime) ||
346
+ Number.isNaN(+timeStart) ||
347
+ Number.isNaN(+timeEnd)
348
+ ) {
349
+ console.warn(`Invalid date attribute(s) on <${this.tagName}>`);
350
+ return;
351
+ }
352
+ if (timeStart > timeEnd) {
353
+ [timeStart, timeEnd] = [timeEnd, timeStart];
354
+ }
355
+
356
+ const minTime = new Date(this._getAttr('min-time') || '');
357
+ const maxTime = new Date(this._getAttr('max-time') || '');
358
+ minTime.setHours(0, 0, 0, 0);
359
+ maxTime.setHours(0, 0, 0, 0);
360
+ if (maxTime < timeEnd) timeEnd = maxTime;
361
+ if (timeStart < minTime) timeStart = minTime;
362
+
363
+ const weekStartAt = this.weekStartAt;
364
+
365
+ const year = currentTime.getFullYear();
366
+ const month = currentTime.getMonth();
367
+
368
+ // number of day for current month
369
+ const days = new Date(year, month + 1, 0).getDate();
370
+ // number of day for previous month
371
+ const daysPrev = new Date(year, month, 0).getDate();
372
+ // first day of the week for current month (0=Sunday, 1=Monday, ..., 6=Saturday)
373
+ const firstWeekOfCurMonth = new Date(year, month, 1).getDay();
374
+
375
+ // Calculate the offset for different week start days
376
+ const weekStartOffset = weekKey.indexOf(weekStartAt);
377
+ // Adjust the first day of week according to weekStartAt
378
+ const adjustedFirstWeek =
379
+ (firstWeekOfCurMonth - weekStartOffset + 7) % 7;
380
+
381
+ let itemIdx = 0;
382
+ const items = this.shadowRoot!.querySelectorAll<HTMLElement>('.item');
383
+ const changeItemText = (item: HTMLElement, text: string) => {
384
+ item.querySelector('span')!.textContent = text;
385
+ };
386
+ items.forEach((ele) => {
387
+ ele.className = 'item disabled';
388
+ ele.removeAttribute('data-time');
389
+ ele.setAttribute('part', 'item disabled');
390
+ changeItemText(ele, ' ');
391
+ });
392
+
393
+ // set previous month days
394
+ for (let i = daysPrev - adjustedFirstWeek + 1; i <= daysPrev; ++i) {
395
+ const ele = items[itemIdx++];
396
+ ele.classList.add('prev');
397
+ ele.part.add('prev');
398
+ changeItemText(ele, this.showOtherMonth ? this.formatter(i) : ' ');
399
+ }
400
+
401
+ // set current month days
402
+ for (let i = 1; i <= days; ++i) {
403
+ const ele = items[itemIdx++];
404
+ const time = new Date(year, month, i);
405
+ ele.classList.toggle('month-start', i === 1);
406
+ ele.classList.toggle('month-end', i === days);
407
+ ele.classList.toggle('disabled', time < minTime || time > maxTime);
408
+ ele.classList.toggle('start', +time === +timeStart);
409
+ ele.classList.toggle(
410
+ 'in-range',
411
+ +time >= +timeStart && +time <= +timeEnd
412
+ );
413
+ ele.classList.toggle('end', +time === +timeEnd);
414
+ ele.setAttribute('part', ele.className);
415
+ ele.dataset.time = time.toISOString();
416
+ changeItemText(ele, this.formatter(i));
417
+ }
418
+ const inRangeItem = Array.from(
419
+ this.shadowRoot!.querySelectorAll('.item.in-range')
420
+ );
421
+ if (inRangeItem.length) {
422
+ inRangeItem[0].classList.add('range-start');
423
+ inRangeItem[0].part.add('range-start');
424
+ inRangeItem[inRangeItem.length - 1].classList.add('range-end');
425
+ inRangeItem[inRangeItem.length - 1].part.add('range-end');
426
+ }
427
+
428
+ // set next month days
429
+ for (let i = 1; itemIdx < items.length; ++i) {
430
+ const ele = items[itemIdx++];
431
+ ele.classList.add('next');
432
+ ele.part.add('next');
433
+ changeItemText(ele, this.showOtherMonth ? this.formatter(i) : ' ');
434
+ }
435
+ }, 0);
436
+
437
+ private _onClick = (e: MouseEvent) => {
438
+ const item = closestByEvent(e, '.item[data-time]:not(.disabled)', this);
439
+ if (!item) return;
440
+ const time = new Date(item.dataset.time!);
441
+ super.dispatchEvent('select-time', time, true);
442
+ };
443
+ private _onPointerOver = (e: Event) => {
444
+ const item = closestByEvent(e, '.item[data-time]:not(.disabled)', this);
445
+ if (!item) return;
446
+ const time = new Date(item.dataset.time!);
447
+ super.dispatchEvent('hover-item', time, true);
448
+ };
449
+
450
+ public formatter = (i: number) => '' + i;
451
+ }
452
+
453
+ Ele.define();
@@ -0,0 +1,61 @@
1
+
2
+ :host {
3
+ display: flex;
4
+ flex-direction: column;
5
+ overflow: hidden;
6
+ gap: 15px;
7
+ }
8
+
9
+ .cols {
10
+ flex: 1;
11
+ display: flex;
12
+ flex-direction: row;
13
+ height: 0;
14
+ justify-content: space-between;
15
+ gap: 2px;
16
+ }
17
+
18
+ .col {
19
+ flex: 1;
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: 10px;
23
+ }
24
+
25
+ .col > span {
26
+ text-align: center;
27
+ display: inline-block;
28
+ line-height: 27px;
29
+ }
30
+
31
+ dt-num-list {
32
+ flex: 1;
33
+ }
34
+
35
+ .ms-input {
36
+ width: 100%;
37
+ box-sizing: border-box;
38
+ border: 1px solid #0003;
39
+ border-radius: 6px;
40
+ padding: 4px;
41
+ cursor: text;
42
+ }
43
+
44
+ label > span {
45
+ display: inline-block;
46
+ line-height: 1;
47
+ font-size: 14px;
48
+ margin-bottom: 2px;
49
+ }
50
+
51
+ input {
52
+ width: 100%;
53
+ box-sizing: border-box;
54
+ padding: 0;
55
+ border: none;
56
+ outline: none;
57
+ }
58
+
59
+ input::placeholder {
60
+ color: #999;
61
+ }