@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,235 @@
|
|
|
1
|
+
import type { Lang } from '../../i18n';
|
|
2
|
+
import { css } from '../../utils';
|
|
3
|
+
// import styleStr from './index.scss?inline';
|
|
4
|
+
const styleStr = css`
|
|
5
|
+
/* firefox only: */
|
|
6
|
+
@-moz-document url-prefix() {
|
|
7
|
+
:host, * {
|
|
8
|
+
scrollbar-width: thin;
|
|
9
|
+
scrollbar-color: var(--scrollbar-thumb-color, #4444) transparent;
|
|
10
|
+
}
|
|
11
|
+
:host:hover, *:hover {
|
|
12
|
+
scrollbar-color: var(--scrollbar-thumb-color-hover, var(--scrollbar-thumb-color, #8888)) transparent;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
// import scrollbarStyleStr from './scrollbar.scss?inline';
|
|
17
|
+
const scrollbarStyleStr = css`
|
|
18
|
+
[dt]::-webkit-scrollbar, :host *::-webkit-scrollbar {
|
|
19
|
+
width: 6px;
|
|
20
|
+
height: 6px;
|
|
21
|
+
}
|
|
22
|
+
[dt]::-webkit-scrollbar-button, :host *::-webkit-scrollbar-button {
|
|
23
|
+
display: none;
|
|
24
|
+
}
|
|
25
|
+
[dt]::-webkit-scrollbar-corner, :host *::-webkit-scrollbar-corner {
|
|
26
|
+
display: none;
|
|
27
|
+
}
|
|
28
|
+
[dt]::-webkit-scrollbar-thumb, :host *::-webkit-scrollbar-thumb {
|
|
29
|
+
background-color: var(--scrollbar-thumb-color, #4444);
|
|
30
|
+
border-radius: 4px;
|
|
31
|
+
cursor: grab;
|
|
32
|
+
}
|
|
33
|
+
[dt]::-webkit-scrollbar-thumb:hover, :host *::-webkit-scrollbar-thumb:hover {
|
|
34
|
+
background-color: var(--scrollbar-thumb-color-hover, var(--scrollbar-thumb-color, #8888));
|
|
35
|
+
}
|
|
36
|
+
[dt]::-webkit-scrollbar-thumb:active, :host *::-webkit-scrollbar-thumb:active {
|
|
37
|
+
background-color: var(--scrollbar-thumb-color-active, var(--scrollbar-thumb-color, #2222));
|
|
38
|
+
cursor: grabbing;
|
|
39
|
+
}
|
|
40
|
+
[dt]::-webkit-scrollbar-track, :host *::-webkit-scrollbar-track {
|
|
41
|
+
background: transparent;
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
|
|
45
|
+
type EmitType = Record<string, any>;
|
|
46
|
+
export type Emit2EventMap<Emit extends EmitType> = {
|
|
47
|
+
[K in keyof Emit]: CustomEvent<Emit[K]>;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type ListenerFn<
|
|
51
|
+
Emit extends EmitType,
|
|
52
|
+
K extends keyof Emit | keyof HTMLElementEventMap
|
|
53
|
+
> = (
|
|
54
|
+
this: HTMLElement,
|
|
55
|
+
ev: K extends keyof Emit
|
|
56
|
+
? CustomEvent<Emit[K]>
|
|
57
|
+
: HTMLElementEventMap[K & keyof HTMLElementEventMap]
|
|
58
|
+
) => any;
|
|
59
|
+
|
|
60
|
+
export type EventListenerObj<
|
|
61
|
+
Emit extends EmitType,
|
|
62
|
+
K extends keyof Emit | keyof HTMLElementEventMap
|
|
63
|
+
> = { handleEvent: ListenerFn<Emit, K> };
|
|
64
|
+
|
|
65
|
+
export type EventListenerOrListenerObj<
|
|
66
|
+
Emit extends EmitType,
|
|
67
|
+
K extends keyof Emit | keyof HTMLElementEventMap
|
|
68
|
+
> = ListenerFn<Emit, K> | EventListenerObj<Emit, K>;
|
|
69
|
+
|
|
70
|
+
type getAttrType<Attr, K extends keyof Attr> = Extract<
|
|
71
|
+
Attr[K],
|
|
72
|
+
string
|
|
73
|
+
> extends never
|
|
74
|
+
? string
|
|
75
|
+
: Extract<Attr[K], string>;
|
|
76
|
+
|
|
77
|
+
// tagName to template element cache
|
|
78
|
+
const templateCache = new Map<string, HTMLTemplateElement>();
|
|
79
|
+
|
|
80
|
+
export interface BaseAttrs {
|
|
81
|
+
/**
|
|
82
|
+
* The language of the component.
|
|
83
|
+
* @type `Lang`
|
|
84
|
+
*/
|
|
85
|
+
lang?: Lang;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (typeof document === 'object') {
|
|
89
|
+
// const styleEle = document.createElement('style');
|
|
90
|
+
// styleEle.innerHTML = scrollbarStyleStr;
|
|
91
|
+
// document.head.prepend(styleEle);
|
|
92
|
+
const styleSheet = new CSSStyleSheet();
|
|
93
|
+
styleSheet.replaceSync(scrollbarStyleStr);
|
|
94
|
+
document.adoptedStyleSheets.unshift(styleSheet);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const HTMLElementBase = (() => {
|
|
98
|
+
if (typeof HTMLElement === 'function') return HTMLElement;
|
|
99
|
+
return class {} as typeof HTMLElement;
|
|
100
|
+
})();
|
|
101
|
+
|
|
102
|
+
export class UiBase<
|
|
103
|
+
Attr extends BaseAttrs = BaseAttrs,
|
|
104
|
+
Emit extends Record<string, any> = {}
|
|
105
|
+
> extends HTMLElementBase {
|
|
106
|
+
public static readonly tagName: string = '';
|
|
107
|
+
protected static _definePromise: Promise<CustomElementConstructor> | null =
|
|
108
|
+
null;
|
|
109
|
+
public static define() {
|
|
110
|
+
if (this._definePromise) return this._definePromise;
|
|
111
|
+
if (typeof customElements === 'undefined') {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const tagName = this.tagName;
|
|
115
|
+
if (!tagName) throw new Error('UiBase.define: tagName is not defined.');
|
|
116
|
+
console.log('Define custom element:', tagName);
|
|
117
|
+
customElements.define(tagName, this);
|
|
118
|
+
return (this._definePromise = customElements.whenDefined(tagName));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// TODO: use override keyword in subclasses
|
|
122
|
+
static get observedAttributes(): string[] {
|
|
123
|
+
return ['lang'] satisfies (keyof BaseAttrs)[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
protected _template = '';
|
|
127
|
+
protected _style = '';
|
|
128
|
+
protected _initTemplate() {
|
|
129
|
+
const { tagName } = this;
|
|
130
|
+
if (templateCache.has(tagName)) return templateCache.get(tagName)!;
|
|
131
|
+
const templateEle = document.createElement('template');
|
|
132
|
+
templateEle.innerHTML = `<style>${scrollbarStyleStr}${styleStr}${this._style}</style>${this._template}`;
|
|
133
|
+
templateCache.set(tagName, templateEle);
|
|
134
|
+
return templateEle;
|
|
135
|
+
}
|
|
136
|
+
protected _applyTemplate() {
|
|
137
|
+
if (!this.shadowRoot) return;
|
|
138
|
+
this.shadowRoot.innerHTML = '';
|
|
139
|
+
this.shadowRoot.appendChild(
|
|
140
|
+
this._initTemplate().content.cloneNode(true)
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
constructor() {
|
|
145
|
+
super();
|
|
146
|
+
this.attachShadow({ mode: 'open' });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
protected _getAttr<
|
|
150
|
+
K extends keyof Attr,
|
|
151
|
+
D extends undefined | getAttrType<Attr, K> = undefined
|
|
152
|
+
>(
|
|
153
|
+
qualifiedName: K,
|
|
154
|
+
defaultValue?: D
|
|
155
|
+
): undefined extends D
|
|
156
|
+
? getAttrType<Attr, K> | null
|
|
157
|
+
: getAttrType<Attr, K> {
|
|
158
|
+
const attr = this.getAttribute(qualifiedName as string);
|
|
159
|
+
return (
|
|
160
|
+
attr === null && defaultValue !== void 0 ? defaultValue : attr
|
|
161
|
+
) as getAttrType<Attr, K>;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
protected _onAttrChanged(_name: string, _oldVal: string, _newVal: string) {}
|
|
165
|
+
|
|
166
|
+
attributeChangedCallback(name: string, oldValue: string, newValue: string) {
|
|
167
|
+
if (oldValue === newValue) return;
|
|
168
|
+
if (name !== 'lang')
|
|
169
|
+
return this._onAttrChanged(name, oldValue, newValue);
|
|
170
|
+
this.shadowRoot?.querySelectorAll('[dt]').forEach((ele) => {
|
|
171
|
+
if (newValue) {
|
|
172
|
+
ele.setAttribute('lang', newValue);
|
|
173
|
+
} else {
|
|
174
|
+
ele.removeAttribute('lang');
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
/** return false | void means not continue */
|
|
179
|
+
connectedCallback(): boolean | void {
|
|
180
|
+
this.setAttribute('dt', '');
|
|
181
|
+
return !!this.shadowRoot;
|
|
182
|
+
}
|
|
183
|
+
/** return false | void means not continue */
|
|
184
|
+
disconnectedCallback(): boolean | void {
|
|
185
|
+
return !!this.shadowRoot;
|
|
186
|
+
}
|
|
187
|
+
connectedMoveCallback() {}
|
|
188
|
+
adoptedCallback() {}
|
|
189
|
+
|
|
190
|
+
dispatchEvent<K extends keyof Emit | undefined = undefined>(
|
|
191
|
+
type: K | Event,
|
|
192
|
+
data?: K extends keyof Emit ? Emit[K] : any,
|
|
193
|
+
global = false
|
|
194
|
+
) {
|
|
195
|
+
return type instanceof Event
|
|
196
|
+
? super.dispatchEvent(type)
|
|
197
|
+
: super.dispatchEvent(
|
|
198
|
+
new CustomEvent(type as string, {
|
|
199
|
+
...(global
|
|
200
|
+
? {
|
|
201
|
+
bubbles: true,
|
|
202
|
+
cancelable: true,
|
|
203
|
+
composed: true
|
|
204
|
+
}
|
|
205
|
+
: {}),
|
|
206
|
+
detail: data
|
|
207
|
+
})
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public addEventListener<K extends keyof Emit | keyof HTMLElementEventMap>(
|
|
212
|
+
type: K | string,
|
|
213
|
+
listener: EventListenerOrListenerObj<Emit, K>,
|
|
214
|
+
options?: boolean | EventListenerOptions
|
|
215
|
+
): void {
|
|
216
|
+
super.addEventListener(
|
|
217
|
+
type as string,
|
|
218
|
+
listener as EventListenerOrEventListenerObject,
|
|
219
|
+
options
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
public removeEventListener<
|
|
223
|
+
K extends keyof Emit | keyof HTMLElementEventMap
|
|
224
|
+
>(
|
|
225
|
+
type: K | string,
|
|
226
|
+
listener: EventListenerOrListenerObj<Emit, K>,
|
|
227
|
+
options?: boolean | EventListenerOptions
|
|
228
|
+
): void {
|
|
229
|
+
super.removeEventListener(
|
|
230
|
+
type as string,
|
|
231
|
+
listener as EventListenerOrEventListenerObject,
|
|
232
|
+
options
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
[dt], :host * {
|
|
3
|
+
&::-webkit-scrollbar {
|
|
4
|
+
width: 6px;
|
|
5
|
+
height: 6px;
|
|
6
|
+
}
|
|
7
|
+
&::-webkit-scrollbar-button {
|
|
8
|
+
display: none;
|
|
9
|
+
}
|
|
10
|
+
&::-webkit-scrollbar-corner {
|
|
11
|
+
display: none;
|
|
12
|
+
}
|
|
13
|
+
&::-webkit-scrollbar-thumb {
|
|
14
|
+
background-color: var(--scrollbar-thumb-color, #4444);
|
|
15
|
+
border-radius: 4px;
|
|
16
|
+
cursor: grab;
|
|
17
|
+
|
|
18
|
+
&:hover {
|
|
19
|
+
background-color: var(--scrollbar-thumb-color-hover, var(--scrollbar-thumb-color, #8888));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:active {
|
|
23
|
+
background-color: var(--scrollbar-thumb-color-active, var(--scrollbar-thumb-color, #2222));
|
|
24
|
+
cursor: grabbing;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
&::-webkit-scrollbar-track {
|
|
28
|
+
background: transparent;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { debounce, html } from '../../utils';
|
|
2
|
+
import { Ele as NumListEle, type EventMap as NumListEvent } from '../num-list';
|
|
3
|
+
NumListEle.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 = '';
|
|
11
|
+
|
|
12
|
+
export interface Attrs extends BaseAttrs {
|
|
13
|
+
millisecond: number;
|
|
14
|
+
// 'max-millisecond'?: number;
|
|
15
|
+
// 'min-millisecond'?: number;
|
|
16
|
+
/**
|
|
17
|
+
* 选择器的粒度,表示最大可选的时间单位。默认为 year。
|
|
18
|
+
* 例如设置为 'month',则表示最大只能选择到月份,年将被忽略。
|
|
19
|
+
*/
|
|
20
|
+
'max-granularity'?: 'year' | 'month' | 'day';
|
|
21
|
+
/**
|
|
22
|
+
* 选择器的粒度,表示最小可选的时间单位。默认为 second。
|
|
23
|
+
* 例如设置为 'month',则表示只能选择到月份,日会将被忽略。
|
|
24
|
+
*/
|
|
25
|
+
'min-granularity'?: 'year' | 'month' | 'day';
|
|
26
|
+
'col-order'?: 'ymd' | 'ydm' | 'myd' | 'mdy' | 'dym' | 'dmy';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface Emits {
|
|
30
|
+
change: {
|
|
31
|
+
oldMs: number;
|
|
32
|
+
newMs: number;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export type EventMap = Emit2EventMap<Emits>;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 日期选择器
|
|
39
|
+
*/
|
|
40
|
+
export class Ele extends UiBase<Attrs, Emits> {
|
|
41
|
+
public static readonly tagName = 'dt-yyyymmdd-list-grp' as const;
|
|
42
|
+
|
|
43
|
+
static get observedAttributes(): string[] {
|
|
44
|
+
return [
|
|
45
|
+
...(super.observedAttributes as (keyof BaseAttrs)[]),
|
|
46
|
+
'millisecond',
|
|
47
|
+
'max-granularity',
|
|
48
|
+
'min-granularity',
|
|
49
|
+
'col-order'
|
|
50
|
+
] satisfies (keyof Attrs)[];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
protected _style = styleStr;
|
|
54
|
+
protected _template = html`
|
|
55
|
+
<div class="cols" part="cols">
|
|
56
|
+
<div class="col year" part="col year">
|
|
57
|
+
<span part="col label year">Year</span>
|
|
58
|
+
<dt-num-list part="list year" class="year"></dt-num-list>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="col month" part="col month">
|
|
61
|
+
<span part="col label month">Month</span>
|
|
62
|
+
<dt-num-list part="list month" class="month" min-num="1" max-num="12"></dt-num-list>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="col day" part="col day">
|
|
65
|
+
<span part="col label day">Day</span>
|
|
66
|
+
<dt-num-list part="list day" class="day" min-num="1" max-num="31"></dt-num-list>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
constructor() {
|
|
72
|
+
super();
|
|
73
|
+
this._applyTemplate();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private get _listEleYear() {
|
|
77
|
+
return this.shadowRoot?.querySelector('dt-num-list.year') as NumListEle;
|
|
78
|
+
}
|
|
79
|
+
private get _listEleMonth() {
|
|
80
|
+
return this.shadowRoot?.querySelector(
|
|
81
|
+
'dt-num-list.month'
|
|
82
|
+
) as NumListEle;
|
|
83
|
+
}
|
|
84
|
+
private get _listEleDay() {
|
|
85
|
+
return this.shadowRoot?.querySelector('dt-num-list.day') as NumListEle;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public get millisecond() {
|
|
89
|
+
return Math.floor(+this._getAttr('millisecond', '0'));
|
|
90
|
+
}
|
|
91
|
+
public set millisecond(v: number) {
|
|
92
|
+
if (!Number.isSafeInteger(v)) return;
|
|
93
|
+
this.setAttribute('millisecond', '' + Math.floor(v));
|
|
94
|
+
}
|
|
95
|
+
public get maxGranularity() {
|
|
96
|
+
return this._getAttr('max-granularity', 'year') as
|
|
97
|
+
| 'year'
|
|
98
|
+
| 'month'
|
|
99
|
+
| 'day';
|
|
100
|
+
}
|
|
101
|
+
public set maxGranularity(v: 'year' | 'month' | 'day') {
|
|
102
|
+
if (!['year', 'month', 'day'].includes(v)) return;
|
|
103
|
+
this.setAttribute('max-granularity', v);
|
|
104
|
+
}
|
|
105
|
+
public get minGranularity() {
|
|
106
|
+
return this._getAttr('min-granularity', 'day') as
|
|
107
|
+
| 'year'
|
|
108
|
+
| 'month'
|
|
109
|
+
| 'day';
|
|
110
|
+
}
|
|
111
|
+
public set minGranularity(v: 'year' | 'month' | 'day') {
|
|
112
|
+
if (!['year', 'month', 'day'].includes(v)) return;
|
|
113
|
+
this.setAttribute('min-granularity', v);
|
|
114
|
+
}
|
|
115
|
+
public get colOrder() {
|
|
116
|
+
return this._getAttr('col-order', 'dmy') as
|
|
117
|
+
| 'ymd'
|
|
118
|
+
| 'ydm'
|
|
119
|
+
| 'myd'
|
|
120
|
+
| 'mdy'
|
|
121
|
+
| 'dym'
|
|
122
|
+
| 'dmy';
|
|
123
|
+
}
|
|
124
|
+
public set colOrder(v: 'ymd' | 'ydm' | 'myd' | 'mdy' | 'dym' | 'dmy') {
|
|
125
|
+
if (!['ymd', 'ydm', 'myd', 'mdy', 'dym', 'dmy'].includes(v)) return;
|
|
126
|
+
this.setAttribute('col-order', v);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public scrollToCurrentItem() {
|
|
130
|
+
this.shadowRoot?.querySelectorAll('dt-num-list').forEach((ele) => {
|
|
131
|
+
if (ele instanceof NumListEle) ele.scrollToCurrent();
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public connectedCallback() {
|
|
136
|
+
if (!super.connectedCallback()) return;
|
|
137
|
+
this._listEleYear.formatter = (num) => '' + num;
|
|
138
|
+
this._listEleMonth.formatter = this._listEleDay.formatter = (num) =>
|
|
139
|
+
('0' + num).slice(-2);
|
|
140
|
+
|
|
141
|
+
this._renderCols();
|
|
142
|
+
this._updateGranularity();
|
|
143
|
+
this._updateColsValue();
|
|
144
|
+
|
|
145
|
+
this._listEleYear.addEventListener('select-num', this._onColsSelect);
|
|
146
|
+
this._listEleMonth.addEventListener('select-num', this._onColsSelect);
|
|
147
|
+
this._listEleDay.addEventListener('select-num', this._onColsSelect);
|
|
148
|
+
}
|
|
149
|
+
public disconnectedCallback() {
|
|
150
|
+
if (!super.disconnectedCallback()) return;
|
|
151
|
+
this._listEleYear.removeEventListener('select-num', this._onColsSelect);
|
|
152
|
+
this._listEleMonth.removeEventListener(
|
|
153
|
+
'select-num',
|
|
154
|
+
this._onColsSelect
|
|
155
|
+
);
|
|
156
|
+
this._listEleDay.removeEventListener('select-num', this._onColsSelect);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
protected _onAttrChanged(name: string, oldValue: string, newValue: string) {
|
|
160
|
+
super._onAttrChanged(name, oldValue, newValue);
|
|
161
|
+
if (name === 'col-order') this._renderCols();
|
|
162
|
+
else if (name === 'max-granularity' || name === 'min-granularity')
|
|
163
|
+
this._updateGranularity();
|
|
164
|
+
else if (name === 'millisecond') this._updateColsValue();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private _renderCols = debounce(() => {
|
|
168
|
+
if (!this.isConnected) return;
|
|
169
|
+
const { colOrder } = this;
|
|
170
|
+
// columns order
|
|
171
|
+
const orderedCols = ['year', 'month', 'day']
|
|
172
|
+
.sort((a, b) => colOrder.indexOf(a[0]) - colOrder.indexOf(b[0]))
|
|
173
|
+
.map(
|
|
174
|
+
(s) => this.shadowRoot!.querySelector<HTMLElement>(`.col.${s}`)!
|
|
175
|
+
);
|
|
176
|
+
const colsContainer =
|
|
177
|
+
this.shadowRoot!.querySelector<HTMLElement>('.cols')!;
|
|
178
|
+
// return if order not changed
|
|
179
|
+
if (orderedCols.every((el, i) => el === colsContainer.children[i]))
|
|
180
|
+
return;
|
|
181
|
+
colsContainer.append(...orderedCols);
|
|
182
|
+
}, 0);
|
|
183
|
+
|
|
184
|
+
private _updateGranularity = debounce(() => {
|
|
185
|
+
if (!this.isConnected) return;
|
|
186
|
+
const { maxGranularity, minGranularity } = this;
|
|
187
|
+
const colsContainer =
|
|
188
|
+
this.shadowRoot!.querySelector<HTMLElement>('.cols')!;
|
|
189
|
+
const yEle = this.shadowRoot!.querySelector<HTMLElement>('.col.year')!;
|
|
190
|
+
const mEle = this.shadowRoot!.querySelector<HTMLElement>('.col.month')!;
|
|
191
|
+
const dEle = this.shadowRoot!.querySelector<HTMLElement>('.col.day')!;
|
|
192
|
+
const granularityMap = { year: 3, month: 2, day: 1 };
|
|
193
|
+
let maxG = granularityMap[maxGranularity] ?? 1;
|
|
194
|
+
let minG = granularityMap[minGranularity] ?? 3;
|
|
195
|
+
if (maxG < minG) [maxG, minG] = [minG, maxG];
|
|
196
|
+
yEle.style.display = maxG >= 3 && minG <= 3 ? '' : 'none';
|
|
197
|
+
mEle.style.display = maxG >= 2 && minG <= 2 ? '' : 'none';
|
|
198
|
+
dEle.style.display = maxG >= 1 && minG <= 1 ? '' : 'none';
|
|
199
|
+
colsContainer.style.display = [yEle, mEle, dEle].filter(
|
|
200
|
+
(ele) => ele.style.display !== 'none'
|
|
201
|
+
).length
|
|
202
|
+
? ''
|
|
203
|
+
: 'none';
|
|
204
|
+
}, 0);
|
|
205
|
+
|
|
206
|
+
private _updateColsValue = debounce(() => {
|
|
207
|
+
if (!this.isConnected) return;
|
|
208
|
+
const { millisecond } = this;
|
|
209
|
+
const date = new Date(millisecond);
|
|
210
|
+
if (Number.isNaN(date.getTime())) return;
|
|
211
|
+
this._listEleYear.currentNum = date.getFullYear();
|
|
212
|
+
this._listEleMonth.currentNum = date.getMonth() + 1;
|
|
213
|
+
this._listEleDay.maxNum = new Date(
|
|
214
|
+
date.getFullYear(),
|
|
215
|
+
date.getMonth() + 1,
|
|
216
|
+
0
|
|
217
|
+
).getDate();
|
|
218
|
+
this._listEleDay.currentNum = date.getDate();
|
|
219
|
+
}, 0);
|
|
220
|
+
|
|
221
|
+
private _getMsFromEle() {
|
|
222
|
+
const month = this._listEleMonth.currentNum;
|
|
223
|
+
const date = new Date(
|
|
224
|
+
this._listEleYear.currentNum,
|
|
225
|
+
month - 1,
|
|
226
|
+
this._listEleDay.currentNum
|
|
227
|
+
);
|
|
228
|
+
if (date.getMonth() + 1 !== month) {
|
|
229
|
+
// 日期不符合预期,可能是因为月份天数不够
|
|
230
|
+
// 例如 2021-02-30,Date 对象会自动调整为 2021-03-02
|
|
231
|
+
// 这里需要将日期设置为该月的最后一天
|
|
232
|
+
date.setDate(0);
|
|
233
|
+
}
|
|
234
|
+
return +date;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private _onColsSelect = ({
|
|
238
|
+
target,
|
|
239
|
+
detail: { newNum }
|
|
240
|
+
}: NumListEvent['select-num']) => {
|
|
241
|
+
if (!(target instanceof NumListEle)) return;
|
|
242
|
+
target.currentNum = newNum;
|
|
243
|
+
const oldMs = this.millisecond;
|
|
244
|
+
const newMs = this._getMsFromEle();
|
|
245
|
+
this.millisecond = newMs;
|
|
246
|
+
this.dispatchEvent(
|
|
247
|
+
'change',
|
|
248
|
+
{
|
|
249
|
+
oldMs,
|
|
250
|
+
newMs: this.millisecond
|
|
251
|
+
},
|
|
252
|
+
true
|
|
253
|
+
);
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
Ele.define();
|