@farris/cli 2.0.0-beta.7 → 2.0.0-beta.8

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 (149) hide show
  1. package/bin/index.js +2 -2
  2. package/lib/commands/build-components.js +21 -17
  3. package/lib/commands/build-components.js.map +1 -0
  4. package/lib/commands/build-css.js +30 -2
  5. package/lib/commands/build-css.js.map +1 -0
  6. package/lib/commands/build-lib.js +16 -6
  7. package/lib/commands/build-lib.js.map +1 -0
  8. package/lib/commands/build.js +11 -5
  9. package/lib/commands/build.js.map +1 -0
  10. package/lib/commands/create-app.js +2 -1
  11. package/lib/commands/create-app.js.map +1 -0
  12. package/lib/commands/dev-serve.js +3 -7
  13. package/lib/commands/dev-serve.js.map +1 -0
  14. package/lib/commands/preview-serve.js +1 -0
  15. package/lib/commands/preview-serve.js.map +1 -0
  16. package/lib/common/constant.js +1 -0
  17. package/lib/common/constant.js.map +1 -0
  18. package/lib/common/generate-app.js +1 -0
  19. package/lib/common/generate-app.js.map +1 -0
  20. package/lib/common/get-dependencies.js +1 -0
  21. package/lib/common/get-dependencies.js.map +1 -0
  22. package/lib/common/get-farris-config.js +3 -2
  23. package/lib/common/get-farris-config.js.map +1 -0
  24. package/lib/common/get-version.js +1 -0
  25. package/lib/common/get-version.js.map +1 -0
  26. package/lib/common/get-vite-config.js +16 -8
  27. package/lib/common/get-vite-config.js.map +1 -0
  28. package/lib/config/vite-app.js +10 -10
  29. package/lib/config/vite-app.js.map +1 -0
  30. package/lib/config/vite-common.js +21 -0
  31. package/lib/config/vite-common.js.map +1 -0
  32. package/lib/config/vite-component.js +30 -0
  33. package/lib/config/vite-component.js.map +1 -0
  34. package/lib/config/vite-lib.js +12 -20
  35. package/lib/config/vite-lib.js.map +1 -0
  36. package/lib/index.js +23 -1
  37. package/lib/index.js.map +1 -0
  38. package/lib/plugins/{gen-component-style.js → create-component-style.js} +6 -4
  39. package/lib/plugins/create-component-style.js.map +1 -0
  40. package/lib/plugins/create-package-json.js +34 -0
  41. package/lib/plugins/create-package-json.js.map +1 -0
  42. package/lib/plugins/dts.js +1 -0
  43. package/lib/plugins/dts.js.map +1 -0
  44. package/lib/plugins/html-system.js +1 -0
  45. package/lib/plugins/html-system.js.map +1 -0
  46. package/lib/plugins/replace.js +1 -0
  47. package/lib/plugins/replace.js.map +1 -0
  48. package/lib/plugins/systemjs-bundle.js +16 -0
  49. package/lib/plugins/systemjs-bundle.js.map +1 -0
  50. package/package.json +41 -38
  51. package/templates/lib/.eslintrc.cjs +15 -15
  52. package/templates/lib/.prettierrc.json +7 -7
  53. package/templates/lib/components/button/index.ts +7 -0
  54. package/templates/lib/components/button/src/button.component.tsx +84 -0
  55. package/templates/lib/components/button/src/button.props.ts +55 -0
  56. package/templates/lib/components/button/src/button.scss +179 -0
  57. package/templates/lib/components/common/index.ts +6 -0
  58. package/templates/lib/components/common/src/common.scss +4 -0
  59. package/templates/lib/components/common/src/compositions/index.ts +19 -0
  60. package/templates/lib/components/common/src/compositions/types.ts +6 -0
  61. package/templates/lib/components/common/src/compositions/use-bem/index.ts +46 -0
  62. package/templates/lib/components/common/src/compositions/use-click-away/index.ts +40 -0
  63. package/templates/lib/components/common/src/compositions/use-context/use-children-contexts.ts +40 -0
  64. package/templates/lib/components/common/src/compositions/use-context/use-parent-context.ts +24 -0
  65. package/templates/lib/components/common/src/compositions/use-event-listener/index.ts +45 -0
  66. package/templates/lib/components/common/src/compositions/use-expose/index.ts +9 -0
  67. package/templates/lib/components/common/src/compositions/use-lay-render/index.ts +17 -0
  68. package/templates/lib/components/common/src/compositions/use-link/index.ts +14 -0
  69. package/templates/lib/components/common/src/compositions/use-lock-scroll/index.ts +25 -0
  70. package/templates/lib/components/common/src/compositions/use-long-press/index.ts +141 -0
  71. package/templates/lib/components/common/src/compositions/use-momentum/index.ts +82 -0
  72. package/templates/lib/components/common/src/compositions/use-mount-component/index.ts +48 -0
  73. package/templates/lib/components/common/src/compositions/use-rect/index.ts +31 -0
  74. package/templates/lib/components/common/src/compositions/use-refs/index.ts +21 -0
  75. package/templates/lib/components/common/src/compositions/use-resize-observer/index.ts +85 -0
  76. package/templates/lib/components/common/src/compositions/use-resize-observer/utils.ts +37 -0
  77. package/templates/lib/components/common/src/compositions/use-scroll-parent/index.ts +42 -0
  78. package/templates/lib/components/common/src/compositions/use-touch/index.ts +82 -0
  79. package/templates/lib/components/common/src/compositions/use-touch-move/index.ts +120 -0
  80. package/templates/lib/components/common/src/entity/base-property.ts +129 -0
  81. package/templates/lib/components/common/src/entity/entity-schema.ts +274 -0
  82. package/templates/lib/components/common/src/entity/input-base-property.ts +285 -0
  83. package/templates/lib/components/common/src/style/animation/index.scss +150 -0
  84. package/templates/lib/components/common/src/style/base.scss +63 -0
  85. package/templates/lib/components/common/src/style/fonts/farris-mobile-icon.ttf +0 -0
  86. package/templates/lib/components/common/src/style/icon.scss +6 -0
  87. package/templates/lib/components/common/src/style/index.scss +4 -0
  88. package/templates/lib/components/common/src/style/mixins/bem.scss +204 -0
  89. package/templates/lib/components/common/src/style/mixins/border-radius.scss +13 -0
  90. package/templates/lib/components/common/src/style/mixins/ellipsis.scss +15 -0
  91. package/templates/lib/components/common/src/style/mixins/hairline.scss +113 -0
  92. package/templates/lib/components/common/src/style/mixins/index.scss +6 -0
  93. package/templates/lib/components/common/src/style/mixins/margin.scss +10 -0
  94. package/templates/lib/components/common/src/style/mixins/safe-area.scss +9 -0
  95. package/templates/lib/components/common/src/style/variables.scss +113 -0
  96. package/templates/lib/components/common/src/utils/index.ts +15 -0
  97. package/templates/lib/components/common/src/utils/src/common.ts +83 -0
  98. package/templates/lib/components/common/src/utils/src/date.ts +134 -0
  99. package/templates/lib/components/common/src/utils/src/dom/event.ts +37 -0
  100. package/templates/lib/components/common/src/utils/src/hook.ts +18 -0
  101. package/templates/lib/components/common/src/utils/src/number.ts +26 -0
  102. package/templates/lib/components/common/src/utils/src/query-filter.ts +40 -0
  103. package/templates/lib/components/common/src/utils/src/resove-asset.ts +33 -0
  104. package/templates/lib/components/common/src/utils/src/string.ts +18 -0
  105. package/templates/lib/components/common/src/utils/src/throttle.ts +41 -0
  106. package/templates/lib/components/common/src/utils/src/transition.ts +14 -0
  107. package/templates/lib/components/common/src/utils/src/type.ts +105 -0
  108. package/templates/lib/components/common/src/utils/src/use-appearance.ts +33 -0
  109. package/templates/lib/components/common/src/utils/src/with-install.ts +16 -0
  110. package/templates/lib/components/common/src/utils/src/with-register-designer.ts +16 -0
  111. package/templates/lib/components/common/src/utils/src/with-register.ts +16 -0
  112. package/templates/lib/components/common/types.ts +131 -0
  113. package/templates/lib/components/index.ts +0 -0
  114. package/templates/lib/farris.config.mjs +37 -16
  115. package/templates/lib/index.html +12 -12
  116. package/templates/lib/package.json +28 -28
  117. package/templates/lib/src/App.vue +80 -5
  118. package/templates/lib/src/components/TheButton.vue +3 -0
  119. package/templates/lib/src/main.ts +10 -9
  120. package/templates/lib/src/router/index.ts +23 -0
  121. package/templates/lib/src/views/AboutView.vue +15 -0
  122. package/templates/lib/src/views/HomeView.vue +9 -0
  123. package/templates/lib/tsconfig.json +19 -17
  124. package/templates/mobile/.eslintrc.cjs +15 -15
  125. package/templates/mobile/.prettierrc.json +7 -7
  126. package/templates/mobile/farris.config.mjs +1 -1
  127. package/templates/mobile/index.html +12 -12
  128. package/templates/mobile/package.json +28 -28
  129. package/templates/mobile/src/App.vue +80 -80
  130. package/templates/mobile/src/components/TheButton.vue +3 -3
  131. package/templates/mobile/src/main.ts +12 -12
  132. package/templates/mobile/src/router/index.ts +23 -23
  133. package/templates/mobile/src/views/AboutView.vue +15 -15
  134. package/templates/mobile/src/views/HomeView.vue +9 -9
  135. package/templates/mobile/tsconfig.json +17 -17
  136. package/templates/web/.eslintrc.cjs +15 -0
  137. package/templates/web/.prettierrc.json +8 -0
  138. package/templates/web/farris.config.mjs +24 -0
  139. package/templates/web/index.html +12 -0
  140. package/templates/web/package.json +29 -0
  141. package/templates/web/src/App.vue +80 -0
  142. package/templates/web/src/components/TheButton.vue +3 -0
  143. package/templates/web/src/main.ts +10 -0
  144. package/templates/web/src/router/index.ts +23 -0
  145. package/templates/web/src/views/AboutView.vue +15 -0
  146. package/templates/web/src/views/HomeView.vue +9 -0
  147. package/templates/web/tsconfig.json +18 -0
  148. package/templates/lib/packages/button/src/index.vue +0 -4
  149. package/templates/lib/packages/index.ts +0 -7
