cdui-js 1.0.13 → 1.0.14
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/build/css.ts +9 -18
- package/css/all.css +8 -3
- package/css/base.css +4 -0
- package/css/button.css +3 -0
- package/css/canlendar.css +1 -26
- package/css/carousel.css +0 -3
- package/css/combobox.css +5 -25
- package/css/datepicker.css +38 -0
- package/css/form.css +19 -0
- package/css/popup.css +33 -0
- package/css/textbox.css +5 -0
- package/{css → demo/css}/build.ts +1 -1
- package/{css → demo/css}/css.md +45 -4
- package/demo/icons/build.ts +17 -0
- package/{index.html → demo/index.html} +20 -2
- package/demo/src/App.tsx +15 -0
- package/demo/src/css/all.css +3 -0
- package/demo/src/css/atomic.css +935 -0
- package/demo/src/main.ts +10 -0
- package/demo/{pages → src/pages}/Canlendar.tsx +1 -1
- package/demo/src/pages/ComboBox.tsx +10 -0
- package/demo/src/pages/DatePicker.tsx +5 -0
- package/demo/src/pages/Form.tsx +66 -0
- package/{vite.config.ts → demo/vite.config.ts} +2 -2
- package/icons/backward.svg +2 -2
- package/icons/close.svg +3 -3
- package/icons/dropdown.svg +2 -2
- package/icons/forward.svg +2 -2
- package/package.json +4 -2
- package/src/components/Button.tsx +5 -0
- package/src/components/Canlendar.tsx +23 -45
- package/src/components/Carousel.tsx +13 -4
- package/src/components/CollapsiblePanel.tsx +2 -4
- package/src/components/ComboBox.tsx +50 -146
- package/src/components/DatePicker.tsx +91 -0
- package/src/components/Dialog.ts +1 -1
- package/src/components/Form.tsx +141 -418
- package/src/components/Icon.tsx +2 -1
- package/src/components/Popup.tsx +220 -0
- package/src/components/Pulldown.tsx +2 -3
- package/src/components/TextBox.tsx +8 -0
- package/src/dom.ts +55 -39
- package/src/http.ts +23 -19
- package/src/i18n/languages/en.json +3 -3
- package/src/index.ts +5 -1
- package/src/reactive.ts +9 -0
- package/demo/App.tsx +0 -31
- package/demo/main.ts +0 -7
- package/demo/pages/ComboBox.tsx +0 -10
- package/demo/pages/Form.tsx +0 -32
- package/icons/build.ts +0 -24
- /package/demo/{test.js → src/test.js} +0 -0
package/src/components/Icon.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { splitProps } from 'solid-js';
|
|
2
2
|
|
|
3
3
|
import { JSX } from '../jsx';
|
|
4
|
+
import { combineClass } from '../reactive';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* 图标组件
|
|
@@ -9,7 +10,7 @@ export const Icon = (props?: JSX.SvgSVGAttributes<never> & { name: string }) =>
|
|
|
9
10
|
let [thisProps, restProps] = splitProps(props, ['class', 'name']);
|
|
10
11
|
|
|
11
12
|
return (
|
|
12
|
-
<svg class={
|
|
13
|
+
<svg class={combineClass('icon', thisProps.class)} aria-hidden={true} {...restProps}>
|
|
13
14
|
<use href={'#icon-' + thisProps.name}></use>
|
|
14
15
|
</svg>
|
|
15
16
|
);
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { JSX } from '../jsx';
|
|
2
|
+
import { layout } from '../layout';
|
|
3
|
+
import { combineClass, splitProps } from '../reactive';
|
|
4
|
+
import { disableAutoCloseEvent, hideMaskLayer, registerAutoClose, showMaskLayer } from '../dom';
|
|
5
|
+
|
|
6
|
+
const POPUP_TOP_CLASS = 'popup-top';
|
|
7
|
+
const POPUP_RIGHT_CLASS = 'popup-right';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 当前弹出层
|
|
11
|
+
*/
|
|
12
|
+
const currentPopup = {
|
|
13
|
+
/**
|
|
14
|
+
* 当前 DOM 对象
|
|
15
|
+
*/
|
|
16
|
+
dom: null as HTMLElement,
|
|
17
|
+
/**
|
|
18
|
+
* 是否显示了遮罩层
|
|
19
|
+
*/
|
|
20
|
+
mask: false,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 是否使用下拉动画
|
|
25
|
+
*/
|
|
26
|
+
let useDropdownTransition = true;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 显示遮罩层方法
|
|
30
|
+
*/
|
|
31
|
+
let showMaskLayerFn = () => layout['le-480'];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 设置是否使用下拉动画
|
|
35
|
+
*
|
|
36
|
+
* @param use 是否使用
|
|
37
|
+
*/
|
|
38
|
+
export const setUseDropdownTransition = (use: boolean) => {
|
|
39
|
+
useDropdownTransition = use;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 设置显示遮罩层的方法
|
|
44
|
+
*
|
|
45
|
+
* @param fn 显示遮罩层的方法
|
|
46
|
+
*/
|
|
47
|
+
export const setShowMaskLayerFn = (fn: () => boolean) => {
|
|
48
|
+
showMaskLayerFn = fn || showMaskLayerFn;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const showPopup = (dom: HTMLElement, onPopup?: (dom: HTMLElement) => void | false) => {
|
|
52
|
+
// 下拉钩子
|
|
53
|
+
if (onPopup && onPopup(dom) === false) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let windowWidth = window.innerWidth;
|
|
58
|
+
let windowHeight = window.innerHeight;
|
|
59
|
+
let classList = dom.classList;
|
|
60
|
+
let style = dom.style;
|
|
61
|
+
|
|
62
|
+
// 有下拉
|
|
63
|
+
if (currentPopup.dom) {
|
|
64
|
+
// 先关闭
|
|
65
|
+
hidePopup();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 记录当前弹出层
|
|
69
|
+
currentPopup.dom = dom;
|
|
70
|
+
|
|
71
|
+
if ((currentPopup.mask = showMaskLayerFn())) {
|
|
72
|
+
showMaskLayer(closePopup);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let host = dom.parentNode as HTMLElement;
|
|
76
|
+
|
|
77
|
+
// 先显示
|
|
78
|
+
style.width = host.offsetWidth + 'px';
|
|
79
|
+
style.height = 'auto';
|
|
80
|
+
style.display = 'block';
|
|
81
|
+
|
|
82
|
+
// 获取宽高及计算位置
|
|
83
|
+
let width = (dom.firstElementChild as HTMLElement).offsetWidth;
|
|
84
|
+
let height = dom.offsetHeight;
|
|
85
|
+
let rect = host.getBoundingClientRect();
|
|
86
|
+
|
|
87
|
+
// 同步子组件宽度
|
|
88
|
+
style.width = width + 'px';
|
|
89
|
+
|
|
90
|
+
if (windowHeight - rect.top - rect.height < height + 4 && rect.top >= height) {
|
|
91
|
+
classList.add(POPUP_TOP_CLASS);
|
|
92
|
+
} else {
|
|
93
|
+
classList.remove(POPUP_TOP_CLASS);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (windowWidth - rect.left - rect.width > width + 4 && rect.left >= width) {
|
|
97
|
+
classList.add(POPUP_RIGHT_CLASS);
|
|
98
|
+
} else {
|
|
99
|
+
classList.remove(POPUP_RIGHT_CLASS);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// 过渡动画
|
|
103
|
+
if (useDropdownTransition) {
|
|
104
|
+
style.height = '0';
|
|
105
|
+
|
|
106
|
+
setTimeout(() => {
|
|
107
|
+
style.height = height + 'px';
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const hidePopup = () => {
|
|
113
|
+
let popup = currentPopup;
|
|
114
|
+
let dom = popup.dom;
|
|
115
|
+
let style = dom.style;
|
|
116
|
+
|
|
117
|
+
currentPopup.dom = null;
|
|
118
|
+
|
|
119
|
+
if (popup.mask) {
|
|
120
|
+
hideMaskLayer();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// 过渡动画
|
|
124
|
+
if (useDropdownTransition) {
|
|
125
|
+
style.height = dom.offsetHeight + 'px';
|
|
126
|
+
|
|
127
|
+
setTimeout(() => {
|
|
128
|
+
style.height = '0';
|
|
129
|
+
});
|
|
130
|
+
} else {
|
|
131
|
+
style.display = 'none';
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const togglePopup = (dom: HTMLElement, onPopup?: (dom: HTMLElement) => void | false, event?: Event) => {
|
|
136
|
+
// 有显示下拉
|
|
137
|
+
if (currentPopup.dom) {
|
|
138
|
+
// 不是当前下拉框
|
|
139
|
+
if (currentPopup.dom !== dom) {
|
|
140
|
+
// 先关闭
|
|
141
|
+
closePopup();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
showPopup(dom, onPopup);
|
|
145
|
+
} else {
|
|
146
|
+
showPopup(dom, onPopup);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
event && event.stopPropagation();
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 弹出层外部访问接口
|
|
154
|
+
*/
|
|
155
|
+
export interface PopupApi {
|
|
156
|
+
/**
|
|
157
|
+
* 打开弹出框
|
|
158
|
+
*/
|
|
159
|
+
openPopup(): void;
|
|
160
|
+
/**
|
|
161
|
+
* 关闭弹出框
|
|
162
|
+
*/
|
|
163
|
+
closePupup(): void;
|
|
164
|
+
/**
|
|
165
|
+
* 显示或关闭弹出层
|
|
166
|
+
*/
|
|
167
|
+
togglePopup(): void;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 弹出层属性
|
|
172
|
+
*/
|
|
173
|
+
export interface PopupProps {
|
|
174
|
+
/**
|
|
175
|
+
* 弹出对话框钩子
|
|
176
|
+
*/
|
|
177
|
+
onPopup?: (dom: HTMLElement) => void | false;
|
|
178
|
+
/**
|
|
179
|
+
* 外部调用接口
|
|
180
|
+
*/
|
|
181
|
+
api?: (api: PopupApi) => void;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 弹出层组件
|
|
186
|
+
*/
|
|
187
|
+
export const Popup = (props?: JSX.HTMLAttributes<never> & PopupProps) => {
|
|
188
|
+
let [thisProps, restProps] = splitProps(props, ['onPopup', 'api', 'children']);
|
|
189
|
+
let popup: HTMLElement;
|
|
190
|
+
|
|
191
|
+
// 初始化外部调用接口
|
|
192
|
+
props.api &&
|
|
193
|
+
props.api({
|
|
194
|
+
openPopup: () => showPopup(popup, thisProps.onPopup),
|
|
195
|
+
closePupup: () => currentPopup.dom === popup && hidePopup(),
|
|
196
|
+
togglePopup: () => togglePopup(popup, thisProps.onPopup),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div
|
|
201
|
+
ref={popup as any}
|
|
202
|
+
class="popup"
|
|
203
|
+
style={{ display: 'none' }}
|
|
204
|
+
{...disableAutoCloseEvent}
|
|
205
|
+
ontransitionend={() => currentPopup.dom === popup || (popup.style.display = 'none')}
|
|
206
|
+
>
|
|
207
|
+
<div {...restProps}>{thisProps.children}</div>
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 关闭当前弹出层
|
|
214
|
+
*/
|
|
215
|
+
export const closePopup = () => {
|
|
216
|
+
currentPopup.dom && hidePopup();
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// 注册点击关闭弹出层的方法
|
|
220
|
+
registerAutoClose(closePopup);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// import { onCleanup, onMount, splitProps } from 'solid-js';
|
|
2
|
-
|
|
3
1
|
// import { JSX } from '../jsx';
|
|
2
|
+
// import { combineClass, onCleanup, onMount, splitProps } from '../reactive';
|
|
4
3
|
// import { addEventListener, removeEventListener } from '../dom';
|
|
5
4
|
|
|
6
5
|
// /**
|
|
@@ -143,7 +142,7 @@
|
|
|
143
142
|
// });
|
|
144
143
|
|
|
145
144
|
// return (
|
|
146
|
-
// <div ref={ref} class={
|
|
145
|
+
// <div ref={ref} class={combineClass('pulldown', thisProps.class)} {...restProps}>
|
|
147
146
|
// {props.children ||
|
|
148
147
|
// pulldownChildren ||
|
|
149
148
|
// (pulldownChildren = (
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { JSX } from '../jsx';
|
|
2
|
+
import { combineClass, splitProps } from '../reactive';
|
|
3
|
+
|
|
4
|
+
export const TextBox = (props?: JSX.SvgSVGAttributes<never>) => {
|
|
5
|
+
let [thisProps, restProps] = splitProps(props, ['class']);
|
|
6
|
+
|
|
7
|
+
return <input type="text" class={combineClass('textbox', thisProps.class)} {...restProps}></input>;
|
|
8
|
+
};
|
package/src/dom.ts
CHANGED
|
@@ -44,50 +44,52 @@ if (isBrowser) {
|
|
|
44
44
|
|
|
45
45
|
root.addEventListener('wheel', disableGlobalScroll, { passive: false });
|
|
46
46
|
root.addEventListener('touchmove', disableGlobalScroll, { passive: false });
|
|
47
|
-
}
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
*/
|
|
52
|
-
export const showMaskLayer = (onclick?: () => void) => {
|
|
53
|
-
if (isBrowser) {
|
|
54
|
-
if (!maskLayers.length) {
|
|
55
|
-
if (!maskLayer) {
|
|
56
|
-
let div = (maskLayer = document.createElement('div'));
|
|
48
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
49
|
+
let div = (maskLayer = document.createElement('div'));
|
|
57
50
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
div.className = 'mask-layer';
|
|
52
|
+
div.style.cssText =
|
|
53
|
+
'position:fixed;top:0;left:0;right:0;bottom:0;display:none;background:rgba(0,0,0,0.4);z-index:8';
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
// 点击遮罩层方法
|
|
56
|
+
div.addEventListener('click', (event) => {
|
|
57
|
+
let callbackFn = maskLayers[maskLayers.length - 1];
|
|
65
58
|
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
callbackFn && callbackFn(event);
|
|
60
|
+
});
|
|
68
61
|
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
document.body.appendChild(div);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
71
65
|
|
|
66
|
+
/**
|
|
67
|
+
* 空函数
|
|
68
|
+
*/
|
|
69
|
+
const noop = () => {};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 显示遮罩层
|
|
73
|
+
*/
|
|
74
|
+
export const showMaskLayer = isBrowser
|
|
75
|
+
? (onclick?: () => void) => {
|
|
72
76
|
maskLayer.style.display = 'block';
|
|
77
|
+
maskLayers.push(onclick);
|
|
73
78
|
}
|
|
74
|
-
|
|
75
|
-
maskLayers.push(onclick);
|
|
76
|
-
}
|
|
77
|
-
};
|
|
79
|
+
: noop;
|
|
78
80
|
|
|
79
81
|
/**
|
|
80
82
|
* 隐藏遮罩层
|
|
81
83
|
*/
|
|
82
|
-
export const hideMaskLayer =
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
export const hideMaskLayer = isBrowser
|
|
85
|
+
? () => {
|
|
86
|
+
maskLayers.pop();
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
if (!maskLayers.length) {
|
|
89
|
+
maskLayer.style.display = 'none';
|
|
90
|
+
}
|
|
88
91
|
}
|
|
89
|
-
|
|
90
|
-
};
|
|
92
|
+
: noop;
|
|
91
93
|
|
|
92
94
|
const autocloseList = [];
|
|
93
95
|
|
|
@@ -117,21 +119,35 @@ export const unregisterAutoClose = (onclose: () => void) => {
|
|
|
117
119
|
};
|
|
118
120
|
|
|
119
121
|
/**
|
|
120
|
-
*
|
|
122
|
+
* 是否禁止自动关闭
|
|
121
123
|
*/
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
let disableAutoClose = false;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 开始侦听自动关闭事件
|
|
128
|
+
*/
|
|
129
|
+
export const startAutoCloseEvent = isBrowser
|
|
130
|
+
? () => {
|
|
131
|
+
// 延迟注册解决 solidjs 事件顺序问题
|
|
132
|
+
setTimeout(() => {
|
|
133
|
+
document.addEventListener('pointerdown', () => {
|
|
134
|
+
if (disableAutoClose) {
|
|
135
|
+
disableAutoClose = false;
|
|
136
|
+
} else {
|
|
137
|
+
for (let i = 0, l = autocloseList.length; i < l; i++) {
|
|
138
|
+
autocloseList[i]();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
126
143
|
}
|
|
127
|
-
|
|
128
|
-
};
|
|
144
|
+
: noop;
|
|
129
145
|
|
|
130
146
|
/**
|
|
131
147
|
* 禁止自动关闭事件
|
|
132
148
|
*/
|
|
133
149
|
export const disableAutoCloseEvent = {
|
|
134
|
-
onpointerdown: (
|
|
135
|
-
|
|
150
|
+
onpointerdown: () => {
|
|
151
|
+
disableAutoClose = true;
|
|
136
152
|
},
|
|
137
153
|
};
|
package/src/http.ts
CHANGED
|
@@ -10,7 +10,7 @@ export interface ResponseResult {
|
|
|
10
10
|
/**
|
|
11
11
|
* 自定义响应结果(type === 'custom' 时有效)
|
|
12
12
|
*/
|
|
13
|
-
custom?:
|
|
13
|
+
custom?: any;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -25,7 +25,7 @@ export const httpInterceptor = {
|
|
|
25
25
|
/**
|
|
26
26
|
* 响应拦截(返回 Promise true 表示需要重新发送请求,返回 Promise false 抛出默认异常)
|
|
27
27
|
*/
|
|
28
|
-
response: (() => {}) as (response: Response, options?: RequestInit) => ResponseResult | void,
|
|
28
|
+
response: (() => {}) as (response: Response, options?: RequestInit) => Promise<ResponseResult> | void,
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -73,30 +73,34 @@ Object.defineProperty(Promise.prototype, 'data', {
|
|
|
73
73
|
},
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
+
const respondDefault = (response: Response, json: boolean) => {
|
|
77
|
+
// 失败返回异常
|
|
78
|
+
return response.ok
|
|
79
|
+
? json
|
|
80
|
+
? response.json()
|
|
81
|
+
: response
|
|
82
|
+
: Promise.reject(response.status + ' ' + response.statusText);
|
|
83
|
+
};
|
|
84
|
+
|
|
76
85
|
const handleResponse = (response: Response, url: string, json: boolean, options?: RequestInit) => {
|
|
77
86
|
// 响应拦截
|
|
78
87
|
let result = httpInterceptor.response(response, options);
|
|
79
88
|
|
|
80
89
|
// 返回了异步对象
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
break;
|
|
90
|
+
return result
|
|
91
|
+
? result.then((result) => {
|
|
92
|
+
switch (result.type) {
|
|
93
|
+
case 'custom':
|
|
94
|
+
return result.custom || respondDefault(response, json);
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
}
|
|
96
|
+
case 'retry':
|
|
97
|
+
return sendInternal(url, json, options);
|
|
93
98
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
: Promise.reject(response.status + ' ' + response.statusText);
|
|
99
|
+
default:
|
|
100
|
+
return respondDefault(response, json);
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
: respondDefault(response, json);
|
|
100
104
|
};
|
|
101
105
|
|
|
102
106
|
/**
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
},
|
|
14
14
|
"Form": {
|
|
15
15
|
"Required": "不能为空",
|
|
16
|
-
"NotLessThan": "不能小于 ${
|
|
17
|
-
"NotGreaterThan": "不能大于 ${
|
|
16
|
+
"NotLessThan": "不能小于 ${value}",
|
|
17
|
+
"NotGreaterThan": "不能大于 ${value}",
|
|
18
18
|
"Between": "必须在 ${min} -> ${max} 之间",
|
|
19
|
-
"NotDate": "
|
|
19
|
+
"NotDate": "\"${value}\" 不是一个有效的日期值"
|
|
20
20
|
}
|
|
21
21
|
}
|
package/src/index.ts
CHANGED
|
@@ -13,8 +13,12 @@ export * from './components/If';
|
|
|
13
13
|
export * from './components/Switch';
|
|
14
14
|
export * from './components/For';
|
|
15
15
|
export * from './components/Icon';
|
|
16
|
-
export * from './components/
|
|
16
|
+
export * from './components/TextBox';
|
|
17
|
+
export * from './components/Button';
|
|
17
18
|
export * from './components/ComboBox';
|
|
19
|
+
export * from './components/Canlendar';
|
|
20
|
+
export * from './components/DatePicker';
|
|
21
|
+
export * from './components/CollapsiblePanel';
|
|
18
22
|
export * from './components/Carousel';
|
|
19
23
|
export * from './components/KeepAlive';
|
|
20
24
|
export * from './components/Dialog';
|
package/src/reactive.ts
CHANGED
|
@@ -299,6 +299,15 @@ export const toRaw = <T>(proxy: T): T => {
|
|
|
299
299
|
return (proxy && proxy.__raw__) || proxy;
|
|
300
300
|
};
|
|
301
301
|
|
|
302
|
+
/**
|
|
303
|
+
* 合并 class
|
|
304
|
+
*
|
|
305
|
+
* @param classList class 列表
|
|
306
|
+
*/
|
|
307
|
+
export const combineClass = (...classList: (string | null | void)[]) => {
|
|
308
|
+
return classList.filter((item) => item).join(' ');
|
|
309
|
+
};
|
|
310
|
+
|
|
302
311
|
/**
|
|
303
312
|
* 观测响应式属性变化
|
|
304
313
|
*
|
package/demo/App.tsx
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { reactive } from '../src/reactive';
|
|
2
|
-
import { CanlendarPage } from './pages/Canlendar';
|
|
3
|
-
import { ComboBoxPage } from './pages/ComboBox';
|
|
4
|
-
import { FormPage } from './pages/Form';
|
|
5
|
-
|
|
6
|
-
const Test = (props: { value: number; text: string }) => {
|
|
7
|
-
return (
|
|
8
|
-
<div>
|
|
9
|
-
<span>{props.value}</span>
|
|
10
|
-
<span>{props.text}</span>
|
|
11
|
-
</div>
|
|
12
|
-
);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export const App = () => {
|
|
16
|
-
const state = reactive({
|
|
17
|
-
value: 111,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
const a = { text: '222' };
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<div>
|
|
24
|
-
<CanlendarPage></CanlendarPage>
|
|
25
|
-
<ComboBoxPage></ComboBoxPage>
|
|
26
|
-
<FormPage></FormPage>
|
|
27
|
-
<Test value={state.value} text={'222' + a.text}></Test>
|
|
28
|
-
<button onclick={() => (state.value = Math.random())}></button>
|
|
29
|
-
</div>
|
|
30
|
-
);
|
|
31
|
-
};
|
package/demo/main.ts
DELETED
package/demo/pages/ComboBox.tsx
DELETED
package/demo/pages/Form.tsx
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { reactive } from '../../src/reactive';
|
|
2
|
-
import { For } from '../../src/components/For';
|
|
3
|
-
import { Form, FormItem } from '../../src/components/Form';
|
|
4
|
-
|
|
5
|
-
export const FormPage = () => {
|
|
6
|
-
const state = reactive({
|
|
7
|
-
align: 'right' as 'right' | 'left',
|
|
8
|
-
width: '100px',
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Form data={{}} rules={{}} align={state.align} labelWidth={state.width}>
|
|
13
|
-
<FormItem field="a" label="111">
|
|
14
|
-
<input></input>
|
|
15
|
-
</FormItem>
|
|
16
|
-
<FormItem
|
|
17
|
-
field="b"
|
|
18
|
-
label={
|
|
19
|
-
<>
|
|
20
|
-
<span>123</span>
|
|
21
|
-
<span>456</span>
|
|
22
|
-
</>
|
|
23
|
-
}
|
|
24
|
-
>
|
|
25
|
-
<input></input>
|
|
26
|
-
</FormItem>
|
|
27
|
-
<button type="button" onclick={() => (state.align = state.align === 'left' ? 'right' : 'left')}>
|
|
28
|
-
align
|
|
29
|
-
</button>
|
|
30
|
-
</Form>
|
|
31
|
-
);
|
|
32
|
-
};
|
package/icons/build.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import { fileURLToPath } from 'url';
|
|
3
|
-
|
|
4
|
-
import { loadIconFile, loadIconsDirectory, saveIconsModule, saveIconsToHtml } from 'cdui-js/build/icons';
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = path.dirname(__filename);
|
|
8
|
-
|
|
9
|
-
const icons = [
|
|
10
|
-
// 加载 cdui-js/icons 下的图标
|
|
11
|
-
loadIconsDirectory(path.join(__dirname, '../../../node_modules/cdui-js/icons'), 'both'),
|
|
12
|
-
|
|
13
|
-
loadIconFile(path.join(__dirname, 'logo.svg')),
|
|
14
|
-
loadIconsDirectory(path.join(__dirname, 'common/both')),
|
|
15
|
-
loadIconsDirectory(path.join(__dirname, 'common/stroke'), 'stroke'),
|
|
16
|
-
loadIconsDirectory(path.join(__dirname, 'header'), 'stroke'),
|
|
17
|
-
|
|
18
|
-
loadIconsDirectory(path.join(__dirname, 'menu'), 'both'),
|
|
19
|
-
loadIconsDirectory(path.join(__dirname, 'menu/color')),
|
|
20
|
-
|
|
21
|
-
loadIconsDirectory(path.join(__dirname, 'my'), 'both'),
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
saveIconsToHtml(path.join(__dirname, '../index.html'), icons.join('\n'));
|
|
File without changes
|