vft 0.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.
- package/package.json +54 -0
- package/src/app/index.ts +3 -0
- package/src/app/page-loading/assets/spin.gif +0 -0
- package/src/app/page-loading/index.less +10 -0
- package/src/app/page-loading/index.ts +3 -0
- package/src/app/page-loading/index.vue +38 -0
- package/src/app/table/assets/sort_triangle.png +0 -0
- package/src/app/table/demos/basic.vue +117 -0
- package/src/app/table/demos/complex.vue +2543 -0
- package/src/app/table/demos/index.vue +453 -0
- package/src/app/table/demos/rightAngle.png +0 -0
- package/src/app/table/header.vue +203 -0
- package/src/app/table/index.less +119 -0
- package/src/app/table/index.ts +5 -0
- package/src/app/table/index.vue +478 -0
- package/src/app/table/md/api.md +23 -0
- package/src/app/table/md/demo.md +3 -0
- package/src/app/table/types.ts +45 -0
- package/src/common/badge/index.scss +78 -0
- package/src/common/badge/index.ts +4 -0
- package/src/common/badge/index.vue +111 -0
- package/src/common/badge/types.ts +1 -0
- package/src/common/clamp/clamp-toggle.vue +91 -0
- package/src/common/clamp/index.ts +4 -0
- package/src/common/clamp/index.vue +247 -0
- package/src/common/code/index.less +321 -0
- package/src/common/code/index.ts +3 -0
- package/src/common/code/index.vue +60 -0
- package/src/common/config-provider/index.ts +4 -0
- package/src/common/config-provider/index.vue +94 -0
- package/src/common/config-provider/types.ts +29 -0
- package/src/common/icon/iconfont/iconfont.css +334 -0
- package/src/common/icon/index.scss +31 -0
- package/src/common/icon/index.ts +4 -0
- package/src/common/icon/index.vue +74 -0
- package/src/common/icon/types.ts +16 -0
- package/src/common/index.ts +6 -0
- package/src/common/message/index.ts +5 -0
- package/src/common/message/instance.ts +29 -0
- package/src/common/message/message.scss +108 -0
- package/src/common/message/message.ts +80 -0
- package/src/common/message/message.vue +162 -0
- package/src/common/message/method.ts +172 -0
- package/src/common/overlay/index.scss +14 -0
- package/src/common/overlay/index.ts +3 -0
- package/src/common/overlay/index.vue +117 -0
- package/src/constants/comp.ts +1 -0
- package/src/constants/index.ts +1 -0
- package/src/index.ts +3 -0
- package/src/page/index.ts +1 -0
- package/src/page/page-wrapper/index.scss +31 -0
- package/src/page/page-wrapper/index.ts +5 -0
- package/src/page/page-wrapper/index.vue +31 -0
- package/src/styles/vars.scss +500 -0
- package/src/use/index.ts +14 -0
- package/src/use/onPopupReopen.ts +15 -0
- package/src/use/use-delayed-toggle/index.ts +30 -0
- package/src/use/use-floating/index.ts +121 -0
- package/src/use/use-forward-ref.ts +35 -0
- package/src/use/use-global-config/index.ts +81 -0
- package/src/use/use-id/index.ts +43 -0
- package/src/use/use-model-toggle/index.ts +151 -0
- package/src/use/use-namespace/index.ts +91 -0
- package/src/use/use-ordered-children/index.ts +43 -0
- package/src/use/use-popper-container/index.ts +43 -0
- package/src/use/use-timeout/index.ts +18 -0
- package/src/use/use-z-index/index.ts +20 -0
- package/src/use/useGlobalZIndex.ts +24 -0
- package/src/use/useLazyRender.ts +17 -0
- package/src/use/useLockScroll.ts +66 -0
- package/src/utils/aria.ts +126 -0
- package/src/utils/arrays.ts +13 -0
- package/src/utils/error.ts +23 -0
- package/src/utils/event.ts +15 -0
- package/src/utils/helper.ts +7 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/interceptor.ts +39 -0
- package/src/utils/mount-component.ts +65 -0
- package/src/utils/popper.ts +6 -0
- package/src/utils/rand.ts +12 -0
- package/src/utils/scroll.ts +101 -0
- package/src/utils/vnode.ts +169 -0
- package/src/web/avatar/index.scss +50 -0
- package/src/web/avatar/index.ts +3 -0
- package/src/web/avatar/index.vue +83 -0
- package/src/web/back-top/index.scss +35 -0
- package/src/web/back-top/index.ts +3 -0
- package/src/web/back-top/index.vue +72 -0
- package/src/web/back-top/types.ts +14 -0
- package/src/web/back-top/use-back-top.ts +65 -0
- package/src/web/cascader/index.scss +214 -0
- package/src/web/cascader/index.ts +5 -0
- package/src/web/cascader/index.vue +767 -0
- package/src/web/cascader-panel/config.ts +44 -0
- package/src/web/cascader-panel/index.scss +134 -0
- package/src/web/cascader-panel/index.ts +5 -0
- package/src/web/cascader-panel/index.vue +319 -0
- package/src/web/cascader-panel/menu.vue +135 -0
- package/src/web/cascader-panel/node-content.ts +23 -0
- package/src/web/cascader-panel/node.ts +218 -0
- package/src/web/cascader-panel/node.vue +197 -0
- package/src/web/cascader-panel/store.ts +83 -0
- package/src/web/cascader-panel/types.ts +56 -0
- package/src/web/cascader-panel/utils.ts +40 -0
- package/src/web/cascader-select/README.md +31 -0
- package/src/web/cascader-select/index.scss +54 -0
- package/src/web/cascader-select/index.ts +5 -0
- package/src/web/cascader-select/index.vue +132 -0
- package/src/web/cascader-select/types.ts +9 -0
- package/src/web/context-menu/createContextMenu.ts +72 -0
- package/src/web/context-menu/index.ts +4 -0
- package/src/web/context-menu/index.vue +89 -0
- package/src/web/context-menu/types.ts +27 -0
- package/src/web/context-menu/useContextMenu.ts +14 -0
- package/src/web/descriptions/description-item.vue +34 -0
- package/src/web/descriptions/description.vue +124 -0
- package/src/web/descriptions/descriptions-cell.ts +95 -0
- package/src/web/descriptions/descriptions-item.scss +68 -0
- package/src/web/descriptions/descriptions-row.vue +49 -0
- package/src/web/descriptions/descriptions.scss +153 -0
- package/src/web/descriptions/descriptions.type.ts +19 -0
- package/src/web/descriptions/index.ts +4 -0
- package/src/web/descriptions/token.ts +4 -0
- package/src/web/divider/index.scss +53 -0
- package/src/web/divider/index.ts +5 -0
- package/src/web/divider/index.vue +60 -0
- package/src/web/divider/types.ts +2 -0
- package/src/web/empty/assets/no-collect.png +0 -0
- package/src/web/empty/assets/no-data.png +0 -0
- package/src/web/empty/assets/no-filter.png +0 -0
- package/src/web/empty/assets/no-page-data.png +0 -0
- package/src/web/empty/assets/no-search.png +0 -0
- package/src/web/empty/constants.ts +12 -0
- package/src/web/empty/index.scss +57 -0
- package/src/web/empty/index.ts +5 -0
- package/src/web/empty/index.vue +96 -0
- package/src/web/exception/exception.png +0 -0
- package/src/web/exception/index.ts +3 -0
- package/src/web/exception/index.vue +44 -0
- package/src/web/filter/README.md +25 -0
- package/src/web/filter/index.scss +14 -0
- package/src/web/filter/index.ts +5 -0
- package/src/web/filter/index.vue +60 -0
- package/src/web/filter/type.ts +13 -0
- package/src/web/focus-trap/index.ts +6 -0
- package/src/web/focus-trap/index.vue +328 -0
- package/src/web/focus-trap/tokens.ts +23 -0
- package/src/web/focus-trap/utils.ts +178 -0
- package/src/web/full-screen/index.scss +22 -0
- package/src/web/full-screen/index.ts +3 -0
- package/src/web/full-screen/index.vue +24 -0
- package/src/web/icon-text/index.ts +3 -0
- package/src/web/icon-text/index.vue +77 -0
- package/src/web/image/index.scss +46 -0
- package/src/web/image/index.ts +5 -0
- package/src/web/image/index.vue +251 -0
- package/src/web/image/types.ts +1 -0
- package/src/web/index.ts +33 -0
- package/src/web/input/index.scss +473 -0
- package/src/web/input/index.ts +3 -0
- package/src/web/input/index.vue +533 -0
- package/src/web/input/utils.ts +102 -0
- package/src/web/layouts/blank.vue +4 -0
- package/src/web/layouts/footer/index.scss +31 -0
- package/src/web/layouts/footer/index.ts +3 -0
- package/src/web/layouts/footer/index.vue +38 -0
- package/src/web/layouts/header/index.scss +35 -0
- package/src/web/layouts/header/index.ts +3 -0
- package/src/web/layouts/header/index.vue +47 -0
- package/src/web/layouts/iframe/index.scss +18 -0
- package/src/web/layouts/iframe/index.vue +36 -0
- package/src/web/layouts/iframe/page.vue +30 -0
- package/src/web/layouts/index.ts +8 -0
- package/src/web/layouts/router-view-content/index.vue +70 -0
- package/src/web/link/index.scss +95 -0
- package/src/web/link/index.ts +3 -0
- package/src/web/link/index.vue +68 -0
- package/src/web/loading/directive.ts +104 -0
- package/src/web/loading/index.ts +6 -0
- package/src/web/loading/loading.scss +108 -0
- package/src/web/loading/loading.ts +156 -0
- package/src/web/loading/service.ts +145 -0
- package/src/web/loading/types.ts +29 -0
- package/src/web/logo/index.scss +31 -0
- package/src/web/logo/index.ts +5 -0
- package/src/web/logo/index.vue +45 -0
- package/src/web/logo/types.ts +6 -0
- package/src/web/menu/index.scss +336 -0
- package/src/web/menu/index.ts +8 -0
- package/src/web/menu/menu-collapse-transition.vue +62 -0
- package/src/web/menu/menu-item-group.vue +27 -0
- package/src/web/menu/menu-item.vue +126 -0
- package/src/web/menu/menu.vue +459 -0
- package/src/web/menu/sub-menu.vue +440 -0
- package/src/web/menu/types.ts +66 -0
- package/src/web/menu/use-menu-css-var.ts +11 -0
- package/src/web/menu/use-menu.ts +60 -0
- package/src/web/menu/utils/menu-bar.ts +19 -0
- package/src/web/menu/utils/menu-item.ts +55 -0
- package/src/web/menu/utils/submenu.ts +66 -0
- package/src/web/multiple-select-flat/index.ts +5 -0
- package/src/web/multiple-select-flat/index.vue +53 -0
- package/src/web/multiple-select-flat/types.ts +5 -0
- package/src/web/multiple-tabs/index.scss +16 -0
- package/src/web/multiple-tabs/index.ts +5 -0
- package/src/web/multiple-tabs/index.vue +193 -0
- package/src/web/multiple-tabs/tab-content.vue +40 -0
- package/src/web/multiple-tabs/types.ts +3 -0
- package/src/web/multiple-tabs/use/index.ts +2 -0
- package/src/web/multiple-tabs/use/use-multiple-tabs.ts +86 -0
- package/src/web/multiple-tabs/use/use-tab-dropdown.ts +101 -0
- package/src/web/nodata/README.md +42 -0
- package/src/web/nodata/fail.vue +13 -0
- package/src/web/nodata/img/100.png +0 -0
- package/src/web/nodata/img/101.png +0 -0
- package/src/web/nodata/img/102.png +0 -0
- package/src/web/nodata/img/103.png +0 -0
- package/src/web/nodata/img/104.png +0 -0
- package/src/web/nodata/img/105.png +0 -0
- package/src/web/nodata/img/106.png +0 -0
- package/src/web/nodata/img/107.png +0 -0
- package/src/web/nodata/img/200.png +0 -0
- package/src/web/nodata/img/201.png +0 -0
- package/src/web/nodata/img/202.png +0 -0
- package/src/web/nodata/img/203.png +0 -0
- package/src/web/nodata/index.scss +37 -0
- package/src/web/nodata/index.ts +6 -0
- package/src/web/nodata/index.vue +46 -0
- package/src/web/nodata/types.ts +17 -0
- package/src/web/only-child/index.tsx +69 -0
- package/src/web/pagination/components/jumper.vue +49 -0
- package/src/web/pagination/components/next.vue +40 -0
- package/src/web/pagination/components/pager.vue +215 -0
- package/src/web/pagination/components/prev.vue +35 -0
- package/src/web/pagination/components/sizes.vue +76 -0
- package/src/web/pagination/components/total.vue +21 -0
- package/src/web/pagination/index.scss +231 -0
- package/src/web/pagination/index.ts +5 -0
- package/src/web/pagination/pagination.ts +363 -0
- package/src/web/pagination/usePagination.ts +13 -0
- package/src/web/popover/directive.ts +21 -0
- package/src/web/popover/index.scss +58 -0
- package/src/web/popover/index.ts +3 -0
- package/src/web/popover/index.vue +161 -0
- package/src/web/popover/types.ts +26 -0
- package/src/web/popper/arrow.vue +45 -0
- package/src/web/popper/content.vue +311 -0
- package/src/web/popper/index.scss +108 -0
- package/src/web/popper/index.ts +11 -0
- package/src/web/popper/popper.vue +57 -0
- package/src/web/popper/tokens.ts +28 -0
- package/src/web/popper/trigger.vue +166 -0
- package/src/web/popper/types.ts +49 -0
- package/src/web/popper/utils.ts +81 -0
- package/src/web/qrcode/drawCanvas.ts +32 -0
- package/src/web/qrcode/drawLogo.ts +82 -0
- package/src/web/qrcode/index.ts +5 -0
- package/src/web/qrcode/index.vue +107 -0
- package/src/web/qrcode/qrcodePlus.ts +4 -0
- package/src/web/qrcode/toCanvas.ts +11 -0
- package/src/web/qrcode/types.ts +38 -0
- package/src/web/result/index.scss +69 -0
- package/src/web/result/index.ts +3 -0
- package/src/web/result/index.vue +63 -0
- package/src/web/scrollbar/bar.vue +48 -0
- package/src/web/scrollbar/index.scss +91 -0
- package/src/web/scrollbar/index.ts +5 -0
- package/src/web/scrollbar/index.vue +236 -0
- package/src/web/scrollbar/thumb.vue +183 -0
- package/src/web/scrollbar/tokens.ts +10 -0
- package/src/web/scrollbar/types.ts +7 -0
- package/src/web/scrollbar/util.ts +38 -0
- package/src/web/select/constants.ts +13 -0
- package/src/web/select/index.ts +11 -0
- package/src/web/select/index.vue +555 -0
- package/src/web/select/option-group.scss +49 -0
- package/src/web/select/option-group.vue +97 -0
- package/src/web/select/option-item.scss +66 -0
- package/src/web/select/option.scss +32 -0
- package/src/web/select/option.vue +110 -0
- package/src/web/select/select-dropdown.scss +86 -0
- package/src/web/select/select-dropdown.vue +51 -0
- package/src/web/select/select.scss +213 -0
- package/src/web/select/token.ts +56 -0
- package/src/web/select/useOption.ts +146 -0
- package/src/web/select/useSelect.ts +942 -0
- package/src/web/select/utils.ts +5 -0
- package/src/web/side-menu/index.scss +66 -0
- package/src/web/side-menu/index.ts +4 -0
- package/src/web/side-menu/index.vue +228 -0
- package/src/web/side-menu/types.ts +20 -0
- package/src/web/single-select/index.scss +60 -0
- package/src/web/single-select/index.ts +5 -0
- package/src/web/single-select/index.vue +70 -0
- package/src/web/single-select/select@2x.png +0 -0
- package/src/web/single-select/types.ts +5 -0
- package/src/web/svg/index.ts +3 -0
- package/src/web/svg/index.vue +22 -0
- package/src/web/tabs/index.scss +579 -0
- package/src/web/tabs/index.ts +6 -0
- package/src/web/tabs/index.vue +236 -0
- package/src/web/tabs/tab-bar.vue +90 -0
- package/src/web/tabs/tab-nav.vue +403 -0
- package/src/web/tabs/tab-pane.vue +90 -0
- package/src/web/tabs/types.ts +66 -0
- package/src/web/tag/index.scss +182 -0
- package/src/web/tag/index.ts +5 -0
- package/src/web/tag/index.vue +78 -0
- package/src/web/tag/types.ts +2 -0
- package/src/web/tooltip/content.vue +239 -0
- package/src/web/tooltip/index.ts +4 -0
- package/src/web/tooltip/tokens.ts +21 -0
- package/src/web/tooltip/tooltip.vue +270 -0
- package/src/web/tooltip/trigger.vue +119 -0
- package/src/web/tooltip/types.ts +56 -0
- package/src/web/tooltip/utils.ts +20 -0
- package/src/web/transition/collapse-transition.vue +73 -0
- package/src/web/transition/index.ts +5 -0
- package/tsconfig.json +8 -0
- package/types/component.ts +1 -0
- package/types/index.d.ts +286 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const FOCUSABLE_ELEMENT_SELECTORS = 'a[href],button:not([disabled]),button:not([hidden]),:not([tabindex="-1"]),input:not([disabled]),input:not([type="hidden"]),select:not([disabled]),textarea:not([disabled])';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Determine if the testing element is visible on screen no matter if its on the viewport or not
|
|
5
|
+
*/
|
|
6
|
+
export const isVisible = (element: HTMLElement) => {
|
|
7
|
+
if (process.env.NODE_ENV === 'test') return true;
|
|
8
|
+
const computed = getComputedStyle(element);
|
|
9
|
+
// element.offsetParent won't work on fix positioned
|
|
10
|
+
// WARNING: potential issue here, going to need some expert advices on this issue
|
|
11
|
+
return computed.position === 'fixed' ? false : element.offsetParent !== null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const obtainAllFocusableElements = (
|
|
15
|
+
element: HTMLElement
|
|
16
|
+
): HTMLElement[] => {
|
|
17
|
+
return Array.from(
|
|
18
|
+
element.querySelectorAll<HTMLElement>(FOCUSABLE_ELEMENT_SELECTORS)
|
|
19
|
+
).filter((item: HTMLElement) => isFocusable(item) && isVisible(item));
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @desc Determine if target element is focusable
|
|
24
|
+
* @param element {HTMLElement}
|
|
25
|
+
* @returns {Boolean} true if it is focusable
|
|
26
|
+
*/
|
|
27
|
+
export const isFocusable = (element: HTMLElement): boolean => {
|
|
28
|
+
if (
|
|
29
|
+
element.tabIndex > 0 ||
|
|
30
|
+
(element.tabIndex === 0 && element.getAttribute('tabIndex') !== null)
|
|
31
|
+
) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
// HTMLButtonElement has disabled
|
|
35
|
+
if ((element as HTMLButtonElement).disabled) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
switch (element.nodeName) {
|
|
40
|
+
case 'A': {
|
|
41
|
+
// casting current element to Specific HTMLElement in order to be more type precise
|
|
42
|
+
return (
|
|
43
|
+
!!(element as HTMLAnchorElement).href &&
|
|
44
|
+
(element as HTMLAnchorElement).rel !== 'ignore'
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
case 'INPUT': {
|
|
48
|
+
return !(
|
|
49
|
+
(element as HTMLInputElement).type === 'hidden' ||
|
|
50
|
+
(element as HTMLInputElement).type === 'file'
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
case 'BUTTON':
|
|
54
|
+
case 'SELECT':
|
|
55
|
+
case 'TEXTAREA': {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
default: {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @desc Set Attempt to set focus on the current node.
|
|
66
|
+
* @param element
|
|
67
|
+
* The node to attempt to focus on.
|
|
68
|
+
* @returns
|
|
69
|
+
* true if element is focused.
|
|
70
|
+
*/
|
|
71
|
+
export const attemptFocus = (element: HTMLElement): boolean => {
|
|
72
|
+
if (!isFocusable(element)) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
// Remove the old try catch block since there will be no error to be thrown
|
|
76
|
+
element.focus?.();
|
|
77
|
+
return document.activeElement === element;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Trigger an event
|
|
82
|
+
* mouseenter, mouseleave, mouseover, keyup, change, click, etc.
|
|
83
|
+
* @param {HTMLElement} elm
|
|
84
|
+
* @param {String} name
|
|
85
|
+
* @param {*} opts
|
|
86
|
+
*/
|
|
87
|
+
export const triggerEvent = function (
|
|
88
|
+
elm: HTMLElement,
|
|
89
|
+
name: string,
|
|
90
|
+
...opts: Array<boolean>
|
|
91
|
+
): HTMLElement {
|
|
92
|
+
let eventName: string;
|
|
93
|
+
|
|
94
|
+
if (name.includes('mouse') || name.includes('click')) {
|
|
95
|
+
eventName = 'MouseEvents';
|
|
96
|
+
} else if (name.includes('key')) {
|
|
97
|
+
eventName = 'KeyboardEvent';
|
|
98
|
+
} else {
|
|
99
|
+
eventName = 'HTMLEvents';
|
|
100
|
+
}
|
|
101
|
+
const evt = document.createEvent(eventName);
|
|
102
|
+
|
|
103
|
+
evt.initEvent(name, ...opts);
|
|
104
|
+
elm.dispatchEvent(evt);
|
|
105
|
+
return elm;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const isLeaf = (el: HTMLElement) => !el.getAttribute('aria-owns');
|
|
109
|
+
|
|
110
|
+
export const getSibling = (
|
|
111
|
+
el: HTMLElement,
|
|
112
|
+
distance: number,
|
|
113
|
+
elClass: string
|
|
114
|
+
) => {
|
|
115
|
+
const { parentNode } = el;
|
|
116
|
+
if (!parentNode) return null;
|
|
117
|
+
const siblings = parentNode.querySelectorAll(elClass);
|
|
118
|
+
const index = Array.prototype.indexOf.call(siblings, el);
|
|
119
|
+
return siblings[index + distance] || null;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const focusNode = (el: HTMLElement) => {
|
|
123
|
+
if (!el) return;
|
|
124
|
+
el.focus();
|
|
125
|
+
!isLeaf(el) && el.click();
|
|
126
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const unique = <T>(arr: T[]) => [...new Set(arr)];
|
|
2
|
+
|
|
3
|
+
type Many<T> = T | ReadonlyArray<T>
|
|
4
|
+
// TODO: rename to `ensureArray`
|
|
5
|
+
/** like `_.castArray`, except falsy value returns empty array. */
|
|
6
|
+
export const castArray = <T>(arr: Many<T>): T[] => {
|
|
7
|
+
if (!arr && (arr as any) !== 0) return [];
|
|
8
|
+
return Array.isArray(arr) ? arr : [arr];
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// TODO: remove import alias
|
|
12
|
+
// avoid naming conflicts
|
|
13
|
+
export { castArray as ensureArray } from 'lodash';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { isString } from '@vri/utils';
|
|
2
|
+
|
|
3
|
+
class VriError extends Error {
|
|
4
|
+
constructor(m: string) {
|
|
5
|
+
super(m);
|
|
6
|
+
this.name = 'VriError';
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function throwError(scope: string, m: string): never {
|
|
11
|
+
throw new VriError(`[${scope}] ${m}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function debugWarn(err: Error): void
|
|
15
|
+
export function debugWarn(scope: string, message: string): void
|
|
16
|
+
export function debugWarn(scope: string | Error, message?: string): void {
|
|
17
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
18
|
+
const error: Error = isString(scope)
|
|
19
|
+
? new VriError(`[${scope}] ${message}`)
|
|
20
|
+
: scope;
|
|
21
|
+
console.warn(error);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const composeEventHandlers = <E>(theirsHandler?: (event: E) => boolean | void, oursHandler?: (event: E) => void, { checkForDefaultPrevented = true } = {}) => {
|
|
2
|
+
const handleEvent = (event: E) => {
|
|
3
|
+
const shouldPrevent = theirsHandler?.(event);
|
|
4
|
+
|
|
5
|
+
if (checkForDefaultPrevented === false || !shouldPrevent) {
|
|
6
|
+
return oursHandler?.(event);
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
return handleEvent;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type WhenMouseHandler = (e: PointerEvent) => any;
|
|
13
|
+
export const whenMouse = (handler: WhenMouseHandler): WhenMouseHandler => {
|
|
14
|
+
return (e: PointerEvent) => (e.pointerType === 'mouse' ? handler(e) : undefined);
|
|
15
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isPromise, noop } from '@vri/utils';
|
|
2
|
+
|
|
3
|
+
export type Interceptor = (...args: any[]) => Promise<boolean> | boolean | undefined | void;
|
|
4
|
+
|
|
5
|
+
export function callInterceptor(
|
|
6
|
+
interceptor: Interceptor | undefined,
|
|
7
|
+
{
|
|
8
|
+
args = [],
|
|
9
|
+
done,
|
|
10
|
+
canceled
|
|
11
|
+
}: {
|
|
12
|
+
args?: unknown[];
|
|
13
|
+
done: () => void;
|
|
14
|
+
canceled?: () => void;
|
|
15
|
+
}
|
|
16
|
+
) {
|
|
17
|
+
if (interceptor) {
|
|
18
|
+
// eslint-disable-next-line prefer-spread
|
|
19
|
+
const returnVal = interceptor.apply(null, args);
|
|
20
|
+
|
|
21
|
+
if (isPromise(returnVal)) {
|
|
22
|
+
returnVal
|
|
23
|
+
.then((value) => {
|
|
24
|
+
if (value) {
|
|
25
|
+
done();
|
|
26
|
+
} else if (canceled) {
|
|
27
|
+
canceled();
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
.catch(noop);
|
|
31
|
+
} else if (returnVal) {
|
|
32
|
+
done();
|
|
33
|
+
} else if (canceled) {
|
|
34
|
+
canceled();
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
done();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createApp, reactive, type Component } from 'vue';
|
|
2
|
+
import { useExpose } from '@vri/use';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @description popup 组件的状态控制
|
|
6
|
+
* @author wfd
|
|
7
|
+
* @date 2022/7/13 13:40
|
|
8
|
+
* @example
|
|
9
|
+
*/
|
|
10
|
+
export function usePopupState() {
|
|
11
|
+
const state = reactive<{
|
|
12
|
+
show: boolean;
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
}>({
|
|
15
|
+
show: false
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// 切换 show 的状态
|
|
19
|
+
const toggle = (show: boolean) => {
|
|
20
|
+
state.show = show;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// 如果是 open 说明是打开 popup,transitionAppear 设置为 true
|
|
24
|
+
const open = (props: Record<string, any>) => {
|
|
25
|
+
// 这里直接用 Object.assign 的原因是可以,合并后 state 会被直接改变
|
|
26
|
+
Object.assign(state, props, { transitionAppear: true });
|
|
27
|
+
// 将 show 改为 true
|
|
28
|
+
toggle(true);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 关闭 popup 事件
|
|
32
|
+
const close = () => toggle(false);
|
|
33
|
+
|
|
34
|
+
// 将 open, close, toggle 合并到 instance 实例对象的 proxy 属性中
|
|
35
|
+
useExpose({ open, close, toggle });
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
open,
|
|
39
|
+
close,
|
|
40
|
+
state,
|
|
41
|
+
toggle
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @description mountComponent
|
|
47
|
+
* @author wfd
|
|
48
|
+
* @date 2022/7/12 20:13
|
|
49
|
+
* @example
|
|
50
|
+
* @param RootComponent
|
|
51
|
+
*/
|
|
52
|
+
export function mountComponent(RootComponent: Component) {
|
|
53
|
+
const app = createApp(RootComponent);
|
|
54
|
+
const root = document.createElement('div');
|
|
55
|
+
|
|
56
|
+
document.body.appendChild(root);
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
instance: app.mount(root),
|
|
60
|
+
unmount() {
|
|
61
|
+
app.unmount();
|
|
62
|
+
document.body.removeChild(root);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createPopper } from '@popperjs/core/lib/popper-lite';
|
|
2
|
+
import offsetModifier from '@popperjs/core/lib/modifiers/offset';
|
|
3
|
+
import type { Instance, Placement } from '@popperjs/core';
|
|
4
|
+
|
|
5
|
+
export { createPopper, offsetModifier };
|
|
6
|
+
export type { Instance, Placement };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate random number in range [0, 1000]
|
|
3
|
+
* Maybe replace with [uuid](https://www.npmjs.com/package/uuid)
|
|
4
|
+
*/
|
|
5
|
+
export const generateId = (): number => Math.floor(Math.random() * 10000);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generating a random int in range (0, max - 1)
|
|
9
|
+
* @param max {number}
|
|
10
|
+
*/
|
|
11
|
+
export const getRandomInt = (max: number) =>
|
|
12
|
+
Math.floor(Math.random() * Math.floor(max));
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { isClient } from '@vueuse/core';
|
|
2
|
+
import { getStyle } from '@vri/utils';
|
|
3
|
+
|
|
4
|
+
export const isScroll = (el: HTMLElement, isVertical?: boolean): boolean => {
|
|
5
|
+
if (!isClient) return false;
|
|
6
|
+
|
|
7
|
+
const key = (
|
|
8
|
+
{
|
|
9
|
+
undefined: 'overflow',
|
|
10
|
+
true: 'overflow-y',
|
|
11
|
+
false: 'overflow-x'
|
|
12
|
+
} as const
|
|
13
|
+
)[String(isVertical)]!;
|
|
14
|
+
const overflow = getStyle(el, key);
|
|
15
|
+
return ['scroll', 'auto', 'overlay'].some((s) => overflow.includes(s));
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const getScrollContainer = (
|
|
19
|
+
el: HTMLElement,
|
|
20
|
+
isVertical?: boolean
|
|
21
|
+
): Window | HTMLElement | undefined => {
|
|
22
|
+
if (!isClient) return;
|
|
23
|
+
|
|
24
|
+
let parent: HTMLElement = el;
|
|
25
|
+
while (parent) {
|
|
26
|
+
if ([window, document, document.documentElement].includes(parent))
|
|
27
|
+
return window;
|
|
28
|
+
|
|
29
|
+
if (isScroll(parent, isVertical)) return parent;
|
|
30
|
+
|
|
31
|
+
parent = parent.parentNode as HTMLElement;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return parent;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
let scrollBarWidth: number;
|
|
38
|
+
export const getScrollBarWidth = (namespace: string): number => {
|
|
39
|
+
if (!isClient) return 0;
|
|
40
|
+
if (scrollBarWidth !== undefined) return scrollBarWidth;
|
|
41
|
+
|
|
42
|
+
const outer = document.createElement('div');
|
|
43
|
+
outer.className = `${namespace}-scrollbar__wrap`;
|
|
44
|
+
outer.style.visibility = 'hidden';
|
|
45
|
+
outer.style.width = '100px';
|
|
46
|
+
outer.style.position = 'absolute';
|
|
47
|
+
outer.style.top = '-9999px';
|
|
48
|
+
document.body.appendChild(outer);
|
|
49
|
+
|
|
50
|
+
const widthNoScroll = outer.offsetWidth;
|
|
51
|
+
outer.style.overflow = 'scroll';
|
|
52
|
+
|
|
53
|
+
const inner = document.createElement('div');
|
|
54
|
+
inner.style.width = '100%';
|
|
55
|
+
outer.appendChild(inner);
|
|
56
|
+
|
|
57
|
+
const widthWithScroll = inner.offsetWidth;
|
|
58
|
+
outer.parentNode?.removeChild(outer);
|
|
59
|
+
scrollBarWidth = widthNoScroll - widthWithScroll;
|
|
60
|
+
|
|
61
|
+
return scrollBarWidth;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Scroll with in the container element, positioning the **selected** element at the top
|
|
66
|
+
* of the container
|
|
67
|
+
*/
|
|
68
|
+
export function scrollIntoView(
|
|
69
|
+
container: HTMLElement,
|
|
70
|
+
selected: HTMLElement
|
|
71
|
+
): void {
|
|
72
|
+
if (!isClient) return;
|
|
73
|
+
|
|
74
|
+
if (!selected) {
|
|
75
|
+
container.scrollTop = 0;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const offsetParents: HTMLElement[] = [];
|
|
80
|
+
let pointer = selected.offsetParent;
|
|
81
|
+
while (
|
|
82
|
+
pointer !== null &&
|
|
83
|
+
container !== pointer &&
|
|
84
|
+
container.contains(pointer)
|
|
85
|
+
) {
|
|
86
|
+
offsetParents.push(pointer as HTMLElement);
|
|
87
|
+
pointer = (pointer as HTMLElement).offsetParent;
|
|
88
|
+
}
|
|
89
|
+
const top =
|
|
90
|
+
selected.offsetTop +
|
|
91
|
+
offsetParents.reduce((prev, curr) => prev + curr.offsetTop, 0);
|
|
92
|
+
const bottom = top + selected.offsetHeight;
|
|
93
|
+
const viewRectTop = container.scrollTop;
|
|
94
|
+
const viewRectBottom = viewRectTop + container.clientHeight;
|
|
95
|
+
|
|
96
|
+
if (top < viewRectTop) {
|
|
97
|
+
container.scrollTop = top;
|
|
98
|
+
} else if (bottom > viewRectBottom) {
|
|
99
|
+
container.scrollTop = bottom - container.clientHeight;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Comment,
|
|
3
|
+
Fragment,
|
|
4
|
+
Text,
|
|
5
|
+
createBlock,
|
|
6
|
+
createCommentVNode,
|
|
7
|
+
isVNode,
|
|
8
|
+
openBlock
|
|
9
|
+
} from 'vue';
|
|
10
|
+
import { camelize, hasOwn, isArray } from '@vue/shared';
|
|
11
|
+
import { debugWarn } from './error';
|
|
12
|
+
import type {
|
|
13
|
+
VNode,
|
|
14
|
+
VNodeArrayChildren,
|
|
15
|
+
VNodeChild,
|
|
16
|
+
VNodeNormalizedChildren
|
|
17
|
+
} from 'vue';
|
|
18
|
+
|
|
19
|
+
const SCOPE = 'utils/vue/vnode';
|
|
20
|
+
|
|
21
|
+
export enum PatchFlags {
|
|
22
|
+
TEXT = 1,
|
|
23
|
+
CLASS = 2,
|
|
24
|
+
STYLE = 4,
|
|
25
|
+
PROPS = 8,
|
|
26
|
+
FULL_PROPS = 16,
|
|
27
|
+
HYDRATE_EVENTS = 32,
|
|
28
|
+
STABLE_FRAGMENT = 64,
|
|
29
|
+
KEYED_FRAGMENT = 128,
|
|
30
|
+
UNKEYED_FRAGMENT = 256,
|
|
31
|
+
NEED_PATCH = 512,
|
|
32
|
+
DYNAMIC_SLOTS = 1024,
|
|
33
|
+
HOISTED = -1,
|
|
34
|
+
BAIL = -2,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type VNodeChildAtom = Exclude<VNodeChild, Array<any>>
|
|
38
|
+
export type RawSlots = Exclude<
|
|
39
|
+
VNodeNormalizedChildren,
|
|
40
|
+
Array<any> | null | string
|
|
41
|
+
>
|
|
42
|
+
|
|
43
|
+
export function isFragment(node: VNode): boolean
|
|
44
|
+
export function isFragment(node: unknown): node is VNode
|
|
45
|
+
export function isFragment(node: unknown): node is VNode {
|
|
46
|
+
return isVNode(node) && node.type === Fragment;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function isText(node: VNode): boolean
|
|
50
|
+
export function isText(node: unknown): node is VNode
|
|
51
|
+
export function isText(node: unknown): node is VNode {
|
|
52
|
+
return isVNode(node) && node.type === Text;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isComment(node: VNode): boolean
|
|
56
|
+
export function isComment(node: unknown): node is VNode
|
|
57
|
+
export function isComment(node: unknown): node is VNode {
|
|
58
|
+
return isVNode(node) && node.type === Comment;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const TEMPLATE = 'template';
|
|
62
|
+
export function isTemplate(node: VNode): boolean
|
|
63
|
+
export function isTemplate(node: unknown): node is VNode
|
|
64
|
+
export function isTemplate(node: unknown): node is VNode {
|
|
65
|
+
return isVNode(node) && node.type === TEMPLATE;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* determine if the element is a valid element type rather than fragments and comment e.g. <template> v-if
|
|
70
|
+
* @param node {VNode} node to be tested
|
|
71
|
+
*/
|
|
72
|
+
export function isValidElementNode(node: VNode): boolean
|
|
73
|
+
export function isValidElementNode(node: unknown): node is VNode
|
|
74
|
+
export function isValidElementNode(node: unknown): node is VNode {
|
|
75
|
+
return isVNode(node) && !isFragment(node) && !isComment(node);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* get a valid child node (not fragment nor comment)
|
|
80
|
+
* @param node {VNode} node to be searched
|
|
81
|
+
* @param depth {number} depth to be searched
|
|
82
|
+
*/
|
|
83
|
+
function getChildren(
|
|
84
|
+
node: VNodeNormalizedChildren | VNodeChild,
|
|
85
|
+
depth: number
|
|
86
|
+
): VNodeNormalizedChildren | VNodeChild {
|
|
87
|
+
if (isComment(node)) return;
|
|
88
|
+
if (isFragment(node) || isTemplate(node)) {
|
|
89
|
+
return depth > 0 ? getFirstValidNode(node.children, depth - 1) : undefined;
|
|
90
|
+
}
|
|
91
|
+
return node;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const getFirstValidNode = (
|
|
95
|
+
nodes: VNodeNormalizedChildren,
|
|
96
|
+
maxDepth = 3
|
|
97
|
+
) => {
|
|
98
|
+
if (Array.isArray(nodes)) {
|
|
99
|
+
return getChildren(nodes[0], maxDepth);
|
|
100
|
+
} else {
|
|
101
|
+
return getChildren(nodes, maxDepth);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export function renderIf(
|
|
106
|
+
condition: boolean,
|
|
107
|
+
...args: Parameters<typeof createBlock>
|
|
108
|
+
) {
|
|
109
|
+
return condition ? renderBlock(...args) : createCommentVNode('v-if', true);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function renderBlock(...args: Parameters<typeof createBlock>) {
|
|
113
|
+
return openBlock(), createBlock(...args);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export const getNormalizedProps = (node: VNode) => {
|
|
117
|
+
if (!isVNode(node)) {
|
|
118
|
+
debugWarn(SCOPE, '[getNormalizedProps] must be a VNode');
|
|
119
|
+
return {};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const raw = node.props || {};
|
|
123
|
+
const type = (isVNode(node.type) ? node.type.props : undefined) || {};
|
|
124
|
+
const props: Record<string, any> = {};
|
|
125
|
+
|
|
126
|
+
Object.keys(type).forEach((key) => {
|
|
127
|
+
if (hasOwn(type[key], 'default')) {
|
|
128
|
+
props[key] = type[key].default;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
Object.keys(raw).forEach((key) => {
|
|
133
|
+
props[camelize(key)] = raw[key];
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return props;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const ensureOnlyChild = (children: VNodeArrayChildren | undefined) => {
|
|
140
|
+
if (!isArray(children) || children.length > 1) {
|
|
141
|
+
throw new Error('expect to receive a single Vue element child');
|
|
142
|
+
}
|
|
143
|
+
return children[0];
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export type FlattenVNodes = Array<VNodeChildAtom | RawSlots>
|
|
147
|
+
|
|
148
|
+
export const flattedChildren = (
|
|
149
|
+
children: FlattenVNodes | VNode | VNodeNormalizedChildren
|
|
150
|
+
): FlattenVNodes => {
|
|
151
|
+
// transform to array
|
|
152
|
+
const vNodes = isArray(children) ? children : [children];
|
|
153
|
+
const result: FlattenVNodes = [];
|
|
154
|
+
|
|
155
|
+
vNodes.forEach((child) => {
|
|
156
|
+
if (isArray(child)) {
|
|
157
|
+
result.push(...flattedChildren(child));
|
|
158
|
+
} else if (isVNode(child) && isArray(child.children)) {
|
|
159
|
+
result.push(...flattedChildren(child.children));
|
|
160
|
+
} else {
|
|
161
|
+
result.push(child);
|
|
162
|
+
if (isVNode(child) && child.component?.subTree) {
|
|
163
|
+
result.push(...flattedChildren(child.component.subTree));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return result;
|
|
169
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
$name: avatar;
|
|
2
|
+
|
|
3
|
+
@include set-root-css-vars($name, $avatar);
|
|
4
|
+
|
|
5
|
+
@include b($name) {
|
|
6
|
+
@include set-component-css-var('avatar-size', $avatar-size);
|
|
7
|
+
|
|
8
|
+
@include set-css-var-value(
|
|
9
|
+
('avatar', 'size'),
|
|
10
|
+
map-get($avatar-size, 'default')
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
display: inline-flex;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
align-items: center;
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
text-align: center;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
color: getCssVar('avatar', 'text-color');
|
|
20
|
+
background: getCssVar('avatar', 'bg-color');
|
|
21
|
+
width: getCssVar('avatar', 'size');
|
|
22
|
+
height: getCssVar('avatar', 'size');
|
|
23
|
+
font-size: getCssVar('avatar', 'text-size');
|
|
24
|
+
|
|
25
|
+
> img {
|
|
26
|
+
display: block;
|
|
27
|
+
height: 100%;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@include m(circle) {
|
|
31
|
+
border-radius: 50%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@include m(square) {
|
|
35
|
+
border-radius: getCssVar('avatar', 'border-radius');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@include m(icon) {
|
|
39
|
+
font-size: getCssVar('avatar', 'icon-size');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@each $size in (small, large) {
|
|
43
|
+
@include m($size) {
|
|
44
|
+
@include set-css-var-value(
|
|
45
|
+
('avatar', 'size'),
|
|
46
|
+
map-get($avatar-size, $size)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|