@@ -0,0 +1,46 @@
1
+ import { isArray, camelToKebabCase } from '../../utils';
2
+
3
+ export const useBem = (name: string) => {
4
+
5
+ const snakeCaseName = camelToKebabCase(name);
6
+
7
+ /**
8
+ * @param element 元素类名
9
+ * @returns .block__element
10
+ */
11
+ const getElementClass = (element?: string | string[])=>{
12
+ if(!element) {
13
+ return snakeCaseName;
14
+ }
15
+ const elementClass = isArray(element) ? element.join('__') : element;
16
+ return `${snakeCaseName}__${elementClass}`;
17
+ };
18
+
19
+ /**
20
+ * @param modifier 修饰符
21
+ * @param element 元素类名
22
+ * @returns .block[__element]--modifier
23
+ */
24
+ const getModifierClass = (modifier: string, element?: string | string[])=>{
25
+ const modifierClass = modifier ? `--${modifier}` : '';
26
+ if(element){
27
+ return getElementClass(element) + modifierClass;
28
+ }
29
+ return snakeCaseName + modifierClass;
30
+ };
31
+
32
+ /**
33
+ * @param element 元素类名
34
+ * @param modifier 修饰符
35
+ * @returns .block__element--modifier
36
+ */
37
+ const bem = (element?: string | string[], modifier?: string) => {
38
+ return modifier ? getModifierClass(modifier, element) : getElementClass(element);
39
+ };
40
+
41
+ return {
42
+ bem,
43
+ getElementClass,
44
+ getModifierClass
45
+ };
46
+ };
@@ -0,0 +1,40 @@
1
+ import { Ref, unref } from 'vue';
2
+ import { useEventListener } from '../use-event-listener';
3
+ import { inBrowser, initNodePath } from '../../utils';
4
+
5
+ export type ClickAwayOptions = {
6
+ eventName?: string
7
+ active?: Ref<boolean> | boolean
8
+ }
9
+
10
+ export function useClickAway(
11
+ target: Element | Ref<Element | undefined>,
12
+ listener: EventListener,
13
+ options: ClickAwayOptions = {},
14
+ ) {
15
+ if (!inBrowser) {
16
+ return;
17
+ }
18
+
19
+ const { eventName = 'click', active = true } = options;
20
+
21
+ const isOutsideElement = (event: Event)=>{
22
+ const _target = unref(target);
23
+ if(!_target){
24
+ return false;
25
+ }
26
+ // 多重条件,防止节点被删除后误触发
27
+ return document.contains(event.target as Node) && !_target.contains(event.target as Node);
28
+ };
29
+
30
+ const onClick = (event: Event) => {
31
+ const _active = unref(active);
32
+
33
+ const enableListener = _active && isOutsideElement(event);
34
+
35
+ if (enableListener) {
36
+ listener(event);
37
+ }
38
+ };
39
+ useEventListener(eventName, onClick, { target: document });
40
+ }
@@ -0,0 +1,40 @@
1
+ import { provide, InjectionKey } from 'vue';
2
+ import { ParentProvideValue } from '../types';
3
+
4
+ export function useChildrenContexts<ParentContext, ChildContext>(
5
+ parentKey: InjectionKey<ParentProvideValue<ParentContext, ChildContext>>,
6
+ parentContext?: ParentContext
7
+ ): { childContexts: Array<ChildContext> } {
8
+ const childContexts: Array<ChildContext> = [];
9
+
10
+ /**
11
+ * 注册子上下文
12
+ */
13
+ function addChild(childContext: ChildContext): void {
14
+ childContexts.push(childContext);
15
+ }
16
+
17
+ /**
18
+ * 移除子上下文
19
+ */
20
+ function removeChild(childContext: ChildContext): void {
21
+ const childIndex = childContexts.indexOf(childContext);
22
+ if (childIndex === -1) {
23
+ return;
24
+ }
25
+ childContexts.splice(childIndex, 1);
26
+ }
27
+
28
+ // 注入父上下文
29
+ const provideValue: ParentProvideValue<ParentContext, ChildContext> = {
30
+ addChild,
31
+ removeChild,
32
+ childContexts,
33
+ parentContext
34
+ };
35
+ provide(parentKey, provideValue);
36
+
37
+ return {
38
+ childContexts
39
+ };
40
+ }
@@ -0,0 +1,24 @@
1
+ import { inject, onUnmounted, InjectionKey } from 'vue';
2
+ import { ParentProvideValue } from '../types';
3
+
4
+ export function useParentContext<ParentContext, ChildContext>(
5
+ key: InjectionKey<ParentProvideValue<ParentContext, ChildContext>>,
6
+ childContext?: ChildContext
7
+ ): { parentContext: ParentContext } {
8
+ const parent = inject(key, null);
9
+ if (!parent) {
10
+ return {
11
+ parentContext: null
12
+ };
13
+ }
14
+
15
+ const { addChild, removeChild, parentContext } = parent;
16
+
17
+ addChild(childContext);
18
+ onUnmounted(() => {
19
+ removeChild(childContext);
20
+ });
21
+ return {
22
+ parentContext
23
+ };
24
+ }
@@ -0,0 +1,45 @@
1
+ import { onMountedOrActivated, inBrowser } from '../../utils';
2
+ import { unref, onUnmounted, onDeactivated, Ref } from 'vue';
3
+
4
+ export const supportsPassive = false;
5
+
6
+ export type UseEventListenerOptions = {
7
+ target?: EventTarget | Ref<EventTarget | undefined>;
8
+ capture?: boolean;
9
+ passive?: boolean;
10
+ immediate?: boolean;
11
+ };
12
+
13
+ export function useEventListener(type: string, listener: EventListener, options: UseEventListenerOptions = {}) {
14
+ if (!inBrowser) {
15
+ return;
16
+ }
17
+
18
+ const { target = window, passive = false, capture = false, immediate = false } = options;
19
+ let attached = false;
20
+
21
+ const add = () => {
22
+ const element = unref(target);
23
+
24
+ if (element && !attached) {
25
+ element.addEventListener(type, listener, supportsPassive ? {
26
+ capture,
27
+ passive
28
+ } : capture);
29
+ attached = true;
30
+ }
31
+ };
32
+
33
+ const remove = () => {
34
+ const element = unref(target);
35
+
36
+ if (element && attached) {
37
+ element.removeEventListener(type, listener, capture);
38
+ attached = false;
39
+ }
40
+ };
41
+
42
+ immediate ? add() : onMountedOrActivated(add);
43
+ onUnmounted(remove);
44
+ onDeactivated(remove);
45
+ }
@@ -0,0 +1,9 @@
1
+ import { getCurrentInstance } from 'vue';
2
+
3
+ // expose public api
4
+ export function useExpose(apis: Record<string, any>) {
5
+ const instance = getCurrentInstance();
6
+ if (instance) {
7
+ Object.assign(instance.proxy, apis);
8
+ }
9
+ }
@@ -0,0 +1,17 @@
1
+ import { ref, watch, WatchSource } from 'vue';
2
+
3
+ export function useLazyRender(show: WatchSource<boolean | undefined>) {
4
+ const inited = ref(false);
5
+
6
+ watch(
7
+ show,
8
+ (value) => {
9
+ if (value) {
10
+ inited.value = value;
11
+ }
12
+ },
13
+ { immediate: true }
14
+ );
15
+
16
+ return (render: () => JSX.Element) => () => (inited.value ? render() : null);
17
+ }
@@ -0,0 +1,14 @@
1
+ import { inject, provide } from "vue";
2
+
3
+ export const useLink = (key: string) => {
4
+ const setParent = <T>(context: T)=>{
5
+ provide(key, context);
6
+ };
7
+ const getParent = <T>(defaultValue?: any): T=>{
8
+ return inject(key, defaultValue);
9
+ };
10
+ return {
11
+ setParent,
12
+ getParent
13
+ };
14
+ };
@@ -0,0 +1,25 @@
1
+ let count = 0;
2
+
3
+ const CLASSNAME = 'fm-overflow-hidden';
4
+
5
+ export function useLockScroll(shouldLock: () => boolean) {
6
+ const lock = () => {
7
+ if (shouldLock()) {
8
+ if (!count) {
9
+ document.body.classList.add(CLASSNAME);
10
+ }
11
+ count++;
12
+ }
13
+ };
14
+
15
+ const unlock = () => {
16
+ if (shouldLock() && count) {
17
+ count--;
18
+ if (!count) {
19
+ document.body.classList.remove(CLASSNAME);
20
+ }
21
+ }
22
+ };
23
+
24
+ return [lock, unlock];
25
+ }
@@ -0,0 +1,141 @@
1
+ /* eslint-disable no-use-before-define */
2
+ import { ObjectDirective } from 'vue';
3
+
4
+ const DEFAULT_DELAY = 600;
5
+ const DEFAULT_THRESHOLD = 10;
6
+
7
+ export interface OnLongPressModifiers {
8
+ stop?: boolean;
9
+ once?: boolean;
10
+ prevent?: boolean;
11
+ capture?: boolean;
12
+ self?: boolean;
13
+ interceptClick?: boolean;
14
+ }
15
+
16
+ export interface OnLongPressOptions {
17
+
18
+ delay?: number;
19
+
20
+ modifiers?: OnLongPressModifiers;
21
+
22
+ distanceThreshold?: number | false;
23
+ }
24
+
25
+ interface Position {
26
+ x: number;
27
+ y: number;
28
+ }
29
+
30
+ function addEventListener(el: HTMLElement, event: string, listener: any, options: any): () => void {
31
+ el.addEventListener(event, listener, options);
32
+ return () => el.removeEventListener(event, listener, options);
33
+ }
34
+
35
+ export function onLongPress(
36
+ target: HTMLElement,
37
+ handler: (evt: TouchEvent) => void,
38
+ options?: OnLongPressOptions,
39
+ ) {
40
+ let timeout: ReturnType<typeof setTimeout> | undefined;
41
+ let posStart: Position | undefined;
42
+
43
+ function clear() {
44
+ if (timeout) {
45
+ clearTimeout(timeout);
46
+ timeout = undefined;
47
+ }
48
+ posStart = undefined;
49
+ }
50
+
51
+ function onStart(ev: TouchEvent) {
52
+ if (options?.modifiers?.self && ev.target !== target) {
53
+ return;
54
+ }
55
+
56
+ clear();
57
+
58
+ options?.modifiers?.prevent && ev.preventDefault();
59
+ options?.modifiers?.stop && ev.stopPropagation();
60
+
61
+ posStart = {
62
+ x: ev.touches[0].pageX,
63
+ y: ev.touches[0].pageY,
64
+ };
65
+ timeout = setTimeout(
66
+ () => {
67
+ timeout = undefined;
68
+ handler(ev);
69
+ },
70
+ options?.delay ?? DEFAULT_DELAY,
71
+ );
72
+ }
73
+
74
+ function onMove(ev: TouchEvent) {
75
+ if (options?.modifiers?.self && ev.target !== target) {
76
+ return;
77
+ }
78
+
79
+ if (!posStart || options?.distanceThreshold === false) {
80
+ return;
81
+ }
82
+
83
+ options?.modifiers?.prevent && ev.preventDefault();
84
+ options?.modifiers?.stop && ev.stopPropagation();
85
+
86
+ const dx = ev.touches[0].pageX - posStart.x;
87
+ const dy = ev.touches[0].pageY - posStart.y;
88
+ const distance = Math.sqrt(dx * dx + dy * dy);
89
+ if (distance >= (options?.distanceThreshold ?? DEFAULT_THRESHOLD)) {
90
+ clear();
91
+ }
92
+ }
93
+
94
+ function onEnd() {
95
+ if (options?.modifiers?.interceptClick && !timeout) {
96
+ addAutoDisappearMask();
97
+ }
98
+ clear();
99
+ }
100
+
101
+ const listenerOptions = {
102
+ capture: options?.modifiers?.capture,
103
+ once: options?.modifiers?.once,
104
+ };
105
+ const cleanup = [
106
+ addEventListener(target, 'touchstart', onStart, listenerOptions),
107
+ addEventListener(target, 'touchmove', onMove, listenerOptions),
108
+ addEventListener(target, 'touchend', onEnd, listenerOptions),
109
+ addEventListener(target, 'touchcancel', clear, listenerOptions),
110
+ ];
111
+ const stop = () => cleanup.forEach(fn => fn());
112
+ return stop;
113
+ }
114
+
115
+ type BindingValue = (evt: TouchEvent) => void;
116
+
117
+ export const vOnLongPress: ObjectDirective<HTMLElement, BindingValue> = {
118
+ mounted(el, binding) {
119
+ const delayStr = binding.arg || '';
120
+ let delay = parseInt(delayStr, 10) || DEFAULT_DELAY;
121
+ if (delay <= 0) {
122
+ delay = DEFAULT_DELAY;
123
+ }
124
+ onLongPress(el, binding.value, { delay, modifiers: binding.modifiers });
125
+ }
126
+ };
127
+
128
+ function addAutoDisappearMask(duration?: number): void {
129
+ console.log(duration);
130
+ const mask = document.createElement('div');
131
+ mask.style.position = 'fixed';
132
+ mask.style.top = '0';
133
+ mask.style.right = '0';
134
+ mask.style.bottom = '0';
135
+ mask.style.left = '0';
136
+ mask.style.zIndex = '99999';
137
+ document.body.appendChild(mask);
138
+ setTimeout(() => {
139
+ document.body.removeChild(mask);
140
+ }, duration || 25);
141
+ }
@@ -0,0 +1,82 @@
1
+ type MonmentumOption = {
2
+ maxOverflowY?: number,
3
+ TimeThreshold?: number,
4
+ YThreshold?: number
5
+ }
6
+
7
+ export const useMonmentum = (options: MonmentumOption) => {
8
+ const { maxOverflowY = 0, TimeThreshold = 200, YThreshold = 88 } = options;
9
+ let startTime = 0;
10
+ let momentumStartY = 0;
11
+ let deltaY = 0;
12
+ const start = (y: number) => {
13
+ startTime = new Date().getTime();
14
+ momentumStartY = y;
15
+ };
16
+ const move = (y: number) => {
17
+ deltaY = y;
18
+ const now = new Date().getTime();
19
+ const duration = now - startTime;
20
+ if (duration > TimeThreshold) {
21
+ momentumStartY = deltaY;
22
+ startTime = now;
23
+ }
24
+ };
25
+ const end = () => {
26
+ const now = new Date().getTime();
27
+ const duration = now - startTime;
28
+ const absDeltaY = Math.abs(deltaY - momentumStartY);
29
+ if (duration < TimeThreshold && absDeltaY > YThreshold) {
30
+ return true;
31
+ }
32
+ return false;
33
+ };
34
+ const get = (current: number, minY: number, maxY: number) => {
35
+ const durationMap = {
36
+ noBounce: 2500,
37
+ weekBounce: 800,
38
+ strongBounce: 400
39
+ };
40
+ const bezierMap = {
41
+ noBounce: 'cubic-bezier(.17, .89, .45, 1)',
42
+ weekBounce: 'cubic-bezier(.25, .46, .45, .94)',
43
+ strongBounce: 'cubic-bezier(.25, .46, .45, .94)'
44
+ };
45
+ let type = 'noBounce';
46
+ // 惯性滑动加速度
47
+ const deceleration = 0.003;
48
+ // 回弹阻力
49
+ const bounceRate = 10;
50
+ // 强弱回弹的分割值
51
+ const bounceThreshold = 300;
52
+
53
+ let overflowY = 0;
54
+ const now = new Date().getTime();
55
+ const duration = now - startTime;
56
+
57
+ const distance = current - momentumStartY;
58
+ const speed = (2 * Math.abs(distance)) / duration;
59
+ let destination = current + (speed / deceleration) * (distance < 0 ? -1 : 1);
60
+ if (destination < minY) {
61
+ overflowY = minY - destination;
62
+ type = overflowY > bounceThreshold ? 'strongBounce' : 'weekBounce';
63
+ destination = Math.max(minY - maxOverflowY, minY - overflowY / bounceRate);
64
+ } else if (destination > maxY) {
65
+ overflowY = destination - maxY;
66
+ type = overflowY > bounceThreshold ? 'strongBounce' : 'weekBounce';
67
+ destination = Math.min(maxY + maxOverflowY, maxY + overflowY / bounceRate);
68
+ }
69
+
70
+ return {
71
+ destination,
72
+ duration: durationMap[type],
73
+ bezier: bezierMap[type]
74
+ };
75
+ };
76
+ return {
77
+ start,
78
+ move,
79
+ end,
80
+ get
81
+ };
82
+ };
@@ -0,0 +1,48 @@
1
+ import { useExpose } from "../use-expose";
2
+ import { Component, createApp, nextTick, reactive } from "vue";
3
+
4
+ export function usePopupState() {
5
+ const state = reactive({
6
+ show: false,
7
+ });
8
+
9
+ const toggle = (show: boolean) => {
10
+ state.show = show;
11
+ };
12
+
13
+ const open = (props: Record<string, any>) => {
14
+ Object.assign(state, props);
15
+
16
+ nextTick(() => {
17
+ toggle(true);
18
+ });
19
+ };
20
+
21
+ const close = () => {
22
+ toggle(false);
23
+ };
24
+
25
+ useExpose({ open, close, toggle });
26
+
27
+ return {
28
+ open,
29
+ close,
30
+ state,
31
+ toggle,
32
+ };
33
+ }
34
+
35
+ export function mountComponent(RootComponent: Component) {
36
+ const app = createApp(RootComponent);
37
+ const root = document.createElement('div');
38
+
39
+ document.body.appendChild(root);
40
+
41
+ return {
42
+ instance: app.mount(root),
43
+ unmount() {
44
+ app.unmount();
45
+ document.body.removeChild(root);
46
+ },
47
+ };
48
+ }
@@ -0,0 +1,31 @@
1
+ import { Ref, unref } from 'vue';
2
+
3
+ const isWindow = (val: unknown): val is Window => val === window;
4
+
5
+ const makeDOMRect = (width: number, height: number) =>
6
+ ({
7
+ top: 0,
8
+ left: 0,
9
+ right: width,
10
+ bottom: height,
11
+ width,
12
+ height,
13
+ }) as DOMRect;
14
+
15
+ export const useRect = (
16
+ elementOrRef: Element | Window | Ref<Element | Window | undefined>,
17
+ ) => {
18
+ const element = unref(elementOrRef);
19
+
20
+ if (isWindow(element)) {
21
+ const width = element.innerWidth;
22
+ const height = element.innerHeight;
23
+ return makeDOMRect(width, height);
24
+ }
25
+
26
+ if (element?.getBoundingClientRect) {
27
+ return element.getBoundingClientRect();
28
+ }
29
+
30
+ return makeDOMRect(0, 0);
31
+ };
@@ -0,0 +1,21 @@
1
+ import { ref, Ref, onBeforeUpdate } from 'vue';
2
+
3
+ export function useRefs<T = Element>() {
4
+ const refs = ref([]) as Ref<T[]>;
5
+ const cache: Array<(el: unknown) => void> = [];
6
+
7
+ onBeforeUpdate(() => {
8
+ refs.value = [];
9
+ });
10
+
11
+ const setRefs = (index: number) => {
12
+ if (!cache[index]) {
13
+ cache[index] = (el: unknown) => {
14
+ refs.value[index] = el as T;
15
+ };
16
+ }
17
+ return cache[index];
18
+ };
19
+
20
+ return [refs, setRefs] as const;
21
+ }
@@ -0,0 +1,85 @@
1
+ /* eslint-disable no-use-before-define */
2
+ import { computed, watch } from 'vue';
3
+ import { MaybeComputedElementRef, unrefElement, tryOnScopeDispose, defaultWindow } from './utils';
4
+
5
+ export interface ResizeObserverSize {
6
+ readonly inlineSize: number;
7
+ readonly blockSize: number;
8
+ }
9
+
10
+ export interface ResizeObserverEntry {
11
+ readonly target: Element;
12
+ readonly contentRect: DOMRectReadOnly;
13
+ readonly borderBoxSize?: ReadonlyArray<ResizeObserverSize>;
14
+ readonly contentBoxSize?: ReadonlyArray<ResizeObserverSize>;
15
+ readonly devicePixelContentBoxSize?: ReadonlyArray<ResizeObserverSize>;
16
+ }
17
+
18
+ export type ResizeObserverCallback = (entries: ReadonlyArray<ResizeObserverEntry>, observer: ResizeObserver) => void;
19
+
20
+ export interface UseResizeObserverOptions {
21
+
22
+ /** 监听的盒模型,默认为`content-box` */
23
+ box?: ResizeObserverBoxOptions;
24
+
25
+ /** 允许指定一个的`window` */
26
+ window?: Window;
27
+ }
28
+
29
+ declare class ResizeObserver {
30
+
31
+ constructor(callback: ResizeObserverCallback);
32
+
33
+ disconnect(): void;
34
+
35
+ observe(target: Element, options?: UseResizeObserverOptions): void;
36
+
37
+ unobserve(target: Element): void;
38
+ }
39
+
40
+ /**
41
+ * 监听元素的大小变化
42
+ */
43
+ export function useResizeObserver(
44
+ target: MaybeComputedElementRef | MaybeComputedElementRef[],
45
+ callback: ResizeObserverCallback,
46
+ options: UseResizeObserverOptions = {},
47
+ ) {
48
+ const { window = defaultWindow, ...observerOptions } = options;
49
+ let observer: ResizeObserver | undefined;
50
+
51
+ const cleanup = () => {
52
+ if (observer) {
53
+ observer.disconnect();
54
+ observer = undefined;
55
+ }
56
+ };
57
+
58
+ const targets = computed(() =>
59
+ Array.isArray(target)
60
+ ? target.map(el => unrefElement(el))
61
+ : [unrefElement(target)]);
62
+
63
+ const stopWatch = watch(
64
+ targets,
65
+ (elements) => {
66
+ cleanup();
67
+ if (window && 'ResizeObserver' in window) {
68
+ observer = new ResizeObserver(callback);
69
+ elements.forEach((element) => {
70
+ element && observer!.observe(element, observerOptions);
71
+ });
72
+ }
73
+ },
74
+ { immediate: true, flush: 'post' },
75
+ );
76
+
77
+ const stop = () => {
78
+ cleanup();
79
+ stopWatch();
80
+ };
81
+
82
+ tryOnScopeDispose(stop);
83
+
84
+ return { stop };
85
+ }