@gez/date-time-kit 1.1.4 → 2.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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/date-time-selector/index.d.ts +53 -0
- package/dist/components/date-time-selector/index.mjs +180 -0
- package/dist/components/date-time-selector/styleStr.d.ts +1 -0
- package/dist/components/date-time-selector/styleStr.mjs +6 -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/index.css +153 -0
- package/dist/components/period-selector/index.d.ts +77 -0
- package/dist/components/period-selector/index.mjs +331 -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 +86 -0
- package/dist/components/quick-selector/index.mjs +379 -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/yyyymm-nav/index.css +92 -0
- package/dist/components/yyyymm-nav/index.d.ts +62 -0
- package/dist/components/yyyymm-nav/index.mjs +160 -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 +8 -0
- package/dist/index.mjs +17 -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/date-time-selector/index.ts +239 -0
- package/src/components/date-time-selector/styleStr.ts +86 -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/index.scss +161 -0
- package/src/components/period-selector/index.ts +581 -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 +656 -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/yyyymm-nav/index.scss +108 -0
- package/src/components/yyyymm-nav/index.ts +319 -0
- package/src/components/yyyymmdd-list-grp/index.scss +33 -0
- package/src/components/yyyymmdd-list-grp/index.ts +290 -0
- package/src/i18n.ts +415 -0
- package/src/index.ts +13 -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,108 @@
|
|
|
1
|
+
|
|
2
|
+
.wrapper {
|
|
3
|
+
display: block;
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
display: flex;
|
|
7
|
+
justify-content: space-between;
|
|
8
|
+
overflow: hidden;
|
|
9
|
+
|
|
10
|
+
&.show-list .btns {
|
|
11
|
+
display: none;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.btns {
|
|
16
|
+
display: flex;
|
|
17
|
+
align-items: center;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.btn {
|
|
21
|
+
width: 25px;
|
|
22
|
+
height: 25px;
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
background: 50% / 16px 16px no-repeat;
|
|
25
|
+
--icon-arrow-left: url('@/assets/arrow-left.svg');
|
|
26
|
+
--icon-arrow-left-double: url('@/assets/arrow-left-double.svg');
|
|
27
|
+
--icon-arrow-right: url('@/assets/arrow-right.svg');
|
|
28
|
+
--icon-arrow-right-double: url('@/assets/arrow-right-double.svg');
|
|
29
|
+
background-image: var(--bg-img);
|
|
30
|
+
border-radius: 50%;
|
|
31
|
+
|
|
32
|
+
&:hover {
|
|
33
|
+
background-color: #eee;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:host(:not([show-ctrl-btn-year-add])) &.add.year,
|
|
37
|
+
:host(:not([show-ctrl-btn-year-sub])) &.sub.year,
|
|
38
|
+
:host(:not([show-ctrl-btn-month-add])) &.add.month,
|
|
39
|
+
:host(:not([show-ctrl-btn-month-sub])) &.sub.month {
|
|
40
|
+
display: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&.sub {
|
|
44
|
+
--bg-img: var(--icon-arrow-left);
|
|
45
|
+
|
|
46
|
+
:host([show-ctrl-btn-month-add]) &.add.year,
|
|
47
|
+
:host([show-ctrl-btn-month-sub]) &.sub.year {
|
|
48
|
+
--bg-img: var(--icon-arrow-left-double);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&.add {
|
|
53
|
+
--bg-img: var(--icon-arrow-right);
|
|
54
|
+
|
|
55
|
+
:host([show-ctrl-btn-month-add]) &.add.year,
|
|
56
|
+
:host([show-ctrl-btn-month-sub]) &.sub.year {
|
|
57
|
+
--bg-img: var(--icon-arrow-right-double);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
dt-yyyymmdd-list-grp {
|
|
63
|
+
width: 100%;
|
|
64
|
+
|
|
65
|
+
&::part(list) {
|
|
66
|
+
scroll-behavior: smooth;
|
|
67
|
+
}
|
|
68
|
+
&::part(col label) {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
dt-popover {
|
|
74
|
+
width: 100%;
|
|
75
|
+
display: flex;
|
|
76
|
+
flex-direction: column;
|
|
77
|
+
align-items: center;
|
|
78
|
+
justify-content: center;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.title-wrapper {
|
|
82
|
+
box-sizing: border-box;
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
gap: 2px;
|
|
86
|
+
cursor: pointer;
|
|
87
|
+
// 25px = icon height
|
|
88
|
+
margin: calc((45px - 25px) / 2) 0;
|
|
89
|
+
min-height: 25px;
|
|
90
|
+
padding: 0 10px;
|
|
91
|
+
border-radius: 2px;
|
|
92
|
+
user-select: none;
|
|
93
|
+
|
|
94
|
+
&:hover {
|
|
95
|
+
background-color: #eee;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.title-arrow {
|
|
100
|
+
display: inline-block;
|
|
101
|
+
width: 16px;
|
|
102
|
+
height: 16px;
|
|
103
|
+
background: url('@/assets/arrow-down.svg') no-repeat center center;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
dt-popover[open] .title-arrow {
|
|
107
|
+
transform: rotate(180deg);
|
|
108
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { css, debounce, html } from '../../utils';
|
|
2
|
+
import {
|
|
3
|
+
type BaseAttrs,
|
|
4
|
+
type Emit2EventMap,
|
|
5
|
+
UiBase
|
|
6
|
+
} from '../web-component-base';
|
|
7
|
+
// import styleStr from './index.scss?inline';
|
|
8
|
+
const styleStr = css`
|
|
9
|
+
.wrapper {
|
|
10
|
+
display: block;
|
|
11
|
+
width: 100%;
|
|
12
|
+
height: 100%;
|
|
13
|
+
display: flex;
|
|
14
|
+
justify-content: space-between;
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
}
|
|
17
|
+
.wrapper.show-list .btns {
|
|
18
|
+
display: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.btns {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.btn {
|
|
27
|
+
width: 25px;
|
|
28
|
+
height: 25px;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
background: 50%/16px 16px no-repeat;
|
|
31
|
+
--icon-arrow-left: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='17' fill='currentColor'%3E%3Cpath d='M11.687 1.703a.5.5 0 0 0-.707 0L4.852 7.83a.505.505 0 0 0-.045.05.5.5 0 0 0-.051.752l6.128 6.128a.5.5 0 0 0 .707-.707L5.817 8.28l5.87-5.87a.5.5 0 0 0 0-.707Z'/%3E%3C/svg%3E");
|
|
32
|
+
--icon-arrow-left-double: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='17' fill='currentColor'%3E%3Cpath d='M9.037 1.98a.5.5 0 1 1 .707.707l-5.87 5.87 5.774 5.774a.5.5 0 1 1-.707.707L2.813 8.911a.5.5 0 0 1 .051-.752.505.505 0 0 1 .045-.051L9.037 1.98ZM13.037 1.98a.5.5 0 0 1 .707.707l-5.87 5.87 5.774 5.774a.5.5 0 1 1-.707.707L6.813 8.911a.5.5 0 0 1 .051-.752.505.505 0 0 1 .045-.051l6.128-6.128Z'/%3E%3C/svg%3E");
|
|
33
|
+
--icon-arrow-right: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='17' height='17' fill='currentColor'%3E%3Cpath d='M5.256 1.703a.5.5 0 0 1 .707 0l6.128 6.128a.493.493 0 0 1 .045.05.5.5 0 0 1 .051.752l-6.128 6.128a.5.5 0 0 1-.707-.707l5.774-5.774-5.87-5.87a.5.5 0 0 1 0-.707Z'/%3E%3C/svg%3E");
|
|
34
|
+
--icon-arrow-right-double: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='17' height='17' fill='currentColor'%3E%3Cpath d='M7.963 1.703a.5.5 0 0 0-.707.707l5.87 5.87-5.774 5.774a.5.5 0 0 0 .707.707l6.128-6.128a.5.5 0 0 0-.051-.751.493.493 0 0 0-.045-.051L7.963 1.703ZM3.963 1.703a.5.5 0 0 0-.707.707l5.87 5.87-5.774 5.774a.5.5 0 0 0 .707.707l6.128-6.128a.5.5 0 0 0-.051-.751.493.493 0 0 0-.045-.051L3.963 1.703Z'/%3E%3C/svg%3E");
|
|
35
|
+
background-image: var(--bg-img);
|
|
36
|
+
border-radius: 50%;
|
|
37
|
+
}
|
|
38
|
+
.btn:hover {
|
|
39
|
+
background-color: #eee;
|
|
40
|
+
}
|
|
41
|
+
:host(:not([show-ctrl-btn-year-add])) .btn.add.year, :host(:not([show-ctrl-btn-year-sub])) .btn.sub.year, :host(:not([show-ctrl-btn-month-add])) .btn.add.month, :host(:not([show-ctrl-btn-month-sub])) .btn.sub.month {
|
|
42
|
+
display: none;
|
|
43
|
+
}
|
|
44
|
+
.btn.sub {
|
|
45
|
+
--bg-img: var(--icon-arrow-left);
|
|
46
|
+
}
|
|
47
|
+
:host([show-ctrl-btn-month-add]) .btn.sub.add.year, :host([show-ctrl-btn-month-sub]) .btn.sub.sub.year {
|
|
48
|
+
--bg-img: var(--icon-arrow-left-double);
|
|
49
|
+
}
|
|
50
|
+
.btn.add {
|
|
51
|
+
--bg-img: var(--icon-arrow-right);
|
|
52
|
+
}
|
|
53
|
+
:host([show-ctrl-btn-month-add]) .btn.add.add.year, :host([show-ctrl-btn-month-sub]) .btn.add.sub.year {
|
|
54
|
+
--bg-img: var(--icon-arrow-right-double);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
dt-yyyymmdd-list-grp {
|
|
58
|
+
width: 100%;
|
|
59
|
+
}
|
|
60
|
+
dt-yyyymmdd-list-grp::part(list) {
|
|
61
|
+
scroll-behavior: smooth;
|
|
62
|
+
}
|
|
63
|
+
dt-yyyymmdd-list-grp::part(col label) {
|
|
64
|
+
display: none;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
dt-popover {
|
|
68
|
+
width: 100%;
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
align-items: center;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.title-wrapper {
|
|
76
|
+
box-sizing: border-box;
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
gap: 2px;
|
|
80
|
+
cursor: pointer;
|
|
81
|
+
margin: 10px 0;
|
|
82
|
+
min-height: 25px;
|
|
83
|
+
padding: 0 10px;
|
|
84
|
+
border-radius: 2px;
|
|
85
|
+
user-select: none;
|
|
86
|
+
}
|
|
87
|
+
.title-wrapper:hover {
|
|
88
|
+
background-color: #eee;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.title-arrow {
|
|
92
|
+
display: inline-block;
|
|
93
|
+
width: 16px;
|
|
94
|
+
height: 16px;
|
|
95
|
+
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' fill='currentColor'%3E%3Cpath d='m8.02 10.54 3.96-4.4a.583.583 0 0 0-.433-.973h-7.88a.583.583 0 0 0-.434.973l3.94 4.378c.216.24.585.26.824.044l.022-.021Z'/%3E%3C/svg%3E") no-repeat center center;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
dt-popover[open] .title-arrow {
|
|
99
|
+
transform: rotate(180deg);
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
import { Ele as PopoverEle, type EventMap as PopoverEvent } from '../popover';
|
|
103
|
+
PopoverEle.define();
|
|
104
|
+
import {
|
|
105
|
+
Ele as YyyyMmDdListGrpEle,
|
|
106
|
+
type EventMap as YyyyMmDdListGrpEvent
|
|
107
|
+
} from '../yyyymmdd-list-grp';
|
|
108
|
+
YyyyMmDdListGrpEle.define();
|
|
109
|
+
|
|
110
|
+
export interface Attrs extends BaseAttrs {
|
|
111
|
+
millisecond: number;
|
|
112
|
+
/**
|
|
113
|
+
* 选择器的粒度,表示最大可选的时间单位。默认为 year。
|
|
114
|
+
*/
|
|
115
|
+
'max-granularity'?: 'year' | 'month';
|
|
116
|
+
/**
|
|
117
|
+
* 选择器的粒度,表示最小可选的时间单位。默认为 month。
|
|
118
|
+
*/
|
|
119
|
+
'min-granularity'?: 'year' | 'month';
|
|
120
|
+
/**
|
|
121
|
+
* 是否显示年份控制按钮(快速增减年份)
|
|
122
|
+
* @default false
|
|
123
|
+
*/
|
|
124
|
+
'show-ctrl-btn-year-add'?: boolean;
|
|
125
|
+
'show-ctrl-btn-year-sub'?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* 是否显示月份控制按钮(快速增减月份)
|
|
128
|
+
* @default false
|
|
129
|
+
*/
|
|
130
|
+
'show-ctrl-btn-month-add'?: boolean;
|
|
131
|
+
'show-ctrl-btn-month-sub'?: boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface Emits {
|
|
135
|
+
change: {
|
|
136
|
+
oldTime: Date;
|
|
137
|
+
newTime: Date;
|
|
138
|
+
};
|
|
139
|
+
'popover-open-change': boolean;
|
|
140
|
+
}
|
|
141
|
+
export type EventMap = Emit2EventMap<Emits>;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 日期导航组件
|
|
145
|
+
*
|
|
146
|
+
* 存在一个 titleFormatter 方法,可以重写该方法以自定义年月标题的回显格式。
|
|
147
|
+
*/
|
|
148
|
+
export class Ele extends UiBase<Attrs, Emits> {
|
|
149
|
+
public static readonly tagName = 'dt-yyyymm-nav' as const;
|
|
150
|
+
|
|
151
|
+
static get observedAttributes(): string[] {
|
|
152
|
+
return [
|
|
153
|
+
...(super.observedAttributes as (keyof BaseAttrs)[]),
|
|
154
|
+
'millisecond',
|
|
155
|
+
'max-granularity',
|
|
156
|
+
'min-granularity',
|
|
157
|
+
'show-ctrl-btn-month-add',
|
|
158
|
+
'show-ctrl-btn-year-sub',
|
|
159
|
+
'show-ctrl-btn-month-add',
|
|
160
|
+
'show-ctrl-btn-month-sub'
|
|
161
|
+
] satisfies (keyof Attrs)[];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
protected _style = styleStr;
|
|
165
|
+
protected _template = html`
|
|
166
|
+
<div class="wrapper">
|
|
167
|
+
<div class="btns sub">
|
|
168
|
+
<i class="btn sub year"></i>
|
|
169
|
+
<i class="btn sub month"></i>
|
|
170
|
+
</div>
|
|
171
|
+
<dt-popover class="echo">
|
|
172
|
+
<div slot="trigger" class="title-wrapper">
|
|
173
|
+
<span class="title">title</span>
|
|
174
|
+
<i class="title-arrow"></i>
|
|
175
|
+
</div>
|
|
176
|
+
<dt-yyyymmdd-list-grp slot="pop" min-granularity="month" part="list-grp"></dt-yyyymmdd-list-grp>
|
|
177
|
+
</dt-popover>
|
|
178
|
+
<div class="btns add">
|
|
179
|
+
<i class="btn add month"></i>
|
|
180
|
+
<i class="btn add year"></i>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
`;
|
|
184
|
+
|
|
185
|
+
public get millisecond() {
|
|
186
|
+
return Math.floor(+this._getAttr('millisecond', '0'));
|
|
187
|
+
}
|
|
188
|
+
public set millisecond(v: number) {
|
|
189
|
+
if (!Number.isSafeInteger(v)) return;
|
|
190
|
+
this.setAttribute('millisecond', '' + Math.floor(v));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
public get showCtrlBtnYearAdd() {
|
|
194
|
+
return this.hasAttribute('show-ctrl-btn-year-add');
|
|
195
|
+
}
|
|
196
|
+
public set showCtrlBtnYearAdd(val: boolean) {
|
|
197
|
+
this.toggleAttribute('show-ctrl-btn-year-add', val);
|
|
198
|
+
}
|
|
199
|
+
public get showCtrlBtnYearSub() {
|
|
200
|
+
return this.hasAttribute('show-ctrl-btn-year-sub');
|
|
201
|
+
}
|
|
202
|
+
public set showCtrlBtnYearSub(val: boolean) {
|
|
203
|
+
this.toggleAttribute('show-ctrl-btn-year-sub', val);
|
|
204
|
+
}
|
|
205
|
+
public get showCtrlBtnMonthAdd() {
|
|
206
|
+
return this.hasAttribute('show-ctrl-btn-month-add');
|
|
207
|
+
}
|
|
208
|
+
public set showCtrlBtnMonthAdd(val: boolean) {
|
|
209
|
+
this.toggleAttribute('show-ctrl-btn-month-add', val);
|
|
210
|
+
}
|
|
211
|
+
public get showCtrlBtnMonthSub() {
|
|
212
|
+
return this.hasAttribute('show-ctrl-btn-month-sub');
|
|
213
|
+
}
|
|
214
|
+
public set showCtrlBtnMonthSub(val: boolean) {
|
|
215
|
+
this.toggleAttribute('show-ctrl-btn-month-sub', val);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
constructor() {
|
|
219
|
+
super();
|
|
220
|
+
this._applyTemplate();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
public connectedCallback() {
|
|
224
|
+
if (!super.connectedCallback()) return;
|
|
225
|
+
this._render();
|
|
226
|
+
this.shadowRoot!.querySelector<PopoverEle>('.echo')!.addEventListener(
|
|
227
|
+
'open-change',
|
|
228
|
+
this._onTitleToggle
|
|
229
|
+
);
|
|
230
|
+
this.shadowRoot!.querySelector<YyyyMmDdListGrpEle>(
|
|
231
|
+
'dt-yyyymmdd-list-grp'
|
|
232
|
+
)!.addEventListener('change', this._onItemSelect);
|
|
233
|
+
this.shadowRoot!.querySelectorAll<HTMLElement>('.btn').forEach(
|
|
234
|
+
(btn) => {
|
|
235
|
+
btn.addEventListener('click', this._onBtnClick);
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
public disconnectedCallback() {
|
|
240
|
+
if (!super.disconnectedCallback()) return;
|
|
241
|
+
this.shadowRoot!.querySelector<PopoverEle>(
|
|
242
|
+
'.echo'
|
|
243
|
+
)!.removeEventListener('open-change', this._onTitleToggle);
|
|
244
|
+
this.shadowRoot!.querySelector<YyyyMmDdListGrpEle>(
|
|
245
|
+
'dt-yyyymmdd-list-grp'
|
|
246
|
+
)!.removeEventListener('change', this._onItemSelect);
|
|
247
|
+
this.shadowRoot!.querySelectorAll<HTMLElement>('.btn').forEach(
|
|
248
|
+
(btn) => {
|
|
249
|
+
btn.removeEventListener('click', this._onBtnClick);
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
protected _onAttrChanged(name: string, oldValue: string, newValue: string) {
|
|
255
|
+
super._onAttrChanged(name, oldValue, newValue);
|
|
256
|
+
this._render();
|
|
257
|
+
if (name === 'millisecond') {
|
|
258
|
+
this.dispatchEvent(
|
|
259
|
+
'change',
|
|
260
|
+
{
|
|
261
|
+
oldTime: new Date(+oldValue),
|
|
262
|
+
newTime: new Date(+newValue)
|
|
263
|
+
},
|
|
264
|
+
true
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private _render = debounce(() => {
|
|
270
|
+
const root = this.shadowRoot!;
|
|
271
|
+
const ms = this.millisecond;
|
|
272
|
+
root.querySelector<YyyyMmDdListGrpEle>(
|
|
273
|
+
'dt-yyyymmdd-list-grp'
|
|
274
|
+
)!.millisecond = ms;
|
|
275
|
+
root.querySelector('.title')!.textContent = this.titleFormatter(ms);
|
|
276
|
+
}, 0);
|
|
277
|
+
|
|
278
|
+
private _onTitleToggle = (e: PopoverEvent['open-change']) => {
|
|
279
|
+
const isOpen = e.detail;
|
|
280
|
+
e.stopPropagation();
|
|
281
|
+
this.shadowRoot!.querySelector('.wrapper')!.classList.toggle(
|
|
282
|
+
'show-list',
|
|
283
|
+
isOpen
|
|
284
|
+
);
|
|
285
|
+
this.shadowRoot!.querySelector<YyyyMmDdListGrpEle>(
|
|
286
|
+
'dt-yyyymmdd-list-grp'
|
|
287
|
+
)!.scrollToCurrentItem();
|
|
288
|
+
this.dispatchEvent('popover-open-change', isOpen, true);
|
|
289
|
+
};
|
|
290
|
+
private _onItemSelect = (e: YyyyMmDdListGrpEvent['change']) => {
|
|
291
|
+
if (!(e.target instanceof YyyyMmDdListGrpEle)) return;
|
|
292
|
+
e.stopPropagation();
|
|
293
|
+
this.millisecond = e.target.millisecond;
|
|
294
|
+
};
|
|
295
|
+
private _onBtnClick = (e: MouseEvent) => {
|
|
296
|
+
if (!(e.target instanceof HTMLElement)) return;
|
|
297
|
+
const date = new Date(this.millisecond);
|
|
298
|
+
date.setDate(1);
|
|
299
|
+
if (e.target.matches('.add.year')) {
|
|
300
|
+
date.setFullYear(date.getFullYear() + 1);
|
|
301
|
+
} else if (e.target.matches('.sub.year')) {
|
|
302
|
+
date.setFullYear(date.getFullYear() - 1);
|
|
303
|
+
} else if (e.target.matches('.add.month')) {
|
|
304
|
+
date.setMonth(date.getMonth() + 1);
|
|
305
|
+
} else if (e.target.matches('.sub.month')) {
|
|
306
|
+
date.setMonth(date.getMonth() - 1);
|
|
307
|
+
}
|
|
308
|
+
this.millisecond = +date;
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
public titleFormatter = (ms: number) => {
|
|
312
|
+
const date = new Date(ms);
|
|
313
|
+
const year = date.getFullYear();
|
|
314
|
+
const month = date.getMonth() + 1;
|
|
315
|
+
return `${('0' + month).slice(-2)}/${year}`;
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
Ele.define();
|