cdui-js 1.0.26 → 1.0.28
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/css/mobile-datepicker.css +75 -75
- package/demo/src/App.tsx +99 -14
- package/demo/src/pages/Canlendar.tsx +1 -1
- package/package.json +1 -1
- package/pnpm-workspace.yaml +2 -0
- package/src/components/Switch.ts +2 -2
- package/src/location.ts +45 -34
- package/src/reactive.ts +5 -19
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
.mobile-date-picker {
|
|
2
|
-
display: flex;
|
|
3
|
-
flex-direction: row;
|
|
4
|
-
width: 100%;
|
|
5
|
-
min-height: calc(44px * 5);
|
|
6
|
-
position: relative;
|
|
7
|
-
box-sizing: border-box;
|
|
8
|
-
user-select: none;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.mobile-date-picker-column {
|
|
12
|
-
flex: 1;
|
|
13
|
-
position: relative;
|
|
14
|
-
min-width: 0;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.mobile-date-picker-column::before {
|
|
18
|
-
content: '';
|
|
19
|
-
pointer-events: none;
|
|
20
|
-
position: absolute;
|
|
21
|
-
left: 0;
|
|
22
|
-
right: 0;
|
|
23
|
-
top: 0;
|
|
24
|
-
bottom: 0;
|
|
25
|
-
z-index: 1;
|
|
26
|
-
background: linear-gradient(
|
|
27
|
-
to bottom,
|
|
28
|
-
rgba(255, 255, 255, 0.95) 0%,
|
|
29
|
-
rgba(255, 255, 255, 0) calc(50% - 22px)
|
|
30
|
-
),
|
|
31
|
-
linear-gradient(
|
|
32
|
-
to top,
|
|
33
|
-
rgba(255, 255, 255, 0.95) 0%,
|
|
34
|
-
rgba(255, 255, 255, 0) calc(50% - 22px)
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.mobile-date-picker-column::after {
|
|
39
|
-
content: '';
|
|
40
|
-
pointer-events: none;
|
|
41
|
-
position: absolute;
|
|
42
|
-
left: 0;
|
|
43
|
-
right: 0;
|
|
44
|
-
top: 50%;
|
|
45
|
-
transform: translateY(-50%);
|
|
46
|
-
height: 44px;
|
|
47
|
-
box-sizing: border-box;
|
|
48
|
-
border-top: 1px solid #e4e4e4;
|
|
49
|
-
border-bottom: 1px solid #e4e4e4;
|
|
50
|
-
z-index: 2;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.mobile-date-picker-wheel {
|
|
54
|
-
--mdp-item-h: 44px;
|
|
55
|
-
height: calc(var(--mdp-item-h) * 5);
|
|
56
|
-
overflow-y: auto;
|
|
57
|
-
touch-action: pan-y;
|
|
58
|
-
-webkit-overflow-scrolling: touch;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
.mobile-date-picker-wheel-inner {
|
|
62
|
-
position: relative;
|
|
63
|
-
width: 100%;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.mobile-date-picker-item {
|
|
67
|
-
position: absolute;
|
|
68
|
-
left: 0;
|
|
69
|
-
right: 0;
|
|
70
|
-
height: var(--mdp-item-h);
|
|
71
|
-
line-height: var(--mdp-item-h);
|
|
72
|
-
text-align: center;
|
|
73
|
-
font-size: 16px;
|
|
74
|
-
color: #1b212d;
|
|
75
|
-
}
|
|
1
|
+
.mobile-date-picker {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: row;
|
|
4
|
+
width: 100%;
|
|
5
|
+
min-height: calc(44px * 5);
|
|
6
|
+
position: relative;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
user-select: none;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.mobile-date-picker-column {
|
|
12
|
+
flex: 1;
|
|
13
|
+
position: relative;
|
|
14
|
+
min-width: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.mobile-date-picker-column::before {
|
|
18
|
+
content: '';
|
|
19
|
+
pointer-events: none;
|
|
20
|
+
position: absolute;
|
|
21
|
+
left: 0;
|
|
22
|
+
right: 0;
|
|
23
|
+
top: 0;
|
|
24
|
+
bottom: 0;
|
|
25
|
+
z-index: 1;
|
|
26
|
+
background: linear-gradient(
|
|
27
|
+
to bottom,
|
|
28
|
+
rgba(255, 255, 255, 0.95) 0%,
|
|
29
|
+
rgba(255, 255, 255, 0) calc(50% - 22px)
|
|
30
|
+
),
|
|
31
|
+
linear-gradient(
|
|
32
|
+
to top,
|
|
33
|
+
rgba(255, 255, 255, 0.95) 0%,
|
|
34
|
+
rgba(255, 255, 255, 0) calc(50% - 22px)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.mobile-date-picker-column::after {
|
|
39
|
+
content: '';
|
|
40
|
+
pointer-events: none;
|
|
41
|
+
position: absolute;
|
|
42
|
+
left: 0;
|
|
43
|
+
right: 0;
|
|
44
|
+
top: 50%;
|
|
45
|
+
transform: translateY(-50%);
|
|
46
|
+
height: 44px;
|
|
47
|
+
box-sizing: border-box;
|
|
48
|
+
border-top: 1px solid #e4e4e4;
|
|
49
|
+
border-bottom: 1px solid #e4e4e4;
|
|
50
|
+
z-index: 2;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.mobile-date-picker-wheel {
|
|
54
|
+
--mdp-item-h: 44px;
|
|
55
|
+
height: calc(var(--mdp-item-h) * 5);
|
|
56
|
+
overflow-y: auto;
|
|
57
|
+
touch-action: pan-y;
|
|
58
|
+
-webkit-overflow-scrolling: touch;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.mobile-date-picker-wheel-inner {
|
|
62
|
+
position: relative;
|
|
63
|
+
width: 100%;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.mobile-date-picker-item {
|
|
67
|
+
position: absolute;
|
|
68
|
+
left: 0;
|
|
69
|
+
right: 0;
|
|
70
|
+
height: var(--mdp-item-h);
|
|
71
|
+
line-height: var(--mdp-item-h);
|
|
72
|
+
text-align: center;
|
|
73
|
+
font-size: 16px;
|
|
74
|
+
color: #1b212d;
|
|
75
|
+
}
|
package/demo/src/App.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { onMount, reactive } from '../../src/reactive';
|
|
2
|
+
import { For } from '../../src/components/For';
|
|
1
3
|
import { showPopup } from '../../src/popup';
|
|
2
4
|
import { CanlendarPage } from './pages/Canlendar';
|
|
3
5
|
import { CarouselPage } from './pages/Carousel';
|
|
@@ -5,19 +7,85 @@ import { ComboBoxPage } from './pages/ComboBox';
|
|
|
5
7
|
import { DatePickerPage } from './pages/DatePicker';
|
|
6
8
|
import { FormPage } from './pages/Form';
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
// 方法1: SolidJS 的直接引用
|
|
11
|
+
const getSolidStyle = (root) => {
|
|
12
|
+
const a = root.firstChild.firstChild.nextSibling.nextSibling;
|
|
13
|
+
const b = a.nextSibling.nextSibling.nextSibling;
|
|
14
|
+
return [a, b];
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const enter = (node, count) => {
|
|
18
|
+
let child = node.firstChild;
|
|
19
|
+
|
|
20
|
+
while (--count) {
|
|
21
|
+
child = child.firstChild;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return child;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const next = (node, count) => {
|
|
28
|
+
node = node.nextSibling;
|
|
12
29
|
|
|
13
|
-
|
|
14
|
-
|
|
30
|
+
while (--count) {
|
|
31
|
+
node = node.nextSibling;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return node;
|
|
35
|
+
};
|
|
15
36
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
37
|
+
(Node.prototype as any).ENTER = function (count) {
|
|
38
|
+
let child = this.firstChild;
|
|
19
39
|
|
|
20
|
-
|
|
40
|
+
while (--count) {
|
|
41
|
+
child = child.firstChild;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return child;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const getChildren = (root) => {
|
|
48
|
+
const a = next(enter(root, 2), 2);
|
|
49
|
+
const b = next(a, 3);
|
|
50
|
+
|
|
51
|
+
return [a, b];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// 方法2: querySelectorAll
|
|
55
|
+
const getQueryStyle = (root) => {
|
|
56
|
+
return root.querySelectorAll('[dynamic]');
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// 方法3: TreeWalker
|
|
60
|
+
const getWalkerStyle = (root) => {
|
|
61
|
+
const walker = document.createNodeIterator(root, NodeFilter.SHOW_COMMENT);
|
|
62
|
+
let node;
|
|
63
|
+
|
|
64
|
+
while ((node = walker.nextNode())) {
|
|
65
|
+
if (node.nodeType === 'dd') {
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// 测试代码
|
|
71
|
+
const template = document.createElement('div');
|
|
72
|
+
template.innerHTML = `<div><span>Static</span><!><!-- dynamic1 --><span>Middle</span><!><!-- dynamic2 --></div>`;
|
|
73
|
+
|
|
74
|
+
console.log(template);
|
|
75
|
+
const printTime = (name: string, fn: Function) => {
|
|
76
|
+
let now = performance.now();
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < 1000000; i++) {
|
|
79
|
+
fn();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log(name, performance.now() - now);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
printTime('solid', () => getSolidStyle(template));
|
|
86
|
+
printTime('children', () => getChildren(template));
|
|
87
|
+
printTime('querySelectorAll', () => getQueryStyle(template));
|
|
88
|
+
printTime('TreeWalker', () => getWalkerStyle(template));
|
|
21
89
|
|
|
22
90
|
const openPopup = (align: HTMLElement) => {
|
|
23
91
|
const popup = showPopup(<div style={{ padding: '100px 0', background: 'silver' }}>11111111111111111111</div>, {
|
|
@@ -28,17 +96,34 @@ const openPopup = (align: HTMLElement) => {
|
|
|
28
96
|
|
|
29
97
|
export const App = () => {
|
|
30
98
|
let refButton: HTMLElement;
|
|
99
|
+
let ref;
|
|
100
|
+
|
|
101
|
+
let state = reactive([]);
|
|
102
|
+
|
|
103
|
+
onMount(() => {
|
|
104
|
+
let now = performance.now();
|
|
105
|
+
for (let i = 0; i < 10000; i++) {
|
|
106
|
+
let child = ref;
|
|
107
|
+
|
|
108
|
+
while ((child = child.nextSibling)) {}
|
|
109
|
+
}
|
|
110
|
+
console.log(performance.now() - now);
|
|
111
|
+
});
|
|
31
112
|
|
|
32
113
|
return (
|
|
33
114
|
<div style={{ 'min-height': '100%' }}>
|
|
34
|
-
<
|
|
115
|
+
<For each={state.value}>{(item) => <div>{item}</div>}</For>
|
|
116
|
+
<button ref={refButton as any} onclick={() => state.value.push(Math.random())}>
|
|
35
117
|
dropdown
|
|
36
118
|
</button>
|
|
37
|
-
<
|
|
38
|
-
<
|
|
119
|
+
<For each={state.value}>{(item) => <div>{item}</div>}</For>
|
|
120
|
+
<button onclick={() => state.value.push(Math.random())}>dropdown</button>
|
|
121
|
+
|
|
122
|
+
{/* <CarouselPage></CarouselPage> */}
|
|
123
|
+
{/* <CanlendarPage></CanlendarPage>
|
|
39
124
|
<DatePickerPage></DatePickerPage>
|
|
40
125
|
<ComboBoxPage></ComboBoxPage>
|
|
41
|
-
<FormPage></FormPage>
|
|
126
|
+
<FormPage></FormPage> */}
|
|
42
127
|
</div>
|
|
43
128
|
);
|
|
44
129
|
};
|
package/package.json
CHANGED
package/src/components/Switch.ts
CHANGED
package/src/location.ts
CHANGED
|
@@ -52,8 +52,10 @@ export const location: Location = reactive({
|
|
|
52
52
|
query: {},
|
|
53
53
|
paths: [],
|
|
54
54
|
routeTo(url: string, scrollTo?: [number, number]) {
|
|
55
|
+
// 更新历史
|
|
55
56
|
history.pushState(null, '', url || '');
|
|
56
|
-
|
|
57
|
+
// 不能立即取 window.location.pathname,在夸克等浏览取不到最新值
|
|
58
|
+
updateURL(url || '');
|
|
57
59
|
|
|
58
60
|
if (isBrowser && scrollTo) {
|
|
59
61
|
window.scrollTo(scrollTo[0] | 0, scrollTo[1] | 0);
|
|
@@ -89,47 +91,56 @@ export const parseQuery = (search: string) => {
|
|
|
89
91
|
/**
|
|
90
92
|
* 更新地址
|
|
91
93
|
*
|
|
92
|
-
* @param
|
|
93
|
-
* @param search 查询条件
|
|
94
|
-
* @param hash hash
|
|
94
|
+
* @param url 当前 url
|
|
95
95
|
*/
|
|
96
|
-
export const updateURL = (
|
|
97
|
-
location.url
|
|
98
|
-
|
|
96
|
+
export const updateURL = (url: string) => {
|
|
97
|
+
if (location.url !== url || (url = '')) {
|
|
98
|
+
let path = url;
|
|
99
|
+
let search = '';
|
|
100
|
+
let hash = '';
|
|
101
|
+
let index;
|
|
102
|
+
|
|
103
|
+
if ((index = path.indexOf('#')) >= 0) {
|
|
104
|
+
hash = path.slice(index);
|
|
105
|
+
path = path.slice(0, index);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if ((index = path.indexOf('?')) >= 0) {
|
|
109
|
+
search = path.slice(index);
|
|
110
|
+
path = path.slice(0, index);
|
|
111
|
+
}
|
|
99
112
|
|
|
100
|
-
if (location.path !== path || location.search !== search) {
|
|
101
113
|
batch(() => {
|
|
114
|
+
location.url = url;
|
|
115
|
+
location.hash = hash;
|
|
102
116
|
location.path = path;
|
|
103
117
|
location.paths = path.match(/\/[^/]*/g) || [];
|
|
104
|
-
location.search = search
|
|
118
|
+
location.search = search;
|
|
105
119
|
location.query = search ? parseQuery(search) : {};
|
|
106
120
|
});
|
|
107
121
|
}
|
|
108
122
|
};
|
|
109
123
|
|
|
110
124
|
// 浏览器环境
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return routeTo;
|
|
134
|
-
})()
|
|
135
|
-
: () => {};
|
|
125
|
+
if (isBrowser) {
|
|
126
|
+
(() => {
|
|
127
|
+
// 更新地址方法
|
|
128
|
+
const routeTo = () => {
|
|
129
|
+
let system = window.location;
|
|
130
|
+
updateURL(system.pathname + system.search + system.hash);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// 立即更新
|
|
134
|
+
routeTo();
|
|
135
|
+
|
|
136
|
+
// 侦听地址变化
|
|
137
|
+
window.addEventListener('popstate', () => routeTo(), true);
|
|
138
|
+
// window.addEventListener(
|
|
139
|
+
// 'hashchange',
|
|
140
|
+
// () => {
|
|
141
|
+
// location.hash = '';
|
|
142
|
+
// },
|
|
143
|
+
// true,
|
|
144
|
+
// );
|
|
145
|
+
})();
|
|
146
|
+
}
|
package/src/reactive.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
const getOwnPropertyNames = Object.getOwnPropertyNames;
|
|
1
|
+
import { createEffect, createSignal, createUniqueId, splitProps } from 'solid-js';
|
|
4
2
|
|
|
5
3
|
export const defineProperty = Object.defineProperty;
|
|
6
4
|
export const defineProperties = Object.defineProperties;
|
|
@@ -9,18 +7,19 @@ export const isArray = Array.isArray;
|
|
|
9
7
|
|
|
10
8
|
export {
|
|
11
9
|
type JSX,
|
|
10
|
+
batch,
|
|
12
11
|
children,
|
|
13
12
|
createComponent,
|
|
14
13
|
createEffect,
|
|
15
14
|
createMemo,
|
|
16
15
|
createContext,
|
|
17
16
|
createSignal,
|
|
18
|
-
|
|
19
|
-
splitProps,
|
|
17
|
+
lazy,
|
|
20
18
|
onMount,
|
|
21
19
|
onCleanup,
|
|
20
|
+
splitProps,
|
|
22
21
|
untrack,
|
|
23
|
-
|
|
22
|
+
useContext,
|
|
24
23
|
} from 'solid-js';
|
|
25
24
|
|
|
26
25
|
export { hydrate, render } from 'solid-js/web';
|
|
@@ -495,16 +494,3 @@ export const createFetcher = <T>(asyncLoad: () => Promise<T>, ssr_cache?: string
|
|
|
495
494
|
},
|
|
496
495
|
) as unknown as FetcherResult<T>;
|
|
497
496
|
};
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* 延迟加载组件
|
|
501
|
-
*
|
|
502
|
-
* @param importFn 按需导入的组件 import('...')
|
|
503
|
-
*/
|
|
504
|
-
export const LazyComponent = (
|
|
505
|
-
importFn: () => Promise<{
|
|
506
|
-
default: Component<any>;
|
|
507
|
-
}>,
|
|
508
|
-
) => {
|
|
509
|
-
return lazy(importFn);
|
|
510
|
-
};
|