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/demo/src/main.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { reactive } from '../../../src/reactive';
|
|
2
|
+
import { For } from '../../../src/components/For';
|
|
3
|
+
import { TextBox } from '../../../src/components/TextBox';
|
|
4
|
+
import { Form, FormApi, FormItem, ValidateRules } from '../../../src/components/Form';
|
|
5
|
+
|
|
6
|
+
const rules: ValidateRules = {
|
|
7
|
+
a: {
|
|
8
|
+
type: 'number',
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const FormPage = () => {
|
|
13
|
+
const state = reactive({
|
|
14
|
+
align: 'left' as 'top' | 'left',
|
|
15
|
+
labelWidth: '60px',
|
|
16
|
+
items: [
|
|
17
|
+
{
|
|
18
|
+
field: 'a',
|
|
19
|
+
label: '111',
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
field: 'b',
|
|
24
|
+
label: '222',
|
|
25
|
+
required: true,
|
|
26
|
+
labelWidth: '100px',
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
let form: FormApi;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Form data={{}} rules={{}} align={state.align} labelWidth={state.labelWidth} api={(api) => (form = api)}>
|
|
35
|
+
<For each={state.items}>
|
|
36
|
+
{(item) => (
|
|
37
|
+
<FormItem field={item.field} label={item.label} required={item.required}>
|
|
38
|
+
<TextBox></TextBox>
|
|
39
|
+
</FormItem>
|
|
40
|
+
)}
|
|
41
|
+
</For>
|
|
42
|
+
<button
|
|
43
|
+
type="button"
|
|
44
|
+
onclick={() =>
|
|
45
|
+
state.items.push({
|
|
46
|
+
field: '?',
|
|
47
|
+
label: '???',
|
|
48
|
+
required: false,
|
|
49
|
+
labelWidth: '100px',
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
>
|
|
53
|
+
append
|
|
54
|
+
</button>
|
|
55
|
+
<button type="button" onclick={() => (state.align = state.align === 'left' ? 'top' : 'left')}>
|
|
56
|
+
align
|
|
57
|
+
</button>
|
|
58
|
+
<button type="button" onclick={() => (state.labelWidth = parseInt(state.labelWidth) + 10 + 'px')}>
|
|
59
|
+
labelWidth
|
|
60
|
+
</button>
|
|
61
|
+
<button type="button" onclick={() => form.validate()}>
|
|
62
|
+
validate
|
|
63
|
+
</button>
|
|
64
|
+
</Form>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
@@ -2,7 +2,7 @@ import path from 'path';
|
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
3
|
import { defineConfig } from 'vite';
|
|
4
4
|
|
|
5
|
-
import VitePlugin from '
|
|
5
|
+
import VitePlugin from '../vite-plugin.js';
|
|
6
6
|
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
|
@@ -32,7 +32,7 @@ export default defineConfig({
|
|
|
32
32
|
build: {
|
|
33
33
|
// target: 'es2015',
|
|
34
34
|
modulePreload: false,
|
|
35
|
-
outDir: path.join(__dirname, '
|
|
35
|
+
outDir: path.join(__dirname, 'dist'),
|
|
36
36
|
emptyOutDir: true,
|
|
37
37
|
rollupOptions: {
|
|
38
38
|
input: path.join(__dirname, 'index.html'),
|
package/icons/backward.svg
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<svg width="
|
|
2
|
-
<path d="
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M10.3661 2.72003L6.01942 7.0667C5.50609 7.58003 5.50609 8.42003 6.01942 8.93336L10.3661 13.28" stroke="#1B212D" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
3
|
</svg>
|
package/icons/close.svg
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<svg viewBox="0 0
|
|
2
|
-
<path d="
|
|
3
|
-
</svg>
|
|
1
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M6.16709 17.8331L17.8333 6.16689M17.8333 17.8331L6.16709 6.16689" stroke="#262626" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
|
+
</svg>
|
package/icons/dropdown.svg
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<svg width="16" height="
|
|
2
|
-
<path d="
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M2.72 5.63428L7.06667 9.98094C7.58 10.4943 8.42 10.4943 8.93333 9.98094L13.28 5.63428" stroke="#1B212D" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
3
|
</svg>
|
package/icons/forward.svg
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
<svg width="
|
|
2
|
-
<path d="M5.
|
|
1
|
+
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M5.63391 2.72003L9.98058 7.0667C10.4939 7.58003 10.4939 8.42003 9.98058 8.93336L5.63391 13.28" stroke="#1B212D" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
3
|
</svg>
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cdui-js",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"bin": {
|
|
7
7
|
"cdui-js": "./cli/bin.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"dev": "vite --config vite.config.ts"
|
|
10
|
+
"dev": "vite --config demo/vite.config.ts",
|
|
11
|
+
"icons": "npx tsx demo/icons/build.ts",
|
|
12
|
+
"css": "npx tsx demo/css/build.ts"
|
|
11
13
|
},
|
|
12
14
|
"dependencies": {
|
|
13
15
|
"chalk": "^5.6.2",
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
import { createSignal, splitProps } from '../reactive';
|
|
1
|
+
import { createSignal, combineClass, splitProps } from '../reactive';
|
|
2
2
|
|
|
3
3
|
import { JSX } from '../jsx';
|
|
4
4
|
import { Canleandar as i18n } from '../i18n';
|
|
5
5
|
import { replaceTemplate } from '../template';
|
|
6
6
|
import { For } from './For';
|
|
7
7
|
|
|
8
|
-
// const equalsDay = ( today: Date,
|
|
9
|
-
// selected?: Date,)
|
|
10
|
-
|
|
11
8
|
// 渲染日期项
|
|
12
9
|
const renderDates = (
|
|
13
10
|
items: string[],
|
|
@@ -111,28 +108,16 @@ const renderItems = (
|
|
|
111
108
|
return items.join('');
|
|
112
109
|
};
|
|
113
110
|
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
fill="none"
|
|
122
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
123
|
-
onclick={props.onclick}
|
|
124
|
-
>
|
|
125
|
-
<path
|
|
126
|
-
d="M10.3661 2.72003L6.01942 7.0667C5.50609 7.58003 5.50609 8.42003 6.01942 8.93336L10.3661 13.28"
|
|
127
|
-
stroke-miterlimit="10"
|
|
128
|
-
stroke-linecap="round"
|
|
129
|
-
stroke-linejoin="round"
|
|
130
|
-
/>
|
|
131
|
-
</svg>
|
|
132
|
-
);
|
|
111
|
+
const switchMonth = (value: Date, offset: 1 | -1) => {
|
|
112
|
+
let date = new Date(value.getTime());
|
|
113
|
+
let month = value.getMonth();
|
|
114
|
+
|
|
115
|
+
date.setMonth(month + offset);
|
|
116
|
+
|
|
117
|
+
return date;
|
|
133
118
|
};
|
|
134
119
|
|
|
135
|
-
const parseDate = (value: Date | string | number) => {
|
|
120
|
+
export const parseDate = (value: Date | string | number) => {
|
|
136
121
|
if (value) {
|
|
137
122
|
switch (typeof value) {
|
|
138
123
|
case 'number':
|
|
@@ -153,15 +138,6 @@ const formatMonth = (value: Date) => {
|
|
|
153
138
|
return month > 9 ? month : '0' + month;
|
|
154
139
|
};
|
|
155
140
|
|
|
156
|
-
const switchMonth = (value: Date, offset: 1 | -1) => {
|
|
157
|
-
let date = new Date(value.getTime());
|
|
158
|
-
let month = value.getMonth();
|
|
159
|
-
|
|
160
|
-
date.setMonth(month + offset);
|
|
161
|
-
|
|
162
|
-
return date;
|
|
163
|
-
};
|
|
164
|
-
|
|
165
141
|
export const Canlendar = (
|
|
166
142
|
props: Omit<JSX.HTMLAttributes<never>, 'children'> & {
|
|
167
143
|
/**
|
|
@@ -183,16 +159,21 @@ export const Canlendar = (
|
|
|
183
159
|
let domMonth: HTMLElement;
|
|
184
160
|
let domBody: HTMLElement;
|
|
185
161
|
|
|
186
|
-
const [
|
|
162
|
+
const [selectedDate, setSelectedDate] = createSignal(parseDate(thisProps.value));
|
|
163
|
+
const [showDate, setShowDate] = createSignal(selectedDate() || new Date());
|
|
187
164
|
|
|
188
165
|
return (
|
|
189
|
-
<div class={
|
|
166
|
+
<div class={combineClass('canlendar', thisProps.class)} {...restProps}>
|
|
190
167
|
<div class="canlendar-header">
|
|
191
168
|
<div ref={domMonth as any} class="canlendar-month">
|
|
192
|
-
{replaceTemplate(i18n.Month,
|
|
169
|
+
{replaceTemplate(i18n.Month, showDate().getFullYear(), formatMonth(showDate()))}
|
|
193
170
|
</div>
|
|
194
|
-
<
|
|
195
|
-
|
|
171
|
+
<svg class="icon icon-s" aria-hidden={true} onclick={() => setShowDate(switchMonth(showDate(), -1))}>
|
|
172
|
+
<use href="#icon-backward"></use>
|
|
173
|
+
</svg>
|
|
174
|
+
<svg class="icon icon-s" aria-hidden={true} onclick={() => setShowDate(switchMonth(showDate(), 1))}>
|
|
175
|
+
<use href="#icon-forward"></use>
|
|
176
|
+
</svg>
|
|
196
177
|
</div>
|
|
197
178
|
<div class="canlendar-weeks">
|
|
198
179
|
<For each={i18n.Weeks}>{(item) => <span>{item}</span>}</For>
|
|
@@ -209,17 +190,14 @@ export const Canlendar = (
|
|
|
209
190
|
|
|
210
191
|
if (dom !== target) {
|
|
211
192
|
date = date.split('|');
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (dom) {
|
|
215
|
-
dom.classList.remove('selected');
|
|
216
|
-
}
|
|
193
|
+
date = new Date(date[0] | 0, date[1] | 0, date[2] | 0);
|
|
217
194
|
|
|
218
|
-
|
|
195
|
+
setSelectedDate(date);
|
|
196
|
+
onValueChange(date);
|
|
219
197
|
}
|
|
220
198
|
}
|
|
221
199
|
}}
|
|
222
|
-
innerHTML={renderItems(
|
|
200
|
+
innerHTML={renderItems(showDate(), selectedDate(), thisProps.disableDate)}
|
|
223
201
|
></div>
|
|
224
202
|
</div>
|
|
225
203
|
);
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import { createEffect, createMemo, createSignal, For, onCleanup, onMount, splitProps } from 'solid-js';
|
|
2
|
-
|
|
3
1
|
import { JSX } from '../jsx';
|
|
4
2
|
import { isBrowser } from '../dom';
|
|
5
3
|
import { animateScrollIntoView } from '../animate-scroll-to';
|
|
6
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
createEffect,
|
|
6
|
+
createMemo,
|
|
7
|
+
createSignal,
|
|
8
|
+
combineClass,
|
|
9
|
+
defineProperty,
|
|
10
|
+
onCleanup,
|
|
11
|
+
onMount,
|
|
12
|
+
splitProps,
|
|
13
|
+
} from '../reactive';
|
|
14
|
+
|
|
15
|
+
import { For } from './For';
|
|
7
16
|
import { Icon } from './Icon';
|
|
8
17
|
|
|
9
18
|
const CLASS_NAME = 'carousel-vertical';
|
|
@@ -269,7 +278,7 @@ export const Carousel = <T, U extends JSX.Element>(
|
|
|
269
278
|
});
|
|
270
279
|
|
|
271
280
|
return (
|
|
272
|
-
<div ref={ref as any} class={
|
|
281
|
+
<div ref={ref as any} class={combineClass('carousel scrollbar-hidden', thisProps.class)} {...restProps}>
|
|
273
282
|
<For each={fillItems(thisProps.each)}>{thisProps.children}</For>
|
|
274
283
|
</div>
|
|
275
284
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createSignal, splitProps } from 'solid-js';
|
|
2
2
|
|
|
3
3
|
import { JSX } from '../jsx';
|
|
4
|
-
import { defineProperty } from '../reactive';
|
|
4
|
+
import { combineClass, defineProperty } from '../reactive';
|
|
5
5
|
|
|
6
6
|
const COLLAPSED_CLASS = 'collapsed';
|
|
7
7
|
|
|
@@ -130,9 +130,7 @@ export const CollapsiblePanel = (
|
|
|
130
130
|
return (
|
|
131
131
|
<div
|
|
132
132
|
ref={ref as any}
|
|
133
|
-
class={
|
|
134
|
-
.filter((item) => item)
|
|
135
|
-
.join(' ')}
|
|
133
|
+
class={combineClass('collapsed-panel', thisProps.collapsed && COLLAPSED_CLASS, thisProps.class)}
|
|
136
134
|
{...restProps}
|
|
137
135
|
></div>
|
|
138
136
|
);
|
|
@@ -1,162 +1,66 @@
|
|
|
1
|
-
import { splitProps } from '../reactive';
|
|
2
1
|
import { JSX } from '../jsx';
|
|
3
|
-
|
|
4
|
-
import { disableAutoCloseEvent
|
|
5
|
-
|
|
6
|
-
const POPUP_TOP_CLASS = 'combobox-popup-top';
|
|
7
|
-
const POPUP_RIGHT_CLASS = 'combobox-popup-right';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 当前弹出层
|
|
11
|
-
*/
|
|
12
|
-
let currentPopup: ComboBoxApi;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* 关闭当前弹出层
|
|
16
|
-
*/
|
|
17
|
-
export const closePopup = () => {
|
|
18
|
-
currentPopup && currentPopup.closePupup();
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* 是否使用下拉动画
|
|
23
|
-
*/
|
|
24
|
-
export let useDropdownTransition = true;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 设置是否使用下拉动画
|
|
28
|
-
*
|
|
29
|
-
* @param use 是否使用
|
|
30
|
-
*/
|
|
31
|
-
export const setUseDropdownTransition = (use: boolean) => {
|
|
32
|
-
useDropdownTransition = use;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
// 注册点击关闭弹出层的方法
|
|
36
|
-
registerAutoClose(closePopup);
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* 下拉框组件外部访问接口
|
|
40
|
-
*/
|
|
41
|
-
export interface ComboBoxApi {
|
|
42
|
-
/**
|
|
43
|
-
* 打开弹出框
|
|
44
|
-
*/
|
|
45
|
-
openPopup(): void;
|
|
46
|
-
/**
|
|
47
|
-
* 关闭弹出框
|
|
48
|
-
*/
|
|
49
|
-
closePupup(): void;
|
|
50
|
-
}
|
|
2
|
+
import { combineClass, splitProps } from '../reactive';
|
|
3
|
+
import { disableAutoCloseEvent } from '../dom';
|
|
4
|
+
import { Popup, PopupApi, PopupProps } from './Popup';
|
|
51
5
|
|
|
52
6
|
/**
|
|
53
7
|
* 下拉框组件
|
|
54
8
|
*/
|
|
55
|
-
export const ComboBox =
|
|
56
|
-
props?: JSX.HTMLAttributes<never> &
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
9
|
+
export const ComboBox = (
|
|
10
|
+
props?: JSX.HTMLAttributes<never> &
|
|
11
|
+
PopupProps & {
|
|
12
|
+
/**
|
|
13
|
+
* 值
|
|
14
|
+
*/
|
|
15
|
+
value?: string;
|
|
16
|
+
/**
|
|
17
|
+
* 是否只读
|
|
18
|
+
*/
|
|
19
|
+
readonly?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* 获取焦点时是否自动弹出
|
|
22
|
+
*/
|
|
23
|
+
popupOnFocus?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* 弹出层属性
|
|
26
|
+
*/
|
|
27
|
+
popup?: Omit<JSX.HTMLAttributes<never>, 'children'>;
|
|
28
|
+
},
|
|
70
29
|
) => {
|
|
71
|
-
let [thisProps, restProps] = splitProps(props, [
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (currentPopup) {
|
|
87
|
-
currentPopup.closePupup();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// 设置当前弹出层
|
|
91
|
-
currentPopup = api;
|
|
92
|
-
|
|
93
|
-
style.height = 'auto';
|
|
94
|
-
style.display = 'block';
|
|
95
|
-
|
|
96
|
-
let height = popup.offsetHeight;
|
|
97
|
-
|
|
98
|
-
if (windowHeight - rect.top - rect.height < height + 4 && rect.top >= height) {
|
|
99
|
-
classList.add(POPUP_TOP_CLASS);
|
|
100
|
-
} else {
|
|
101
|
-
classList.remove(POPUP_TOP_CLASS);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (windowWidth - rect.left - rect.width >= 0) {
|
|
105
|
-
classList.add(POPUP_RIGHT_CLASS);
|
|
106
|
-
} else {
|
|
107
|
-
classList.remove(POPUP_RIGHT_CLASS);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (useDropdownTransition) {
|
|
111
|
-
style.height = '0';
|
|
112
|
-
|
|
113
|
-
setTimeout(() => {
|
|
114
|
-
style.height = height + 'px';
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
} else {
|
|
118
|
-
currentPopup = null;
|
|
119
|
-
|
|
120
|
-
if (useDropdownTransition) {
|
|
121
|
-
style.height = popup.offsetHeight + 'px';
|
|
122
|
-
|
|
123
|
-
setTimeout(() => {
|
|
124
|
-
style.height = '0';
|
|
125
|
-
});
|
|
126
|
-
} else {
|
|
127
|
-
style.display = 'none';
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
event && event.stopPropagation();
|
|
30
|
+
let [thisProps, restProps] = splitProps(props, [
|
|
31
|
+
'class',
|
|
32
|
+
'value',
|
|
33
|
+
'readonly',
|
|
34
|
+
'popupOnFocus',
|
|
35
|
+
'popup',
|
|
36
|
+
'onPopup',
|
|
37
|
+
'api',
|
|
38
|
+
'children',
|
|
39
|
+
]);
|
|
40
|
+
let popup: PopupApi;
|
|
41
|
+
|
|
42
|
+
const initApi = (api) => {
|
|
43
|
+
popup = api;
|
|
44
|
+
thisProps.api && thisProps.api(popup);
|
|
133
45
|
};
|
|
134
46
|
|
|
135
|
-
const api = {
|
|
136
|
-
openPopup: () => opened || toggle(),
|
|
137
|
-
closePupup: () => opened && toggle(),
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// 初始化外部调用接口
|
|
141
|
-
props.api && props.api(api);
|
|
142
|
-
|
|
143
47
|
return (
|
|
144
|
-
<div class={
|
|
145
|
-
<div class="combobox-host" {...disableAutoCloseEvent}
|
|
146
|
-
<input
|
|
147
|
-
|
|
48
|
+
<div class={combineClass('combobox', thisProps.class)} {...restProps}>
|
|
49
|
+
<div class="combobox-host" {...disableAutoCloseEvent}>
|
|
50
|
+
<input
|
|
51
|
+
class="combobox-input"
|
|
52
|
+
value={thisProps.value || ''}
|
|
53
|
+
readonly={thisProps.readonly}
|
|
54
|
+
onfocus={() => thisProps.popupOnFocus && popup.openPopup()}
|
|
55
|
+
onclick={() => thisProps.readonly && !thisProps.popupOnFocus && popup.togglePopup()}
|
|
56
|
+
></input>
|
|
57
|
+
<svg class="icon icon-s" aria-hidden={true} onclick={() => popup.togglePopup()}>
|
|
148
58
|
<use href="#icon-dropdown"></use>
|
|
149
59
|
</svg>
|
|
150
60
|
</div>
|
|
151
|
-
<
|
|
152
|
-
ref={popup as any}
|
|
153
|
-
class="combobox-popup"
|
|
154
|
-
style={{ display: 'none' }}
|
|
155
|
-
{...disableAutoCloseEvent}
|
|
156
|
-
ontransitionend={() => opened || (popup.style.display = 'none')}
|
|
157
|
-
>
|
|
61
|
+
<Popup api={initApi} onPopup={thisProps.onPopup} {...thisProps.popup}>
|
|
158
62
|
{thisProps.children}
|
|
159
|
-
</
|
|
63
|
+
</Popup>
|
|
160
64
|
</div>
|
|
161
65
|
);
|
|
162
66
|
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { JSX } from '../jsx';
|
|
2
|
+
import { combineClass, createSignal, splitProps } from '../reactive';
|
|
3
|
+
import { disableAutoCloseEvent } from '../dom';
|
|
4
|
+
import { For } from './For';
|
|
5
|
+
import { Popup, PopupApi } from './Popup';
|
|
6
|
+
import { parseDate } from './Canlendar';
|
|
7
|
+
|
|
8
|
+
const formatDate = (date: Date, format: string) => {
|
|
9
|
+
return date ? date.toLocaleString() : '';
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const showPopup = () => {};
|
|
13
|
+
|
|
14
|
+
const MobileTouchScroll = (props: { items: (number | string)[] }) => {
|
|
15
|
+
return (
|
|
16
|
+
<div>
|
|
17
|
+
<For each={props.items}>{(item) => <div>{item}</div>}</For>
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const formatMonth = (value: Date) => {
|
|
23
|
+
let month = value.getMonth() + 1;
|
|
24
|
+
|
|
25
|
+
return month > 9 ? month : '0' + month;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// const computeMobileList = (value: Date) => {
|
|
29
|
+
// let year = value.getFullYear();
|
|
30
|
+
// let month = value.getMonth() + 1;
|
|
31
|
+
// let date = value.getDate();
|
|
32
|
+
|
|
33
|
+
// return [
|
|
34
|
+
// year > 5 ? [year - 2, year - 1, year, year + 1, year + 2]: [1,2,3,4,5],
|
|
35
|
+
// [formatMonth(month - 2), ]
|
|
36
|
+
// ];
|
|
37
|
+
// };
|
|
38
|
+
|
|
39
|
+
// const MobileDatePicker = (yearList: number[], monthList: string[], dateList: string[]) => {
|
|
40
|
+
// return (
|
|
41
|
+
// <div>
|
|
42
|
+
// <MobileTouchScroll items={yearList}></MobileTouchScroll>
|
|
43
|
+
// <MobileTouchScroll items={monthList}></MobileTouchScroll>
|
|
44
|
+
// <MobileTouchScroll items={dateList}></MobileTouchScroll>
|
|
45
|
+
// </div>
|
|
46
|
+
// );
|
|
47
|
+
// };
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 日期选择组件
|
|
51
|
+
*/
|
|
52
|
+
export const DatePicker = (
|
|
53
|
+
props?: JSX.HTMLAttributes<never> & {
|
|
54
|
+
/**
|
|
55
|
+
* 值
|
|
56
|
+
*/
|
|
57
|
+
value?: string | number | Date;
|
|
58
|
+
/**
|
|
59
|
+
* 日期格式
|
|
60
|
+
*/
|
|
61
|
+
format?: string;
|
|
62
|
+
/**
|
|
63
|
+
* 是否只读
|
|
64
|
+
*/
|
|
65
|
+
readonly?: boolean;
|
|
66
|
+
},
|
|
67
|
+
) => {
|
|
68
|
+
let [thisProps, restProps] = splitProps(props, ['class', 'value', 'readonly', 'format', 'children']);
|
|
69
|
+
let popup: PopupApi;
|
|
70
|
+
|
|
71
|
+
const [value, setValue] = createSignal(thisProps.value && parseDate(thisProps.value));
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div class={combineClass('datepicker', thisProps.class)} {...restProps}>
|
|
75
|
+
<div class="datepicker-host" {...disableAutoCloseEvent}>
|
|
76
|
+
<input
|
|
77
|
+
class="datepicker-input"
|
|
78
|
+
value={formatDate(value(), thisProps.format)}
|
|
79
|
+
readonly={thisProps.readonly}
|
|
80
|
+
onclick={() => thisProps.readonly && popup.togglePopup()}
|
|
81
|
+
></input>
|
|
82
|
+
<svg class="icon icon-s" aria-hidden={true} onclick={() => popup.togglePopup()}>
|
|
83
|
+
<use href="#icon-dropdown"></use>
|
|
84
|
+
</svg>
|
|
85
|
+
</div>
|
|
86
|
+
<Popup api={(api) => (popup = api)} onPopup={() => showPopup()}>
|
|
87
|
+
{thisProps.children}
|
|
88
|
+
</Popup>
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
};
|
package/src/components/Dialog.ts
CHANGED