Commit 144ab577da06ff0bd1f258d1901b87864f232e45

Authored by vben
1 parent 8d7d0835

fix(modal): height calc error #161

CHANGELOG.zh_CN.md
... ... @@ -13,6 +13,7 @@
13 13 - 恢复 table 的`isTreeTable`属性
14 14 - 修复表格内存溢出问题
15 15 - 修复`layout` 收缩展开功能在分割模式下失效
  16 +- 修复 modal 高度计算错误
16 17  
17 18 ## 2.0.0-rc.15 (2020-12-31)
18 19  
... ...
README.md
... ... @@ -256,8 +256,8 @@ yarn clean:lib # 删除node_modules,兼容window系统
256 256  
257 257 如果这些插件对你有帮助,可以给一个 star 支持下
258 258  
259   -- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock)
260   -- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html)
  259 +- [vite-plugin-mock](https://github.com/vbenjs/vite-plugin-mock)
  260 +- [vite-plugin-html](https://github.com/vbenjs/vite-plugin-html)
261 261  
262 262 ## 加入我们
263 263  
... ...
src/components/Basic/src/BasicArrow.vue
... ... @@ -15,6 +15,7 @@
15 15  
16 16 export default defineComponent({
17 17 name: 'BasicArrow',
  18 + inheritAttrs: false,
18 19 components: { RightOutlined },
19 20 props: {
20 21 // Expand contract, expand by default
... ...
src/components/Basic/src/BasicHelp.vue
... ... @@ -12,6 +12,7 @@
12 12 import { useDesign } from '/@/hooks/web/useDesign';
13 13 export default defineComponent({
14 14 name: 'BasicHelp',
  15 + inheritAttrs: false,
15 16 components: { Tooltip },
16 17 props: {
17 18 // max-width
... ...
src/components/Basic/src/BasicTitle.vue
... ... @@ -15,6 +15,7 @@
15 15  
16 16 export default defineComponent({
17 17 name: 'BasicTitle',
  18 + inheritAttrs: false,
18 19 components: { BasicHelp },
19 20 props: {
20 21 helpMessage: {
... ...
src/components/Container/src/LazyContainer.vue
... ... @@ -35,6 +35,7 @@
35 35  
36 36 export default defineComponent({
37 37 name: 'LazyContainer',
  38 + inheritAttrs: false,
38 39 components: { Skeleton },
39 40 props: {
40 41 // Waiting time, if the time is specified, whether visible or not, it will be automatically loaded after the specified time
... ...
src/components/Container/src/ScrollContainer.vue
... ... @@ -12,6 +12,7 @@
12 12  
13 13 export default defineComponent({
14 14 name: 'ScrollContainer',
  15 + inheritAttrs: false,
15 16 components: { Scrollbar },
16 17 setup() {
17 18 const scrollbarRef = ref<Nullable<ScrollbarType>>(null);
... ...
src/components/Markdown/src/index.vue
... ... @@ -8,19 +8,23 @@
8 8  
9 9 import { propTypes } from '/@/utils/propTypes';
10 10 import { useLocale } from '/@/hooks/web/useLocale';
  11 + import { useModalContext } from '../../Modal';
11 12  
12 13 type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
13 14 export default defineComponent({
14   - emits: ['change'],
  15 + inheritAttrs: false,
15 16 props: {
16 17 height: propTypes.number.def(360),
17 18 value: propTypes.string.def(''),
18 19 },
  20 + emits: ['change', 'get'],
19 21 setup(props, { attrs, emit }) {
20 22 const wrapRef = ref<ElRef>(null);
21 23 const vditorRef = ref<Nullable<Vditor>>(null);
22 24 const initedRef = ref(false);
23 25  
  26 + const modalFn = useModalContext();
  27 +
24 28 const lang = ref<Lang>();
25 29  
26 30 const { getLang } = useLocale();
... ... @@ -66,10 +70,19 @@
66 70 initedRef.value = true;
67 71 }
68 72  
  73 + const instance = {
  74 + getVditor: (): Vditor => vditorRef.value!,
  75 + };
  76 +
69 77 onMounted(() => {
70 78 nextTick(() => {
71 79 init();
  80 + setTimeout(() => {
  81 + modalFn?.redoModalHeight?.();
  82 + }, 200);
72 83 });
  84 +
  85 + emit('get', instance);
73 86 });
74 87  
75 88 onUnmounted(() => {
... ... @@ -82,7 +95,7 @@
82 95  
83 96 return {
84 97 wrapRef,
85   - getVditor: (): Vditor => vditorRef.value!,
  98 + ...instance,
86 99 };
87 100 },
88 101 });
... ...
src/components/Modal/src/BasicModal.vue
... ... @@ -27,7 +27,7 @@
27 27 :height="getProps.height"
28 28 :visible="visibleRef"
29 29 :modalFooterHeight="footer !== undefined && !footer ? 0 : undefined"
30   - v-bind="omit(getProps.wrapperProps, 'visible')"
  30 + v-bind="omit(getProps.wrapperProps, 'visible', 'height')"
31 31 @ext-height="handleExtHeight"
32 32 @height-change="handleHeightChange"
33 33 >
... ... @@ -51,6 +51,7 @@
51 51 watchEffect,
52 52 toRef,
53 53 getCurrentInstance,
  54 + nextTick,
54 55 } from 'vue';
55 56  
56 57 import Modal from './components/Modal';
... ... @@ -67,6 +68,7 @@
67 68 import { omit } from 'lodash-es';
68 69 export default defineComponent({
69 70 name: 'BasicModal',
  71 + inheritAttrs: false,
70 72 components: { Modal, ModalWrapper, ModalClose, ModalFooter, ModalHeader },
71 73 props: basicProps,
72 74 emits: ['visible-change', 'height-change', 'cancel', 'ok', 'register'],
... ...
src/components/Modal/src/components/ModalWrapper.vue
... ... @@ -31,6 +31,7 @@
31 31  
32 32 export default defineComponent({
33 33 name: 'ModalWrapper',
  34 + inheritAttrs: false,
34 35 components: { Spin, ScrollContainer },
35 36 props: {
36 37 loading: propTypes.bool,
... ... @@ -51,6 +52,8 @@
51 52 const realHeightRef = ref(0);
52 53 const minRealHeightRef = ref(0);
53 54  
  55 + let realHeight = 0;
  56 +
54 57 let stopElResizeFn: Fn = () => {};
55 58  
56 59 useWindowSizeFn(setModalHeight);
... ... @@ -137,8 +140,9 @@
137 140  
138 141 if (!spinEl) return;
139 142  
140   - const realHeight = spinEl.scrollHeight;
141   -
  143 + if (!realHeight) {
  144 + realHeight = spinEl.scrollHeight;
  145 + }
142 146 if (props.fullScreen) {
143 147 realHeightRef.value =
144 148 window.innerHeight - props.modalFooterHeight - props.modalHeaderHeight;
... ... @@ -147,7 +151,7 @@
147 151 ? props.height
148 152 : realHeight > maxHeight
149 153 ? maxHeight
150   - : realHeight + 16 + 30;
  154 + : realHeight + 46;
151 155 }
152 156 emit('height-change', unref(realHeightRef));
153 157 } catch (error) {
... ...
src/components/Scrollbar/src/index.vue
... ... @@ -33,6 +33,7 @@
33 33  
34 34 export default defineComponent({
35 35 name: 'Scrollbar',
  36 + inheritAttrs: false,
36 37 components: { Bar },
37 38 props: {
38 39 native: {
... ... @@ -91,12 +92,18 @@
91 92 onMounted(() => {
92 93 if (props.native) return;
93 94 nextTick(update);
94   - !props.noresize && addResizeListener(resize.value, update);
  95 + if (!props.noresize) {
  96 + addResizeListener(resize.value, update);
  97 + addResizeListener(wrap.value, update);
  98 + }
95 99 });
96 100  
97 101 onBeforeUnmount(() => {
98 102 if (props.native) return;
99   - !props.noresize && removeResizeListener(resize.value, update);
  103 + if (!props.noresize) {
  104 + removeResizeListener(resize.value, update);
  105 + removeResizeListener(wrap.value, update);
  106 + }
100 107 });
101 108 const style = computed(() => {
102 109 let style: any = props.wrapStyle;
... ... @@ -127,7 +134,7 @@
127 134  
128 135 &__wrap {
129 136 height: 100%;
130   - overflow: scroll;
  137 + overflow: auto;
131 138  
132 139 &--hidden-default {
133 140 scrollbar-width: none;
... ...
src/components/Tinymce/src/Editor.vue
... ... @@ -31,6 +31,7 @@
31 31  
32 32 export default defineComponent({
33 33 name: 'Tinymce',
  34 + inheritAttrs: false,
34 35 props: basicProps,
35 36 emits: ['change', 'update:modelValue'],
36 37 setup(props, { emit, attrs }) {
... ...
src/components/Tree/src/BasicTree.tsx
... ... @@ -15,6 +15,7 @@ import { extendSlots } from &#39;/@/utils/helper/tsxHelper&#39;;
15 15 import { basicProps } from './props';
16 16 import { useTree } from './useTree';
17 17 import { useExpose } from '/@/hooks/core/useExpose';
  18 +import { onMounted } from 'vue';
18 19  
19 20 interface State {
20 21 expandedKeys: Keys;
... ... @@ -25,7 +26,7 @@ const prefixCls = &#39;basic-tree&#39;;
25 26 export default defineComponent({
26 27 name: 'BasicTree',
27 28 props: basicProps,
28   - emits: ['update:expandedKeys', 'update:selectedKeys', 'update:value'],
  29 + emits: ['update:expandedKeys', 'update:selectedKeys', 'update:value', 'get'],
29 30 setup(props, { attrs, slots, emit }) {
30 31 const state = reactive<State>({
31 32 expandedKeys: props.expandedKeys || [],
... ... @@ -182,7 +183,7 @@ export default defineComponent({
182 183 state.checkedKeys = props.checkedKeys;
183 184 });
184 185  
185   - useExpose<TreeActionType>({
  186 + const instance: TreeActionType = {
186 187 setExpandedKeys,
187 188 getExpandedKeys,
188 189 setSelectedKeys,
... ... @@ -195,6 +196,12 @@ export default defineComponent({
195 196 filterByLevel: (level: number) => {
196 197 state.expandedKeys = filterByLevel(level);
197 198 },
  199 + };
  200 +
  201 + useExpose<TreeActionType>(instance);
  202 +
  203 + onMounted(() => {
  204 + emit('get', instance);
198 205 });
199 206  
200 207 return () => {
... ...
src/hooks/component/usePageContext.ts
1 1 import type { InjectionKey, ComputedRef, Ref } from 'vue';
2 2 import { createContext, useContext } from '/@/hooks/core/useContext';
3 3  
4   -import {} from 'vue';
5   -
6 4 export interface PageContextProps {
7 5 contentHeight: ComputedRef<number>;
8 6 pageHeight: Ref<number>;
... ...
src/layouts/default/sider/MixSider.vue
... ... @@ -113,7 +113,6 @@
113 113 const activePath = ref('');
114 114 const chilrenMenus = ref<Menu[]>([]);
115 115 const openMenu = ref(false);
116   - const isInit = ref(false);
117 116 const dragBarRef = ref<ElRef>(null);
118 117 const sideRef = ref<ElRef>(null);
119 118 const currentRoute = ref<Nullable<RouteLocationNormalized>>(null);
... ... @@ -251,8 +250,8 @@
251 250 }
252 251  
253 252 function handleClickOutside() {
  253 + setActive(true);
254 254 closeMenu();
255   - setActive();
256 255 }
257 256  
258 257 function getItemEvents(item: Menu) {
... ...
src/utils/browser.ts
... ... @@ -75,7 +75,7 @@ export function isOperaFn() {
75 75 * set page Title
76 76 * @param {*} title :page Title
77 77 */
78   -const setDocumentTitle = (title: string) => {
  78 +function setDocumentTitle(title: string) {
79 79 document.title = title;
80 80 const ua = navigator.userAgent;
81 81 const regex = /\bMicroMessenger\/([\d.]+)/;
... ... @@ -91,7 +91,7 @@ const setDocumentTitle = (title: string) =&gt; {
91 91 };
92 92 document.body.appendChild(i);
93 93 }
94   -};
  94 +}
95 95  
96 96 export function setTitle(title: string, appTitle?: string) {
97 97 if (title) {
... ...
src/utils/color.ts
... ... @@ -5,10 +5,10 @@
5 5 * @param String color 十六进制颜色值
6 6 * @return Boolean
7 7 */
8   -export const isHexColor = function (color: string) {
  8 +export function isHexColor(color: string) {
9 9 const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
10 10 return reg.test(color);
11   -};
  11 +}
12 12  
13 13 /**
14 14 * RGB 颜色值转换为 十六进制颜色值.
... ... @@ -19,18 +19,18 @@ export const isHexColor = function (color: string) {
19 19 * @param g
20 20 * @param b
21 21 */
22   -export const rgbToHex = function (r: number, g: number, b: number) {
  22 +export function rgbToHex(r: number, g: number, b: number) {
23 23 // tslint:disable-next-line:no-bitwise
24 24 const hex = ((r << 16) | (g << 8) | b).toString(16);
25 25 return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex;
26   -};
  26 +}
27 27  
28 28 /**
29 29 * Transform a HEX color to its RGB representation
30 30 * @param {string} hex The color to transform
31 31 * @returns The RGB representation of the passed color
32 32 */
33   -export const hexToRGB = function (hex: string) {
  33 +export function hexToRGB(hex: string) {
34 34 let sHex = hex.toLowerCase();
35 35 if (isHexColor(hex)) {
36 36 if (sHex.length === 4) {
... ... @@ -47,16 +47,16 @@ export const hexToRGB = function (hex: string) {
47 47 return 'RGB(' + sColorChange.join(',') + ')';
48 48 }
49 49 return sHex;
50   -};
  50 +}
51 51  
52   -export const colorIsDark = (color: string) => {
  52 +export function colorIsDark(color: string) {
53 53 if (!isHexColor(color)) return;
54 54 const [r, g, b] = hexToRGB(color)
55 55 .replace(/(?:\(|\)|rgb|RGB)*/g, '')
56 56 .split(',')
57 57 .map((item) => Number(item));
58 58 return r * 0.299 + g * 0.578 + b * 0.114 < 192;
59   -};
  59 +}
60 60  
61 61 /**
62 62 * Darkens a HEX color given the passed percentage
... ... @@ -64,14 +64,14 @@ export const colorIsDark = (color: string) =&gt; {
64 64 * @param {number} amount The amount to change the color by
65 65 * @returns {string} The HEX representation of the processed color
66 66 */
67   -export const darken = (color: string, amount: number) => {
  67 +export function darken(color: string, amount: number) {
68 68 color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
69 69 amount = Math.trunc((255 * amount) / 100);
70 70 return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight(
71 71 color.substring(2, 4),
72 72 amount
73 73 )}${subtractLight(color.substring(4, 6), amount)}`;
74   -};
  74 +}
75 75  
76 76 /**
77 77 * Lightens a 6 char HEX color according to the passed percentage
... ... @@ -79,14 +79,14 @@ export const darken = (color: string, amount: number) =&gt; {
79 79 * @param {number} amount The amount to change the color by
80 80 * @returns {string} The processed color represented as HEX
81 81 */
82   -export const lighten = (color: string, amount: number) => {
  82 +export function lighten(color: string, amount: number) {
83 83 color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color;
84 84 amount = Math.trunc((255 * amount) / 100);
85 85 return `#${addLight(color.substring(0, 2), amount)}${addLight(
86 86 color.substring(2, 4),
87 87 amount
88 88 )}${addLight(color.substring(4, 6), amount)}`;
89   -};
  89 +}
90 90  
91 91 /* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */
92 92 /**
... ... @@ -95,11 +95,11 @@ export const lighten = (color: string, amount: number) =&gt; {
95 95 * @param {number} amount The amount to change the color by
96 96 * @returns {string} The processed part of the color
97 97 */
98   -const addLight = (color: string, amount: number) => {
  98 +function addLight(color: string, amount: number) {
99 99 const cc = parseInt(color, 16) + amount;
100 100 const c = cc > 255 ? 255 : cc;
101 101 return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
102   -};
  102 +}
103 103  
104 104 /**
105 105 * Calculates luminance of an rgb color
... ... @@ -107,33 +107,36 @@ const addLight = (color: string, amount: number) =&gt; {
107 107 * @param {number} g green
108 108 * @param {number} b blue
109 109 */
110   -const luminanace = (r: number, g: number, b: number) => {
  110 +function luminanace(r: number, g: number, b: number) {
111 111 const a = [r, g, b].map((v) => {
112 112 v /= 255;
113 113 return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
114 114 });
115 115 return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
116   -};
  116 +}
117 117  
118 118 /**
119 119 * Calculates contrast between two rgb colors
120 120 * @param {string} rgb1 rgb color 1
121 121 * @param {string} rgb2 rgb color 2
122 122 */
123   -const contrast = (rgb1: string[], rgb2: number[]) =>
124   - (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
125   - (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05);
  123 +function contrast(rgb1: string[], rgb2: number[]) {
  124 + return (
  125 + (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
  126 + (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05)
  127 + );
  128 +}
126 129  
127 130 /**
128 131 * Determines what the best text color is (black or white) based con the contrast with the background
129 132 * @param hexColor - Last selected color by the user
130 133 */
131   -export const calculateBestTextColor = (hexColor: string) => {
  134 +export function calculateBestTextColor(hexColor: string) {
132 135 const rgbColor = hexToRGB(hexColor.substring(1));
133 136 const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]);
134 137  
135 138 return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF';
136   -};
  139 +}
137 140  
138 141 /**
139 142 * Subtracts the indicated percentage to the R, G or B of a HEX color
... ... @@ -141,8 +144,8 @@ export const calculateBestTextColor = (hexColor: string) =&gt; {
141 144 * @param {number} amount The amount to change the color by
142 145 * @returns {string} The processed part of the color
143 146 */
144   -const subtractLight = (color: string, amount: number) => {
  147 +function subtractLight(color: string, amount: number) {
145 148 const cc = parseInt(color, 16) - amount;
146 149 const c = cc < 0 ? 0 : cc;
147 150 return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`;
148   -};
  151 +}
... ...
src/utils/dateUtil.ts
... ... @@ -14,7 +14,7 @@ export function formatToDate(date: moment.MomentInput = null, format = DATE_FORM
14 14 return moment(date).format(format);
15 15 }
16 16  
17   -export const formatAgo = (str: string | number) => {
  17 +export function formatAgo(str: string | number) {
18 18 if (!str) return '';
19 19 const date = new Date(Number(str));
20 20 const time = new Date().getTime() - date.getTime(); // 现在的时间-传入的时间 = 相差的时间(单位 = 毫秒)
... ... @@ -35,6 +35,6 @@ export const formatAgo = (str: string | number) =&gt; {
35 35 } else {
36 36 return parseInt(String(time / 31536000000)) + '年前';
37 37 }
38   -};
  38 +}
39 39  
40 40 export const dateUtil = moment;
... ...
src/utils/domUtils.ts
... ... @@ -132,7 +132,7 @@ export function hackCss(attr: string, value: string) {
132 132 }
133 133  
134 134 /* istanbul ignore next */
135   -export const on = function (
  135 +export function on(
136 136 element: Element | HTMLElement | Document | Window,
137 137 event: string,
138 138 handler: EventListenerOrEventListenerObject
... ... @@ -140,10 +140,10 @@ export const on = function (
140 140 if (element && event && handler) {
141 141 element.addEventListener(event, handler, false);
142 142 }
143   -};
  143 +}
144 144  
145 145 /* istanbul ignore next */
146   -export const off = function (
  146 +export function off(
147 147 element: Element | HTMLElement | Document | Window,
148 148 event: string,
149 149 handler: Fn
... ... @@ -151,10 +151,10 @@ export const off = function (
151 151 if (element && event && handler) {
152 152 element.removeEventListener(event, handler, false);
153 153 }
154   -};
  154 +}
155 155  
156 156 /* istanbul ignore next */
157   -export const once = function (el: HTMLElement, event: string, fn: EventListener): void {
  157 +export function once(el: HTMLElement, event: string, fn: EventListener): void {
158 158 const listener = function (this: any, ...args: unknown[]) {
159 159 if (fn) {
160 160 fn.apply(this, args);
... ... @@ -162,4 +162,4 @@ export const once = function (el: HTMLElement, event: string, fn: EventListener)
162 162 off(el, event, listener);
163 163 };
164 164 on(el, event, listener);
165   -};
  165 +}
... ...
src/utils/env.ts
1 1 import type { GlobEnvConfig } from '/@/types/config';
2 2  
3   -export const getGlobEnvConfig = (): GlobEnvConfig => {
  3 +export function getGlobEnvConfig(): GlobEnvConfig {
4 4 const env = import.meta.env;
5 5 return (env as unknown) as GlobEnvConfig;
6   -};
  6 +}
7 7  
8 8 /**
9 9 * @description: 开发模式
... ... @@ -20,25 +20,33 @@ export const prodMode = &#39;production&#39;;
20 20 * @returns:
21 21 * @example:
22 22 */
23   -export const getEnv = (): string => import.meta.env.MODE;
  23 +export function getEnv(): string {
  24 + return import.meta.env.MODE;
  25 +}
24 26  
25 27 /**
26 28 * @description: 是否是开发模式
27 29 * @returns:
28 30 * @example:
29 31 */
30   -export const isDevMode = (): boolean => import.meta.env.DEV;
  32 +export function isDevMode(): boolean {
  33 + return import.meta.env.DEV;
  34 +}
31 35  
32 36 /**
33 37 * @description: 是否是生产模式模式
34 38 * @returns:
35 39 * @example:
36 40 */
37   -export const isProdMode = (): boolean => import.meta.env.PROD;
  41 +export function isProdMode(): boolean {
  42 + return import.meta.env.PROD;
  43 +}
38 44  
39 45 /**
40 46 * @description: 是否开启mock
41 47 * @returns:
42 48 * @example:
43 49 */
44   -export const isUseMock = (): boolean => import.meta.env.VITE_USE_MOCK === 'true';
  50 +export function isUseMock(): boolean {
  51 + return import.meta.env.VITE_USE_MOCK === 'true';
  52 +}
... ...
src/utils/event/resizeEvent.ts
... ... @@ -3,7 +3,7 @@ import ResizeObserver from &#39;resize-observer-polyfill&#39;;
3 3 const isServer = typeof window === 'undefined';
4 4  
5 5 /* istanbul ignore next */
6   -const resizeHandler = function (entries: any[]) {
  6 +function resizeHandler(entries: any[]) {
7 7 for (const entry of entries) {
8 8 const listeners = entry.target.__resizeListeners__ || [];
9 9 if (listeners.length) {
... ... @@ -12,10 +12,10 @@ const resizeHandler = function (entries: any[]) {
12 12 });
13 13 }
14 14 }
15   -};
  15 +}
16 16  
17 17 /* istanbul ignore next */
18   -export const addResizeListener = function (element: any, fn: () => any) {
  18 +export function addResizeListener(element: any, fn: () => any) {
19 19 if (isServer) return;
20 20 if (!element.__resizeListeners__) {
21 21 element.__resizeListeners__ = [];
... ... @@ -23,13 +23,13 @@ export const addResizeListener = function (element: any, fn: () =&gt; any) {
23 23 element.__ro__.observe(element);
24 24 }
25 25 element.__resizeListeners__.push(fn);
26   -};
  26 +}
27 27  
28 28 /* istanbul ignore next */
29   -export const removeResizeListener = function (element: any, fn: () => any) {
  29 +export function removeResizeListener(element: any, fn: () => any) {
30 30 if (!element || !element.__resizeListeners__) return;
31 31 element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
32 32 if (!element.__resizeListeners__.length) {
33 33 element.__ro__.disconnect();
34 34 }
35   -};
  35 +}
... ...
src/utils/event/triggerWindowResizeEvent.ts
... ... @@ -4,6 +4,6 @@
4 4 export function triggerWindowResize() {
5 5 const event = document.createEvent('HTMLEvents');
6 6 event.initEvent('resize', true, true);
7   - (event as ChangeEvent).eventType = 'message';
  7 + (event as any).eventType = 'message';
8 8 window.dispatchEvent(event);
9 9 }
... ...
src/utils/helper/envHelper.ts
... ... @@ -4,6 +4,6 @@ import pkg from &#39;../../../package.json&#39;;
4 4 const globSetting = useGlobSetting();
5 5  
6 6 // Generate cache key according to version
7   -export const getStorageShortName = () => {
  7 +export function getStorageShortName() {
8 8 return `${globSetting.shortName}__${getEnv()}${`__${pkg.version}`}__`.toUpperCase();
9   -};
  9 +}
... ...
src/utils/index.ts
... ... @@ -85,3 +85,17 @@ export function getDynamicProps&lt;T, U&gt;(props: T): Partial&lt;U&gt; {
85 85  
86 86 return ret as Partial<U>;
87 87 }
  88 +
  89 +export function getLastItem<T extends any>(list: T) {
  90 + if (Array.isArray(list)) {
  91 + return list.slice(-1)[0];
  92 + }
  93 +
  94 + if (list instanceof Set) {
  95 + return Array.from(list).slice(-1)[0];
  96 + }
  97 +
  98 + if (list instanceof Map) {
  99 + return Array.from(list.values()).slice(-1)[0];
  100 + }
  101 +}
... ...
src/utils/is.ts
... ... @@ -4,17 +4,33 @@ export function is(val: unknown, type: string) {
4 4 return toString.call(val) === `[object ${type}]`;
5 5 }
6 6  
7   -export const isDef = <T = unknown>(val?: T): val is T => {
  7 +export function isDef<T = unknown>(val?: T): val is T {
8 8 return typeof val !== 'undefined';
9   -};
  9 +}
10 10  
11   -export const isUnDef = <T = unknown>(val?: T): val is T => {
  11 +export function isUnDef<T = unknown>(val?: T): val is T {
12 12 return !isDef(val);
13   -};
  13 +}
14 14  
15   -export const isObject = (val: any): val is Record<any, any> => {
  15 +export function isObject(val: any): val is Record<any, any> {
16 16 return val !== null && is(val, 'Object');
17   -};
  17 +}
  18 +
  19 +export function isEmpty<T = unknown>(val: T): val is T {
  20 + if (isArray(val) || isString(val)) {
  21 + return val.length === 0;
  22 + }
  23 +
  24 + if (val instanceof Map || val instanceof Set) {
  25 + return val.size === 0;
  26 + }
  27 +
  28 + if (isObject(val)) {
  29 + return Object.keys(val).length === 0;
  30 + }
  31 +
  32 + return false;
  33 +}
18 34  
19 35 export function isDate(val: unknown): val is Date {
20 36 return is(val, 'Date');
... ... @@ -40,7 +56,9 @@ export function isString(val: unknown): val is string {
40 56 return is(val, 'String');
41 57 }
42 58  
43   -export const isFunction = (val: unknown): val is Function => typeof val === 'function';
  59 +export function isFunction(val: unknown): val is Function {
  60 + return typeof val === 'function';
  61 +}
44 62  
45 63 export function isBoolean(val: unknown): val is boolean {
46 64 return is(val, 'Boolean');
... ... @@ -54,13 +72,13 @@ export function isArray(val: any): val is Array&lt;any&gt; {
54 72 return val && Array.isArray(val);
55 73 }
56 74  
57   -export const isWindow = (val: any): val is Window => {
  75 +export function isWindow(val: any): val is Window {
58 76 return typeof window !== 'undefined' && is(val, 'Window');
59   -};
  77 +}
60 78  
61   -export const isElement = (val: unknown): val is Element => {
  79 +export function isElement(val: unknown): val is Element {
62 80 return isObject(val) && !!val.tagName;
63   -};
  81 +}
64 82  
65 83 export const isServer = typeof window === 'undefined';
66 84  
... ... @@ -70,17 +88,17 @@ export function isImageDom(o: Element) {
70 88 return o && ['IMAGE', 'IMG'].includes(o.tagName);
71 89 }
72 90  
73   -export const isTextarea = (element: Element | null): element is HTMLTextAreaElement => {
  91 +export function isTextarea(element: Element | null): element is HTMLTextAreaElement {
74 92 return element !== null && element.tagName.toLowerCase() === 'textarea';
75   -};
  93 +}
76 94  
77   -export const isMobile = (): boolean => {
  95 +export function isMobile(): boolean {
78 96 return !!navigator.userAgent.match(
79 97 /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
80 98 );
81   -};
  99 +}
82 100  
83   -export const isUrl = (path: string): boolean => {
  101 +export function isUrl(path: string): boolean {
84 102 const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
85 103 return reg.test(path);
86   -};
  104 +}
... ...
src/utils/scrollbarWidth.ts deleted 100644 → 0
1   -import { isWindow } from '/@/utils/is';
2   -
3   -let scrollBarWidth: number;
4   -
5   -export default function (): number {
6   - if (!isWindow) return 0;
7   - if (scrollBarWidth !== undefined) return scrollBarWidth;
8   -
9   - const outer = document.createElement('div');
10   - outer.className = 'scrollbar__wrap';
11   - outer.style.visibility = 'hidden';
12   - outer.style.width = '100px';
13   - outer.style.position = 'absolute';
14   - outer.style.top = '-9999px';
15   - document.body.appendChild(outer);
16   -
17   - const widthNoScroll = outer.offsetWidth;
18   - outer.style.overflow = 'scroll';
19   -
20   - const inner = document.createElement('div');
21   - inner.style.width = '100%';
22   - outer.appendChild(inner);
23   -
24   - const widthWithScroll = inner.offsetWidth;
25   - const parentNode = outer.parentNode;
26   - parentNode && parentNode.removeChild(outer);
27   - scrollBarWidth = widthNoScroll - widthWithScroll;
28   -
29   - return scrollBarWidth;
30   -}