china-diff 1.0.1

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.
Files changed (52) hide show
  1. package/.gitattributes +1 -0
  2. package/.prettierignore +2 -0
  3. package/.prettierrc +5 -0
  4. package/README.md +1 -0
  5. package/build/css.ts +293 -0
  6. package/build/icons.ts +108 -0
  7. package/css/all.css +8 -0
  8. package/css/atomic/align.css +35 -0
  9. package/css/atomic/all.css +13 -0
  10. package/css/atomic/cursor.css +7 -0
  11. package/css/atomic/display.css +11 -0
  12. package/css/atomic/flex.css +124 -0
  13. package/css/atomic/grid.css +0 -0
  14. package/css/atomic/hidden.css +37 -0
  15. package/css/atomic/other.css +23 -0
  16. package/css/atomic/overflow.css +47 -0
  17. package/css/atomic/position.css +58 -0
  18. package/css/base.css +16 -0
  19. package/css/carousel.css +46 -0
  20. package/css/combobox.css +58 -0
  21. package/css/icon.css +7 -0
  22. package/icons/backward.svg +3 -0
  23. package/icons/close.svg +3 -0
  24. package/icons/dropdown.svg +3 -0
  25. package/icons/forward.svg +3 -0
  26. package/icons/toggle.svg +3 -0
  27. package/index.ts +1 -0
  28. package/jsx-runtime.d.ts +1 -0
  29. package/package.json +13 -0
  30. package/src/animate-scroll-to.ts +65 -0
  31. package/src/components/Carousel.tsx +299 -0
  32. package/src/components/CollapsiblePanel.tsx +139 -0
  33. package/src/components/ComboBox.tsx +163 -0
  34. package/src/components/Dialog.tsx +36 -0
  35. package/src/components/For.tsx +26 -0
  36. package/src/components/Icon.tsx +39 -0
  37. package/src/components/If.tsx +14 -0
  38. package/src/components/KeepAlive.tsx +26 -0
  39. package/src/components/Pulldown.tsx +157 -0
  40. package/src/components/Switch.tsx +49 -0
  41. package/src/dom.ts +137 -0
  42. package/src/http.ts +282 -0
  43. package/src/index.ts +68 -0
  44. package/src/jsx.ts +2 -0
  45. package/src/language.ts +34 -0
  46. package/src/layout.ts +89 -0
  47. package/src/location.ts +133 -0
  48. package/src/message.ts +290 -0
  49. package/src/reactive.ts +211 -0
  50. package/src/template.ts +23 -0
  51. package/tsconfig.json +16 -0
  52. package/vite-plugin.js +4 -0
