cbvirtua 1.0.9 → 1.0.11

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 (63) hide show
  1. package/package.json +1 -1
  2. package/vant/style/README.md +79 -0
  3. package/vant/style/README.zh-CN.md +79 -0
  4. package/vant/style/animation.less +139 -0
  5. package/vant/style/base.less +10 -0
  6. package/vant/style/clearfix.less +5 -0
  7. package/vant/style/demo/index.vue +110 -0
  8. package/vant/style/ellipsis.less +13 -0
  9. package/vant/style/hairline.less +47 -0
  10. package/vant/style/mixins/clearfix.less +7 -0
  11. package/vant/style/mixins/ellipsis.less +15 -0
  12. package/vant/style/mixins/hairline.less +39 -0
  13. package/vant/style/normalize.less +38 -0
  14. package/vant/style/reset.less +171 -0
  15. package/vant/style/var.less +901 -0
  16. package/vant/tab/README.md +307 -0
  17. package/vant/tab/README.zh-CN.md +342 -0
  18. package/vant/tab/demo/index.vue +193 -0
  19. package/vant/tab/index.js +95 -0
  20. package/vant/tab/index.less +17 -0
  21. package/vant/tab/test/__snapshots__/demo.spec.js.snap +349 -0
  22. package/vant/tab/test/__snapshots__/index.spec.js.snap +352 -0
  23. package/vant/tab/test/__snapshots__/insert.spec.js.snap +63 -0
  24. package/vant/tab/test/demo.spec.js +4 -0
  25. package/vant/tab/test/index.spec.js +435 -0
  26. package/vant/tab/test/insert.spec.js +75 -0
  27. package/vant/tabs/Content.js +79 -0
  28. package/vant/tabs/Title.js +91 -0
  29. package/vant/tabs/index.js +453 -0
  30. package/vant/tabs/index.less +153 -0
  31. package/vant/tabs/utils.ts +53 -0
  32. package/vant/utils/constant.ts +11 -0
  33. package/vant/utils/create/bem.ts +45 -0
  34. package/vant/utils/create/component.ts +86 -0
  35. package/vant/utils/create/i18n.ts +16 -0
  36. package/vant/utils/create/index.ts +14 -0
  37. package/vant/utils/deep-assign.ts +27 -0
  38. package/vant/utils/deep-clone.ts +23 -0
  39. package/vant/utils/dom/event.ts +56 -0
  40. package/vant/utils/dom/node.ts +7 -0
  41. package/vant/utils/dom/raf.ts +40 -0
  42. package/vant/utils/dom/reset-scroll.ts +16 -0
  43. package/vant/utils/dom/scroll.ts +81 -0
  44. package/vant/utils/dom/style.ts +11 -0
  45. package/vant/utils/format/number.ts +52 -0
  46. package/vant/utils/format/string.ts +15 -0
  47. package/vant/utils/format/unit.ts +61 -0
  48. package/vant/utils/functional.ts +73 -0
  49. package/vant/utils/index.ts +79 -0
  50. package/vant/utils/interceptor.ts +27 -0
  51. package/vant/utils/router.ts +54 -0
  52. package/vant/utils/test/bem.spec.js +39 -0
  53. package/vant/utils/test/index.spec.js +152 -0
  54. package/vant/utils/test/interceptor.spec.js +50 -0
  55. package/vant/utils/types.ts +40 -0
  56. package/vant/utils/validate/date.ts +8 -0
  57. package/vant/utils/validate/email.ts +5 -0
  58. package/vant/utils/validate/mobile.ts +6 -0
  59. package/vant/utils/validate/number.ts +12 -0
  60. package/vant/utils/validate/system.ts +13 -0
  61. package/vant/utils/vnodes.ts +33 -0
  62. package/vue2/ex.vue +66 -0
  63. package/vue2/exx.vue +44 -0
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Vue Router support
3
+ */
4
+
5
+ import { RenderContext } from 'vue/types';
6
+ import VueRouter, { RawLocation } from 'vue-router/types';
7
+
8
+ export type RouteConfig = {
9
+ url?: string;
10
+ to?: RawLocation;
11
+ replace?: boolean;
12
+ };
13
+
14
+ function isRedundantNavigation(err: Error) {
15
+ return (
16
+ err.name === 'NavigationDuplicated' ||
17
+ // compatible with vue-router@3.3
18
+ (err.message && err.message.indexOf('redundant navigation') !== -1)
19
+ );
20
+ }
21
+
22
+ export function route(router: VueRouter, config: RouteConfig) {
23
+ const { to, url, replace } = config;
24
+ if (to && router) {
25
+ const promise = router[replace ? 'replace' : 'push'](to);
26
+
27
+ /* istanbul ignore else */
28
+ if (promise && promise.catch) {
29
+ promise.catch((err) => {
30
+ if (err && !isRedundantNavigation(err)) {
31
+ throw err;
32
+ }
33
+ });
34
+ }
35
+ } else if (url) {
36
+ replace ? location.replace(url) : (location.href = url);
37
+ }
38
+ }
39
+
40
+ export function functionalRoute(context: RenderContext) {
41
+ route(context.parent && context.parent.$router, context.props);
42
+ }
43
+
44
+ export type RouteProps = {
45
+ url?: string;
46
+ replace?: boolean;
47
+ to?: RawLocation;
48
+ };
49
+
50
+ export const routeProps = {
51
+ url: String,
52
+ replace: Boolean,
53
+ to: [String, Object],
54
+ };
@@ -0,0 +1,39 @@
1
+ import { createBEM } from '../create/bem';
2
+
3
+ test('bem', () => {
4
+ const bem = createBEM('button');
5
+
6
+ expect(bem()).toEqual('button');
7
+
8
+ expect(bem('text')).toEqual('button__text');
9
+
10
+ expect(bem({ disabled: false })).toEqual('button');
11
+
12
+ expect(bem({ disabled: true })).toEqual('button button--disabled');
13
+
14
+ expect(bem('text', { disabled: true })).toEqual(
15
+ 'button__text button__text--disabled'
16
+ );
17
+
18
+ expect(bem(['disabled', 'primary'])).toEqual(
19
+ 'button button--disabled button--primary'
20
+ );
21
+
22
+ expect(bem([])).toEqual('button');
23
+
24
+ expect(bem(null)).toEqual('button');
25
+
26
+ expect(bem([null])).toEqual('button');
27
+
28
+ expect(bem(['disabled', ''])).toEqual('button button--disabled');
29
+
30
+ expect(bem(['disabled', undefined])).toEqual('button button--disabled');
31
+
32
+ expect(bem('text', ['disabled', 'primary'])).toEqual(
33
+ 'button__text button__text--disabled button__text--primary'
34
+ );
35
+
36
+ expect(bem('text', [{ disabled: true }, 'primary'])).toEqual(
37
+ 'button__text button__text--disabled button__text--primary'
38
+ );
39
+ });
@@ -0,0 +1,152 @@
1
+ import { deepClone } from '../deep-clone';
2
+ import { deepAssign } from '../deep-assign';
3
+ import { isDef, get, noop } from '..';
4
+ import { raf, cancelRaf } from '../dom/raf';
5
+ import { later } from '../../../test';
6
+ import { isEmail } from '../validate/email';
7
+ import { isMobile } from '../validate/mobile';
8
+ import { isNumeric } from '../validate/number';
9
+ import { isAndroid } from '../validate/system';
10
+ import { camelize } from '../format/string';
11
+ import { formatNumber } from '../format/number';
12
+ import { addUnit, unitToPx } from '../format/unit';
13
+
14
+ test('deepClone', () => {
15
+ const a = { foo: 0 };
16
+ const b = { foo: 0, bar: 1 };
17
+ const arr = [a, b];
18
+ expect(deepClone(a)).toEqual(a);
19
+ expect(deepClone(b)).toEqual(b);
20
+ expect(deepClone(noop)).toEqual(noop);
21
+ expect(deepClone(arr)).toEqual(arr);
22
+ expect(deepClone(undefined)).toEqual(undefined);
23
+ expect(deepClone(1)).toEqual(1);
24
+ });
25
+
26
+ test('deepAssign', () => {
27
+ expect(deepAssign({}, { foo: null })).toEqual({});
28
+ expect(deepAssign({}, { foo: undefined })).toEqual({});
29
+ expect(deepAssign({ noop: null }, { noop })).toEqual({ noop });
30
+ expect(deepAssign({ foo: 0 }, { bar: 1 })).toEqual({ foo: 0, bar: 1 });
31
+ expect(
32
+ deepAssign({ foo: { bar: false } }, { foo: { bar: true, foo: false } })
33
+ ).toEqual({
34
+ foo: {
35
+ bar: true,
36
+ foo: false,
37
+ },
38
+ });
39
+ });
40
+
41
+ test('isDef', () => {
42
+ expect(isDef(null)).toBeFalsy();
43
+ expect(isDef(undefined)).toBeFalsy();
44
+ expect(isDef(1)).toBeTruthy();
45
+ expect(isDef('1')).toBeTruthy();
46
+ expect(isDef({})).toBeTruthy();
47
+ expect(isDef(noop)).toBeTruthy();
48
+ });
49
+
50
+ test('camelize', () => {
51
+ expect(camelize('ab')).toEqual('ab');
52
+ expect(camelize('a-b')).toEqual('aB');
53
+ expect(camelize('a-b-c-d')).toEqual('aBCD');
54
+ expect(camelize('a-b-')).toEqual('aB-');
55
+ expect(camelize('-a-b')).toEqual('AB');
56
+ expect(camelize('-')).toEqual('-');
57
+ });
58
+
59
+ test('get', () => {
60
+ expect(get({ a: 1 }, 'a')).toEqual(1);
61
+ expect(get({ a: { b: 2 } }, 'a.b')).toEqual(2);
62
+ expect(get({ a: { b: 2 } }, 'a.b.c')).toEqual('');
63
+ });
64
+
65
+ test('isAndroid', () => {
66
+ expect(isAndroid()).toBeFalsy();
67
+ });
68
+
69
+ test('raf', async () => {
70
+ const spy = jest.fn();
71
+ raf(spy);
72
+
73
+ await later(50);
74
+ expect(spy).toHaveBeenCalledTimes(1);
75
+ cancelRaf(1);
76
+ });
77
+
78
+ test('isEmail', () => {
79
+ expect(isEmail('abc@gmail.com')).toBeTruthy();
80
+ expect(isEmail(' abc@gmail.com ')).toBeTruthy();
81
+ expect(isEmail('abc@@gmail.com')).toBeFalsy();
82
+ expect(isEmail('@gmail.com')).toBeFalsy();
83
+ expect(isEmail('abc@')).toBeFalsy();
84
+ });
85
+
86
+ test('isMobile', () => {
87
+ expect(isMobile('13000000000')).toBeTruthy();
88
+ expect(isMobile('+8613000000000')).toBeTruthy();
89
+ expect(isMobile('8613000000000')).toBeTruthy();
90
+ expect(isMobile('1300000000')).toBeFalsy();
91
+ expect(isMobile('abc')).toBeFalsy();
92
+ });
93
+
94
+ test('isNumeric', () => {
95
+ expect(isNumeric('1')).toBeTruthy();
96
+ expect(isNumeric('1.2')).toBeTruthy();
97
+ expect(isNumeric('1..2')).toBeFalsy();
98
+ expect(isNumeric('abc')).toBeFalsy();
99
+ expect(isNumeric('1b2')).toBeFalsy();
100
+ });
101
+
102
+ test('formatNumber', () => {
103
+ // with dot
104
+ expect(formatNumber('abc')).toEqual('');
105
+ expect(formatNumber('1.2')).toEqual('1.2');
106
+ expect(formatNumber('abc1.2')).toEqual('1.2');
107
+ expect(formatNumber('123.4.')).toEqual('123.4');
108
+
109
+ // without dot
110
+ expect(formatNumber('1.2', false)).toEqual('1');
111
+ expect(formatNumber('abc1.2', false)).toEqual('1');
112
+ expect(formatNumber('123.4.', false)).toEqual('123');
113
+
114
+ // minus
115
+ expect(formatNumber('-1.2', false)).toEqual('-1');
116
+ expect(formatNumber('-1.2', false, false)).toEqual('1');
117
+ expect(formatNumber('-1.2', true)).toEqual('-1.2');
118
+ expect(formatNumber('-1.2-', true)).toEqual('-1.2');
119
+ expect(formatNumber('123-')).toEqual('123');
120
+
121
+ // special cases
122
+ expect(formatNumber('.1', true)).toEqual('0.1');
123
+ expect(formatNumber('-.1')).toEqual('-0.1');
124
+ });
125
+
126
+ test('addUnit', () => {
127
+ expect(addUnit(0)).toEqual('0px');
128
+ expect(addUnit(10)).toEqual('10px');
129
+ expect(addUnit('1%')).toEqual('1%');
130
+ expect(addUnit('1px')).toEqual('1px');
131
+ expect(addUnit('1vw')).toEqual('1vw');
132
+ expect(addUnit('1vh')).toEqual('1vh');
133
+ expect(addUnit('1rem')).toEqual('1rem');
134
+ });
135
+
136
+ test('unitToPx', () => {
137
+ const originGetComputedStyle = window.getComputedStyle;
138
+
139
+ window.innerWidth = 100;
140
+ window.innerHeight = 200;
141
+ window.getComputedStyle = () => ({ fontSize: '16px' });
142
+
143
+ expect(unitToPx(0)).toEqual(0);
144
+ expect(unitToPx(10)).toEqual(10);
145
+ expect(unitToPx('10px')).toEqual(10);
146
+ expect(unitToPx('0rem')).toEqual(0);
147
+ expect(unitToPx('10rem')).toEqual(160);
148
+ expect(unitToPx('10vw')).toEqual(10);
149
+ expect(unitToPx('10vh')).toEqual(20);
150
+
151
+ window.getComputedStyle = originGetComputedStyle;
152
+ });
@@ -0,0 +1,50 @@
1
+ import { later } from '../../../test';
2
+ import { callInterceptor } from '../interceptor';
3
+
4
+ test('#callInterceptor', async () => {
5
+ const done = jest.fn();
6
+ callInterceptor({ done });
7
+ expect(done).toHaveBeenCalledTimes(1);
8
+
9
+ callInterceptor({
10
+ interceptor: () => false,
11
+ done,
12
+ });
13
+ expect(done).toHaveBeenCalledTimes(1);
14
+
15
+ callInterceptor({
16
+ interceptor: () => true,
17
+ done,
18
+ });
19
+ expect(done).toHaveBeenCalledTimes(2);
20
+
21
+ callInterceptor({
22
+ interceptor: () => Promise.resolve(false),
23
+ done,
24
+ });
25
+ await later();
26
+ expect(done).toHaveBeenCalledTimes(2);
27
+
28
+ callInterceptor({
29
+ interceptor: () => Promise.resolve(true),
30
+ done,
31
+ });
32
+ await later();
33
+ expect(done).toHaveBeenCalledTimes(3);
34
+
35
+ callInterceptor({
36
+ interceptor: () => Promise.reject(),
37
+ done,
38
+ });
39
+ await later();
40
+ expect(done).toHaveBeenCalledTimes(3);
41
+
42
+ callInterceptor({
43
+ interceptor: (...args) => {
44
+ expect(args).toEqual(['foo']);
45
+ },
46
+ args: ['foo'],
47
+ done,
48
+ });
49
+ expect(done).toHaveBeenCalledTimes(3);
50
+ });
@@ -0,0 +1,40 @@
1
+ import { VNode, CreateElement, RenderContext } from 'vue';
2
+ import { InjectOptions, PropsDefinition } from 'vue/types/options';
3
+
4
+ export type EventHandler = (event: Event) => void;
5
+
6
+ export type ObjectIndex = Record<string, any>;
7
+
8
+ export type ScopedSlot<Props = any> = (
9
+ props?: Props
10
+ ) => VNode[] | VNode | undefined;
11
+
12
+ export type DefaultSlots = {
13
+ default?: ScopedSlot;
14
+ };
15
+
16
+ export type ScopedSlots = DefaultSlots & {
17
+ [key: string]: ScopedSlot | undefined;
18
+ };
19
+
20
+ export type ModelOptions = {
21
+ prop?: string;
22
+ event?: string;
23
+ };
24
+
25
+ export type DefaultProps = ObjectIndex;
26
+
27
+ export type FunctionComponent<
28
+ Props = DefaultProps,
29
+ PropDefs = PropsDefinition<Props>
30
+ > = {
31
+ (
32
+ h: CreateElement,
33
+ props: Props,
34
+ slots: ScopedSlots,
35
+ context: RenderContext<Props>
36
+ ): VNode | undefined;
37
+ props?: PropDefs;
38
+ model?: ModelOptions;
39
+ inject?: InjectOptions;
40
+ };
@@ -0,0 +1,8 @@
1
+ import { isNaN } from './number';
2
+
3
+ export function isDate(val: Date): val is Date {
4
+ return (
5
+ Object.prototype.toString.call(val) === '[object Date]' &&
6
+ !isNaN(val.getTime())
7
+ );
8
+ }
@@ -0,0 +1,5 @@
1
+ /* eslint-disable */
2
+ export function isEmail(value: string): boolean {
3
+ const reg = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
4
+ return reg.test(value.trim());
5
+ }
@@ -0,0 +1,6 @@
1
+ export function isMobile(value: string): boolean {
2
+ value = value.replace(/[^-|\d]/g, '');
3
+ return (
4
+ /^((\+86)|(86))?(1)\d{10}$/.test(value) || /^0[0-9-]{10,13}$/.test(value)
5
+ );
6
+ }
@@ -0,0 +1,12 @@
1
+ export function isNumeric(val: string): boolean {
2
+ return /^\d+(\.\d+)?$/.test(val);
3
+ }
4
+
5
+ export function isNaN(val: number): val is typeof NaN {
6
+ if (Number.isNaN) {
7
+ return Number.isNaN(val);
8
+ }
9
+
10
+ // eslint-disable-next-line no-self-compare
11
+ return val !== val;
12
+ }
@@ -0,0 +1,13 @@
1
+ import { isServer } from '..';
2
+
3
+ export function isAndroid(): boolean {
4
+ /* istanbul ignore next */
5
+ return isServer ? false : /android/.test(navigator.userAgent.toLowerCase());
6
+ }
7
+
8
+ export function isIOS(): boolean {
9
+ /* istanbul ignore next */
10
+ return isServer
11
+ ? false
12
+ : /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase());
13
+ }
@@ -0,0 +1,33 @@
1
+ import { VNode } from 'vue';
2
+
3
+ function flattenVNodes(vnodes: VNode[]) {
4
+ const result: VNode[] = [];
5
+
6
+ function traverse(vnodes: VNode[]) {
7
+ vnodes.forEach((vnode) => {
8
+ result.push(vnode);
9
+
10
+ if (vnode.componentInstance) {
11
+ traverse(vnode.componentInstance.$children.map((item) => item.$vnode));
12
+ }
13
+
14
+ if (vnode.children) {
15
+ traverse(vnode.children);
16
+ }
17
+ });
18
+ }
19
+
20
+ traverse(vnodes);
21
+ return result;
22
+ }
23
+
24
+ // sort children instances by vnodes order
25
+ export function sortChildren(children: Vue[], parent: Vue) {
26
+ const { componentOptions } = parent.$vnode;
27
+ if (!componentOptions || !componentOptions.children) {
28
+ return;
29
+ }
30
+
31
+ const vnodes = flattenVNodes(componentOptions.children);
32
+ children.sort((a, b) => vnodes.indexOf(a.$vnode) - vnodes.indexOf(b.$vnode));
33
+ }
package/vue2/ex.vue ADDED
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <div>
3
+ <p @click="exfun()" v-if="status">222</p>
4
+ <div v-if="refresh">
5
+ <exx v-show="hasData" />
6
+ </div>
7
+ </div>
8
+ </template>
9
+ <script>
10
+ import exx from './exx.vue'
11
+ let context = {}
12
+ const setContext = (vnode) => {
13
+ const p = new Promise((resolve, reject) => {
14
+ context.resolve = resolve
15
+ context.reject = reject
16
+ if (!vnode.context) {
17
+ vnode.context = context
18
+ }
19
+ })
20
+ return p
21
+ }
22
+ const initContext = () => {
23
+ setContext(exx) && context.resolve()
24
+ }
25
+
26
+ initContext()
27
+
28
+
29
+ export default {
30
+ name: 'ex',
31
+
32
+ data() {
33
+ return {
34
+ refresh: false,
35
+ status: true,
36
+ hasData: false
37
+ }
38
+ },
39
+ async beforeCreated() {
40
+
41
+ },
42
+
43
+ async mounted() {
44
+
45
+ },
46
+ components: {
47
+ exx
48
+ },
49
+ methods: {
50
+ async exfun() {
51
+ let p = setContext(exx)
52
+ this.refresh = !this.refresh
53
+ if (this.refresh) {
54
+ let d = await p
55
+ if (d) {
56
+ this.hasData = true
57
+ this.status = false
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ </script>
64
+
65
+ <style></style>
66
+
package/vue2/exx.vue ADDED
@@ -0,0 +1,44 @@
1
+ <script>
2
+ const NOOP = () => { }
3
+ export function useContext() {
4
+
5
+ }
6
+
7
+ let i = 0
8
+ export default {
9
+ name: 'ex',
10
+ data() {
11
+ return {
12
+ exx: 'exx1'
13
+ }
14
+ },
15
+ created() {
16
+ console.log(122222)
17
+ this.test()
18
+ },
19
+ mounted() {
20
+
21
+ },
22
+ components: {
23
+
24
+ },
25
+ methods: {
26
+ test() {
27
+ setTimeout(() => {
28
+ this.exx = 'exx2'
29
+ const { resolve } = this.$options.context
30
+ console.log(resolve)
31
+ i++
32
+ resolve(i)
33
+
34
+ }, 3000)
35
+ }
36
+ },
37
+ render() {
38
+ return <div>{this.exx}</div>
39
+ }
40
+ }
41
+ </script>
42
+
43
+ <style></style>
44
+