py-test-component 1.0.2 → 1.0.4
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/py-component.esm.js +2 -0
- package/dist/py-component.esm.js.LICENSE.txt +37 -0
- package/dist/py-component.js +1 -1
- package/dist/py-component.js.LICENSE.txt +6 -0
- package/index.d.ts +21 -11
- package/package.json +25 -15
- package/src/react/index.js +102 -27
|
@@ -6,6 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* vue-custom-element v3.3.0
|
|
11
|
+
* (c) 2021 Karol Fabjańczuk
|
|
12
|
+
* @license MIT
|
|
13
|
+
*/
|
|
14
|
+
|
|
9
15
|
/**
|
|
10
16
|
* @license
|
|
11
17
|
* Lodash <https://lodash.com/>
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// ============================================
|
|
2
|
+
// py-test-component - TypeScript 类型定义
|
|
3
|
+
// ============================================
|
|
4
|
+
|
|
1
5
|
declare module 'py-test-component' {
|
|
2
6
|
export interface PyComponentStore {
|
|
3
7
|
set(config: Record<string, any>): void;
|
|
@@ -35,6 +39,8 @@ declare module 'py-test-component/react' {
|
|
|
35
39
|
export interface PyTableProps {
|
|
36
40
|
/** 表格数据 */
|
|
37
41
|
data?: Record<string, any>[];
|
|
42
|
+
/** 加载中的占位内容 */
|
|
43
|
+
loading?: ReactNode;
|
|
38
44
|
/** 其他 HTML 属性 */
|
|
39
45
|
[key: string]: any;
|
|
40
46
|
}
|
|
@@ -42,29 +48,33 @@ declare module 'py-test-component/react' {
|
|
|
42
48
|
export interface PyWeatherProps {
|
|
43
49
|
/** 城市名称 */
|
|
44
50
|
city?: string;
|
|
51
|
+
/** 加载中的占位内容 */
|
|
52
|
+
loading?: ReactNode;
|
|
45
53
|
/** 其他 HTML 属性 */
|
|
46
54
|
[key: string]: any;
|
|
47
55
|
}
|
|
48
56
|
|
|
49
|
-
export interface
|
|
50
|
-
/** 获取 DOM 元素 */
|
|
51
|
-
getElement: () => HTMLElement | null;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export interface PyWeatherRef {
|
|
57
|
+
export interface PyComponentRef {
|
|
55
58
|
/** 获取 DOM 元素 */
|
|
56
59
|
getElement: () => HTMLElement | null;
|
|
60
|
+
/** 是否已加载完成 */
|
|
61
|
+
loaded: boolean;
|
|
62
|
+
/** 加载错误信息 */
|
|
63
|
+
error: Error | null;
|
|
57
64
|
}
|
|
58
65
|
|
|
59
|
-
/** 表格组件 */
|
|
60
|
-
export const PyTable: ForwardRefExoticComponent<PyTableProps & RefAttributes<
|
|
66
|
+
/** 表格组件 - React 版本 */
|
|
67
|
+
export const PyTable: ForwardRefExoticComponent<PyTableProps & RefAttributes<PyComponentRef>>;
|
|
61
68
|
|
|
62
|
-
/** 天气组件 */
|
|
63
|
-
export const PyWeather: ForwardRefExoticComponent<PyWeatherProps & RefAttributes<
|
|
69
|
+
/** 天气组件 - React 版本 */
|
|
70
|
+
export const PyWeather: ForwardRefExoticComponent<PyWeatherProps & RefAttributes<PyComponentRef>>;
|
|
64
71
|
|
|
65
72
|
/** 初始化组件库 */
|
|
66
|
-
export function initPyComponent(config?: Record<string, any>):
|
|
73
|
+
export function initPyComponent(config?: Record<string, any>): Promise<any>;
|
|
67
74
|
|
|
68
75
|
/** 获取全局 store */
|
|
69
76
|
export function getStore(): Record<string, any> | null;
|
|
77
|
+
|
|
78
|
+
/** 预加载组件库(可提前调用以加速渲染) */
|
|
79
|
+
export function preloadPyComponent(): Promise<any>;
|
|
70
80
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "py-test-component",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Vue2 + ElementUI 组件库,支持 React 使用",
|
|
5
5
|
"main": "dist/py-component.js",
|
|
6
6
|
"module": "dist/py-component.esm.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
+
"types": "./index.d.ts",
|
|
10
11
|
"import": "./dist/py-component.esm.js",
|
|
11
12
|
"require": "./dist/py-component.js"
|
|
12
13
|
},
|
|
13
|
-
"./vue":
|
|
14
|
-
|
|
14
|
+
"./vue": {
|
|
15
|
+
"types": "./index.d.ts",
|
|
16
|
+
"import": "./src/vue/index.js",
|
|
17
|
+
"require": "./src/vue/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./react": {
|
|
20
|
+
"types": "./index.d.ts",
|
|
21
|
+
"import": "./src/react/index.js",
|
|
22
|
+
"require": "./src/react/index.js"
|
|
23
|
+
}
|
|
15
24
|
},
|
|
16
25
|
"files": [
|
|
17
26
|
"dist",
|
|
@@ -24,24 +33,25 @@
|
|
|
24
33
|
"dev": "webpack --mode development --watch"
|
|
25
34
|
},
|
|
26
35
|
"dependencies": {
|
|
27
|
-
"
|
|
28
|
-
"
|
|
36
|
+
"element-ui": "^2.15.0",
|
|
37
|
+
"vue": "^2.7.0",
|
|
38
|
+
"vue-custom-element": "^3.3.0"
|
|
29
39
|
},
|
|
30
40
|
"devDependencies": {
|
|
31
|
-
"webpack": "^5.88.0",
|
|
32
|
-
"webpack-cli": "^5.1.0",
|
|
33
|
-
"vue-loader": "^15.10.1",
|
|
34
|
-
"vue-template-compiler": "^2.7.14",
|
|
35
|
-
"css-loader": "^6.8.1",
|
|
36
|
-
"style-loader": "^1.3.0",
|
|
37
|
-
"babel-loader": "^9.1.2",
|
|
38
41
|
"@babel/core": "^7.22.0",
|
|
39
42
|
"@babel/preset-env": "^7.22.0",
|
|
40
|
-
"@vue/web-component-wrapper": "^1.3.0"
|
|
43
|
+
"@vue/web-component-wrapper": "^1.3.0",
|
|
44
|
+
"babel-loader": "^9.1.2",
|
|
45
|
+
"css-loader": "^6.8.1",
|
|
46
|
+
"style-loader": "^1.3.0",
|
|
47
|
+
"vue-loader": "^15.10.1",
|
|
48
|
+
"vue-template-compiler": "^2.7.14",
|
|
49
|
+
"webpack": "^5.88.0",
|
|
50
|
+
"webpack-cli": "^5.1.0"
|
|
41
51
|
},
|
|
42
52
|
"peerDependencies": {
|
|
43
|
-
"
|
|
44
|
-
"
|
|
53
|
+
"element-ui": "^2.15.0",
|
|
54
|
+
"vue": "^2.7.0"
|
|
45
55
|
},
|
|
46
56
|
"peerDependenciesMeta": {
|
|
47
57
|
"vue": {
|
package/src/react/index.js
CHANGED
|
@@ -1,65 +1,135 @@
|
|
|
1
|
-
import { createElement, useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
|
|
1
|
+
import { createElement, useEffect, useRef, useState, forwardRef, useImperativeHandle } from 'react';
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// 注入 ElementUI CSS(只执行一次)
|
|
4
|
+
let cssInjected = false;
|
|
5
|
+
function injectElementUICSS() {
|
|
6
|
+
if (cssInjected || typeof document === 'undefined') return;
|
|
7
|
+
cssInjected = true;
|
|
8
|
+
|
|
9
|
+
// 检查是否已存在
|
|
10
|
+
if (document.querySelector('link[data-py-component-css]')) return;
|
|
11
|
+
|
|
12
|
+
const link = document.createElement('link');
|
|
13
|
+
link.rel = 'stylesheet';
|
|
14
|
+
link.href = 'https://unpkg.com/element-ui/lib/theme-chalk/index.css';
|
|
15
|
+
link.dataset.pyComponentCss = 'true';
|
|
16
|
+
document.head.appendChild(link);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 加载状态管理
|
|
4
20
|
let loadPromise = null;
|
|
21
|
+
let isLoaded = false;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 加载组件库核心逻辑
|
|
25
|
+
* 使用 ESM 动态导入,由构建工具处理路径解析
|
|
26
|
+
*/
|
|
27
|
+
async function doLoad() {
|
|
28
|
+
if (typeof window === 'undefined') return null;
|
|
29
|
+
if (window.PyComponent) return window.PyComponent;
|
|
30
|
+
|
|
31
|
+
const module = await import('py-test-component');
|
|
32
|
+
const PyComponent = module.default || module;
|
|
33
|
+
|
|
34
|
+
if (PyComponent && typeof window !== 'undefined') {
|
|
35
|
+
window.PyComponent = PyComponent;
|
|
36
|
+
}
|
|
5
37
|
|
|
38
|
+
return PyComponent;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 获取或创建加载 Promise
|
|
43
|
+
*/
|
|
6
44
|
function loadPyComponent() {
|
|
7
45
|
if (loadPromise) return loadPromise;
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
script.async = true;
|
|
15
|
-
script.onload = () => resolve(window.PyComponent);
|
|
16
|
-
script.onerror = reject;
|
|
17
|
-
document.body.appendChild(script);
|
|
46
|
+
if (isLoaded && window.PyComponent) {
|
|
47
|
+
return Promise.resolve(window.PyComponent);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
loadPromise = doLoad().finally(() => {
|
|
51
|
+
isLoaded = true;
|
|
18
52
|
});
|
|
19
53
|
|
|
20
54
|
return loadPromise;
|
|
21
55
|
}
|
|
22
56
|
|
|
57
|
+
/**
|
|
58
|
+
* 使用组件库的 Hook
|
|
59
|
+
*/
|
|
60
|
+
function usePyComponent() {
|
|
61
|
+
const [loaded, setLoaded] = useState(isLoaded);
|
|
62
|
+
const [error, setError] = useState(null);
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
// 自动注入 CSS
|
|
66
|
+
injectElementUICSS();
|
|
67
|
+
|
|
68
|
+
if (isLoaded) {
|
|
69
|
+
setLoaded(true);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
loadPyComponent()
|
|
74
|
+
.then(() => setLoaded(true))
|
|
75
|
+
.catch((err) => {
|
|
76
|
+
console.error('[py-test-component] 加载失败:', err);
|
|
77
|
+
setError(err);
|
|
78
|
+
});
|
|
79
|
+
}, []);
|
|
80
|
+
|
|
81
|
+
return { loaded, error, PyComponent: typeof window !== 'undefined' ? window.PyComponent : null };
|
|
82
|
+
}
|
|
83
|
+
|
|
23
84
|
// PyTable React 包装组件
|
|
24
|
-
export const PyTable = forwardRef(function PyTable({ data, ...props }, ref) {
|
|
85
|
+
export const PyTable = forwardRef(function PyTable({ data, loading: propsLoading, ...props }, ref) {
|
|
25
86
|
const elRef = useRef(null);
|
|
87
|
+
const { loaded, error } = usePyComponent();
|
|
26
88
|
|
|
27
89
|
useImperativeHandle(ref, () => ({
|
|
28
|
-
getElement: () => elRef.current
|
|
90
|
+
getElement: () => elRef.current,
|
|
91
|
+
loaded,
|
|
92
|
+
error
|
|
29
93
|
}));
|
|
30
94
|
|
|
31
95
|
useEffect(() => {
|
|
32
|
-
|
|
33
|
-
}, []);
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
if (elRef.current && data) {
|
|
96
|
+
if (elRef.current && data && loaded) {
|
|
37
97
|
elRef.current.setAttribute('table-data', JSON.stringify(data));
|
|
38
98
|
}
|
|
39
|
-
}, [data]);
|
|
99
|
+
}, [data, loaded]);
|
|
100
|
+
|
|
101
|
+
if (!loaded && propsLoading) {
|
|
102
|
+
return createElement('div', { style: { padding: '20px', textAlign: 'center' } }, propsLoading);
|
|
103
|
+
}
|
|
40
104
|
|
|
41
105
|
return createElement('py-table', { ref: elRef, ...props });
|
|
42
106
|
});
|
|
43
107
|
|
|
44
108
|
// PyWeather React 包装组件
|
|
45
|
-
export const PyWeather = forwardRef(function PyWeather(props, ref) {
|
|
109
|
+
export const PyWeather = forwardRef(function PyWeather({ loading: propsLoading, ...props }, ref) {
|
|
46
110
|
const elRef = useRef(null);
|
|
111
|
+
const { loaded, error } = usePyComponent();
|
|
47
112
|
|
|
48
113
|
useImperativeHandle(ref, () => ({
|
|
49
|
-
getElement: () => elRef.current
|
|
114
|
+
getElement: () => elRef.current,
|
|
115
|
+
loaded,
|
|
116
|
+
error
|
|
50
117
|
}));
|
|
51
118
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
119
|
+
if (!loaded && propsLoading) {
|
|
120
|
+
return createElement('div', { style: { padding: '20px', textAlign: 'center' } }, propsLoading);
|
|
121
|
+
}
|
|
55
122
|
|
|
56
123
|
return createElement('py-weather', { ref: elRef, ...props });
|
|
57
124
|
});
|
|
58
125
|
|
|
59
126
|
// 初始化函数
|
|
60
127
|
export function initPyComponent(config) {
|
|
61
|
-
loadPyComponent().then((PyComponent) => {
|
|
62
|
-
PyComponent
|
|
128
|
+
return loadPyComponent().then((PyComponent) => {
|
|
129
|
+
if (PyComponent?.init) {
|
|
130
|
+
PyComponent.init(config);
|
|
131
|
+
}
|
|
132
|
+
return PyComponent;
|
|
63
133
|
});
|
|
64
134
|
}
|
|
65
135
|
|
|
@@ -67,3 +137,8 @@ export function initPyComponent(config) {
|
|
|
67
137
|
export function getStore() {
|
|
68
138
|
return typeof window !== 'undefined' ? window.PyComponent?.store : null;
|
|
69
139
|
}
|
|
140
|
+
|
|
141
|
+
// 预加载函数
|
|
142
|
+
export function preloadPyComponent() {
|
|
143
|
+
return loadPyComponent();
|
|
144
|
+
}
|