easy-component-ui 0.0.2 → 1.0.3
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/components/Base.js +90 -0
- package/components/ea-alert/index.js +298 -0
- package/components/ea-avatar/index.js +277 -0
- package/components/ea-backtop/index.js +232 -0
- package/components/ea-badge/index.js +160 -0
- package/components/ea-button/index.js +584 -0
- package/components/ea-button-group/index.js +459 -0
- package/components/ea-calendar/index.js +409 -0
- package/components/ea-card/index.js +77 -0
- package/components/ea-carousel/index.js +434 -0
- package/components/ea-checkbox/index.js +314 -0
- package/components/ea-checkbox-group/index.js +107 -0
- package/components/ea-collapse/index.js +293 -0
- package/components/ea-descriptions/index.js +240 -0
- package/components/ea-descriptions-item/index.js +110 -0
- package/components/ea-empty/index.js +141 -0
- package/{icon → components/ea-icon}/config.json +1017 -1017
- package/{icon → components/ea-icon}/css/animation.css +85 -85
- package/{icon → components/ea-icon}/css/fontello.css +224 -224
- package/components/ea-icon/font/fontello.svg +683 -0
- package/components/ea-icon/index.css +2 -0
- package/components/ea-icon/index.js +47 -0
- package/components/ea-image/index.js +412 -0
- package/components/ea-infinite-scroll/index.js +170 -0
- package/components/ea-input/index.js +765 -0
- package/components/ea-input-number/index.js +458 -0
- package/components/ea-link/index.js +200 -0
- package/components/ea-loading/index.js +218 -0
- package/components/ea-message/MessageClass.js +71 -0
- package/components/ea-message/index.js +233 -0
- package/components/ea-message-box/EaMessageBoxClass.js +48 -0
- package/components/ea-message-box/index.js +202 -0
- package/components/ea-pagination/index.js +444 -0
- package/components/ea-progress/index.js +333 -0
- package/components/ea-radio/index.js +287 -0
- package/components/ea-radio-group/index.js +59 -0
- package/components/ea-rate/index.js +326 -0
- package/components/ea-result/index.js +167 -0
- package/components/ea-select/index.js +34 -0
- package/components/ea-skeleton/index.js +341 -0
- package/components/ea-switch/index.js +301 -0
- package/components/ea-tag/index.js +212 -0
- package/components/ea-textarea/index.js +333 -0
- package/components/ea-timeline/index.js +334 -0
- package/components/ea-ui-base-style.css +0 -0
- package/package.json +1 -1
- package/utils/createElement.js +30 -0
- package/utils/handleTemplate.js +19 -0
- package/utils/setStyle.js +8 -0
- package/icon/font/fontello.svg +0 -346
- package/icon/index.css +0 -2
- package/index.js +0 -1693
- /package/{icon → components/ea-icon}/css/fontello-codes.css +0 -0
- /package/{icon → components/ea-icon}/css/fontello-embedded.css +0 -0
- /package/{icon → components/ea-icon}/css/fontello-ie7-codes.css +0 -0
- /package/{icon → components/ea-icon}/css/fontello-ie7.css +0 -0
- /package/{icon → components/ea-icon}/font/fontello.eot +0 -0
- /package/{icon → components/ea-icon}/font/fontello.ttf +0 -0
- /package/{icon → components/ea-icon}/font/fontello.woff +0 -0
- /package/{icon → components/ea-icon}/font/fontello.woff2 +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import Base from "../Base.js";
|
|
3
|
+
|
|
4
|
+
export class EaIcon extends Base {
|
|
5
|
+
static observedAttributes = ['type', 'size', 'color'];
|
|
6
|
+
|
|
7
|
+
#wrap;
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
|
|
12
|
+
const shadowRoot = this.attachShadow({ mode: 'open' });
|
|
13
|
+
const wrap = document.createElement('i');
|
|
14
|
+
|
|
15
|
+
this.setIconFile(new URL('../ea-icon/index.css', import.meta.url).href);
|
|
16
|
+
|
|
17
|
+
this.#wrap = wrap;
|
|
18
|
+
|
|
19
|
+
shadowRoot.appendChild(wrap);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ------- icon 图标类名 -------
|
|
23
|
+
// #region
|
|
24
|
+
get icon() {
|
|
25
|
+
return this.getAttribute('icon') || "";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
set icon(value) {
|
|
29
|
+
this.setAttribute('icon', value);
|
|
30
|
+
|
|
31
|
+
this.#wrap.className = `${value}`;
|
|
32
|
+
}
|
|
33
|
+
// #endregion
|
|
34
|
+
// ------- end -------
|
|
35
|
+
|
|
36
|
+
#init() {
|
|
37
|
+
this.icon = this.icon;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
connectedCallback() {
|
|
41
|
+
this.#init()
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!window.customElements.get("ea-icon")) {
|
|
46
|
+
window.customElements.define("ea-icon", EaIcon);
|
|
47
|
+
}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import Base from '../Base.js';
|
|
3
|
+
import { createElement, createSlotElement } from '../../utils/createElement.js';
|
|
4
|
+
|
|
5
|
+
const stylesheet = `
|
|
6
|
+
.ea-image_wrap.is-loading, .ea-image_wrap.is-error {
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
background-color: #f5f7fa;
|
|
11
|
+
}
|
|
12
|
+
.ea-image_wrap.is-error svg {
|
|
13
|
+
width: 20px;
|
|
14
|
+
height: 20px;
|
|
15
|
+
}
|
|
16
|
+
.ea-image_wrap img {
|
|
17
|
+
position: relative;
|
|
18
|
+
width: 100%;
|
|
19
|
+
height: 100%;
|
|
20
|
+
user-zoom: scale;
|
|
21
|
+
object-fit: cover;
|
|
22
|
+
transition: rotate 0.3s, scale 0.3s;
|
|
23
|
+
}
|
|
24
|
+
.ea-image_wrap .ea-image_preview-wrap {
|
|
25
|
+
position: fixed;
|
|
26
|
+
top: 0;
|
|
27
|
+
left: 0;
|
|
28
|
+
width: 100%;
|
|
29
|
+
height: 100%;
|
|
30
|
+
z-index: 999;
|
|
31
|
+
opacity: 0;
|
|
32
|
+
transform: translateY(-1rem);
|
|
33
|
+
transition: opacity 0.3s, transform 0.3s;
|
|
34
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
35
|
+
}
|
|
36
|
+
.ea-image_wrap .ea-image_preview-wrap.entry {
|
|
37
|
+
opacity: 1;
|
|
38
|
+
transform: translateY(0);
|
|
39
|
+
}
|
|
40
|
+
.ea-image_wrap .ea-image_preview-wrap .ea-icon-close {
|
|
41
|
+
position: absolute;
|
|
42
|
+
right: 40px;
|
|
43
|
+
top: 40px;
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
width: 40px;
|
|
46
|
+
height: 40px;
|
|
47
|
+
font-size: 24px;
|
|
48
|
+
line-height: 36px;
|
|
49
|
+
border-radius: 50%;
|
|
50
|
+
color: #fff;
|
|
51
|
+
background-color: #606266;
|
|
52
|
+
text-align: center;
|
|
53
|
+
}
|
|
54
|
+
.ea-image_wrap .ea-image_preview-wrap img {
|
|
55
|
+
width: 100%;
|
|
56
|
+
height: 100%;
|
|
57
|
+
object-fit: contain;
|
|
58
|
+
}
|
|
59
|
+
.ea-image_wrap .ea-image_preview-tools {
|
|
60
|
+
display: flex;
|
|
61
|
+
align-items: center;
|
|
62
|
+
justify-content: space-around;
|
|
63
|
+
position: absolute;
|
|
64
|
+
bottom: 20px;
|
|
65
|
+
left: 50%;
|
|
66
|
+
padding: 0.5rem 1rem;
|
|
67
|
+
user-select: none;
|
|
68
|
+
border-radius: 999px;
|
|
69
|
+
transform: translateX(-50%);
|
|
70
|
+
background-color: rgba(96, 98, 102, 0.568627451);
|
|
71
|
+
color: #fff;
|
|
72
|
+
}
|
|
73
|
+
.ea-image_wrap .ea-image_preview-tools .ea-icon-zoom,
|
|
74
|
+
.ea-image_wrap .ea-image_preview-tools .ea-icon-rotate {
|
|
75
|
+
width: 2rem;
|
|
76
|
+
text-align: center;
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
margin: 0 1rem;
|
|
79
|
+
}
|
|
80
|
+
.ea-image_wrap .ea-image_preview-tools .ea-icon-zoom {
|
|
81
|
+
font-size: 2rem;
|
|
82
|
+
}
|
|
83
|
+
.ea-image_wrap .ea-image_preview-tools .ea-icon-zoom-in {
|
|
84
|
+
font-size: 1.75rem;
|
|
85
|
+
}
|
|
86
|
+
.ea-image_wrap .ea-image_preview-tools .ea-icon-rotate {
|
|
87
|
+
font-size: 1.5rem;
|
|
88
|
+
}
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
const errorImage = `
|
|
92
|
+
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
|
93
|
+
<path fill="#c0c4cc" d="M0 0h100v100H0z" />
|
|
94
|
+
<path fill="#fff" d="M15 20h70v60H15z" />
|
|
95
|
+
<circle r="8" cx="32" cy="35" fill="#c0c4cc" />
|
|
96
|
+
<path d="M60 42.5L39 75h42z" fill="#c0c4cc" />
|
|
97
|
+
<path d="M35 52.5L20 75h-4 32z" fill="#c0c4cc" />
|
|
98
|
+
</svg>
|
|
99
|
+
`;
|
|
100
|
+
|
|
101
|
+
export class EaImage extends Base {
|
|
102
|
+
#wrap;
|
|
103
|
+
|
|
104
|
+
#img;
|
|
105
|
+
#imgSlot;
|
|
106
|
+
|
|
107
|
+
#previewWrap;
|
|
108
|
+
|
|
109
|
+
constructor() {
|
|
110
|
+
super();
|
|
111
|
+
|
|
112
|
+
const shadowRoot = this.attachShadow({ mode: 'open' });
|
|
113
|
+
const wrap = document.createElement('div');
|
|
114
|
+
wrap.className = 'ea-image_wrap';
|
|
115
|
+
|
|
116
|
+
const imgSlot = createSlotElement('placeholder');
|
|
117
|
+
const img = createElement('img', 'ea-image', [imgSlot]);
|
|
118
|
+
wrap.appendChild(img);
|
|
119
|
+
|
|
120
|
+
this.#wrap = wrap;
|
|
121
|
+
this.#img = img;
|
|
122
|
+
this.#imgSlot = imgSlot;
|
|
123
|
+
|
|
124
|
+
this.build(shadowRoot, stylesheet);
|
|
125
|
+
this.shadowRoot.appendChild(wrap);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ------- src 图片的路径 -------
|
|
129
|
+
// #region
|
|
130
|
+
get src() {
|
|
131
|
+
return this.getAttribute('src') || "";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
set src(src) {
|
|
135
|
+
this.setAttribute('src', src);
|
|
136
|
+
}
|
|
137
|
+
// #endregion
|
|
138
|
+
// ------- end -------
|
|
139
|
+
|
|
140
|
+
// ------- width 图片宽度 -------
|
|
141
|
+
// #region
|
|
142
|
+
get width() {
|
|
143
|
+
return this.getAttribute('width') || "100px";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
set width(value) {
|
|
147
|
+
this.setAttribute('width', value);
|
|
148
|
+
|
|
149
|
+
this.#wrap.style.width = value;
|
|
150
|
+
}
|
|
151
|
+
// #endregion
|
|
152
|
+
// ------- end -------
|
|
153
|
+
|
|
154
|
+
// ------- height 图片高度 -------
|
|
155
|
+
// #region
|
|
156
|
+
get height() {
|
|
157
|
+
return this.getAttribute('height') || "100px";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
set height(value) {
|
|
161
|
+
this.setAttribute('height', value);
|
|
162
|
+
|
|
163
|
+
this.#wrap.style.height = value;
|
|
164
|
+
}
|
|
165
|
+
// #endregion
|
|
166
|
+
// ------- end -------
|
|
167
|
+
|
|
168
|
+
// ------- alt 图片描述 -------
|
|
169
|
+
// #region
|
|
170
|
+
get alt() {
|
|
171
|
+
return this.getAttribute('alt') || "";
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
set alt(value) {
|
|
175
|
+
this.setAttribute('alt', value);
|
|
176
|
+
|
|
177
|
+
this.#img.alt = value;
|
|
178
|
+
}
|
|
179
|
+
// #endregion
|
|
180
|
+
// ------- end -------
|
|
181
|
+
|
|
182
|
+
// ------- fit 图片缩放模式 -------
|
|
183
|
+
// #region
|
|
184
|
+
get fit() {
|
|
185
|
+
return this.getAttribute('fit') || "cover";
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
set fit(value) {
|
|
189
|
+
this.setAttribute('fit', value);
|
|
190
|
+
|
|
191
|
+
this.#img.style.objectFit = value;
|
|
192
|
+
}
|
|
193
|
+
// #endregion
|
|
194
|
+
// ------- end -------
|
|
195
|
+
|
|
196
|
+
// ------- lazy 图片懒加载 -------
|
|
197
|
+
// #region
|
|
198
|
+
get lazy() {
|
|
199
|
+
return this.getAttrBoolean('lazy');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
set lazy(value) {
|
|
203
|
+
this.setAttribute('lazy', value);
|
|
204
|
+
}
|
|
205
|
+
// #endregion
|
|
206
|
+
// ------- end -------
|
|
207
|
+
|
|
208
|
+
// ------- preview 大图预览 -------
|
|
209
|
+
// #region
|
|
210
|
+
get preview() {
|
|
211
|
+
return this.getAttrBoolean('preview');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
set preview(value) {
|
|
215
|
+
this.setAttribute('preview', value);
|
|
216
|
+
}
|
|
217
|
+
// #endregion
|
|
218
|
+
// ------- end -------
|
|
219
|
+
|
|
220
|
+
#handleImageLoad(src, isLazy = false) {
|
|
221
|
+
const image = new Image();
|
|
222
|
+
|
|
223
|
+
if (isLazy) {
|
|
224
|
+
const observer = new IntersectionObserver((entries) => {
|
|
225
|
+
if (entries[0].intersectionRatio <= 0) return;
|
|
226
|
+
|
|
227
|
+
image.src = src;
|
|
228
|
+
observer.disconnect();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
observer.observe(this.#wrap);
|
|
232
|
+
} else {
|
|
233
|
+
image.src = src;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
image.onload = () => {
|
|
237
|
+
this.#img.setAttribute('src', src);
|
|
238
|
+
this.#imgSlot.innerHTML = "";
|
|
239
|
+
|
|
240
|
+
this.dispatchEvent(new CustomEvent('load', { detail: { src } }));
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
image.onerror = () => {
|
|
244
|
+
this.#wrap.innerHTML = errorImage;
|
|
245
|
+
this.#wrap.classList.add('is-error');
|
|
246
|
+
this.#imgSlot.innerHTML = "";
|
|
247
|
+
|
|
248
|
+
this.dispatchEvent(new CustomEvent('error', { detail: { src } }));
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
#handlePreviewDisplay(wrap) {
|
|
253
|
+
wrap.classList.remove('entry');
|
|
254
|
+
|
|
255
|
+
wrap.addEventListener('transitionend', () => {
|
|
256
|
+
wrap.remove();
|
|
257
|
+
document.body.style.overflow = 'auto';
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* 创建一个图片预览的关闭按钮
|
|
263
|
+
*
|
|
264
|
+
* @returns {HTMLElement} 返回创建的关闭按钮元素
|
|
265
|
+
*/
|
|
266
|
+
#createCloseBtn(wrap) {
|
|
267
|
+
// 创建一个span元素,并设置其类名为'ea-icon-close',用于表示一个关闭图标
|
|
268
|
+
const closeBtn = createElement('span', 'ea-icon-close');
|
|
269
|
+
|
|
270
|
+
// 设置按钮的内联文本为"x",作为关闭符号
|
|
271
|
+
closeBtn.innerText = "x";
|
|
272
|
+
|
|
273
|
+
// 为按钮添加点击事件监听器,当按钮被点击时,调用#handlePreviewDisplay处理函数
|
|
274
|
+
closeBtn.addEventListener('click', () => {
|
|
275
|
+
this.#handlePreviewDisplay(wrap);
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// 返回创建的关闭按钮元素
|
|
279
|
+
return closeBtn;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 创建一个图片预览的关闭按钮
|
|
284
|
+
*
|
|
285
|
+
* @param {HTMLElement} img 图片元素
|
|
286
|
+
* @returns {HTMLElement} 返回创建的关闭按钮元素
|
|
287
|
+
*/
|
|
288
|
+
#createPreviewTools(img) {
|
|
289
|
+
const zoomInBtn = createElement('span', 'ea-icon-zoom ea-icon-zoom-in');
|
|
290
|
+
zoomInBtn.innerText = "+";
|
|
291
|
+
zoomInBtn.addEventListener('click', () => {
|
|
292
|
+
img.style.scale = img.style.scale ? Number(img.style.scale) + 0.2 : 1.2;
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const zoomOutBtn = createElement('span', 'ea-icon-zoom ea-icon-zoom-out');
|
|
296
|
+
zoomOutBtn.innerText = "-";
|
|
297
|
+
zoomOutBtn.addEventListener('click', () => {
|
|
298
|
+
img.style.scale = img.style.scale ? Number(img.style.scale) - 0.2 : 0.8;
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
const rotateLeft = createElement('span', 'ea-icon-rotate ea-icon-rotate-left');
|
|
302
|
+
rotateLeft.innerText = "↺";
|
|
303
|
+
rotateLeft.addEventListener('click', () => {
|
|
304
|
+
img.style.rotate = (img.style.rotate ? Number(img.style.rotate.split('deg')[0]) - 90 : -90) + "deg";
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
const rotateRight = createElement('span', 'ea-icon-rotate ea-icon-rotate-right');
|
|
308
|
+
rotateRight.innerText = "↻";
|
|
309
|
+
rotateRight.addEventListener('click', () => {
|
|
310
|
+
img.style.rotate = (img.style.rotate ? Number(img.style.rotate.split('deg')[0]) + 90 : 90) + "deg";
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const toolsWrap = createElement('div', 'ea-image_preview-tools', [zoomInBtn, zoomOutBtn, rotateLeft, rotateRight]);
|
|
314
|
+
|
|
315
|
+
return toolsWrap;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* 构建图片预览工具
|
|
320
|
+
* @param {HTMLElement} img 图片元素
|
|
321
|
+
*/
|
|
322
|
+
#handleImageDrag(wrap, img) {
|
|
323
|
+
let startX = 0;
|
|
324
|
+
let startY = 0;
|
|
325
|
+
|
|
326
|
+
function handleMouseMove(e) {
|
|
327
|
+
const { clientX, clientY } = e;
|
|
328
|
+
|
|
329
|
+
img.style.marginLeft = `${clientX - startX}px`;
|
|
330
|
+
img.style.marginTop = `${clientY - startY}px`;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
img.addEventListener('dragstart', (e) => {
|
|
334
|
+
e.preventDefault();
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
img.addEventListener('mousedown', (e) => {
|
|
338
|
+
startX = e.clientX;
|
|
339
|
+
startY = e.clientY;
|
|
340
|
+
|
|
341
|
+
img.addEventListener('mousemove', handleMouseMove);
|
|
342
|
+
|
|
343
|
+
img.addEventListener('mouseup', () => {
|
|
344
|
+
img.removeEventListener('mousemove', handleMouseMove);
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* 处理图片预览功能。
|
|
351
|
+
* 当isPreview参数为true时,为图片添加点击事件监听器,以实现预览功能。
|
|
352
|
+
* 预览功能包括:克隆图片元素、设置图片样式、处理图片拖动、创建关闭按钮和工具栏、以及隐藏滚动条。
|
|
353
|
+
* @param {boolean} isPreview - 是否开启图片预览功能。
|
|
354
|
+
*/
|
|
355
|
+
#handleImagePreview(isPreview) {
|
|
356
|
+
if (isPreview) {
|
|
357
|
+
this.#img.addEventListener('click', () => {
|
|
358
|
+
// 克隆图片元素以用于预览,并设置图片的object-fit属性为contain。
|
|
359
|
+
const img = this.#img.cloneNode(true);
|
|
360
|
+
img.style.objectFit = "contain";
|
|
361
|
+
|
|
362
|
+
// 创建预览包装元素,并将克隆的图片添加到其中。
|
|
363
|
+
const wrap = createElement('div', 'ea-image_preview-wrap', [img]);
|
|
364
|
+
this.#wrap.appendChild(wrap);
|
|
365
|
+
|
|
366
|
+
// 创建并添加关闭按钮到预览窗口。
|
|
367
|
+
const closeBtn = this.#createCloseBtn(wrap);
|
|
368
|
+
wrap.appendChild(closeBtn);
|
|
369
|
+
|
|
370
|
+
// 创建并添加预览工具栏到预览窗口。
|
|
371
|
+
const toolkit = this.#createPreviewTools(img, wrap);
|
|
372
|
+
wrap.appendChild(toolkit);
|
|
373
|
+
|
|
374
|
+
// 延迟20毫秒后添加动画入口类,以平滑地显示预览窗口。
|
|
375
|
+
setTimeout(() => {
|
|
376
|
+
wrap.classList.add('entry');
|
|
377
|
+
}, 20)
|
|
378
|
+
|
|
379
|
+
// 初始化图片拖动功能。
|
|
380
|
+
this.#handleImageDrag(wrap, img);
|
|
381
|
+
|
|
382
|
+
// 隐藏页面滚动条,以提供更好的预览体验。
|
|
383
|
+
document.body.style.overflow = 'hidden';
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
init() {
|
|
389
|
+
const that = this;
|
|
390
|
+
|
|
391
|
+
this.width = this.width;
|
|
392
|
+
this.height = this.height;
|
|
393
|
+
this.fit = this.fit;
|
|
394
|
+
this.alt = this.alt;
|
|
395
|
+
|
|
396
|
+
this.lazy = this.lazy;
|
|
397
|
+
this.src = this.src;
|
|
398
|
+
|
|
399
|
+
this.preview = this.preview;
|
|
400
|
+
|
|
401
|
+
this.#handleImageLoad(this.src, this.lazy);
|
|
402
|
+
this.#handleImagePreview(this.preview);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
connectedCallback() {
|
|
406
|
+
this.init();
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (!customElements.get('ea-image')) {
|
|
411
|
+
customElements.define('ea-image', EaImage);
|
|
412
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
import Base from '../Base.js';
|
|
3
|
+
import { createElement, createSlotElement } from '../../utils/createElement.js';
|
|
4
|
+
|
|
5
|
+
const stylesheet = `
|
|
6
|
+
`;
|
|
7
|
+
|
|
8
|
+
export class EaInfiniteScroll extends Base {
|
|
9
|
+
#wrap;
|
|
10
|
+
|
|
11
|
+
#loadingSlot;
|
|
12
|
+
|
|
13
|
+
#noMoreSlot;
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
super();
|
|
17
|
+
|
|
18
|
+
const shadowRoot = this.attachShadow({ mode: 'open' });
|
|
19
|
+
const wrap = document.createElement('div');
|
|
20
|
+
wrap.className = 'ea-infinite_wrap';
|
|
21
|
+
wrap.part = "wrap";
|
|
22
|
+
|
|
23
|
+
const slot = createSlotElement("");
|
|
24
|
+
wrap.appendChild(slot);
|
|
25
|
+
|
|
26
|
+
this.#wrap = wrap;
|
|
27
|
+
|
|
28
|
+
this.build(shadowRoot, stylesheet);
|
|
29
|
+
this.shadowRoot.appendChild(wrap);
|
|
30
|
+
|
|
31
|
+
const loadingSlot = createSlotElement("loading");
|
|
32
|
+
loadingSlot.style.display = "none";
|
|
33
|
+
this.shadowRoot.appendChild(loadingSlot);
|
|
34
|
+
|
|
35
|
+
const noMoreSlot = createSlotElement("noMore");
|
|
36
|
+
noMoreSlot.style.display = "none";
|
|
37
|
+
this.shadowRoot.appendChild(noMoreSlot);
|
|
38
|
+
|
|
39
|
+
this.#loadingSlot = loadingSlot;
|
|
40
|
+
this.#noMoreSlot = noMoreSlot;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ------- delay 节流时延, 单位为ms -------
|
|
44
|
+
// #region
|
|
45
|
+
get delay() {
|
|
46
|
+
return this.getAttrNumber('delay') || 200;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
set delay(value) {
|
|
50
|
+
this.setAttribute('delay', value);
|
|
51
|
+
}
|
|
52
|
+
// #endregion
|
|
53
|
+
// ------- end -------
|
|
54
|
+
|
|
55
|
+
// ------- loading 是否在加载时显示加载状态 -------
|
|
56
|
+
// #region
|
|
57
|
+
get loading() {
|
|
58
|
+
return this.getAttrBoolean('loading');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
set loading(value) {
|
|
62
|
+
if (value === undefined) return;
|
|
63
|
+
|
|
64
|
+
this.setAttribute('loading', value);
|
|
65
|
+
}
|
|
66
|
+
// #endregion
|
|
67
|
+
// ------- end -------
|
|
68
|
+
|
|
69
|
+
// ------- disabled 是否禁用 -------
|
|
70
|
+
// #region
|
|
71
|
+
get disabled() {
|
|
72
|
+
return this.getAttrBoolean('disabled') || false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
set disabled(value) {
|
|
76
|
+
this.setAttribute('disabled', value);
|
|
77
|
+
|
|
78
|
+
if (value) this.#noMoreSlot.style.display = 'block';
|
|
79
|
+
}
|
|
80
|
+
// #endregion
|
|
81
|
+
// ------- end -------
|
|
82
|
+
|
|
83
|
+
#getLastChild() {
|
|
84
|
+
const items = this.querySelectorAll('ea-infinite-item');
|
|
85
|
+
return items[items.length - 1];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#initBottomReachedObserver(delay) {
|
|
89
|
+
if (this.disabled) return;
|
|
90
|
+
|
|
91
|
+
let item = this.#getLastChild();
|
|
92
|
+
let timer = null;
|
|
93
|
+
|
|
94
|
+
const observer = new IntersectionObserver((entries) => {
|
|
95
|
+
const { isIntersecting } = entries[0];
|
|
96
|
+
if (this.disabled) {
|
|
97
|
+
observer.disconnect();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!isIntersecting || timer) return;
|
|
102
|
+
|
|
103
|
+
if (this.loading) this.#loadingSlot.style.display = 'block';
|
|
104
|
+
|
|
105
|
+
observer.unobserve(item);
|
|
106
|
+
|
|
107
|
+
timer = setTimeout(() => {
|
|
108
|
+
this.dispatchEvent(new CustomEvent('bottomReached'));
|
|
109
|
+
|
|
110
|
+
clearTimeout(timer);
|
|
111
|
+
timer = null;
|
|
112
|
+
|
|
113
|
+
item = this.#getLastChild();
|
|
114
|
+
observer.observe(item);
|
|
115
|
+
this.#loadingSlot.style.display = 'none';
|
|
116
|
+
|
|
117
|
+
}, delay || 200);
|
|
118
|
+
}, { root: this.parentNode, rootMargin: '10px', threshold: 0.1 });
|
|
119
|
+
|
|
120
|
+
// 初始观察
|
|
121
|
+
observer.observe(item);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
init() {
|
|
125
|
+
const that = this;
|
|
126
|
+
|
|
127
|
+
this.delay = this.delay;
|
|
128
|
+
|
|
129
|
+
this.#initBottomReachedObserver(this.delay);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
connectedCallback() {
|
|
133
|
+
this.init();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (!customElements.get('ea-infinite')) {
|
|
138
|
+
customElements.define('ea-infinite', EaInfiniteScroll);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export class EaInfiniteScrollItem extends Base {
|
|
142
|
+
#wrap;
|
|
143
|
+
constructor() {
|
|
144
|
+
super();
|
|
145
|
+
|
|
146
|
+
const shadowRoot = this.attachShadow({ mode: 'open' });
|
|
147
|
+
const wrap = document.createElement('div');
|
|
148
|
+
wrap.className = 'ea-infinite-item_wrap';
|
|
149
|
+
|
|
150
|
+
const slot = createSlotElement("");
|
|
151
|
+
wrap.appendChild(slot);
|
|
152
|
+
|
|
153
|
+
this.#wrap = wrap;
|
|
154
|
+
|
|
155
|
+
this.build(shadowRoot, stylesheet);
|
|
156
|
+
this.shadowRoot.appendChild(wrap);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
init() {
|
|
160
|
+
const that = this;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
connectedCallback() {
|
|
164
|
+
this.init();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (!customElements.get('ea-infinite-item')) {
|
|
169
|
+
customElements.define('ea-infinite-item', EaInfiniteScrollItem);
|
|
170
|
+
}
|