├── .browserslistrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── babel.config.js ├── build ├── gulpfile.js ├── md-loader │ ├── config.js │ ├── containers.js │ ├── fence.js │ ├── index.js │ └── util.js ├── rollup.config.js └── webpack.dev.js ├── docs ├── 0c51f5157c4954238cc7.ttf ├── 0e183abb317dc7309207.eot ├── 511aad842c035d563ea2.woff ├── ea78a237145b724f979a.svg ├── favicon.ico ├── index.html ├── js │ ├── DOCS0.48024f5.js │ ├── DOCS1.48024f5.js │ ├── DOCS10.48024f5.js │ ├── DOCS11.48024f5.js │ ├── DOCS12.48024f5.js │ ├── DOCS13.48024f5.js │ ├── DOCS14.48024f5.js │ ├── DOCS15.48024f5.js │ ├── DOCS16.48024f5.js │ ├── DOCS17.48024f5.js │ ├── DOCS18.48024f5.js │ ├── DOCS19.48024f5.js │ ├── DOCS2.48024f5.js │ ├── DOCS20.48024f5.js │ ├── DOCS21.48024f5.js │ ├── DOCS22.48024f5.js │ ├── DOCS23.48024f5.js │ ├── DOCS24.48024f5.js │ ├── DOCS25.48024f5.js │ ├── DOCS26.48024f5.js │ ├── DOCS27.48024f5.js │ ├── DOCS28.48024f5.js │ ├── DOCS29.48024f5.js │ ├── DOCS3.48024f5.js │ ├── DOCS30.48024f5.js │ ├── DOCS31.48024f5.js │ ├── DOCS32.48024f5.js │ ├── DOCS33.48024f5.js │ ├── DOCS34.48024f5.js │ ├── DOCS35.48024f5.js │ ├── DOCS36.48024f5.js │ ├── DOCS37.48024f5.js │ ├── DOCS38.48024f5.js │ ├── DOCS39.48024f5.js │ ├── DOCS4.48024f5.js │ ├── DOCS40.48024f5.js │ ├── DOCS41.48024f5.js │ ├── DOCS42.48024f5.js │ ├── DOCS43.48024f5.js │ ├── DOCS44.48024f5.js │ ├── DOCS45.48024f5.js │ ├── DOCS46.48024f5.js │ ├── DOCS47.48024f5.js │ ├── DOCS48.48024f5.js │ ├── DOCS49.48024f5.js │ ├── DOCS5.48024f5.js │ ├── DOCS50.48024f5.js │ ├── DOCS51.48024f5.js │ ├── DOCS52.48024f5.js │ ├── DOCS53.48024f5.js │ ├── DOCS54.48024f5.js │ ├── DOCS55.48024f5.js │ ├── DOCS56.48024f5.js │ ├── DOCS57.48024f5.js │ ├── DOCS58.48024f5.js │ ├── DOCS59.48024f5.js │ ├── DOCS6.48024f5.js │ ├── DOCS60.48024f5.js │ ├── DOCS61.48024f5.js │ ├── DOCS62.48024f5.js │ ├── DOCS63.48024f5.js │ ├── DOCS64.48024f5.js │ ├── DOCS65.48024f5.js │ ├── DOCS66.48024f5.js │ ├── DOCS67.48024f5.js │ ├── DOCS7.48024f5.js │ ├── DOCS8.48024f5.js │ ├── DOCS9.48024f5.js │ ├── app.js │ └── vendors.js └── static │ ├── iconfont.0bf6cd3.ttf │ ├── iconfont.90bdc02.woff │ ├── iconfont.a49ca6a.svg │ ├── iconfont.e3031e0.eot │ └── text.8834c48.svg ├── examples ├── App.vue ├── assets │ ├── images │ │ ├── Bin-UI-Next-01.png │ │ ├── Bin-UI-Next-02.png │ │ ├── Bin-UI-Next-03.png │ │ ├── Bin-UI-Next-04.png │ │ ├── Bin-UI-Next-05.png │ │ ├── admin │ │ │ ├── Bin-Admin-Pro-01.png │ │ │ ├── Bin-Admin-Pro-01.svg │ │ │ ├── Bin-Admin-Pro-02.png │ │ │ ├── Bin-Admin-Pro-02.svg │ │ │ ├── Bin-Admin-Pro-03.png │ │ │ └── Bin-Admin-Pro-03.svg │ │ ├── bin-ui.png │ │ ├── loading.svg │ │ ├── loading1.svg │ │ ├── logo │ │ │ ├── bin-ui-next-01.png │ │ │ ├── bin-ui-next-01.svg │ │ │ ├── bin-ui-next-02.png │ │ │ ├── bin-ui-next-02.svg │ │ │ ├── bin-ui-next-03.png │ │ │ ├── bin-ui-next-03.svg │ │ │ ├── favicon1.ico │ │ │ ├── favicon2.ico │ │ │ └── favicon3.ico │ │ ├── logo01.png │ │ ├── svg │ │ │ ├── Bin-UI-Next-01.svg │ │ │ ├── Bin-UI-Next-02.svg │ │ │ ├── Bin-UI-Next-03.svg │ │ │ ├── Bin-UI-Next-04.svg │ │ │ ├── Bin-UI-Next-05.svg │ │ │ ├── code-show.svg │ │ │ └── code.svg │ │ └── text.svg │ └── styles │ │ ├── base.styl │ │ ├── color-brewer.styl │ │ ├── common.styl │ │ ├── demo.styl │ │ ├── index.styl │ │ └── scrollbar.styl ├── components │ ├── SvgLoading │ │ ├── index.vue │ │ └── loading │ │ │ ├── loading-text.vue │ │ │ ├── loading01.vue │ │ │ ├── loading02.vue │ │ │ ├── loading03.vue │ │ │ ├── loading04.vue │ │ │ ├── loading05.vue │ │ │ ├── loading06.vue │ │ │ ├── loading07.vue │ │ │ ├── loading08.vue │ │ │ ├── loading09.vue │ │ │ ├── loading10.vue │ │ │ ├── loading11.vue │ │ │ └── loading12.vue │ ├── color-base.vue │ ├── demo-block.vue │ ├── draggable-demo.vue │ ├── footer.vue │ ├── header.vue │ ├── icon-pane.vue │ ├── search.vue │ └── side-nav.vue ├── docs │ ├── affix.md │ ├── alert.md │ ├── anchor.md │ ├── backtop.md │ ├── badge.md │ ├── base.md │ ├── breadcrumb.md │ ├── button.md │ ├── calendar.md │ ├── card.md │ ├── carousel.md │ ├── cascader.md │ ├── checkbox.md │ ├── circle.md │ ├── collapse.md │ ├── color-picker.md │ ├── color.md │ ├── config-provider.md │ ├── console.md │ ├── countTo.md │ ├── date-picker.md │ ├── desc.md │ ├── directive.md │ ├── divider.md │ ├── drawer.md │ ├── dropdown.md │ ├── empty.md │ ├── form.md │ ├── grid.md │ ├── guide.md │ ├── icon.md │ ├── input.md │ ├── inputNumber.md │ ├── layout.md │ ├── loading-bar.md │ ├── loading.md │ ├── logs.md │ ├── menu.md │ ├── message.md │ ├── messageBox.md │ ├── modal.md │ ├── notice.md │ ├── page.md │ ├── popover.md │ ├── popperjs.md │ ├── progress.md │ ├── radio.md │ ├── rate.md │ ├── scrollbar.md │ ├── select.md │ ├── skeleton.md │ ├── slider.md │ ├── sortablejs.md │ ├── space.md │ ├── split.md │ ├── start.md │ ├── steps.md │ ├── switch.md │ ├── table.md │ ├── tabs.md │ ├── tag.md │ ├── theme.md │ ├── time-picker.md │ ├── timeline.md │ ├── tooltip.md │ ├── transition.md │ ├── tree.md │ └── upload.md ├── favicon.ico ├── generateTreeData.js ├── index.html ├── main.js ├── nav.config.json ├── route.js └── util.js ├── jsconfig.json ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js └── src ├── components ├── affix │ ├── affix.vue │ └── index.js ├── alert │ ├── alert.vue │ └── index.js ├── anchor-link │ └── index.js ├── anchor │ ├── anchor-link.vue │ ├── anchor.vue │ └── index.js ├── back-top │ ├── back-top.vue │ └── index.js ├── badge │ ├── badge.vue │ └── index.js ├── breadcrumb-item │ └── index.js ├── breadcrumb │ ├── breadcrumb-item.vue │ ├── breadcrumb.vue │ └── index.js ├── button-group │ └── index.js ├── button │ ├── button-group.vue │ ├── button.vue │ └── index.js ├── calendar │ ├── calendar.vue │ └── index.js ├── card │ ├── card.vue │ └── index.js ├── carousel-item │ └── index.js ├── carousel │ ├── carousel-item.vue │ ├── carousel.vue │ └── index.js ├── cascader-panel │ ├── index.js │ ├── src │ │ ├── index.vue │ │ ├── menu.vue │ │ └── node.vue │ └── utils │ │ ├── config.js │ │ ├── node.js │ │ ├── store.js │ │ └── utils.js ├── cascader │ ├── cascader.vue │ └── index.js ├── checkbox-group │ └── index.js ├── checkbox │ ├── checkbox-group.vue │ ├── checkbox.vue │ ├── index.js │ └── useCheckbox.js ├── circle │ ├── circle.vue │ └── index.js ├── col │ ├── col.vue │ └── index.js ├── collapse-panel │ └── index.js ├── collapse-transition │ ├── collapse-transition.vue │ └── index.js ├── collapse-wrap │ ├── index.js │ └── wrapper.vue ├── collapse │ ├── collapse.vue │ ├── index.js │ └── panel.vue ├── color-picker │ ├── alpha-slider.vue │ ├── color.js │ ├── draggable.js │ ├── hue-slider.vue │ ├── index.js │ ├── picker.vue │ ├── predefine.vue │ └── sv-panel.vue ├── config-provider │ ├── index.js │ └── src │ │ ├── ConfigProvider.js │ │ ├── context.js │ │ └── types.js ├── count-to │ ├── count-to.vue │ └── index.js ├── date-picker │ ├── date-picker-com │ │ ├── basic-date-table.vue │ │ ├── basic-month-table.vue │ │ ├── basic-year-table.vue │ │ ├── panel-date-pick.vue │ │ ├── panel-date-range.vue │ │ └── panel-month-range.vue │ ├── date-picker.js │ └── index.js ├── desc-item │ ├── index.js │ └── item.vue ├── desc │ ├── desc.vue │ ├── descriptions-cell.js │ ├── descriptions-row.vue │ └── index.js ├── divider │ ├── divider.vue │ └── index.js ├── drawer │ ├── drawer.vue │ └── index.js ├── dropdown-item │ └── index.js ├── dropdown-menu │ └── index.js ├── dropdown │ ├── dropdown-item.vue │ ├── dropdown-menu.vue │ ├── dropdown.vue │ ├── index.js │ └── useDropdown.js ├── empty │ ├── empty.vue │ └── index.js ├── form-item │ └── index.js ├── form │ ├── form-item.vue │ ├── form.vue │ ├── index.js │ ├── label-wrap.js │ └── token.js ├── icon-select │ ├── icon-select.vue │ └── index.js ├── icon │ ├── icon.vue │ └── index.js ├── input-number │ ├── index.js │ └── input-number.vue ├── input │ ├── calcTextareaHeight.js │ ├── index.js │ └── input.vue ├── layout │ ├── Layout.vue │ └── index.js ├── loading-bar │ ├── index.js │ ├── instance.js │ └── loading-bar.vue ├── loading │ ├── index.js │ └── loading.vue ├── menu-item-group │ └── index.js ├── menu-item │ └── index.js ├── menu │ ├── index.js │ ├── menu-item-group.vue │ ├── menu-item.vue │ ├── menu.vue │ ├── submenu.vue │ ├── useMenu.js │ ├── useMenuColor.js │ └── util │ │ ├── menu-bar.js │ │ ├── menu-item.js │ │ └── submenu.js ├── message-box │ ├── index.js │ ├── instance.js │ └── message-box.vue ├── message │ ├── index.js │ ├── instance.js │ └── message.vue ├── modal │ ├── addListener.js │ ├── index.js │ ├── mask.vue │ ├── modal.vue │ └── useModal.js ├── move-transition │ ├── index.js │ └── move-transition.js ├── notice │ ├── index.js │ ├── instance.js │ └── notice.vue ├── option-group │ └── index.js ├── option │ └── index.js ├── page │ ├── index.js │ ├── options.vue │ └── page.vue ├── popover │ ├── index.js │ ├── popover.vue │ └── usePopover.js ├── popper │ ├── index.js │ └── src │ │ ├── index.vue │ │ ├── renderers │ │ ├── arrow.js │ │ ├── index.js │ │ ├── popper.js │ │ └── trigger.js │ │ └── use-popper │ │ ├── build-modifiers.js │ │ ├── defaults.js │ │ ├── index.js │ │ └── popper-options.js ├── progress │ ├── index.js │ └── progress.vue ├── radio-group │ └── index.js ├── radio │ ├── index.js │ ├── radio-group.vue │ ├── radio.vue │ └── useRadio.js ├── rate │ ├── index.js │ └── rate.vue ├── row │ ├── index.js │ └── row.vue ├── scrollbar │ ├── bar.js │ ├── index.js │ ├── scrollbar.vue │ └── util.js ├── select │ ├── index.js │ ├── option-group.vue │ ├── option.vue │ ├── select-dropdown.vue │ ├── select.vue │ ├── token.js │ ├── useOption.js │ └── useSelect.js ├── skeleton-item │ ├── img-placeholder.vue │ ├── index.js │ └── item.vue ├── skeleton │ ├── index.js │ ├── skeleton.vue │ └── use-throttle.js ├── slider │ ├── index.js │ └── src │ │ ├── button.vue │ │ ├── index.vue │ │ ├── marker.vue │ │ ├── useMarks.js │ │ ├── useSlide.js │ │ ├── useSliderButton.js │ │ └── useStops.js ├── space │ ├── index.js │ ├── item.vue │ └── useSpace.js ├── split │ ├── index.js │ ├── pane.vue │ ├── resizer.vue │ └── split.vue ├── step │ └── index.js ├── steps │ ├── index.js │ ├── step.vue │ └── steps.vue ├── submenu │ └── index.js ├── switch │ ├── index.js │ └── switch.vue ├── table │ ├── cell.vue │ ├── index.js │ ├── main │ │ ├── expand.js │ │ ├── header.js │ │ ├── mixin.js │ │ ├── slot.js │ │ └── util.js │ ├── table-body.vue │ ├── table-head.vue │ ├── table-tr.vue │ └── table.vue ├── tabs │ ├── index.js │ ├── scroll-pane.vue │ └── tabs.vue ├── tag │ ├── index.js │ └── tag.vue ├── time-picker │ ├── common │ │ ├── constant.js │ │ ├── date-utils.js │ │ ├── picker.vue │ │ └── props.js │ ├── index.js │ ├── time-picker-com │ │ ├── basic-time-spinner.vue │ │ ├── panel-time-pick.vue │ │ ├── panel-time-range.vue │ │ └── useTimePicker.js │ └── time-picker.js ├── timeline-item │ └── index.js ├── timeline │ ├── index.js │ ├── timeline-item.vue │ └── timeline.vue ├── tooltip │ ├── index.js │ └── tooltip.js ├── tree-big │ └── index.js ├── tree-select │ ├── index.js │ └── tree-select.vue ├── tree │ ├── big-tree.vue │ ├── index.js │ ├── node.vue │ ├── render.js │ └── tree.vue └── upload │ ├── ajax.js │ ├── index.js │ ├── upload-list.vue │ └── upload.vue ├── directives ├── click-animation │ └── index.js ├── click-outside │ └── index.js ├── index.js ├── loading │ └── index.js ├── no-data │ └── index.js ├── repeat-click │ └── index.js └── waves │ └── index.js ├── hooks ├── index.js ├── useFocus.js ├── useForm.js ├── useLockScreen.js ├── useModal.js ├── useModalDrag.js ├── useMousePosition.js ├── useRestoreActive.js ├── useSortable.js └── useTimeout.js ├── index.js ├── styles ├── common │ ├── common.styl │ ├── mixins.styl │ ├── transition.styl │ ├── vars.styl │ └── waves.styl ├── components │ ├── affix.styl │ ├── alert.styl │ ├── anchor.styl │ ├── backtop.styl │ ├── badge.styl │ ├── breadcrumb.styl │ ├── button.styl │ ├── calendar.styl │ ├── card.styl │ ├── carousel.styl │ ├── cascader-panel.styl │ ├── cascader.styl │ ├── checkbox.styl │ ├── circle.styl │ ├── collapse.styl │ ├── color-picker.styl │ ├── date-picker.styl │ ├── desc.styl │ ├── divider.styl │ ├── drawer.styl │ ├── dropdown.styl │ ├── empty.styl │ ├── form.styl │ ├── grid.styl │ ├── icon.styl │ ├── input-number.styl │ ├── input.styl │ ├── layout.styl │ ├── loading.styl │ ├── loadingbar.styl │ ├── mask.styl │ ├── menu.styl │ ├── message-box.styl │ ├── message.styl │ ├── modal.styl │ ├── notice.styl │ ├── page.styl │ ├── popover.styl │ ├── popper.styl │ ├── progress.styl │ ├── radio.styl │ ├── rate.styl │ ├── scrollbar.styl │ ├── select.styl │ ├── skeleton.styl │ ├── slider.styl │ ├── space.styl │ ├── split.styl │ ├── steps.styl │ ├── switch.styl │ ├── table.styl │ ├── tabs.styl │ ├── tag.styl │ ├── time-picker.styl │ ├── timeline.styl │ ├── tree.styl │ └── upload.styl ├── flex.styl ├── fonts │ ├── iconfont.eot │ ├── iconfont.json │ ├── iconfont.svg │ ├── iconfont.ttf │ ├── iconfont.woff │ └── iconfont.woff2 ├── icon.styl ├── index.styl ├── normalize.styl └── scrollbar.styl └── utils ├── TransitionEvents.js ├── aria.js ├── color.js ├── config-util.js ├── config.js ├── constants.js ├── create-loading-like-directive.js ├── dom.js ├── isDef.js ├── isServer.js ├── log.js ├── popup-manager.js ├── resize-event.js ├── scroll-into-view.js ├── util-helper.js ├── util.js ├── validator-size.js └── vnode.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,jsx,ts,tsx,vue}] 2 | indent_style = space 3 | indent_size = 2 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | public/ 3 | es/ 4 | lib/ 5 | dist/ 6 | package.json 7 | src/assets/ 8 | plop-templates/ 9 | handlebars/ 10 | website/ 11 | build/ 12 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | es6: true, 6 | node: true, 7 | }, 8 | globals: { 9 | defineEmits: 'readonly', 10 | defineProps: 'readonly', 11 | defineExpose: 'readonly', 12 | defineOptions: 'readonly', 13 | }, 14 | extends: ['eslint:recommended', 'plugin:vue/vue3-essential'], 15 | parserOptions: { 16 | parser: '@babel/eslint-parser', 17 | }, 18 | rules: { 19 | 'no-unused-vars': 'warn', 20 | 'no-var': 'error', 21 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 22 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 23 | 'space-before-function-paren': 'off', 24 | 'template-curly-spacing': 'off', 25 | 'comma-dangle': 'off', 26 | eqeqeq: ['error', 'always'], 27 | indent: 'off', 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | /lib 5 | 6 | # local env files 7 | .env.local 8 | .env.*.local 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn-debug.log* 13 | yarn-error.log* 14 | pnpm-debug.log* 15 | 16 | # Editor directories and files 17 | .idea 18 | .vscode 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.md 3 | *.yml 4 | build/ 5 | node_modules/ 6 | test/ 7 | gulpfile.js 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | docs 3 | node_modules 4 | pnpm-lock.yaml -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "useTabs": false, 4 | "semi": false, 5 | "singleQuote": true, 6 | "quoteProps": "as-needed", 7 | "trailingComma": "all", 8 | "bracketSpacing": true, 9 | "arrowParens": "avoid", 10 | "htmlWhitespaceSensitivity": "ignore", 11 | "overrides": [ 12 | { 13 | "files": ".prettierrc", 14 | "options": { 15 | "parser": "json" 16 | } 17 | } 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bin-ui-next 2 | 3 | bin-ui-next 是基于 vue3.0 的组件库,是 bin-ui 的升级,提供常用组件和公共样式、函数 4 | 5 | ## Docs 6 | 7 | [document](https://wangbin3162.github.io/bin-ui-next/) 8 | 9 | ## Bin-UI-Next 10 | 11 | bin-ui-next 是 bin-ui 的 vue3 升级版,目前组件源码正在疯狂重构中... 12 | 13 | 整体 api 设计仍然基于原有库,只会在极个别组件进行重构优化,整体组件依赖 vue3,使用 typescript 编写代码 14 | 15 | ### 特性 16 | 17 | - 💪 基于 Vue 3.0 Composition API 18 | - 🔥 Written in TypeScript 19 | - 🌈 最新图标基于阿里 iconfont ant-design 官方图标精简版 20 | - 🗑 移除了部分冗余代码 21 | - ⌨️ 部分组件代码进行重构优化 22 | 23 | ### 支持环境 24 | 25 | - 支持 ie11 以上 26 | - 支持服务端渲染 27 | 28 | ### 版本 29 | 30 | [![NPM version](https://img.shields.io/npm/v/bin-ui-next.svg)](https://www.npmjs.com/package/bin-ui-next) 31 | 32 | ### 安装 33 | 34 | 推荐使用 `npm` 或 `yarn` 进行安装,它能更好地和 `webpack` 打包工具配合使用。而且可以更好的和 `es6` `typescript` 配合使用。并且支持按需引入 35 | 36 | ```shell 37 | npm i bin-ui-next -S 38 | # or 39 | yarn add bin-ui-next 40 | ``` 41 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | loose: true, 7 | modules: false, 8 | }, 9 | ], 10 | ], 11 | plugins: [ 12 | ['@babel/plugin-transform-runtime', { 13 | 'regenerator': true, 14 | }], 15 | ], 16 | env: { 17 | utils: { 18 | presets: [ 19 | [ 20 | '@babel/env', 21 | { 22 | loose: true, 23 | modules: false, 24 | }, 25 | ], 26 | ], 27 | plugins: [ 28 | [ 29 | 'babel-plugin-module-resolver', 30 | { 31 | root: ['bin-ui-next'], 32 | alias: { 'bin-ui-next/src': 'bin-ui-next/lib' }, 33 | }, 34 | ], 35 | ], 36 | }, 37 | }, 38 | } 39 | -------------------------------------------------------------------------------- /build/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | // 单独打包css 3 | const {src, dest, series, task} = require('gulp') 4 | const stylus = require('gulp-stylus') 5 | const autoprefixer = require('gulp-autoprefixer') 6 | const cssmin = require('gulp-cssmin') 7 | 8 | // 打包默认的 9 | function compile() { 10 | return src('../src/styles/*.styl') 11 | .pipe(stylus()) 12 | .pipe(autoprefixer({ 13 | overrideBrowserslist: ['ie > 9', 'last 2 versions'], 14 | cascade: false, 15 | })) 16 | .pipe(cssmin()) 17 | .pipe(dest('../lib/styles')) 18 | } 19 | 20 | // 打包组件样式 21 | function compileComponents() { 22 | return src('../src/styles/components/*.styl') 23 | .pipe(stylus()) 24 | .pipe(autoprefixer({ 25 | overrideBrowserslist: ['ie > 9', 'last 2 versions'], 26 | cascade: false, 27 | })) 28 | .pipe(cssmin()) 29 | .pipe(dest('../lib/styles/components')) 30 | } 31 | 32 | // 复制字体包 33 | function copyFont() { 34 | return src('../src/styles/fonts/**') 35 | .pipe(cssmin()) 36 | .pipe(dest('../lib/styles/fonts')) 37 | } 38 | 39 | task('default', series(copyFont, compile, compileComponents)) 40 | -------------------------------------------------------------------------------- /build/md-loader/config.js: -------------------------------------------------------------------------------- 1 | const Config = require('markdown-it-chain') 2 | const anchorPlugin = require('markdown-it-anchor') 3 | const slugify = require('transliteration').slugify 4 | const hljs = require('highlight.js') 5 | const containers = require('./containers') 6 | const overWriteFenceRule = require('./fence') 7 | 8 | const config = new Config() 9 | 10 | const highlight = (str, lang) => { 11 | if (!lang || !hljs.getLanguage(lang)) { 12 | return '
' + str + '
' 13 | } 14 | const html = hljs.highlight(str, { language: lang, ignoreIllegals: true }).value 15 | return `
${html}
` 16 | } 17 | 18 | config 19 | .options.html(true).highlight(highlight).end() 20 | 21 | .plugin('anchor').use(anchorPlugin, [ 22 | { 23 | level: 2, 24 | slugify: slugify, 25 | permalink: false, 26 | permalinkBefore: false, 27 | }, 28 | ]).end() 29 | 30 | .plugin('containers').use(containers).end() 31 | 32 | const md = config.toMd() 33 | overWriteFenceRule(md) 34 | 35 | module.exports = md 36 | -------------------------------------------------------------------------------- /build/md-loader/containers.js: -------------------------------------------------------------------------------- 1 | const mdContainer = require('markdown-it-container') 2 | 3 | module.exports = md => { 4 | md.use(mdContainer, 'demo', { 5 | validate(params) { 6 | return params.trim().match(/^demo\s*(.*)$/) 7 | }, 8 | render(tokens, idx) { 9 | const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/) 10 | if (tokens[idx].nesting === 1) { 11 | const description = m && m.length > 1 ? m[1] : '' 12 | const content = tokens[idx + 1].type === 'fence' ? tokens[idx + 1].content : '' 13 | return ` 14 | ${description ? `
${md.render(description)}
` : ''} 15 | 16 | ` 17 | } 18 | return '
' 19 | }, 20 | }) 21 | 22 | md.use(mdContainer, 'tip') 23 | md.use(mdContainer, 'warning') 24 | } 25 | -------------------------------------------------------------------------------- /build/md-loader/fence.js: -------------------------------------------------------------------------------- 1 | // 覆盖默认的 fence 渲染策略 2 | module.exports = md => { 3 | const defaultRender = md.renderer.rules.fence 4 | md.renderer.rules.fence = (tokens, idx, options, env, self) => { 5 | const token = tokens[idx] 6 | // 判断该 fence 是否在 :::demo 内 7 | const prevToken = tokens[idx - 1] 8 | const isInDemoContainer = prevToken && prevToken.nesting === 1 && prevToken.info.trim().match(/^demo\s*(.*)$/) 9 | if (token.info === 'html' && isInDemoContainer) { 10 | return `` 11 | } 12 | return defaultRender(tokens, idx, options, env, self) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /docs/0c51f5157c4954238cc7.ttf: -------------------------------------------------------------------------------- 1 | export default __webpack_public_path__ + "static/iconfont.0bf6cd3.ttf"; -------------------------------------------------------------------------------- /docs/0e183abb317dc7309207.eot: -------------------------------------------------------------------------------- 1 | export default __webpack_public_path__ + "static/iconfont.e3031e0.eot"; -------------------------------------------------------------------------------- /docs/511aad842c035d563ea2.woff: -------------------------------------------------------------------------------- 1 | export default __webpack_public_path__ + "static/iconfont.90bdc02.woff"; -------------------------------------------------------------------------------- /docs/ea78a237145b724f979a.svg: -------------------------------------------------------------------------------- 1 | export default __webpack_public_path__ + "static/iconfont.a49ca6a.svg"; -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/docs/favicon.ico -------------------------------------------------------------------------------- /docs/static/iconfont.0bf6cd3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/docs/static/iconfont.0bf6cd3.ttf -------------------------------------------------------------------------------- /docs/static/iconfont.90bdc02.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/docs/static/iconfont.90bdc02.woff -------------------------------------------------------------------------------- /docs/static/iconfont.e3031e0.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/docs/static/iconfont.e3031e0.eot -------------------------------------------------------------------------------- /examples/assets/images/Bin-UI-Next-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/Bin-UI-Next-01.png -------------------------------------------------------------------------------- /examples/assets/images/Bin-UI-Next-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/Bin-UI-Next-02.png -------------------------------------------------------------------------------- /examples/assets/images/Bin-UI-Next-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/Bin-UI-Next-03.png -------------------------------------------------------------------------------- /examples/assets/images/Bin-UI-Next-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/Bin-UI-Next-04.png -------------------------------------------------------------------------------- /examples/assets/images/Bin-UI-Next-05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/Bin-UI-Next-05.png -------------------------------------------------------------------------------- /examples/assets/images/admin/Bin-Admin-Pro-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/admin/Bin-Admin-Pro-01.png -------------------------------------------------------------------------------- /examples/assets/images/admin/Bin-Admin-Pro-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/admin/Bin-Admin-Pro-02.png -------------------------------------------------------------------------------- /examples/assets/images/admin/Bin-Admin-Pro-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/admin/Bin-Admin-Pro-03.png -------------------------------------------------------------------------------- /examples/assets/images/bin-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/bin-ui.png -------------------------------------------------------------------------------- /examples/assets/images/logo/bin-ui-next-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/logo/bin-ui-next-01.png -------------------------------------------------------------------------------- /examples/assets/images/logo/bin-ui-next-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/logo/bin-ui-next-02.png -------------------------------------------------------------------------------- /examples/assets/images/logo/bin-ui-next-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/logo/bin-ui-next-03.png -------------------------------------------------------------------------------- /examples/assets/images/logo/favicon1.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/logo/favicon1.ico -------------------------------------------------------------------------------- /examples/assets/images/logo/favicon2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/logo/favicon2.ico -------------------------------------------------------------------------------- /examples/assets/images/logo/favicon3.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/logo/favicon3.ico -------------------------------------------------------------------------------- /examples/assets/images/logo01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/assets/images/logo01.png -------------------------------------------------------------------------------- /examples/assets/images/svg/code-show.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | code-open 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/assets/images/svg/code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | code 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/assets/styles/base.styl: -------------------------------------------------------------------------------- 1 | // 优化显示 2 | body { 3 | color: #515a6e; 4 | font-size: 14px; 5 | font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -webkit-tap-highlight-color: transparent; 8 | } 9 | 10 | ul { 11 | margin: 0; 12 | padding: 0; 13 | list-style: none; 14 | } 15 | ul li { 16 | margin: 0; 17 | padding: 0; 18 | list-style: none; 19 | } 20 | a { 21 | color: #1089ff; 22 | text-decoration: none; 23 | &:focus { 24 | outline: none; 25 | } 26 | } 27 | 28 | .icon-loading { 29 | animation: rotating 2s linear infinite; 30 | } 31 | 32 | @keyframes rotating { 33 | 0% { 34 | transform: rotateZ(0deg); 35 | } 36 | 100% { 37 | transform: rotateZ(360deg); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /examples/assets/styles/color-brewer.styl: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Colorbrewer theme 4 | Original: https://github.com/mbostock/colorbrewer-theme (c) Mike Bostock 5 | Ported by Fabrício Tavares de Oliveira 6 | 7 | */ 8 | 9 | .hljs { 10 | display: block; 11 | overflow-x: auto; 12 | padding: 0.5em; 13 | background: #fff; 14 | } 15 | 16 | .hljs, 17 | .hljs-subst { 18 | color: #000; 19 | } 20 | 21 | .hljs-string, 22 | .hljs-meta, 23 | .hljs-symbol, 24 | .hljs-template-tag, 25 | .hljs-template-variable, 26 | .hljs-addition { 27 | color: #f72671; 28 | } 29 | 30 | .hljs-comment, 31 | .hljs-quote { 32 | color: #636363; 33 | } 34 | 35 | .hljs-number, 36 | .hljs-regexp, 37 | .hljs-literal, 38 | .hljs-bullet, 39 | .hljs-link { 40 | color: #31a354; 41 | } 42 | 43 | .hljs-deletion, 44 | .hljs-variable { 45 | color: #88f; 46 | } 47 | 48 | 49 | .hljs-keyword, 50 | .hljs-selector-tag, 51 | .hljs-title, 52 | .hljs-section, 53 | .hljs-built_in, 54 | .hljs-doctag, 55 | .hljs-type, 56 | .hljs-tag, 57 | .hljs-name, 58 | .hljs-selector-id, 59 | .hljs-selector-class, 60 | .hljs-strong { 61 | color: #3182bd; 62 | } 63 | 64 | .hljs-emphasis { 65 | font-style: italic; 66 | } 67 | 68 | .hljs-attribute { 69 | color: #e6550d; 70 | } 71 | 72 | 73 | .hljs { 74 | line-height: 1.5715; 75 | font-family: Menlo, Monaco, Consolas, Courier, monospace; 76 | font-size: 12px; 77 | padding: 18px 24px; 78 | background-color: #fafafa; 79 | border: 1px solid #eaeefb; 80 | margin-bottom: 25px; 81 | border-radius: 4px; 82 | -webkit-font-smoothing: auto; 83 | } 84 | -------------------------------------------------------------------------------- /examples/assets/styles/index.styl: -------------------------------------------------------------------------------- 1 | @import 'color-brewer.styl'; 2 | @import 'base.styl'; 3 | @import 'common.styl'; 4 | @import 'demo.styl'; 5 | -------------------------------------------------------------------------------- /examples/assets/styles/scrollbar.styl: -------------------------------------------------------------------------------- 1 | // ================================= 2 | // ==============scrollbar========== 3 | // ================================= 4 | ::-webkit-scrollbar { 5 | width: 6px; 6 | height: 6px; 7 | } 8 | 9 | ::-webkit-scrollbar-track { 10 | background: rgba(0, 0, 0, 0.05); 11 | } 12 | 13 | ::-webkit-scrollbar-thumb { 14 | background: rgba(0, 0, 0, 0.2); 15 | box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1); 16 | transition: box-shadow 1.2s; 17 | } 18 | 19 | ::-webkit-scrollbar-thumb:hover { 20 | box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.25); 21 | } 22 | -------------------------------------------------------------------------------- /examples/components/SvgLoading/loading/loading02.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 31 | -------------------------------------------------------------------------------- /examples/components/SvgLoading/loading/loading03.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /examples/components/SvgLoading/loading/loading04.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 37 | -------------------------------------------------------------------------------- /examples/components/SvgLoading/loading/loading05.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /examples/components/SvgLoading/loading/loading09.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 40 | -------------------------------------------------------------------------------- /examples/components/SvgLoading/loading/loading10.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 27 | -------------------------------------------------------------------------------- /examples/components/footer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 20 | -------------------------------------------------------------------------------- /examples/docs/affix.md: -------------------------------------------------------------------------------- 1 | ## Affix 图钉 2 | 3 | ### 基础用法 4 | 5 | 原生滚动相对于window窗口固定,也可以结合scrollbar进行配置 6 | 7 | ::: demo 8 | 9 | ```html 10 | 11 | 16 | ``` 17 | 18 | ::: 19 | 20 | ### 固定位置 21 | 22 | 可以设置固定距离底部的位置 23 | 24 | ::: demo 25 | 26 | ```html 27 | 28 | 33 | ``` 34 | 35 | ::: 36 | 37 | ### Props 38 | 39 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 40 | |---------- |-------- |---------- |------------- |-------- | 41 | | offset | 距离窗口位置触发 | Number | — | 0 | 42 | | position | 可设置距离顶部或底部 | String | top、bottom | top | 43 | | z-index | 层级 | Number | — | 10 | 44 | 45 | ### Events 46 | 47 | | 事件名 | 说明 | 返回值 | 48 | |---------- |-------- |---------- | 49 | | change | 在固定状态发生改变时触发 | true/false | 50 | | scroll | 滚动响应事件 | Object{scrollTop,fixed} | 51 | 52 | ### Slot 53 | 54 | | 名称 | 说明 | 55 | |---------- |-------- | 56 | | default | 警告提示内容 | 57 | -------------------------------------------------------------------------------- /examples/docs/badge.md: -------------------------------------------------------------------------------- 1 | ## Badge 徽标 2 | 3 | 用于提示当前条目数量等 4 | 5 | ### 基础用法 6 | 7 | 基础的徽标用法 8 | 9 | ::: demo 10 | 11 | ```html 12 | 13 | 30 | ``` 31 | 32 | ::: 33 | 34 | ### 自定义提示内容 35 | 36 | 可以提示非数字的徽标 37 | 38 | ::: demo 39 | 40 | ```html 41 | 42 | 51 | ``` 52 | 53 | ::: 54 | 55 | ### Props 56 | 57 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 58 | |---------- |-------- |---------- |------------- |-------- | 59 | | value | 显示值 | string, number | — | — | 60 | | max | 最大值,超过最大值会显示 '{max}+' | number | — | — | 61 | | is-dot | 小圆点 | boolean | — |false| 62 | | hidden | 隐藏 badge | boolean | — |false| 63 | | type | 类型 | string | primary / success / warning / danger / info | — | 64 | -------------------------------------------------------------------------------- /examples/docs/breadcrumb.md: -------------------------------------------------------------------------------- 1 | ## Breadcrumb 面包屑 2 | 3 | 显示当前页面的路径,快速返回之前的任意页面或者跳转链接 4 | 5 | ### 基础用法 6 | 7 | 面包屑的用法,separator设置分隔符 不设置to属性,一切都需要自行在插槽中灵活运用 8 | 9 | ::: demo 10 | 11 | ```html 12 | 13 | 38 | ``` 39 | 40 | ::: 41 | 42 | ### 分隔符 43 | 44 | 可以设置分隔符 45 | 46 | ::: demo 47 | 48 | ```html 49 | 50 | 63 | ``` 64 | 65 | ::: 66 | 67 | ### Breadcrumb Props 68 | 69 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 70 | |---------- |-------- |---------- |------------- |-------- | 71 | | separator | 分隔 | string | — | '/' | 72 | | separator-icon| 图标分隔符icon | string | — | — | 73 | -------------------------------------------------------------------------------- /examples/docs/calendar.md: -------------------------------------------------------------------------------- 1 | ## Calendar 日历组件 2 | 3 | ### 基础用法 4 | 5 | 简单的日历组件用于装饰页面 6 | 7 | ::: demo 8 | 9 | ```html 10 | 11 | 14 | ``` 15 | 16 | ::: 17 | 18 | ### mini显示 19 | 20 | 简单的日历组件用于装饰页面 21 | 22 | ::: demo 23 | 24 | ```html 25 | 26 | 36 | ``` 37 | 38 | ::: 39 | 40 | ### Props 41 | 42 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 43 | |---------- |-------- |---------- |------------- |-------- | 44 | | grid-height | 日期高度,不填默认 80 | String | — | 80px | 45 | | text-align | 日期对其方式 | String | left center right | left | 46 | | mini | 迷你模式 | Boolean | l— | — | 47 | | body-style | 日期表body样式 | Object | — | — | 48 | | day-style | 每天样式 | Object | — | — | 49 | 50 | ### Events 51 | 52 | | 事件名 | 说明 | 返回值 | 53 | |---------- |-------- |---------- | 54 | | prev | 上个月按钮事件 | — | 55 | | next | 下个月按钮事件 | — | 56 | | today | 今天按钮事件 | — | 57 | | selected | 选中某一天事件 | day | 58 | -------------------------------------------------------------------------------- /examples/docs/color.md: -------------------------------------------------------------------------------- 1 | ## 色彩设计 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/docs/config-provider.md: -------------------------------------------------------------------------------- 1 | ## ConfigProvider 全局配置 2 | 3 | ### 基础用法 4 | 5 | 可以借助全局配置组件,来进行样式覆盖 6 | 7 | ::: demo 8 | 9 | ```html 10 | 11 | 17 | ``` 18 | 19 | ::: 20 | 21 | ### 抽象容器 22 | 23 | 可以使用抽象标签来注入,这里会默认注入到html ,进行全局覆盖(慎用) 24 | 25 | ::: demo 26 | 27 | ```html 28 | 29 | 34 | 35 | 53 | ``` 54 | 55 | ::: 56 | 57 | 58 | ### Props 59 | 60 | 61 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 62 | |---------- |-------- |---------- |------------- |-------- | 63 | | abstract | 抽象的,没有实体dom,参数会注入到ducument | boolean | — | — | 64 | | tag | 渲染dom | string | — | 'div' | 65 | | locale | 语言包 | string | — | zh-CN | 66 | | themeName | 主题名称 | string | 'dark' | — | 67 | | theme | 主题样式对象,这里可以存储js变量 使用首字母小写,连字符号后字母大写,如binColorPrimary | Object | — | — | -------------------------------------------------------------------------------- /examples/docs/directive.md: -------------------------------------------------------------------------------- 1 | ## 自定义指令 2 | 3 | ### 点击动画指令 4 | 5 | 在标签中追加`v-click-animation`指令增加点击动画指令,波纹颜色根据border或background颜色创建 6 | 7 | ::: demo 8 | 9 | ```html 10 | 11 | 24 | ``` 25 | 26 | ::: 27 | 28 | ### 水波纹指令 29 | 30 | 在标签中追加`v-waves`指令增加水波纹指令,指令可以设置波纹颜色和点击方式, 注意,增加水波纹指令会默认覆盖原有的按钮点击效果 31 | 32 | ::: demo 33 | 34 | ```html 35 | 36 | 42 | ``` 43 | 44 | ::: 45 | 46 | ### clickOutSide 47 | 48 | 通过添加`v-click-outside="clickOutSide"`来添加外部点击事件 49 | 50 | ::: demo 51 | 52 | ```html 53 | 54 | 62 | 71 | ``` 72 | 73 | ::: 74 | -------------------------------------------------------------------------------- /examples/docs/divider.md: -------------------------------------------------------------------------------- 1 | ## Divider 分割线 2 | 3 | 区隔内容的分割线。可以对对不同文本段落进行分割。可以对行内文字/链接进行分割,例如表格的操作列。 4 | 5 | ### 水平分割线 6 | 7 | 默认为水平分割线,可在中间加入文字。 可以是虚线 8 | 9 | :::demo 10 | 11 | ```html 12 | 13 | 22 | ``` 23 | 24 | ::: 25 | 26 | ### 垂直分割线 27 | 28 | 使用 type="vertical" 设置为行内的垂直分割线。 29 | 30 | :::demo 31 | 32 | ```html 33 | 34 | 41 | ``` 42 | 43 | ::: 44 | 45 | ### 修改标题的位置 46 | 47 | align属性可以设置标题位置 使用 align="left" 设置为行内的垂直分割线。 48 | 49 | :::demo 50 | 51 | ```html 52 | 53 | 58 | ``` 59 | 60 | ::: 61 | 62 | ### Props 63 | 64 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 65 | |---------- |-------- |---------- |------------- |-------- | 66 | | type | 水平还是垂直类型 | string | horizontal / vertical | horizontal | 67 | | align | 分割线标题的位置 | string | left / right / center | center | 68 | | dashed | 是否虚线 | Boolean | false / true | false | 69 | -------------------------------------------------------------------------------- /examples/docs/empty.md: -------------------------------------------------------------------------------- 1 | ## Empty 空状态 2 | 3 | ### 基础用法 4 | 5 | 目前表格和tree型结构使用,可以自定义标签使用,也可以使用指令使用 6 | 7 | ::: demo 8 | 9 | ```html 10 | 11 | 16 | ``` 17 | 18 | ::: 19 | 20 | ### 指令方式 21 | 22 | 可以使用v-no-data指令动态指定,并可以绑定显示文字 23 | 24 | ::: demo 25 | 26 | ```html 27 | 28 | 33 | 42 | ``` 43 | 44 | ::: 45 | 46 | ### Props 47 | 48 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 49 | |---------- |-------- |---------- |------------- |-------- | 50 | | title | 文字提示 | string | — | 暂无数据 | 51 | 52 | 53 | ### Slots 54 | 55 | | 参数 | 说明 | 56 | |---------- |-------- | 57 | | icon | 插入的图标内容 | 58 | 59 | 60 | ### Methods 61 | 62 | | 方法名 | 说明 | 返回值 | 63 | |---------- |-------- |---------- | 64 | | setTitle | 设置文字,主要为指令提供外部操作 | Function(title) | 65 | -------------------------------------------------------------------------------- /examples/docs/guide.md: -------------------------------------------------------------------------------- 1 | ## Bin-UI-Next 2 | 3 | bin-ui-next 是bin-ui的vue3升级版,目前组件库已经基本完成重构,整体组件依赖vue3 4 | 5 | ### 特性 6 | 7 | 13 | 14 | ### 支持环境 15 | 16 | 20 | 21 | ### 版本 22 | 23 | [![NPM version](https://img.shields.io/npm/v/bin-ui-next.svg)](https://www.npmjs.com/package/bin-ui-next) 24 | 25 | ### 相关链接 26 | 27 | [bin-ui](https://wangbin3162.github.io/bin-ui/) 28 | 29 | ### 安装 30 | 31 | 推荐使用 `npm` 或 `yarn` 进行安装,它能更好地和 `webpack` 打包工具配合使用。而且可以更好的和 `es6` `typescript` 配合使用。并且支持按需引入 32 | 33 | ```shell 34 | npm i bin-ui-next 35 | # or 36 | yarn add bin-ui-next 37 | # or 38 | pnpm add bin-ui-next 39 | ``` 40 | 41 | 如果您了解node.js、npm安装,并希望配合webpack使用,请阅读下一节:[快速上手](/#/start)。 42 | -------------------------------------------------------------------------------- /examples/docs/icon.md: -------------------------------------------------------------------------------- 1 | ## Icon 图标 2 | 3 | 图标这里使用了阿里[iconfont](https://www.iconfont.cn/)图标库生成了图标,图标来源于开源项目 ionicons,结合整理添加了一些其他的图标。 4 | 5 | i 标签可以直接设置样式类名为 `b-iconfont b-icon-xxx` 来使用即可。icon 组件可以只设置 name 来实用。 设置 `icon-is-rotating` 可以开启旋转 6 | 7 | :::demo size 和 color 可以设置字体大小和颜色 8 | 9 | ```html 10 | 11 |
12 | 13 | 14 | 15 | 16 |

17 | 图标选择器: 18 |

19 | 20 |
21 |

22 |
23 | ``` 24 | 25 | ::: 26 | 27 | ### 图标集合 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /examples/docs/layout.md: -------------------------------------------------------------------------------- 1 | ## Layout 基础布局 2 | 3 | ### 基础用法 4 | 5 | 目前暂时为简易左右布局,后续扩展 6 | 7 | ::: demo 8 | 9 | ```html 10 | 11 | 19 | ``` 20 | 21 | ::: 22 | 23 | 24 | ### Props 25 | 26 | 27 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 28 | |---------- |-------- |---------- |------------- |-------- | 29 | | hasSider | 是否又侧边栏(目前为左侧) | boolean | — | — | 30 | | siderWidth | 侧边栏宽度 | number | — | 240 | 31 | | collapsedWidth | 侧边栏折叠后宽度 | number | — | 40 | 32 | | showToggle | 是否显示折叠按钮 | boolean | — | true | 33 | | showCollapsedContent | 是否显示折叠后的内部区域 | boolean | — | false | 34 | | contentStyle | 右侧容器样式 | object | — | {} | -------------------------------------------------------------------------------- /examples/docs/scrollbar.md: -------------------------------------------------------------------------------- 1 | ## ScrollBar 滚动 2 | 3 | 由于默认浏览器滚动条极为丑陋切不同浏览器之间样式不统一,故封装一个滚动组件用于实现滚动 4 | 5 | ### 用法 6 | 7 | 使用`b-scrollbar`进行包裹,默认`slot`为内容显示区域,如当前示例所包含的滚动结构如下: 8 | :::demo 9 | 10 | ```html 11 | 12 | 19 | ``` 20 | 21 | ::: 22 | 23 | 注意:如果内容区域不超过容器高度则不会生成滚动条 24 | 25 | ### 使用贴士 26 | 27 | - b-scrollbar的父层要有固定高度 28 | - b-scrollbar的高度要设成100% 29 | - 如果出现横滚动条,请添加css(.bin-scrollbar__wrap{overflow-x:hidden;}) 30 | 31 | ### Props 32 | 33 | | 参数 | 说明 | 类型 | 可选值 | 默认值 | 34 | |---------- |-------- |---------- |------------- |-------- | 35 | | native | 是否采用原生滚动 (隐藏原生滚动条) | boolean | true | false | 36 | | always | 是否一直显示,而非悬停显示 | boolean | true | false | 37 | | wrapStyle | 内联方式 自定义wrap容器的样式 | Object | - | {} | 38 | | wrapClass | 类名方式 自定义wrap容器的样式 | Object | - | {} | 39 | | viewClass | 类名方式 自定义view容器的样式 | Object | - | {} | 40 | | viewStyle | 内联方式 自定义view容器的样式 | Object | - | {} | 41 | | barStyle | 滚动条thumb样式 | Object | - | {} | 42 | | barWrapStyle | 滚动条bar样式 | Object | - | {} | 43 | | noresize | 如果 container 尺寸不会发生变化,最好设置它可以优化性能 | boolean | true | false | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/docs/start.md: -------------------------------------------------------------------------------- 1 | ## 快速上手 2 | 3 | 本章节介绍如何在项目中使用vue3版本的bin-ui-next 4 | 5 | ### 引入 6 | 7 | 你可以引入整个 bin-ui-next,或是根据需要仅引入部分组件。我们先介绍如何引入完整的 bin-ui。 8 | 9 | #### 完整引入 10 | 11 | 在 main.js 中写入以下内容: 12 | 13 | ```javascript 14 | import { createApp } from 'vue' 15 | import BinUI from 'bin-ui-next' 16 | import App from './App.vue' 17 | import 'bin-ui-next/lib/styles/index.css' 18 | 19 | const app = createApp(App) 20 | app.use(BinUI) 21 | // app.use(BinUI,{disabledDoc:true}) // 可以设置禁用doc地址log 22 | app.mount('#app') 23 | ``` 24 | 25 | 以上代码便完成了 bin-ui-next 的引入。需要注意的是,样式文件需要单独引入。 26 | 27 | #### 按需引入 28 | 29 | 借助插件 [babel-plugin-import](https://github.com/ant-design/babel-plugin-import)我们可以只引入需要的组件,以达到减小项目体积的目的 30 | 31 | ```shell script 32 | npm install babel-plugin-import --save-dev 33 | ``` 34 | 35 | 然后,将 .babelrc 或 babel.config.js修改为: 36 | 37 | ```javascript 38 | module.exports = { 39 | presets: [ 40 | ['@vue/app', { 41 | useBuiltIns: 'entry' 42 | }] 43 | ], 44 | plugins: [ 45 | ["import", { 46 | "libraryName": "bin-ui-next", 47 | "libraryDirectory": "src/components" 48 | }] 49 | ] 50 | } 51 | ``` 52 | 53 | 如果你只希望引入部分组件,比如 Button 和 Icon,那么需要在 main.js 中写入以下内容 54 | 55 | ```javascript 56 | import { createApp } from 'vue' 57 | import { BButton } from 'bin-ui-next' 58 | import App from './App.vue' 59 | import 'bin-ui-next/lib/styles/components/button.css' 60 | 61 | const app = createApp(App) 62 | app.use(BButton) 63 | app.mount('#app') 64 | ``` 65 | 66 | **特别提醒:按需引用仍然需要导入样式,即在 main.js 或根组件 import 'bin-ui-next/lib/styles/index.css';** 67 | 68 | 完整组件列表参考源代码 69 | -------------------------------------------------------------------------------- /examples/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangbin3162/bin-ui-next/544f55f06d067ce354d7af68379206074f5ec117/examples/favicon.ico -------------------------------------------------------------------------------- /examples/generateTreeData.js: -------------------------------------------------------------------------------- 1 | let maxNode = 10000 // 最大的节点数 2 | const childNodesNumber = [2, 5] // 子节点数 3 | const maxLevel = 3 // 最大嵌套层级 4 | const childRate = 0.4 // 拥有子节点的概率 5 | const label = '节点' // 节点label 6 | 7 | let index = 0 8 | const data = [] 9 | 10 | const randomInteger = function (min, max) { 11 | let result = min - 0.5 + Math.random() * (max - min + 1) 12 | result = Math.round(result) 13 | return result 14 | } 15 | 16 | const generateId = function () { 17 | ++index 18 | return Math.random().toString().slice(3) * 1 19 | } 20 | const generateNode = function () { 21 | const id = generateId() 22 | return { 23 | id: id, 24 | title: `${label}_${index}-id:${id}` 25 | } 26 | } 27 | const generateChild = function (tree, level = 1) { 28 | if (index > maxNode - 1) return 29 | tree.children = [] 30 | const childNumber = randomInteger(childNodesNumber[0], childNodesNumber[1]) 31 | for (let i = 0; i < childNumber; i++) { 32 | if (index > maxNode - 1) break 33 | const obj = generateNode() 34 | 35 | if (Math.random() < childRate && level < maxLevel) { 36 | generateChild(obj, ++level) 37 | } 38 | tree.children.push(obj) 39 | } 40 | } 41 | 42 | const generate = function (number) { 43 | // eslint-disable-next-line no-const-assign 44 | maxNode = number 45 | // eslint-disable-next-line no-unmodified-loop-condition 46 | while (index < maxNode) { 47 | let obj = generateNode() 48 | generateChild(obj) 49 | data.push(obj) 50 | } 51 | return data 52 | } 53 | export default generate 54 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import router from './route' 3 | import App from './App.vue' 4 | 5 | import DemoBlock from './components/demo-block.vue' 6 | import MainFooter from './components/footer.vue' 7 | import MainHeader from './components/header.vue' 8 | import SideNav from './components/side-nav.vue' 9 | import ColorBase from './components/color-base.vue' 10 | import IconPane from './components/icon-pane.vue' 11 | import DraggableDemo from './components/draggable-demo' 12 | 13 | import BinUI from 'bin-ui-next' 14 | import * as BinUINext from 'bin-ui-next' 15 | import '../src/styles/normalize.styl' 16 | import '../src/styles/scrollbar.styl' 17 | import '../src/styles/index.styl' 18 | import './assets/styles/index.styl' 19 | 20 | import generate from './generateTreeData' 21 | 22 | const app = createApp(App) 23 | app.use(BinUI) // , { disabledDoc: true } 24 | app.config.productionTip = false 25 | app.config.globalProperties.$generateTree = generate // Icon 列表页用 26 | 27 | app.config.globalProperties.BinUINext = BinUINext // Icon 列表页用 28 | 29 | app.component('DemoBlock', DemoBlock) 30 | app.component('MainHeader', MainHeader) 31 | app.component('MainFooter', MainFooter) 32 | app.component('SideNav', SideNav) 33 | app.component('ColorBase', ColorBase) 34 | app.component('DraggableDemo', DraggableDemo) 35 | app.component('IconPane', IconPane) 36 | app.use(router) 37 | // Mount when the route is ready 38 | router.isReady().then(() => { 39 | app.mount('#app', true) 40 | }) 41 | -------------------------------------------------------------------------------- /examples/route.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHashHistory } from 'vue-router' 2 | import { nextTick } from 'vue' 3 | import { LoadingBar } from '../src' 4 | import hljs from 'highlight.js' 5 | 6 | const navConfig = require('./nav.config.json') 7 | 8 | let routes = [ 9 | { 10 | path: '', 11 | redirect: 'guide', 12 | name: 'index', 13 | }, 14 | ] 15 | 16 | Object.keys(navConfig).forEach((header) => { 17 | routes = routes.concat(navConfig[header]) 18 | }) 19 | 20 | const addComponent = router => { 21 | router.forEach((route) => { 22 | if (route.items) { 23 | addComponent(route.items) 24 | routes = routes.concat(route.items) 25 | } else { 26 | if (!route.name) return 27 | route.meta = { desc: route.desc } 28 | route.component = () => import(/* webpackChunkName: "DOCS" */ `./docs/${route.name}.md`) 29 | } 30 | }) 31 | } 32 | addComponent(routes) 33 | 34 | const router = createRouter({ 35 | history: createWebHashHistory(), 36 | routes, 37 | }) 38 | router.beforeEach((to, from, next) => { 39 | LoadingBar.start() 40 | next() 41 | }) 42 | router.afterEach(async () => { 43 | await nextTick() 44 | const blocks = document.querySelectorAll('pre code:not(.hljs)') 45 | Array.prototype.forEach.call(blocks, hljs.highlightElement) 46 | LoadingBar.done() 47 | }) 48 | 49 | export default router 50 | -------------------------------------------------------------------------------- /examples/util.js: -------------------------------------------------------------------------------- 1 | export function stripScript(content) { 2 | const result = content.match(/<(script)>([\s\S]+)<\/\1>/) 3 | return result && result[2] ? result[2].trim() : '' 4 | } 5 | 6 | export function stripStyle(content) { 7 | const result = content.match(/<(style)\s*>([\s\S]+)<\/\1>/) 8 | return result && result[2] ? result[2].trim() : '' 9 | } 10 | 11 | export function stripTemplate(content) { 12 | content = content.trim() 13 | if (!content) { 14 | return content 15 | } 16 | return content.replace(/<(script|style)[\s\S]+<\/\1>/g, '').trim() 17 | } 18 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "vueCompilerOptions": { 3 | "experimentalDisableTemplateSupport": true, 4 | "experimentalShamefullySupportOptionsApi": false 5 | }, 6 | "compilerOptions": { 7 | "baseUrl": ".", 8 | "paths": { 9 | "@/*": ["./src/*"] 10 | } 11 | }, 12 | "include": ["src/**/*.js", "src/**/*.vue"], 13 | "exclude": ["node_modules"] 14 | } 15 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer')({ 4 | browsers: [ 5 | 'defaults', 6 | 'not ie < 11', 7 | 'last 2 versions', 8 | '> 1%', 9 | 'iOS 7', 10 | 'last 3 iOS versions', 11 | ], 12 | }), 13 | ], 14 | } 15 | -------------------------------------------------------------------------------- /src/components/affix/index.js: -------------------------------------------------------------------------------- 1 | import Affix from './affix.vue' 2 | 3 | Affix.install = app => { 4 | app.component(Affix.name, Affix) 5 | } 6 | 7 | export default Affix 8 | -------------------------------------------------------------------------------- /src/components/alert/alert.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 76 | -------------------------------------------------------------------------------- /src/components/alert/index.js: -------------------------------------------------------------------------------- 1 | import Alert from './alert.vue' 2 | 3 | Alert.install = (app) => { 4 | app.component(Alert.name, Alert) 5 | } 6 | 7 | export default Alert 8 | -------------------------------------------------------------------------------- /src/components/anchor-link/index.js: -------------------------------------------------------------------------------- 1 | import AnchorLink from '../anchor/anchor-link.vue' 2 | 3 | AnchorLink.install = (app) => { 4 | app.component(AnchorLink.name, AnchorLink) 5 | } 6 | 7 | export default AnchorLink 8 | -------------------------------------------------------------------------------- /src/components/anchor/anchor-link.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 59 | -------------------------------------------------------------------------------- /src/components/anchor/index.js: -------------------------------------------------------------------------------- 1 | import Anchor from './anchor.vue' 2 | 3 | Anchor.install = (app) => { 4 | app.component(Anchor.name, Anchor) 5 | } 6 | 7 | export default Anchor 8 | -------------------------------------------------------------------------------- /src/components/back-top/index.js: -------------------------------------------------------------------------------- 1 | import BackTop from './back-top.vue' 2 | 3 | BackTop.install = (app) => { 4 | app.component(BackTop.name, BackTop) 5 | } 6 | 7 | export default BackTop 8 | -------------------------------------------------------------------------------- /src/components/badge/badge.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 49 | -------------------------------------------------------------------------------- /src/components/badge/index.js: -------------------------------------------------------------------------------- 1 | import Badge from './badge.vue' 2 | 3 | Badge.install = (app) => { 4 | app.component(Badge.name, Badge) 5 | } 6 | 7 | export default Badge 8 | -------------------------------------------------------------------------------- /src/components/breadcrumb-item/index.js: -------------------------------------------------------------------------------- 1 | import BreadcrumbItem from '../breadcrumb/breadcrumb-item.vue' 2 | 3 | BreadcrumbItem.install = (app) => { 4 | app.component(BreadcrumbItem.name, BreadcrumbItem) 5 | } 6 | 7 | export default BreadcrumbItem 8 | -------------------------------------------------------------------------------- /src/components/breadcrumb/breadcrumb-item.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 34 | -------------------------------------------------------------------------------- /src/components/breadcrumb/breadcrumb.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 35 | -------------------------------------------------------------------------------- /src/components/breadcrumb/index.js: -------------------------------------------------------------------------------- 1 | import Breadcrumb from './breadcrumb.vue' 2 | 3 | Breadcrumb.install = (app) => { 4 | app.component(Breadcrumb.name, Breadcrumb) 5 | } 6 | 7 | export default Breadcrumb 8 | -------------------------------------------------------------------------------- /src/components/button-group/index.js: -------------------------------------------------------------------------------- 1 | import ButtonGroup from '../button/button-group.vue' 2 | 3 | ButtonGroup.install = (app) => { 4 | app.component(ButtonGroup.name, ButtonGroup) 5 | } 6 | export default ButtonGroup 7 | -------------------------------------------------------------------------------- /src/components/button/button-group.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /src/components/button/index.js: -------------------------------------------------------------------------------- 1 | import Button from './button.vue' 2 | 3 | Button.install = (app) => { 4 | app.component(Button.name, Button) 5 | } 6 | 7 | export default Button 8 | -------------------------------------------------------------------------------- /src/components/calendar/index.js: -------------------------------------------------------------------------------- 1 | import Calendar from './calendar.vue' 2 | 3 | Calendar.install = (app) => { 4 | app.component(Calendar.name, Calendar) 5 | } 6 | 7 | export default Calendar 8 | -------------------------------------------------------------------------------- /src/components/card/card.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 51 | -------------------------------------------------------------------------------- /src/components/card/index.js: -------------------------------------------------------------------------------- 1 | import Card from './card.vue' 2 | 3 | Card.install = (app) => { 4 | app.component(Card.name, Card) 5 | } 6 | 7 | export default Card 8 | -------------------------------------------------------------------------------- /src/components/carousel-item/index.js: -------------------------------------------------------------------------------- 1 | import CarouselItem from '../carousel/carousel-item.vue' 2 | 3 | CarouselItem.install = (app) => { 4 | app.component(CarouselItem.name, CarouselItem) 5 | } 6 | 7 | export default CarouselItem 8 | -------------------------------------------------------------------------------- /src/components/carousel/index.js: -------------------------------------------------------------------------------- 1 | import Carousel from './carousel.vue' 2 | 3 | Carousel.install = (app) => { 4 | app.component(Carousel.name, Carousel) 5 | } 6 | 7 | export default Carousel 8 | -------------------------------------------------------------------------------- /src/components/cascader-panel/index.js: -------------------------------------------------------------------------------- 1 | import CascaderPanel from './src/index.vue' 2 | 3 | CascaderPanel.install = (app) => { 4 | app.component(CascaderPanel.name, CascaderPanel) 5 | } 6 | 7 | export default CascaderPanel 8 | -------------------------------------------------------------------------------- /src/components/cascader-panel/utils/config.js: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue' 2 | import { NOOP } from '@vue/shared' 3 | 4 | export const DefaultProps = { 5 | expandTrigger: 'click', 6 | multiple: false, 7 | checkStrictly: false, // whether all nodes can be selected 8 | emitPath: true, // wether to emit an array of all levels value in which node is located 9 | lazy: false, 10 | lazyLoad: NOOP, 11 | value: 'value', 12 | label: 'label', 13 | children: 'children', 14 | leaf: 'leaf', 15 | disabled: 'disabled', 16 | hoverThreshold: 500, 17 | } 18 | 19 | export const useCascaderConfig = (props) => { 20 | return computed(() => ({ 21 | ...DefaultProps, 22 | ...props.props, 23 | })) 24 | } 25 | -------------------------------------------------------------------------------- /src/components/cascader-panel/utils/store.js: -------------------------------------------------------------------------------- 1 | import Node from './node' 2 | import { isEqual } from '../../../utils/util' 3 | 4 | const flatNodes = (nodes, leafOnly) => { 5 | return nodes.reduce((res, node) => { 6 | if (node.isLeaf) { 7 | res.push(node) 8 | } else { 9 | !leafOnly && res.push(node) 10 | res = res.concat(flatNodes(node.children, leafOnly)) 11 | } 12 | return res 13 | }, []) 14 | } 15 | 16 | export default class Store { 17 | constructor(data, config) { 18 | this.config = config 19 | const nodes = (data || []).map(nodeData => new Node(nodeData, this.config)) 20 | this.nodes = nodes 21 | this.allNodes = flatNodes(nodes, false) 22 | this.leafNodes = flatNodes(nodes, true) 23 | } 24 | 25 | getNodes() { 26 | return this.nodes 27 | } 28 | 29 | getFlattedNodes(leafOnly) { 30 | return leafOnly ? this.leafNodes : this.allNodes 31 | } 32 | 33 | appendNode(nodeData, parentNode) { 34 | const node = parentNode 35 | ? parentNode.appendChild(nodeData) 36 | : new Node(nodeData, this.config) 37 | 38 | if (!parentNode) this.nodes.push(node) 39 | 40 | this.allNodes.push(node) 41 | node.isLeaf && this.leafNodes.push(node) 42 | } 43 | 44 | appendNodes(nodeDataList, parentNode) { 45 | nodeDataList.forEach(nodeData => this.appendNode(nodeData, parentNode)) 46 | } 47 | 48 | // when checkStrictly, leaf node first 49 | getNodeByValue(value, leafOnly = false) { 50 | if (!value && value !== 0) return null 51 | 52 | const nodes = this.getFlattedNodes(leafOnly) 53 | .filter(node => isEqual(node.value, value) || isEqual(node.pathValues, value)) 54 | 55 | return nodes[0] || null 56 | } 57 | 58 | getSameNode(node) { 59 | if (!node) return null 60 | 61 | const nodes = this.getFlattedNodes(false) 62 | .filter(({ value, level }) => isEqual(node.value, value) && node.level === level) 63 | 64 | return nodes[0] || null 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/components/cascader-panel/utils/utils.js: -------------------------------------------------------------------------------- 1 | export const isLeaf = (el) => !el.getAttribute('aria-owns') 2 | 3 | export const getSibling = (el, distance) => { 4 | const { parentNode } = el 5 | 6 | if (!parentNode) return null 7 | 8 | const siblings = parentNode.querySelectorAll('.bin-cascader-node[tabindex="-1"]') 9 | const index = Array.prototype.indexOf.call(siblings, el) 10 | return siblings[index + distance] || null 11 | } 12 | 13 | export const getMenuIndex = (el) => { 14 | if (!el) return 0 15 | const pieces = el.id.split('-') 16 | return Number(pieces[pieces.length - 2]) 17 | } 18 | 19 | export const focusNode = el => { 20 | if (!el) return 21 | el.focus() 22 | !isLeaf(el) && el.click() 23 | } 24 | 25 | export const checkNode = el => { 26 | if (!el) return 27 | 28 | const input = el.querySelector('input') 29 | if (input) { 30 | input.click() 31 | } else if (isLeaf(el)) { 32 | el.click() 33 | } 34 | } 35 | 36 | export const sortByOriginalOrder = (oldNodes, newNodes) => { 37 | const newNodesCopy = newNodes.slice(0) 38 | const newIds = newNodesCopy.map(node => node.uid) 39 | const res = oldNodes.reduce((acc, item) => { 40 | const index = newIds.indexOf(item.uid) 41 | if (index > -1) { 42 | acc.push(item) 43 | newNodesCopy.splice(index, 1) 44 | newIds.splice(index, 1) 45 | } 46 | return acc 47 | }, []) 48 | 49 | res.push(...newNodesCopy) 50 | 51 | return res 52 | } 53 | 54 | export const PANEL_INJECTION_KEY = Symbol() 55 | -------------------------------------------------------------------------------- /src/components/cascader/index.js: -------------------------------------------------------------------------------- 1 | import Cascader from './cascader.vue' 2 | 3 | Cascader.install = (app) => { 4 | app.component(Cascader.name, Cascader) 5 | } 6 | 7 | export default Cascader 8 | -------------------------------------------------------------------------------- /src/components/checkbox-group/index.js: -------------------------------------------------------------------------------- 1 | import CheckboxGroup from '../checkbox/checkbox-group.vue' 2 | 3 | CheckboxGroup.install = (app) => { 4 | app.component(CheckboxGroup.name, CheckboxGroup) 5 | } 6 | 7 | export default CheckboxGroup 8 | -------------------------------------------------------------------------------- /src/components/checkbox/checkbox-group.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 65 | -------------------------------------------------------------------------------- /src/components/checkbox/index.js: -------------------------------------------------------------------------------- 1 | import Checkbox from './checkbox.vue' 2 | 3 | Checkbox.install = (app) => { 4 | app.component(Checkbox.name, Checkbox) 5 | } 6 | 7 | export default Checkbox 8 | -------------------------------------------------------------------------------- /src/components/circle/index.js: -------------------------------------------------------------------------------- 1 | import Circle from './circle.vue' 2 | 3 | Circle.install = (app) => { 4 | app.component(Circle.name, Circle) 5 | } 6 | 7 | export default Circle 8 | -------------------------------------------------------------------------------- /src/components/col/index.js: -------------------------------------------------------------------------------- 1 | import Col from './col.vue' 2 | 3 | Col.install = (app) => { 4 | app.component(Col.name, Col) 5 | } 6 | 7 | export default Col 8 | -------------------------------------------------------------------------------- /src/components/collapse-panel/index.js: -------------------------------------------------------------------------------- 1 | import CollapsePanel from '../collapse/panel.vue' 2 | 3 | CollapsePanel.install = (app) => { 4 | app.component(CollapsePanel.name, CollapsePanel) 5 | } 6 | 7 | export default CollapsePanel 8 | -------------------------------------------------------------------------------- /src/components/collapse-transition/index.js: -------------------------------------------------------------------------------- 1 | import CollapseTransition from './collapse-transition.vue' 2 | 3 | CollapseTransition.install = (app) => { 4 | app.component(CollapseTransition.name, CollapseTransition) 5 | } 6 | 7 | export default CollapseTransition 8 | -------------------------------------------------------------------------------- /src/components/collapse-wrap/index.js: -------------------------------------------------------------------------------- 1 | import CollapseWrapper from './wrapper.vue' 2 | 3 | CollapseWrapper.install = (app) => { 4 | app.component(CollapseWrapper.name, CollapseWrapper) 5 | } 6 | 7 | export default CollapseWrapper 8 | -------------------------------------------------------------------------------- /src/components/collapse/index.js: -------------------------------------------------------------------------------- 1 | import Collapse from './collapse.vue' 2 | 3 | Collapse.install = (app) => { 4 | app.component(Collapse.name, Collapse) 5 | } 6 | 7 | export default Collapse 8 | -------------------------------------------------------------------------------- /src/components/collapse/panel.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 68 | -------------------------------------------------------------------------------- /src/components/color-picker/draggable.js: -------------------------------------------------------------------------------- 1 | import isServer from '../../utils/isServer' 2 | import { on, off } from '../../utils/dom' 3 | 4 | let isDragging = false 5 | 6 | export default function(element, options) { 7 | if (isServer) return 8 | 9 | const moveFn = function(event) { 10 | options.drag?.(event) 11 | } 12 | const upFn = function(event) { 13 | off(document, 'mousemove', moveFn) 14 | off(document, 'mouseup', upFn) 15 | document.onselectstart = null 16 | document.ondragstart = null 17 | 18 | isDragging = false 19 | 20 | options.end?.(event) 21 | } 22 | 23 | on(element, 'mousedown', function(event) { 24 | if (isDragging) return 25 | document.onselectstart = () => false 26 | document.ondragstart = () => false 27 | on(document, 'mousemove', moveFn) 28 | on(document, 'mouseup', upFn) 29 | 30 | isDragging = true 31 | 32 | options.start?.(event) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /src/components/color-picker/index.js: -------------------------------------------------------------------------------- 1 | import ColorPicker from './picker.vue' 2 | 3 | ColorPicker.install = (app) => { 4 | app.component(ColorPicker.name, ColorPicker) 5 | } 6 | 7 | export default ColorPicker 8 | -------------------------------------------------------------------------------- /src/components/color-picker/predefine.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 72 | -------------------------------------------------------------------------------- /src/components/config-provider/index.js: -------------------------------------------------------------------------------- 1 | import ConfigProvider from './src/ConfigProvider' 2 | 3 | ConfigProvider.install = app => { 4 | app.component(ConfigProvider.name, ConfigProvider) 5 | } 6 | 7 | export default ConfigProvider 8 | -------------------------------------------------------------------------------- /src/components/config-provider/src/context.js: -------------------------------------------------------------------------------- 1 | export const configProviderInjectionKey = Symbol('b-config-provider') 2 | -------------------------------------------------------------------------------- /src/components/config-provider/src/types.js: -------------------------------------------------------------------------------- 1 | // 配置注入器的props 2 | export const configProviderProps = { 3 | // 是否是抽象的 4 | abstract: { 5 | type: Boolean, 6 | }, 7 | tag: { 8 | type: String, 9 | default: 'div', 10 | }, 11 | // 是否禁用 inline css 主题变量 如果不需要更改主题变量theme 12 | inlineThemeDisabled: { 13 | type: Boolean, 14 | }, 15 | // 语言包 16 | locale: { 17 | type: String, 18 | default: 'zh-CN', 19 | }, 20 | // 主题名称 21 | themeName: { 22 | type: String, 23 | validate: val => ['dark'].includes(val), 24 | }, 25 | // 主题样式对象,这里可以存储js变量 26 | theme: { 27 | type: Object, 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /src/components/count-to/index.js: -------------------------------------------------------------------------------- 1 | import CountTo from './count-to' 2 | 3 | CountTo.install = app => { 4 | app.component(CountTo.name, CountTo) 5 | } 6 | 7 | export default CountTo 8 | -------------------------------------------------------------------------------- /src/components/date-picker/index.js: -------------------------------------------------------------------------------- 1 | import DatePicker from './date-picker' 2 | 3 | DatePicker.install = app => { 4 | app.component(DatePicker.name, DatePicker) 5 | } 6 | 7 | export default DatePicker 8 | -------------------------------------------------------------------------------- /src/components/desc-item/index.js: -------------------------------------------------------------------------------- 1 | import DescItem from './item' 2 | 3 | DescItem.install = (app) => { 4 | app.component(DescItem.name, DescItem) 5 | } 6 | export default DescItem 7 | -------------------------------------------------------------------------------- /src/components/desc-item/item.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /src/components/desc/descriptions-cell.js: -------------------------------------------------------------------------------- 1 | import { computed, h, inject } from 'vue' 2 | 3 | export default { 4 | name: 'BDescCell', 5 | props: { 6 | cell: { 7 | type: Object, 8 | }, 9 | tag: { 10 | type: String, 11 | }, 12 | type: { 13 | type: String, 14 | }, 15 | }, 16 | setup(props) { 17 | const descriptions = inject('BDesc', {}) 18 | 19 | const label = computed(() => props.cell?.children?.label?.() || props.cell?.props?.label) 20 | const content = computed(() => props.cell?.children?.default?.()) 21 | const span = computed(() => props.cell?.props?.span || 1) 22 | const labelWidth = computed(() => descriptions.labelWidth || (50 / descriptions.column)) 23 | const contentWidth = computed(() => { 24 | const labelWidth = descriptions.labelWidth 25 | const column = descriptions.column 26 | return labelWidth ? ((100 - column * labelWidth) / column) : (50 / column) 27 | }) 28 | 29 | return { 30 | descriptions, 31 | label, 32 | content, 33 | span, 34 | labelWidth, 35 | contentWidth, 36 | } 37 | }, 38 | render() { 39 | switch (this.type) { 40 | case 'label': 41 | return h(this.tag, { 42 | class: ['bin-desc__label', { 'is-bordered-label': this.descriptions.border }], 43 | style: { width: `${this.labelWidth}%` }, 44 | colSpan: 1, 45 | }, this.label) 46 | case 'content': 47 | return h(this.tag, { 48 | class: 'bin-desc__content', 49 | style: { width: `${this.span * this.contentWidth}%` }, 50 | colSpan: this.span * 2 - 1, 51 | }, this.content) 52 | default: 53 | return h('td', { 54 | colSpan: this.span, 55 | style: { width: `${this.span * ((100 / this.descriptions.column))}%` }, 56 | }, [ 57 | h('span', { class: 'bin-desc__label' }, this.label), 58 | h('span', { class: 'bin-desc__content' }, this.content)]) 59 | } 60 | }, 61 | } 62 | -------------------------------------------------------------------------------- /src/components/desc/descriptions-row.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 34 | -------------------------------------------------------------------------------- /src/components/desc/index.js: -------------------------------------------------------------------------------- 1 | import Desc from './desc.vue' 2 | 3 | Desc.install = (app) => { 4 | app.component(Desc.name, Desc) 5 | } 6 | 7 | export default Desc 8 | -------------------------------------------------------------------------------- /src/components/divider/divider.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 42 | -------------------------------------------------------------------------------- /src/components/divider/index.js: -------------------------------------------------------------------------------- 1 | import Divider from './divider.vue' 2 | 3 | Divider.install = (app) => { 4 | app.component(Divider.name, Divider) 5 | } 6 | 7 | export default Divider 8 | -------------------------------------------------------------------------------- /src/components/drawer/index.js: -------------------------------------------------------------------------------- 1 | import Drawer from './drawer.vue' 2 | 3 | Drawer.install = (app) => { 4 | app.component(Drawer.name, Drawer) 5 | } 6 | 7 | export default Drawer 8 | -------------------------------------------------------------------------------- /src/components/dropdown-item/index.js: -------------------------------------------------------------------------------- 1 | import DropdownItem from '../dropdown/dropdown-item.vue' 2 | 3 | DropdownItem.install = (app) => { 4 | app.component(DropdownItem.name, DropdownItem) 5 | } 6 | 7 | export default DropdownItem 8 | -------------------------------------------------------------------------------- /src/components/dropdown-menu/index.js: -------------------------------------------------------------------------------- 1 | import DropdownMenu from '../dropdown/dropdown-menu.vue' 2 | 3 | DropdownMenu.install = (app) => { 4 | app.component(DropdownMenu.name, DropdownMenu) 5 | } 6 | 7 | export default DropdownMenu 8 | -------------------------------------------------------------------------------- /src/components/dropdown/dropdown-item.vue: -------------------------------------------------------------------------------- 1 | 17 | 51 | -------------------------------------------------------------------------------- /src/components/dropdown/dropdown-menu.vue: -------------------------------------------------------------------------------- 1 | 11 | 49 | 50 | -------------------------------------------------------------------------------- /src/components/dropdown/index.js: -------------------------------------------------------------------------------- 1 | import Dropdown from './dropdown.vue' 2 | 3 | Dropdown.install = (app) => { 4 | app.component(Dropdown.name, Dropdown) 5 | } 6 | 7 | export default Dropdown 8 | -------------------------------------------------------------------------------- /src/components/empty/empty.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 47 | -------------------------------------------------------------------------------- /src/components/empty/index.js: -------------------------------------------------------------------------------- 1 | import Empty from './empty.vue' 2 | 3 | Empty.install = (app) => { 4 | app.component(Empty.name, Empty) 5 | } 6 | 7 | export default Empty 8 | -------------------------------------------------------------------------------- /src/components/form-item/index.js: -------------------------------------------------------------------------------- 1 | import FormItem from '../form/form-item.vue' 2 | 3 | FormItem.install = (app) => { 4 | app.component(FormItem.name, FormItem) 5 | } 6 | 7 | export default FormItem 8 | -------------------------------------------------------------------------------- /src/components/form/index.js: -------------------------------------------------------------------------------- 1 | import Form from './form.vue' 2 | 3 | Form.install = (app) => { 4 | app.component(Form.name, Form) 5 | } 6 | 7 | export default Form 8 | 9 | export * from './token' 10 | -------------------------------------------------------------------------------- /src/components/form/token.js: -------------------------------------------------------------------------------- 1 | export const FormKey = 'BForm' 2 | 3 | export const FormItemKey = 'BFormItem' 4 | 5 | export const FormEvents = { 6 | addField: 'form.addField', 7 | removeField: 'form.removeField', 8 | blur: 'form.blur', 9 | change: 'form.change', 10 | } 11 | -------------------------------------------------------------------------------- /src/components/icon-select/index.js: -------------------------------------------------------------------------------- 1 | import IconSelect from './icon-select' 2 | 3 | IconSelect.install = (app) => { 4 | app.component(IconSelect.name, IconSelect) 5 | } 6 | 7 | export default IconSelect 8 | -------------------------------------------------------------------------------- /src/components/icon/icon.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 42 | -------------------------------------------------------------------------------- /src/components/icon/index.js: -------------------------------------------------------------------------------- 1 | import Icon from './icon.vue' 2 | 3 | Icon.install = (app) => { 4 | app.component(Icon.name, Icon) 5 | } 6 | 7 | export default Icon 8 | -------------------------------------------------------------------------------- /src/components/input-number/index.js: -------------------------------------------------------------------------------- 1 | import InputNumber from './input-number.vue' 2 | 3 | InputNumber.install = (app) => { 4 | app.component(InputNumber.name, InputNumber) 5 | } 6 | 7 | export default InputNumber 8 | -------------------------------------------------------------------------------- /src/components/input/index.js: -------------------------------------------------------------------------------- 1 | import Input from './input.vue' 2 | 3 | Input.install = (app) => { 4 | app.component(Input.name, Input) 5 | } 6 | 7 | export default Input 8 | -------------------------------------------------------------------------------- /src/components/layout/Layout.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 66 | -------------------------------------------------------------------------------- /src/components/layout/index.js: -------------------------------------------------------------------------------- 1 | import Layout from './Layout.vue' 2 | 3 | Layout.install = app => { 4 | app.component(Layout.name, Layout) 5 | } 6 | 7 | export default Layout 8 | -------------------------------------------------------------------------------- /src/components/loading-bar/instance.js: -------------------------------------------------------------------------------- 1 | import LoadingBar from './loading-bar.vue' 2 | import { createApp } from 'vue' 3 | 4 | export default function getInstance(properties) { 5 | const _props = properties || {} 6 | const app = createApp(LoadingBar, _props) 7 | const loadingBar = app.mount(document.createElement('div')) 8 | document.body.appendChild(loadingBar.$el) 9 | return { 10 | update(options) { 11 | if ('percent' in options) { 12 | loadingBar.percent = options.percent 13 | } 14 | if (options.status) { 15 | loadingBar.status = options.status 16 | } 17 | if ('show' in options) { 18 | loadingBar.show = options.show 19 | } 20 | if ('icon' in options) { 21 | loadingBar.icon = options.icon 22 | } 23 | }, 24 | component: loadingBar, 25 | destroy() { 26 | document.body.removeChild(document.getElementsByClassName('bin-loading-bar')[0]) 27 | }, 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/components/loading/index.js: -------------------------------------------------------------------------------- 1 | import Loading from './loading.vue' 2 | 3 | Loading.install = (app) => { 4 | app.component(Loading.name, Loading) 5 | } 6 | 7 | export default Loading 8 | -------------------------------------------------------------------------------- /src/components/loading/loading.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 62 | -------------------------------------------------------------------------------- /src/components/menu-item-group/index.js: -------------------------------------------------------------------------------- 1 | import MenuItemGroup from '../menu/menu-item-group.vue' 2 | 3 | MenuItemGroup.install = (app) => { 4 | app.component(MenuItemGroup.name, MenuItemGroup) 5 | } 6 | 7 | export default MenuItemGroup 8 | 9 | -------------------------------------------------------------------------------- /src/components/menu-item/index.js: -------------------------------------------------------------------------------- 1 | import MenuItem from '../menu/menu-item.vue' 2 | 3 | MenuItem.install = (app) => { 4 | app.component(MenuItem.name, MenuItem) 5 | } 6 | 7 | export default MenuItem 8 | 9 | -------------------------------------------------------------------------------- /src/components/menu/index.js: -------------------------------------------------------------------------------- 1 | import Menu from './menu.vue' 2 | 3 | Menu.install = (app) => { 4 | app.component(Menu.name, Menu) 5 | } 6 | 7 | export default Menu 8 | 9 | -------------------------------------------------------------------------------- /src/components/menu/menu-item-group.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 63 | -------------------------------------------------------------------------------- /src/components/menu/useMenu.js: -------------------------------------------------------------------------------- 1 | import { computed, inject } from 'vue' 2 | 3 | export default function useMenu(instance, currentIndex) { 4 | const rootMenu = inject('rootMenu') 5 | 6 | const indexPath = computed(() => { 7 | let parent = instance.parent 8 | const path = [currentIndex] 9 | while (parent.type.name !== 'BMenu') { 10 | if (parent.props.index) { 11 | path.unshift(parent.props.index) 12 | } 13 | parent = parent.parent 14 | } 15 | return path 16 | }) 17 | 18 | const parentMenu = computed(() => { 19 | let parent = instance.parent 20 | while (parent && ['BMenu', 'BSubmenu'].indexOf(parent.type.name) === -1) { 21 | parent = parent.parent 22 | } 23 | return parent 24 | }) 25 | const paddingStyle = computed(() => { 26 | let parent = instance.parent 27 | if (rootMenu.props.mode !== 'vertical') return {} 28 | 29 | let padding = 20 30 | 31 | if (rootMenu.props.collapse) { 32 | padding = 20 33 | } else { 34 | while (parent && parent.type.name !== 'BMenu') { 35 | if (parent.type.name === 'BSubmenu') { 36 | padding += 20 37 | } 38 | parent = parent.parent 39 | } 40 | } 41 | return { paddingLeft: padding + 'px' } 42 | }) 43 | return { parentMenu, paddingStyle, indexPath } 44 | } 45 | -------------------------------------------------------------------------------- /src/components/menu/useMenuColor.js: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | 3 | export default function useMenuColor(color = '') { 4 | const menuBarColor = ref('') 5 | function calcColorChannels(c) { 6 | let rawColor = c.replace('#', '') 7 | if (/^[0-9a-fA-F]{3}$/.test(rawColor)) { 8 | const color = rawColor.split('') 9 | for (let i = 2; i >= 0; i--) { 10 | color.splice(i, 0, color[i]) 11 | } 12 | rawColor = color.join('') 13 | } 14 | if (/^[0-9a-fA-F]{6}$/.test(rawColor)) { 15 | return { 16 | red: parseInt(rawColor.slice(0, 2), 16), 17 | green: parseInt(rawColor.slice(2, 4), 16), 18 | blue: parseInt(rawColor.slice(4, 6), 16), 19 | } 20 | } else { 21 | return { 22 | red: 255, 23 | green: 255, 24 | blue: 255, 25 | } 26 | } 27 | } 28 | function mixColor(color, percent = 0.2) { 29 | let { red, green, blue } = calcColorChannels(color) 30 | if (percent > 0) { 31 | // shade given color 32 | red *= 1 - percent 33 | green *= 1 - percent 34 | blue *= 1 - percent 35 | } else { 36 | // tint given color 37 | red += (255 - red) * percent 38 | green += (255 - green) * percent 39 | blue += (255 - blue) * percent 40 | } 41 | return `rgb(${Math.round(red)}, ${Math.round(green)}, ${Math.round(blue)})` 42 | } 43 | if (!color) { 44 | return menuBarColor 45 | } 46 | menuBarColor.value = mixColor(color) 47 | return menuBarColor 48 | } 49 | -------------------------------------------------------------------------------- /src/components/menu/util/menu-bar.js: -------------------------------------------------------------------------------- 1 | import MenuItem from './menu-item' 2 | 3 | class Menu { 4 | constructor(domNode) { 5 | this.domNode = domNode 6 | this.init() 7 | } 8 | 9 | init() { 10 | const menuChildren = this.domNode.childNodes 11 | ;[].filter 12 | .call(menuChildren, (child) => child.nodeType === 1) 13 | .forEach((child) => { 14 | new MenuItem(child) 15 | }) 16 | } 17 | } 18 | 19 | export default Menu 20 | -------------------------------------------------------------------------------- /src/components/menu/util/menu-item.js: -------------------------------------------------------------------------------- 1 | import { EVENT_CODE, triggerEvent } from '../../../utils/aria' 2 | import SubMenu from './submenu' 3 | 4 | class MenuItem { 5 | constructor(domNode) { 6 | this.domNode = domNode 7 | this.submenu = null 8 | this.init() 9 | } 10 | 11 | init() { 12 | this.domNode.setAttribute('tabindex', '0') 13 | const menuChild = this.domNode.querySelector('.bin-menu') 14 | if (menuChild) { 15 | this.submenu = new SubMenu(this, menuChild) 16 | } 17 | this.addListeners() 18 | } 19 | 20 | addListeners() { 21 | this.domNode.addEventListener('keydown', (event) => { 22 | let prevDef = false 23 | switch (event.code) { 24 | case EVENT_CODE.down: { 25 | triggerEvent(event.currentTarget, 'mouseenter') 26 | this.submenu && this.submenu.gotoSubIndex(0) 27 | prevDef = true 28 | break 29 | } 30 | case EVENT_CODE.up: { 31 | triggerEvent(event.currentTarget, 'mouseenter') 32 | this.submenu && 33 | this.submenu.gotoSubIndex(this.submenu.subMenuItems.length - 1) 34 | prevDef = true 35 | break 36 | } 37 | case EVENT_CODE.tab: { 38 | triggerEvent(event.currentTarget, 'mouseleave') 39 | break 40 | } 41 | case EVENT_CODE.enter: 42 | case EVENT_CODE.space: { 43 | prevDef = true 44 | ;(event.currentTarget).click() 45 | break 46 | } 47 | } 48 | if (prevDef) { 49 | event.preventDefault() 50 | } 51 | }) 52 | } 53 | } 54 | 55 | export default MenuItem 56 | -------------------------------------------------------------------------------- /src/components/menu/util/submenu.js: -------------------------------------------------------------------------------- 1 | import { EVENT_CODE, triggerEvent } from '../../../utils/aria' 2 | 3 | class SubMenu { 4 | constructor(parent, domNode) { 5 | this.subIndex = 0 6 | this.parent = parent 7 | this.domNode = domNode 8 | this.subMenuItems = [] 9 | this.init() 10 | } 11 | 12 | init() { 13 | this.subMenuItems = this.domNode.querySelectorAll('li') 14 | this.addListeners() 15 | } 16 | 17 | gotoSubIndex(idx) { 18 | if (idx === this.subMenuItems.length) { 19 | idx = 0 20 | } else if (idx < 0) { 21 | idx = this.subMenuItems.length - 1 22 | } 23 | this.subMenuItems[idx].focus() 24 | this.subIndex = idx 25 | } 26 | 27 | addListeners() { 28 | const parentNode = this.parent.domNode 29 | Array.prototype.forEach.call(this.subMenuItems, (el) => { 30 | el.addEventListener('keydown', (event) => { 31 | let prevDef = false 32 | switch (event.code) { 33 | case EVENT_CODE.down: { 34 | this.gotoSubIndex(this.subIndex + 1) 35 | prevDef = true 36 | break 37 | } 38 | case EVENT_CODE.up: { 39 | this.gotoSubIndex(this.subIndex - 1) 40 | prevDef = true 41 | break 42 | } 43 | case EVENT_CODE.tab: { 44 | triggerEvent(parentNode, 'mouseleave') 45 | break 46 | } 47 | case EVENT_CODE.enter: 48 | case EVENT_CODE.space: { 49 | prevDef = true 50 | event.currentTarget.click() 51 | break 52 | } 53 | } 54 | if (prevDef) { 55 | event.preventDefault() 56 | event.stopPropagation() 57 | } 58 | return false 59 | }) 60 | }) 61 | } 62 | } 63 | 64 | export default SubMenu 65 | -------------------------------------------------------------------------------- /src/components/message-box/index.js: -------------------------------------------------------------------------------- 1 | import MessageBox from './instance' 2 | 3 | MessageBox.install = (app) => { 4 | app.config.globalProperties.$messageBox = MessageBox 5 | app.config.globalProperties.$alert = MessageBox.alert 6 | app.config.globalProperties.$confirm = MessageBox.confirm 7 | } 8 | 9 | export default MessageBox 10 | -------------------------------------------------------------------------------- /src/components/message/index.js: -------------------------------------------------------------------------------- 1 | import Message from './instance' 2 | 3 | Message.install = (app) => { 4 | app.config.globalProperties.$message = Message 5 | } 6 | 7 | export default Message 8 | -------------------------------------------------------------------------------- /src/components/modal/addListener.js: -------------------------------------------------------------------------------- 1 | let supportsPassive = false 2 | try { 3 | const opts = Object.defineProperty({}, 'passive', { 4 | // eslint-disable-next-line getter-return 5 | get() { 6 | supportsPassive = true 7 | }, 8 | }) 9 | window.addEventListener('testPassive', null, opts) 10 | window.removeEventListener('testPassive', null, opts) 11 | // eslint-disable-next-line no-empty 12 | } catch (e) { 13 | } 14 | 15 | export function addEventListenerWrap(target, eventType, cb, option) { 16 | if (target.addEventListener) { 17 | let opt = option 18 | if ( 19 | opt === undefined && 20 | supportsPassive && 21 | (eventType === 'touchstart' || eventType === 'touchmove' || eventType === 'wheel') 22 | ) { 23 | opt = { passive: false } 24 | } 25 | target.addEventListener(eventType, cb, opt) 26 | } 27 | return { 28 | remove: () => { 29 | if (target.removeEventListener) { 30 | target.removeEventListener(eventType, cb) 31 | } 32 | }, 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/components/modal/index.js: -------------------------------------------------------------------------------- 1 | import Modal from './modal.vue' 2 | 3 | Modal.install = (app) => { 4 | app.component(Modal.name, Modal) 5 | } 6 | 7 | export default Modal 8 | export { default as useModal } from './useModal' 9 | -------------------------------------------------------------------------------- /src/components/modal/mask.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 60 | -------------------------------------------------------------------------------- /src/components/move-transition/index.js: -------------------------------------------------------------------------------- 1 | import MoveTransition from './move-transition' 2 | 3 | MoveTransition.install = (app) => { 4 | app.component(MoveTransition.name, MoveTransition) 5 | } 6 | 7 | export default MoveTransition 8 | -------------------------------------------------------------------------------- /src/components/move-transition/move-transition.js: -------------------------------------------------------------------------------- 1 | import { h, Transition, TransitionGroup } from 'vue' 2 | 3 | export default { 4 | name: 'BMoveTransition', 5 | functional: true, 6 | props: { 7 | name: { 8 | type: String, 9 | default: 'fade-transverse', 10 | }, 11 | group: { 12 | type: Boolean, 13 | default: false, 14 | }, 15 | }, 16 | setup(props, { slots }) { 17 | return () => { 18 | const config = { 19 | name: props.name, 20 | appear: true, 21 | onBeforeLeave(el) { 22 | el.style.position = 'absolute' 23 | el.style.top = '0' 24 | el.style.left = '0' 25 | el.style.width = '100%' 26 | el.style.height = '100%' 27 | el.style.overflow = 'hidden' 28 | }, 29 | onAfterLeave(el) { 30 | el.style = '' 31 | }, 32 | } 33 | if (props.group) { 34 | return h(TransitionGroup, config, slots.default) 35 | } 36 | return h(Transition, config, slots.default) 37 | } 38 | }, 39 | } 40 | -------------------------------------------------------------------------------- /src/components/notice/index.js: -------------------------------------------------------------------------------- 1 | import Notice from './instance' 2 | 3 | Notice.install = (app) => { 4 | app.config.globalProperties.$notice = Notice 5 | } 6 | 7 | export default Notice 8 | -------------------------------------------------------------------------------- /src/components/option-group/index.js: -------------------------------------------------------------------------------- 1 | import OptionGroup from '../select/option-group.vue' 2 | 3 | OptionGroup.install = (app) => { 4 | app.component(OptionGroup.name, OptionGroup) 5 | } 6 | 7 | export default OptionGroup 8 | -------------------------------------------------------------------------------- /src/components/option/index.js: -------------------------------------------------------------------------------- 1 | import { Option } from '../select' 2 | 3 | Option.install = app => { 4 | app.component(Option.name, Option) 5 | } 6 | 7 | export default Option 8 | -------------------------------------------------------------------------------- /src/components/page/index.js: -------------------------------------------------------------------------------- 1 | import Page from './page.vue' 2 | 3 | Page.install = (app) => { 4 | app.component(Page.name, Page) 5 | } 6 | 7 | export default Page 8 | -------------------------------------------------------------------------------- /src/components/popover/index.js: -------------------------------------------------------------------------------- 1 | import Popover from './popover' 2 | 3 | Popover.install = (app) => { 4 | app.component(Popover.name, Popover) 5 | } 6 | 7 | export default Popover 8 | -------------------------------------------------------------------------------- /src/components/popover/usePopover.js: -------------------------------------------------------------------------------- 1 | import { computed, watch } from 'vue' 2 | import { isString } from '@vue/shared' 3 | import { usePopper } from '../popper' 4 | 5 | export const SHOW_EVENT = 'show' 6 | export const HIDE_EVENT = 'hide' 7 | 8 | export default function usePopover(props, ctx) { 9 | const popperProps = usePopper(props, ctx) 10 | 11 | const popperStyle = computed(() => { 12 | let _width 13 | 14 | if (isString(props.width)) { 15 | _width = props.width 16 | } else { 17 | _width = props.width + 'px' 18 | } 19 | 20 | return { 21 | width: _width, 22 | zIndex: popperProps.popperStyle.value.zIndex, 23 | } 24 | }) 25 | 26 | watch(popperProps.visibility, val => { 27 | ctx.emit(val ? SHOW_EVENT : HIDE_EVENT) 28 | }) 29 | 30 | return { 31 | ...popperProps, 32 | popperStyle, 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/components/popper/index.js: -------------------------------------------------------------------------------- 1 | import Popper from './src/index.vue' 2 | 3 | Popper.install = (app) => { 4 | app.component(Popper.name, Popper) 5 | } 6 | 7 | export default Popper 8 | export const BPopper = Popper 9 | 10 | export { default as defaultProps, Theme } from './src/use-popper/defaults' 11 | export { default as usePopper } from './src/use-popper' 12 | export * from './src/renderers' 13 | -------------------------------------------------------------------------------- /src/components/popper/src/renderers/arrow.js: -------------------------------------------------------------------------------- 1 | import { Comment, h } from 'vue' 2 | 3 | export default function renderArrow(showArrow) { 4 | return showArrow 5 | ? h( 6 | 'div', 7 | { 8 | ref: 'arrowRef', 9 | class: 'bin-popper__arrow', 10 | 'data-popper-arrow': '', 11 | }, 12 | null, 13 | ) 14 | : h(Comment, null, '') 15 | } 16 | -------------------------------------------------------------------------------- /src/components/popper/src/renderers/index.js: -------------------------------------------------------------------------------- 1 | export { default as renderPopper } from './popper' 2 | export { default as renderTrigger } from './trigger' 3 | export { default as renderArrow } from './arrow' 4 | -------------------------------------------------------------------------------- /src/components/popper/src/renderers/popper.js: -------------------------------------------------------------------------------- 1 | import { withDirectives, Transition, vShow, withCtx, h } from 'vue' 2 | import { NOOP } from '@vue/shared' 3 | import { stop } from '../../../../utils/dom' 4 | 5 | export default function renderPopper(props, children) { 6 | const { 7 | theme, 8 | name, 9 | stopPopperMouseEvent, 10 | popperClass, 11 | popperStyle, 12 | popperRef, 13 | pure, 14 | popperId, 15 | visibility, 16 | onMouseEnter, 17 | onMouseLeave, 18 | onAfterEnter, 19 | onAfterLeave, 20 | onBeforeEnter, 21 | onBeforeLeave, 22 | } = props 23 | 24 | const kls = [popperClass, 'bin-popper', 'is-' + theme, pure ? 'is-pure' : ''] 25 | /** 26 | * Equivalent to 27 | * 28 | *
37 | * 38 | *
39 | *
40 | */ 41 | 42 | const mouseUpAndDown = stopPopperMouseEvent ? stop : NOOP 43 | return h( 44 | Transition, 45 | { 46 | name, 47 | 'onAfterEnter': onAfterEnter, 48 | 'onAfterLeave': onAfterLeave, 49 | 'onBeforeEnter': onBeforeEnter, 50 | 'onBeforeLeave': onBeforeLeave, 51 | }, 52 | { 53 | default: withCtx(() => [withDirectives( 54 | h( 55 | 'div', 56 | { 57 | 'aria-hidden': String(!visibility), 58 | class: kls, 59 | style: popperStyle ?? {}, 60 | id: popperId, 61 | ref: popperRef ?? 'popperRef', 62 | role: 'tooltip', 63 | onMouseenter: onMouseEnter, 64 | onMouseleave: onMouseLeave, 65 | onClick: stop, 66 | onMousedown: mouseUpAndDown, 67 | onMouseup: mouseUpAndDown, 68 | }, 69 | children, 70 | ), 71 | [[vShow, visibility]], 72 | )]), 73 | }, 74 | ) 75 | } 76 | -------------------------------------------------------------------------------- /src/components/popper/src/renderers/trigger.js: -------------------------------------------------------------------------------- 1 | import { cloneVNode } from 'vue' 2 | import { getFirstValidNode } from '../../../../utils/vnode' 3 | import { throwError } from '../../../../utils/log' 4 | 5 | export default function renderTrigger(trigger, extraProps) { 6 | const firstElement = getFirstValidNode(trigger, 1) 7 | if (!firstElement) { 8 | throwError('renderTrigger', 'trigger expects single rooted node') 9 | } 10 | return cloneVNode(firstElement, extraProps, true) 11 | } 12 | -------------------------------------------------------------------------------- /src/components/popper/src/use-popper/build-modifiers.js: -------------------------------------------------------------------------------- 1 | export default function buildModifier(props, externalModifiers = []) { 2 | const { arrow, arrowOffset, offset, gpuAcceleration } = props 3 | 4 | const modifiers = [ 5 | { 6 | name: 'offset', 7 | options: { 8 | offset: [0, offset ?? 12], 9 | }, 10 | }, 11 | { 12 | name: 'preventOverflow', 13 | options: { 14 | padding: { 15 | top: 2, 16 | bottom: 2, 17 | left: 5, 18 | right: 5, 19 | }, 20 | }, 21 | }, 22 | { 23 | name: 'flip', 24 | options: { 25 | padding: 5, 26 | }, 27 | }, 28 | { 29 | name: 'computeStyles', 30 | options: { 31 | gpuAcceleration, 32 | adaptive: gpuAcceleration, 33 | }, 34 | }, 35 | // tippyModifier, 36 | ] 37 | 38 | if (arrow) { 39 | modifiers.push({ 40 | name: 'arrow', 41 | options: { 42 | element: arrow, 43 | // the arrow size is an equailateral triangle with 10px side length, the 3rd side length ~ 14.1px 44 | // adding a offset to the ceil of 4.1 should be 4 this resolves the problem of arrow overflowing out of popper. 45 | padding: arrowOffset ?? 4, 46 | }, 47 | }) 48 | } 49 | 50 | modifiers.push(...externalModifiers) 51 | return modifiers 52 | } 53 | -------------------------------------------------------------------------------- /src/components/popper/src/use-popper/popper-options.js: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue' 2 | import buildModifiers from './build-modifiers' 3 | 4 | export default function usePopperOptions(props, state) { 5 | return computed(() => { 6 | return { 7 | placement: props.placement, 8 | ...props.popperOptions, 9 | // Avoiding overriding modifiers. 10 | modifiers: buildModifiers({ 11 | arrow: state.arrow.value, 12 | arrowOffset: props.arrowOffset, 13 | offset: props.offset, 14 | gpuAcceleration: props.gpuAcceleration, 15 | fallbackPlacements: props.fallbackPlacements, 16 | }, props.popperOptions?.modifiers), 17 | } 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /src/components/progress/index.js: -------------------------------------------------------------------------------- 1 | import Progress from './progress.vue' 2 | 3 | Progress.install = (app) => { 4 | app.component(Progress.name, Progress) 5 | } 6 | 7 | export default Progress 8 | -------------------------------------------------------------------------------- /src/components/radio-group/index.js: -------------------------------------------------------------------------------- 1 | import RadioGroup from '../radio/radio-group.vue' 2 | 3 | RadioGroup.install = (app) => { 4 | app.component(RadioGroup.name, RadioGroup) 5 | } 6 | 7 | export default RadioGroup 8 | -------------------------------------------------------------------------------- /src/components/radio/index.js: -------------------------------------------------------------------------------- 1 | import Radio from './radio.vue' 2 | 3 | Radio.install = (app) => { 4 | app.component(Radio.name, Radio) 5 | } 6 | 7 | export default Radio 8 | -------------------------------------------------------------------------------- /src/components/radio/useRadio.js: -------------------------------------------------------------------------------- 1 | import { ref, computed, inject } from 'vue' 2 | import useForm from '../../hooks/useForm' 3 | 4 | export const useRadio = () => { 5 | const { BForm, BFormItem, formEmit } = useForm() 6 | const radioGroup = inject('RadioGroup', {}) 7 | const focus = ref(false) 8 | const isGroup = computed(() => radioGroup?.name === 'BRadioGroup') 9 | const isBtnGroup = computed(() => isGroup.value && radioGroup?.type === 'button') 10 | 11 | return { 12 | isGroup, 13 | focus, 14 | radioGroup, 15 | isBtnGroup, 16 | BForm, BFormItem, formEmit, 17 | } 18 | } 19 | 20 | export const useRadioAttrs = (props, { isGroup, radioGroup, BForm, model }) => { 21 | const isDisabled = computed(() => { 22 | return isGroup.value 23 | ? radioGroup.disabled || props.disabled || BForm.disabled 24 | : props.disabled || BForm.disabled 25 | }) 26 | 27 | const tabIndex = computed(() => { 28 | return (isDisabled.value || (isGroup.value && model.value !== props.label)) ? -1 : 0 29 | }) 30 | 31 | return { 32 | isDisabled, 33 | tabIndex, 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/components/rate/index.js: -------------------------------------------------------------------------------- 1 | import Rate from './rate.vue' 2 | 3 | Rate.install = (app) => { 4 | app.component(Rate.name, Rate) 5 | } 6 | 7 | export default Rate 8 | -------------------------------------------------------------------------------- /src/components/row/index.js: -------------------------------------------------------------------------------- 1 | import Row from './row.vue' 2 | 3 | Row.install = (app) => { 4 | app.component(Row.name, Row) 5 | } 6 | 7 | export default Row 8 | -------------------------------------------------------------------------------- /src/components/row/row.vue: -------------------------------------------------------------------------------- 1 | 6 | 68 | -------------------------------------------------------------------------------- /src/components/scrollbar/index.js: -------------------------------------------------------------------------------- 1 | import Scrollbar from './scrollbar.vue' 2 | 3 | Scrollbar.install = (app) => { 4 | app.component(Scrollbar.name, Scrollbar) 5 | } 6 | 7 | export default Scrollbar 8 | -------------------------------------------------------------------------------- /src/components/scrollbar/util.js: -------------------------------------------------------------------------------- 1 | export const BAR_MAP = { 2 | vertical: { 3 | offset: 'offsetHeight', 4 | scroll: 'scrollTop', 5 | scrollSize: 'scrollHeight', 6 | size: 'height', 7 | key: 'vertical', 8 | axis: 'Y', 9 | client: 'clientY', 10 | direction: 'top', 11 | }, 12 | horizontal: { 13 | offset: 'offsetWidth', 14 | scroll: 'scrollLeft', 15 | scrollSize: 'scrollWidth', 16 | size: 'width', 17 | key: 'horizontal', 18 | axis: 'X', 19 | client: 'clientX', 20 | direction: 'left', 21 | }, 22 | } 23 | 24 | export function renderThumbStyle({ move, size, bar }) { 25 | const style = {} 26 | const translate = `translate${bar.axis}(${move}%)` 27 | 28 | style[bar.size] = size 29 | style.transform = translate 30 | style.msTransform = translate 31 | style.webkitTransform = translate 32 | 33 | return style 34 | } 35 | 36 | // 数组转换成对象 37 | export function toObject(arr) { 38 | const res = {} 39 | for (let i = 0; i < arr.length; i++) { 40 | if (arr[i]) { 41 | extend(res, arr[i]) 42 | } 43 | } 44 | return res 45 | } 46 | 47 | function extend(to, _from) { 48 | for (const key in _from) { 49 | to[key] = _from[key] 50 | } 51 | return to 52 | } 53 | -------------------------------------------------------------------------------- /src/components/select/index.js: -------------------------------------------------------------------------------- 1 | import Select from './select.vue' 2 | import Option from './option.vue' 3 | 4 | Select.install = (app) => { 5 | app.component(Select.name, Select) 6 | } 7 | 8 | export { Option } 9 | export default Select 10 | -------------------------------------------------------------------------------- /src/components/select/option-group.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 47 | -------------------------------------------------------------------------------- /src/components/select/select-dropdown.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 49 | -------------------------------------------------------------------------------- /src/components/select/token.js: -------------------------------------------------------------------------------- 1 | // For individual build sharing injection key, we had to make `Symbol` to string 2 | export const selectGroupKey = 'SelectGroup' 3 | 4 | export const selectKey = 'Select' 5 | 6 | export const selectEvents = { 7 | queryChange: 'OptionQueryChange', 8 | groupQueryChange: 'OptionGroupQueryChange', 9 | } 10 | -------------------------------------------------------------------------------- /src/components/skeleton-item/img-placeholder.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 17 | -------------------------------------------------------------------------------- /src/components/skeleton-item/index.js: -------------------------------------------------------------------------------- 1 | import SkeletonItem from './item.vue' 2 | 3 | SkeletonItem.install = (app) => { 4 | app.component(SkeletonItem.name, SkeletonItem) 5 | } 6 | 7 | export default SkeletonItem 8 | -------------------------------------------------------------------------------- /src/components/skeleton-item/item.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 21 | -------------------------------------------------------------------------------- /src/components/skeleton/index.js: -------------------------------------------------------------------------------- 1 | import Skeleton from './skeleton.vue' 2 | 3 | Skeleton.install = (app) => { 4 | app.component(Skeleton.name, Skeleton) 5 | } 6 | 7 | export default Skeleton 8 | -------------------------------------------------------------------------------- /src/components/skeleton/skeleton.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 65 | -------------------------------------------------------------------------------- /src/components/skeleton/use-throttle.js: -------------------------------------------------------------------------------- 1 | import { onMounted, ref, watch } from 'vue' 2 | 3 | export default function(loading, throttle = 0) { 4 | if (throttle === 0) return loading 5 | const throttled = ref(false) 6 | let timeoutHandle = 0 7 | 8 | const dispatchThrottling = () => { 9 | if (timeoutHandle) { 10 | clearTimeout(timeoutHandle) 11 | } 12 | timeoutHandle = window.setTimeout(() => { 13 | throttled.value = loading.value 14 | }, throttle) 15 | } 16 | onMounted(dispatchThrottling) 17 | 18 | watch(() => loading.value, val => { 19 | if (val) { 20 | dispatchThrottling() 21 | } else { 22 | throttled.value = val 23 | } 24 | }) 25 | return throttled 26 | } 27 | -------------------------------------------------------------------------------- /src/components/slider/index.js: -------------------------------------------------------------------------------- 1 | import Slider from './src/index.vue' 2 | 3 | /* istanbul ignore next */ 4 | Slider.install = function(Vue) { 5 | Vue.component(Slider.name, Slider) 6 | } 7 | 8 | export default Slider 9 | -------------------------------------------------------------------------------- /src/components/slider/src/marker.vue: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /src/components/slider/src/useMarks.js: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue' 2 | 3 | export const useMarks = (props) => { 4 | return computed(() => { 5 | if (!props.marks) { 6 | return [] 7 | } 8 | 9 | const marksKeys = Object.keys(props.marks) 10 | return marksKeys.map(parseFloat) 11 | .sort((a, b) => a - b) 12 | .filter(point => point <= props.max && point >= props.min) 13 | .map((point) => ({ 14 | point, 15 | position: (point - props.min) * 100 / (props.max - props.min), 16 | mark: props.marks[point], 17 | })) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /src/components/slider/src/useStops.js: -------------------------------------------------------------------------------- 1 | import { computed } from 'vue' 2 | 3 | export const useStops = (props, initData, minValue, maxValue) => { 4 | const stops = computed(() => { 5 | if (!props.showStops || props.min > props.max) return [] 6 | if (props.step === 0) { 7 | process.env.NODE_ENV !== 'production' && console.warn('[Element Warn][Slider]step should not be 0.') 8 | return [] 9 | } 10 | 11 | const stopCount = (props.max - props.min) / props.step 12 | const stepWidth = 100 * props.step / (props.max - props.min) 13 | const result = Array.from({ length: stopCount - 1 }).map((_, index) => ((index + 1) * stepWidth)) 14 | 15 | if (props.range) { 16 | return result.filter(step => { 17 | return step < 100 * (minValue.value - props.min) / (props.max - props.min) 18 | || step > 100 * (maxValue.value - props.min) / (props.max - props.min) 19 | }) 20 | } else { 21 | return result.filter(step => step > 100 * (initData.firstValue - props.min) / (props.max - props.min)) 22 | } 23 | }) 24 | 25 | const getStopStyle = (position) => { 26 | return (props.vertical ? { 'bottom': position + '%' } : { 'left': position + '%' }) 27 | } 28 | 29 | return { 30 | stops, 31 | getStopStyle, 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/components/space/item.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 25 | -------------------------------------------------------------------------------- /src/components/split/index.js: -------------------------------------------------------------------------------- 1 | import Split from './split.vue' 2 | 3 | Split.install = (app) => { 4 | app.component(Split.name, Split) 5 | } 6 | 7 | export default Split 8 | -------------------------------------------------------------------------------- /src/components/split/pane.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 22 | -------------------------------------------------------------------------------- /src/components/split/resizer.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 19 | -------------------------------------------------------------------------------- /src/components/step/index.js: -------------------------------------------------------------------------------- 1 | import Step from '../steps/step.vue' 2 | 3 | Step.install = (app) => { 4 | app.component(Step.name, Step) 5 | } 6 | 7 | export default Step 8 | -------------------------------------------------------------------------------- /src/components/steps/index.js: -------------------------------------------------------------------------------- 1 | import Steps from './steps.vue' 2 | 3 | Steps.install = (app) => { 4 | app.component(Steps.name, Steps) 5 | } 6 | 7 | export default Steps 8 | -------------------------------------------------------------------------------- /src/components/submenu/index.js: -------------------------------------------------------------------------------- 1 | import Submenu from '../menu/submenu.vue' 2 | 3 | Submenu.install = (app) => { 4 | app.component(Submenu.name, Submenu) 5 | } 6 | 7 | export default Submenu 8 | -------------------------------------------------------------------------------- /src/components/switch/index.js: -------------------------------------------------------------------------------- 1 | import Switch from './switch.vue' 2 | 3 | Switch.install = (app) => { 4 | app.component(Switch.name, Switch) 5 | } 6 | 7 | export default Switch 8 | -------------------------------------------------------------------------------- /src/components/table/index.js: -------------------------------------------------------------------------------- 1 | import Table from './table.vue' 2 | 3 | Table.install = (app) => { 4 | app.component(Table.name, Table) 5 | } 6 | 7 | export default Table 8 | -------------------------------------------------------------------------------- /src/components/table/main/expand.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'TableExpand', 3 | functional: true, 4 | props: { 5 | row: Object, 6 | render: Function, 7 | index: Number, 8 | column: { 9 | type: Object, 10 | default: null, 11 | }, 12 | }, 13 | render: (ctx) => { 14 | const params = { 15 | row: ctx.row, 16 | index: ctx.index, 17 | } 18 | if (ctx.column) params.column = ctx.column 19 | return ctx.render(params) 20 | }, 21 | } 22 | -------------------------------------------------------------------------------- /src/components/table/main/header.js: -------------------------------------------------------------------------------- 1 | import { h } from 'vue' 2 | 3 | export default { 4 | name: 'TableRenderHeader', 5 | functional: true, 6 | props: { 7 | render: Function, 8 | column: Object, 9 | index: Number, 10 | }, 11 | render: (ctx) => { 12 | const params = { 13 | column: ctx.props.column, 14 | index: ctx.props.index, 15 | } 16 | return ctx.props.render(h, params) 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /src/components/table/main/mixin.js: -------------------------------------------------------------------------------- 1 | export function useMixin(props) { 2 | function alignCls(column, row = {}) { 3 | let cellClassName = '' 4 | if (row.cellClassName && column.key && row.cellClassName[column.key]) { 5 | cellClassName = row.cellClassName[column.key] 6 | } 7 | return [ 8 | { 9 | [`${cellClassName}`]: cellClassName, // cell className 10 | [`${column.className}`]: column.className, // column className 11 | [`${props.prefixCls}-column-${column.align}`]: column.align, 12 | [`${props.prefixCls}-hidden`]: (props.fixed === 'left' && column.fixed !== 'left') || 13 | (props.fixed === 'right' && column.fixed !== 'right') || 14 | (!props.fixed && column.fixed && (column.fixed === 'left' || column.fixed === 'right')), 15 | }, 16 | ] 17 | } 18 | 19 | function isPopperShow(column) { 20 | return column.filters && ((!props.fixed && !column.fixed) || (props.fixed === 'left' && column.fixed === 'left') || (props.fixed === 'right' && column.fixed === 'right')) 21 | } 22 | 23 | function setCellWidth(column) { 24 | let width = '' 25 | if (column.width) { 26 | width = column.width 27 | } else if (props.columnsWidth[column._index]) { 28 | width = props.columnsWidth[column._index].width 29 | } 30 | if (width === '0') width = '' 31 | return width 32 | } 33 | 34 | return { 35 | alignCls, 36 | isPopperShow, 37 | setCellWidth 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/components/table/main/slot.js: -------------------------------------------------------------------------------- 1 | import { inject } from 'vue' 2 | 3 | export default { 4 | name: 'TableSlot', 5 | functional: true, 6 | props: { 7 | row: Object, 8 | index: Number, 9 | column: { 10 | type: Object, 11 | default: null, 12 | }, 13 | }, 14 | setup(props) { 15 | const tableRoot = inject('BTable', {}) 16 | const render = tableRoot.slots[props.column.slot] 17 | if (!render) { 18 | throw Error('columns slot should be write