@@ -0,0 +1,139 @@
1
+ import { createSignal, splitProps } from 'solid-js';
2
+
3
+ import { JSX } from '../jsx';
4
+ import { defineProperty } from '../reactive';
5
+
6
+ const COLLAPSED_CLASS = 'collapsed';
7
+
8
+ /**
9
+ * 可收拢面板外部调用接口
10
+ */
11
+ export interface CollapsiblePanelApi {
12
+ /**
13
+ * 是否收拢
14
+ */
15
+ collapsed: boolean;
16
+
17
+ /**
18
+ * 从当前或指定开始大小过渡到指定大小
19
+ *
20
+ * @param size 指定大小
21
+ * @param fromSize 开始大小
22
+ */
23
+ transitionTo(size: string, fromSize?: string): void;
24
+ }
25
+
26
+ /**
27
+ * 可收拢面板(第一个子项为头部区域,收拢时会增加 class "collapsed")
28
+ */
29
+ export const CollapsiblePanel = (
30
+ props: JSX.HTMLAttributes<never> & {
31
+ /**
32
+ * 是否默认收拢
33
+ */
34
+ collapsed?: boolean;
35
+ /**
36
+ * 收拢时的大小(默认为 '')
37
+ */
38
+ collapsedSize?: string;
39
+ /**
40
+ * 自定义获取展开时的大小(默认为滚动区的大小)
41
+ */
42
+ getExpandedSize?: () => string;
43
+ /**
44
+ * 是否使用过渡动画(需自己设置 height transition,如:will-change: height; transition: height 0.2s linear)
45
+ */
46
+ useTransition?: boolean;
47
+ /**
48
+ * 外部调用接口
49
+ */
50
+ api?: (api: CollapsiblePanelApi) => void;
51
+ },
52
+ ) => {
53
+ let ref: HTMLElement;
54
+
55
+ const [thisProps, restProps] = splitProps(props, [
56
+ 'class',
57
+ 'collapsed',
58
+ 'collapsedSize',
59
+ 'getExpandedSize',
60
+ 'useTransition',
61
+ 'api',
62
+ ]);
63
+ const [collapsed, setCollapsed] = createSignal(thisProps.collapsed || false);
64
+
65
+ const transitionTo = (size: string, fromSize?: string) => {
66
+ let style = ref.style;
67
+ let transition = style.transition;
68
+
69
+ style.transition = 'none';
70
+
71
+ fromSize && (style.height = fromSize);
72
+ style.height = ref.offsetHeight + 'px';
73
+
74
+ style.transition = transition;
75
+
76
+ setTimeout(() => {
77
+ style.height = size || '';
78
+ });
79
+ };
80
+
81
+ const update = (value: boolean) => {
82
+ if (value !== collapsed()) {
83
+ let classList = ref.classList;
84
+ let style = ref.style;
85
+
86
+ // 设置成收拢状态
87
+ if (value) {
88
+ if (thisProps.useTransition) {
89
+ style.height = ref.offsetHeight + 'px';
90
+
91
+ setTimeout(() => {
92
+ style.height = thisProps.collapsedSize || '';
93
+ classList.add(COLLAPSED_CLASS);
94
+ });
95
+ } else {
96
+ style.height = thisProps.collapsedSize || '';
97
+ classList.add(COLLAPSED_CLASS);
98
+ }
99
+ } else {
100
+ let getExpandedSize = thisProps.getExpandedSize;
101
+
102
+ // 设置成展开状态
103
+ if (thisProps.useTransition) {
104
+ style.height = ref.offsetHeight + 'px';
105
+
106
+ setTimeout(() => {
107
+ style.height = (getExpandedSize && getExpandedSize()) || ref.scrollHeight + 'px';
108
+ // 移除收拢的 class
109
+ classList.remove(COLLAPSED_CLASS);
110
+ });
111
+ } else {
112
+ style.height = (getExpandedSize && getExpandedSize()) || '';
113
+ // 移除收拢的 class
114
+ classList.remove(COLLAPSED_CLASS);
115
+ }
116
+ }
117
+
118
+ setCollapsed(value);
119
+ }
120
+ };
121
+
122
+ thisProps.api &&
123
+ thisProps.api(
124
+ defineProperty({ transitionTo }, 'collapsed', {
125
+ get: collapsed,
126
+ set: update,
127
+ }) as CollapsiblePanelApi,
128
+ );
129
+
130
+ return (
131
+ <div
132
+ ref={ref as any}
133
+ class={['collapsed-panel', thisProps.collapsed && COLLAPSED_CLASS, thisProps.class]
134
+ .filter((item) => item)
135
+ .join(' ')}
136
+ {...restProps}
137
+ ></div>
138
+ );
139
+ };
@@ -0,0 +1,163 @@
1
+ import { splitProps } from 'solid-js';
2
+
3
+ import { JSX } from '../jsx';
4
+
5
+ import { disableAutoCloseEvent, registerAutoClose } from '../dom';
6
+
7
+ const POPUP_TOP_CLASS = 'combobox-popup-top';
8
+ const POPUP_RIGHT_CLASS = 'combobox-popup-right';
9
+
10
+ /**
11
+ * 当前弹出层
12
+ */
13
+ let currentPopup: ComboBoxApi;
14
+
15
+ /**
16
+ * 关闭当前弹出层
17
+ */
18
+ export const closePopup = () => {
19
+ currentPopup && currentPopup.closePupup();
20
+ };
21
+
22
+ /**
23
+ * 是否使用下拉动画
24
+ */
25
+ export let useDropdownTransition = true;
26
+
27
+ /**
28
+ * 设置是否使用下拉动画
29
+ *
30
+ * @param use 是否使用
31
+ */
32
+ export const setUseDropdownTransition = (use: boolean) => {
33
+ useDropdownTransition = use;
34
+ };
35
+
36
+ // 注册点击关闭弹出层的方法
37
+ registerAutoClose(closePopup);
38
+
39
+ /**
40
+ * 下拉框组件外部访问接口
41
+ */
42
+ export interface ComboBoxApi {
43
+ /**
44
+ * 打开弹出框
45
+ */
46
+ openPopup(): void;
47
+ /**
48
+ * 关闭弹出框
49
+ */
50
+ closePupup(): void;
51
+ }
52
+
53
+ /**
54
+ * 下拉框组件
55
+ */
56
+ export const ComboBox = <T, U extends JSX.Element>(
57
+ props?: JSX.HTMLAttributes<never> & {
58
+ /**
59
+ * 值
60
+ */
61
+ value?: string;
62
+ /**
63
+ * 是否只读
64
+ */
65
+ readonly?: boolean;
66
+ /**
67
+ * 外部调用接口
68
+ */
69
+ api?: (api: ComboBoxApi) => void;
70
+ },
71
+ ) => {
72
+ let [thisProps, restProps] = splitProps(props, ['class', 'value', 'readonly', 'api', 'children']);
73
+ let popup: HTMLElement;
74
+ let opened: boolean;
75
+
76
+ const toggle = (event?: Event) => {
77
+ if (popup) {
78
+ let combobox = popup.parentNode as HTMLElement;
79
+ let rect = combobox.getBoundingClientRect();
80
+ let style = popup.style;
81
+
82
+ if ((opened = !opened)) {
83
+ let windowWidth = window.innerWidth;
84
+ let windowHeight = window.innerHeight;
85
+ let classList = popup.classList;
86
+
87
+ if (currentPopup) {
88
+ currentPopup.closePupup();
89
+ }
90
+
91
+ // 设置当前弹出层
92
+ currentPopup = api;
93
+
94
+ style.height = 'auto';
95
+ style.display = 'block';
96
+
97
+ let height = popup.offsetHeight;
98
+
99
+ if (windowHeight - rect.top - rect.height < height + 4 && rect.top >= height) {
100
+ classList.add(POPUP_TOP_CLASS);
101
+ } else {
102
+ classList.remove(POPUP_TOP_CLASS);
103
+ }
104
+
105
+ if (windowWidth - rect.left - rect.width >= 0) {
106
+ classList.add(POPUP_RIGHT_CLASS);
107
+ } else {
108
+ classList.remove(POPUP_RIGHT_CLASS);
109
+ }
110
+
111
+ if (useDropdownTransition) {
112
+ style.height = '0';
113
+
114
+ setTimeout(() => {
115
+ style.height = height + 'px';
116
+ });
117
+ }
118
+ } else {
119
+ currentPopup = null;
120
+
121
+ if (useDropdownTransition) {
122
+ style.height = popup.offsetHeight + 'px';
123
+
124
+ setTimeout(() => {
125
+ style.height = '0';
126
+ });
127
+ } else {
128
+ style.display = 'none';
129
+ }
130
+ }
131
+ }
132
+
133
+ event && event.stopPropagation();
134
+ };
135
+
136
+ const api = {
137
+ openPopup: () => opened || toggle(),
138
+ closePupup: () => opened && toggle(),
139
+ };
140
+
141
+ // 初始化外部调用接口
142
+ props.api && props.api(api);
143
+
144
+ return (
145
+ <div class={'combobox' + (thisProps.class ? ' ' + thisProps.class : '')} {...restProps}>
146
+ <div class="combobox-host" {...disableAutoCloseEvent} onclick={() => thisProps.readonly && toggle()}>
147
+ <input value={thisProps.value ?? ''} readonly={thisProps.readonly} style={{ border: 'none' }}></input>
148
+ <svg class="icon icon-s" aria-hidden={true} style={{ height: '100%', padding: '0 4px' }} onclick={toggle}>
149
+ <use href="#icon-dropdown"></use>
150
+ </svg>
151
+ </div>
152
+ <div
153
+ ref={popup as any}
154
+ class="combobox-popup"
155
+ style={{ display: 'none' }}
156
+ {...disableAutoCloseEvent}
157
+ ontransitionend={() => opened || (popup.style.display = 'none')}
158
+ >
159
+ {thisProps.children}
160
+ </div>
161
+ </div>
162
+ );
163
+ };
@@ -0,0 +1,36 @@
1
+ import { createRoot } from 'solid-js';
2
+
3
+ import { JSX } from '../jsx';
4
+
5
+ /**
6
+ * 对话框
7
+ */
8
+ export type Dialog = HTMLElement & {
9
+ /**
10
+ * 关闭对话框方法
11
+ */
12
+ close(): void;
13
+ };
14
+
15
+ /**
16
+ * 显示对话框
17
+ *
18
+ * @param component 对话框组件
19
+ * @returns 关闭对话框方法
20
+ */
21
+ export const showDialog = (component: () => JSX.Element): Dialog => {
22
+ return createRoot((dispose) => {
23
+ let body = document.body;
24
+ let dialog = component() as Dialog;
25
+
26
+ dialog.style.cssText = 'position:fixed;z-index:9';
27
+ body.appendChild(dialog);
28
+
29
+ dialog.close = () => {
30
+ body.removeChild(dialog);
31
+ dispose();
32
+ };
33
+
34
+ return dialog;
35
+ });
36
+ };
@@ -0,0 +1,26 @@
1
+ import { createMemo, mapArray } from 'solid-js';
2
+
3
+ import { JSX } from '../jsx';
4
+
5
+ export const For = <T, U extends JSX.Element>(props: {
6
+ /**
7
+ * 要循环的数据集合
8
+ */
9
+ each: readonly T[];
10
+ /**
11
+ * 子节点
12
+ *
13
+ * @param item 数据项
14
+ * @param index 索引
15
+ * @returns JSX.Element
16
+ */
17
+ children: (item: T, index: () => number) => U;
18
+ }) => {
19
+ return createMemo(
20
+ mapArray(() => props.each, props.children),
21
+ void 0,
22
+ {
23
+ name: 'value',
24
+ }
25
+ ) as unknown as JSX.Element;
26
+ };
@@ -0,0 +1,39 @@
1
+ import { splitProps } from 'solid-js';
2
+
3
+ import { JSX } from '../jsx';
4
+
5
+ /**
6
+ * 图标组件
7
+ */
8
+ export const Icon = (props?: JSX.SvgSVGAttributes<never> & { name: string }) => {
9
+ let [thisProps, restProps] = splitProps(props, ['class', 'name']);
10
+
11
+ return (
12
+ <svg class={'icon' + (thisProps.class ? ' ' + thisProps.class : '')} aria-hidden={true} {...restProps}>
13
+ <use href={'#icon-' + thisProps.name}></use>
14
+ </svg>
15
+ );
16
+ };
17
+
18
+ /**
19
+ * 加载 svg 图标集
20
+ *
21
+ * @param svgSymbols svg symbol 内容(由 icons 构建工具生成)
22
+ */
23
+ export const loadSvgIcons = (svgSymbols: string) => {
24
+ let body = document.body;
25
+ let svg = document.getElementById('ICONS');
26
+
27
+ if (svg) {
28
+ svg.insertAdjacentHTML('beforeend', svgSymbols);
29
+ } else {
30
+ svg = document.createElement('svg');
31
+ svg.id = 'ICONS';
32
+ svg.ariaHidden = 'true';
33
+ svg.style.cssText = 'position:absolute;width:0px;height:0px;overflow:hidden;';
34
+ svg.innerHTML = svgSymbols;
35
+ svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
36
+
37
+ body.insertBefore(svg, body.firstChild);
38
+ }
39
+ };
@@ -0,0 +1,14 @@
1
+ import { createMemo } from 'solid-js';
2
+
3
+ import { JSX } from '../jsx';
4
+
5
+ /**
6
+ * 条件渲染
7
+ *
8
+ * @param props 属性集合
9
+ */
10
+ export const If = (props: { when: any; children: JSX.Element | JSX.Element[]; else?: JSX.Element | JSX.Element[] }) => {
11
+ return createMemo(() => {
12
+ return props.when ? props.children : props.else;
13
+ }) as unknown as JSX.Element;
14
+ };
@@ -0,0 +1,26 @@
1
+ import { JSX, createMemo, createRoot, onCleanup } from 'solid-js';
2
+
3
+ export const KeepAlive = (props: {
4
+ /**
5
+ * 是否显示
6
+ */
7
+ show: boolean;
8
+ children: JSX.Element | JSX.Element[];
9
+ }) => {
10
+ let root, ondestory;
11
+
12
+ onCleanup(() => {
13
+ ondestory && ondestory();
14
+ });
15
+
16
+ return createMemo(() => {
17
+ return (
18
+ props.show &&
19
+ (root ||
20
+ (root = createRoot((dispose) => {
21
+ ondestory = dispose;
22
+ return props.children;
23
+ })))
24
+ );
25
+ }) as unknown as JSX.Element;
26
+ };
@@ -0,0 +1,157 @@
1
+ // import { onCleanup, onMount, splitProps } from 'solid-js';
2
+
3
+ // import { JSX } from '../jsx';
4
+ // import { addEventListener, removeEventListener } from '../dom';
5
+
6
+ // /**
7
+ // * 下拉状态
8
+ // */
9
+ // const state = {
10
+ // /**
11
+ // * 订阅数量
12
+ // */
13
+ // count: 0,
14
+ // /**
15
+ // * 按下时位置
16
+ // */
17
+ // y: 0,
18
+
19
+ // /**
20
+ // * 按下时的时间
21
+ // */
22
+ // time: 0,
23
+
24
+ // /**
25
+ // * 下拉组件节点
26
+ // */
27
+ // pulldown: null as HTMLElement,
28
+ // drag: null as HTMLElement,
29
+ // ready: null as HTMLElement,
30
+ // };
31
+
32
+ // const ontouchstart = (event: TouchEvent) => {
33
+ // let pulldown = (state.pulldown = document.querySelector('.pulldown'));
34
+
35
+ // state.y = (event.changedTouches[0] || event.touches[0]).screenY;
36
+
37
+ // if (pulldown) {
38
+ // let drag = (state.drag = pulldown.querySelector('.pulldown-drag'));
39
+ // let ready = (state.ready = pulldown.querySelector('.pulldown-ready'));
40
+
41
+ // if (drag || ready) {
42
+ // state.time = Date.now();
43
+
44
+ // // 有滚动则停止下拉
45
+ // addEventListener('scroll', removeListener, true);
46
+
47
+ // addEventListener('touchmove', ontouchmove, true);
48
+ // addEventListener('touchend', ontouchend, true);
49
+ // } else {
50
+ // console.error('Pulldown no pulldown-drag and pulldown-ready class child node');
51
+ // }
52
+ // }
53
+ // };
54
+
55
+ // const ontouchmove = (event: TouchEvent) => {
56
+ // let screenY = (event.changedTouches[0] || event.touches[0]).screenY;
57
+ // let distance = screenY - state.y;
58
+ // let pulldown = state.pulldown;
59
+ // let style = pulldown.style;
60
+
61
+ // if (distance <= 40 || Date.now() - state.time < 200) {
62
+ // style.display = 'none';
63
+ // return;
64
+ // }
65
+
66
+ // // 已经开始下拉
67
+ // if (style.display !== 'none') {
68
+ // } else {
69
+ // // 最小移动 20 像素的距离才显示
70
+ // style.display = 'flex';
71
+ // style.justifyContent = style.alignItems = 'center';
72
+ // }
73
+
74
+ // state.drag.style.display = distance <= 60 ? '' : 'none';
75
+ // state.ready.style.display = distance > 60 ? '' : 'none';
76
+
77
+ // style.height = distance + 'px';
78
+ // };
79
+
80
+ // const removeListener = () => {
81
+ // let pulldown = state.pulldown;
82
+ // let ready = state.ready;
83
+
84
+ // removeEventListener('scroll', removeListener, true);
85
+
86
+ // removeEventListener('touchmove', ontouchmove, true);
87
+ // removeEventListener('touchend', ontouchend, true);
88
+
89
+ // state.pulldown = state.drag = state.ready = null;
90
+
91
+ // if (pulldown && pulldown.style.display !== 'none') {
92
+ // pulldown.style.display = 'none';
93
+
94
+ // if (ready && ready.style.display !== 'none') {
95
+ // return pulldown;
96
+ // }
97
+ // }
98
+ // };
99
+
100
+ // const ontouchend = (event: TouchEvent) => {
101
+ // let pulldown = removeListener();
102
+
103
+ // if (pulldown) {
104
+ // pulldown.dispatchEvent(new Event('refresh'));
105
+ // }
106
+ // };
107
+
108
+ // /**
109
+ // * 默认子控件
110
+ // */
111
+ // let pulldownChildren;
112
+
113
+ // /**
114
+ // * 设置下拉刷新默认子组件
115
+ // *
116
+ // * @param children 子组件集合(需包含 class 分别为 pulldown-drag 及 pulldown-ready 的两个元素)
117
+ // */
118
+ // export const setPulldownChildren = (children: JSX.Element | JSX.Element[]) => {
119
+ // pulldownChildren = children;
120
+ // };
121
+
122
+ // /**
123
+ // * 下拉刷新
124
+ // *
125
+ // * @param props 属性集
126
+ // */
127
+ // export const Pulldown = (props: JSX.HTMLAttributes<never> & { onrefresh: Function }) => {
128
+ // const [thisProps, restProps] = splitProps(props, ['class', 'onrefresh', 'children']);
129
+ // let ref;
130
+
131
+ // onMount(() => {
132
+ // if (state.count++) {
133
+ // } else {
134
+ // addEventListener('touchstart', ontouchstart);
135
+ // }
136
+ // });
137
+
138
+ // onCleanup(() => {
139
+ // if (--state.count) {
140
+ // } else {
141
+ // removeEventListener('touchstart', ontouchstart);
142
+ // }
143
+ // });
144
+
145
+ // return (
146
+ // <div ref={ref} class={'pulldown' + (thisProps.class ? ' ' + thisProps.class : '')} {...restProps}>
147
+ // {props.children ||
148
+ // pulldownChildren ||
149
+ // (pulldownChildren = (
150
+ // <>
151
+ // <div class="pulldown-drag">下拉刷新</div>
152
+ // <div class="pulldown-ready">释放立即刷新</div>
153
+ // </>
154
+ // ))}
155
+ // </div>
156
+ // );
157
+ // };
@@ -0,0 +1,49 @@
1
+ import { JSX, createMemo, createRoot, onCleanup } from 'solid-js';
2
+
3
+ export interface SwitchProps {
4
+ /**
5
+ * 要切换的分支
6
+ */
7
+ case?: {
8
+ /**
9
+ * 目标组件
10
+ */
11
+ component: () => JSX.Element;
12
+ /**
13
+ * 捉拿
14
+ */
15
+ keepalive?: string;
16
+ };
17
+ }
18
+
19
+ export const Switch = (props: SwitchProps) => {
20
+ let roots = {};
21
+ let disposes = {};
22
+
23
+ onCleanup(() => {
24
+ for (let key in disposes) {
25
+ disposes[key]();
26
+ }
27
+
28
+ roots = disposes = null;
29
+ });
30
+
31
+ return createMemo(() => {
32
+ let branch = props.case;
33
+ let keepalive;
34
+
35
+ if (branch) {
36
+ if ((keepalive = branch.keepalive)) {
37
+ return (
38
+ roots[keepalive] ||
39
+ (roots[keepalive] = createRoot((dispose) => {
40
+ disposes[keepalive] = dispose;
41
+ return branch.component();
42
+ }))
43
+ );
44
+ }
45
+
46
+ return branch.component();
47
+ }
48
+ }) as unknown as JSX.Element;
49
+ };