nv-refresh-btn-bw 1.0.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/nv-refresh-btn-bw.js +105 -0
- package/com.sh +1 -0
- package/index.d.ts +324 -0
- package/index.js +425 -0
- package/package.json +12 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
var nvrefreshbtnbw=(()=>{var b=(c,e)=>()=>(e||c((e={exports:{}}).exports,e),e.exports);var f=b((v,d)=>{var a=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this._width="40px",this._height="40px",this._color="#3498db",this._errorColor="#e74c3c",this._isRefreshing=!1,this._render()}static get observedAttributes(){return["width","height","color","error-color","disabled"]}attributeChangedCallback(e,t,r){if(t!==r)switch(e){case"width":this._width=r,this._updateStyles();break;case"height":this._height=r,this._updateStyles();break;case"color":this._color=r,this._updateStyles();break;case"error-color":this._errorColor=r,this._updateStyles();break;case"disabled":this._updateDisabledState();break}}connectedCallback(){this.shadowRoot.querySelector(".nv-refresh-btn").addEventListener("click",this._handleClick.bind(this))}disconnectedCallback(){this.shadowRoot.querySelector(".nv-refresh-btn").removeEventListener("click",this._handleClick)}_render(){let e=document.createElement("template");e.innerHTML=`
|
|
2
|
+
<style>
|
|
3
|
+
.nv-refresh-btn {
|
|
4
|
+
background: ${this._color};
|
|
5
|
+
border: none;
|
|
6
|
+
color: white;
|
|
7
|
+
cursor: pointer;
|
|
8
|
+
padding: 0;
|
|
9
|
+
position: relative;
|
|
10
|
+
display: inline-flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
transition: all 0.3s ease;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
width: ${this._width};
|
|
16
|
+
height: ${this._height};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* \u52A8\u6001\u8BA1\u7B97\u8FB9\u6846\u534A\u5F84 - \u76F8\u5BF9\u5C3A\u5BF8\u768410% */
|
|
20
|
+
.nv-refresh-btn {
|
|
21
|
+
border-radius: ${this._calculateRelativeSize("border-radius")};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.nv-refresh-btn::before {
|
|
25
|
+
content: "";
|
|
26
|
+
display: inline-block;
|
|
27
|
+
width: ${this._calculateIconSize()};
|
|
28
|
+
height: ${this._calculateIconSize()};
|
|
29
|
+
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>');
|
|
30
|
+
background-repeat: no-repeat;
|
|
31
|
+
background-position: center;
|
|
32
|
+
transition: transform 0.3s ease;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* \u60AC\u505C\u6548\u679C - \u76F8\u5BF9\u5C3A\u5BF8 */
|
|
36
|
+
.nv-refresh-btn:hover:not(.nv-refresh-btn-disabled):not(.nv-refresh-btn-refreshing) {
|
|
37
|
+
background: ${this._getDarkerColor(this._color)};
|
|
38
|
+
transform: translateY(${this._calculateRelativeSize("translateY")});
|
|
39
|
+
box-shadow: 0 ${this._calculateRelativeSize("shadow-offset")} ${this._calculateRelativeSize("shadow-blur")} rgba(0, 0, 0, 0.2);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.nv-refresh-btn:active:not(.nv-refresh-btn-disabled):not(.nv-refresh-btn-refreshing) {
|
|
43
|
+
transform: translateY(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.nv-refresh-btn.nv-refresh-btn-refreshing::before {
|
|
47
|
+
animation: nv-refresh-btn-spin ${this._calculateAnimationDuration()} linear infinite;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.nv-refresh-btn.nv-refresh-btn-disabled {
|
|
51
|
+
background: #bdc3c7;
|
|
52
|
+
cursor: not-allowed;
|
|
53
|
+
opacity: 0.6;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.nv-refresh-btn.error {
|
|
57
|
+
background: ${this._errorColor} !important;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@keyframes nv-refresh-btn-spin {
|
|
61
|
+
0% { transform: rotate(0deg); }
|
|
62
|
+
100% { transform: rotate(360deg); }
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
65
|
+
|
|
66
|
+
<button class="nv-refresh-btn" aria-label="\u5237\u65B0">
|
|
67
|
+
</button>
|
|
68
|
+
`,this.shadowRoot.appendChild(e.content.cloneNode(!0))}_calculateIconSize(){let e=this._parseSizeValue(this._width),t=this._parseSizeValue(this._height),r=Math.min(e,t);return`${Math.max(16,r*.6)}px`}_calculateRelativeSize(e){let t=this._parseSizeValue(this._width),r=this._parseSizeValue(this._height),s=Math.min(t,r);switch(e){case"border-radius":return`${Math.max(2,s*.1)}px`;case"translateY":return`-${Math.min(4,s*.05)}px`;case"shadow-offset":return`${Math.min(4,s*.05)}px`;case"shadow-blur":return`${Math.min(8,s*.1)}px`;default:return"4px"}}_calculateAnimationDuration(){let t=1+(Math.min(this._parseSizeValue(this._width),this._parseSizeValue(this._height))-40)*.01;return`${Math.max(.8,Math.min(1.2,t))}s`}_parseSizeValue(e){return e.endsWith("px")?parseInt(e,10):e.endsWith("rem")||e.endsWith("em")?parseFloat(e)*16:e.endsWith("%")?40:parseInt(e,10)||40}_updateStyles(){let e=this.shadowRoot.querySelector(".nv-refresh-btn");if(!e)return;e.style.width=this._width,e.style.height=this._height,e.style.borderRadius=this._calculateRelativeSize("border-radius");let t=this._calculateIconSize();e.style.setProperty("--nv-refresh-btn-icon-size",t),e.classList.contains("error")||(e.style.background=this._color);let r=this._calculateRelativeSize("translateY"),s=this._calculateRelativeSize("shadow-offset"),o=this._calculateRelativeSize("shadow-blur"),i=this._calculateAnimationDuration(),n=this.shadowRoot.querySelector("style");if(n){let h=this._getDarkerColor(this._color),l=this._errorColor,u=`
|
|
69
|
+
.nv-refresh-btn {
|
|
70
|
+
background: ${this._color};
|
|
71
|
+
width: ${this._width};
|
|
72
|
+
height: ${this._height};
|
|
73
|
+
border-radius: ${this._calculateRelativeSize("border-radius")};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.nv-refresh-btn::before {
|
|
77
|
+
width: ${this._calculateIconSize()};
|
|
78
|
+
height: ${this._calculateIconSize()};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.nv-refresh-btn:hover:not(.nv-refresh-btn-disabled):not(.nv-refresh-btn-refreshing) {
|
|
82
|
+
background: ${h};
|
|
83
|
+
transform: translateY(${r});
|
|
84
|
+
box-shadow: 0 ${s} ${o} rgba(0, 0, 0, 0.2);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.nv-refresh-btn.nv-refresh-btn-refreshing::before {
|
|
88
|
+
animation: nv-refresh-btn-spin ${i} linear infinite;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.nv-refresh-btn.nv-refresh-btn-disabled {
|
|
92
|
+
background: #bdc3c7;
|
|
93
|
+
cursor: not-allowed;
|
|
94
|
+
opacity: 0.6;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.nv-refresh-btn.error {
|
|
98
|
+
background: ${l} !important;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@keyframes nv-refresh-btn-spin {
|
|
102
|
+
0% { transform: rotate(0deg); }
|
|
103
|
+
100% { transform: rotate(360deg); }
|
|
104
|
+
}
|
|
105
|
+
`;n.textContent=u}}_getDarkerColor(e){let t=e.replace("#","");if(t.length!==6)return e;let r=parseInt(t.substr(0,2),16),s=parseInt(t.substr(2,2),16),o=parseInt(t.substr(4,2),16),i=.8,n=Math.floor(r*i),h=Math.floor(s*i),l=Math.floor(o*i);return`rgb(${n}, ${h}, ${l})`}_updateDisabledState(){let e=this.shadowRoot.querySelector(".nv-refresh-btn");e&&(this.hasAttribute("disabled")?(e.classList.add("nv-refresh-btn-disabled"),e.setAttribute("disabled","")):(e.classList.remove("nv-refresh-btn-disabled"),e.removeAttribute("disabled")))}_handleClick(){if(this.hasAttribute("disabled")||this._isRefreshing)return;let e=this.shadowRoot.querySelector(".nv-refresh-btn");if(!e)return;e.classList.remove("error"),e.style.background=this._color,this._isRefreshing=!0;let t=new CustomEvent("nv-refresh-btn-start",{bubbles:!0,composed:!0,detail:{timestamp:Date.now()}});this.dispatchEvent(t),e.classList.add("nv-refresh-btn-refreshing")}finish(e=!0){let t=this.shadowRoot.querySelector(".nv-refresh-btn");if(t)if(t.classList.remove("nv-refresh-btn-refreshing"),this._isRefreshing=!1,e){t.classList.remove("error"),t.style.background=this._color;let r=new CustomEvent("nv-refresh-btn-complete",{bubbles:!0,composed:!0,detail:{timestamp:Date.now(),success:!0}});this.dispatchEvent(r)}else{t.classList.add("error"),t.style.background=this._errorColor;let r=new CustomEvent("nv-refresh-btn-error",{bubbles:!0,composed:!0,detail:{timestamp:Date.now(),success:!1}});this.dispatchEvent(r)}}refresh(){this._handleClick()}setColor(e){this._color=e,this._updateStyles()}setErrorColor(e){this._errorColor=e,this._updateStyles()}setSize(e,t){this._width=e,this._height=t,this._updateStyles()}getState(){return{isRefreshing:this._isRefreshing,width:this._width,height:this._height,color:this._color,errorColor:this._errorColor,disabled:this.hasAttribute("disabled")}}getComputedStyles(){return{iconSize:this._calculateIconSize(),borderRadius:this._calculateRelativeSize("border-radius"),hoverTranslateY:this._calculateRelativeSize("translateY"),shadowOffset:this._calculateRelativeSize("shadow-offset"),shadowBlur:this._calculateRelativeSize("shadow-blur"),animationDuration:this._calculateAnimationDuration()}}};customElements.get("nv-refresh-btn")||customElements.define("nv-refresh-btn",a);d.exports={NvRefreshBtn:a}});return f();})();
|
package/com.sh
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nv_cli_build -m -g nvrefreshbtnbw -i index.js -o ./DIST/nv-refresh-btn-bw.js
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 自定义刷新按钮元素的 TypeScript 类型声明
|
|
3
|
+
* 对应自定义元素: <nv-refresh-btn>
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 刷新按钮自定义元素接口
|
|
8
|
+
*/
|
|
9
|
+
interface NvRefreshBtnElement extends HTMLElement {
|
|
10
|
+
/**
|
|
11
|
+
* 按钮宽度
|
|
12
|
+
* @example "40px"
|
|
13
|
+
* @example "3rem"
|
|
14
|
+
* @example "100%"
|
|
15
|
+
*/
|
|
16
|
+
width: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 按钮高度
|
|
20
|
+
* @example "40px"
|
|
21
|
+
* @example "3rem"
|
|
22
|
+
* @example "100%"
|
|
23
|
+
*/
|
|
24
|
+
height: string;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 按钮背景颜色
|
|
28
|
+
* @example "#3498db"
|
|
29
|
+
* @example "rgb(52, 152, 219)"
|
|
30
|
+
*/
|
|
31
|
+
color: string;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 错误状态时的背景颜色
|
|
35
|
+
* @example "#e74c3c"
|
|
36
|
+
* @example "rgb(231, 76, 60)"
|
|
37
|
+
*/
|
|
38
|
+
errorColor: string;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 是否禁用按钮
|
|
42
|
+
*/
|
|
43
|
+
disabled: boolean;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 手动触发刷新动画
|
|
47
|
+
* @returns void
|
|
48
|
+
*/
|
|
49
|
+
refresh(): void;
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 完成刷新操作
|
|
53
|
+
* @param success 刷新是否成功,默认为 true
|
|
54
|
+
* @returns void
|
|
55
|
+
*/
|
|
56
|
+
finish(success?: boolean): void;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 设置按钮颜色
|
|
60
|
+
* @param color 新的颜色值
|
|
61
|
+
* @returns void
|
|
62
|
+
*/
|
|
63
|
+
setColor(color: string): void;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 设置错误颜色
|
|
67
|
+
* @param color 新的错误颜色值
|
|
68
|
+
* @returns void
|
|
69
|
+
*/
|
|
70
|
+
setErrorColor(color: string): void;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 设置按钮尺寸
|
|
74
|
+
* @param width 新的宽度
|
|
75
|
+
* @param height 新的高度
|
|
76
|
+
* @returns void
|
|
77
|
+
*/
|
|
78
|
+
setSize(width: string, height: string): void;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* 获取按钮当前状态
|
|
82
|
+
* @returns 包含按钮状态的对象
|
|
83
|
+
*/
|
|
84
|
+
getState(): NvRefreshBtnState;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 获取计算后的样式值
|
|
88
|
+
* @returns 包含计算后样式值的对象
|
|
89
|
+
*/
|
|
90
|
+
getComputedStyles(): NvRefreshBtnComputedStyles;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 刷新开始事件监听器
|
|
94
|
+
* @param type 事件类型: "nv-refresh-btn-start"
|
|
95
|
+
* @param listener 事件监听函数
|
|
96
|
+
* @param options 事件监听选项
|
|
97
|
+
*/
|
|
98
|
+
addEventListener(
|
|
99
|
+
type: "nv-refresh-btn-start",
|
|
100
|
+
listener: (this: NvRefreshBtnElement, ev: NvRefreshBtnStartEvent) => any,
|
|
101
|
+
options?: boolean | AddEventListenerOptions
|
|
102
|
+
): void;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 刷新完成事件监听器
|
|
106
|
+
* @param type 事件类型: "nv-refresh-btn-complete"
|
|
107
|
+
* @param listener 事件监听函数
|
|
108
|
+
* @param options 事件监听选项
|
|
109
|
+
*/
|
|
110
|
+
addEventListener(
|
|
111
|
+
type: "nv-refresh-btn-complete",
|
|
112
|
+
listener: (this: NvRefreshBtnElement, ev: NvRefreshBtnCompleteEvent) => any,
|
|
113
|
+
options?: boolean | AddEventListenerOptions
|
|
114
|
+
): void;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 刷新错误事件监听器
|
|
118
|
+
* @param type 事件类型: "nv-refresh-btn-error"
|
|
119
|
+
* @param listener 事件监听函数
|
|
120
|
+
* @param options 事件监听选项
|
|
121
|
+
*/
|
|
122
|
+
addEventListener(
|
|
123
|
+
type: "nv-refresh-btn-error",
|
|
124
|
+
listener: (this: NvRefreshBtnElement, ev: NvRefreshBtnErrorEvent) => any,
|
|
125
|
+
options?: boolean | AddEventListenerOptions
|
|
126
|
+
): void;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 通用事件监听器
|
|
130
|
+
*/
|
|
131
|
+
addEventListener(
|
|
132
|
+
type: string,
|
|
133
|
+
listener: EventListenerOrEventListenerObject,
|
|
134
|
+
options?: boolean | AddEventListenerOptions
|
|
135
|
+
): void;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 刷新按钮状态接口
|
|
140
|
+
*/
|
|
141
|
+
interface NvRefreshBtnState {
|
|
142
|
+
/** 是否正在刷新 */
|
|
143
|
+
isRefreshing: boolean;
|
|
144
|
+
/** 按钮宽度 */
|
|
145
|
+
width: string;
|
|
146
|
+
/** 按钮高度 */
|
|
147
|
+
height: string;
|
|
148
|
+
/** 按钮颜色 */
|
|
149
|
+
color: string;
|
|
150
|
+
/** 错误颜色 */
|
|
151
|
+
errorColor: string;
|
|
152
|
+
/** 是否禁用 */
|
|
153
|
+
disabled: boolean;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* 刷新按钮计算样式接口
|
|
158
|
+
*/
|
|
159
|
+
interface NvRefreshBtnComputedStyles {
|
|
160
|
+
/** 图标尺寸 */
|
|
161
|
+
iconSize: string;
|
|
162
|
+
/** 边框半径 */
|
|
163
|
+
borderRadius: string;
|
|
164
|
+
/** 悬停上移距离 */
|
|
165
|
+
hoverTranslateY: string;
|
|
166
|
+
/** 阴影偏移 */
|
|
167
|
+
shadowOffset: string;
|
|
168
|
+
/** 阴影模糊 */
|
|
169
|
+
shadowBlur: string;
|
|
170
|
+
/** 动画持续时间 */
|
|
171
|
+
animationDuration: string;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 刷新按钮事件详情接口
|
|
176
|
+
*/
|
|
177
|
+
interface NvRefreshBtnEventDetail {
|
|
178
|
+
/** 事件时间戳 */
|
|
179
|
+
timestamp: number;
|
|
180
|
+
/** 是否成功(仅完成/错误事件有) */
|
|
181
|
+
success?: boolean;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 刷新开始事件
|
|
186
|
+
*/
|
|
187
|
+
interface NvRefreshBtnStartEvent extends CustomEvent<NvRefreshBtnEventDetail> {
|
|
188
|
+
/** 事件目标 */
|
|
189
|
+
readonly target: NvRefreshBtnElement;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 刷新完成事件
|
|
194
|
+
*/
|
|
195
|
+
interface NvRefreshBtnCompleteEvent extends CustomEvent<NvRefreshBtnEventDetail> {
|
|
196
|
+
/** 事件目标 */
|
|
197
|
+
readonly target: NvRefreshBtnElement;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* 刷新错误事件
|
|
202
|
+
*/
|
|
203
|
+
interface NvRefreshBtnErrorEvent extends CustomEvent<NvRefreshBtnEventDetail> {
|
|
204
|
+
/** 事件目标 */
|
|
205
|
+
readonly target: NvRefreshBtnElement;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 刷新按钮类定义
|
|
210
|
+
*/
|
|
211
|
+
declare class NvRefreshBtn extends HTMLElement implements NvRefreshBtnElement {
|
|
212
|
+
/** 监听属性变化 */
|
|
213
|
+
static get observedAttributes(): string[];
|
|
214
|
+
|
|
215
|
+
/** 按钮宽度 */
|
|
216
|
+
width: string;
|
|
217
|
+
|
|
218
|
+
/** 按钮高度 */
|
|
219
|
+
height: string;
|
|
220
|
+
|
|
221
|
+
/** 按钮颜色 */
|
|
222
|
+
color: string;
|
|
223
|
+
|
|
224
|
+
/** 错误颜色 */
|
|
225
|
+
errorColor: string;
|
|
226
|
+
|
|
227
|
+
/** 是否禁用 */
|
|
228
|
+
disabled: boolean;
|
|
229
|
+
|
|
230
|
+
/** 手动触发刷新动画 */
|
|
231
|
+
refresh(): void;
|
|
232
|
+
|
|
233
|
+
/** 完成刷新操作 */
|
|
234
|
+
finish(success?: boolean): void;
|
|
235
|
+
|
|
236
|
+
/** 设置按钮颜色 */
|
|
237
|
+
setColor(color: string): void;
|
|
238
|
+
|
|
239
|
+
/** 设置错误颜色 */
|
|
240
|
+
setErrorColor(color: string): void;
|
|
241
|
+
|
|
242
|
+
/** 设置按钮尺寸 */
|
|
243
|
+
setSize(width: string, height: string): void;
|
|
244
|
+
|
|
245
|
+
/** 获取按钮当前状态 */
|
|
246
|
+
getState(): NvRefreshBtnState;
|
|
247
|
+
|
|
248
|
+
/** 获取计算后的样式值 */
|
|
249
|
+
getComputedStyles(): NvRefreshBtnComputedStyles;
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* 属性变化回调
|
|
253
|
+
* @param name 属性名
|
|
254
|
+
* @param oldValue 旧值
|
|
255
|
+
* @param newValue 新值
|
|
256
|
+
*/
|
|
257
|
+
attributeChangedCallback(name: string, oldValue: string, newValue: string): void;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* 元素连接到DOM时的回调
|
|
261
|
+
*/
|
|
262
|
+
connectedCallback(): void;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* 元素从DOM断开时的回调
|
|
266
|
+
*/
|
|
267
|
+
disconnectedCallback(): void;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* 全局类型扩展
|
|
272
|
+
*/
|
|
273
|
+
declare global {
|
|
274
|
+
/**
|
|
275
|
+
* 扩展 HTMLElementTagNameMap 以支持自定义元素
|
|
276
|
+
*/
|
|
277
|
+
interface HTMLElementTagNameMap {
|
|
278
|
+
"nv-refresh-btn": NvRefreshBtnElement;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* 扩展 Window 对象,包含自定义元素
|
|
283
|
+
*/
|
|
284
|
+
interface Window {
|
|
285
|
+
/**
|
|
286
|
+
* 刷新按钮自定义元素类
|
|
287
|
+
*/
|
|
288
|
+
NvRefreshBtn: typeof NvRefreshBtn;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* 扩展 Document 对象的事件类型
|
|
293
|
+
*/
|
|
294
|
+
interface Document {
|
|
295
|
+
addEventListener(
|
|
296
|
+
type: "nv-refresh-btn-start",
|
|
297
|
+
listener: (this: Document, ev: NvRefreshBtnStartEvent) => any,
|
|
298
|
+
options?: boolean | AddEventListenerOptions
|
|
299
|
+
): void;
|
|
300
|
+
|
|
301
|
+
addEventListener(
|
|
302
|
+
type: "nv-refresh-btn-complete",
|
|
303
|
+
listener: (this: Document, ev: NvRefreshBtnCompleteEvent) => any,
|
|
304
|
+
options?: boolean | AddEventListenerOptions
|
|
305
|
+
): void;
|
|
306
|
+
|
|
307
|
+
addEventListener(
|
|
308
|
+
type: "nv-refresh-btn-error",
|
|
309
|
+
listener: (this: Document, ev: NvRefreshBtnErrorEvent) => any,
|
|
310
|
+
options?: boolean | AddEventListenerOptions
|
|
311
|
+
): void;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* 导出刷新按钮类
|
|
317
|
+
*/
|
|
318
|
+
export { NvRefreshBtn };
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* 默认导出刷新按钮类型
|
|
322
|
+
*/
|
|
323
|
+
export default NvRefreshBtn;
|
|
324
|
+
|
package/index.js
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
class NvRefreshBtn extends HTMLElement {
|
|
2
|
+
constructor() {
|
|
3
|
+
super();
|
|
4
|
+
|
|
5
|
+
// 创建Shadow DOM
|
|
6
|
+
this.attachShadow({ mode: 'open' });
|
|
7
|
+
|
|
8
|
+
// 默认属性
|
|
9
|
+
this._width = '40px'; // 默认宽度
|
|
10
|
+
this._height = '40px'; // 默认高度
|
|
11
|
+
this._color = '#3498db'; // 默认颜色
|
|
12
|
+
this._errorColor = '#e74c3c'; // 默认错误颜色
|
|
13
|
+
this._isRefreshing = false; // 是否正在刷新
|
|
14
|
+
|
|
15
|
+
// 初始化渲染
|
|
16
|
+
this._render();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 监听属性变化
|
|
20
|
+
static get observedAttributes() {
|
|
21
|
+
return ['width', 'height', 'color', 'error-color', 'disabled'];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 属性变化回调
|
|
25
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
26
|
+
if (oldValue === newValue) return;
|
|
27
|
+
|
|
28
|
+
switch(name) {
|
|
29
|
+
case 'width':
|
|
30
|
+
this._width = newValue;
|
|
31
|
+
this._updateStyles();
|
|
32
|
+
break;
|
|
33
|
+
case 'height':
|
|
34
|
+
this._height = newValue;
|
|
35
|
+
this._updateStyles();
|
|
36
|
+
break;
|
|
37
|
+
case 'color':
|
|
38
|
+
this._color = newValue;
|
|
39
|
+
this._updateStyles();
|
|
40
|
+
break;
|
|
41
|
+
case 'error-color':
|
|
42
|
+
this._errorColor = newValue;
|
|
43
|
+
this._updateStyles();
|
|
44
|
+
break;
|
|
45
|
+
case 'disabled':
|
|
46
|
+
this._updateDisabledState();
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 连接回调
|
|
52
|
+
connectedCallback() {
|
|
53
|
+
// 绑定点击事件
|
|
54
|
+
this.shadowRoot.querySelector('.nv-refresh-btn').addEventListener('click', this._handleClick.bind(this));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 断开连接回调
|
|
58
|
+
disconnectedCallback() {
|
|
59
|
+
// 清理事件监听器
|
|
60
|
+
this.shadowRoot.querySelector('.nv-refresh-btn').removeEventListener('click', this._handleClick);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 渲染方法
|
|
64
|
+
_render() {
|
|
65
|
+
const template = document.createElement('template');
|
|
66
|
+
template.innerHTML = `
|
|
67
|
+
<style>
|
|
68
|
+
.nv-refresh-btn {
|
|
69
|
+
background: ${this._color};
|
|
70
|
+
border: none;
|
|
71
|
+
color: white;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
padding: 0;
|
|
74
|
+
position: relative;
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
transition: all 0.3s ease;
|
|
79
|
+
box-sizing: border-box;
|
|
80
|
+
width: ${this._width};
|
|
81
|
+
height: ${this._height};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* 动态计算边框半径 - 相对尺寸的10% */
|
|
85
|
+
.nv-refresh-btn {
|
|
86
|
+
border-radius: ${this._calculateRelativeSize('border-radius')};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.nv-refresh-btn::before {
|
|
90
|
+
content: "";
|
|
91
|
+
display: inline-block;
|
|
92
|
+
width: ${this._calculateIconSize()};
|
|
93
|
+
height: ${this._calculateIconSize()};
|
|
94
|
+
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>');
|
|
95
|
+
background-repeat: no-repeat;
|
|
96
|
+
background-position: center;
|
|
97
|
+
transition: transform 0.3s ease;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* 悬停效果 - 相对尺寸 */
|
|
101
|
+
.nv-refresh-btn:hover:not(.nv-refresh-btn-disabled):not(.nv-refresh-btn-refreshing) {
|
|
102
|
+
background: ${this._getDarkerColor(this._color)};
|
|
103
|
+
transform: translateY(${this._calculateRelativeSize('translateY')});
|
|
104
|
+
box-shadow: 0 ${this._calculateRelativeSize('shadow-offset')} ${this._calculateRelativeSize('shadow-blur')} rgba(0, 0, 0, 0.2);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.nv-refresh-btn:active:not(.nv-refresh-btn-disabled):not(.nv-refresh-btn-refreshing) {
|
|
108
|
+
transform: translateY(0);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.nv-refresh-btn.nv-refresh-btn-refreshing::before {
|
|
112
|
+
animation: nv-refresh-btn-spin ${this._calculateAnimationDuration()} linear infinite;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.nv-refresh-btn.nv-refresh-btn-disabled {
|
|
116
|
+
background: #bdc3c7;
|
|
117
|
+
cursor: not-allowed;
|
|
118
|
+
opacity: 0.6;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.nv-refresh-btn.error {
|
|
122
|
+
background: ${this._errorColor} !important;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@keyframes nv-refresh-btn-spin {
|
|
126
|
+
0% { transform: rotate(0deg); }
|
|
127
|
+
100% { transform: rotate(360deg); }
|
|
128
|
+
}
|
|
129
|
+
</style>
|
|
130
|
+
|
|
131
|
+
<button class="nv-refresh-btn" aria-label="刷新">
|
|
132
|
+
</button>
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 计算图标尺寸 - 相对最小尺寸的60%
|
|
139
|
+
_calculateIconSize() {
|
|
140
|
+
const widthValue = this._parseSizeValue(this._width);
|
|
141
|
+
const heightValue = this._parseSizeValue(this._height);
|
|
142
|
+
const minSize = Math.min(widthValue, heightValue);
|
|
143
|
+
const iconSize = Math.max(16, minSize * 0.6); // 最小16px
|
|
144
|
+
return `${iconSize}px`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 计算相对尺寸
|
|
148
|
+
_calculateRelativeSize(type) {
|
|
149
|
+
const widthValue = this._parseSizeValue(this._width);
|
|
150
|
+
const heightValue = this._parseSizeValue(this._height);
|
|
151
|
+
const minSize = Math.min(widthValue, heightValue);
|
|
152
|
+
|
|
153
|
+
switch(type) {
|
|
154
|
+
case 'border-radius':
|
|
155
|
+
// 边框半径 = 最小尺寸的10%,最小2px
|
|
156
|
+
return `${Math.max(2, minSize * 0.1)}px`;
|
|
157
|
+
case 'translateY':
|
|
158
|
+
// 悬停上移距离 = 最小尺寸的5%,最大4px
|
|
159
|
+
return `-${Math.min(4, minSize * 0.05)}px`;
|
|
160
|
+
case 'shadow-offset':
|
|
161
|
+
// 阴影偏移 = 最小尺寸的5%,最大4px
|
|
162
|
+
return `${Math.min(4, minSize * 0.05)}px`;
|
|
163
|
+
case 'shadow-blur':
|
|
164
|
+
// 阴影模糊 = 最小尺寸的10%,最大8px
|
|
165
|
+
return `${Math.min(8, minSize * 0.1)}px`;
|
|
166
|
+
default:
|
|
167
|
+
return '4px';
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 计算动画持续时间 - 相对尺寸
|
|
172
|
+
_calculateAnimationDuration() {
|
|
173
|
+
const minSize = Math.min(
|
|
174
|
+
this._parseSizeValue(this._width),
|
|
175
|
+
this._parseSizeValue(this._height)
|
|
176
|
+
);
|
|
177
|
+
// 基础1秒,小尺寸按钮动画稍快,大尺寸按钮动画稍慢
|
|
178
|
+
const duration = 1 + (minSize - 40) * 0.01; // 40px基准1秒
|
|
179
|
+
return `${Math.max(0.8, Math.min(1.2, duration))}s`; // 限制在0.8-1.2秒之间
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 解析尺寸值
|
|
183
|
+
_parseSizeValue(value) {
|
|
184
|
+
if (value.endsWith('px')) {
|
|
185
|
+
return parseInt(value, 10);
|
|
186
|
+
} else if (value.endsWith('rem')) {
|
|
187
|
+
return parseFloat(value) * 16; // 假设1rem = 16px
|
|
188
|
+
} else if (value.endsWith('em')) {
|
|
189
|
+
return parseFloat(value) * 16; // 假设1em = 16px
|
|
190
|
+
} else if (value.endsWith('%')) {
|
|
191
|
+
return 40; // 对于百分比,返回一个基准值
|
|
192
|
+
} else {
|
|
193
|
+
return parseInt(value, 10) || 40; // 默认40px
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// 更新样式
|
|
198
|
+
_updateStyles() {
|
|
199
|
+
const button = this.shadowRoot.querySelector('.nv-refresh-btn');
|
|
200
|
+
if (!button) return;
|
|
201
|
+
|
|
202
|
+
// 更新尺寸
|
|
203
|
+
button.style.width = this._width;
|
|
204
|
+
button.style.height = this._height;
|
|
205
|
+
|
|
206
|
+
// 更新边框半径
|
|
207
|
+
button.style.borderRadius = this._calculateRelativeSize('border-radius');
|
|
208
|
+
|
|
209
|
+
// 更新图标尺寸
|
|
210
|
+
const iconSize = this._calculateIconSize();
|
|
211
|
+
button.style.setProperty('--nv-refresh-btn-icon-size', iconSize);
|
|
212
|
+
|
|
213
|
+
// 如果不是错误状态,更新背景颜色
|
|
214
|
+
if (!button.classList.contains('error')) {
|
|
215
|
+
button.style.background = this._color;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 更新悬停效果
|
|
219
|
+
const hoverTranslateY = this._calculateRelativeSize('translateY');
|
|
220
|
+
const shadowOffset = this._calculateRelativeSize('shadow-offset');
|
|
221
|
+
const shadowBlur = this._calculateRelativeSize('shadow-blur');
|
|
222
|
+
|
|
223
|
+
// 更新动画持续时间
|
|
224
|
+
const animationDuration = this._calculateAnimationDuration();
|
|
225
|
+
|
|
226
|
+
// 更新样式元素
|
|
227
|
+
const styleElement = this.shadowRoot.querySelector('style');
|
|
228
|
+
if (styleElement) {
|
|
229
|
+
const hoverColor = this._getDarkerColor(this._color);
|
|
230
|
+
const errorColor = this._errorColor;
|
|
231
|
+
|
|
232
|
+
// 构建新的样式
|
|
233
|
+
const newStyle = `
|
|
234
|
+
.nv-refresh-btn {
|
|
235
|
+
background: ${this._color};
|
|
236
|
+
width: ${this._width};
|
|
237
|
+
height: ${this._height};
|
|
238
|
+
border-radius: ${this._calculateRelativeSize('border-radius')};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.nv-refresh-btn::before {
|
|
242
|
+
width: ${this._calculateIconSize()};
|
|
243
|
+
height: ${this._calculateIconSize()};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.nv-refresh-btn:hover:not(.nv-refresh-btn-disabled):not(.nv-refresh-btn-refreshing) {
|
|
247
|
+
background: ${hoverColor};
|
|
248
|
+
transform: translateY(${hoverTranslateY});
|
|
249
|
+
box-shadow: 0 ${shadowOffset} ${shadowBlur} rgba(0, 0, 0, 0.2);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.nv-refresh-btn.nv-refresh-btn-refreshing::before {
|
|
253
|
+
animation: nv-refresh-btn-spin ${animationDuration} linear infinite;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.nv-refresh-btn.nv-refresh-btn-disabled {
|
|
257
|
+
background: #bdc3c7;
|
|
258
|
+
cursor: not-allowed;
|
|
259
|
+
opacity: 0.6;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.nv-refresh-btn.error {
|
|
263
|
+
background: ${errorColor} !important;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@keyframes nv-refresh-btn-spin {
|
|
267
|
+
0% { transform: rotate(0deg); }
|
|
268
|
+
100% { transform: rotate(360deg); }
|
|
269
|
+
}
|
|
270
|
+
`;
|
|
271
|
+
|
|
272
|
+
styleElement.textContent = newStyle;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// 获取更深色
|
|
277
|
+
_getDarkerColor(color) {
|
|
278
|
+
// 简单实现:将颜色变暗20%
|
|
279
|
+
const hex = color.replace('#', '');
|
|
280
|
+
if (hex.length !== 6) return color; // 如果不是6位十六进制颜色,直接返回
|
|
281
|
+
|
|
282
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
283
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
284
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
285
|
+
|
|
286
|
+
const darken = 0.8; // 变暗20%
|
|
287
|
+
const newR = Math.floor(r * darken);
|
|
288
|
+
const newG = Math.floor(g * darken);
|
|
289
|
+
const newB = Math.floor(b * darken);
|
|
290
|
+
|
|
291
|
+
return `rgb(${newR}, ${newG}, ${newB})`;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 更新禁用状态
|
|
295
|
+
_updateDisabledState() {
|
|
296
|
+
const button = this.shadowRoot.querySelector('.nv-refresh-btn');
|
|
297
|
+
if (!button) return;
|
|
298
|
+
|
|
299
|
+
if (this.hasAttribute('disabled')) {
|
|
300
|
+
button.classList.add('nv-refresh-btn-disabled');
|
|
301
|
+
button.setAttribute('disabled', '');
|
|
302
|
+
} else {
|
|
303
|
+
button.classList.remove('nv-refresh-btn-disabled');
|
|
304
|
+
button.removeAttribute('disabled');
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// 点击处理
|
|
309
|
+
_handleClick() {
|
|
310
|
+
if (this.hasAttribute('disabled') || this._isRefreshing) return;
|
|
311
|
+
|
|
312
|
+
const button = this.shadowRoot.querySelector('.nv-refresh-btn');
|
|
313
|
+
if (!button) return;
|
|
314
|
+
|
|
315
|
+
// 移除可能的错误状态
|
|
316
|
+
button.classList.remove('error');
|
|
317
|
+
button.style.background = this._color;
|
|
318
|
+
this._isRefreshing = true;
|
|
319
|
+
|
|
320
|
+
// 触发自定义事件
|
|
321
|
+
const startEvent = new CustomEvent('nv-refresh-btn-start', {
|
|
322
|
+
bubbles: true,
|
|
323
|
+
composed: true,
|
|
324
|
+
detail: { timestamp: Date.now() }
|
|
325
|
+
});
|
|
326
|
+
this.dispatchEvent(startEvent);
|
|
327
|
+
|
|
328
|
+
// 添加旋转动画
|
|
329
|
+
button.classList.add('nv-refresh-btn-refreshing');
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// 公共方法:完成刷新
|
|
333
|
+
finish(success = true) {
|
|
334
|
+
const button = this.shadowRoot.querySelector('.nv-refresh-btn');
|
|
335
|
+
if (!button) return;
|
|
336
|
+
|
|
337
|
+
// 停止动画
|
|
338
|
+
button.classList.remove('nv-refresh-btn-refreshing');
|
|
339
|
+
this._isRefreshing = false;
|
|
340
|
+
|
|
341
|
+
if (success) {
|
|
342
|
+
// 成功:恢复到原始颜色
|
|
343
|
+
button.classList.remove('error');
|
|
344
|
+
button.style.background = this._color;
|
|
345
|
+
|
|
346
|
+
// 触发成功事件
|
|
347
|
+
const completeEvent = new CustomEvent('nv-refresh-btn-complete', {
|
|
348
|
+
bubbles: true,
|
|
349
|
+
composed: true,
|
|
350
|
+
detail: { timestamp: Date.now(), success: true }
|
|
351
|
+
});
|
|
352
|
+
this.dispatchEvent(completeEvent);
|
|
353
|
+
} else {
|
|
354
|
+
// 失败:改变背景颜色
|
|
355
|
+
button.classList.add('error');
|
|
356
|
+
button.style.background = this._errorColor;
|
|
357
|
+
|
|
358
|
+
// 触发失败事件
|
|
359
|
+
const errorEvent = new CustomEvent('nv-refresh-btn-error', {
|
|
360
|
+
bubbles: true,
|
|
361
|
+
composed: true,
|
|
362
|
+
detail: { timestamp: Date.now(), success: false }
|
|
363
|
+
});
|
|
364
|
+
this.dispatchEvent(errorEvent);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 公共方法:手动触发刷新
|
|
369
|
+
refresh() {
|
|
370
|
+
this._handleClick();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// 公共方法:设置颜色
|
|
374
|
+
setColor(color) {
|
|
375
|
+
this._color = color;
|
|
376
|
+
this._updateStyles();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// 公共方法:设置错误颜色
|
|
380
|
+
setErrorColor(color) {
|
|
381
|
+
this._errorColor = color;
|
|
382
|
+
this._updateStyles();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// 公共方法:设置尺寸
|
|
386
|
+
setSize(width, height) {
|
|
387
|
+
this._width = width;
|
|
388
|
+
this._height = height;
|
|
389
|
+
this._updateStyles();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// 公共方法:获取当前状态
|
|
393
|
+
getState() {
|
|
394
|
+
return {
|
|
395
|
+
isRefreshing: this._isRefreshing,
|
|
396
|
+
width: this._width,
|
|
397
|
+
height: this._height,
|
|
398
|
+
color: this._color,
|
|
399
|
+
errorColor: this._errorColor,
|
|
400
|
+
disabled: this.hasAttribute('disabled')
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// 公共方法:获取计算后的样式值
|
|
405
|
+
getComputedStyles() {
|
|
406
|
+
return {
|
|
407
|
+
iconSize: this._calculateIconSize(),
|
|
408
|
+
borderRadius: this._calculateRelativeSize('border-radius'),
|
|
409
|
+
hoverTranslateY: this._calculateRelativeSize('translateY'),
|
|
410
|
+
shadowOffset: this._calculateRelativeSize('shadow-offset'),
|
|
411
|
+
shadowBlur: this._calculateRelativeSize('shadow-blur'),
|
|
412
|
+
animationDuration: this._calculateAnimationDuration()
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// 注册自定义元素
|
|
418
|
+
if (!customElements.get('nv-refresh-btn')) {
|
|
419
|
+
customElements.define('nv-refresh-btn', NvRefreshBtn);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
module.exports = {
|
|
424
|
+
NvRefreshBtn
|
|
425
|
+
}
|
package/package.json
ADDED