@sun-panel/micro-app 1.0.6 → 1.0.7
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/README.md +1 -277
- package/dist/SunPanelPageElement.d.ts +1 -2
- package/dist/SunPanelPageElement.d.ts.map +1 -1
- package/dist/index.bundle.js +1 -1
- package/dist/index.bundle.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/api.d.ts +57 -92
- package/dist/types/common.d.ts +5 -0
- package/package.json +1 -1
- package/src/types/api.d.ts +57 -92
- package/src/types/common.d.ts +5 -0
package/README.md
CHANGED
|
@@ -7,7 +7,6 @@ Sun Panel 微应用组件 - 基于 LitElement 的微应用开发框架,提供
|
|
|
7
7
|
`@sun-panel/micro-app` 是一个用于开发 Sun Panel 微应用的 JavaScript 组件库,提供了:
|
|
8
8
|
|
|
9
9
|
- 基于原生 Web Components 的基础组件类
|
|
10
|
-
- 内置的事件绑定和验证功能
|
|
11
10
|
- TypeScript 类型定义支持
|
|
12
11
|
- 预设的卡片和页面组件基类
|
|
13
12
|
- 与 Lit 框架兼容的开发体验
|
|
@@ -20,279 +19,4 @@ npm install @sun-panel/micro-app
|
|
|
20
19
|
|
|
21
20
|
## 快速开始
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```javascript
|
|
26
|
-
import { SunPanelCardElement } from '@sun-panel/micro-app';
|
|
27
|
-
|
|
28
|
-
class MyCard extends SunPanelCardElement {
|
|
29
|
-
constructor() {
|
|
30
|
-
super();
|
|
31
|
-
this.title = 'My Card';
|
|
32
|
-
this.count = 0;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
render() {
|
|
36
|
-
return `
|
|
37
|
-
<style>
|
|
38
|
-
:host {
|
|
39
|
-
display: block;
|
|
40
|
-
padding: 16px;
|
|
41
|
-
border: 1px solid #ccc;
|
|
42
|
-
}
|
|
43
|
-
</style>
|
|
44
|
-
<h3>${this.title}</h3>
|
|
45
|
-
<p>Count: ${this.count}</p>
|
|
46
|
-
<button onclick="this.increment()">Increment</button>
|
|
47
|
-
`;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
increment() {
|
|
51
|
-
this.count++;
|
|
52
|
-
this.update();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 定义自定义元素
|
|
57
|
-
customElements.define('my-card', MyCard);
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### 创建页面组件
|
|
61
|
-
|
|
62
|
-
```javascript
|
|
63
|
-
import { SunPanelPageElement } from '@sun-panel/micro-app';
|
|
64
|
-
|
|
65
|
-
class MyPage extends SunPanelPageElement {
|
|
66
|
-
constructor() {
|
|
67
|
-
super();
|
|
68
|
-
this.message = 'Hello World';
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
render() {
|
|
72
|
-
return `
|
|
73
|
-
<style>
|
|
74
|
-
:host {
|
|
75
|
-
display: block;
|
|
76
|
-
padding: 20px;
|
|
77
|
-
}
|
|
78
|
-
</style>
|
|
79
|
-
<h1>${this.pageTitle}</h1>
|
|
80
|
-
<p>${this.message}</p>
|
|
81
|
-
`;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// 定义自定义元素
|
|
86
|
-
customElements.define('my-page', MyPage);
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### 使用验证功能
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
import { Validator, FormValidator } from '@sun-panel/micro-app';
|
|
93
|
-
|
|
94
|
-
// 验证单个字段
|
|
95
|
-
const rules = {
|
|
96
|
-
required: true,
|
|
97
|
-
type: 'string',
|
|
98
|
-
minLength: 3,
|
|
99
|
-
maxLength: 20
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const errors = await Validator.validateField('test', rules, 'username');
|
|
103
|
-
if (errors.length > 0) {
|
|
104
|
-
console.log('Validation errors:', errors);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// 验证对象
|
|
108
|
-
const formRules = {
|
|
109
|
-
username: {
|
|
110
|
-
required: true,
|
|
111
|
-
type: 'string',
|
|
112
|
-
minLength: 3
|
|
113
|
-
},
|
|
114
|
-
email: {
|
|
115
|
-
required: true,
|
|
116
|
-
type: 'email'
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const formData = {
|
|
121
|
-
username: 'test',
|
|
122
|
-
email: 'test@example.com'
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const formValidator = new FormValidator(formRules);
|
|
126
|
-
await formValidator.validateOrThrow(formData); // 抛出验证错误或无错误
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## 核心组件
|
|
130
|
-
|
|
131
|
-
### SunPanelElement
|
|
132
|
-
|
|
133
|
-
基础元素类,提供微应用的基本能力:
|
|
134
|
-
|
|
135
|
-
- 基于原生 Web Components 标准
|
|
136
|
-
- 内置影子 DOM 管理
|
|
137
|
-
- 属性和生命周期管理
|
|
138
|
-
- 事件派发机制
|
|
139
|
-
|
|
140
|
-
### SunPanelCardElement
|
|
141
|
-
|
|
142
|
-
卡片元素基类,适用于微应用中的卡片组件:
|
|
143
|
-
|
|
144
|
-
- 支持卡片大小配置
|
|
145
|
-
- 支持卡片标题
|
|
146
|
-
- 内置卡片信息处理
|
|
147
|
-
- 预设卡片样式
|
|
148
|
-
|
|
149
|
-
### SunPanelPageElement
|
|
150
|
-
|
|
151
|
-
页面元素基类,适用于微应用中的页面组件:
|
|
152
|
-
|
|
153
|
-
- 支持页面标题和描述
|
|
154
|
-
- 内置页面生命周期管理
|
|
155
|
-
- 预设页面布局
|
|
156
|
-
|
|
157
|
-
## API
|
|
158
|
-
|
|
159
|
-
### 元素生命周期
|
|
160
|
-
|
|
161
|
-
- `connectedCallback()` - 元素插入 DOM 时调用
|
|
162
|
-
- `disconnectedCallback()` - 元素从 DOM 移除时调用
|
|
163
|
-
- `attributeChangedCallback()` - 属性变化时调用
|
|
164
|
-
|
|
165
|
-
### 实用工具
|
|
166
|
-
|
|
167
|
-
- `Validator` - 验证工具类
|
|
168
|
-
- `FormValidator` - 表单验证器
|
|
169
|
-
- `ValidationError` - 验证错误类
|
|
170
|
-
|
|
171
|
-
## 构建
|
|
172
|
-
|
|
173
|
-
```bash
|
|
174
|
-
# 复制源文件到发布目录
|
|
175
|
-
npm run build
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## 开发
|
|
179
|
-
|
|
180
|
-
### 开发测试环境
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
# 启动开发服务器(带热重载)
|
|
184
|
-
✓ Rollup 正在监听文件变化
|
|
185
|
-
✓ 开发服务器运行在: http://localhost:3000
|
|
186
|
-
✓ LiveReload 已启用
|
|
187
|
-
✓ 成功构建: dev/bundle.js (91ms)
|
|
188
|
-
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
这将:
|
|
192
|
-
- 启动 Rollup watch 模式监听文件变化
|
|
193
|
-
- 自动启动开发服务器(http://localhost:3000)
|
|
194
|
-
- 自动在浏览器中打开测试页面
|
|
195
|
-
- 支持源码修改后自动重新构建和热重载
|
|
196
|
-
|
|
197
|
-
### 测试环境功能
|
|
198
|
-
|
|
199
|
-
开发测试环境包含:
|
|
200
|
-
- **卡片组件测试**:展示不同主题和大小的卡片
|
|
201
|
-
- **页面组件测试**:演示页面组件的功能
|
|
202
|
-
- **验证功能测试**:测试字段和表单验证
|
|
203
|
-
- **实时预览**:修改源代码后自动刷新
|
|
204
|
-
|
|
205
|
-
### 修改代码后
|
|
206
|
-
|
|
207
|
-
1. 修改 `src/` 目录下的源代码
|
|
208
|
-
2. Rollup 会自动重新构建 `dev/bundle.js`
|
|
209
|
-
3. 浏览器会自动刷新
|
|
210
|
-
4. 立即查看修改效果
|
|
211
|
-
|
|
212
|
-
### 构建生产版本
|
|
213
|
-
|
|
214
|
-
```bash
|
|
215
|
-
# 构建生产版本
|
|
216
|
-
npm run build
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
## 开发模式说明
|
|
220
|
-
|
|
221
|
-
此库采用 TypeScript 定义文件的开发模式:
|
|
222
|
-
|
|
223
|
-
- 使用者可以选择使用 JavaScript 或 TypeScript 方式导入和使用组件
|
|
224
|
-
|
|
225
|
-
## 开发时链接模块(开发者指南)
|
|
226
|
-
|
|
227
|
-
如果你正在开发基于 `@sun-panel/micro-app` 的微应用,并且希望在开发时获得最新的类型提示,可以使用 npm link 方式链接到本地的开发版本:
|
|
228
|
-
|
|
229
|
-
### 在微应用项目中链接开发版本
|
|
230
|
-
|
|
231
|
-
假设你有以下目录结构:
|
|
232
|
-
```
|
|
233
|
-
sun-panel-app/
|
|
234
|
-
├── sun-panel-micro-app/ # 正在开发的模块
|
|
235
|
-
└── sun-panel-micro-app-hslr-demo-app/ # 微应用项目
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
**步骤 1:在 sun-panel-micro-app 目录创建全局链接**
|
|
239
|
-
|
|
240
|
-
```bash
|
|
241
|
-
cd sun-panel-micro-app
|
|
242
|
-
npm link
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
**步骤 2:在微应用项目目录链接到全局包**
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
cd sun-panel-micro-app-hslr-demo-app
|
|
249
|
-
npm link @sun-panel/micro-app
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
**步骤 3:重新加载 VSCode**
|
|
253
|
-
|
|
254
|
-
按 `Cmd+Shift+P`,输入 "Developer: Reload Window" 并回车。
|
|
255
|
-
|
|
256
|
-
### 配置 jsconfig.json
|
|
257
|
-
|
|
258
|
-
在微应用项目根目录创建 `jsconfig.json` 文件:
|
|
259
|
-
|
|
260
|
-
```json
|
|
261
|
-
{
|
|
262
|
-
"compilerOptions": {
|
|
263
|
-
"baseUrl": ".",
|
|
264
|
-
"moduleResolution": "node",
|
|
265
|
-
"checkJs": true
|
|
266
|
-
},
|
|
267
|
-
"include": ["src/**/*", "**/*.js"],
|
|
268
|
-
"exclude": ["node_modules", "dist"]
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### 效果
|
|
273
|
-
|
|
274
|
-
- ✅ 编辑器会显示来自 `sun-panel-micro-app/src` 的最新类型定义
|
|
275
|
-
- ✅ 修改类型定义后无需重新发布,编辑器会自动更新提示
|
|
276
|
-
- ✅ 运行时代码通过 vite alias 引用开发目录的代码
|
|
277
|
-
- ✅ 类型提示通过 npm link 引用开发目录的类型定义
|
|
278
|
-
|
|
279
|
-
### 解除链接
|
|
280
|
-
|
|
281
|
-
如果要恢复使用 npm 发布的版本:
|
|
282
|
-
|
|
283
|
-
```bash
|
|
284
|
-
cd sun-panel-micro-app-hslr-demo-app
|
|
285
|
-
npm unlink @sun-panel/micro-app
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
然后重新加载 VSCode 即可。
|
|
289
|
-
|
|
290
|
-
## 类型定义开源
|
|
291
|
-
|
|
292
|
-
本项目的所有类型定义文件(以 `.d.ts` 结尾的文件)采用 MIT 开源协议发布,允许在任何项目中自由使用。
|
|
293
|
-
|
|
294
|
-
详细信息请参阅 [TYPES_LICENSE.md](TYPES_LICENSE.md) 文件。
|
|
295
|
-
|
|
296
|
-
## 许可证
|
|
297
|
-
|
|
298
|
-
MIT
|
|
22
|
+
参阅:[官方微应用开发文档](https://doc.sun-panel.top/v2/zh_cn/micro_app_dev/)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { SunPanelElement } from './SunPanelElement';
|
|
2
2
|
import { TemplateResult, PropertyValueMap } from 'lit';
|
|
3
|
-
import { SpContextPage, NetworkMode } from './types/common';
|
|
4
|
-
import { PageInitializedParam } from './types/api';
|
|
3
|
+
import { SpContextPage, NetworkMode, PageInitializedParam } from './types/common';
|
|
5
4
|
/**
|
|
6
5
|
* Sun Panel 页面元素基类
|
|
7
6
|
* 用于开发微应用中的页面组件,以窗口的形式加载
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SunPanelPageElement.d.ts","sourceRoot":"","sources":["../src/SunPanelPageElement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAQ,cAAc,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAwB,
|
|
1
|
+
{"version":3,"file":"SunPanelPageElement.d.ts","sourceRoot":"","sources":["../src/SunPanelPageElement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAQ,cAAc,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,WAAW,EAAwB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAIxG;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,eAAe;IAEtD,MAAM,CAAC,UAAU;;;;;MAGf;IAEF,KAAK,EAAE,aAAa,CAAC;;IAmBrB;;;;OAIG;IACH,aAAa,CAAC,cAAc,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI;IAa3D;;OAEG;IACH;;;OAGG;IACH,YAAY,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAK/E;;OAEG;IACH,OAAO,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAwB1E,WAAW,IAAI,IAAI;IAKnB;;;OAGG;IACH,aAAa,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IAIjD;;;OAGG;IACH,eAAe,IAAI,IAAI;IAIvB;;;OAGG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI;IAI9D;;;OAGG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI;IAIhE;;;OAGG;IACH,oBAAoB,CAAC,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,GAAG,IAAI;IAInF;;OAEG;IACH,MAAM,IAAI,cAAc;CAIzB"}
|
package/dist/index.bundle.js
CHANGED
|
@@ -20,5 +20,5 @@ const b=globalThis,E=t=>t,C=b.trustedTypes,w=C?C.createPolicy("lit-html",{create
|
|
|
20
20
|
* @license
|
|
21
21
|
* Copyright 2017 Google LLC
|
|
22
22
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
23
|
-
*/class ot extends v{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,s)=>{const i=s?.renderBefore??e;let n=i._$litPart$;if(void 0===n){const t=s?.renderBefore??null;i._$litPart$=n=new X(e.insertBefore(O(),t),t,void 0,s??{})}return n._$AI(t),n})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return B}}ot._$litElement$=!0,ot.finalized=!0,rt.litElementHydrateSupport?.({LitElement:ot});const at=rt.litElementPolyfillSupport;at?.({LitElement:ot}),(rt.litElementVersions??=[]).push("4.2.2");class ht extends ot{constructor(){super(),this._initialized=!1,this._eventListeners=new Map}initializeMicroApp(){this._initialized||(this._setupEventListeners(),this._initialized=!0)}connectedCallback(){super.connectedCallback(),this.initializeMicroApp(),this.onConnected()}disconnectedCallback(){super.disconnectedCallback(),this._cleanupEventListeners(),this.onDisconnected()}attributeChangedCallback(t,e,s){super.attributeChangedCallback(t,e,s),this.onAttributeChanged(t,e,s)}_setupEventListeners(){}_cleanupEventListeners(){const t=Array.from(this._eventListeners.entries());for(const[e,s]of t)s.forEach(t=>{window.removeEventListener(e,t)});this._eventListeners.clear()}addEventListener(t,e,s){super.addEventListener(t,e,s)}dispatchCustomEvent(t,e){const s=new CustomEvent(t,{bubbles:!0,composed:!0,detail:e});this.dispatchEvent(s)}onConnected(){}onDisconnected(){}onAttributeChanged(t,e,s){}render(){return V``}}class lt extends ht{constructor(){super(),this.spCtx={api:{},darkMode:!1,language:"zh-CN",networkMode:"wan",staticPath:"",role:0,widgetInfo:{}}}updateContext(t){if(!t||"object"!=typeof t)return;const e=Object.fromEntries(Object.entries(t).filter(([t,e])=>void 0!==e));this.spCtx={...this.spCtx,...e}}firstUpdated(t){super.firstUpdated?.(t),this.onFirstRendered()}updated(t){if(super.updated(t),t.has("spCtx")){const e=t.get("spCtx")||{},s=this.spCtx;s.widgetInfo!==e.widgetInfo&&this.onWidgetInfoChanged(s.widgetInfo,e.widgetInfo),s.darkMode!==e.darkMode&&this.onDarkModeChanged(s.darkMode,e.darkMode),s.language!==e.language&&this.onLanguageChanged(s.language,e.language),s.networkMode!==e.networkMode&&this.onNetworkModeChanged(s.networkMode,e.networkMode)}}onConnected(){super.onConnected(),this.onInitialized()}onInitialized(){}onFirstRendered(){}onDarkModeChanged(t,e){}onLanguageChanged(t,e){}onNetworkModeChanged(t,e){}onWidgetInfoChanged(t,e){}render(){return V``}}lt.properties={spCtx:{type:Object,attribute:!1}};class dt extends ht{constructor(){super(),this.spCtx={api:{},darkMode:!1,language:"zh-CN",networkMode:"wan",staticPath:"",role:0,background:"",widgetInfo:{},customParam:{}}}updateContext(t){if(!t||"object"!=typeof t)return;const e=Object.fromEntries(Object.entries(t).filter(([t,e])=>void 0!==e));this.spCtx={...this.spCtx,...e}}firstUpdated(t){super.firstUpdated?.(t),this.onFirstRendered()}updated(t){if(super.updated(t),t.has("spCtx")){const e=t.get("spCtx")||{},s=this.spCtx;s.darkMode!==e.darkMode&&this.onDarkModeChanged(s.darkMode,e.darkMode),s.language!==e.language&&this.onLanguageChanged(s.language,e.language),s.networkMode!==e.networkMode&&this.onNetworkModeChanged(s.networkMode,e.networkMode)}}onConnected(){super.onConnected(),this.onInitialized({widgetInfo:this.spCtx.widgetInfo,customParam:this.spCtx.customParam})}onInitialized(t){}onFirstRendered(){}onDarkModeChanged(t,e){}onLanguageChanged(t,e){}onNetworkModeChanged(t,e){}render(){return V``}}dt.properties={spCtx:{type:Object,attribute:!1}};class ct extends Error{constructor(t){super(`Validation failed: ${t.map(t=>t.message).join(", ")}`),this.name="ValidationError",this.errors=t}}class pt{static async validateField(t,e,s="field"){const i=[];if(e.required&&(null==t||""===t))return i.push({field:s,message:e.message||`${s} is required`,value:t}),i;if(null==t||""===t)return i;if(e.type){let n=!1;switch(e.type){case"string":n="string"==typeof t;break;case"number":n="number"==typeof t&&!isNaN(t);break;case"boolean":n="boolean"==typeof t;break;case"object":n="object"==typeof t&&null!==t&&!Array.isArray(t);break;case"array":n=Array.isArray(t);break;case"date":n=t instanceof Date||!isNaN(Date.parse(t));break;case"email":n="string"==typeof t&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);break;case"url":try{new URL(t),n=!0}catch{n=!1}break;default:n=!0}n||i.push({field:s,message:e.message||`${s} must be of type ${e.type}`,value:t})}if(void 0!==e.minLength&&"string"==typeof t&&t.length<e.minLength&&i.push({field:s,message:e.message||`${s} must be at least ${e.minLength} characters`,value:t}),void 0!==e.maxLength&&"string"==typeof t&&t.length>e.maxLength&&i.push({field:s,message:e.message||`${s} must be no more than ${e.maxLength} characters`,value:t}),void 0!==e.min&&"number"==typeof t&&t<e.min&&i.push({field:s,message:e.message||`${s} must be at least ${e.min}`,value:t}),void 0!==e.max&&"number"==typeof t&&t>e.max&&i.push({field:s,message:e.message||`${s} must be no more than ${e.max}`,value:t}),e.pattern&&"string"==typeof t&&!e.pattern.test(t)&&i.push({field:s,message:e.message||`${s} format is invalid`,value:t}),e.validator)try{const n=await Promise.resolve(e.validator(t));"string"==typeof n?i.push({field:s,message:n,value:t}):!1===n&&i.push({field:s,message:e.message||`${s} is invalid`,value:t})}catch(n){i.push({field:s,message:e.message||`Validation failed for ${s}: ${n instanceof Error?n.message:String(n)}`,value:t})}return i}static async validateObject(t,e){const s=[];for(const i of Object.keys(e)){const n=e[i],r=t[i],o=await this.validateField(r,n,i);s.push(...o)}return s}static async validateArray(t,e){if(!Array.isArray(t))return[{field:"array",message:"Value must be an array",value:t}];const s=[];if(void 0!==e.min&&t.length<e.min&&s.push({field:"array",message:e.message||`Array must have at least ${e.min} items`,value:t}),void 0!==e.max&&t.length>e.max&&s.push({field:"array",message:e.message||`Array must have no more than ${e.max} items`,value:t}),e.validator)for(let i=0;i<t.length;i++){const n=t[i],r=await this.validateField(n,e,`array[${i}]`);s.push(...r)}return s}}t.FormValidator=class{constructor(t){this.rules=t}async validate(t){return await pt.validateObject(t,this.rules)}async validateOrThrow(t){const e=await this.validate(t);if(e.length>0)throw new ct(e)}},t.SunPanelElement=ht,t.SunPanelPageElement=dt,t.SunPanelWidgetElement=lt,t.VERSION='"1.0.
|
|
23
|
+
*/class ot extends v{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=((t,e,s)=>{const i=s?.renderBefore??e;let n=i._$litPart$;if(void 0===n){const t=s?.renderBefore??null;i._$litPart$=n=new X(e.insertBefore(O(),t),t,void 0,s??{})}return n._$AI(t),n})(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return B}}ot._$litElement$=!0,ot.finalized=!0,rt.litElementHydrateSupport?.({LitElement:ot});const at=rt.litElementPolyfillSupport;at?.({LitElement:ot}),(rt.litElementVersions??=[]).push("4.2.2");class ht extends ot{constructor(){super(),this._initialized=!1,this._eventListeners=new Map}initializeMicroApp(){this._initialized||(this._setupEventListeners(),this._initialized=!0)}connectedCallback(){super.connectedCallback(),this.initializeMicroApp(),this.onConnected()}disconnectedCallback(){super.disconnectedCallback(),this._cleanupEventListeners(),this.onDisconnected()}attributeChangedCallback(t,e,s){super.attributeChangedCallback(t,e,s),this.onAttributeChanged(t,e,s)}_setupEventListeners(){}_cleanupEventListeners(){const t=Array.from(this._eventListeners.entries());for(const[e,s]of t)s.forEach(t=>{window.removeEventListener(e,t)});this._eventListeners.clear()}addEventListener(t,e,s){super.addEventListener(t,e,s)}dispatchCustomEvent(t,e){const s=new CustomEvent(t,{bubbles:!0,composed:!0,detail:e});this.dispatchEvent(s)}onConnected(){}onDisconnected(){}onAttributeChanged(t,e,s){}render(){return V``}}class lt extends ht{constructor(){super(),this.spCtx={api:{},darkMode:!1,language:"zh-CN",networkMode:"wan",staticPath:"",role:0,widgetInfo:{}}}updateContext(t){if(!t||"object"!=typeof t)return;const e=Object.fromEntries(Object.entries(t).filter(([t,e])=>void 0!==e));this.spCtx={...this.spCtx,...e}}firstUpdated(t){super.firstUpdated?.(t),this.onFirstRendered()}updated(t){if(super.updated(t),t.has("spCtx")){const e=t.get("spCtx")||{},s=this.spCtx;s.widgetInfo!==e.widgetInfo&&this.onWidgetInfoChanged(s.widgetInfo,e.widgetInfo),s.darkMode!==e.darkMode&&this.onDarkModeChanged(s.darkMode,e.darkMode),s.language!==e.language&&this.onLanguageChanged(s.language,e.language),s.networkMode!==e.networkMode&&this.onNetworkModeChanged(s.networkMode,e.networkMode)}}onConnected(){super.onConnected(),this.onInitialized()}onInitialized(){}onFirstRendered(){}onDarkModeChanged(t,e){}onLanguageChanged(t,e){}onNetworkModeChanged(t,e){}onWidgetInfoChanged(t,e){}render(){return V``}}lt.properties={spCtx:{type:Object,attribute:!1}};class dt extends ht{constructor(){super(),this.spCtx={api:{},darkMode:!1,language:"zh-CN",networkMode:"wan",staticPath:"",role:0,background:"",widgetInfo:{},customParam:{}}}updateContext(t){if(!t||"object"!=typeof t)return;const e=Object.fromEntries(Object.entries(t).filter(([t,e])=>void 0!==e));this.spCtx={...this.spCtx,...e}}firstUpdated(t){super.firstUpdated?.(t),this.onFirstRendered()}updated(t){if(super.updated(t),t.has("spCtx")){const e=t.get("spCtx")||{},s=this.spCtx;s.darkMode!==e.darkMode&&this.onDarkModeChanged(s.darkMode,e.darkMode),s.language!==e.language&&this.onLanguageChanged(s.language,e.language),s.networkMode!==e.networkMode&&this.onNetworkModeChanged(s.networkMode,e.networkMode)}}onConnected(){super.onConnected(),this.onInitialized({widgetInfo:this.spCtx.widgetInfo,customParam:this.spCtx.customParam})}onInitialized(t){}onFirstRendered(){}onDarkModeChanged(t,e){}onLanguageChanged(t,e){}onNetworkModeChanged(t,e){}render(){return V``}}dt.properties={spCtx:{type:Object,attribute:!1}};class ct extends Error{constructor(t){super(`Validation failed: ${t.map(t=>t.message).join(", ")}`),this.name="ValidationError",this.errors=t}}class pt{static async validateField(t,e,s="field"){const i=[];if(e.required&&(null==t||""===t))return i.push({field:s,message:e.message||`${s} is required`,value:t}),i;if(null==t||""===t)return i;if(e.type){let n=!1;switch(e.type){case"string":n="string"==typeof t;break;case"number":n="number"==typeof t&&!isNaN(t);break;case"boolean":n="boolean"==typeof t;break;case"object":n="object"==typeof t&&null!==t&&!Array.isArray(t);break;case"array":n=Array.isArray(t);break;case"date":n=t instanceof Date||!isNaN(Date.parse(t));break;case"email":n="string"==typeof t&&/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(t);break;case"url":try{new URL(t),n=!0}catch{n=!1}break;default:n=!0}n||i.push({field:s,message:e.message||`${s} must be of type ${e.type}`,value:t})}if(void 0!==e.minLength&&"string"==typeof t&&t.length<e.minLength&&i.push({field:s,message:e.message||`${s} must be at least ${e.minLength} characters`,value:t}),void 0!==e.maxLength&&"string"==typeof t&&t.length>e.maxLength&&i.push({field:s,message:e.message||`${s} must be no more than ${e.maxLength} characters`,value:t}),void 0!==e.min&&"number"==typeof t&&t<e.min&&i.push({field:s,message:e.message||`${s} must be at least ${e.min}`,value:t}),void 0!==e.max&&"number"==typeof t&&t>e.max&&i.push({field:s,message:e.message||`${s} must be no more than ${e.max}`,value:t}),e.pattern&&"string"==typeof t&&!e.pattern.test(t)&&i.push({field:s,message:e.message||`${s} format is invalid`,value:t}),e.validator)try{const n=await Promise.resolve(e.validator(t));"string"==typeof n?i.push({field:s,message:n,value:t}):!1===n&&i.push({field:s,message:e.message||`${s} is invalid`,value:t})}catch(n){i.push({field:s,message:e.message||`Validation failed for ${s}: ${n instanceof Error?n.message:String(n)}`,value:t})}return i}static async validateObject(t,e){const s=[];for(const i of Object.keys(e)){const n=e[i],r=t[i],o=await this.validateField(r,n,i);s.push(...o)}return s}static async validateArray(t,e){if(!Array.isArray(t))return[{field:"array",message:"Value must be an array",value:t}];const s=[];if(void 0!==e.min&&t.length<e.min&&s.push({field:"array",message:e.message||`Array must have at least ${e.min} items`,value:t}),void 0!==e.max&&t.length>e.max&&s.push({field:"array",message:e.message||`Array must have no more than ${e.max} items`,value:t}),e.validator)for(let i=0;i<t.length;i++){const n=t[i],r=await this.validateField(n,e,`array[${i}]`);s.push(...r)}return s}}t.FormValidator=class{constructor(t){this.rules=t}async validate(t){return await pt.validateObject(t,this.rules)}async validateOrThrow(t){const e=await this.validate(t);if(e.length>0)throw new ct(e)}},t.SunPanelElement=ht,t.SunPanelPageElement=dt,t.SunPanelWidgetElement=lt,t.VERSION='"1.0.7"',t.ValidationError=ct,t.Validator=pt}(this.SunPanelMicroApp=this.SunPanelMicroApp||{});
|
|
24
24
|
//# sourceMappingURL=index.bundle.js.map
|