From f35d506b10d7359e003f72675ab62ed6cfe48535 Mon Sep 17 00:00:00 2001 From: wangyaju Date: Wed, 31 Aug 2022 10:50:23 +0800 Subject: [PATCH] chore(release): release 14.0.0 (#259) Co-authored-by: huaweidevcloud --- README.md | 2 +- README_zh_CN.md | 2 +- angular.json | 14 +- .../src/codecopy/codecopy.directive.ts | 2 +- .../src/demo-nav/d-demo-nav.component.html | 2 +- devui-commons/src/devui-commons.scss | 21 +- devui-commons/src/header/header.component.ts | 4 +- .../version-switch.component.scss | 2 +- .../src/sidebar/sidebar.component.scss | 11 +- .../src/sidebar/sidebar.component.ts | 37 ++- .../accordion-item-routerlink.component.ts | 21 +- devui/accordion/accordion-list-token.ts | 3 - devui/accordion/accordion-list.component.html | 3 +- devui/accordion/accordion-list.component.ts | 98 ++++---- devui/accordion/accordion-menu-token.ts | 3 - devui/accordion/accordion-menu.component.html | 2 +- devui/accordion/accordion-menu.component.ts | 71 +++--- devui/accordion/accordion.module.ts | 8 +- devui/accordion/accordion.service.ts | 16 ++ .../accordion/demo/accordion-demo.moudule.ts | 2 +- devui/accordion/ng-package.json | 5 + devui/accordion/package.json | 7 - devui/accordion/public-api.ts | 3 +- devui/alert/demo/alert-demo.module.ts | 2 +- devui/alert/ng-package.json | 5 + devui/alert/package.json | 7 - devui/anchor/anchor-box.directive.ts | 2 +- devui/anchor/demo/anchor-demo.module.ts | 2 +- devui/anchor/ng-package.json | 5 + devui/anchor/package.json | 7 - .../animations/demo/animations-demo.module.ts | 2 +- .../auto-complete/auto-complete.directive.ts | 2 +- .../demo/auto-complete-demo.module.ts | 2 +- devui/auto-complete/ng-package.json | 5 + devui/auto-complete/package.json | 7 - devui/avatar/demo/avatar-demo.module.ts | 2 +- devui/avatar/ng-package.json | 5 + devui/avatar/package.json | 8 - devui/back-top/demo/back-top-demo.module.ts | 2 +- devui/back-top/ng-package.json | 5 + devui/back-top/package.json | 7 - devui/badge/demo/badge-demo.module.ts | 2 +- devui/badge/ng-package.json | 5 + devui/badge/package.json | 7 - .../breadcrumb/demo/breadcrumb-demo.module.ts | 2 +- devui/breadcrumb/ng-package.json | 5 + devui/breadcrumb/package.json | 7 - devui/button/demo/button-demo.module.ts | 2 +- devui/button/ng-package.json | 5 + devui/button/package.json | 7 - devui/card/card.component.scss | 13 ++ devui/card/card.component.ts | 20 +- devui/card/demo/basic/basic.component.scss | 12 - devui/card/demo/card-demo.component.html | 7 + devui/card/demo/card-demo.component.ts | 7 + devui/card/demo/card-demo.module.ts | 5 +- .../card-interactive.component.html | 16 ++ .../card-interactive.component.scss | 20 ++ .../card-interactive.component.ts | 12 + devui/card/demo/custom/custom.component.scss | 12 - .../demo/with-media/with-media.component.scss | 12 - devui/card/doc/api-cn.md | 24 +- devui/card/doc/api-en.md | 44 ++-- devui/card/ng-package.json | 5 + devui/card/package.json | 7 - devui/carousel/carousel.component.html | 4 +- devui/carousel/carousel.component.scss | 24 +- devui/carousel/carousel.component.ts | 2 +- .../demo/carousel-demo.component.html | 6 + .../carousel/demo/carousel-demo.component.ts | 7 + devui/carousel/demo/carousel-demo.module.ts | 6 +- .../carousel-demo-custom.component.html | 8 +- .../with-transition-progress.component.html | 3 + .../with-transition-progress.component.ts | 21 ++ devui/carousel/doc/api-cn.md | 10 +- devui/carousel/ng-package.json | 5 + devui/carousel/package.json | 7 - devui/cascader/cascader-li.component.ts | 2 +- devui/cascader/cascader.component.ts | 2 +- devui/cascader/demo/cascader-demo.module.ts | 2 +- devui/cascader/ng-package.json | 5 + devui/cascader/package.json | 7 - .../category-search.component.html | 14 +- .../category-search.component.scss | 4 + .../category-search.component.ts | 210 +++++++++-------- devui/category-search/category-search.type.ts | 4 +- .../demo/category-search-demo.module.ts | 3 + devui/category-search/doc/api-cn.md | 45 ++-- devui/category-search/doc/api-en.md | 45 ++-- devui/category-search/ng-package.json | 5 + devui/category-search/package.json | 7 - devui/checkbox/demo/checkbox-demo.module.ts | 2 +- devui/checkbox/ng-package.json | 5 + devui/checkbox/package.json | 7 - devui/common/demo/common-demo.module.ts | 2 +- devui/common/ng-package.json | 5 + devui/common/package.json | 7 - devui/dashboard/demo/dashboard-demo.module.ts | 4 +- devui/dashboard/ng-package.json | 5 + devui/dashboard/package.json | 11 - devui/data-table/data-table-cell.component.ts | 5 +- devui/data-table/data-table-column.spec.ts | 10 +- .../data-table/data-table-row.component.scss | 1 + devui/data-table/data-table-row.component.ts | 6 +- devui/data-table/data-table.component.html | 2 +- devui/data-table/data-table.component.scss | 50 +++- devui/data-table/data-table.model.ts | 1 + .../data-table-demo-async.component.html | 4 +- .../data-table-demo-basic.component.html | 2 +- .../check-options/check-options.component.ts | 13 ++ .../data-table/demo/data-table-demo.module.ts | 2 +- devui/data-table/doc/api-cn.md | 9 + devui/data-table/doc/api-en.md | 9 + devui/data-table/ng-package.json | 5 + devui/data-table/package.json | 7 - .../table/body/td/td.component.scss | 1 + .../table/head/th/th.component.scss | 8 + .../data-table/table/head/th/th.component.ts | 1 + .../datepicker-pro-calendar.component.ts | 2 +- .../datepicker-pro.component.scss | 3 + .../datepicker-pro.component.ts | 4 +- .../demo/datepicker-pro-demo.component.html | 32 +-- .../demo/datepicker-pro-demo.module.ts | 2 +- .../lib/calendar-panel.component.scss | 4 +- .../lib/calendar-panel.component.ts | 6 +- .../lib/month-panel.component.ts | 6 +- .../lib/timepicker-panel.component.ts | 2 +- .../lib/year-panel.component.ts | 6 +- devui/datepicker-pro/ng-package.json | 5 + devui/datepicker-pro/package.json | 8 - .../range-datepicker-pro.component.scss | 5 +- .../range-datepicker-pro.component.ts | 4 +- .../datepicker/demo/datepicker-demo.module.ts | 2 +- devui/datepicker/ng-package.json | 5 + devui/datepicker/package.json | 7 - .../demo/design-animation-demo.module.ts | 2 +- .../border-radius.component.html | 5 - .../demo/design-border-radius-demo.module.ts | 2 +- .../color/demo/color/color.component.html | 26 +-- .../color/demo/design-color-demo.module.ts | 2 +- .../font/demo/design-font-demo.module.ts | 2 +- .../font/demo/font/font.component.html | 5 - .../link/demo/design-link-demo.module.ts | 2 +- .../shadow/demo/design-shadow-demo.module.ts | 2 +- .../shadow/demo/shadow/shadow.component.html | 5 - .../demo/design-z-index-demo.module.ts | 2 +- devui/dragdrop/demo/dragdrop-demo.module.ts | 2 +- .../directives/dragdrop-sync-box.directive.ts | 3 +- .../directives/draggable.directive.ts | 8 +- .../directives/drop-sort-sync.directive.ts | 3 +- devui/dragdrop/ng-package.json | 5 + devui/dragdrop/package.json | 7 - devui/dragdrop/shared/utils.ts | 4 +- devui/drawer/demo/drawer-demo.module.ts | 2 +- devui/drawer/ng-package.json | 5 + devui/drawer/package.json | 7 - .../demo/add-icon/add-icon.component.html | 2 +- .../append-to-body.component.html | 12 +- .../dropdown/demo/basic/basic.component.html | 28 +-- .../close-scope/close-scope.component.html | 12 +- devui/dropdown/demo/dropdown-demo.module.ts | 2 +- .../dropdown/demo/focus/focus.component.html | 28 +-- .../dropdown/demo/hover/hover.component.html | 6 +- .../demo/manually/manually.component.html | 4 +- .../multi-level/multi-level.component.html | 48 ++-- .../dropdown-set-is-open.component.html | 4 +- devui/dropdown/doc/api-cn.md | 4 + devui/dropdown/doc/api-en.md | 4 + devui/dropdown/dropdown-item.directive.ts | 9 + devui/dropdown/dropdown.module.ts | 22 ++ devui/dropdown/dropdown.spec.ts | 50 ++-- devui/dropdown/ng-package.json | 5 + devui/dropdown/package.json | 7 - devui/dropdown/public-api.ts | 3 +- .../demo/editable-select-demo.module.ts | 2 +- devui/editable-select/ng-package.json | 5 + devui/editable-select/package.json | 7 - devui/form/demo/form-demo.component.html | 94 ++++---- devui/form/demo/form-demo.component.ts | 6 + devui/form/demo/form-demo.module.ts | 2 +- .../validate-cross-component.component.ts | 8 +- .../validate-reactive.component.ts | 12 +- .../custom-message-show.component.html | 3 +- .../custom-validator.component.html | 2 +- .../debounce-time.component.html | 2 +- .../error-strategy.component.html | 3 +- .../inner-validator.component.html | 2 +- .../user-register.component.html | 2 +- .../validate-template-form.component.html | 2 +- devui/form/doc/api-cn.md | 137 +++++++---- devui/form/doc/api-en.md | 118 +++++++--- devui/form/form-operation.component.ts | 4 +- devui/form/ng-package.json | 5 + devui/form/package.json | 7 - .../form-control-rules.directive.ts | 4 +- devui/form/validator-directive/validators.ts | 216 +++++++++++++++++- .../fullscreen/demo/fullscreen-demo.module.ts | 1 + devui/fullscreen/ng-package.json | 5 + devui/fullscreen/package.json | 7 - devui/gantt/demo/gantt-demo.module.ts | 2 +- devui/gantt/gantt-bar/gantt-bar.component.ts | 10 +- devui/gantt/gantt.service.ts | 6 +- devui/gantt/ng-package.json | 5 + devui/gantt/package.json | 7 - devui/i18n/ng-package.json | 5 + devui/i18n/package.json | 8 - devui/icon/demo/basic/basic.component.html | 9 +- devui/icon/demo/icon-demo.module.ts | 2 +- devui/icon/doc/api-cn.md | 2 +- devui/icon/doc/api-en.md | 2 +- devui/icon/icon.component.scss | 32 +++ devui/icon/icon.component.ts | 17 +- devui/icon/icon.module.ts | 6 +- devui/icon/ng-package.json | 5 + devui/icon/package.json | 7 - .../demo/image-preview-demo.module.ts | 2 +- devui/image-preview/ng-package.json | 5 + devui/image-preview/package.json | 7 - .../demo/input-number-demo.module.ts | 2 +- devui/input-number/ng-package.json | 5 + devui/input-number/package.json | 7 - devui/layout/class.directive.ts | 2 +- devui/layout/demo/layout-demo.module.ts | 2 +- devui/layout/flex.directive.ts | 2 +- devui/layout/gutter.directive.ts | 2 +- devui/layout/ng-package.json | 5 + devui/layout/package.json | 7 - devui/layout/screen-media-query.service.ts | 2 +- devui/layout/space.directive.ts | 2 +- devui/layout/style.directive.ts | 2 +- devui/loading/demo/basic/basic.component.html | 2 +- devui/loading/demo/loading-demo.module.ts | 2 +- devui/loading/doc/api-cn.md | 10 +- devui/loading/doc/api-en.md | 10 +- devui/loading/loading.component.scss | 31 +++ devui/loading/loading.component.ts | 93 ++++++-- devui/loading/loading.directive.ts | 6 +- devui/loading/loading.service.ts | 2 + devui/loading/loading.types.ts | 4 + devui/loading/ng-package.json | 5 + devui/loading/package.json | 7 - devui/mention/assets/common.scss | 3 - devui/mention/demo/async/async.component.ts | 8 +- devui/mention/demo/custom/custom.component.ts | 26 +-- .../mention/demo/mention-demo.component.html | 16 +- devui/mention/demo/mention-demo.component.ts | 11 +- devui/mention/demo/mention-demo.module.ts | 10 +- devui/mention/demo/prefix/prefix.component.ts | 12 +- devui/mention/demo/target/target.component.ts | 16 +- .../mention/demo/toggle/toggle.component.html | 18 ++ devui/mention/demo/toggle/toggle.component.ts | 34 +++ devui/mention/doc/api-cn.md | 37 +-- devui/mention/doc/api-en.md | 33 +-- devui/mention/mention.component.scss | 4 +- devui/mention/mention.component.ts | 25 +- devui/mention/mention.directive.ts | 93 ++++---- devui/mention/mention.module.ts | 2 +- devui/mention/ng-package.json | 5 + devui/mention/package.json | 7 - devui/modal/demo/modal-demo.module.ts | 2 +- devui/modal/ng-package.json | 5 + devui/modal/package.json | 7 - .../demo/multi-auto-complete-demo.module.ts | 2 +- devui/multi-auto-complete/ng-package.json | 5 + devui/multi-auto-complete/package.json | 7 - .../nav-sprite/demo/nav-sprite-demo.module.ts | 1 + devui/nav-sprite/doc/api-cn.md | 44 ++-- devui/nav-sprite/doc/api-en.md | 45 ++-- devui/nav-sprite/nav-sprite.component.html | 6 +- devui/nav-sprite/nav-sprite.component.scss | 6 +- devui/nav-sprite/nav-sprite.component.ts | 4 +- devui/nav-sprite/ng-package.json | 5 + devui/nav-sprite/package.json | 7 - .../demo/basic/basic.component.html | 18 ++ .../demo/basic/basic.component.ts | 25 ++ .../demo/demo.component.html | 8 + .../number-translation/demo/demo.component.ts | 15 ++ devui/number-translation/demo/demo.module.ts | 39 ++++ devui/number-translation/doc/api-cn.md | 43 ++++ devui/number-translation/doc/api-en.md | 43 ++++ devui/number-translation/index.ts | 1 + devui/number-translation/ng-package.json | 5 + .../number-translation.module.ts | 12 + .../number-translation.pipe.ts | 77 +++++++ devui/number-translation/public-api.ts | 3 + devui/overlay-container/ng-package.json | 5 + devui/overlay-container/package.json | 7 - devui/package.json | 12 +- .../pagination/demo/pagination-demo.module.ts | 2 +- devui/pagination/ng-package.json | 5 + devui/pagination/package.json | 7 - devui/panel/demo/panel-demo.component.ts | 1 - devui/panel/demo/panel-demo.module.ts | 2 +- devui/panel/ng-package.json | 5 + devui/panel/package.json | 7 - devui/popover/demo/popover-demo.module.ts | 2 +- devui/popover/ng-package.json | 5 + devui/popover/package.json | 7 - devui/popover/popover.directive.ts | 4 +- devui/portal/ng-package.json | 5 + devui/portal/package.json | 7 - devui/position/ng-package.json | 5 + devui/position/package.json | 7 - devui/progress/demo/progress-demo.module.ts | 2 +- devui/progress/ng-package.json | 5 + devui/progress/package.json | 7 - .../demo/quadrant-diagram-demo.module.ts | 2 +- devui/quadrant-diagram/ng-package.json | 5 + devui/quadrant-diagram/package.json | 8 - devui/radio/demo/custom/custom.component.ts | 4 +- devui/radio/demo/radio-demo.module.ts | 2 +- devui/radio/ng-package.json | 5 + devui/radio/package.json | 7 - devui/rate/demo/rate-demo.module.ts | 2 +- devui/rate/ng-package.json | 5 + devui/rate/package.json | 8 - devui/read-tip/demo/read-tip-demo.module.ts | 2 +- devui/read-tip/ng-package.json | 5 + devui/read-tip/package.json | 8 - devui/relative-time/demo/demo.module.ts | 2 +- devui/relative-time/ng-package.json | 5 + devui/relative-time/package.json | 7 - devui/relative-time/relative-time.pipe.ts | 2 +- devui/search/demo/search-demo.module.ts | 2 +- devui/search/ng-package.json | 5 + devui/search/package.json | 7 - devui/search/search.component.scss | 6 +- devui/select/demo/select-demo.module.ts | 2 +- devui/select/ng-package.json | 5 + devui/select/package.json | 7 - devui/select/select.component.ts | 158 +++++++------ .../shared/devui-api/devui-api.component.html | 5 +- .../shared/devui-api/devui-api.component.scss | 19 +- .../devui-online-ide.service.ts | 18 +- devui/shared/devui-online-ide/files/main.ts | 12 + devui/slider/demo/slider-demo.module.ts | 2 +- devui/slider/ng-package.json | 5 + devui/slider/package.json | 7 - devui/slider/slider.component.ts | 4 +- devui/splitter/demo/splitter-demo.module.ts | 2 +- devui/splitter/ng-package.json | 5 + devui/splitter/package.json | 7 - devui/status/demo/status-demo.module.ts | 2 +- devui/status/ng-package.json | 5 + devui/status/package.json | 7 - .../demo/steps-guide-demo.component.html | 12 +- .../demo/steps-guide-demo.module.ts | 2 +- devui/steps-guide/ng-package.json | 5 + devui/steps-guide/package.json | 7 - devui/sticky/demo/sticky-demo.module.ts | 2 +- devui/sticky/ng-package.json | 5 + devui/sticky/package.json | 7 - devui/style/core/_color.scss | 1 + devui/style/core/_common.scss | 16 +- devui/style/core/_dropdown.scss | 20 ++ devui/style/core/_form.scss | 19 +- devui/style/core/_index.scss | 6 +- devui/style/core/_shadow.scss | 1 + devui/style/devui.css | 10 +- devui/style/theme/_basic.scss | 3 +- devui/style/theme/_color.scss | 9 +- devui/style/theme/_shadow.scss | 8 +- .../demo/big-data/big-data.component.html | 19 +- .../demo/big-data/big-data.component.scss | 13 ++ .../tabs/demo/big-data/big-data.component.ts | 23 +- devui/tabs/demo/custom/custom.component.html | 5 +- devui/tabs/demo/tabs-demo.component.ts | 1 + devui/tabs/demo/tabs-demo.module.ts | 6 +- .../without-content.component.html | 8 +- .../without-content.component.ts | 18 +- devui/tabs/doc/api-cn.md | 44 ++-- devui/tabs/doc/api-en.md | 42 ++-- devui/tabs/ng-package.json | 5 + devui/tabs/package.json | 7 - devui/tabs/tab.component.ts | 7 +- devui/tabs/tabs.component.html | 18 +- devui/tabs/tabs.component.scss | 15 +- devui/tabs/tabs.component.ts | 123 ++++++---- .../tags-input/demo/tags.input-demo.module.ts | 2 +- devui/tags-input/ng-package.json | 5 + devui/tags-input/package.json | 7 - devui/tags/demo/tags-demo.module.ts | 2 +- devui/tags/ng-package.json | 5 + devui/tags/package.json | 7 - devui/tags/tags.component.html | 1 + devui/tags/tags.component.ts | 22 +- .../text-input/demo/text-input-demo.module.ts | 2 +- devui/text-input/ng-package.json | 5 + devui/text-input/package.json | 7 - devui/textarea/demo/text-demo.module.ts | 2 +- devui/textarea/ng-package.json | 5 + devui/textarea/package.json | 7 - devui/theme-collection/extend-theme.ts | 52 +++-- devui/theme-collection/ng-package.json | 5 + devui/theme-collection/overwrite-style.scss | 22 +- devui/theme-collection/package.json | 7 - .../theme-custom-components-data.ts | 9 +- devui/theme-collection/theme-initial-data.ts | 2 +- devui/theme/ng-package.json | 5 + devui/theme/package.json | 7 - devui/theme/theme-data.ts | 6 +- devui/theme/theme-management.ts | 16 +- devui/time-axis/demo/time-axis-demo.module.ts | 2 +- devui/time-axis/ng-package.json | 5 + devui/time-axis/package.json | 7 - .../demo/time-picker-demo.module.ts | 2 +- devui/time-picker/ng-package.json | 5 + devui/time-picker/package.json | 7 - devui/toast/demo/toast-demo.module.ts | 2 +- devui/toast/ng-package.json | 5 + devui/toast/package.json | 7 - devui/toast/toast.component.html | 2 +- devui/toggle-menu/ng-package.json | 5 + devui/toggle-menu/package.json | 7 - devui/toggle/demo/toggle-demo.module.ts | 2 +- devui/toggle/ng-package.json | 5 + devui/toggle/package.json | 7 - devui/tooltip/demo/tooltip-demo.module.ts | 2 +- devui/tooltip/ng-package.json | 5 + devui/tooltip/package.json | 7 - devui/tooltip/tooltip.directive.ts | 4 +- devui/transfer/demo/transfer-demo.module.ts | 2 +- devui/transfer/ng-package.json | 5 + devui/transfer/package.json | 7 - devui/transfer/transfer.component.ts | 4 +- devui/tree-select/ng-package.json | 5 + devui/tree-select/package.json | 7 - devui/tree-select/tree-select.component.scss | 2 +- devui/tree-select/tree-select.component.ts | 2 +- .../demo/draggable/draggable.component.html | 1 - .../demo/draggable/draggable.component.ts | 5 - devui/tree/demo/tree-demo.module.ts | 2 +- devui/tree/ng-package.json | 5 + devui/tree/operable-tree.component.scss | 9 + devui/tree/operable-tree.component.ts | 119 ++++++++-- devui/tree/package.json | 7 - devui/tree/tree-factory.class.ts | 2 +- devui/tree/tree.component.scss | 4 +- devui/tree/tree.component.ts | 2 +- devui/tsconfig.lib.json | 8 +- devui/tsconfig.spec.json | 2 +- devui/upload/demo/upload-demo.module.ts | 2 +- devui/upload/ng-package.json | 5 + devui/upload/package.json | 7 - devui/utils/ng-package.json | 5 + devui/utils/package.json | 7 - devui/version.ts | 2 +- devui/window-ref/ng-package.json | 5 + devui/window-ref/package.json | 7 - e2e/tsconfig.e2e.json | 2 +- package.json | 40 ++-- ...r+13.1.3.patch => ng-packagr+14.1.0.patch} | 4 +- .../babel-loader-wepack-config.js | 2 +- .../webpack-config-less-loader-importer.js | 2 +- scripts/sass-importer/get-tsconfig-alias.js | 2 +- .../webpack-config-sass-loader-importer.js | 2 +- src/app/app.component.scss | 4 +- src/app/component/component.route.ts | 17 +- src/app/component/d-demo-nav.component.html | 12 - src/app/component/d-demo-nav.component.scss | 49 ---- src/app/component/d-demo-nav.component.ts | 17 -- src/app/component/d-demo-nav.module.ts | 24 -- .../component/example-panel.component.html | 18 +- .../component/example-panel.component.scss | 33 ++- src/app/component/example-panel.component.ts | 33 ++- src/app/component/getStarted-cn.md | 2 +- src/app/component/getStarted-en.md | 2 +- src/app/component/overview.component.scss | 6 +- src/app/component/scope-list.ts | 23 +- src/app/component/themeGuide-cn.md | 2 +- src/app/component/themeGuide-en.md | 2 +- src/assets/i18n/en-us.json | 67 +++++- src/assets/i18n/zh-cn.json | 60 ++++- src/main.ts | 5 +- src/styles.scss | 1 - src/tsconfig.app.json | 2 +- src/tsconfig.spec.json | 2 +- src/utils.ts | 15 ++ tsconfig.base.json | 35 --- tsconfig.json | 61 +++-- 480 files changed, 3490 insertions(+), 2133 deletions(-) delete mode 100644 devui/accordion/accordion-list-token.ts delete mode 100644 devui/accordion/accordion-menu-token.ts create mode 100644 devui/accordion/accordion.service.ts create mode 100644 devui/accordion/ng-package.json delete mode 100755 devui/accordion/package.json create mode 100644 devui/alert/ng-package.json delete mode 100755 devui/alert/package.json create mode 100644 devui/anchor/ng-package.json delete mode 100755 devui/anchor/package.json create mode 100644 devui/auto-complete/ng-package.json delete mode 100755 devui/auto-complete/package.json create mode 100644 devui/avatar/ng-package.json delete mode 100644 devui/avatar/package.json create mode 100644 devui/back-top/ng-package.json delete mode 100644 devui/back-top/package.json create mode 100644 devui/badge/ng-package.json delete mode 100644 devui/badge/package.json create mode 100644 devui/breadcrumb/ng-package.json delete mode 100644 devui/breadcrumb/package.json create mode 100644 devui/button/ng-package.json delete mode 100755 devui/button/package.json create mode 100644 devui/card/demo/card-interactive/card-interactive.component.html create mode 100644 devui/card/demo/card-interactive/card-interactive.component.scss create mode 100644 devui/card/demo/card-interactive/card-interactive.component.ts create mode 100644 devui/card/ng-package.json delete mode 100644 devui/card/package.json create mode 100644 devui/carousel/demo/with-transition-progress/with-transition-progress.component.html create mode 100644 devui/carousel/demo/with-transition-progress/with-transition-progress.component.ts create mode 100644 devui/carousel/ng-package.json delete mode 100644 devui/carousel/package.json create mode 100644 devui/cascader/ng-package.json delete mode 100644 devui/cascader/package.json create mode 100644 devui/category-search/ng-package.json delete mode 100644 devui/category-search/package.json create mode 100644 devui/checkbox/ng-package.json delete mode 100755 devui/checkbox/package.json create mode 100644 devui/common/ng-package.json delete mode 100755 devui/common/package.json create mode 100644 devui/dashboard/ng-package.json delete mode 100644 devui/dashboard/package.json create mode 100644 devui/data-table/ng-package.json delete mode 100755 devui/data-table/package.json create mode 100644 devui/data-table/table/head/th/th.component.scss create mode 100644 devui/datepicker-pro/ng-package.json delete mode 100644 devui/datepicker-pro/package.json create mode 100644 devui/datepicker/ng-package.json delete mode 100755 devui/datepicker/package.json create mode 100644 devui/dragdrop/ng-package.json delete mode 100755 devui/dragdrop/package.json create mode 100644 devui/drawer/ng-package.json delete mode 100755 devui/drawer/package.json create mode 100644 devui/dropdown/dropdown-item.directive.ts create mode 100644 devui/dropdown/dropdown.module.ts create mode 100644 devui/dropdown/ng-package.json delete mode 100755 devui/dropdown/package.json create mode 100644 devui/editable-select/ng-package.json delete mode 100755 devui/editable-select/package.json create mode 100644 devui/form/ng-package.json delete mode 100644 devui/form/package.json create mode 100644 devui/fullscreen/ng-package.json delete mode 100644 devui/fullscreen/package.json create mode 100644 devui/gantt/ng-package.json delete mode 100644 devui/gantt/package.json create mode 100644 devui/i18n/ng-package.json delete mode 100644 devui/i18n/package.json create mode 100644 devui/icon/ng-package.json delete mode 100644 devui/icon/package.json create mode 100644 devui/image-preview/ng-package.json delete mode 100644 devui/image-preview/package.json create mode 100644 devui/input-number/ng-package.json delete mode 100755 devui/input-number/package.json create mode 100644 devui/layout/ng-package.json delete mode 100644 devui/layout/package.json create mode 100644 devui/loading/ng-package.json delete mode 100755 devui/loading/package.json delete mode 100644 devui/mention/assets/common.scss create mode 100644 devui/mention/demo/toggle/toggle.component.html create mode 100644 devui/mention/demo/toggle/toggle.component.ts create mode 100644 devui/mention/ng-package.json delete mode 100644 devui/mention/package.json create mode 100644 devui/modal/ng-package.json delete mode 100755 devui/modal/package.json create mode 100644 devui/multi-auto-complete/ng-package.json delete mode 100644 devui/multi-auto-complete/package.json create mode 100644 devui/nav-sprite/ng-package.json delete mode 100644 devui/nav-sprite/package.json create mode 100644 devui/number-translation/demo/basic/basic.component.html create mode 100644 devui/number-translation/demo/basic/basic.component.ts create mode 100644 devui/number-translation/demo/demo.component.html create mode 100644 devui/number-translation/demo/demo.component.ts create mode 100644 devui/number-translation/demo/demo.module.ts create mode 100644 devui/number-translation/doc/api-cn.md create mode 100644 devui/number-translation/doc/api-en.md create mode 100644 devui/number-translation/index.ts create mode 100644 devui/number-translation/ng-package.json create mode 100644 devui/number-translation/number-translation.module.ts create mode 100644 devui/number-translation/number-translation.pipe.ts create mode 100644 devui/number-translation/public-api.ts create mode 100644 devui/overlay-container/ng-package.json delete mode 100755 devui/overlay-container/package.json create mode 100644 devui/pagination/ng-package.json delete mode 100755 devui/pagination/package.json create mode 100644 devui/panel/ng-package.json delete mode 100755 devui/panel/package.json create mode 100644 devui/popover/ng-package.json delete mode 100755 devui/popover/package.json create mode 100644 devui/portal/ng-package.json delete mode 100755 devui/portal/package.json create mode 100644 devui/position/ng-package.json delete mode 100755 devui/position/package.json create mode 100644 devui/progress/ng-package.json delete mode 100755 devui/progress/package.json create mode 100644 devui/quadrant-diagram/ng-package.json delete mode 100644 devui/quadrant-diagram/package.json create mode 100644 devui/radio/ng-package.json delete mode 100755 devui/radio/package.json create mode 100644 devui/rate/ng-package.json delete mode 100644 devui/rate/package.json create mode 100644 devui/read-tip/ng-package.json delete mode 100644 devui/read-tip/package.json create mode 100644 devui/relative-time/ng-package.json delete mode 100644 devui/relative-time/package.json create mode 100644 devui/search/ng-package.json delete mode 100755 devui/search/package.json create mode 100644 devui/select/ng-package.json delete mode 100755 devui/select/package.json create mode 100644 devui/slider/ng-package.json delete mode 100755 devui/slider/package.json create mode 100644 devui/splitter/ng-package.json delete mode 100644 devui/splitter/package.json create mode 100644 devui/status/ng-package.json delete mode 100755 devui/status/package.json create mode 100644 devui/steps-guide/ng-package.json delete mode 100644 devui/steps-guide/package.json create mode 100644 devui/sticky/ng-package.json delete mode 100755 devui/sticky/package.json create mode 100644 devui/style/core/_color.scss create mode 100644 devui/style/core/_shadow.scss create mode 100644 devui/tabs/demo/big-data/big-data.component.scss create mode 100644 devui/tabs/ng-package.json delete mode 100755 devui/tabs/package.json create mode 100644 devui/tags-input/ng-package.json delete mode 100755 devui/tags-input/package.json create mode 100644 devui/tags/ng-package.json delete mode 100755 devui/tags/package.json create mode 100644 devui/text-input/ng-package.json delete mode 100644 devui/text-input/package.json create mode 100644 devui/textarea/ng-package.json delete mode 100644 devui/textarea/package.json create mode 100644 devui/theme-collection/ng-package.json delete mode 100644 devui/theme-collection/package.json create mode 100644 devui/theme/ng-package.json delete mode 100644 devui/theme/package.json create mode 100644 devui/time-axis/ng-package.json delete mode 100644 devui/time-axis/package.json create mode 100644 devui/time-picker/ng-package.json delete mode 100644 devui/time-picker/package.json create mode 100644 devui/toast/ng-package.json delete mode 100755 devui/toast/package.json create mode 100644 devui/toggle-menu/ng-package.json delete mode 100644 devui/toggle-menu/package.json create mode 100644 devui/toggle/ng-package.json delete mode 100755 devui/toggle/package.json create mode 100644 devui/tooltip/ng-package.json delete mode 100755 devui/tooltip/package.json create mode 100644 devui/transfer/ng-package.json delete mode 100644 devui/transfer/package.json create mode 100644 devui/tree-select/ng-package.json delete mode 100755 devui/tree-select/package.json create mode 100644 devui/tree/ng-package.json delete mode 100755 devui/tree/package.json create mode 100644 devui/upload/ng-package.json delete mode 100755 devui/upload/package.json create mode 100644 devui/utils/ng-package.json delete mode 100755 devui/utils/package.json create mode 100644 devui/window-ref/ng-package.json delete mode 100755 devui/window-ref/package.json rename patches/{ng-packagr+13.1.3.patch => ng-packagr+14.1.0.patch} (87%) delete mode 100644 src/app/component/d-demo-nav.component.html delete mode 100644 src/app/component/d-demo-nav.component.scss delete mode 100644 src/app/component/d-demo-nav.component.ts delete mode 100644 src/app/component/d-demo-nav.module.ts create mode 100644 src/utils.ts delete mode 100644 tsconfig.base.json diff --git a/README.md b/README.md index 0a2daa01..5043e492 100755 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ To see more in [devui.design](https://devui.design/home). ## Angular Support -Now supports Angular `^13.0.0` +Now supports Angular `^14.0.0` ## Getting Started diff --git a/README_zh_CN.md b/README_zh_CN.md index 5a0cbe1f..36ae860e 100644 --- a/README_zh_CN.md +++ b/README_zh_CN.md @@ -23,7 +23,7 @@ DevUI Design设计系统包含了DevUI规则、设计语言和最佳实践的资 ## Angular版本 -当前支持的angular版本`^13.0.0` +当前支持的angular版本`^14.0.0` ## 快速开始 diff --git a/angular.json b/angular.json index 483fd0c7..824fc936 100755 --- a/angular.json +++ b/angular.json @@ -67,6 +67,14 @@ } ] }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + }, "es5": { "tsConfig": "src/tsconfig.app.es5.json" }, @@ -84,13 +92,17 @@ "production": { "browserTarget": "devui:build:production" }, + "development": { + "browserTarget": "devui:build:development" + }, "es5": { "browserTarget": "devui:build:es5" }, "separate": { "browserTarget": "devui:build:separate" } - } + }, + "defaultConfiguration": "development" }, "extract-i18n": { "builder": "@angular-devkit/build-angular:extract-i18n", diff --git a/devui-commons/src/codecopy/codecopy.directive.ts b/devui-commons/src/codecopy/codecopy.directive.ts index 182df6f5..a379ae21 100644 --- a/devui-commons/src/codecopy/codecopy.directive.ts +++ b/devui-commons/src/codecopy/codecopy.directive.ts @@ -9,7 +9,7 @@ import { ReadTipOption, StrCopySVG } from './codecopy.types'; }) export class CodeCopyDirective implements OnInit, AfterViewInit, OnDestroy { @Output('copied') copied: EventEmitter = new EventEmitter(); - private destroy$ = new Subject(); + private destroy$ = new Subject(); timer: any; optionsSuccess = ReadTipOption.optionSuccessData['zh-cn']; options = ReadTipOption.optionData['zh-cn']; diff --git a/devui-commons/src/demo-nav/d-demo-nav.component.html b/devui-commons/src/demo-nav/d-demo-nav.component.html index af6c9a2a..48067fee 100644 --- a/devui-commons/src/demo-nav/d-demo-nav.component.html +++ b/devui-commons/src/demo-nav/d-demo-nav.component.html @@ -1,7 +1,7 @@
-
{{ goToText }}
+
  • {{ navitem.value }} diff --git a/devui-commons/src/devui-commons.scss b/devui-commons/src/devui-commons.scss index 76218bc4..11ed8ece 100644 --- a/devui-commons/src/devui-commons.scss +++ b/devui-commons/src/devui-commons.scss @@ -16,10 +16,9 @@ .devui-content-layout { top: 60px; position: absolute; - padding: 0 20% 32px 13%; - margin-left: 260px; - width: calc(100% - 260px); - background-color: $devui-base-bg; + padding: 0 15vw 0 25vw; + width: calc(100vw - 20px); + background-color: $devui-global-bg; } //内容区文档头样式 @@ -48,7 +47,11 @@ } .devui-demo-example { - margin-bottom: 48px; + margin-bottom: 20px; + padding: 20px; + background-color: $devui-base-bg; + box-shadow: $devui-shadow-length-base $devui-light-shadow; + border-radius: 8px; } .devui-demo-title { @@ -154,10 +157,10 @@ .devui-content-nav { width: 240px; position: fixed; - top: 90px; + top: 170px; right: 0; height: 100%; - z-index: 1; + z-index: calc(#{$devui-z-index-framework} + 1); .devui-fast-forward { width: 130px; @@ -218,10 +221,6 @@ .devui-content-nav { width: 150px; } - - .devui-content-layout { - padding: 0 15% 0 8%; - } } @media (max-width: 1250px) { diff --git a/devui-commons/src/header/header.component.ts b/devui-commons/src/header/header.component.ts index 4d440588..160245d8 100644 --- a/devui-commons/src/header/header.component.ts +++ b/devui-commons/src/header/header.component.ts @@ -33,7 +33,7 @@ export class HeaderComponent implements OnInit { @HostListener('window:resize') resize(): void { - this.showSlideMenu = document.body.clientWidth < 1024 ? false : true; + this.showSlideMenu = document.body.clientWidth < 1280 ? false : true; this.setSlideBarStyle(); } @@ -69,7 +69,7 @@ export class HeaderComponent implements OnInit { setSlideBarStyle(): void { const ele = document.querySelector('.sidebar-wrapper'); if (ele) { - ele.setAttribute('style', `max-width: ${ this.showSlideMenu ? '260px' : '0'}`); + ele.setAttribute('style', `max-width: ${ this.showSlideMenu ? '320px' : '0'}`); } } diff --git a/devui-commons/src/header/version-switch/version-switch.component.scss b/devui-commons/src/header/version-switch/version-switch.component.scss index 07fa05bb..524cf633 100644 --- a/devui-commons/src/header/version-switch/version-switch.component.scss +++ b/devui-commons/src/header/version-switch/version-switch.component.scss @@ -1,5 +1,5 @@ .header-version-switch { - width: 80px; + width: 100px; margin: 0 12px; } diff --git a/devui-commons/src/sidebar/sidebar.component.scss b/devui-commons/src/sidebar/sidebar.component.scss index 974d3efd..0cb75788 100644 --- a/devui-commons/src/sidebar/sidebar.component.scss +++ b/devui-commons/src/sidebar/sidebar.component.scss @@ -2,11 +2,12 @@ .sidebar-wrapper { position: fixed; - top: 70px; - width: 260px; - max-width: 260px; + top: 60px; + width: 320px; + max-width: 320px; height: 100%; overflow-y: hidden; + scroll-behavior: smooth; z-index: 1000; border-right: 1px solid $devui-dividing-line; background-color: $devui-base-bg; @@ -19,12 +20,12 @@ } .sidebar-nav { - width: 260px; + width: 100%; padding-bottom: 80px; } .sidebar-menu { - width: 260px; + width: 320px; outline: none; margin-bottom: 0; diff --git a/devui-commons/src/sidebar/sidebar.component.ts b/devui-commons/src/sidebar/sidebar.component.ts index e5eac372..04dce9eb 100644 --- a/devui-commons/src/sidebar/sidebar.component.ts +++ b/devui-commons/src/sidebar/sidebar.component.ts @@ -1,5 +1,8 @@ -import { Component, Input, OnInit } from '@angular/core'; +import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { NavigationEnd, Router } from '@angular/router'; import { cloneDeep } from 'lodash-es'; +import { Subject } from 'rxjs'; +import { filter, takeUntil } from 'rxjs/operators'; import { DevuiCommonsService } from '../devui-commons.service'; @Component({ @@ -7,7 +10,7 @@ import { DevuiCommonsService } from '../devui-commons.service'; templateUrl: './sidebar.component.html', styleUrls: ['./sidebar.component.scss'] }) -export class SidebarComponent implements OnInit { +export class SidebarComponent implements OnInit, AfterViewInit, OnDestroy { @Input() sideMenuList; @Input() linkType = 'routerLink'; @Input() text = { @@ -15,6 +18,8 @@ export class SidebarComponent implements OnInit { sunset: 'Sunset' }; _navData; + private _currentUrl: string = ''; + private destroy$: Subject = new Subject(); componentsDataDisplay; @Input() set navData(data) { @@ -26,14 +31,40 @@ export class SidebarComponent implements OnInit { return this._navData; } - constructor(private commonsService: DevuiCommonsService) { } + constructor(private commonsService: DevuiCommonsService, private router: Router, private ele: ElementRef) { } ngOnInit(): void { + this._currentUrl = this.router.url; this.commonsService.on('searchEvent').subscribe(term => { this.filterData(term); }); } + ngAfterViewInit(): void { + this.router.events + .pipe( + filter((event) => event instanceof NavigationEnd), + takeUntil(this.destroy$) + ) + .subscribe((event) => { + const destUrl = (event as NavigationEnd).urlAfterRedirects; + if (this._currentUrl.endsWith('overview')) { + setTimeout(() => { + const activeItem: HTMLElement = this.ele.nativeElement.querySelector('.devui-router-active'); + if (activeItem) { + activeItem.scrollIntoView({ block: 'center' }); + } + }); + } + this._currentUrl = destUrl; + }); + } + + ngOnDestroy(): void { + this.destroy$.next(); + this.destroy$.complete(); + } + filterData(event): void { this.componentsDataDisplay = cloneDeep(this.navData).filter(catalog => { catalog.children = catalog.children.filter(item => { diff --git a/devui/accordion/accordion-item-routerlink.component.ts b/devui/accordion/accordion-item-routerlink.component.ts index 52a63a9b..95797e42 100644 --- a/devui/accordion/accordion-item-routerlink.component.ts +++ b/devui/accordion/accordion-item-routerlink.component.ts @@ -12,9 +12,10 @@ import { ACCORDION } from './accordion-token'; export class AccordionItemRouterlinkComponent extends AccordionBaseLinkComponent implements OnChanges { @ViewChild(RouterLinkActive) routerLinkActiveDirective: RouterLinkActive; @HostBinding('class.devui-router-active') - get routerLinkActived(): boolean { + get routerLinkActivated(): boolean { return !!(this.routerLinkActiveDirective && this.routerLinkActiveDirective.isActive); } + private set urlTree(urlTree: UrlTree) { if (urlTree) { this.queryParams = urlTree.queryParams; @@ -25,25 +26,25 @@ export class AccordionItemRouterlinkComponent extends AccordionBaseLinkComponent } } - public path: string; - public queryParams: Params; - public fragment: string; - - constructor(@Inject(ACCORDION) protected accordion: any, private router: Router) { - super(accordion); - } - @HostListener('click', ['$event']) onClick(event: MouseEvent) { if (!this.disabled) { this.accordion.linkItemClickFn({ item: this.item, parent: this.parent, - event: event + event: event, }); } } + path: string; + queryParams: Params; + fragment: string; + + constructor(@Inject(ACCORDION) protected accordion: any, private router: Router) { + super(accordion); + } + ngOnChanges(changes: SimpleChanges): void { if (changes['item']) { if (this.link) { diff --git a/devui/accordion/accordion-list-token.ts b/devui/accordion/accordion-list-token.ts deleted file mode 100644 index 72c2a979..00000000 --- a/devui/accordion/accordion-list-token.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { InjectionToken } from '@angular/core'; - -export const ACCORDION_LIST = new InjectionToken('AccordionListComponent'); diff --git a/devui/accordion/accordion-list.component.html b/devui/accordion/accordion-list.component.html index c58ce90c..587acb5b 100644 --- a/devui/accordion/accordion-list.component.html +++ b/devui/accordion/accordion-list.component.html @@ -4,12 +4,13 @@ diff --git a/devui/accordion/accordion-list.component.ts b/devui/accordion/accordion-list.component.ts index c2e62d74..950be15d 100644 --- a/devui/accordion/accordion-list.component.ts +++ b/devui/accordion/accordion-list.component.ts @@ -1,13 +1,9 @@ -import { - Component, - forwardRef, Host, HostBinding, Inject, Input, OnDestroy, OnInit, - Optional, QueryList, SkipSelf, ViewChildren, ViewEncapsulation -} from '@angular/core'; +import { Component, HostBinding, Inject, Input, OnDestroy, OnInit, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core'; import { expandCollapse, expandCollapseForDomDestroy } from 'ng-devui/utils'; import { AccordionItemRouterlinkComponent } from './accordion-item-routerlink.component'; -import { ACCORDION_LIST } from './accordion-list-token'; -import { ACCORDION_MENU } from './accordion-menu-token'; +import { AccordionMenuComponent } from './accordion-menu.component'; import { ACCORDION } from './accordion-token'; +import { AccordionService } from './accordion.service'; import { AccordionMenuItem } from './accordion.type'; @Component({ @@ -16,15 +12,13 @@ import { AccordionMenuItem } from './accordion.type'; encapsulation: ViewEncapsulation.None, animations: [expandCollapse, expandCollapseForDomDestroy], preserveWhitespaces: false, - providers: [{ - provide: ACCORDION_LIST, - useExisting: forwardRef(() => AccordionListComponent) - }] }) export class AccordionListComponent implements OnInit, OnDestroy { - - constructor(@Optional() @Host() @SkipSelf() @Inject(ACCORDION_MENU) private parentComponent: any, - @Inject(ACCORDION) private accordion: any) {} + @Input() data: Array; + @Input() deepth = 0; + @Input() parent: AccordionMenuItem; + @ViewChildren(AccordionMenuComponent) accordionMenuQueryList: QueryList; + @ViewChildren(AccordionItemRouterlinkComponent) accordionItemRouterlinkQueryList: QueryList; @HostBinding('class.devui-accordion-show-animate') get animateState() { return this.accordion.showAnimation; } @@ -40,9 +34,11 @@ export class AccordionListComponent implements OnInit, OnDestroy { get linkTypeKey() { return this.accordion.linkTypeKey; } + get childrenKey() { return this.accordion.childrenKey; } + get activeKey() { return this.accordion.activeKey; } @@ -50,89 +46,111 @@ export class AccordionListComponent implements OnInit, OnDestroy { get itemTemplate() { return this.accordion.itemTemplate; } + get menuItemTemplate() { return this.accordion.menuItemTemplate; } + get innerListTemplate() { return this.accordion.innerListTemplate; } + get loadingTemplate() { return this.accordion.loadingTemplate; } + get noContentTemplate() { return this.accordion.noContentTemplate; } + get linkType() { return this.accordion.linkType; } + get i18nCommonText() { return this.accordion.i18nCommonText; } + get showNoContent() { return this.accordion.showNoContent; } + get linkDefaultTarget() { return this.accordion.linkDefaultTarget; } - get routerLinkActived(): boolean { - return (!!this.accordionItemRouterlinkQueryList - && this.accordionItemRouterlinkQueryList.some(airlc => this.isLinkRouterActive(airlc)) - ) || ( - !!this.accordionMenuQueryList - && this.accordionMenuQueryList.some(amc => this.isMenuRouterActive(amc)) + + get routerLinkActivated(): boolean { + return ( + (!!this.accordionItemRouterlinkQueryList && this.accordionItemRouterlinkQueryList.some((airlc) => this.isLinkRouterActive(airlc))) || + (!!this.accordionMenuQueryList && this.accordionMenuQueryList.some((amc) => this.isMenuRouterActive(amc))) ); } + get hasActiveChildren(): boolean { - return (!!this.accordionMenuQueryList - && this.accordionMenuQueryList.some(amc => this.isMenuDataActive(amc))) - || (!!this.data && !!this.data.length - && this.data.some(item => this.isItemData(item) && this.isItemDataActive(item)) - ); + return ( + (!!this.accordionMenuQueryList && this.accordionMenuQueryList.some((amc) => this.isMenuDataActive(amc))) || + (!!this.data && !!this.data.length && this.data.some((item) => this.isItemData(item) && this.isItemDataActive(item))) + ); } - @Input() data: Array; - @Input() deepth = 0; - @Input() parent: AccordionMenuItem; - @ViewChildren(ACCORDION_MENU) accordionMenuQueryList: QueryList; - @ViewChildren(AccordionItemRouterlinkComponent) accordionItemRouterlinkQueryList: QueryList; - 6; + + constructor(@Inject(ACCORDION) private accordion: any, private accordionService: AccordionService) {} + ngOnInit(): void { - if (this.parentComponent) { - setTimeout(() => {this.parentComponent.accordionListFromView = this; }); + if (this.parent) { + this.accordionService.setChildListInstance(this, this.parent); } } + ngOnDestroy(): void { - if (this.parentComponent) { - this.parentComponent.accordionListFromView = undefined; + if (this.parent) { + this.accordionService.setChildListInstance(undefined, this.parent); } } + private isLinkRouterActive(airlc: AccordionItemRouterlinkComponent): boolean { - return airlc.routerLinkActived; + return airlc.routerLinkActivated; } + private isMenuRouterActive(amc: any): boolean { - return amc.routerLinkActived; + return amc.routerLinkActivated; } + private isMenuDataActive(amc: any): boolean { return amc.hasActiveChildren; } + private isItemDataActive(item: AccordionMenuItem): boolean { return !!item[this.activeKey]; } + private isItemData(item: AccordionMenuItem): boolean { return item[this.childrenKey] === undefined; } - menuToggleItemFn = (item: any , event?: any) => { + + menuToggleItemFn = (item: any, event?: any) => { this.accordion.menuToggleFn({ item: item, open: !item[this.accordion.openKey], parent: this.parent.parent, - event: event + event: event, }); }; + itemClickItemFn = (item: any, event?: any) => { this.accordion.itemClickFn({ item: item, parent: this.parent, - event: event + event: event, }); }; + + getOpenState(item, list) { + let stateFlag = false; + if (item && list) { + const open = item[this.accordion.openKey]; + const childActivated = list.routerLinkActivated || list.hasActiveChildren; + stateFlag = open === undefined && this.accordion.autoOpenActiveMenu ? childActivated : open; + } + return stateFlag ? 'expanded' : 'collapsed'; + } } diff --git a/devui/accordion/accordion-menu-token.ts b/devui/accordion/accordion-menu-token.ts deleted file mode 100644 index d2a9a3ff..00000000 --- a/devui/accordion/accordion-menu-token.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { InjectionToken } from '@angular/core'; - -export const ACCORDION_MENU = new InjectionToken('AccordionMenuComponent'); diff --git a/devui/accordion/accordion-menu.component.html b/devui/accordion/accordion-menu.component.html index cc056756..e978e0f6 100644 --- a/devui/accordion/accordion-menu.component.html +++ b/devui/accordion/accordion-menu.component.html @@ -2,7 +2,7 @@ class="devui-accordion-item-title devui-over-flow-ellipsis" [ngClass]="{ open: open, - active: childActived, + active: childActivated, disabled: disabled }" title="{{ title }}" diff --git a/devui/accordion/accordion-menu.component.ts b/devui/accordion/accordion-menu.component.ts index 2dcddb53..9ce7f242 100644 --- a/devui/accordion/accordion-menu.component.ts +++ b/devui/accordion/accordion-menu.component.ts @@ -1,34 +1,36 @@ -import { Component, forwardRef, HostBinding, Inject, ViewEncapsulation } from '@angular/core'; +import { Component, HostBinding, Inject, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core'; +import { Subscription } from 'rxjs'; import { AccordionBaseComponent } from './accordion-base-component.class'; -import { ACCORDION_MENU } from './accordion-menu-token'; import { ACCORDION } from './accordion-token'; +import { AccordionService } from './accordion.service'; import { AccordionBaseMenu, AccordionMenuItem } from './accordion.type'; @Component({ selector: 'd-accordion-menu', templateUrl: './accordion-menu.component.html', encapsulation: ViewEncapsulation.None, preserveWhitespaces: false, - providers: [{ - provide: ACCORDION_MENU, - useExisting: forwardRef(() => AccordionMenuComponent) - }] }) -export class AccordionMenuComponent extends AccordionBaseComponent> { - @HostBinding('class.devui-accordion-menu-item') - defaultClasses = true; +export class AccordionMenuComponent extends AccordionBaseComponent> implements OnInit, OnDestroy { + childListSub: Subscription; + accordionListFromView: any; // AccordionListComponent - public accordionListFromView: any; // AccordionListComponent - - get menuItemTemplate() { - return this.accordion.menuItemTemplate; - } + @HostBinding('class.devui-accordion-menu-item') defaultClasses = true; @HostBinding('class.open') get open() { - return (this.keyOpen === undefined && this.accordion.autoOpenActiveMenu) - ? this.childActived - : this.keyOpen; + return this.keyOpen === undefined && this.accordion.autoOpenActiveMenu ? this.childActivated : this.keyOpen; + } + + @HostBinding('class.devui-router-active') + get routerLinkActivated() { + return this.accordionListFromView && this.accordionListFromView.routerLinkActivated; } + + @HostBinding('class.devui-has-active-item') + get hasActiveChildren() { + return this.accordionListFromView && this.accordionListFromView.hasActiveChildren; + } + get keyOpen() { return this.item && this.item[this.accordion.openKey]; } @@ -36,30 +38,43 @@ export class AccordionMenuComponent extends AccordionBaseComponent { + // list的parent与menu的item为同一数据,通过该属性匹配父子关系,避免互相嵌套导致循环依赖 + if (parent === this.item) { + // 延时赋值规避脏检查后值改变报错 + setTimeout(() => { + this.accordionListFromView = listInstance; + }); + } + }); + } + + ngOnDestroy(): void { + if (this.childListSub) { + this.childListSub.unsubscribe(); + } + } + toggle(event) { this.accordion.menuToggleFn({ item: this.item, open: !this.open, parent: this.parent, - event: event + event: event, }); } } diff --git a/devui/accordion/accordion.module.ts b/devui/accordion/accordion.module.ts index 5d75595e..d4edf122 100755 --- a/devui/accordion/accordion.module.ts +++ b/devui/accordion/accordion.module.ts @@ -7,12 +7,10 @@ import { AccordionItemComponent } from './accordion-item.component'; import { AccordionListComponent } from './accordion-list.component'; import { AccordionMenuComponent } from './accordion-menu.component'; import { AccordionComponent } from './accordion.component'; +import { AccordionService } from './accordion.service'; @NgModule({ - imports: [ - CommonModule, - RouterModule, - ], + imports: [CommonModule, RouterModule], declarations: [ AccordionComponent, AccordionListComponent, @@ -29,6 +27,6 @@ import { AccordionComponent } from './accordion.component'; AccordionItemHreflinkComponent, AccordionItemRouterlinkComponent, ], + providers: [AccordionService], }) - export class AccordionModule {} diff --git a/devui/accordion/accordion.service.ts b/devui/accordion/accordion.service.ts new file mode 100644 index 00000000..23642cb2 --- /dev/null +++ b/devui/accordion/accordion.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@angular/core'; +import { ReplaySubject } from 'rxjs'; + +@Injectable() +export class AccordionService { + childListSubject = new ReplaySubject(1); + childListObs = this.childListSubject.asObservable(); + + setChildListInstance(listInstance, parent) { + this.childListSubject.next({ listInstance, parent }); + } + + getChildListInstance() { + return this.childListObs; + } +} diff --git a/devui/accordion/demo/accordion-demo.moudule.ts b/devui/accordion/demo/accordion-demo.moudule.ts index 1db4906c..0966b219 100755 --- a/devui/accordion/demo/accordion-demo.moudule.ts +++ b/devui/accordion/demo/accordion-demo.moudule.ts @@ -28,7 +28,7 @@ import { TemplateComponent } from './template/template.component'; DevUICodeboxModule, DevUIApiModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: AccordionDemoComponent }, { path: 'api', diff --git a/devui/accordion/ng-package.json b/devui/accordion/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/accordion/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/accordion/package.json b/devui/accordion/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/accordion/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/accordion/public-api.ts b/devui/accordion/public-api.ts index 003abed3..bdc93c66 100755 --- a/devui/accordion/public-api.ts +++ b/devui/accordion/public-api.ts @@ -4,11 +4,10 @@ export * from './accordion-base-link-component.class'; export * from './accordion-item-hreflink.component'; export * from './accordion-item-routerlink.component'; export * from './accordion-item.component'; -export * from './accordion-list-token'; export * from './accordion-list.component'; -export * from './accordion-menu-token'; export * from './accordion-menu.component'; export * from './accordion-token'; export * from './accordion.component'; export * from './accordion.module'; +export * from './accordion.service'; export * from './accordion.type'; diff --git a/devui/alert/demo/alert-demo.module.ts b/devui/alert/demo/alert-demo.module.ts index 1f948999..f2d00a0a 100755 --- a/devui/alert/demo/alert-demo.module.ts +++ b/devui/alert/demo/alert-demo.module.ts @@ -23,7 +23,7 @@ import { WithoutIconComponent } from './withoutIcon/withoutIcon.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: AlertDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/alert/ng-package.json b/devui/alert/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/alert/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/alert/package.json b/devui/alert/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/alert/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/anchor/anchor-box.directive.ts b/devui/anchor/anchor-box.directive.ts index 51fdfc39..06cd03de 100755 --- a/devui/anchor/anchor-box.directive.ts +++ b/devui/anchor/anchor-box.directive.ts @@ -18,7 +18,7 @@ export class AnchorBoxDirective implements IAnchorBox, OnDestroy { }; @Input() defaultAnchor: string; @Input() scrollTarget: HTMLElement; - refreshAnchorMap: Subject = new Subject(); + refreshAnchorMap: Subject = new Subject(); anchorMap: { [anchor: string]: AnchorDirective; }; diff --git a/devui/anchor/demo/anchor-demo.module.ts b/devui/anchor/demo/anchor-demo.module.ts index 41d74725..57f6ac4c 100755 --- a/devui/anchor/demo/anchor-demo.module.ts +++ b/devui/anchor/demo/anchor-demo.module.ts @@ -30,7 +30,7 @@ import { ScrollTargetComponent } from './scroll-target/scroll-target.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: AnchorDemoComponent }, { path: 'api', diff --git a/devui/anchor/ng-package.json b/devui/anchor/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/anchor/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/anchor/package.json b/devui/anchor/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/anchor/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/animations/demo/animations-demo.module.ts b/devui/animations/demo/animations-demo.module.ts index 960b0393..5784e10f 100644 --- a/devui/animations/demo/animations-demo.module.ts +++ b/devui/animations/demo/animations-demo.module.ts @@ -33,7 +33,7 @@ import { WipeInOutComponent } from './wipe-in-out/wipe-in-out.component'; DevUICodeboxModule, TranslateModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: AnimationsDemoComponent }, { path: 'api', diff --git a/devui/auto-complete/auto-complete.directive.ts b/devui/auto-complete/auto-complete.directive.ts index 47609808..8a315da3 100755 --- a/devui/auto-complete/auto-complete.directive.ts +++ b/devui/auto-complete/auto-complete.directive.ts @@ -113,7 +113,7 @@ export class AutoCompleteDirective implements OnInit, OnDestroy, OnChanges, Cont KEYBOARD_EVENT_NOT_REFRESH = ['escape', 'enter', 'arrowup', 'arrowdown', /* ie 10 edge */ 'esc', 'up', 'down']; popupRef: ComponentRef; - private destroy$ = new Subject(); + private destroy$ = new Subject(); i18nText: I18nInterface['autoComplete']; popTipsText = ''; position: any; diff --git a/devui/auto-complete/demo/auto-complete-demo.module.ts b/devui/auto-complete/demo/auto-complete-demo.module.ts index 4e7f7509..d506d9b7 100755 --- a/devui/auto-complete/demo/auto-complete-demo.module.ts +++ b/devui/auto-complete/demo/auto-complete-demo.module.ts @@ -34,7 +34,7 @@ import { AutoDemoObjectComponent } from './object/auto-complete-demo-object.comp ButtonModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: AutoCompleteDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/auto-complete/ng-package.json b/devui/auto-complete/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/auto-complete/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/auto-complete/package.json b/devui/auto-complete/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/auto-complete/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/avatar/demo/avatar-demo.module.ts b/devui/avatar/demo/avatar-demo.module.ts index 9fd3b4bc..53faf5b6 100644 --- a/devui/avatar/demo/avatar-demo.module.ts +++ b/devui/avatar/demo/avatar-demo.module.ts @@ -23,7 +23,7 @@ import { SpecialComponent } from './special/special.component'; AvatarModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: AvatarDemoComponent }, { path: 'api', component: DevUIApiComponent, data: { diff --git a/devui/avatar/ng-package.json b/devui/avatar/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/avatar/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/avatar/package.json b/devui/avatar/package.json deleted file mode 100644 index 3b9bd979..00000000 --- a/devui/avatar/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } - \ No newline at end of file diff --git a/devui/back-top/demo/back-top-demo.module.ts b/devui/back-top/demo/back-top-demo.module.ts index df3bb93b..c1a9efd2 100644 --- a/devui/back-top/demo/back-top-demo.module.ts +++ b/devui/back-top/demo/back-top-demo.module.ts @@ -27,7 +27,7 @@ import { ScrollContainerComponent } from './scroll-container/scroll-container.co ToggleModule, BackTopModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: BackTopDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/back-top/ng-package.json b/devui/back-top/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/back-top/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/back-top/package.json b/devui/back-top/package.json deleted file mode 100644 index be79078b..00000000 --- a/devui/back-top/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} \ No newline at end of file diff --git a/devui/badge/demo/badge-demo.module.ts b/devui/badge/demo/badge-demo.module.ts index c2377239..f9536906 100644 --- a/devui/badge/demo/badge-demo.module.ts +++ b/devui/badge/demo/badge-demo.module.ts @@ -24,7 +24,7 @@ import { StatusComponent } from './status/status.component'; DevUICodeboxModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: BadgeDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/badge/ng-package.json b/devui/badge/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/badge/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/badge/package.json b/devui/badge/package.json deleted file mode 100644 index e7399223..00000000 --- a/devui/badge/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } \ No newline at end of file diff --git a/devui/breadcrumb/demo/breadcrumb-demo.module.ts b/devui/breadcrumb/demo/breadcrumb-demo.module.ts index d8723a69..99f09fdd 100644 --- a/devui/breadcrumb/demo/breadcrumb-demo.module.ts +++ b/devui/breadcrumb/demo/breadcrumb-demo.module.ts @@ -27,7 +27,7 @@ import { SourceConfigComponent } from './source-config/source-config.component'; DDemoNavModule, DropDownModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: BreadCrumbDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/breadcrumb/ng-package.json b/devui/breadcrumb/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/breadcrumb/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/breadcrumb/package.json b/devui/breadcrumb/package.json deleted file mode 100644 index 1971f0f5..00000000 --- a/devui/breadcrumb/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } \ No newline at end of file diff --git a/devui/button/demo/button-demo.module.ts b/devui/button/demo/button-demo.module.ts index 18e69b6f..adf74f33 100755 --- a/devui/button/demo/button-demo.module.ts +++ b/devui/button/demo/button-demo.module.ts @@ -32,7 +32,7 @@ import { TextComponent } from './text/text.component'; DDemoNavModule, DropDownModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: ButtonDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/button/ng-package.json b/devui/button/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/button/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/button/package.json b/devui/button/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/button/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/card/card.component.scss b/devui/card/card.component.scss index 7df4b86a..a74993a4 100644 --- a/devui/card/card.component.scss +++ b/devui/card/card.component.scss @@ -2,6 +2,7 @@ @import '../style/theme/shadow'; @import '../style/theme/corner'; @import '../style/core/_font'; +@import '../style/core/animation'; $card-ele-space: var(--card-ele-space, 8px); $card-block-space: var(--card-block-space, 16px); @@ -16,6 +17,18 @@ $card-content-font-size: $devui-font-size; padding: 16px 20px; border-radius: $card-border-radius; box-shadow: $devui-shadow-length-base $devui-light-shadow; + + &.devui-card-interactive { + cursor: pointer; + transition: + box-shadow $devui-animation-duration-slow $devui-animation-ease-in-out-smooth, + transform $devui-animation-duration-slow $devui-animation-ease-in-out-smooth; + + &:hover { + box-shadow: $devui-shadow-length-hover $devui-light-shadow; + transform: translateY(-5px); + } + } } .devui-card-title { diff --git a/devui/card/card.component.ts b/devui/card/card.component.ts index a42ba26f..6ed86524 100644 --- a/devui/card/card.component.ts +++ b/devui/card/card.component.ts @@ -1,26 +1,17 @@ -import { - ChangeDetectionStrategy, - Component, - Directive, - HostBinding, - Input, - ViewEncapsulation -} from '@angular/core'; +import { ChangeDetectionStrategy, Component, Directive, HostBinding, Input, ViewEncapsulation } from '@angular/core'; @Directive({ - selector: 'd-card-content, [dCardContent]' + selector: 'd-card-content, [dCardContent]', }) export class CardContentDirective { @HostBinding('class.devui-card-content') default = true; - } @Directive({ - selector: `d-card-title, [dCardTitle]` + selector: `d-card-title, [dCardTitle]`, }) export class CardTitleDirective { @HostBinding('class.devui-card-title') default = true; - } @Directive({ @@ -49,14 +40,14 @@ export class CardActionsDirective { @Directive({ selector: '[dCardMeta]', - exportAs: 'dCardMeta' + exportAs: 'dCardMeta', }) export class CardMetaDirective { @HostBinding('class.devui-card-meta') default = true; } @Directive({ - selector: '[dCardAvatar]' + selector: '[dCardAvatar]', }) export class CardAvatarDirective { @HostBinding('class.devui-card-avatar') default = true; @@ -72,6 +63,7 @@ export class CardAvatarDirective { }) export class CardComponent { @HostBinding('class.devui-card') default = true; + @Input() @HostBinding('class.devui-card-interactive') interactive: boolean; } @Component({ diff --git a/devui/card/demo/basic/basic.component.scss b/devui/card/demo/basic/basic.component.scss index c71b17d1..a5e8dd86 100644 --- a/devui/card/demo/basic/basic.component.scss +++ b/devui/card/demo/basic/basic.component.scss @@ -15,18 +15,6 @@ margin-right: 16px; } -d-card { - cursor: pointer; - transition: - box-shadow $devui-animation-duration-slow $devui-animation-ease-in-out-smooth, - transform $devui-animation-duration-slow $devui-animation-ease-in-out-smooth; - - &:hover { - box-shadow: $devui-shadow-length-hover $devui-light-shadow; - transform: translateY(-5px); - } -} - .card-container { width: 350px; } diff --git a/devui/card/demo/card-demo.component.html b/devui/card/demo/card-demo.component.html index 17733279..23ca40ad 100644 --- a/devui/card/demo/card-demo.component.html +++ b/devui/card/demo/card-demo.component.html @@ -9,6 +9,13 @@
+
+
{{ 'components.card.cardInteractiveDemo.title' | translate }}
+ + + +
+
{{ 'components.card.mediaDemo.title' | translate }}
{{ 'components.card.mediaDemo.description' | translate }}
diff --git a/devui/card/demo/card-demo.component.ts b/devui/card/demo/card-demo.component.ts index 3531ad1e..86b1bea0 100644 --- a/devui/card/demo/card-demo.component.ts +++ b/devui/card/demo/card-demo.component.ts @@ -8,6 +8,12 @@ import { Subscription } from 'rxjs'; templateUrl: './card-demo.component.html', }) export class CardDemoComponent implements OnInit, OnDestroy { + cardInteractiveSourceData: Array = [ + { title: 'HTML', language: 'xml', code: require('./card-interactive/card-interactive.component.html?raw') }, + { title: 'TS', language: 'typescript', code: require('./card-interactive/card-interactive.component.ts?raw') }, + { title: 'SCSS', language: 'scss', code: require('./card-interactive/card-interactive.component.scss?raw') }, + ]; + CardDemoBasic: Array = [ { title: 'HTML', language: 'xml', code: require('./basic/basic.component.html?raw') }, { title: 'TS', language: 'typescript', code: require('./basic/basic.component.ts?raw') }, @@ -46,6 +52,7 @@ export class CardDemoComponent implements OnInit, OnDestroy { setNavValues(values) { this.navItems = [ { dAnchorLink: 'card-basic', value: values['card-basic'] }, + { dAnchorLink: 'card-interactive-usage', value: values['card-interactive-usage'] }, { dAnchorLink: 'card-with-media', value: values['card-with-media'] }, { dAnchorLink: 'card-custom', value: values['card-custom'] }, ]; diff --git a/devui/card/demo/card-demo.module.ts b/devui/card/demo/card-demo.module.ts index 6e83e42b..bbf5ae6d 100644 --- a/devui/card/demo/card-demo.module.ts +++ b/devui/card/demo/card-demo.module.ts @@ -13,9 +13,10 @@ import { BasicComponent } from './basic/basic.component'; import { CardDemoComponent } from './card-demo.component'; import { CustomComponent } from './custom/custom.component'; import { WithMediaComponent } from './with-media/with-media.component'; +import { CardInteractiveComponent } from './card-interactive/card-interactive.component'; @NgModule({ - declarations: [CardDemoComponent, BasicComponent, CustomComponent, WithMediaComponent], + declarations: [CardDemoComponent, BasicComponent, CustomComponent, WithMediaComponent, CardInteractiveComponent], imports: [ TranslateModule, CommonModule, @@ -26,7 +27,7 @@ import { WithMediaComponent } from './with-media/with-media.component'; AvatarModule, ButtonModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: CardDemoComponent }, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/card/demo/card-interactive/card-interactive.component.html b/devui/card/demo/card-interactive/card-interactive.component.html new file mode 100644 index 00000000..5934c0a6 --- /dev/null +++ b/devui/card/demo/card-interactive/card-interactive.component.html @@ -0,0 +1,16 @@ + + + + DEVUI Course + DevUI + + + DEVUI is a free open-source and common solution for the front end of enterprise mid- and back-end products. Its design values are based + on... + + +
12
+
8
+
8
+
+
diff --git a/devui/card/demo/card-interactive/card-interactive.component.scss b/devui/card/demo/card-interactive/card-interactive.component.scss new file mode 100644 index 00000000..a5e8dd86 --- /dev/null +++ b/devui/card/demo/card-interactive/card-interactive.component.scss @@ -0,0 +1,20 @@ +@import '~ng-devui/styles-var/devui-var.scss'; + +.card-icon { + cursor: pointer; + font-size: $devui-font-size-icon; + margin-right: 8px; + vertical-align: middle; +} + +.card-icon + span { + vertical-align: middle; +} + +.card-block { + margin-right: 16px; +} + +.card-container { + width: 350px; +} diff --git a/devui/card/demo/card-interactive/card-interactive.component.ts b/devui/card/demo/card-interactive/card-interactive.component.ts new file mode 100644 index 00000000..6603dbe3 --- /dev/null +++ b/devui/card/demo/card-interactive/card-interactive.component.ts @@ -0,0 +1,12 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'd-card-card-interactive', + templateUrl: './card-interactive.component.html', + styleUrls: ['./card-interactive.component.scss'], +}) +export class CardInteractiveComponent implements OnInit { + constructor(){} + + ngOnInit(): void {} +} diff --git a/devui/card/demo/custom/custom.component.scss b/devui/card/demo/custom/custom.component.scss index eb16fcc6..4298a0c8 100644 --- a/devui/card/demo/custom/custom.component.scss +++ b/devui/card/demo/custom/custom.component.scss @@ -14,18 +14,6 @@ } } -d-card { - cursor: pointer; - transition: - box-shadow $devui-animation-duration-slow $devui-animation-ease-in-out-smooth, - transform $devui-animation-duration-slow $devui-animation-ease-in-out-smooth; - - &:hover { - box-shadow: $devui-shadow-length-hover $devui-light-shadow; - transform: translateY(-5px); - } -} - .custom-avatar { display: flex; justify-content: space-between; diff --git a/devui/card/demo/with-media/with-media.component.scss b/devui/card/demo/with-media/with-media.component.scss index 246f6047..4ff09511 100644 --- a/devui/card/demo/with-media/with-media.component.scss +++ b/devui/card/demo/with-media/with-media.component.scss @@ -20,15 +20,3 @@ .card-block { margin-right: 16px; } - -d-card { - cursor: pointer; - transition: - box-shadow $devui-animation-duration-slow $devui-animation-ease-in-out-smooth, - transform $devui-animation-duration-slow $devui-animation-ease-in-out-smooth; - - &:hover { - box-shadow: $devui-shadow-length-hover $devui-light-shadow; - transform: translateY(-5px); - } -} diff --git a/devui/card/doc/api-cn.md b/devui/card/doc/api-cn.md index 110e3adf..e787d5d7 100644 --- a/devui/card/doc/api-cn.md +++ b/devui/card/doc/api-cn.md @@ -1,6 +1,6 @@ # 如何使用 -在module中引入: +在 module 中引入: ```ts import { CardModule } from 'ng-devui/card'; @@ -18,8 +18,10 @@ import { CardModule } from 'ng-devui/card'; ``` -# d-card -## d-card 区块划分 + +## d-card + +### d-card 区块划分 | 标签 | 描述 | | :------------: | :--------------------------------------------------------------------------------------------: | @@ -28,7 +30,13 @@ import { CardModule } from 'ng-devui/card'; | d-card-content | 辅助信息区,分析和支撑标题作用,可以包含摘要或者说明。 | | d-card-actions | 决策作用,可以包含操作文本或者操作图标。 | -## d-card-header 区块划分 +### d-card 参数 + +| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | 全局配置项 | +| :---------: | :-------: | :----: | :------------------: | :---------------------------------------- | ---------- | +| interactive | `boolean` | -- | 可选,卡片是否可交互 | [可交互卡片](demo#card-interactive-usage) | | + +### d-card-header 区块划分 | 标签 | 描述 | | :-------------: | :------------------------------------: | @@ -36,8 +44,8 @@ import { CardModule } from 'ng-devui/card'; | [dCardAvatar] | 头像区域,用作头像等图片展示 | | d-card-subtitle | 对标题的补充,可包含标签等信息 | -## d-card-actions 参数 +### d-card-actions 参数 -| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo |全局配置项| -| :----------------: | :---: | :------: | :---: | :-------------: | --------- | -| align | `'start' \| 'end' \|'spaceBetween'` | 'start' | 可选,操作区域对齐方式,分别对应起始对齐,尾部对齐,拉伸对齐 | [基本用法](demo#card-basic) | +| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | 全局配置项 | +| :---: | :---------------------------------: | :-----: | :----------------------------------------------------------: | :-------------------------: | ---------- | +| align | `'start' \| 'end' \|'spaceBetween'` | 'start' | 可选,操作区域对齐方式,分别对应起始对齐,尾部对齐,拉伸对齐 | [基本用法](demo#card-basic) | diff --git a/devui/card/doc/api-en.md b/devui/card/doc/api-en.md index 4f74b6cc..da3ceb9f 100644 --- a/devui/card/doc/api-en.md +++ b/devui/card/doc/api-en.md @@ -18,26 +18,34 @@ In the page: ``` -# d-card -## d-card Block Division -| Tag | Description | -| :------------: | :--------------------------------------------------------------------------------------------: | -| d-card-header | Title area, which is used as an overview. It usually contains elements such as title `d-card-title`, subtitle `d-card-subtitle`, and avatar `dAvatar` | -| [dCardMeta] | Media information area, which can store multiple media, including pictures, graphics, and videos | -| d-card-content | Auxiliary information area, which analyzes and supports the title function. It can contain abstracts or descriptions | -| d-card-actions | Decision-making function, which can contain operation text or operation icons | +## d-card -## d-card-header Block Division +### d-card Block Division -| Tag | Description | -| :-------------: | :------------------------------------: | -| d-card-title | Card content description, which is generally defined as the card name | -| [dCardAvatar] | Avatar area, which is used to display images such as avatars | -| d-card-subtitle | Supplement to the title, including tag information | +| Tag | Description | +| :------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------: | +| d-card-header | Title area, which is used as an overview. It usually contains elements such as title `d-card-title`, subtitle `d-card-subtitle`, and avatar `dAvatar` | +| [dCardMeta] | Media information area, which can store multiple media, including pictures, graphics, and videos | +| d-card-content | Auxiliary information area, which analyzes and supports the title function. It can contain abstracts or descriptions | +| d-card-actions | Decision-making function, which can contain operation text or operation icons | -## d-card-actions Parameter +### d-card 参数 -| Parameter | Type | Default | Description | Jump to Demo |Global Config| -| :----------------: | :---: | :------: | :---: | :-------------: | --------- | -| align | `'start'\|'end'\|'spaceBetween'` | 'start' | Optional. Operation area alignment mode, which corresponds to start alignment, tail alignment, and stretch alignment | [Basic usage](demo#card-basic) | +| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | 全局配置项 | +| :---------: | :-------: | :----: | :---------------------------------------: | :---------------------------------------------- | ---------- | +| interactive | `boolean` | -- | Optional, whether the card is interactive | [Interactive Card](demo#card-interactive-usage) | | + +### d-card-header Block Division + +| Tag | Description | +| :-------------: | :-------------------------------------------------------------------: | +| d-card-title | Card content description, which is generally defined as the card name | +| [dCardAvatar] | Avatar area, which is used to display images such as avatars | +| d-card-subtitle | Supplement to the title, including tag information | + +### d-card-actions Parameter + +| Parameter | Type | Default | Description | Jump to Demo | Global Config | +| :-------: | :------------------------------: | :-----: | :------------------------------------------------------------------------------------------------------------------: | :----------------------------: | ------------- | +| align | `'start'\|'end'\|'spaceBetween'` | 'start' | Optional. Operation area alignment mode, which corresponds to start alignment, tail alignment, and stretch alignment | [Basic usage](demo#card-basic) | diff --git a/devui/card/ng-package.json b/devui/card/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/card/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/card/package.json b/devui/card/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/card/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/carousel/carousel.component.html b/devui/carousel/carousel.component.html index 18d41418..637e519b 100644 --- a/devui/carousel/carousel.component.html +++ b/devui/carousel/carousel.component.html @@ -44,6 +44,8 @@ (mouseenter)="switchStep(index, 'hover')" [ngClass]="{ active: activeIndex === index }" *ngFor="let item of items; let index = index" - > + > + +
diff --git a/devui/carousel/carousel.component.scss b/devui/carousel/carousel.component.scss index acfbfec9..a9119497 100644 --- a/devui/carousel/carousel.component.scss +++ b/devui/carousel/carousel.component.scss @@ -1,6 +1,7 @@ @import '../style/theme/color'; @import '../style/theme/shadow'; @import '../style/core/animation'; +@import '../style/theme/corner'; @mixin fixed-arrow-button() { position: absolute; @@ -82,19 +83,34 @@ .dot-item { width: 6px; height: 6px; - border-radius: 3px; + border-radius: $devui-border-radius-feedback; margin-right: 8px; background: $devui-icon-fill; + cursor: pointer; + + .dot-item-active-progress { + width: 0; + display: inline-block; + position: absolute; + } &:hover { - cursor: pointer; background: $devui-icon-fill-hover; } &.active { width: 24px; - background: $devui-icon-fill-active; - transition: all $devui-animation-duration-slow $devui-animation-ease-in-out-smooth; + background-color: $devui-icon-fill; + transition: all $devui-animation-duration-fast $devui-animation-ease-in-out-smooth; + + .dot-item-active-progress { + width: 24px; + height: 6px; + background-color: $devui-icon-fill-active; + border-radius: $devui-border-radius-feedback; + transition-property: width; + transition-timing-function: $devui-animation-ease-out; + } } } } diff --git a/devui/carousel/carousel.component.ts b/devui/carousel/carousel.component.ts index a4a5222c..30aa573c 100644 --- a/devui/carousel/carousel.component.ts +++ b/devui/carousel/carousel.component.ts @@ -13,7 +13,7 @@ import { Output, QueryList, Renderer2, - SimpleChanges + SimpleChanges, } from '@angular/core'; import { CarouselItemComponent } from './carousel-item.component'; diff --git a/devui/carousel/demo/carousel-demo.component.html b/devui/carousel/demo/carousel-demo.component.html index 525f44d7..9d6ed64e 100644 --- a/devui/carousel/demo/carousel-demo.component.html +++ b/devui/carousel/demo/carousel-demo.component.html @@ -28,5 +28,11 @@
+
+
{{ 'components.carousel.withTransitionProgressDemo.title' | translate }}
+ + + +
diff --git a/devui/carousel/demo/carousel-demo.component.ts b/devui/carousel/demo/carousel-demo.component.ts index 6704d066..40be18fb 100644 --- a/devui/carousel/demo/carousel-demo.component.ts +++ b/devui/carousel/demo/carousel-demo.component.ts @@ -1,4 +1,5 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; +import { DevuiSourceData } from 'ng-devui/shared/devui-codebox/devui-source-data'; import { TranslateService, TranslationChangeEvent } from '@ngx-translate/core'; import { Subscription } from 'rxjs'; @@ -7,6 +8,11 @@ import { Subscription } from 'rxjs'; templateUrl: './carousel-demo.component.html', }) export class CarouselDemoComponent implements OnInit, OnDestroy { + withTransitionProgressSourceData: Array = [ + { title: 'HTML', language: 'xml', code: require('./with-transition-progress/with-transition-progress.component.html?raw') }, + { title: 'TS', language: 'typescript', code: require('./with-transition-progress/with-transition-progress.component.ts?raw') }, + ]; + CarouselBasicComponent = [ { title: 'HTML', language: 'html', code: require('./basic/carousel-demo-basic.component.html?raw') }, { title: 'TS', language: 'typescript', code: require('./basic/carousel-demo-basic.component.ts?raw') }, @@ -52,6 +58,7 @@ export class CarouselDemoComponent implements OnInit, OnDestroy { { dAnchorLink: 'trigger-usage', value: values['trigger-usage'] }, { dAnchorLink: 'autoplay-usage', value: values['autoplay-usage'] }, { dAnchorLink: 'custom-usage', value: values['custom-usage'] }, + { dAnchorLink: 'with-transition-progress-usage', value: values['with-transition-progress-usage'] }, ]; } diff --git a/devui/carousel/demo/carousel-demo.module.ts b/devui/carousel/demo/carousel-demo.module.ts index 09613bac..f854d05f 100644 --- a/devui/carousel/demo/carousel-demo.module.ts +++ b/devui/carousel/demo/carousel-demo.module.ts @@ -14,6 +14,7 @@ import { CarouselDemoBasicComponent } from './basic/carousel-demo-basic.componen import { CarouselDemoComponent } from './carousel-demo.component'; import { CarouselDemoCustomComponent } from './custom/carousel-demo-custom.component'; import { CarouselDemoTriggerComponent } from './trigger/carousel-demo-trigger.component'; +import { WithTransitionProgressComponent } from './with-transition-progress/with-transition-progress.component'; @NgModule({ imports: [ @@ -26,7 +27,7 @@ import { CarouselDemoTriggerComponent } from './trigger/carousel-demo-trigger.co DDemoNavModule, ButtonModule, RouterModule.forChild([ - {path: '', redirectTo: 'demo'}, + {path: '', redirectTo: 'demo', pathMatch: 'full'}, {path: 'demo', component: CarouselDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { @@ -42,7 +43,8 @@ import { CarouselDemoTriggerComponent } from './trigger/carousel-demo-trigger.co CarouselDemoBasicComponent, CarouselDemoTriggerComponent, CarouselDemoAutoPlayComponent, - CarouselDemoCustomComponent + CarouselDemoCustomComponent, + WithTransitionProgressComponent ], }) export class CarouselDemoModule { diff --git a/devui/carousel/demo/custom/carousel-demo-custom.component.html b/devui/carousel/demo/custom/carousel-demo-custom.component.html index 80949212..7e46fa75 100644 --- a/devui/carousel/demo/custom/carousel-demo-custom.component.html +++ b/devui/carousel/demo/custom/carousel-demo-custom.component.html @@ -1,8 +1,10 @@ - {{ 'page ' + i }} + +
you can write your own dom here {{ i }}
+
+ 第一张 上一张 - 下一张 - 第一张 + 下一张
diff --git a/devui/carousel/demo/with-transition-progress/with-transition-progress.component.html b/devui/carousel/demo/with-transition-progress/with-transition-progress.component.html new file mode 100644 index 00000000..1f4c8bcf --- /dev/null +++ b/devui/carousel/demo/with-transition-progress/with-transition-progress.component.html @@ -0,0 +1,3 @@ + + {{ 'page ' + i }} + diff --git a/devui/carousel/demo/with-transition-progress/with-transition-progress.component.ts b/devui/carousel/demo/with-transition-progress/with-transition-progress.component.ts new file mode 100644 index 00000000..010ce4e6 --- /dev/null +++ b/devui/carousel/demo/with-transition-progress/with-transition-progress.component.ts @@ -0,0 +1,21 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'd-carousel-with-transition-progress', + templateUrl: './with-transition-progress.component.html', + styleUrls: ['../demo-common.scss'], +}) +export class WithTransitionProgressComponent implements OnInit { + array = [1, 2, 3, 4]; + height = '200px'; + activeIndex = 0; + + getIndex(index) { + console.log(this.activeIndex); + console.log(index); + } + + constructor() {} + + ngOnInit(): void {} +} diff --git a/devui/carousel/doc/api-cn.md b/devui/carousel/doc/api-cn.md index 75a0d390..f73eaec9 100644 --- a/devui/carousel/doc/api-cn.md +++ b/devui/carousel/doc/api-cn.md @@ -14,29 +14,29 @@ import { CarouselModule } from 'ng-devui/carousel'; ``` -# d-carousel +## d-carousel -## d-carousel 参数 +### d-carousel 参数 | 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | 全局配置项 | | :-------------: | :--------------------------: | :------: | :----------------------------------------------------------------: | :------------------------------------ | ---------- | | arrowTrigger | `'hover'\|'never'\|'always'` | 'hover' | 可选,指定切换箭头显示方式 | [指示器&切换箭头](demo#trigger-usage) | | autoplay | `boolean` | false | 可选,是否自动轮播 | [自动轮播](demo#autoplay-usage) | | autoplaySpeed | `number` | 3000 | 可选,配合`autoplay`使用,自动轮播速度,单位 ms | [自动轮播](demo#autoplay-usage) | -| transitionSpeed | `number` | 500 | 可选,卡片切换动画速度,单位 ms | [自动轮播](demo#autoplay-usage) | +| transitionSpeed | `number` | 500 | 可选,卡片切换动画速度,单位 ms | [自动轮播](demo#autoplay-usage) | | height | `string` | '100%' | 可选,轮播容器高度 | [基本用法](demo#basic-usage) | | showDots | `boolean` | true | 可选,是否显示面板指示器 | [自动轮播](demo#autoplay-usage) | | dotPosition | `'top'\|'bottom'` | 'bottom' | 可选,面板指示器位置 | [指示器&切换箭头](demo#trigger-usage) | | dotTrigger | `'click'\|'hover'` | 'click' | 可选,指示器触发轮播方式 | [指示器&切换箭头](demo#trigger-usage) | | activeIndex | `number` | 0 | 可选,初始化激活卡片索引,从 0 开始,支持`[(activeIndex)]`双向绑定 | [基本用法](demo#basic-usage) | -## d-carousel 事件 +### d-carousel 事件 | 事件 | 类型 | 描述 | 跳转 Demo | | :---------------: | :--------------------: | :---------------------------------------: | ---------------------------- | | activeIndexChange | `EventEmitter` | 卡片切换时,返回当前卡片的索引,从 0 开始 | [基本用法](demo#basic-usage) | -## d-carousel 方法 +### d-carousel 方法 | 方法 | 描述 | 跳转 Demo | | :---------: | :---------------------------------- | :------------------------------ | diff --git a/devui/carousel/ng-package.json b/devui/carousel/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/carousel/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/carousel/package.json b/devui/carousel/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/carousel/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/cascader/cascader-li.component.ts b/devui/cascader/cascader-li.component.ts index 32362491..fd088572 100644 --- a/devui/cascader/cascader-li.component.ts +++ b/devui/cascader/cascader-li.component.ts @@ -26,7 +26,7 @@ export class CascaderLiComponent implements OnInit, OnDestroy { halfCheck: boolean; active: boolean; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); @HostListener('click', ['$event']) onClick(event: Event) { diff --git a/devui/cascader/cascader.component.ts b/devui/cascader/cascader.component.ts index 22fea4a8..bc51a9ae 100644 --- a/devui/cascader/cascader.component.ts +++ b/devui/cascader/cascader.component.ts @@ -76,7 +76,7 @@ export class CascaderComponent implements OnInit, OnDestroy, OnChanges, ControlV isLazyLoad: boolean; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); searchValueChange = new Subject(); diff --git a/devui/cascader/demo/cascader-demo.module.ts b/devui/cascader/demo/cascader-demo.module.ts index 83213735..5b3296bb 100644 --- a/devui/cascader/demo/cascader-demo.module.ts +++ b/devui/cascader/demo/cascader-demo.module.ts @@ -31,7 +31,7 @@ import { TemplateCascaderComponent } from './template-cascader/template-cascader ButtonModule, TabsModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: CascaderDemoComponent }, { path: 'api', diff --git a/devui/cascader/ng-package.json b/devui/cascader/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/cascader/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/cascader/package.json b/devui/cascader/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/cascader/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/category-search/category-search.component.html b/devui/category-search/category-search.component.html index 3e8916cd..01fc7184 100644 --- a/devui/category-search/category-search.component.html +++ b/devui/category-search/category-search.component.html @@ -73,16 +73,16 @@ (keydown.backspace)="backspaceEvent(inputDropdown)" (keydown.enter)="searchInputValue($event); closeMenu(inputDropdown)" (focus)="isHover = false; isFocus = true" - (blur)="isFocus = false; blurInput()" + (blur)="isFocus = false; blurInput($event)" />
-
    +
    • @@ -122,7 +122,7 @@
      {{ showSearchConfig.categoryDescription }}
      -
        +
        • - {{ i18nCategorySearchText?.saveFilter }} + {{ textConfig.createFilter }}
          - {{ i18nCategorySearchText?.saveFilter }} + {{ textConfig.createFilter }}
          - {{ i18nCategorySearchText?.filterTitle }} + {{ textConfig.filterTitle }}
          ; // 用户配置组顺序 @Input() customGroupNameTemplate: TemplateRef; // 用户自定义组名称显示模板 @Input() tagMaxWidth: number; + @Input() textConfig = { + keywordName: '', + createFilter: '', + filterTitle: '', + }; @Input() filterNameRules: DValidateRules = []; @Input() beforeTagChange: (tag, searchKey, operation) => boolean | Promise | Observable; @Input() toggleEvent: (dropdown, tag?, currentSelectTag?) => void; @@ -70,9 +76,9 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI @Output() createFilterEvent = new EventEmitter(); @Output() clearAllEvent = new EventEmitter(); @Output() searchKeyChange = new EventEmitter(); - @ViewChild('InputEle') inputEle: ElementRef; - @ViewChild('ScrollBarContainer') scrollBarContainer: ElementRef; - @ViewChild('PrimeContainer') primeContainer: ElementRef; + @ViewChild('InputEle', { static: true }) inputEle: ElementRef; + @ViewChild('ScrollBarContainer', { static: true }) scrollBarContainer: ElementRef; + @ViewChild('PrimeContainer', { static: true }) primeContainer: ElementRef; @ViewChildren('selectedDropdown') selectedDropdownList: QueryList; @ViewChildren(DatepickerProCalendarComponent, { read: ElementRef }) datePickerElements: QueryList; @ViewChildren(DefaultTemplateDirective) defaultTemplates: QueryList; @@ -93,13 +99,14 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI noRecord = false; showNoDataTips = false; icons = DefaultIcons; - destroy$ = new Subject(); + destroy$ = new Subject(); i18nCommonText: I18nInterface['common']; i18nCategorySearchText: I18nInterface['categorySearch']; currentSearchCategory: Array; categoryDisplay: Array; currentOpenDropdown: DropDownDirective; currentScrollTagIndex: number; // 当前要滚动至的标签索引 + blurTimer: any; // 失焦关闭下拉延时器,失焦后立刻展开下拉需清除该延时 scrollTimeout: any; // 如果标签在可视范围内则延时展开下拉的定时器 scrollToTailFlag = true; // 是否在更新标签内容后滚动至输入框的开关 DROPDOWN_ANIMATION_TIMEOUT = 200; // 下拉动画延迟 @@ -119,30 +126,27 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI this.document = this.doc; this.dateConverter = new DefaultDateConverter(); this.id = CategorySearchComponent.ID_SEED++; + this.showSearchConfig = { keyword: true, field: true, category: true }; this.setI18nText(); - this.showSearchConfig = { - keyword: true, - keywordDescription: this.i18nCategorySearchText.getSearchMessage, - field: true, - fieldDescription: this.i18nCategorySearchText.getFindingMessage, - category: true, - categoryDescription: this.i18nCategorySearchText.selectFilterCondition, - }; } ngOnChanges(changes: SimpleChanges): void { - if (changes['defaultSearchField'] || changes['category'] || changes['selectedTags']) { + const { defaultSearchField, category, selectedTags, searchKey, showSearchCategory, tagMaxWidth, textConfig } = changes; + if (defaultSearchField || category || selectedTags) { this.init(); } - if (changes['searchKey']) { + if (searchKey) { this.setSearchKeyTag(); } - if (changes['showSearchCategory']) { + if (showSearchCategory) { this.setSearchShow(); } - if (changes['tagMaxWidth']) { + if (tagMaxWidth) { this.setTagsMaxWidth(); } + if (textConfig) { + this.setI18nAndFilterText(this.i18n.getI18nText()); + } } ngAfterViewInit() { @@ -171,7 +175,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI // 300毫秒内不再触发滚动事件则展开下拉列表 debounceTime(this.DELAY) ) - .subscribe((event) => this.openCurrentScrollTagMenu(event)); + .subscribe((event: Event) => this.openCurrentScrollTagMenu(event)); } } @@ -201,21 +205,29 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } setI18nText() { - this.i18nCommonText = this.i18n.getI18nText().common; - this.i18nCategorySearchText = this.i18n.getI18nText().categorySearch; + this.setI18nAndFilterText(this.i18n.getI18nText()); this.i18n .langChange() .pipe(takeUntil(this.destroy$)) - .subscribe((data) => { - this.i18nCommonText = data.common; - this.i18nCategorySearchText = data.categorySearch; - // 关键字分类内文本不能随语言对象变化,需重新赋值 - const [keyword] = this.selectedTags.filter((item) => item.field === 'devuiCategorySearchKeyword'); - if (keyword) { - keyword.label = this.i18nCategorySearchText['keyword']; - keyword.title = `${keyword.label}:${keyword.value?.label}`; - } - }); + .subscribe((data) => this.setI18nAndFilterText(data)); + } + + setI18nAndFilterText(data) { + this.i18nCommonText = data.common; + this.i18nCategorySearchText = data.categorySearch; + this.textConfig.createFilter = this.textConfig.createFilter || this.i18nCategorySearchText?.saveFilter; + this.textConfig.filterTitle = this.textConfig.filterTitle || this.i18nCategorySearchText?.filterTitle; + this.showSearchConfig.keywordDescription = + this.showSearchCategory['keywordDescription'] || this.i18nCategorySearchText.getSearchMessage; + this.showSearchConfig.fieldDescription = this.showSearchCategory['fieldDescription'] || this.i18nCategorySearchText.getFindingMessage; + this.showSearchConfig.categoryDescription = + this.showSearchCategory['categoryDescription'] || this.i18nCategorySearchText.selectFilterCondition; + // 关键字分类内文本不能随语言对象变化,需重新赋值 + const keyword = this.selectedTags.find((item) => item.field === 'devuiCategorySearchKeyword'); + if (keyword) { + keyword.label = this.textConfig.keywordName || this.i18nCategorySearchText['keyword']; + keyword.title = `${keyword.label}:${keyword.value?.label}`; + } } // 插入tag max-width 样式控制是否显示省略号 @@ -243,7 +255,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI setSearchKeyTag() { const result = this.selectedTags.filter((item) => item.field !== 'devuiCategorySearchKeyword'); if (this.searchKey && !this.currentSelectTag) { - const label = this.i18nCategorySearchText['keyword']; + const label = this.textConfig.keywordName || this.i18nCategorySearchText['keyword']; const searchKeyTag = { options: [], field: 'devuiCategorySearchKeyword', @@ -304,13 +316,19 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI return item; } + mergeCheck(objValue, srcValue, key) { + if (key === 'options' && objValue !== srcValue) { + return srcValue; + } + } + setValue(data, isSelectedTags = false) { if (Array.isArray(data) && data.length) { data.forEach((item) => { if (isSelectedTags) { let result = ''; const originItem = this.category.find((categoryItem) => categoryItem.field === item.field); - merge(item, originItem); + mergeWith(item, originItem, this.mergeCheck); if (item.value.value) { item.value.cache = cloneDeep(item.value.value); result = this.joinLabelTypes.includes(item.type) ? this.getItemValue(item.value.value, item.filterKey || 'label') : ''; @@ -451,7 +469,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } } - openCurrentScrollTagMenu(event) { + openCurrentScrollTagMenu(event: Event) { if (this.currentScrollTagIndex !== undefined) { const dropdownArr = this.selectedDropdownList.toArray(); this.openMenu(dropdownArr[this.currentScrollTagIndex], event); @@ -494,13 +512,14 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } tag = this.resetValue(tag); this.selectedTags = this.selectedTags.filter((item) => item.field !== tag.field); - if (tag.type !== 'keyword') { - this.selectedTagsChange.emit({ selectedTags: this.selectedTags, currentChangeTag: tag, operation: 'delete' }); - this.resolveCategoryDisplay(tag, 'add'); - } else { + if (tag.type === 'keyword') { this.searchKey = this.searchKey === this.searchKeyCache ? '' : this.searchKey; this.searchKeyCache = ''; - this.searchEvent.emit({ selectedTags: this.selectedTags, searchKey: '' }); + this.enterSearch = this.searchKey !== ''; + this.searchEvent.emit({ selectedTags: this.selectedTags, searchKey: this.searchKey }); + } else { + this.resolveCategoryDisplay(tag, 'add'); + this.selectedTagsChange.emit({ selectedTags: this.selectedTags, currentChangeTag: tag, operation: 'delete' }); } this.currentSelectTag = undefined; }); @@ -523,16 +542,19 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // 失焦时关闭当前下拉列表,延时用以防止关闭掉点击分类展开的内容列表 - blurInput() { - setTimeout(() => { - if (!this.currentSelectTag && this.currentOpenDropdown) { + blurInput(event: FocusEvent) { + this.blurTimer = setTimeout(() => { + const className = event.relatedTarget && event.relatedTarget['className']; + const outsideHost = !className || className.indexOf(`devui-category-dropdown-menu-${this.id}`) === -1; + if (!this.currentSelectTag && this.currentOpenDropdown && outsideHost) { this.currentOpenDropdown.isOpen = false; } }, this.DELAY); } - openMenu(inputDropdown: DropDownDirective, event) { - if (inputDropdown.isOpen || (event.type === 'keyup' && (event.code === 'Enter' || event.code === 'Backspace'))) { + openMenu(inputDropdown: DropDownDirective, event: Event) { + const code = event['code']; + if (inputDropdown.isOpen || (event.type === 'keyup' && ['Enter', 'Backspace', 'Escape'].includes(code))) { return; } setTimeout(() => { @@ -548,7 +570,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } } - backspaceEvent(inputDropdown) { + backspaceEvent(inputDropdown: DropDownDirective) { if (this.searchKey) { return; } @@ -557,20 +579,12 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI this.closeMenu(inputDropdown); return; } - this.canChange(this.selectedTags[this.selectedTags.length - 1], 'delete').then((val) => { - if (!val) { - return; - } - const changeTag = this.selectedTags.pop(); - this.resolveCategoryDisplay(changeTag, 'add'); - if (changeTag) { - this.selectedTagsChange.emit({ selectedTags: this.selectedTags, currentChangeTag: changeTag, operation: 'delete' }); - } - }); + const tag = this.selectedTags[this.selectedTags.length - 1]; + this.removeTag(tag); this.closeMenu(inputDropdown); } - canChange(tag, operation: 'delete' | 'add') { + canChange(tag: ICategorySearchTagItem, operation: 'delete' | 'add') { let changeResult = Promise.resolve(true); if (this.beforeTagChange) { const result: any = this.beforeTagChange(tag, this.searchKey, operation); @@ -592,7 +606,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI this.inputEle.nativeElement.focus(); } - clearFilter(event) { + clearFilter(event: MouseEvent) { if (this.selectedTags.length) { this.selectedTags.forEach((item) => this.resetValue(item)); this.selectedTags = []; @@ -609,7 +623,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI this.initCategoryDisplay(); } - resolveCategoryDisplay(tag, type) { + resolveCategoryDisplay(tag: ICategorySearchTagItem, type: string) { if (tag && type === 'add') { if (this.categoryInGroup) { const groupIndex = this.categoryDisplay.findIndex((item) => item.groupName === tag.group); @@ -647,15 +661,15 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI searchKeyChangeEvent(event: string) { this.enterSearch = !!event; - this.currentSearchCategory = this.category.filter((item) => item['label'].toLowerCase().includes(event.toLowerCase())); + this.currentSearchCategory = event ? this.category.filter((item) => item['label'].toLowerCase().includes(event.toLowerCase())) : []; this.searchKeyChange.emit(event); } - checkType(value) { - return value && value.type === 'radio' ? 'all' : 'blank'; + checkType(tag: ICategorySearchTagItem) { + return tag && tag.type === 'radio' ? 'all' : 'blank'; } - resetValue(tag) { + resetValue(tag: ICategorySearchTagItem) { tag.value = this.valueIsArrayTypes.includes(tag.type) ? { value: [] } : { value: undefined }; tag.value[tag.filterKey || 'label'] = undefined; return tag; @@ -670,32 +684,36 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI /* 各类型模板调用方法 */ // radio 单选 处理选中项方法 - chooseItem(tag, chooseItem) { + chooseItem(tag: ICategorySearchTagItem, chooseItem: ITagOption) { this.afterDropdownClosed(); - tag.value = cloneDeep(chooseItem); - tag.value.cache = tag.value.value; + const key = tag.filterKey || 'label'; + tag.value = { value: chooseItem, cache: cloneDeep(chooseItem) }; + tag.value[key] = chooseItem[key]; tag.title = this.setTitle(tag, 'radio'); this.updateSelectedTags(tag); } - confirmDate(tag) { + confirmDate(tag: ICategorySearchTagItem) { this.afterDropdownClosed(); + const start = tag.value.value[0] as Date; + const end = tag.value.value[1] as Date; tag.value.cache = cloneDeep(tag.value.value); tag.value[tag.filterKey || 'label'] = tag.showTime - ? this.dateConverter.formatDateTime(tag.value.value[0]) + ' - ' + this.dateConverter.formatDateTime(tag.value.value[1]) - : this.dateConverter.format(tag.value.value[0]) + ' - ' + this.dateConverter.format(tag.value.value[1]); + ? `${this.dateConverter.formatDateTime(start)} - ${this.dateConverter.formatDateTime(end)}` + : `${this.dateConverter.format(start)} - ${this.dateConverter.format(end)}`; tag.title = this.setTitle(tag, 'dateRange'); this.updateSelectedTags(tag); } - dateValueChange(tag, datepickerpro: DatepickerProCalendarComponent) { - if (datepickerpro.dateValue.length) { - const index = datepickerpro.currentActiveInput === 'start' ? 0 : 1; - if (tag.value.value && !datepickerpro.dateValue.includes('')) { - tag.value.value[index] = datepickerpro.curActiveDate; - tag.value.value = [...tag.value.value]; + dateValueChange(tag: ICategorySearchTagItem, datepickerPro: DatepickerProCalendarComponent) { + if (datepickerPro.dateValue.length) { + if (tag.value.value && !datepickerPro.dateValue.includes('')) { + const date = datepickerPro.curActiveDate; + const index = datepickerPro.currentActiveInput === 'start' ? 0 : 1; + const value = tag.value.value[index]; + tag.value.value = value ? [value, date] : [date, value]; } else { - tag.value.value = [datepickerpro.curActiveDate]; + tag.value.value = [datepickerPro.curActiveDate]; } } else { tag.value.value = []; @@ -703,12 +721,13 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // checkbox | label 多选 处理选中项方法 - chooseItems(tag) { + chooseItems(tag: ICategorySearchTagItem) { this.afterDropdownClosed(); - const result = this.getItemValue(tag.value.value, tag.filterKey || 'label'); + const key = tag.filterKey || 'label'; + const result = this.getItemValue(tag.value.value, key); if (result) { tag.title = this.setTitle(tag, 'checkbox', result); - tag.value[tag.filterKey || 'label'] = result; + tag.value[key] = result; tag.value.cache = cloneDeep(tag.value.value); this.updateSelectedTags(tag); } else { @@ -717,7 +736,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // checkbox | label 将选中项对应filterKey的值合并的方法,当前多选已通过data展示,可考虑移除 - getItemValue(value, key) { + getItemValue(value: any, key: string) { if (value && Array.isArray(value)) { const result = value.map((item) => item[key]); return result.join(','); @@ -725,7 +744,10 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // checkbox | label 当下拉菜单展开重置多选的选中状态 - resetContent(dropdown: DropDownDirective, tag?: any) { + resetContent(dropdown: DropDownDirective, tag?: ICategorySearchTagItem) { + if (this.blurTimer) { + clearTimeout(this.blurTimer); + } if (this.toggleEvent) { this.toggleEvent(dropdown, tag, this.currentSelectTag); } @@ -733,6 +755,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI this.currentOpenDropdown = dropdown; if (tag?.type === 'keyword') { this.searchKey = this.searchKeyCache; + this.searchKeyChangeEvent(this.searchKey); this.inputEle.nativeElement.focus(); dropdown.isOpen = false; } @@ -756,11 +779,11 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI this.showNoDataTips = this.categoryDisplay.length === 0 || !this.categoryDisplay.some((item) => item && item.groupLength === undefined); } - showCurrentSearchCategory(item, inputDropdown: DropDownDirective) { + showCurrentSearchCategory(tag: ICategorySearchTagItem, inputDropdown: DropDownDirective) { this.isSearchCategory = true; this.clearSearchKey(); this.closeMenu(inputDropdown); - this.chooseCategory(item, inputDropdown); + this.chooseCategory(tag, inputDropdown); setTimeout(() => this.checkInputSearching(), this.DELAY); } @@ -791,9 +814,9 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // label 合并名称和颜色字段赋给tag,待[tag]支持传入对象后可移除 - mergeToLabel(obj) { - if (obj && obj.options && Array.isArray(obj.options)) { - obj.options.map((item) => { + mergeToLabel(obj: any) { + if (obj?.options && Array.isArray(obj.options)) { + obj.options.forEach((item) => { item.$label = `${item[obj.filterKey || 'label']}_${item[obj.colorKey || 'color']}`; }); } @@ -801,7 +824,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // label 拆分名称和颜色用于下拉选项显示 - splitLabel(key, value) { + splitLabel(key: string, value: any) { // 初始化选中类别生成标签时,value为label的对象,不需要对值进行操作 if (typeof value !== 'string') { return; @@ -812,7 +835,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // textInput 文本输入框 处理选中项方法 - getTextInputValue(tag) { + getTextInputValue(tag: ICategorySearchTagItem) { this.afterDropdownClosed(); tag.value[tag.filterKey || 'label'] = tag.value.cache = tag.value.value; tag.title = this.setTitle(tag, 'textInput'); @@ -820,7 +843,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // numberRange 数字范围 处理选中项方法 - getNumberRangeValue(tag) { + getNumberRangeValue(tag: ICategorySearchTagItem) { this.afterDropdownClosed(); const startNum = tag.value.value[0] || 0; const endNum = tag.value.value[1] || 0; @@ -832,11 +855,12 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } // treeSelect 树 处理选中项方法 - getTreeValue(tag, tree) { + getTreeValue(tag: ICategorySearchTagItem, tree: OperableTreeComponent) { this.afterDropdownClosed(); const result = []; const selectedIds = []; - tag.value.value.forEach((item) => { + const data = tag.value.value as ITagOption[]; + data.forEach((item) => { result.push(item[tag.filterKey || tag.treeNodeTitleKey || 'title']); selectedIds.push(item[tag.treeNodeIdKey || 'id']); }); @@ -856,7 +880,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } } - updateTreeData(tag, data, selectedIds, halfCheckedIds) { + updateTreeData(tag: ICategorySearchTagItem, data: ITagOption[], selectedIds: string[], halfCheckedIds: string[]) { data.forEach((item) => { const itemId = item[tag.treeNodeIdKey || 'id']; const childData = item[tag.treeNodeChildrenKey || 'children']; @@ -879,7 +903,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } } - onOperableNodeSelected(selectedNode: ITreeItem, tag: ICategorySearchTagItem, tree) { + onOperableNodeSelected(selectedNode: ITreeItem, tag: ICategorySearchTagItem, tree: OperableTreeComponent) { if (tag.multiple || (tag.leafOnly && selectedNode.data.isParent)) { return; } @@ -891,7 +915,7 @@ export class CategorySearchComponent implements OnChanges, OnDestroy, AfterViewI } } - treeSearch(tree, value) { + treeSearch(tree: OperableTreeComponent, value: string) { tree.operableTree.treeFactory.searchTree(value, true); } diff --git a/devui/category-search/category-search.type.ts b/devui/category-search/category-search.type.ts index 7072e5a7..152158e9 100644 --- a/devui/category-search/category-search.type.ts +++ b/devui/category-search/category-search.type.ts @@ -52,8 +52,8 @@ export interface ICategorySearchTagItem { */ value?: { label?: string; - value?: string | Array; - cache?: string | Array; + value?: string | ITagOption | Array; + cache?: string | ITagOption | Array; [propName: string]: any; }; [propName: string]: any; diff --git a/devui/category-search/demo/category-search-demo.module.ts b/devui/category-search/demo/category-search-demo.module.ts index 172d4ed5..6a8236eb 100644 --- a/devui/category-search/demo/category-search-demo.module.ts +++ b/devui/category-search/demo/category-search-demo.module.ts @@ -1,5 +1,6 @@ import { CommonModule } from "@angular/common"; import { NgModule } from "@angular/core"; +import { FormsModule } from "@angular/forms"; import { RouterModule } from "@angular/router"; import { CategorySearchModule } from "ng-devui/category-search"; import { SelectModule } from "ng-devui/select"; @@ -25,10 +26,12 @@ import { CategorySearchDemoComponent } from "./category-search-demo.component"; DevUIApiModule, CategorySearchModule, SelectModule, + FormsModule, RouterModule.forChild([ { path: "", redirectTo: "demo", + pathMatch: 'full' }, { path: "demo", diff --git a/devui/category-search/doc/api-cn.md b/devui/category-search/doc/api-cn.md index 746d585b..2facc7c6 100644 --- a/devui/category-search/doc/api-cn.md +++ b/devui/category-search/doc/api-cn.md @@ -14,26 +14,27 @@ import { CategorySearchModule } from 'ng-devui/category-search'; ### d-category-search 参数 -| 参数 | 类型 | 默认 | 说明 | 跳转 | -| :---------------------: | :---------------------------------------------------------------------------------: | :---: | :------------------------------------------------------------------------------------------ | :----------------------------------- | -| category | `ICategorySearchTagItem` | -- | 必选,传入分类搜索源数据 | [基本用法](demo#basic-usage) | -| defaultSearchField | `String[]` | [] | 可选,配置输入关键字时可在哪些分类中筛选 | [基本用法](demo#basic-usage) | -| selectedTags | `ICategorySearchTagItem` | -- | 可选,传入需要默认选中的分类数据 | [基本用法](demo#basic-usage) | -| placeholderText | `string` | -- | 可选, 自定义搜索输入框占位文字 | [基本用法](demo#basic-usage) | -| allowSave | `boolean` | true | 可选,是否显示保存当前过滤的按钮 | [基本用法](demo#basic-usage) | -| allowClear | `boolean` | true | 可选,是否显示清除当前过滤的按钮 | [基本用法](demo#basic-usage) | -| allowShowMore | `boolean` | false | 可选,是否显示当前过滤条件下拉列表的按钮 | [大数据量优化展示](demo#auto-scroll) | -| showSearchCategory | `boolean \| SearchConfig` | true | 可选,是否显示搜索关键字下拉菜单 | [自定义展示模板](demo##custom-template) | -| searchKey | `string` | '' | 可选,搜索框内的默认展示值 | [基本用法](demo#basic-usage) | -| beforeTagChange | `(tag, searchKey, operation) => boolean \| Promise \| Observable` | -- | 可选,改变标签前调用的方法,返回 boolean 类型,返回 false 可以阻止分类值改变 | | -| toggleEvent | `(dropdown, tag?, currentSelectTag?) => void` | -- | 可选,已选分类的下拉菜单开关时调用的方法,可使用 return 阻止之后的默认方法执行 | [基本用法](demo#basic-usage) | -| inputReadOnly | `boolean` | false | 可选,限制是否可通过搜索框输入关键字搜索,`true`则无法输入关键字,仅可根据提供的分类数据筛选 | | -| tagMaxWidth | `number` | -- | 可选,单个过滤条件的最大宽度,超过则显示省略号,不设置则不限制 | [大数据量优化展示](demo#auto-scroll) | -| toggleScrollToTail | `boolean` | false | 可选,在有滚动条存在时初始化加载或选择过滤内容后自动滚动至最右侧,以便用户选择新的过滤内容 | [大数据量优化展示](demo#auto-scroll) | -| filterNameRules | `DValidateRules` | false | 可选,配置保存过滤器标题的校验规则,详细规则参见 ng-devui 库 form 组件 | [基本用法](demo#basic-usage) | -| categoryInGroup | `boolean` | false | 可选,是否按组别显示分类下拉列表 | [大数据量优化展示](demo#auto-scroll) | -| groupOrderConfig | `String[]` | -- | 可选,配置组的排序 | [大数据量优化展示](demo#auto-scroll) | -| customGroupNameTemplate | `TemplateRef` | -- | 可选,自定义组名称显示模板 | [大数据量优化展示](demo#auto-scroll) | +| 参数 | 类型 | 默认 | 说明 | 跳转 | +| ----------------------- | ----------------------------------------------------------------------------------- | ----- | ------------------------------------------------------------------------------------------- | --------------------------------------- | +| category | `ICategorySearchTagItem` | -- | 必选,传入分类搜索源数据 | [基本用法](demo#basic-usage) | +| defaultSearchField | `String[]` | [] | 可选,配置输入关键字时可在哪些分类中筛选 | [基本用法](demo#basic-usage) | +| selectedTags | `ICategorySearchTagItem` | -- | 可选,传入需要默认选中的分类数据 | [基本用法](demo#basic-usage) | +| placeholderText | `string` | -- | 可选, 自定义搜索输入框占位文字 | [基本用法](demo#basic-usage) | +| allowSave | `boolean` | true | 可选,是否显示保存当前过滤的按钮 | [基本用法](demo#basic-usage) | +| allowClear | `boolean` | true | 可选,是否显示清除当前过滤的按钮 | [基本用法](demo#basic-usage) | +| allowShowMore | `boolean` | false | 可选,是否显示当前过滤条件下拉列表的按钮 | [大数据量优化展示](demo#auto-scroll) | +| showSearchCategory | `boolean \| SearchConfig` | true | 可选,是否显示搜索关键字下拉菜单 | [自定义展示模板](demo##custom-template) | +| searchKey | `string` | '' | 可选,搜索框内的默认展示值 | [基本用法](demo#basic-usage) | +| beforeTagChange | `(tag, searchKey, operation) => boolean \| Promise \| Observable` | -- | 可选,改变标签前调用的方法,返回 boolean 类型,返回 false 可以阻止分类值改变 | | +| toggleEvent | `(dropdown, tag?, currentSelectTag?) => void` | -- | 可选,已选分类的下拉菜单开关时调用的方法,可使用 return 阻止之后的默认方法执行 | [基本用法](demo#basic-usage) | +| inputReadOnly | `boolean` | false | 可选,限制是否可通过搜索框输入关键字搜索,`true`则无法输入关键字,仅可根据提供的分类数据筛选 | | +| tagMaxWidth | `number` | -- | 可选,单个过滤条件的最大宽度,超过则显示省略号,不设置则不限制 | [大数据量优化展示](demo#auto-scroll) | +| textConfig | `{keywordName: string, createFilter: string, filterTitle: string}` | -- | 可选,配置关键字分类名称、保存过滤器下拉窗口的文字内容 | [自定义展示模板](demo##custom-template) | +| toggleScrollToTail | `boolean` | false | 可选,在有滚动条存在时初始化加载或选择过滤内容后自动滚动至最右侧,以便用户选择新的过滤内容 | [大数据量优化展示](demo#auto-scroll) | +| filterNameRules | `DValidateRules` | false | 可选,配置保存过滤器标题的校验规则,详细规则参见 ng-devui 库 form 组件 | [基本用法](demo#basic-usage) | +| categoryInGroup | `boolean` | false | 可选,是否按组别显示分类下拉列表 | [大数据量优化展示](demo#auto-scroll) | +| groupOrderConfig | `String[]` | -- | 可选,配置组的排序 | [大数据量优化展示](demo#auto-scroll) | +| customGroupNameTemplate | `TemplateRef` | -- | 可选,自定义组名称显示模板 | [大数据量优化展示](demo#auto-scroll) | ### d-category-search 事件 @@ -88,8 +89,8 @@ export interface ICategorySearchTagItem { */ value?: { label: string; // 用于显示选中值,如果指定了 filterKey 则使用该值为属性名,例如 basic demo 中的状态 - value: string | Array; // 下拉列表的选择值 - cache: string | Array; // 下拉列表展开时用于重置选择值的缓存数据 + value: string | ITagOption | Array; // 下拉列表的选择值 + cache: string | ITagOption | Array; // 下拉列表展开时用于重置选择值的缓存数据 }; /** * dateRange 类型是否显示时分秒 diff --git a/devui/category-search/doc/api-en.md b/devui/category-search/doc/api-en.md index 35f359f5..57cd8ca3 100644 --- a/devui/category-search/doc/api-en.md +++ b/devui/category-search/doc/api-en.md @@ -14,29 +14,30 @@ In the page ### d-category-search 参数 -| Parameter | Type | Default | Description | Jump to Demo | -| :---------------------: | :---------------------------------------------------------------------------------: | :-----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------: | -| category | `ICategorySearchTagItem` | -- | Required. The data of categories. | [Basic usage](demo#basic-usage) | -| defaultSearchField | `String[]` | [] | Optional. Configure the categories that can be filtered when entering keywords. | [Basic usage](demo#basic-usage) | -| selectedTags | `ICategorySearchTagItem` | -- | Optional. The categories to be selected by default. | [Basic usage](demo#basic-usage) | -| allowSave | `boolean` | true | Optional. Whether to show save current filter button. | [Basic usage](demo#basic-usage) | -| allowClear | `boolean` | true | Optional. Whether to display the button for clearing the current filter. | [Basic usage](demo#basic-usage) | -| allowShowMore | `boolean` | false | Optional. Whether to display the button in the drop-down list of the current filter criteria. | [Large-scale data display optimization](demo#auto-scroll) | -| showSearchCategory | `boolean \| SearchConfig` | true | Optional. Whether to display the search keyword drop-down list. | [Customize drop-down list box](demo##custom-template) | -| searchKey | `string` | '' | Optional. Default value displayed in the search box. | [Basic usage](demo#basic-usage) | -| beforeTagChange | `(tag, searchKey, operation) => boolean \| Promise \| Observable` | -- | Optional. Method called before changing the tag, returns the boolean type, and returns false to prevent the classification value from changing. | | -| toggleEvent | `(dropdown, tag?, currentSelectTag?) => void` | -- | Optional. Method called when the drop-down menu switch of the selected classification is enabled, which can be executed by the default method after being blocked by return. | [Basic usage](demo#basic-usage) | -| inputReadOnly | `boolean` | false | Optional. Specifies whether to enter keywords in the search box. If it is `true`, you cannot enter keywords and can only filter data based on the provided classification data. | [Basic usage](demo#basic-usage) | -| tagMaxWidth | `number` | -- | Optional. Maximum width of a single filter criterion. If the width exceeds the value, an ellipsis is displayed. If this parameter is not set, no restriction is imposed. | | -| toggleScrollToTail | `boolean` | false | Optional. When a scroll bar exists, the system automatically scrolls to the right after loading or filtering content is selected, so that users can select new filtering content. | [Large-scale data display optimization](demo#auto-scroll) | -| filterNameRules | `DValidateRules` | false | Optional. Configure the validation rule for saving the filter title. For details, see the form component in the ng-devui library. | [Basic usage](demo#basic-usage) | -| categoryInGroup | `boolean` | false | Optional. Indicates whether to display the category drop-down list by group. | [Large-scale data display optimization](demo#auto-scroll) | -| groupOrderConfig | `String[]` | -- | Optional. Configure the sorting of groups. | [Large-scale data display optimization](demo#auto-scroll) | -| customGroupNameTemplate | `TemplateRef` | -- | Optional. Custom Group Name Display Template. | [Large-scale data display optimization](demo#auto-scroll) | +| Parameter | Type | Default | Description | Jump to Demo | +| ----------------------- | ----------------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | +| category | `ICategorySearchTagItem` | -- | Required. The data of categories. | [Basic usage](demo#basic-usage) | +| defaultSearchField | `String[]` | [] | Optional. Configure the categories that can be filtered when entering keywords. | [Basic usage](demo#basic-usage) | +| selectedTags | `ICategorySearchTagItem` | -- | Optional. The categories to be selected by default. | [Basic usage](demo#basic-usage) | +| allowSave | `boolean` | true | Optional. Whether to show save current filter button. | [Basic usage](demo#basic-usage) | +| allowClear | `boolean` | true | Optional. Whether to display the button for clearing the current filter. | [Basic usage](demo#basic-usage) | +| allowShowMore | `boolean` | false | Optional. Whether to display the button in the drop-down list of the current filter criteria. | [Large-scale data display optimization](demo#auto-scroll) | +| showSearchCategory | `boolean \| SearchConfig` | true | Optional. Whether to display the search keyword drop-down list. | [Customize drop-down list box](demo##custom-template) | +| searchKey | `string` | '' | Optional. Default value displayed in the search box. | [Basic usage](demo#basic-usage) | +| beforeTagChange | `(tag, searchKey, operation) => boolean \| Promise \| Observable` | -- | Optional. Method called before changing the tag, returns the boolean type, and returns false to prevent the classification value from changing. | | +| toggleEvent | `(dropdown, tag?, currentSelectTag?) => void` | -- | Optional. Method called when the drop-down menu switch of the selected classification is enabled, which can be executed by the default method after being blocked by return. | [Basic usage](demo#basic-usage) | +| inputReadOnly | `boolean` | false | Optional. Specifies whether to enter keywords in the search box. If it is `true`, you cannot enter keywords and can only filter data based on the provided classification data. | [Basic usage](demo#basic-usage) | +| tagMaxWidth | `number` | -- | Optional. Maximum width of a single filter criterion. If the width exceeds the value, an ellipsis is displayed. If this parameter is not set, no restriction is imposed. | | +| textConfig | `{keywordName: string, createFilter: string, filterTitle: string}` | -- | Optional. Configure the keyword category name and the text in the filter drop-down list box. | [Customizing a Display Template](demo##custom-template) | +| toggleScrollToTail | `boolean` | false | Optional. When a scroll bar exists, the system automatically scrolls to the right after loading or filtering content is selected, so that users can select new filtering content. | [Large-scale data display optimization](demo#auto-scroll) | +| filterNameRules | `DValidateRules` | false | Optional. Configure the validation rule for saving the filter title. For details, see the form component in the ng-devui library. | [Basic usage](demo#basic-usage) | +| categoryInGroup | `boolean` | false | Optional. Indicates whether to display the category drop-down list by group. | [Large-scale data display optimization](demo#auto-scroll) | +| groupOrderConfig | `String[]` | -- | Optional. Configure the sorting of groups. | [Large-scale data display optimization](demo#auto-scroll) | +| customGroupNameTemplate | `TemplateRef` | -- | Optional. Custom Group Name Display Template. | [Large-scale data display optimization](demo#auto-scroll) | ### d-category-search 事件 -| 事件 | 类型 | 说明 | +| Event | Type | Description | | ------------------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | selectedTagsChange | `EventEmitter` | Triggered when category data is changed. The returned value is the selected category data. | | searchKeyChange | `EventEmitter` | Triggered when the search keyword is changed. The return value is the bound value of the text box. | @@ -87,8 +88,8 @@ export interface ICategorySearchTagItem { */ value?: { label: string; // Used to display the selected value, or the property name if filterKey is specified, such as the status in basic demo. - value: string | Array; // Selected value from the drop-down list box - cache: string | Array; // Cached data used to reset the selection value when the drop-down list expands + value: string | ITagOption | Array; // Selected value from the drop-down list box + cache: string | ITagOption | Array; // Cached data used to reset the selection value when the drop-down list expands }; /** * Indicates whether to display hour, minute, and second for the dateRange type. diff --git a/devui/category-search/ng-package.json b/devui/category-search/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/category-search/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/category-search/package.json b/devui/category-search/package.json deleted file mode 100644 index 61f8a57d..00000000 --- a/devui/category-search/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} \ No newline at end of file diff --git a/devui/checkbox/demo/checkbox-demo.module.ts b/devui/checkbox/demo/checkbox-demo.module.ts index bcc7f05e..ae7603cb 100755 --- a/devui/checkbox/demo/checkbox-demo.module.ts +++ b/devui/checkbox/demo/checkbox-demo.module.ts @@ -27,7 +27,7 @@ import { CheckboxGroupBasicComponent } from './group/checkbox-group-basic.compon DevUICodeboxModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: CheckBoxDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/checkbox/ng-package.json b/devui/checkbox/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/checkbox/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/checkbox/package.json b/devui/checkbox/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/checkbox/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/common/demo/common-demo.module.ts b/devui/common/demo/common-demo.module.ts index 47e4f224..8549871e 100644 --- a/devui/common/demo/common-demo.module.ts +++ b/devui/common/demo/common-demo.module.ts @@ -41,7 +41,7 @@ import { PipeDemoComponent } from './pipe/pipe.component'; DataTableModule, TextInputModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: CommonDemoComponent }, { path: 'api', diff --git a/devui/common/ng-package.json b/devui/common/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/common/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/common/package.json b/devui/common/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/common/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/dashboard/demo/dashboard-demo.module.ts b/devui/dashboard/demo/dashboard-demo.module.ts index 1e40c1db..85253424 100644 --- a/devui/dashboard/demo/dashboard-demo.module.ts +++ b/devui/dashboard/demo/dashboard-demo.module.ts @@ -11,7 +11,7 @@ import { DevUIApiComponent } from 'ng-devui/shared/devui-api/devui-api.component import { DevUIApiModule } from 'ng-devui/shared/devui-api/devui-api.module'; import { DevUICodeboxModule } from 'ng-devui/shared/devui-codebox'; import { TranslateModule } from '@ngx-translate/core'; -import { DDemoNavModule } from 'src/app/component/d-demo-nav.module'; +import { DDemoNavModule } from 'devui-commons/src/demo-nav/d-demo-nav.module'; import { BasicComponent } from './basic/basic.component'; import { DashboardDemoComponent } from './dashboard-demo.component'; import { MoreConfigComponent } from './more-config/more-config.component'; @@ -41,7 +41,7 @@ import { MoreConfigComponent } from './more-config/more-config.component'; DrawerModule, TabsModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DashboardDemoComponent }, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/dashboard/ng-package.json b/devui/dashboard/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/dashboard/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/dashboard/package.json b/devui/dashboard/package.json deleted file mode 100644 index 6756d6f5..00000000 --- a/devui/dashboard/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - }, - "peerDependencies": { - "gridstack": "4.2.6" - }, - "sideEffects": true -} diff --git a/devui/data-table/data-table-cell.component.ts b/devui/data-table/data-table-cell.component.ts index bf8704d1..eaf41cfa 100755 --- a/devui/data-table/data-table-cell.component.ts +++ b/devui/data-table/data-table-cell.component.ts @@ -75,7 +75,7 @@ export class DataTableCellComponent implements OnInit, OnChanges, OnDestroy { } this.ngZone.runOutsideAngular(() => { this.cellRef.nativeElement.addEventListener( - 'click', + 'mouseup', this.onCellClick.bind(this) ); this.cellRef.nativeElement.addEventListener( @@ -121,7 +121,8 @@ export class DataTableCellComponent implements OnInit, OnChanges, OnDestroy { column: this.column, rowItem: this.rowItem, cellComponent: this, - rowComponent: this.rowComponent + rowComponent: this.rowComponent, + event: $event }; this.clickCount++; diff --git a/devui/data-table/data-table-column.spec.ts b/devui/data-table/data-table-column.spec.ts index 17c3e07d..e8ca7b20 100644 --- a/devui/data-table/data-table-column.spec.ts +++ b/devui/data-table/data-table-column.spec.ts @@ -271,7 +271,7 @@ class TestDataTableAdvancedColumnComponent implements OnInit { filterChangeMultiple($event) { const filterList = $event.map(item => item.name); const dataDisplay = []; - JSON.parse(JSON.stringify(originSource.slice(0, 6))).map(item => { + JSON.parse(JSON.stringify(originSource.slice(0, 6))).forEach(item => { if (filterList.includes(item.firstName)) { dataDisplay.push(item); } @@ -966,7 +966,7 @@ describe('data-table column', () => { it('should cell click work', fakeAsync(() => { const cellEl = debugEl.query(By.css('.devui-data-table .devui-table tbody tr td:nth-child(2)')); - cellEl.nativeElement.dispatchEvent(new Event('click')); + cellEl.nativeElement.dispatchEvent(new Event('mouseup')); flush(); expect(component.testCellClickEvent).not.toBeNull(); })); @@ -980,14 +980,14 @@ describe('data-table column', () => { it('should row click work', fakeAsync(() => { const rowEl = debugEl.query(By.css('.devui-data-table .devui-table tbody tr')); - rowEl.nativeElement.dispatchEvent(new Event('click')); + rowEl.nativeElement.dispatchEvent(new Event('mouseup')); flush(); expect(component.testRowClickEvent).not.toBeNull(); fixture.detectChanges(); component.testRowClickEvent = null; // click twice - rowEl.nativeElement.dispatchEvent(new Event('click')); - rowEl.nativeElement.dispatchEvent(new Event('click')); + rowEl.nativeElement.dispatchEvent(new Event('mouseup')); + rowEl.nativeElement.dispatchEvent(new Event('mouseup')); expect(component.testRowClickEvent).toBeNull(); flush(); })); diff --git a/devui/data-table/data-table-row.component.scss b/devui/data-table/data-table-row.component.scss index 81c2ab8c..da678b7a 100755 --- a/devui/data-table/data-table-row.component.scss +++ b/devui/data-table/data-table-row.component.scss @@ -77,6 +77,7 @@ svg.svg-icon-arrow > g > polygon { cursor: pointer; margin-left: -5px; padding-left: 5px; + min-height: 20px; &:hover { background: $devui-list-item-hover-bg; diff --git a/devui/data-table/data-table-row.component.ts b/devui/data-table/data-table-row.component.ts index 215edfd0..313e55e9 100755 --- a/devui/data-table/data-table-row.component.ts +++ b/devui/data-table/data-table-row.component.ts @@ -57,7 +57,7 @@ export class DataTableRowComponent implements OnInit { ngOnInit(): void { this.ngZone.runOutsideAngular(() => { this.rowRef.nativeElement.addEventListener( - 'click', + 'mouseup', this.onRowClick.bind(this) ); this.rowRef.nativeElement.addEventListener( @@ -87,7 +87,9 @@ export class DataTableRowComponent implements OnInit { if (this.clickCount === 1) { this.timeoutId = setTimeout(() => { if (this.clickCount === 1) { - this.dt.onRowClick({ rowIndex: this.rowIndex, nestedIndex: this.nestedIndex, rowItem: this.rowItem, rowComponent: this }); + this.dt.onRowClick({ + rowIndex: this.rowIndex, nestedIndex: this.nestedIndex, rowItem: this.rowItem, rowComponent: this, event: $event + }); } this.clickCount = 0; clearTimeout(this.timeoutId); diff --git a/devui/data-table/data-table.component.html b/devui/data-table/data-table.component.html index b01614e5..a80a92fa 100755 --- a/devui/data-table/data-table.component.html +++ b/devui/data-table/data-table.component.html @@ -103,7 +103,7 @@
          diff --git a/devui/data-table/data-table.component.scss b/devui/data-table/data-table.component.scss index 36fb7acb..b61ade92 100755 --- a/devui/data-table/data-table.component.scss +++ b/devui/data-table/data-table.component.scss @@ -45,6 +45,7 @@ $devui-table-inset-shadow-right: var(--devui-table-inset-shadow-right, -8px 0 8p &.overflow-overlay { overflow: hidden; + transform: translate3d(0, 0, 0); &:hover { overflow: auto; @@ -93,6 +94,7 @@ $devui-table-inset-shadow-right: var(--devui-table-inset-shadow-right, -8px 0 8p &.overflow-overlay { overflow: hidden; + transform: translate3d(0, 0, 0); &:hover { overflow: auto; @@ -161,12 +163,6 @@ $devui-table-inset-shadow-right: var(--devui-table-inset-shadow-right, -8px 0 8p .devui-table ::ng-deep { thead { - span { - font-weight: bold; - color: $devui-text; - font-size: $devui-font-size-sm; - } - tr { background-color: $devui-base-bg; @@ -421,13 +417,47 @@ $devui-table-inset-shadow-right: var(--devui-table-inset-shadow-right, -8px 0 8p .resizeable:hover { .resize-handle { - border-right: 1px solid $devui-line; + border-right: 2px solid $devui-line; + + &::before { + content: ''; + display: block; + width: 0; + height: 0; + border: 5px solid transparent; + border-right-color: $devui-line; + position: absolute; + left: -8px; + top: 50%; + transform: translateY(-50%); + } + + &::after { + content: ''; + display: block; + width: 0; + height: 0; + border: 5px solid transparent; + border-left-color: $devui-line; + position: absolute; + left: 6px; + top: 50%; + transform: translateY(-50%); + } } } .resizeable { .resize-handle:hover { border-right: 2px solid $devui-form-control-line-active; + + &::before { + display: none; + } + + &::after { + display: none; + } } } } @@ -467,6 +497,12 @@ $devui-table-inset-shadow-right: var(--devui-table-inset-shadow-right, -8px 0 8p } } +.devui-table ::ng-deep { + tbody > tr > td.devui-operation-cell { + padding: 5px 20px; + } +} + .devui-table { &.devui-table-md ::ng-deep { tbody > tr > td { diff --git a/devui/data-table/data-table.model.ts b/devui/data-table/data-table.model.ts index 69029486..1af8d084 100755 --- a/devui/data-table/data-table.model.ts +++ b/devui/data-table/data-table.model.ts @@ -24,6 +24,7 @@ export interface RowSelectedEventArg { nestedIndex: string; rowItem: any; rowComponent: DataTableRowComponent; + event?: MouseEvent; } export interface SortEventArg { diff --git a/devui/data-table/demo/async/data-table-demo-async.component.html b/devui/data-table/demo/async/data-table-demo-async.component.html index 8c60ebe4..c92f536e 100755 --- a/devui/data-table/demo/async/data-table-demo-async.component.html +++ b/devui/data-table/demo/async/data-table-demo-async.component.html @@ -12,7 +12,9 @@ > - {{ colOption.header }} + + {{ colOption.header }} + diff --git a/devui/data-table/demo/basic/data-table-demo-basic.component.html b/devui/data-table/demo/basic/data-table-demo-basic.component.html index 3aac22de..027ed9c2 100755 --- a/devui/data-table/demo/basic/data-table-demo-basic.component.html +++ b/devui/data-table/demo/basic/data-table-demo-basic.component.html @@ -9,7 +9,7 @@ {{ rowIndex + 1 }} - + {{ colOption.fieldType === 'date' ? (rowItem[colOption.field] | i18nDate: 'short':false) : rowItem[colOption.field] }} diff --git a/devui/data-table/demo/check-options/check-options.component.ts b/devui/data-table/demo/check-options/check-options.component.ts index 2c7df1c2..7fa3130e 100644 --- a/devui/data-table/demo/check-options/check-options.component.ts +++ b/devui/data-table/demo/check-options/check-options.component.ts @@ -73,6 +73,10 @@ export class CheckOptionsComponent implements OnInit { label: '全选所有数据', onChecked: this.checkTotalData.bind(this) }, + { + label: '取消所有数据全选', + onChecked: this.uncheckTotalData.bind(this) + }, { label: '全选当前页数据', onChecked: this.checkPageData.bind(this) @@ -96,6 +100,15 @@ export class CheckOptionsComponent implements OnInit { this.totalDataChecked = true; } + uncheckTotalData() { + this.datatable.setTableCheckStatus( + { + pageAllChecked: false + } + ); + this.totalDataChecked = false; + } + checkPageData() { this.datatable.setTableCheckStatus( { diff --git a/devui/data-table/demo/data-table-demo.module.ts b/devui/data-table/demo/data-table-demo.module.ts index 018e4217..080595d8 100755 --- a/devui/data-table/demo/data-table-demo.module.ts +++ b/devui/data-table/demo/data-table-demo.module.ts @@ -59,7 +59,7 @@ import { VirtualScrollComponent } from './virtual-scroll/virtual-scroll.componen LoadingModule, SplitterModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DataTableDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/data-table/doc/api-cn.md b/devui/data-table/doc/api-cn.md index fd0ec030..303fbe72 100644 --- a/devui/data-table/doc/api-cn.md +++ b/devui/data-table/doc/api-cn.md @@ -180,6 +180,15 @@ import { DataTableModule } from 'ng-devui/data-table'; | field | `string` | -- | 单元格所属列的字段,作为beforeEditStart、beforeEditEnd的参数 | [编辑单元格](demo#edit-cell) | | nestedColumnIndent| `number` | 16 | 单元格中子表格的缩进距离,单位px | [树形表格](demo#tree-form) | +## 单元格公共class + +| 参数名 | 描述 | 跳转 Demo | +| :-------------: | :------------------------------------------------------------: | :------------------------------------------------- | +| devui-operation-cell | 单元格内放置input,d-icon等操作类组件时需要加上,会调整padding适应行高 | | +| devui-table-link | 单元格内放置链接时需要加上 | | +| devui-table-title | 单元格内放置表头信息时需要加上,会自动加粗 | | + + ## dTableCell 事件 | 事件 | 类型 | 描述 | 跳转 Demo | diff --git a/devui/data-table/doc/api-en.md b/devui/data-table/doc/api-en.md index 8fab389f..f899ac24 100644 --- a/devui/data-table/doc/api-en.md +++ b/devui/data-table/doc/api-en.md @@ -158,6 +158,7 @@ On the page: | toggleChildrenTableEvent | `EventEmitter` | Event for expanding and collapsing all subtables. The value true indicates expanding, and the value false indicates collapse. | | sortDirectionChange | `EventEmitter` | Sort Order Direction Change Event| + # dTableCell ## dTableCell Parameter @@ -186,6 +187,14 @@ On the page: | editStatusEvent | `EventEmitter` | Cell editing status event | [edit cell](demo#edit-cell) | | toggleChildTableEvent | `EventEmitter` | Event for expanding and collapsing the subtable in the current row. The options are true and false. | [Tree table](demo#tree-form) | +## Cell common class + +| Parameter name | Description | Jump to Demo | +| :-------------: | :------------------------------------------------------------: | :------------------------------------------------- | +| devui-operation-cell | When operation components such as input and d-icon are placed in a cell, padding is adjusted to fit the row height. | | +| devui-table-link | Add | when placing links in cells. +| devui-table-title | When table header information is placed in a cell, it is automatically bolded. | | + #### Configure the row template of the dTableBody when the user-defined template is used. For details, see (demo#tree-form)**. diff --git a/devui/data-table/ng-package.json b/devui/data-table/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/data-table/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/data-table/package.json b/devui/data-table/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/data-table/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/data-table/table/body/td/td.component.scss b/devui/data-table/table/body/td/td.component.scss index d96c510e..007941a2 100644 --- a/devui/data-table/table/body/td/td.component.scss +++ b/devui/data-table/table/body/td/td.component.scss @@ -96,6 +96,7 @@ svg.svg-icon-arrow > g > polygon { cursor: pointer; margin-left: -5px; padding-left: 5px; + min-height: 20px; &:hover { background: $devui-list-item-hover-bg; diff --git a/devui/data-table/table/head/th/th.component.scss b/devui/data-table/table/head/th/th.component.scss new file mode 100644 index 00000000..68efe47e --- /dev/null +++ b/devui/data-table/table/head/th/th.component.scss @@ -0,0 +1,8 @@ +@import '../../../../style/theme/color'; +@import '../../../../style/core/_font'; + +:host { + font-weight: bold; + color: $devui-text; + font-size: $devui-font-size-sm; +} diff --git a/devui/data-table/table/head/th/th.component.ts b/devui/data-table/table/head/th/th.component.ts index ca8ccdc0..8fae0540 100644 --- a/devui/data-table/table/head/th/th.component.ts +++ b/devui/data-table/table/head/th/th.component.ts @@ -12,6 +12,7 @@ import { TABLE_TH } from './th.token'; /* eslint-disable-next-line @angular-eslint/component-selector*/ selector: '[dHeadCell]', templateUrl: './th.component.html', + styleUrls: ['./th.component.scss'], providers: [{ provide: TABLE_TH, useExisting: forwardRef(() => TableThComponent) diff --git a/devui/datepicker-pro/datepicker-pro-calendar.component.ts b/devui/datepicker-pro/datepicker-pro-calendar.component.ts index 61834d42..75353018 100644 --- a/devui/datepicker-pro/datepicker-pro-calendar.component.ts +++ b/devui/datepicker-pro/datepicker-pro-calendar.component.ts @@ -117,7 +117,7 @@ export class DatepickerProCalendarComponent implements OnInit, AfterViewInit, On _dateValue = []; i18nText; datepickerConvert: DefaultDateConverter; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); private i18nLocale: I18nInterface['locale']; private onChange = (_: any) => null; diff --git a/devui/datepicker-pro/datepicker-pro.component.scss b/devui/datepicker-pro/datepicker-pro.component.scss index 5ae6433c..bea4daf1 100644 --- a/devui/datepicker-pro/datepicker-pro.component.scss +++ b/devui/datepicker-pro/datepicker-pro.component.scss @@ -10,6 +10,8 @@ box-sizing: border-box; width: 100%; min-height: 24px; + display: flex; + align-items: center; .devui-input { padding: 4px 8px; @@ -18,6 +20,7 @@ &-icon { vertical-align: bottom; + height: 16px; } .close-icon-wrapper { diff --git a/devui/datepicker-pro/datepicker-pro.component.ts b/devui/datepicker-pro/datepicker-pro.component.ts index 4d36d651..c0eb93c4 100644 --- a/devui/datepicker-pro/datepicker-pro.component.ts +++ b/devui/datepicker-pro/datepicker-pro.component.ts @@ -82,7 +82,7 @@ export class DatepickerProComponent implements OnInit, AfterViewInit, OnDestroy, i18nText; dateValue = ''; datepickerConvert: DefaultDateConverter; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); isOpen = false; get dateConfig(): DateConfig { return { @@ -191,6 +191,8 @@ export class DatepickerProComponent implements OnInit, AfterViewInit, OnDestroy, value: inputDate }); + this.onChange(inputDate); + if (this.showTime) { this.pickerSrv.updateTimeChange.next({ hour: inputDate.getHours(), diff --git a/devui/datepicker-pro/demo/datepicker-pro-demo.component.html b/devui/datepicker-pro/demo/datepicker-pro-demo.component.html index 33787b2a..c6ce337e 100644 --- a/devui/datepicker-pro/demo/datepicker-pro-demo.component.html +++ b/devui/datepicker-pro/demo/datepicker-pro-demo.component.html @@ -1,56 +1,56 @@
          -
          -
          {{ 'components.datepicker-pro.basicDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.basicDemo.title' | translate }}
          -
          -
          {{ 'components.datepicker-pro.markedTypeDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.markedTypeDemo.title' | translate }}
          -
          -
          {{ 'components.datepicker-pro.showTimeDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.showTimeDemo.title' | translate }}
          -
          -
          {{ 'components.datepicker-pro.templateDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.templateDemo.title' | translate }}
          -
          -
          {{ 'components.datepicker-pro.monthYearDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.monthYearDemo.title' | translate }}
          -
          -
          {{ 'components.datepicker-pro.rangePickerDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.rangePickerDemo.title' | translate }}
          -
          -
          {{ 'components.datepicker-pro.rangeTemplateDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.rangeTemplateDemo.title' | translate }}
          -
          -
          {{ 'components.datepicker-pro.hostTemplateDemo.title' | translate }}
          +
          +
          {{ 'components.datepicker-pro.hostTemplateDemo.title' | translate }}
          diff --git a/devui/datepicker-pro/demo/datepicker-pro-demo.module.ts b/devui/datepicker-pro/demo/datepicker-pro-demo.module.ts index 5ac8611b..0f0d7b9b 100644 --- a/devui/datepicker-pro/demo/datepicker-pro-demo.module.ts +++ b/devui/datepicker-pro/demo/datepicker-pro-demo.module.ts @@ -45,7 +45,7 @@ import { DatepickerProTemplateComponent } from './template/datepicker-template.c DDemoNavModule, DatepickerProModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DatepickerProDemoComponent }, { path: 'api', diff --git a/devui/datepicker-pro/lib/calendar-panel.component.scss b/devui/datepicker-pro/lib/calendar-panel.component.scss index fcd4b732..5a876a90 100644 --- a/devui/datepicker-pro/lib/calendar-panel.component.scss +++ b/devui/datepicker-pro/lib/calendar-panel.component.scss @@ -175,7 +175,7 @@ } } - &.devui-table-date-start:not(.devui-table-date-end) { + &.devui-table-date-start:not(.devui-table-date-end,.devui-table-date-disable) { position: relative; &::after { @@ -198,7 +198,7 @@ } } - &.devui-table-date-end:not(.devui-table-date-start) { + &.devui-table-date-end:not(.devui-table-date-start,.devui-table-date-disable) { position: relative; &::after { diff --git a/devui/datepicker-pro/lib/calendar-panel.component.ts b/devui/datepicker-pro/lib/calendar-panel.component.ts index 6020101f..060ebd3f 100644 --- a/devui/datepicker-pro/lib/calendar-panel.component.ts +++ b/devui/datepicker-pro/lib/calendar-panel.component.ts @@ -31,7 +31,7 @@ export class CalendarPanelComponent implements OnInit, OnDestroy { i18nText: I18nInterface['datePickerPro']; i18nSubscription: Subscription; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); allMonthList = []; yearAndMonthList = []; @@ -342,7 +342,7 @@ export class CalendarPanelComponent implements OnInit, OnDestroy { } else if (this.pickerSrv.currentActiveInput === 'end' && !this.selectedRangeDate[0]) { this.selectedRangeDate[0] = this.curDate; } else { - this.pickerSrv.closeDropdownEvent.next(); + this.pickerSrv.closeDropdownEvent.next(false); } } this.pickerSrv.selectedDateChange.next({ @@ -360,7 +360,7 @@ export class CalendarPanelComponent implements OnInit, OnDestroy { } if (this.pickerSrv.closeAfterSelected) { - this.pickerSrv.closeDropdownEvent.next(); + this.pickerSrv.closeDropdownEvent.next(false); } } diff --git a/devui/datepicker-pro/lib/month-panel.component.ts b/devui/datepicker-pro/lib/month-panel.component.ts index abea51a5..fabd6027 100644 --- a/devui/datepicker-pro/lib/month-panel.component.ts +++ b/devui/datepicker-pro/lib/month-panel.component.ts @@ -25,7 +25,7 @@ export class MonthPanelComponent implements OnInit, OnDestroy { @ViewChild('scrollList') scrollListCmp: CdkVirtualScrollViewport; @Input() isRangeType = false; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); scrollListener: Subscription; i18nText: I18nInterface['datePickerPro']; i18nSubscription: Subscription; @@ -193,7 +193,7 @@ export class MonthPanelComponent implements OnInit, OnDestroy { } else if (this.pickerSrv.currentActiveInput === 'end' && !this.selectedRangeDate[0]) { this.pickerSrv.currentActiveInput = 'start'; } else { - this.pickerSrv.closeDropdownEvent.next(); + this.pickerSrv.closeDropdownEvent.next(false); } } @@ -203,7 +203,7 @@ export class MonthPanelComponent implements OnInit, OnDestroy { }); if (this.pickerSrv.closeAfterSelected) { - this.pickerSrv.closeDropdownEvent.next(); + this.pickerSrv.closeDropdownEvent.next(false); } } diff --git a/devui/datepicker-pro/lib/timepicker-panel.component.ts b/devui/datepicker-pro/lib/timepicker-panel.component.ts index 091f561f..3134f9a5 100644 --- a/devui/datepicker-pro/lib/timepicker-panel.component.ts +++ b/devui/datepicker-pro/lib/timepicker-panel.component.ts @@ -31,7 +31,7 @@ export class TimepickerPanelComponent implements OnInit, OnDestroy { typeList = ['hour', 'min', 'sec']; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); i18nText: I18nInterface['datePickerPro']; i18nSubscription: Subscription; diff --git a/devui/datepicker-pro/lib/year-panel.component.ts b/devui/datepicker-pro/lib/year-panel.component.ts index 90699749..fb04bb80 100644 --- a/devui/datepicker-pro/lib/year-panel.component.ts +++ b/devui/datepicker-pro/lib/year-panel.component.ts @@ -28,7 +28,7 @@ export class YearPanelComponent implements OnInit, OnDestroy { yearList = []; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); get curHoverDate() { return this.pickerSrv.curHoverDate; @@ -193,7 +193,7 @@ export class YearPanelComponent implements OnInit, OnDestroy { } else if (this.pickerSrv.currentActiveInput === 'end' && !this.pickerSrv.curRangeDate[0]) { this.pickerSrv.currentActiveInput = 'start'; } else { - this.pickerSrv.closeDropdownEvent.next(); + this.pickerSrv.closeDropdownEvent.next(false); } } @@ -203,7 +203,7 @@ export class YearPanelComponent implements OnInit, OnDestroy { }); if (this.pickerSrv.closeAfterSelected) { - this.pickerSrv.closeDropdownEvent.next(); + this.pickerSrv.closeDropdownEvent.next(false); } } diff --git a/devui/datepicker-pro/ng-package.json b/devui/datepicker-pro/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/datepicker-pro/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/datepicker-pro/package.json b/devui/datepicker-pro/package.json deleted file mode 100644 index 3b9bd979..00000000 --- a/devui/datepicker-pro/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } - \ No newline at end of file diff --git a/devui/datepicker-pro/range-datepicker-pro.component.scss b/devui/datepicker-pro/range-datepicker-pro.component.scss index 04a10652..dd1151a9 100644 --- a/devui/datepicker-pro/range-datepicker-pro.component.scss +++ b/devui/datepicker-pro/range-datepicker-pro.component.scss @@ -10,6 +10,8 @@ box-sizing: border-box; width: 100%; min-height: 24px; + display: flex; + align-items: center; .devui-input { padding: 4px 8px; @@ -33,12 +35,13 @@ } &.devui-end-side { - left: calc(50% + 20px); + left: calc(50% + 12px); } } &-icon { vertical-align: bottom; + height: 16px; } .close-icon-wrapper { diff --git a/devui/datepicker-pro/range-datepicker-pro.component.ts b/devui/datepicker-pro/range-datepicker-pro.component.ts index 6a97ae95..c36b2455 100644 --- a/devui/datepicker-pro/range-datepicker-pro.component.ts +++ b/devui/datepicker-pro/range-datepicker-pro.component.ts @@ -86,7 +86,7 @@ export class RangeDatepickerProComponent implements OnInit, OnDestroy, AfterView i18nText; _dateValue = []; datepickerConvert: DefaultDateConverter; - unsubscribe$ = new Subject(); + unsubscribe$ = new Subject(); isOpen = false; strWidth = 0; @@ -303,6 +303,8 @@ export class RangeDatepickerProComponent implements OnInit, OnDestroy, AfterView value: this.pickerSrv.curRangeDate }); + this.onChange(this.pickerSrv.curRangeDate); + if (this.showTime) { this.pickerSrv.updateTimeChange.next({ activeInput: type, diff --git a/devui/datepicker/demo/datepicker-demo.module.ts b/devui/datepicker/demo/datepicker-demo.module.ts index 57b9e038..ef7ecb64 100755 --- a/devui/datepicker/demo/datepicker-demo.module.ts +++ b/devui/datepicker/demo/datepicker-demo.module.ts @@ -41,7 +41,7 @@ import { TwoDatepickerFormatComponent } from './two-datepicker-format/two-datepi DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DatepickerDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/datepicker/ng-package.json b/devui/datepicker/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/datepicker/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/datepicker/package.json b/devui/datepicker/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/datepicker/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/design-token/animation/demo/design-animation-demo.module.ts b/devui/design-token/animation/demo/design-animation-demo.module.ts index c5d42225..600cf858 100644 --- a/devui/design-token/animation/demo/design-animation-demo.module.ts +++ b/devui/design-token/animation/demo/design-animation-demo.module.ts @@ -21,7 +21,7 @@ import { DesignAnimationDemoComponent } from './design-animation-demo.component' DDemoNavModule, TabsModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DesignAnimationDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/design-token/border-radius/demo/border-radius/border-radius.component.html b/devui/design-token/border-radius/demo/border-radius/border-radius.component.html index e86eee57..518ae1c9 100644 --- a/devui/design-token/border-radius/demo/border-radius/border-radius.component.html +++ b/devui/design-token/border-radius/demo/border-radius/border-radius.component.html @@ -6,11 +6,6 @@

          {{ 'components.design-border-radius.cornerDemo.instan [width]="'150px'" > - {{ 'components.design-color.colorDemo.instance.title' {{ 'components.design-color.colorDemo.instance.defaultTable.colorVar' | translate }} - {{ 'components.design-color.colorDemo.instance.defaultTable.normalColor' | translate }} - {{ 'components.design-color.colorDemo.instance.defaultTable.darkColor' | translate }} {{ 'components.design-color.colorDemo.instance.defaultTable.themeValue' | translate }} {{ 'components.design-color.colorDemo.instance.defaultTable.description' | translate }} @@ -35,18 +33,6 @@

          {{ 'components.design-color.colorDemo.instance.title'

          {{ rowItem?.name }} - -
          - {{ rowItem?.light }} -
          -
          - - -
          - {{ rowItem?.dark }} -
          -
          -
          {{ rowItem?.themeValue }} @@ -71,17 +57,7 @@

          {{ 'components.design-color.colorDemo.instance.title' {{ col }}

          -
          - - - - - - - - - -
          +
          diff --git a/devui/design-token/color/demo/design-color-demo.module.ts b/devui/design-token/color/demo/design-color-demo.module.ts index e6df8602..55cbb522 100644 --- a/devui/design-token/color/demo/design-color-demo.module.ts +++ b/devui/design-token/color/demo/design-color-demo.module.ts @@ -21,7 +21,7 @@ import { DesignColorDemoComponent } from './design-color-demo.component'; DDemoNavModule, TabsModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DesignColorDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/design-token/font/demo/design-font-demo.module.ts b/devui/design-token/font/demo/design-font-demo.module.ts index 671d0bb9..a3cd77de 100644 --- a/devui/design-token/font/demo/design-font-demo.module.ts +++ b/devui/design-token/font/demo/design-font-demo.module.ts @@ -21,7 +21,7 @@ import { FontComponent } from './font/font.component'; DDemoNavModule, TabsModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DesignFontDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/design-token/font/demo/font/font.component.html b/devui/design-token/font/demo/font/font.component.html index 0a8551cc..6c0ec9f8 100644 --- a/devui/design-token/font/demo/font/font.component.html +++ b/devui/design-token/font/demo/font/font.component.html @@ -13,11 +13,6 @@

          {{ 'components.design-font.fontDemo.instance.tableTit - {{ 'components.design-shadow.shadowDemo.instance.desc [width]="'150px'" > - this.dragDropSyncService.updateDragSyncList(list) ) - ).add( + ); + this.sub.add( this.dropSyncList.changes.subscribe( list => this.dragDropSyncService.updateDropSyncList(list) ) diff --git a/devui/dragdrop/directives/draggable.directive.ts b/devui/dragdrop/directives/draggable.directive.ts index 986e8f75..2e936712 100755 --- a/devui/dragdrop/directives/draggable.directive.ts +++ b/devui/dragdrop/directives/draggable.directive.ts @@ -119,7 +119,8 @@ export class DraggableDirective implements OnInit, AfterViewInit, OnDestroy { } dropSubscription() { - this.dragDropService.newSubscription().add( + const dragDropSub = this.dragDropService.newSubscription(); + dragDropSub.add( this.dragDropService.dropEvent.subscribe((event) => { this.mouseOverElement = undefined; this.renderer.removeClass(this.el.nativeElement, this.dragOverClass); @@ -140,7 +141,8 @@ export class DraggableDirective implements OnInit, AfterViewInit, OnDestroy { this.dragDropService.draggedElIdentity = undefined; } this.dragDropService.subscription.unsubscribe(); - })).add( + })); + dragDropSub.add( this.dragDropService.dragElShowHideEvent.subscribe(this.dragElShowHideEvent) ); } @@ -191,7 +193,7 @@ export class DraggableDirective implements OnInit, AfterViewInit, OnDestroy { this.dragDropService.dragFollowOptions = this.dragFollowOptions; this.dragDropService.dragItemParentName = this.dragItemParentName; this.dragDropService.dragItemChildrenName = this.dragItemChildrenName; - this.beforeDragStartEvent.next(); + this.beforeDragStartEvent.next(true); if (this.dragPreviewDirective && this.dragPreviewDirective.dragPreviewTemplate) { this.dragDropService.dragFollow = true; this.dragDropService.dragPreviewDirective = this.dragPreviewDirective; diff --git a/devui/dragdrop/directives/drop-sort-sync.directive.ts b/devui/dragdrop/directives/drop-sort-sync.directive.ts index a1602ea2..8d69740a 100644 --- a/devui/dragdrop/directives/drop-sort-sync.directive.ts +++ b/devui/dragdrop/directives/drop-sort-sync.directive.ts @@ -36,7 +36,8 @@ export class DropSortSyncDirective extends DescendantChildren { + under.dispatchEvent(ev); + }, 0); return event; } } diff --git a/devui/drawer/demo/drawer-demo.module.ts b/devui/drawer/demo/drawer-demo.module.ts index e0a9a8bd..96bae0c8 100755 --- a/devui/drawer/demo/drawer-demo.module.ts +++ b/devui/drawer/demo/drawer-demo.module.ts @@ -28,7 +28,7 @@ import { UndestroyableComponent } from './undestroyable/undestroyable.component' DDemoNavModule, TextInputModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DrawerDemoComponent }, { path: 'api', diff --git a/devui/drawer/ng-package.json b/devui/drawer/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/drawer/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/drawer/package.json b/devui/drawer/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/drawer/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/dropdown/demo/add-icon/add-icon.component.html b/devui/dropdown/demo/add-icon/add-icon.component.html index c53875d0..b3cacf60 100755 --- a/devui/dropdown/demo/add-icon/add-icon.component.html +++ b/devui/dropdown/demo/add-icon/add-icon.component.html @@ -5,7 +5,7 @@

          @@ -41,13 +41,13 @@
          Align Center
          diff --git a/devui/dropdown/demo/basic/basic.component.html b/devui/dropdown/demo/basic/basic.component.html index 5353acea..099fbeff 100755 --- a/devui/dropdown/demo/basic/basic.component.html +++ b/devui/dropdown/demo/basic/basic.component.html @@ -11,25 +11,25 @@
        • - New + New
        • - Delete + Delete
        • - Item 1 + Item 1
        • - Item 3 + Item 3
        • - Item 4 + Item 4
@@ -48,25 +48,25 @@
Attached to Body to avoid being blocked by container with scrollbar
  • - New + New
  • - Delete + Delete
  • - Item 1 + Item 1
  • - Item 3 + Item 3
  • - Item 4 + Item 4
  • diff --git a/devui/dropdown/demo/close-scope/close-scope.component.html b/devui/dropdown/demo/close-scope/close-scope.component.html index df637ebe..8ea5919a 100755 --- a/devui/dropdown/demo/close-scope/close-scope.component.html +++ b/devui/dropdown/demo/close-scope/close-scope.component.html @@ -13,13 +13,13 @@

    Click Outside to Close Dropdown Menu

  • - Item 2 + Item 2
  • - Item 3 + Item 3
  • @@ -40,13 +40,13 @@

    Custom Control of Closing

  • - Item 2 + Item 2
  • - Close + Close
  • diff --git a/devui/dropdown/demo/dropdown-demo.module.ts b/devui/dropdown/demo/dropdown-demo.module.ts index 4a94dbf5..a57bacda 100755 --- a/devui/dropdown/demo/dropdown-demo.module.ts +++ b/devui/dropdown/demo/dropdown-demo.module.ts @@ -35,7 +35,7 @@ import { DropdownSetIsOpenComponent } from './set-is-open/dropdown-set-is-open.c IconModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DropdownDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/dropdown/demo/focus/focus.component.html b/devui/dropdown/demo/focus/focus.component.html index 80d5c0d0..1e0ab205 100755 --- a/devui/dropdown/demo/focus/focus.component.html +++ b/devui/dropdown/demo/focus/focus.component.html @@ -14,25 +14,25 @@
    Using Tab navigate to Dropdown Toggle Element, it will auto open
  • - New + New
  • - Delete + Delete
  • - Item 1 + Item 1
  • - Item 3 + Item 3
  • - Item 4 + Item 4
  • @@ -55,25 +55,25 @@
    auto focus after initiating, use toggleOnFocus at the same time to open menu
  • - New + New
  • - Delete + Delete
  • - Item 1 + Item 1
  • - Item 3 + Item 3
  • - Item 4 + Item 4
  • diff --git a/devui/dropdown/demo/hover/hover.component.html b/devui/dropdown/demo/hover/hover.component.html index ec51ac14..dd2a8d8c 100755 --- a/devui/dropdown/demo/hover/hover.component.html +++ b/devui/dropdown/demo/hover/hover.component.html @@ -2,9 +2,9 @@ diff --git a/devui/dropdown/demo/manually/manually.component.html b/devui/dropdown/demo/manually/manually.component.html index 5a01c63c..c4088ac0 100644 --- a/devui/dropdown/demo/manually/manually.component.html +++ b/devui/dropdown/demo/manually/manually.component.html @@ -2,10 +2,10 @@ diff --git a/devui/dropdown/demo/multi-level/multi-level.component.html b/devui/dropdown/demo/multi-level/multi-level.component.html index edc8a694..0aa6ab10 100644 --- a/devui/dropdown/demo/multi-level/multi-level.component.html +++ b/devui/dropdown/demo/multi-level/multi-level.component.html @@ -8,34 +8,34 @@

    Click

    @@ -50,34 +50,34 @@

    Hover

    @@ -92,34 +92,34 @@

    Click to Open, Mouse Leave Menu Auto Close

    diff --git a/devui/dropdown/demo/set-is-open/dropdown-set-is-open.component.html b/devui/dropdown/demo/set-is-open/dropdown-set-is-open.component.html index 462a44f3..e3cba688 100644 --- a/devui/dropdown/demo/set-is-open/dropdown-set-is-open.component.html +++ b/devui/dropdown/demo/set-is-open/dropdown-set-is-open.component.html @@ -2,10 +2,10 @@ diff --git a/devui/dropdown/doc/api-cn.md b/devui/dropdown/doc/api-cn.md index 6fef317c..e5cf28d6 100644 --- a/devui/dropdown/doc/api-cn.md +++ b/devui/dropdown/doc/api-cn.md @@ -117,3 +117,7 @@ appendToBodyDirections 默认的显示顺序为 ['rightDown', 'leftDown', 'right ## dDropDownMenu 用在需要展开和关闭的菜单内容上,参考 demo。 + +## dDropDownMenuItem + +用在下拉选项上,参考 demo。 diff --git a/devui/dropdown/doc/api-en.md b/devui/dropdown/doc/api-en.md index ac3be8fd..35cd7f6b 100644 --- a/devui/dropdown/doc/api-en.md +++ b/devui/dropdown/doc/api-en.md @@ -114,3 +114,7 @@ Used for menu control objects. For details, see demo. ## dDropDownMenu Used to expand and close menus. For details, see the demo. + +## dDropDownMenuItem + +Used for drop-down list items. For details, see the demo. diff --git a/devui/dropdown/dropdown-item.directive.ts b/devui/dropdown/dropdown-item.directive.ts new file mode 100644 index 00000000..c6ea3bb5 --- /dev/null +++ b/devui/dropdown/dropdown-item.directive.ts @@ -0,0 +1,9 @@ +import { Directive, HostBinding } from '@angular/core'; + +@Directive({ + selector: '[dDropDownMenuItem]', + exportAs: 'd-dropdown-menu-item', +}) +export class DropDownMenuItemDirective { + @HostBinding('class.devui-dropdown-item') itemClass = true; +} diff --git a/devui/dropdown/dropdown.module.ts b/devui/dropdown/dropdown.module.ts new file mode 100644 index 00000000..1aa238c2 --- /dev/null +++ b/devui/dropdown/dropdown.module.ts @@ -0,0 +1,22 @@ +import { OverlayModule } from '@angular/cdk/overlay'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { WindowRefModule } from 'ng-devui/window-ref'; +import { DropDownMenuItemDirective } from './dropdown-item.directive'; +import { DropDownMenuDirective } from './dropdown-menu.directive'; +import { DropDownToggleDirective } from './dropdown-toggle.directive'; +import { DropDownAppendToBodyComponent } from './dropdown.component'; +import { DropDownDirective } from './dropdown.directive'; + +@NgModule({ + imports: [CommonModule, OverlayModule, WindowRefModule], + exports: [DropDownDirective, DropDownMenuItemDirective, DropDownMenuDirective, DropDownToggleDirective, DropDownAppendToBodyComponent], + declarations: [ + DropDownDirective, + DropDownMenuItemDirective, + DropDownMenuDirective, + DropDownToggleDirective, + DropDownAppendToBodyComponent, + ], +}) +export class DropDownModule {} diff --git a/devui/dropdown/dropdown.spec.ts b/devui/dropdown/dropdown.spec.ts index 5243dafa..02d59a1a 100644 --- a/devui/dropdown/dropdown.spec.ts +++ b/devui/dropdown/dropdown.spec.ts @@ -6,7 +6,7 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { DropDownMenuDirective } from './dropdown-menu.directive'; import { DropDownToggleDirective } from './dropdown-toggle.directive'; import { DropDownDirective } from './dropdown.directive'; -import { DropDownModule } from './dropdown.moudule'; +import { DropDownModule } from './dropdown.module'; @Component({ template: `
    @@ -24,16 +24,16 @@ import { DropDownModule } from './dropdown.moudule'; @@ -84,16 +84,16 @@ class TestDropdownComponent { @@ -123,16 +123,16 @@ class TestDropdownAppendToBodyComponent { @@ -155,45 +155,45 @@ class TestDropdownToggleComponent { diff --git a/devui/dropdown/ng-package.json b/devui/dropdown/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/dropdown/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/dropdown/package.json b/devui/dropdown/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/dropdown/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/dropdown/public-api.ts b/devui/dropdown/public-api.ts index 60338acf..aa2bae9d 100755 --- a/devui/dropdown/public-api.ts +++ b/devui/dropdown/public-api.ts @@ -1,6 +1,7 @@ -export * from './dropdown.moudule'; +export * from './dropdown-item.directive'; export * from './dropdown-menu.directive'; export * from './dropdown-toggle.directive'; export * from './dropdown.component'; export * from './dropdown.directive'; +export * from './dropdown.module'; export * from './dropdown.service'; diff --git a/devui/editable-select/demo/editable-select-demo.module.ts b/devui/editable-select/demo/editable-select-demo.module.ts index d3decaa5..755b3418 100755 --- a/devui/editable-select/demo/editable-select-demo.module.ts +++ b/devui/editable-select/demo/editable-select-demo.module.ts @@ -29,7 +29,7 @@ import { WithSearchFunctionComponent } from './search-function/with-search-funct ButtonModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: EditableSelectDemoComponent }, { path: 'api', diff --git a/devui/editable-select/ng-package.json b/devui/editable-select/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/editable-select/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/editable-select/package.json b/devui/editable-select/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/editable-select/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/form/demo/form-demo.component.html b/devui/form/demo/form-demo.component.html index 1bbcd8bd..1b0d4957 100644 --- a/devui/form/demo/form-demo.component.html +++ b/devui/form/demo/form-demo.component.html @@ -49,49 +49,63 @@ -
    +
    +
    {{ 'components.form.innerValidatorDemo.title' | translate }}
    +
    {{ 'components.form.innerValidatorDemo.subtitle' | translate }}
    +
    + + + +
    + +
    +
    {{ 'components.form.customerValidatorDemo.title' | translate }}
    +
    + + + +
    + +
    +
    {{ 'components.form.customErrorStrategyDemo.title' | translate }}
    +
    + + + +
    + +
    +
    {{ 'components.form.customMessageShowDemo.title' | translate }}
    +
    + + + +
    + +
    +
    {{ 'components.form.debounceTimeDemo.title' | translate }}
    +
    + + + +
    -
    {{ 'components.form.templateValidateDemo.title' | translate }}
    -
    -
    -
    {{ 'components.form.innerValidatorDemo.title' | translate }}
    -
    - - - -
    {{ 'components.form.customerValidatorDemo.title' | translate }}
    -
    - - - -
    {{ 'components.form.customErrorStrategyDemo.title' | translate }}
    -
    - - - -
    {{ 'components.form.customMessageShowDemo.title' | translate }}
    -
    - - - -
    {{ 'components.form.debounceTimeDemo.title' | translate }}
    -
    - - - -
    {{ 'components.form.validateTemplateForm.title' | translate }}
    -
    - - - -
    {{ 'components.form.userRegisterDemo.title' | translate }}
    -
    - - - -
    +
    {{ 'components.form.validateTemplateForm.title' | translate }}
    +
    + + + +
    + +
    +
    {{ 'components.form.userRegisterDemo.title' | translate }}
    +
    + + +
    +
    {{ 'components.form.validateReactiveDemo.title' | translate }}
    diff --git a/devui/form/demo/form-demo.component.ts b/devui/form/demo/form-demo.component.ts index ca1da5e1..5b0edc1e 100644 --- a/devui/form/demo/form-demo.component.ts +++ b/devui/form/demo/form-demo.component.ts @@ -218,7 +218,13 @@ export class FormDemoComponent implements OnInit, OnDestroy { { dAnchorLink: 'demo-label-horizontal', value: values['demo-label-horizontal'] }, { dAnchorLink: 'demo-modal', value: values['demo-modal'] }, { dAnchorLink: 'demo-multi-col', value: values['demo-multi-col'] }, + { dAnchorLink: 'demo-inner-validator', value: values['demo-inner-validator'] }, + { dAnchorLink: 'demo-custom-validator', value: values['demo-custom-validator'] }, + { dAnchorLink: 'demo-error-strategy', value: values['demo-error-strategy'] }, + { dAnchorLink: 'demo-custom-message', value: values['demo-custom-message'] }, + { dAnchorLink: 'demo-debounce-time', value: values['demo-debounce-time'] }, { dAnchorLink: 'demo-validate-template', value: values['demo-validate-template'] }, + { dAnchorLink: 'demo-user-register', value: values['demo-user-register'] }, { dAnchorLink: 'demo-validate-reactive', value: values['demo-validate-reactive'] }, { dAnchorLink: 'demo-custom-status', value: values['demo-custom-status'] }, { dAnchorLink: 'demo-validate-sync', value: values['demo-validate-sync'] }, diff --git a/devui/form/demo/form-demo.module.ts b/devui/form/demo/form-demo.module.ts index 88b4b36c..859b51f1 100644 --- a/devui/form/demo/form-demo.module.ts +++ b/devui/form/demo/form-demo.module.ts @@ -84,7 +84,7 @@ import { ValidateUpdateComponent } from './validate-update/validate-update.compo EditableSelectModule, DatepickerModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: FormDemoComponent }, { path: 'api', diff --git a/devui/form/demo/validate-cross-component/validate-cross-component.component.ts b/devui/form/demo/validate-cross-component/validate-cross-component.component.ts index 30da3e04..19c9c401 100644 --- a/devui/form/demo/validate-cross-component/validate-cross-component.component.ts +++ b/devui/form/demo/validate-cross-component/validate-cross-component.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; +import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { DFormGroupRuleDirective, DValidateRules, FormLayout } from 'ng-devui/form'; import { of } from 'rxjs'; import { delay, map } from 'rxjs/operators'; @@ -15,9 +15,9 @@ export class ValidateCrossComponentComponent implements OnInit { childUser: null, }; - userFormGroup = new FormGroup({ - username: new FormControl(this.formData.userName), - childUser: new FormControl(this.formData.childUser), + userFormGroup = new UntypedFormGroup({ + username: new UntypedFormControl(this.formData.userName), + childUser: new UntypedFormControl(this.formData.childUser), }); formRules: { [key: string]: DValidateRules } = { diff --git a/devui/form/demo/validate-reactive/validate-reactive.component.ts b/devui/form/demo/validate-reactive/validate-reactive.component.ts index a0418098..d71a468a 100644 --- a/devui/form/demo/validate-reactive/validate-reactive.component.ts +++ b/devui/form/demo/validate-reactive/validate-reactive.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; +import { UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { DFormGroupRuleDirective, DValidateRules, FormLayout } from 'ng-devui/form'; import { of } from 'rxjs'; import { delay, map } from 'rxjs/operators'; @@ -19,12 +19,12 @@ export class ValidateReactiveComponent implements OnInit { confirmPassword: '', }; - singleSelectControl = new FormControl(null); + singleSelectControl = new UntypedFormControl(null); - userFormGroup = new FormGroup({ - username: new FormControl(this.formData.userName), - password: new FormControl(this.formData.password), - confirmPassword: new FormControl(this.formData.confirmPassword), + userFormGroup = new UntypedFormGroup({ + username: new UntypedFormControl(this.formData.userName), + password: new UntypedFormControl(this.formData.password), + confirmPassword: new UntypedFormControl(this.formData.confirmPassword), }); singleSelectRules: DValidateRules = { diff --git a/devui/form/demo/validate-template/custom-message-show/custom-message-show.component.html b/devui/form/demo/validate-template/custom-message-show/custom-message-show.component.html index 8ab998eb..e8d995e8 100644 --- a/devui/form/demo/validate-template/custom-message-show/custom-message-show.component.html +++ b/devui/form/demo/validate-template/custom-message-show/custom-message-show.component.html @@ -1,4 +1,4 @@ -
    +

    {{ inputValidate.errorMessage }}

    +
    +
    +
    +
    +
    +
    +
    +
    ``` -# dForm +## dForm -## dForm 参数 +### dForm 参数 -| 参数 | 类型 | 默认 | 说明 | 跳转 Demo |全局配置项| -| :----------------: | :-------: | :-----------------------------------: | :----------: | :------------------------------------------------------------------------- | -------------------------------------------- | -| layout | `'horizontal'\|'vertical'\|'columns'` | 'horizontal' | 可选,设置表单的排列方式 | [基本用法](demo#basic-usage) | -| labelSize | `'sm' \| '' \| 'lg'` | '' | 可选,设置 label 的占宽,未设置默认为 100px,'sm'对应 80px,'lg'对应 150px | [label 横向排列](demo#demo-label-horizontal) | -| labelAlign | `'start' \| 'center' \| 'end'` | 'start' | 可选,设置水平布局方式下,label 对齐方式 | [label 横向排列](demo#demo-label-horizontal) | -|dHasFeedback| `boolean` | false | 可选,设置当前 form 是否显示反馈图标 | | +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 | +| :----------: | :-----------------------------------: | :----------: | :------------------------------------------------------------------------: | :------------------------------------------- | ---------- | +| layout | `'horizontal'\|'vertical'\|'columns'` | 'horizontal' | 可选,设置表单的排列方式 | [基本用法](demo#basic-usage) | +| labelSize | `'sm' \| '' \| 'lg'` | '' | 可选,设置 label 的占宽,未设置默认为 100px,'sm'对应 80px,'lg'对应 150px | [label 横向排列](demo#demo-label-horizontal) | +| labelAlign | `'start' \| 'center' \| 'end'` | 'start' | 可选,设置水平布局方式下,label 对齐方式 | [label 横向排列](demo#demo-label-horizontal) | +| dHasFeedback | `boolean` | false | 可选,设置当前 form 是否显示反馈图标 | | -## dForm 事件 +### dForm 事件 | 参数 | 类型 | 说明 | 跳转 Demo | | :-----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------- | ------------------------------------------------------- | | dSubmit | `EventEmitter<{valid: boolean, directive: `[`DFormGroupRuleDirective`](#dformgroupruledirective) `\| AbstractControlDirective}, errors: {[key: string]: ValidationErrors}>` | 可选,使用 dFormSubmit 绑定元素触发提交时,响应事件 | [模板驱动表单验证(推荐)](demo#demo-validate-template) | -# d-form-item +## d-form-item -## d-form-item 参数 +### d-form-item 参数 | 参数 | 类型 | 默认 | 说明 | 跳转 Demo | | :----------: | :-------: | :---: | :------------------------------------------ | --------------------------------------------- | | dHasFeedback | `boolean` | false | 可选,设置当前 formControl 是否显示反馈图标 | [响应式表单验证](demo#demo-validate-reactive) | -# d-form-label +## d-form-label -## d-form-label 参数 +### d-form-label 参数 | 参数 | 类型 | 默认 | 说明 | 跳转 Demo | | :------: | :-------: | :---: | :------------------------------------------------- | ---------------------------- | @@ -78,9 +78,9 @@ import { FormsModule } from '@angular/forms'; | hasHelp | `boolean` | false | 可选,表单项是否需要帮助指引 | [基本用法](demo#basic-usage) | | helpTips | `string` | '' | 可选,表单项帮助指引提示内容,需配合 `hasHelp`使用 | [基本用法](demo#basic-usage) | -# d-form-control +## d-form-control -## d-form-control 参数 +### d-form-control 参数 | 参数 | 类型 | 默认 | 说明 | 跳转 Demo | | :------------: | :-----------------------------------------: | :--: | :----------------------------------------- | -------------------------------------------- | @@ -88,36 +88,36 @@ import { FormsModule } from '@angular/forms'; | feedbackStatus | [`DFormControlStatus`](#dformcontrolstatus) | -- | 可选,手动指定当前 control 状态反馈 | [指定表单状态](demo#demo-custom-status) | | suffixTemplate | `TemplateRef` | -- | 可选,可传入图标模板作为输入框后缀 | -# dFormSubmit +## dFormSubmit - 在``(需绑定 dForm)中指定触发`submit`的元素。 - 可设置触发事件(默认为'click'),如`dFormSubmit="dblclick"`,设置元素双击时触发`submit`。 -## dFormSubmit 参数 +### dFormSubmit 参数 | 参数 | 类型 | 默认 | 说明 | 跳转 Demo | | :-------------: | :------: | :-----: | :-------------------------------------------------------------------: | :-------------------------------------------: | | dFormSubmit | `string` | 'click' | 可选,配置用于触发 submit 的事件名 | [响应式表单验证](demo#demo-validate-reactive) | | dFormSubmitData | `any` | -- | 可选,配置需要传递与 dSubmit 回调事件数据,可用于需区分多个按钮的场景 | [响应式表单验证](demo#demo-validate-reactive) | -# dFormReset +## dFormReset - 在``(需绑定 dForm)中指定触发`reset`的元素。 - 可设置触发事件(默认为'click'),如`dFormReset="dblclick"`,设置元素双击时触发`reset`。 -## dFormReset 参数 +### dFormReset 参数 | 参数 | 类型 | 默认 | 说明 | 跳转 Demo | | :--------: | :------: | :-----: | :--------------------------------: | :-------: | | dFormReset | `string` | 'click' | 可选,配置用于触发 submit 的事件名 | | -# dValidateRules 表单验证 +## dValidateRules 表单验证 -## 定位 +### 定位 - DevUI 表单验证基于[Angular Form](https://angular.io/guide/forms-overview),完全兼容响应式表单与模板驱动表单。旨在封装与简化表单校验逻辑,你只需配置简单规则,验证消息与验证状态管理全交由 DevUI Form 自动完成。 -## 如何使用 +### 如何使用表单校验 - 当你使用了响应式表单或模板驱动表单(均需在你的模块中引入`Angular FormsModule`): @@ -131,14 +131,14 @@ import { FormsModule } from '@angular/forms'; ``` -## dValidateRules 参数 +### dValidateRules 参数 -| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | -| :------------: | :---------------------------------: | :--: | :--------------------: | :-----------------------------------------------------: | -| dValidateRules | [`DValidateRules`](#dvalidaterules) | -- | 必选,配置你的校验规则 | [模板驱动表单验证(推荐)](demo#demo-validate-template) | -| dValidatePopConfig | [`DPopConfig`](#dpopconfig) | -- | 可选,popover提示配置 | [模板驱动表单验证(推荐)](demo#demo-validate-template) | +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | +| :----------------: | :---------------------------------: | :--: | :--------------------: | :-----------------------------------------------------: | +| dValidateRules | [`DValidateRules`](#dvalidaterules) | -- | 必选,配置你的校验规则 | [模板驱动表单验证(推荐)](demo#demo-validate-template) | +| dValidatePopConfig | [`DPopConfig`](#dpopconfig) | -- | 可选,popover 提示配置 | [模板驱动表单验证(推荐)](demo#demo-validate-template) | -## dValidateSyncKey 参数 +### dValidateSyncKey 参数 表单协同校验。 @@ -146,7 +146,66 @@ import { FormsModule } from '@angular/forms'; | :--------------: | :------: | :--: | :-----------------------------------------------------------------------------------------------------------: | :-------------------------------------: | | dValidateSyncKey | `string` | -- | 必选,配置唯一标识 key,相同 key 表单元素将在其中一个元素值发生变更时,同时触发校验,支持响应式与模板驱动表单 | [表单协同验证](demo#demo-validate-sync) | -# 接口 & 类型定义 +## 封装的校验规则 + +### 使用方法 + +```typescript +// 在 xxx.component.ts 中引入 +import { DValidators } from 'ng-devui/form/validator-directive/validators'; +import { DValidateRules } from 'ng-devui/form/validator-directive/validate.type'; + +const rules: DValidateRules = { + validators: [ + { contains: DValidators.contains('abc'), message: '自定义提示信息', isNgValidator: true }, + { alphabet: DValidators.alphabet, message: '自定义提示信息', isNgValidator: true }, + { whitespace: true } // 因为 whitespace 已经注册到 Angular 中 + ... + ], +}; + +// 自定义校验器的写法可以参考下方代码 +// public static contains(contain: string | number): ValidatorFn { +// return (control: AbstractControl): ValidationErrors | null => { +// if (DValidators.isEmptyInput(control.value) || DValidators.isEmptyInput(contain)) { +// return null; +// } +// return control.value.indexOf(contain) === -1 ? { contains: { requiredContains: contain,actualValue: control.value } } : null; +// }; +// } +// public static alphabet(control: AbstractControl): ValidationErrors | null { +// if (DValidators.isEmptyInput(control.value)) { +// return null; +// } +// return DValidators.AlphabetPattern.test(control.value) ? null : { alphabet: true }; +// } +``` + +```html + + +``` + +### 校验规则 + +| 校验器 | 说明 | +| :---------: | :----------------------------: | +| contains | 校验是否包含 | +| notContains | 校验是否不包含 | +| equal | 校验是否等于 | +| notEqual | 校验是否不等于 | +| port | 校验端口号是否属于 [0, 65535] | +| date | 校验日期是否合法 | +| url | 校验 url 是否合法 | +| integer | 校验是否是整数 | +| digits | 校验是否是数字 | +| number | 校验是否是数字,包括科学计数法 | +| alphabet | 校验是否是字母 | +| script | 校验是否是 script 标签 | +| ipv4 | 校验 ipv4 地址是否合法 | +| ipv6 | 校验 ipv6 地址是否合法 | + +## 接口 & 类型定义 ### DFormControlStatus @@ -181,22 +240,22 @@ DFormGroupRuleDirective 为表单容器对应 dValidateRules 指令对象,以 ```ts export type DValidateRules = - { - validators?: DValidateRule[]; // 同步校验规则 + | { + validators?: DValidateRule[]; // 同步校验规则 - asyncValidators?: DAsyncValidateRule[]; // 异步校验规则 + asyncValidators?: DAsyncValidateRule[]; // 异步校验规则 - asyncDebounceTime?: number; // 异步校验器debounceTime(单位ms),默认为300 + asyncDebounceTime?: number; // 异步校验器debounceTime(单位ms),默认为300 - errorStrategy?: DValidationErrorStrategy; // error更新策略,默认为'dirty' + errorStrategy?: DValidationErrorStrategy; // error更新策略,默认为'dirty' - message?: string | { [key: string]: string }; // 统一配置的message,如果你的某一条校验规则未配置message,将取统一message + message?: string | { [key: string]: string }; // 统一配置的message,如果你的某一条校验规则未配置message,将取统一message - messageShowType?: 'popover' | 'text' | 'none'; // 消息自动显示策略(当前仅单个表单组件下生效),(popover | d-form-item容器内部显示 | 不显示) + messageShowType?: 'popover' | 'text' | 'none'; // 消息自动显示策略(当前仅单个表单组件下生效),(popover | d-form-item容器内部显示 | 不显示) - // 消息显示为popover时,设置popover的内容弹出方向,默认为['right', 'bottom'] - popPosition?: 'top' | 'right' | 'bottom' | 'left' | ('top' | 'right' | 'bottom' | 'left')[]; - } + // 消息显示为popover时,设置popover的内容弹出方向,默认为['right', 'bottom'] + popPosition?: 'top' | 'right' | 'bottom' | 'left' | ('top' | 'right' | 'bottom' | 'left')[]; + } | DValidateRule[]; // 若只需设置同步校验规则,可传同步校验规则数组 ``` diff --git a/devui/form/doc/api-en.md b/devui/form/doc/api-en.md index 843b7723..462f167e 100644 --- a/devui/form/doc/api-en.md +++ b/devui/form/doc/api-en.md @@ -43,34 +43,34 @@ In the page ``` -# dForm +## dForm -## dForm Parameter +### dForm Parameter -| Parameter | Type | Default | Description | Jump to Demo |Global Config| -| :----------------: | :-------: | :-----------------------------------: | :----------: | :----------------------------------------------------------------------- | ------------------------------------------------------------- | -| layout | `'horizontal'\|'vertical'\|'columns'` | 'horizontal' | Optional. Sets the form arrangement mode. | [Basic usage](demo#basic-usage) | -| labelSize | `'sm' \| '' \| 'lg'` | '' | Optional. Sets the width of the label. If this parameter is not set, the default value is 100 px. 'sm' corresponds to 80 px, 'lg' corresponds to 150px | [Label horizontal arrangement](demo#demo-label-horizontal) | -| labelAlign | `'start'\|'center'\|'end'` | 'start' | Optional. This parameter specifies the label alignment mode in horizontal layout mode. | [label horizontal arrangement](demo#demo-label-horizontal) | -|dHasFeedback| `boolean` | false | Optional. Sets whether to display the feedback icon for the current form. | | +| Parameter | Type | Default | Description | Jump to Demo | Global Config | +| :----------: | :-----------------------------------: | :----------: | :----------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------- | ------------- | +| layout | `'horizontal'\|'vertical'\|'columns'` | 'horizontal' | Optional. Sets the form arrangement mode. | [Basic usage](demo#basic-usage) | +| labelSize | `'sm' \| '' \| 'lg'` | '' | Optional. Sets the width of the label. If this parameter is not set, the default value is 100 px. 'sm' corresponds to 80 px, 'lg' corresponds to 150px | [Label horizontal arrangement](demo#demo-label-horizontal) | +| labelAlign | `'start'\|'center'\|'end'` | 'start' | Optional. This parameter specifies the label alignment mode in horizontal layout mode. | [label horizontal arrangement](demo#demo-label-horizontal) | +| dHasFeedback | `boolean` | false | Optional. Sets whether to display the feedback icon for the current form. | | -## dForm Event +### dForm Event | Parameter | Type | Description | Jump to Demo | | :-------: | :------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | | dSubmit | `EventEmitter<{valid: boolean, directive: `[`DFormGroupRuleDirective`](#dformgroupruledirective) `\| AbstractControlDirective}>` | Optional. This event is responded to when the dFormSubmit binding element is used to trigger submission. | [Template-driven form verification (recommended)](demo#demo-validate-template) | -# d-form-item +## d-form-item -## d-form-item parameter +### d-form-item parameter | Parameter | Type | Default | Description | Jump to Demo | | :----------: | :-------: | :-----: | :-------------------------------------------------------------------------------- | ------------------------------------------------------- | | dHasFeedback | `boolean` | false | Optional. Sets whether to display the feedback icon for the current form control. | [Reactive form validation](demo#demo-validate-reactive) | -# d-form-label +## d-form-label -## d-form-label parameter +### d-form-label parameter | Parameter | Type | Default | Description | Jump to Demo | | :-------: | :-------: | :-----: | :--------------------------------------------------------- | ------------------------------- | @@ -78,9 +78,9 @@ In the page | hasHelp | `boolean` | false | Optional. Indicating whether a form item requires help. | [Basic usage](demo#basic-usage) | | helpTips | `string` | '' | Optional. This parameter is used together with `hasHelp`. | [Basic usage](demo#basic-usage) | -# d-form-control +## d-form-control -## d-form-control parameters +### d-form-control parameters | Parameter | Type | Default | Description | Jump to Demo | | :------------: | :-----------------------------------------: | :-----: | :---------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | @@ -88,36 +88,36 @@ In the page | feedbackStatus | [`DFormControlStatus`](#dformcontrolstatus) | -- | Optional. Manually specify the current control status. | [Specify form status](demo#demo-custom-status) | | suffixTemplate | `TemplateRef` | -- | Optional. Pass icon template to be the suffix of Input. | -# dFormSubmit +## dFormSubmit - Specify the element that triggers the `submit` in `` (the dForm needs to be bound). - You can set the trigger event (click by default), for example, `dFormSubmit="dblclick"`, to trigger `submit` when an element is double-clicked. -## dFormSubmit Parameter +### dFormSubmit Parameter | Parameter | Type | Default | Description | Jump to Demo | | :-------------: | :------: | :-----: | :------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------: | | dFormSubmit | `string` | 'click' | Optional. Configure the event name used to trigger submit. | [Reactive form validation](demo#demo-validate-reactive) | | dFormSubmitData | `any` | -- | Optional. Configure the data that needs to be transferred and the dSubmit callback event, which can be used to distinguish multiple buttons. | [Reactive form validation](demo#demo-validate-reactive) | -# dFormReset +## dFormReset - Specify the element that triggers the `reset` in `` (the dForm needs to be bound). - You can set the trigger event (click by default), for example, `dFormReset="dblclick"`, to trigger `reset` when an element is double-clicked. -## dFormReset Parameter +### dFormReset Parameter | Parameter | Type | Default | Description | Jump to Demo | | :--------: | :------: | :-----: | :-------------------------------------------------------: | :----------: | | dFormReset | `string` | 'click' | Optional. Configure the event name for triggering submit. | | -# dValidateRules Form Validation +## dValidateRules Form Validation -## Locating +### Locating - DevUI form verification is based on [Angular Form](https://angular.io/guide/forms-overview) and is fully compatible with responsive forms and template-driven forms. To encapsulate and simplify form validation logic, you only need to configure simple rules. Verification messages and verification status management are automatically completed by DevUI Form. -## How to use +### How to use form validator - When you use a responsive form or a template-driven form (both include `Angular FormsModule` in your module): @@ -131,15 +131,14 @@ import { Forms } from '@angular/forms'; ``` -## dValidateRules Parameter +### dValidateRules Parameter -| Parameter | Type | Default | Description | Jump to Demo | -| :------------: | :---------------------------------: | :-----: | :----------------------------------------: | :----------------------------------------------------------------------------: | -| dValidateRules | [`DValidateRules`](#dvalidaterules) | -- | Required. Configure the verification rule. | [Template-driven form verification (recommended)](demo#demo-validate-template) | -| dValidatePopConfig | [`DPopConfig`](#dpopconfig) | -- | Optional. popover hint config | [Template-driven form verification (recommended)](demo#demo-validate-template) | +| Parameter | Type | Default | Description | Jump to Demo | +| :----------------: | :---------------------------------: | :-----: | :----------------------------------------: | :----------------------------------------------------------------------------: | +| dValidateRules | [`DValidateRules`](#dvalidaterules) | -- | Required. Configure the verification rule. | [Template-driven form verification (recommended)](demo#demo-validate-template) | +| dValidatePopConfig | [`DPopConfig`](#dpopconfig) | -- | Optional. popover hint config | [Template-driven form verification (recommended)](demo#demo-validate-template) | - -## dValidateSyncKey Parameter +### dValidateSyncKey Parameter Collaborative form validation. @@ -147,7 +146,66 @@ Collaborative form validation. | :--------------: | :------: | :-----: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------: | | dValidateSyncKey | `string` | -- | Required. This parameter is mandatory. It specifies the unique key. When the value of one element in the form of the same key changes, verification is triggered. responsive and template-driven forms are supported. | [Form collaboration verification](demo#demo-validate-sync) | -# Interface & Type Definition +## Integrated Validation Rules + +### Using + +```typescript +// import at xxx.component.ts +import { DValidators } from 'ng-devui/form/validator-directive/validators'; +import { DValidateRules } from 'ng-devui/form/validator-directive/validate.type'; + +const rules: DValidateRules = { + validators: [ + { contains: DValidators.contains('abc'), message: 'Custom Info', isNgValidator: true }, + { alphabet: DValidators.alphabet, message: 'Custom Info', isNgValidator: true }, + { whitespace: true } // whitespace has been registered to Angular + ... + ], +}; + +// You can custom your validator like following +// public static contains(contain: string | number): ValidatorFn { +// return (control: AbstractControl): ValidationErrors | null => { +// if (DValidators.isEmptyInput(control.value) || DValidators.isEmptyInput(contain)) { +// return null; +// } +// return control.value.indexOf(contain) === -1 ? { contains: { requiredContains: contain,actualValue: control.value } } : null; +// }; +// } +// public static alphabet(control: AbstractControl): ValidationErrors | null { +// if (DValidators.isEmptyInput(control.value)) { +// return null; +// } +// return DValidators.AlphabetPattern.test(control.value) ? null : { alphabet: true }; +// } +``` + +```html + + +``` + +### Validators + +| Validator | Description | +| :---------: | :----------------------------------------------------: | +| contains | Check if it contains sth. | +| notContains | Check if it not contains sth. | +| equal | Check if it is equal to sth. | +| notEqual | Check if it is not equal to sth. | +| port | Check if a port number is in [0, 65535] | +| date | Check if a date is valid | +| url | Check if a url is valid | +| integer | Check integer | +| digits | Check digit | +| number | Check if it is a number, including scientific notation | +| alphabet | Check if it is an alphabet | +| script | Check if it is a script tag | +| ipv4 | Check if it is a valid ipv4 address | +| ipv6 | Check if it is a valid ipv6 address | + +## Interface & Type Definition ### DFormControlStatus diff --git a/devui/form/form-operation.component.ts b/devui/form/form-operation.component.ts index 74d40be9..326ca2cd 100644 --- a/devui/form/form-operation.component.ts +++ b/devui/form/form-operation.component.ts @@ -62,7 +62,7 @@ export class DFormSubmitDirective implements AfterViewInit, OnDestroy { @Input('dFormSubmitData') data: any; - private destroy$ = new Subject(); + private destroy$ = new Subject(); // TODO:这里是否需要接管如果所关联的表单校验不通过,切换到disabled状态 @@ -106,7 +106,7 @@ export class DFormResetDirective implements AfterViewInit, OnDestroy { } } - private destroy$ = new Subject(); + private destroy$ = new Subject(); constructor(private elementRef: ElementRef, @Optional() @Host() private _dForm: FormDirective) {} diff --git a/devui/form/ng-package.json b/devui/form/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/form/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/form/package.json b/devui/form/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/form/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/form/validator-directive/form-control-rules.directive.ts b/devui/form/validator-directive/form-control-rules.directive.ts index 38452daa..0da055fe 100644 --- a/devui/form/validator-directive/form-control-rules.directive.ts +++ b/devui/form/validator-directive/form-control-rules.directive.ts @@ -463,7 +463,7 @@ export class DFormGroupRuleDirective extends DAbstractControlRuleDirective imple @Input('dValidateRules') rules: DValidateRules; @Output() dRulesStatusChange: EventEmitter = new EventEmitter(); - private destroy$ = new Subject(); + private destroy$ = new Subject(); constructor(@Self() cd: ControlContainer, @Optional() @Host() @SkipSelf() parentDir: DFormGroupRuleDirective, private i18n: I18nService) { super(cd, parentDir); @@ -511,7 +511,7 @@ export class DFormControlRuleDirective extends DAbstractControlRuleDirective imp @Input('dValidatePopConfig') popConfig: DPopConfig; popoverComponentRef: ComponentRef; - private destroy$ = new Subject(); + private destroy$ = new Subject(); popMessage: string; // 最终显示的message get showType() { diff --git a/devui/form/validator-directive/validators.ts b/devui/form/validator-directive/validators.ts index 6758a8e0..e2f47ec6 100644 --- a/devui/form/validator-directive/validators.ts +++ b/devui/form/validator-directive/validators.ts @@ -1,13 +1,223 @@ -import { AbstractControl, ValidationErrors } from '@angular/forms'; +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; +// @dynamic export class DValidators { + // eslint-disable-next-line max-len + private static readonly ScriptPattern = /<+\/?[Ss][Cc][Rr][Ii][Pp][Tt] *.*>*/; + // eslint-disable-next-line max-len + private static readonly UrlPattern = /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i; + private static readonly Ipv4Pattern = /^(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))$/i; + // eslint-disable-next-line max-len + private static readonly Ipv6Pattern = /^(((([\da-f]{1,4}):){7}([\da-f]{1,4}))|(((([\da-f]{1,4}):){1,7}:)|((([\da-f]{1,4}):){6}:([\da-f]{1,4}))|((([\da-f]{1,4}):){5}:(([\da-f]{1,4}):)?([\da-f]{1,4}))|((([\da-f]{1,4}):){4}:(([\da-f]{1,4}):){0,2}([\da-f]{1,4}))|((([\da-f]{1,4}):){3}:(([\da-f]{1,4}):){0,3}([\da-f]{1,4}))|((([\da-f]{1,4}):){2}:(([\da-f]{1,4}):){0,4}([\da-f]{1,4}))|((([\da-f]{1,4}):){1}:(([\da-f]{1,4}):){0,5}([\da-f]{1,4}))|(::(([\da-f]{1,4}):){0,6}([\da-f]{1,4}))|(::([\da-f]{1,4})?))|(((([\da-f]{1,4}):){6}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-f]{1,4}):){5}:(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-f]{1,4}):){4}:(([\da-f]{1,4}):)?(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-f]{1,4}):){3}:(([\da-f]{1,4}):){0,2}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|((([\da-f]{1,4}):){2}:(([\da-f]{1,4}):){0,3}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|(([\da-f]{1,4})::(([\da-f]{1,4}):){0,4}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))|(::(([\da-f]{1,4}):){0,5}(((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5]))\.){3}((1?[1-9]?\d)|(10\d)|(2[0-4]\d)|(25[0-5])))))$/i; + private static readonly AlphabetPattern = /^[a-zA-Z]+(\s+[a-zA-Z]+)*$/; + private static readonly DigitPattern = /^\d+$/; + private static readonly IntegerPattern = /^-?\d+$/; + private static readonly NumberPattern = /^(?:-?\d+|[+-]?[\d]+([\.][\d]+)?([Ee][+-]?[\d]+)?|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/; // 支持科学计数法 + private static readonly PortRange: [number, number] = [0, 65535]; + private static isEmptyInput(value: any): boolean { + return value === null || value.length === 0; + } /* Failed if only has whitespace */ - static whiteSpace(control: AbstractControl): ValidationErrors|null { + public static whiteSpace(control: AbstractControl): ValidationErrors | null { let res = null; if (typeof control.value === 'string' && control.value.length !== 0 && control.value.trim().length === 0) { - res = { 'whitespace': true }; + res = { whitespace: true }; } return res; } + + /** + * 校验是否包含 + * @param contain + * @returns + */ + public static contains(contain: string | number): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (DValidators.isEmptyInput(control.value) || DValidators.isEmptyInput(contain)) { + return null; + } + + return control.value.indexOf(contain) === -1 ? { contains: { requiredContains: contain, actualValue: control.value } } : null; + }; + } + + /** + * 校验是否不包含 + * @param contain + * @returns + */ + public static notContains(contain: string | number): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (DValidators.isEmptyInput(control.value) || DValidators.isEmptyInput(contain)) { + return null; + } + + return control.value.indexOf(contain) !== -1 ? { notContains: { requiredNotContains: contain, actualValue: control.value } } : null; + }; + } + + /** + * 校验是否相等 + * @param equal + * @returns + */ + public static equal(equal: string | number | boolean): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (DValidators.isEmptyInput(control.value) || DValidators.isEmptyInput(equal)) { + return null; + } + + return control.value !== equal ? { equal: { requiredEqual: equal, actualValue: control.value } } : null; + }; + } + + /** + * 校验是否不相等 + * @param equal + * @returns + */ + public static notEqual(equal: string | number): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + if (DValidators.isEmptyInput(control.value) || DValidators.isEmptyInput(equal)) { + return null; + } + + return control.value === equal ? { notEqual: { requiredNotEqual: equal, actualValue: control.value } } : null; + }; + } + + /** + * 校验端口号 + * @param control + * @returns + */ + public static port(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; + } + + return DValidators.DigitPattern.test(control.value) && + control.value >= DValidators.PortRange[0] && + control.value <= DValidators.PortRange[1] + ? null + : { port: { min: DValidators.PortRange[0], max: DValidators.PortRange[1] } }; + } + + /** + * 校验日期是否合法 + * @param control + * @returns + */ + public static date(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; // don't validate empty values to allow optional controls + } + + return !/Invalid|NaN/.test(new Date(control.value).toString()) ? null : { date: true }; + } + + /** + * 校验 url 是否合法 + * @param control + * @returns + */ + public static url(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; // don't validate empty values to allow optional controls + } + + return DValidators.UrlPattern.test(control.value) ? null : { url: true }; + } + + /** + * 校验整数 + * @param control + * @returns + */ + public static integer(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; // don't validate empty values to allow optional controls + } + + return DValidators.IntegerPattern.test(control.value) ? null : { integer: true }; + } + + /** + * 校验是否是数字 + * @param control + * @returns + */ + public static digits(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; // don't validate empty values to allow optional controls + } + + return DValidators.DigitPattern.test(control.value) ? null : { digits: true }; + } + + /** + * 校验数字,支持科学计数法 + * @param control + * @returns + */ + public static number(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; // don't validate empty values to allow optional controls + } + + return DValidators.NumberPattern.test(control.value) ? null : { number: true }; + } + + /** + * 校验是否是字母 + * @param control + * @returns + */ + public static alphabet(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; + } + + return DValidators.AlphabetPattern.test(control.value) ? null : { alphabet: true }; + } + + /** + * 校验是 script 标签 + * @param control + * @returns + */ + public static notScript(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; + } + + return DValidators.ScriptPattern.test(control.value) ? { notScript: true } : null; + } + + /** + * 校验 ipv4 + * @param control + * @returns + */ + public static ipv4(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; + } + + return DValidators.Ipv4Pattern.test(control.value) ? null : { ipv4: true }; + } + + /** + * 校验 ipv6 + * @param control + * @returns + */ + public static ipv6(control: AbstractControl): ValidationErrors | null { + if (DValidators.isEmptyInput(control.value)) { + return null; + } + + return DValidators.Ipv6Pattern.test(control.value) ? null : { ipv6: true }; + } } diff --git a/devui/fullscreen/demo/fullscreen-demo.module.ts b/devui/fullscreen/demo/fullscreen-demo.module.ts index 91304b58..371e7d0e 100644 --- a/devui/fullscreen/demo/fullscreen-demo.module.ts +++ b/devui/fullscreen/demo/fullscreen-demo.module.ts @@ -26,6 +26,7 @@ import { FullscreenDemoNormalComponent } from "./normal/normal.component"; { path: "", redirectTo: "demo", + pathMatch: 'full' }, { path: "demo", diff --git a/devui/fullscreen/ng-package.json b/devui/fullscreen/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/fullscreen/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/fullscreen/package.json b/devui/fullscreen/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/fullscreen/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/gantt/demo/gantt-demo.module.ts b/devui/gantt/demo/gantt-demo.module.ts index 184a4388..6e913e20 100644 --- a/devui/gantt/demo/gantt-demo.module.ts +++ b/devui/gantt/demo/gantt-demo.module.ts @@ -29,7 +29,7 @@ import { TableComponent } from './table/table.component'; TranslateModule, FullscreenModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: GanttDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/gantt/gantt-bar/gantt-bar.component.ts b/devui/gantt/gantt-bar/gantt-bar.component.ts index e9807607..2079ee4a 100644 --- a/devui/gantt/gantt-bar/gantt-bar.component.ts +++ b/devui/gantt/gantt-bar/gantt-bar.component.ts @@ -280,7 +280,7 @@ export class GanttBarComponent implements OnInit, OnChanges, AfterViewInit, OnDe e.stopPropagation(); e.preventDefault(); }), - pluck('pageX') + pluck('pageX') ); this.dragProgressStartListener = fromEvent(this.ganttBarProgress.nativeElement, 'mousedown').pipe( @@ -288,7 +288,7 @@ export class GanttBarComponent implements OnInit, OnChanges, AfterViewInit, OnDe e.stopPropagation(); e.preventDefault(); }), - pluck('pageX'), + pluck('pageX'), map((position: number) => this.mousePositionToAdaptiveValue(position)) ); @@ -297,7 +297,7 @@ export class GanttBarComponent implements OnInit, OnChanges, AfterViewInit, OnDe e.stopPropagation(); e.preventDefault(); }), - pluck('pageX') + pluck('pageX') ); this.resizeBarRightStartListener = fromEvent(this.ganttBarDarggerRight.nativeElement, 'mousedown').pipe( @@ -305,7 +305,7 @@ export class GanttBarComponent implements OnInit, OnChanges, AfterViewInit, OnDe e.stopPropagation(); e.preventDefault(); }), - pluck('pageX') + pluck('pageX') ); this.mouseEndListener = fromEvent(document, 'mouseup'); @@ -314,7 +314,7 @@ export class GanttBarComponent implements OnInit, OnChanges, AfterViewInit, OnDe e.stopPropagation(); e.preventDefault(); }), - pluck('pageX'), + pluck('pageX'), distinctUntilChanged(), takeUntil(this.mouseEndListener) ); diff --git a/devui/gantt/gantt.service.ts b/devui/gantt/gantt.service.ts index a657fb7d..6a01fea7 100644 --- a/devui/gantt/gantt.service.ts +++ b/devui/gantt/gantt.service.ts @@ -23,12 +23,12 @@ export class GanttService { registContainerEvents(scrollContainer: HTMLElement) { // 背景拖拽 - this.mouseDownListener = fromEvent(scrollContainer, 'mousedown').pipe(pluck('pageX')); + this.mouseDownListener = fromEvent(scrollContainer, 'mousedown').pipe(pluck('pageX')); - this.mouseMoveListener = fromEvent(scrollContainer, 'mousemove').pipe(pluck('pageX')); + this.mouseMoveListener = fromEvent(scrollContainer, 'mousemove').pipe(pluck('pageX')); this.mouseEndListener = merge(fromEvent(scrollContainer, 'mouseup'), fromEvent(scrollContainer, 'mouseout')).pipe( - pluck('pageX') + pluck('pageX') ); } diff --git a/devui/gantt/ng-package.json b/devui/gantt/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/gantt/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/gantt/package.json b/devui/gantt/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/gantt/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/i18n/ng-package.json b/devui/i18n/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/i18n/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/i18n/package.json b/devui/i18n/package.json deleted file mode 100644 index 3b9bd979..00000000 --- a/devui/i18n/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } - \ No newline at end of file diff --git a/devui/icon/demo/basic/basic.component.html b/devui/icon/demo/basic/basic.component.html index 6a92a943..1c15adac 100644 --- a/devui/icon/demo/basic/basic.component.html +++ b/devui/icon/demo/basic/basic.component.html @@ -12,8 +12,8 @@

    可交互默认图标 - 正常/禁用/旋转

    链接图标

    - - 首页 + + 如何使用Icon

    文字图标 - 文字后置

    @@ -36,6 +36,11 @@

    文字图标 - 禁用

    无权编辑
    +

    文字图标 - 图标变色,常用于文字表单场景

    + + 暂无描述 + +

    文字图标 - 旋转

    运行中 diff --git a/devui/icon/demo/icon-demo.module.ts b/devui/icon/demo/icon-demo.module.ts index 1dd8f7ef..9a331bf5 100644 --- a/devui/icon/demo/icon-demo.module.ts +++ b/devui/icon/demo/icon-demo.module.ts @@ -26,7 +26,7 @@ import { IconGroupDemoComponent } from './icon-group/icon-group.component'; DataTableModule, DropDownModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: IconDemoComponent }, { path: 'api', component: DevUIApiComponent, data: { diff --git a/devui/icon/doc/api-cn.md b/devui/icon/doc/api-cn.md index 9093e4cb..625dafff 100644 --- a/devui/icon/doc/api-cn.md +++ b/devui/icon/doc/api-cn.md @@ -23,7 +23,7 @@ import { IconModule } from 'ng-devui/icon'; | 参数 | 类型 | 默认 | 说明 | | :------: | :------------------------: | :---: | :------------------------------------------------------------------------------------------ | -| icon | `string\|TemplateRef` | -- | 必选,传入[图标库](https://devui.huawei.com/icon/zh-cn/ruleResource)图标,例如 'icon-add' | +| icon | `string\|TemplateRef` | -- | 必选,传入[图标库](https://devui.design/icon/ruleResource)图标,例如 'icon-add' | | operable | `boolean` | false | 可选,图标是否可操作 | | disabled | `boolean` | false | 可选,图标是否禁用 | | rotate | `number\|'infinite'` | -- | 可选,图标的旋转角度,设置为'infinite'时图标会保持持续旋转 | diff --git a/devui/icon/doc/api-en.md b/devui/icon/doc/api-en.md index fd897616..6542203b 100644 --- a/devui/icon/doc/api-en.md +++ b/devui/icon/doc/api-en.md @@ -23,7 +23,7 @@ In the page: | Parameter | Type | Default | Description | | :-------: | :------------------------: | :-----: | :--------------------------------------------------------------------------------------------------------------------------- | -| icon | `string\|TemplateRef` | -- | (mandatory). Transfer the [icon library](https://devui.huawei.com/icon/zh-cn/ruleResource) icon, for example, 'icon-add' | +| icon | `string\|TemplateRef` | -- | (mandatory). Transfer the [icon library](https://devui.design/icon/ruleResource) icon, for example, 'icon-add' | | operable | `boolean` | false | Optional. Indicates whether the icon is operable. | | disabled | `boolean` | false | Optional. Indicates whether the icon is disabled. | | rotate | `number\|'infinite'` | -- | Optional. Rotation angle of the icon. If the value is ‘infinite’, the icon rotates continuously. | diff --git a/devui/icon/icon.component.scss b/devui/icon/icon.component.scss index caee0976..50fd0cef 100644 --- a/devui/icon/icon.component.scss +++ b/devui/icon/icon.component.scss @@ -1,6 +1,10 @@ @import './icon-style-token.scss'; @import '../style/core/animation'; +:host { + display: inline-flex; +} + .devui-icon { font-size: $devui-icon-font-size; display: inline-block; @@ -81,3 +85,31 @@ ::ng-deep .devui-icon-container i { vertical-align: middle; } + +::ng-deep d-icon.devui-icon-hover { + cursor: pointer; + + &:hover { + .devui-icon-container { + .devui-icon { + color: $devui-icon-fill-hover; + } + } + } +} + +::ng-deep d-icon.devui-icon-link { + cursor: pointer; + + a { + color: $devui-aide-text; + } + + &:hover { + .devui-icon-container { + .devui-icon { + color: $devui-brand; + } + } + } +} diff --git a/devui/icon/icon.component.ts b/devui/icon/icon.component.ts index ccdc672b..3aab17db 100644 --- a/devui/icon/icon.component.ts +++ b/devui/icon/icon.component.ts @@ -1,4 +1,4 @@ -import { Component, ElementRef, Input, NgZone, OnDestroy, OnInit, TemplateRef } from '@angular/core'; +import { Component, Directive, ElementRef, HostBinding, Input, NgZone, OnDestroy, OnInit, TemplateRef } from '@angular/core'; import { fromEvent, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; @Component({ @@ -37,3 +37,18 @@ export class IconComponent implements OnInit, OnDestroy { this.destroy$.complete(); } } + +@Directive({ + selector: `d-icon-link, [dIconLink]`, +}) +export class IconLinkDirective { + @HostBinding('class.devui-icon-link') default = true; +} + + +@Directive({ + selector: `d-icon-hover, [dIconHover]`, +}) +export class IconHoverDirective { + @HostBinding('class.devui-icon-hover') default = true; +} diff --git a/devui/icon/icon.module.ts b/devui/icon/icon.module.ts index 6aa1b1db..50b2a8d7 100644 --- a/devui/icon/icon.module.ts +++ b/devui/icon/icon.module.ts @@ -1,13 +1,13 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { IconGroupComponent } from './icon-group.component'; -import { IconComponent } from './icon.component'; +import { IconComponent, IconHoverDirective, IconLinkDirective } from './icon.component'; @NgModule({ - declarations: [IconComponent,IconGroupComponent], + declarations: [IconComponent,IconGroupComponent,IconLinkDirective,IconHoverDirective], imports: [ CommonModule ], - exports: [IconComponent,IconGroupComponent] + exports: [IconComponent,IconGroupComponent,IconLinkDirective,IconHoverDirective] }) export class IconModule { } diff --git a/devui/icon/ng-package.json b/devui/icon/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/icon/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/icon/package.json b/devui/icon/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/icon/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/image-preview/demo/image-preview-demo.module.ts b/devui/image-preview/demo/image-preview-demo.module.ts index 5b883f24..ea5f42e1 100644 --- a/devui/image-preview/demo/image-preview-demo.module.ts +++ b/devui/image-preview/demo/image-preview-demo.module.ts @@ -27,7 +27,7 @@ import { ZIndexComponent } from './z-index/z-index.component'; SafePipeModule, ButtonModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DImagePreviewDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/image-preview/ng-package.json b/devui/image-preview/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/image-preview/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/image-preview/package.json b/devui/image-preview/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/image-preview/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/input-number/demo/input-number-demo.module.ts b/devui/input-number/demo/input-number-demo.module.ts index 8a2c0f4e..af397f4f 100755 --- a/devui/input-number/demo/input-number-demo.module.ts +++ b/devui/input-number/demo/input-number-demo.module.ts @@ -26,7 +26,7 @@ import { InputNumberRegComponent } from './reg/input-number-reg.component'; FormsModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: InputNumberDemoComponent }, { path: 'api', diff --git a/devui/input-number/ng-package.json b/devui/input-number/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/input-number/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/input-number/package.json b/devui/input-number/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/input-number/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/layout/class.directive.ts b/devui/layout/class.directive.ts index 8df259bb..074c8132 100644 --- a/devui/layout/class.directive.ts +++ b/devui/layout/class.directive.ts @@ -11,7 +11,7 @@ import { DScreenMediaQueryService } from './screen-media-query.service'; export class DClassDirective implements OnInit, OnDestroy { @Input() dClass: DResponseParameter; - private destroy$ = new Subject(); + private destroy$ = new Subject(); private executedClassList: string[] = []; constructor( diff --git a/devui/layout/demo/layout-demo.module.ts b/devui/layout/demo/layout-demo.module.ts index 280f07b7..62b86ed0 100644 --- a/devui/layout/demo/layout-demo.module.ts +++ b/devui/layout/demo/layout-demo.module.ts @@ -40,7 +40,7 @@ import { LayoutTopComponent } from './top/top.component'; TranslateModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: LayoutDemoComponent }, { path: 'api', diff --git a/devui/layout/flex.directive.ts b/devui/layout/flex.directive.ts index 570ed0a6..f2f8d479 100644 --- a/devui/layout/flex.directive.ts +++ b/devui/layout/flex.directive.ts @@ -33,7 +33,7 @@ export class DFlexDirective implements OnInit, OnChanges, OnDestroy { /* TODO:实现这个特性 */ @Input() dFlexWrap: DResponseParameter; - private destroy$ = new Subject(); + private destroy$ = new Subject(); constructor( private elementRef: ElementRef, diff --git a/devui/layout/gutter.directive.ts b/devui/layout/gutter.directive.ts index 690e6022..49ef14cd 100644 --- a/devui/layout/gutter.directive.ts +++ b/devui/layout/gutter.directive.ts @@ -9,7 +9,7 @@ import { DScreenMediaQueryService } from './screen-media-query.service'; }) export class DGutterDirective implements OnInit, OnDestroy { - private destroy$ = new Subject(); + private destroy$ = new Subject(); private executedGutter: [number, number] = [null, null]; @Input() dGutter: DResponseParameter; diff --git a/devui/layout/ng-package.json b/devui/layout/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/layout/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/layout/package.json b/devui/layout/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/layout/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/layout/screen-media-query.service.ts b/devui/layout/screen-media-query.service.ts index f967faff..46b679e5 100644 --- a/devui/layout/screen-media-query.service.ts +++ b/devui/layout/screen-media-query.service.ts @@ -8,7 +8,7 @@ export class DScreenMediaQueryService implements OnDestroy { private currentPoint: DBreakpoint; private pointChangeSub: ReplaySubject<{ currentPoint: DBreakpoint; change: number; compare: { [key: string]: number } }> = new ReplaySubject(1); - private destroy$ = new Subject(); + private destroy$ = new Subject(); // 可以传入一个基准point,返回数据结构{ currentPoint, 变大or变小or没变,比基准point大or小or一样 } public getPoint(): ReplaySubject<{ currentPoint: DBreakpoint; change: number; compare: { [key: string]: number } }> { diff --git a/devui/layout/space.directive.ts b/devui/layout/space.directive.ts index 4e869443..4e50fe52 100644 --- a/devui/layout/space.directive.ts +++ b/devui/layout/space.directive.ts @@ -9,7 +9,7 @@ import { DScreenMediaQueryService } from './screen-media-query.service'; }) export class DSpaceDirective implements OnInit, OnDestroy { - private destroy$ = new Subject(); + private destroy$ = new Subject(); private executedSpace: [number, number] = [null, null]; @Input() dSpace: DResponseParameter; diff --git a/devui/layout/style.directive.ts b/devui/layout/style.directive.ts index 14609c94..f10a3224 100644 --- a/devui/layout/style.directive.ts +++ b/devui/layout/style.directive.ts @@ -11,7 +11,7 @@ import { DScreenMediaQueryService } from './screen-media-query.service'; export class DStyleDirective implements OnInit, OnDestroy { @Input() dStyle: DResponseParameter; - private destroy$ = new Subject(); + private destroy$ = new Subject(); private styleObject = {}; constructor( diff --git a/devui/loading/demo/basic/basic.component.html b/devui/loading/demo/basic/basic.component.html index f00532bf..1463ba0c 100755 --- a/devui/loading/demo/basic/basic.component.html +++ b/devui/loading/demo/basic/basic.component.html @@ -1,6 +1,6 @@
    click me! - +
    diff --git a/devui/loading/demo/loading-demo.module.ts b/devui/loading/demo/loading-demo.module.ts index 6b112bfc..814eeff7 100755 --- a/devui/loading/demo/loading-demo.module.ts +++ b/devui/loading/demo/loading-demo.module.ts @@ -28,7 +28,7 @@ import { SubscriptionComponent } from './subscription/subscription.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: LoadingDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/loading/doc/api-cn.md b/devui/loading/doc/api-cn.md index 747d1460..c8ca23cd 100644 --- a/devui/loading/doc/api-cn.md +++ b/devui/loading/doc/api-cn.md @@ -27,6 +27,7 @@ import { LoadingModule } from 'ng-devui/loading'; | positionType | `string` | 'relative' | 可选,指定`dLoading`宿主元素的定位类型,取值与 css position 属性一致。 | [使用 showLoading 控制](demo#show-loading) | | view | `{top?:string,left?:string}` | {top:'50%',left:'50%'} | 可选,调整 loading 的显示位置,相对于宿主元素的顶部距离与左侧距离 | [基本用法](demo#basic-usage) | | zIndex | `number` | -- | 可选,loading加载提示的 z-index 值 | [基本用法](demo#basic-usage) | +| loadingStyle | [`LoadingStyle`](#LoadingStyle) | `'default'` | 可选,类型 `'default' \| 'infinity'` | [基本用法](demo#basic-usage) | ### LoadingType @@ -34,6 +35,12 @@ import { LoadingModule } from 'ng-devui/loading'; export type LoadingType = Observable | Promise | Array> | Array> | Subscription | undefined; ``` +### LoadingStyle + +```ts +export type LoadingStyle = 'default' | 'infinity'; +``` + # LoadingService 在 component 中引入: @@ -82,4 +89,5 @@ constructor( private loadingService: LoadingService ) {} | positionType | `'static' \| 'relative' \| 'absolute' \| 'fixed' \|'sticky'` | 'relative' | 可选,指定`dLoading`宿主元素的定位类型, |[服务方式调用](demo#full-screen) | view | `{top?:string,left?:string}` | {top:'50%',left:'50%'} | 可选,调整 loading 的显示位置,相对于宿主元素的顶部距离与左侧距离 | [服务方式调用](demo#full-screen) | | zIndex | `number` | -- | 可选,弹出框 z-index 值 | [服务方式调用](demo#full-screen) | -| injector | `Injector` | -- | 可选,可以选择指定将用作组件的父级的注射器 | \ No newline at end of file +| injector | `Injector` | -- | 可选,可以选择指定将用作组件的父级的注射器 | +| loadingStyle | [`LoadingStyle`](#LoadingStyle) | `'default'` | 可选,类型 `'default' \| 'infinity'` | | \ No newline at end of file diff --git a/devui/loading/doc/api-en.md b/devui/loading/doc/api-en.md index 6aaac216..6fbb5561 100644 --- a/devui/loading/doc/api-en.md +++ b/devui/loading/doc/api-en.md @@ -27,6 +27,7 @@ In the page | positionType | `string` | 'relative' | Optional. This parameter specifies the positioning type of the `dLoading` host element. The value is the same as that of the css position attribute | [Using ShowLoading](demo#show-loading) | | view | `{top?:string,left?:string}` | {top: '50%',left:'50%'} | Optional. Adjust the loading display position, that is, the distance between the top and left of the host element | [Basic Usage](demo#basic-usage) | | zIndex | `number` | -- | Optional. Z-index value in the loading displayed. | [Basic Usage](demo#basic-usage) | +| loadingStyle | [`LoadingStyle`](###LoadingStyle) | `'default'` | Optional. Loading type `'default' \| 'infinity'`. | [Basic Usage](demo#basic-usage) | ### LoadingType @@ -34,6 +35,12 @@ In the page export type LoadingType = Observable | Promise | Array> | Array> | Subscription | undefined; ``` +### LoadingStyle + +```ts +export type LoadingStyle = 'default' | 'infinity'; +``` + # LoadingService Import into component @@ -82,4 +89,5 @@ Invoke loadingService.open() in the openFullScreen function to enable loading. T | positionType | `'static' \| 'relative' \| 'absolute' \| 'fixed' \|'sticky'` | 'relative' | Optional. This parameter specifies the positioning type of the `dLoading` host element. |[Service function](demo#full-screen) | view | `{top?:string,left?:string}` | {top: '50%',left:'50%'} | Optional. Adjust the loading display position, that is, the distance between the top and left of the host element | [Service function](demo#full-screen) | | zIndex | `number` | -- | Optional. Z-index value in the loading displayed. | [Service function](demo#full-screen) | -| injector | `Injector` | -- | Optional. You can specify the syringe that will be used as the parent of the component. | \ No newline at end of file +| injector | `Injector` | -- | Optional. You can specify the syringe that will be used as the parent of the component. | +| loadingStyle | [`LoadingStyle`](###LoadingStyle) | `'default'` | Optional. Loading type `'default' \| 'infinity'`. | | \ No newline at end of file diff --git a/devui/loading/loading.component.scss b/devui/loading/loading.component.scss index f3b13ca3..00b96aa9 100755 --- a/devui/loading/loading.component.scss +++ b/devui/loading/loading.component.scss @@ -104,3 +104,34 @@ transform: rotate(360deg) scale(1); } } + +$len: 170px; +$time: 1800ms; + +#infinity-outline { + stroke-dasharray: $len * 0.01, $len; + stroke-dashoffset: 0; + animation: anim $time linear infinite; + opacity: 1; +} + +#infinity-bg { + stroke: $devui-zinc-20; +} + +@keyframes anim { + 0% { + stroke-dasharray: $len * 0, $len; + stroke-dashoffset: -$len * 0; + } + + 55% { + stroke-dasharray: $len * 0.24, $len; + stroke-dashoffset: -$len * 0.36; + } + + 100% { + stroke-dasharray: -$len * 0.93, $len; + stroke-dashoffset: -$len * 0.93; + } +} diff --git a/devui/loading/loading.component.ts b/devui/loading/loading.component.ts index c943728f..b8f5620d 100755 --- a/devui/loading/loading.component.ts +++ b/devui/loading/loading.component.ts @@ -6,31 +6,83 @@ import { SimpleChanges, TemplateRef } from '@angular/core'; +import { LoadingStyle } from './loading.types'; @Component({ selector: 'd-loading', - template: `
    - - - -
    -
    -
    -
    -
    -
    -
    -
    -
    {{message}}
    -
    -
    -
    -
    `, + template: `
    + + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + + + + + + + + + + + +
    +
    {{ message }}
    +
    +
    +
    +
    `, styleUrls: ['./loading.component.scss'], preserveWhitespaces: false, }) -export class LoadingComponent implements OnInit, OnChanges { +export class LoadingComponent implements OnInit, OnChanges { @Input() loadingTemplateRef: TemplateRef; @Input() message: string; @Input() top: string; @@ -38,6 +90,7 @@ export class LoadingComponent implements OnInit, OnChanges { @Input() customPosition: boolean; @Input() target: Element; @Input() zIndex: number; + @Input() loadingStyle: LoadingStyle = 'default'; targetName: string; ngOnInit() { if (this.target) { diff --git a/devui/loading/loading.directive.ts b/devui/loading/loading.directive.ts index fca37fa7..2d7bdbf4 100755 --- a/devui/loading/loading.directive.ts +++ b/devui/loading/loading.directive.ts @@ -1,4 +1,5 @@ import { + ComponentFactoryResolver, ComponentRef, Directive, ElementRef, @@ -14,7 +15,7 @@ import { forkJoin, from, Observable, Subscription, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { LoadingBackdropComponent } from './loading-backdrop.component'; import { LoadingComponent } from './loading.component'; -import { LoadingType } from './loading.types'; +import { LoadingStyle, LoadingType } from './loading.types'; @Directive({ selector: '[dLoading]', exportAs: 'dLoading' @@ -35,11 +36,13 @@ export class LoadingDirective implements OnChanges { @Input() loading: LoadingType; @Input() zIndex: number ; + @Input() loadingStyle: LoadingStyle = 'default'; backdropRef: ComponentRef; loadingRef: ComponentRef; active = true; constructor( + private componentFactoryResolver: ComponentFactoryResolver, private triggerElementRef: ElementRef, private viewContainerRef: ViewContainerRef, private injector: Injector, @@ -127,6 +130,7 @@ export class LoadingDirective implements OnChanges { left: this.view ? this.view.left : '50%', isCustomPosition: !!this.view, zIndex: this.zIndex ? this.zIndex : '', + loadingStyle: this.loadingStyle, }); } diff --git a/devui/loading/loading.service.ts b/devui/loading/loading.service.ts index dcb2982e..39115328 100644 --- a/devui/loading/loading.service.ts +++ b/devui/loading/loading.service.ts @@ -30,6 +30,7 @@ export class LoadingService { view, injector, zIndex, + loadingStyle = 'default' }: ILoadingOptions = {}) { const finalComponentFactoryResolver = this.componentFactoryResolver; @@ -63,6 +64,7 @@ export class LoadingService { left: view ? view.left : '50%', isCustomPosition: !!view, target: target ? target : this.document.body, + loadingStyle: loadingStyle }); this.renderer.setStyle(target, 'position', positionType); diff --git a/devui/loading/loading.types.ts b/devui/loading/loading.types.ts index 25c3f6f2..f624e7d8 100755 --- a/devui/loading/loading.types.ts +++ b/devui/loading/loading.types.ts @@ -5,6 +5,8 @@ import { Observable, Subscription } from 'rxjs'; export type LoadingType = Observable | Promise | Array> | Array> | Subscription | undefined; + +export type LoadingStyle = 'default' | 'infinity'; export interface ILoadingOptions { target?: Element; zIndex?: number; @@ -17,4 +19,6 @@ export interface ILoadingOptions { left?: string; }; injector?: Injector; + loadingStyle?: LoadingStyle; } + diff --git a/devui/loading/ng-package.json b/devui/loading/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/loading/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/loading/package.json b/devui/loading/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/loading/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/mention/assets/common.scss b/devui/mention/assets/common.scss deleted file mode 100644 index 07d4f9f8..00000000 --- a/devui/mention/assets/common.scss +++ /dev/null @@ -1,3 +0,0 @@ -@import '../../style/theme/color'; -@import '../../style/theme/shadow'; -@import '../../style/theme/corner'; diff --git a/devui/mention/demo/async/async.component.ts b/devui/mention/demo/async/async.component.ts index 16ef3a9a..85c84adf 100644 --- a/devui/mention/demo/async/async.component.ts +++ b/devui/mention/demo/async/async.component.ts @@ -1,17 +1,13 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'd-mention-async', templateUrl: './async.component.html', }) -export class AsyncComponent implements OnInit { +export class AsyncComponent { loading = true; suggestions = []; - constructor() {} - - ngOnInit() {} - onSearchChange({ value }) { this.loading = true; this.fetchSuggestions(value, (suggestions) => { diff --git a/devui/mention/demo/custom/custom.component.ts b/devui/mention/demo/custom/custom.component.ts index f43d4e20..3077ccff 100644 --- a/devui/mention/demo/custom/custom.component.ts +++ b/devui/mention/demo/custom/custom.component.ts @@ -1,46 +1,40 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'd-mention-custom', templateUrl: './custom.component.html', }) -export class CustomComponent implements OnInit { +export class CustomComponent { suggestions = [ { name: 'C#', - id: 1 + id: 1, }, { name: 'C', - id: 2 + id: 2, }, { name: 'C++', - id: 3 + id: 3, }, { name: 'Python', - id: 4 + id: 4, }, { name: 'Java', - id: 5 + id: 5, }, { name: 'JavaScript', - id: 6 + id: 6, }, { name: 'Go', - id: 7 - } + id: 7, + }, ]; valueWith = (data) => data.name; - - constructor() {} - - ngOnInit() { - - } } diff --git a/devui/mention/demo/mention-demo.component.html b/devui/mention/demo/mention-demo.component.html index 6a94e413..fa7e69b0 100644 --- a/devui/mention/demo/mention-demo.component.html +++ b/devui/mention/demo/mention-demo.component.html @@ -2,7 +2,7 @@
    {{ 'components.mention.basicDemo.title' | translate }}
    -
    +
    {{ 'components.mention.basicDemo.description' | translate }}
    @@ -10,7 +10,7 @@
    {{ 'components.mention.asyncDemo.title' | translate }}
    -
    +
    {{ 'components.mention.asyncDemo.description' | translate }}
    @@ -18,7 +18,7 @@
    {{ 'components.mention.prefixDemo.title' | translate }}
    -
    +
    {{ 'components.mention.prefixDemo.description' | translate }}
    @@ -26,9 +26,17 @@
    {{ 'components.mention.customDemo.title' | translate }}
    -
    +
    {{ 'components.mention.customDemo.description' | translate }}
    + +
    +
    {{ 'components.mention.toggleDemo.title' | translate }}
    +
    {{ 'components.mention.toggleDemo.description' | translate }}
    + + + +
    diff --git a/devui/mention/demo/mention-demo.component.ts b/devui/mention/demo/mention-demo.component.ts index 934cdb06..794e29cb 100644 --- a/devui/mention/demo/mention-demo.component.ts +++ b/devui/mention/demo/mention-demo.component.ts @@ -5,10 +5,9 @@ import { Subscription } from 'rxjs'; @Component({ selector: 'd-mention-demo', - templateUrl: './mention-demo.component.html' + templateUrl: './mention-demo.component.html', }) export class MentionDemoComponent implements OnInit, OnDestroy { - navItems = []; basicSource: Array = [ @@ -31,6 +30,11 @@ export class MentionDemoComponent implements OnInit, OnDestroy { { title: 'TS', language: 'typescript', code: require('./prefix/prefix.component.ts?raw') }, ]; + toggleSource: Array = [ + { title: 'HTML', language: 'xml', code: require('./toggle/toggle.component.html?raw') }, + { title: 'TS', language: 'typescript', code: require('./toggle/toggle.component.ts?raw') }, + ]; + subs: Subscription = new Subscription(); constructor(private translate: TranslateService) {} @@ -56,10 +60,11 @@ export class MentionDemoComponent implements OnInit, OnDestroy { { dAnchorLink: 'async-usage', value: values['async-usage'] }, { dAnchorLink: 'custom-prefix', value: values['custom-prefix'] }, { dAnchorLink: 'custom-template', value: values['custom-template'] }, + { dAnchorLink: 'use-separator', value: values['use-separator'] }, ]; } - ngOnDestroy () { + ngOnDestroy() { if (this.subs) { this.subs.unsubscribe(); } diff --git a/devui/mention/demo/mention-demo.module.ts b/devui/mention/demo/mention-demo.module.ts index a050a247..39881cfe 100644 --- a/devui/mention/demo/mention-demo.module.ts +++ b/devui/mention/demo/mention-demo.module.ts @@ -4,6 +4,7 @@ import { RouterModule } from '@angular/router'; import { TextareaModule } from 'ng-devui'; import { AnchorModule } from 'ng-devui/anchor'; import { AvatarModule } from 'ng-devui/avatar'; +import { ButtonModule } from 'ng-devui/button'; import { MentionModule } from 'ng-devui/mention'; import { DevUIApiComponent } from 'ng-devui/shared/devui-api/devui-api.component'; import { DevUIApiModule } from 'ng-devui/shared/devui-api/devui-api.module'; @@ -16,6 +17,7 @@ import { CustomComponent } from './custom/custom.component'; import { MentionDemoComponent } from './mention-demo.component'; import { PrefixComponent } from './prefix/prefix.component'; import { TargetComponent } from './target/target.component'; +import { ToggleComponent } from './toggle/toggle.component'; @NgModule({ imports: [ @@ -28,21 +30,21 @@ import { TargetComponent } from './target/target.component'; TextareaModule, MentionModule, AvatarModule, + ButtonModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: MentionDemoComponent }, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), - 'en-us': require('!html-loader!markdown-loader!../doc/api-en.md') + 'en-us': require('!html-loader!markdown-loader!../doc/api-en.md'), }, }, ]), ], - declarations: [MentionDemoComponent, BasicComponent, AsyncComponent, CustomComponent, TargetComponent, PrefixComponent], + declarations: [MentionDemoComponent, BasicComponent, AsyncComponent, CustomComponent, TargetComponent, PrefixComponent, ToggleComponent], exports: [MentionDemoComponent], - }) export class MentionDemoModule {} diff --git a/devui/mention/demo/prefix/prefix.component.ts b/devui/mention/demo/prefix/prefix.component.ts index 58763276..4fc0d3b6 100644 --- a/devui/mention/demo/prefix/prefix.component.ts +++ b/devui/mention/demo/prefix/prefix.component.ts @@ -1,15 +1,14 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; import { MentionOnSearchTypes } from 'ng-devui/mention/mention.types'; @Component({ selector: 'd-mention-prefix', templateUrl: './prefix.component.html', }) -export class PrefixComponent implements OnInit { +export class PrefixComponent { suggestions = []; - prefixes = ['#', '!']; - + tags = ['1.0', '2.0', '3.0']; users = [ 'C#', 'C', @@ -26,11 +25,6 @@ export class PrefixComponent implements OnInit { 'LiveScript', 'CoffeeScript', ]; - tags = ['1.0', '2.0', '3.0']; - - constructor() {} - - ngOnInit() {} searchChangeHandler({ value, trigger }: MentionOnSearchTypes) { this.suggestions = trigger === '#' ? this.users : this.tags; diff --git a/devui/mention/demo/target/target.component.ts b/devui/mention/demo/target/target.component.ts index f5373310..893d2c87 100644 --- a/devui/mention/demo/target/target.component.ts +++ b/devui/mention/demo/target/target.component.ts @@ -2,10 +2,12 @@ import { Component } from '@angular/core'; @Component({ selector: 'd-mention-target', - templateUrl: './target.component.html' + templateUrl: './target.component.html', }) export class TargetComponent { - + mentionValue = ''; + editorRef = null; + beforeShow: any; suggestions = [ 'C#', 'C', @@ -23,17 +25,11 @@ export class TargetComponent { 'CoffeeScript', ]; - mentionValue = ''; - - editorRef = null; - - beforeShow; - - contentChange (e) { + contentChange(e) { this.beforeShow(e); } - afterEditorInit (e) { + afterEditorInit(e) { this.editorRef = e; } } diff --git a/devui/mention/demo/toggle/toggle.component.html b/devui/mention/demo/toggle/toggle.component.html new file mode 100644 index 00000000..40a35ac8 --- /dev/null +++ b/devui/mention/demo/toggle/toggle.component.html @@ -0,0 +1,18 @@ + + {{ mentionSeparatorToggle.prefix ? 'No space before the prefix' : 'Use space in prefix' }} + + + {{ mentionSeparatorToggle.suffix ? 'close suggestions without matching results' : 'Use space at the end' }} + +
    +
    + diff --git a/devui/mention/demo/toggle/toggle.component.ts b/devui/mention/demo/toggle/toggle.component.ts new file mode 100644 index 00000000..77c62255 --- /dev/null +++ b/devui/mention/demo/toggle/toggle.component.ts @@ -0,0 +1,34 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'd-mention-toggle', + templateUrl: './toggle.component.html', + styles: [ + ` + d-button { + margin-right: 8px; + } + `, + ], +}) +export class ToggleComponent { + content = `before separator @C++ after separator`; + mentionSeparator = ' '; + mentionSeparatorToggle = { prefix: true, suffix: true }; + suggestions = [ + 'C#', + 'C', + 'C++', + 'Python', + 'Java', + 'JavaScript', + 'Go', + 'Python', + 'Ruby', + 'F#', + 'TypeScript', + 'SQL', + 'LiveScript', + 'CoffeeScript', + ]; +} diff --git a/devui/mention/doc/api-cn.md b/devui/mention/doc/api-cn.md index 22c862be..9e451cd4 100644 --- a/devui/mention/doc/api-cn.md +++ b/devui/mention/doc/api-cn.md @@ -1,6 +1,6 @@ # 如何使用 -在module中引入: +在 module 中引入: ```ts import { MentionModule } from 'ng-devui/mention'; @@ -13,33 +13,36 @@ import { MentionModule } from 'ng-devui/mention'; ``` # mention + ## mention 参数 -| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | -| :--------: | :--------------------: | :--: | :-------------------------------------------------------------------------- | ------------------------------------------------------------- | -| mentionPosition | `'top' \| 'bottom'` | `bottom` | 可选,建议框位置 | -- | -| mentionSuggestions | `[]` | -- | 必选,建议数据源 | [基本用法](demo#basic-usage) | -| mentionNotFoundContent | `string` | `'No suggestion matched' ` | 可选,用于在没有匹配到数据的时候的提示 | -- | -| mentionLoading | `boolean` | `false` | 可选,异步加载数据源的时候是否显示loading效果 | [异步用法](demo#async-usage) | -| mentionItemTemplate | `TemplateRef` | -- | 可选,自定义建议模板 | [自定义模板](demo#custom-template) | -| dmValueParse | `(value: string) => string = (value) => value;` | -- | 可选,建议选项的取值方法 | [自定义模板](demo#custom-template) | -| mentionTrigger | `string[]` | `['@']` | 可选,触发组件的前缀符 | [自定义前缀](demo#custom-prefix) | +| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | +| ---------------------- | ----------------------------------------------- | ---------------------------------- | ---------------------------------------------------- | ------------------------------------- | +| mentionPosition | `'top' \| 'bottom'` | `bottom` | 可选,建议框位置 | -- | +| mentionSuggestions | `[]` | -- | 必选,建议数据源 | [基本用法](demo#basic-usage) | +| mentionNotFoundContent | `string` | `'No suggestion matched' ` | 可选,用于在没有匹配到数据的时候的提示 | -- | +| mentionLoading | `boolean` | `false` | 可选,异步加载数据源的时候是否显示 loading 效果 | [异步用法](demo#async-usage) | +| mentionItemTemplate | `TemplateRef` | -- | 可选,自定义建议模板 | [自定义模板](demo#custom-template) | +| dmValueParse | `(value: string) => string = (value) => value;` | -- | 可选,建议选项的取值方法 | [自定义模板](demo#custom-template) | +| mentionTrigger | `string[]` | `['@']` | 可选,触发组件的前缀符 | [自定义前缀](demo#custom-prefix) | +| mentionSeparator | `string` | -- | 可选,用于分隔触发组件内容与其他内容,默认为半角空格 | [是否使用间隔符](demo#use-separator) | +| mentionSeparatorToggle | `{ prefix: boolean,`
    `suffix: boolean }` | `{ prefix: false, suffix: false }` | 可选,控制是否用空格分隔组件与其他内容 | [是否使用间隔符](demo#use-separator) | ## mention 事件 -| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | -| :--------: | :--------------------: | :--: | :-------------------------------------------------------------------------- | ------------------------------------------------------------- | -| mentionSelectItem | `any` | -- | 可选,触发选中建议 | [基本用法](demo#basic-usage) | -| mentionAfterMentionInit | -- | -- | 可选,在指令初始化之后返回指令实例 | [基本用法](demo#basic-usage) | -| mentionSearchChange | [`EventEmitter`](#MentionOnSearchTypes) | -- | 可选,输入框change事件 | [自定义前缀](demo#custom-prefix) | +| 参数 | 类型 | 默认值 | 描述 | 跳转 Demo | +| ----------------------- | ------------------------------------------------------------- | ------ | ---------------------------------- | -------------------------------- | +| mentionSelectItem | `any` | -- | 可选,触发选中建议 | [基本用法](demo#basic-usage) | +| mentionAfterMentionInit | -- | -- | 可选,在指令初始化之后返回指令实例 | [基本用法](demo#basic-usage) | +| mentionSearchChange | [`EventEmitter`](#MentionOnSearchTypes) | -- | 可选,输入框 change 事件 | [自定义前缀](demo#custom-prefix) | # 接口 & 类型定义 -### MentionOnSearchTypes +## MentionOnSearchTypes ```ts export interface MentionOnSearchTypes { value: string; trigger: string; } -``` \ No newline at end of file +``` diff --git a/devui/mention/doc/api-en.md b/devui/mention/doc/api-en.md index 93745ee5..c4ebcb31 100644 --- a/devui/mention/doc/api-en.md +++ b/devui/mention/doc/api-en.md @@ -13,25 +13,28 @@ In the page: ``` # mention + ## mention parameters -| Parameter | Type | Default | Description | Jump to Demo | -| :--------: | :--------------------: | :--: | :-------------------------------------------------------------------------- | ------------------------------------------------------------- | -| mentionPosition | `'top' \| 'bottom'` | `bottom` | Option. Recommended box location | [Basic Usage](demo#basic-usage) | -| mentionSuggestions | `[]` | -- | required. Suggested Data Source | [Basic Usage](demo#basic-usage) | -| mentionNotFoundContent | `string` | `'No suggestion matched'` | Option. It is used for prompting when no data is matched. | -- | -| mentionLoading | `boolean` | `false` | Option.Indicates whether to display the loading effect during asynchronous data source loading. | [Async Usage](demo#async-usage) | -| mentionItemTemplate | `TemplateRef` | -- | Option. Custom Recommendation Template | [Custom Template](demo#custom-template) | -| dmValueParse | `(value: string) => string = (value) => value;` | -- | Option. Function that maps an suggestion's value | [Custom Prefix](demo#custom-prefix) | -| mentionTrigger | `string[]` | `['@']` | Option. Prefix for triggering components | [Custom Prefix](demo#custom-prefix) | +| Parameter | Type | Default | Description | Jump to Demo | +| ---------------------- | ----------------------------------------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | +| mentionPosition | `'top' \| 'bottom'` | `bottom` | Option. Recommended box location | [Basic Usage](demo#basic-usage) | +| mentionSuggestions | `[]` | -- | required. Suggested Data Source | [Basic Usage](demo#basic-usage) | +| mentionNotFoundContent | `string` | `'No suggestion matched'` | Option. It is used for prompting when no data is matched. | -- | +| mentionLoading | `boolean` | `false` | Option.Indicates whether to display the loading effect during asynchronous data source loading. | [Async Usage](demo#async-usage) | +| mentionItemTemplate | `TemplateRef` | -- | Option. Custom Recommendation Template | [Custom Template](demo#custom-template) | +| dmValueParse | `(value: string) => string = (value) => value;` | -- | Option. Function that maps an suggestion's value | [Custom Prefix](demo#custom-prefix) | +| mentionTrigger | `string[]` | `['@']` | Option. Prefix for triggering components | [Custom Prefix](demo#custom-prefix) | +| mentionSeparator | `string` | -- | Option.Used to separate the content of the triggering component from other content. The default value is a space. | [Use Separators](demo#use-separator) | +| mentionSeparatorToggle | `{ prefix: boolean,`
    `suffix: boolean }` | `{ prefix: false, suffix: false }` | Option.Controls whether components are separated from other content by spaces | [Use Separators](demo#use-separator) | ## mention Event -| Parameter | Type | Default | Description | Jump to Demo | -| :--------: | :--------------------: | :--: | :-------------------------------------------------------------------------- | ------------------------------------------------------------- | -| mentionSelectItem | `any` | -- | Option. Trigger Selection Suggestion. | [Basic Usage](demo#basic-usage) | -| mentionAfterMentionInit | -- | -- | Option. Returns an directive instance after directive initialization | [Basic Usage](demo#basic-usage) | -| mentionSearchChange | [`EventEmitter`](#MentionOnSearchTypes) | -- | Option. Input box change event | [Custom Prefix](demo#custom-prefix) | +| Parameter | Type | Default | Description | Jump to Demo | +| ----------------------- | ------------------------------------------------------------- | ------- | -------------------------------------------------------------------- | ----------------------------------- | +| mentionSelectItem | `any` | -- | Option. Trigger Selection Suggestion. | [Basic Usage](demo#basic-usage) | +| mentionAfterMentionInit | -- | -- | Option. Returns an directive instance after directive initialization | [Basic Usage](demo#basic-usage) | +| mentionSearchChange | [`EventEmitter`](#MentionOnSearchTypes) | -- | Option. Input box change event | [Custom Prefix](demo#custom-prefix) | # Interface & Type Definition @@ -42,4 +45,4 @@ export interface MentionOnSearchTypes { value: string; trigger: string; } -``` \ No newline at end of file +``` diff --git a/devui/mention/mention.component.scss b/devui/mention/mention.component.scss index 8a2efb47..42e709dc 100644 --- a/devui/mention/mention.component.scss +++ b/devui/mention/mention.component.scss @@ -1,5 +1,7 @@ -@import './assets/common'; +@import '../style/theme/color'; +@import '../style/theme/corner'; @import '../style/core/font'; +@import '../style/theme/shadow'; @import '../style/core/z-index'; .devui-mention-dropdown { diff --git a/devui/mention/mention.component.ts b/devui/mention/mention.component.ts index 348cb690..3039a019 100644 --- a/devui/mention/mention.component.ts +++ b/devui/mention/mention.component.ts @@ -1,4 +1,5 @@ import { Component, ElementRef, QueryList, TemplateRef, ViewChildren } from '@angular/core'; +import { MentionPositionType } from './mention.types'; import { MentionDirective } from './mention.directive'; @Component({ @@ -7,25 +8,15 @@ import { MentionDirective } from './mention.directive'; styleUrls: ['./mention.component.scss'], }) export class MentionComponent { - - @ViewChildren('items', { read: ElementRef }) - items!: QueryList; - + @ViewChildren('items', { read: ElementRef }) items!: QueryList; suggestions = []; - - trigger: MentionDirective; - - value = ''; - activeIndex = -1; - loading = false; - - mentionItemTemplate: TemplateRef; - + value = ''; mentionNotFoundContent = ''; - - position; + mentionItemTemplate: TemplateRef; + trigger: MentionDirective; + position: MentionPositionType; private get focusItemElement(): HTMLElement | null { const itemArr = this.items?.toArray(); @@ -35,9 +26,7 @@ export class MentionComponent { return null; } - constructor() {} - - selectSuggestion (suggestion) { + selectSuggestion(suggestion) { if (this.trigger) { this.trigger.selectSuggestion(suggestion); } diff --git a/devui/mention/mention.directive.ts b/devui/mention/mention.directive.ts index 2b5f3144..55833fa8 100644 --- a/devui/mention/mention.directive.ts +++ b/devui/mention/mention.directive.ts @@ -30,34 +30,28 @@ import { getCaretCoordinates } from './utils'; exportAs: 'dMention', }) export class MentionDirective implements OnInit, OnChanges, AfterViewInit, OnDestroy { - get nativeElement() { - return this.el.nativeElement; - } - - constructor( - private el: ElementRef, - private viewContainerRef: ViewContainerRef, - private cdr: ChangeDetectorRef, - private overlay: Overlay - ) {} @Input() mentionNotFoundContent = 'No suggestion matched'; - @Input() mentionSuggestions = []; - @Input() mentionLoading = false; - @Input() mentionTrigger = ['@']; - + @Input() mentionSeparator = ' '; + @Input() mentionSeparatorToggle = { prefix: false, suffix: false }; @Input() mentionPosition: MentionPositionType = 'bottom'; - @Input() mentionItemTemplate: TemplateRef; - + @Input() mentionValueParse: (value: string) => string = (value) => value; @Output() mentionSelectItem = new EventEmitter(); - @Output() mentionSearchChange: EventEmitter = new EventEmitter(); - @Output() mentionAfterMentionInit: EventEmitter = new EventEmitter(); + isOpen = false; + activeIndex = -1; + unsubscribe$ = new Subject(); + defaultNotFoundText = ''; + + get nativeElement() { + return this.el.nativeElement; + } + private value = ''; private previousValue = ''; private cursorMention: any; @@ -70,15 +64,12 @@ export class MentionDirective implements OnInit, OnChanges, AfterViewInit, OnDes private mentionRef: ComponentRef; private filterSuggestions = []; - isOpen = false; - - activeIndex = -1; - - unsubscribe$ = new Subject(); - - defaultNotFoundText = ''; - - @Input() mentionValueParse: (value: string) => string = (value) => value; + constructor( + private el: ElementRef, + private viewContainerRef: ViewContainerRef, + private cdr: ChangeDetectorRef, + private overlay: Overlay + ) {} @HostListener('keydown', ['$event']) onKeyDown(event) { @@ -130,6 +121,15 @@ export class MentionDirective implements OnInit, OnChanges, AfterViewInit, OnDes } } + ngOnChanges(changes: SimpleChanges): void { + const { mentionSuggestions } = changes; + if (mentionSuggestions && this.isOpen) { + this.previousValue = null; + this.activeIndex = -1; + this.resetMention(false); + } + } + ngOnInit(): void { this.mentionAfterMentionInit.emit(this); } @@ -142,13 +142,9 @@ export class MentionDirective implements OnInit, OnChanges, AfterViewInit, OnDes }); } - ngOnChanges(changes: SimpleChanges): void { - if (Object.prototype.hasOwnProperty.call(changes, 'mentionSuggestions')) { - if (this.isOpen) { - this.previousValue = null; - this.activeIndex = -1; - this.resetMention(false); - } + ngOnDestroy() { + if (this.overlayRef) { + this.overlayRef.dispose(); } } @@ -159,24 +155,31 @@ export class MentionDirective implements OnInit, OnChanges, AfterViewInit, OnDes return; } this.suggestionsFilter(this.cursorMention, emit); - const activeIndex = this.filterSuggestions.indexOf(this.cursorMention.substring(1)); - this.activeIndex = activeIndex >= 0 ? activeIndex : 0; - this.showMention(); + if (this.mentionSeparatorToggle.suffix || (this.filterSuggestions.length && !this.mentionSeparatorToggle.suffix)) { + const activeIndex = this.filterSuggestions.indexOf(this.value); + this.activeIndex = activeIndex >= 0 ? activeIndex : 0; + this.showMention(); + } else if (this.mentionLoading) { + this.showMention(); + } else { + this.hideMention(); + } } checkMention() { - const value = this.nativeElement.value.replace(/[\r\n]/g, ' ') || ''; + const value = this.nativeElement.value.replace(/[\r\n]/g, this.mentionSeparator) || ''; const selectionStart = this.nativeElement.selectionStart; let i = this.mentionTrigger.length; while (i >= 0) { const startPos = value.lastIndexOf(this.mentionTrigger[i], selectionStart); - const endPos = value.indexOf(' ', selectionStart) > -1 ? value.indexOf(' ', selectionStart) : value.length; + const endPos = + value.indexOf(this.mentionSeparator, selectionStart) > -1 ? value.indexOf(this.mentionSeparator, selectionStart) : value.length; const mention = value.substring(startPos, selectionStart); if ( - (startPos > 0 && value[startPos - 1] !== ' ') || + (this.mentionSeparatorToggle.prefix && startPos > 0 && value[startPos - 1] !== this.mentionSeparator) || startPos < 0 || mention.includes(this.mentionTrigger[i], 1) || - mention.includes(' ') + (this.mentionSeparatorToggle.suffix && mention.includes(this.mentionSeparator)) ) { this.cursorMention = null; this.cursorMentionStart = -1; @@ -296,7 +299,7 @@ export class MentionDirective implements OnInit, OnChanges, AfterViewInit, OnDes insertMention(mention: Mention) { const value: string = this.el.nativeElement.value; - const insertValue = mention.mention.trim() + ' '; + const insertValue = `${mention.mention.trim()}${this.mentionSeparatorToggle.suffix ? this.mentionSeparator : ''}`; const newValue = [value.slice(0, mention.startPos + 1), insertValue, value.slice(mention.endPos, value.length)].join(''); this.el.nativeElement.value = newValue; this.value = newValue; @@ -321,10 +324,4 @@ export class MentionDirective implements OnInit, OnChanges, AfterViewInit, OnDes } }); } - - ngOnDestroy() { - if (this.overlayRef) { - this.overlayRef.dispose(); - } - } } diff --git a/devui/mention/mention.module.ts b/devui/mention/mention.module.ts index 4c1a1a0a..ff200642 100644 --- a/devui/mention/mention.module.ts +++ b/devui/mention/mention.module.ts @@ -7,6 +7,6 @@ import { MentionDirective } from './mention.directive'; @NgModule({ imports: [CommonModule, LoadingModule], declarations: [MentionComponent, MentionDirective], - exports: [MentionComponent, MentionDirective] + exports: [MentionComponent, MentionDirective], }) export class MentionModule {} diff --git a/devui/mention/ng-package.json b/devui/mention/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/mention/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/mention/package.json b/devui/mention/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/mention/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/modal/demo/modal-demo.module.ts b/devui/modal/demo/modal-demo.module.ts index 852091a7..7557db50 100755 --- a/devui/modal/demo/modal-demo.module.ts +++ b/devui/modal/demo/modal-demo.module.ts @@ -44,7 +44,7 @@ import { TipsComponent } from './tips/tips.component'; DDemoNavModule, TextInputModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: ModalDemoComponent }, { path: 'api', diff --git a/devui/modal/ng-package.json b/devui/modal/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/modal/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/modal/package.json b/devui/modal/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/modal/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/multi-auto-complete/demo/multi-auto-complete-demo.module.ts b/devui/multi-auto-complete/demo/multi-auto-complete-demo.module.ts index 1ac5c997..f60a8ec3 100644 --- a/devui/multi-auto-complete/demo/multi-auto-complete-demo.module.ts +++ b/devui/multi-auto-complete/demo/multi-auto-complete-demo.module.ts @@ -27,7 +27,7 @@ import { MultiAutoCompleteDemoComponent } from './multi-auto-complete-demo.compo DevUICodeboxModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: MultiAutoCompleteDemoComponent }, { path: 'api', diff --git a/devui/multi-auto-complete/ng-package.json b/devui/multi-auto-complete/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/multi-auto-complete/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/multi-auto-complete/package.json b/devui/multi-auto-complete/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/multi-auto-complete/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/nav-sprite/demo/nav-sprite-demo.module.ts b/devui/nav-sprite/demo/nav-sprite-demo.module.ts index a735b3ec..657af78f 100644 --- a/devui/nav-sprite/demo/nav-sprite-demo.module.ts +++ b/devui/nav-sprite/demo/nav-sprite-demo.module.ts @@ -22,6 +22,7 @@ import { NavSpriteDemoComponent } from "./nav-sprite-demo.component"; { path: "", redirectTo: "demo", + pathMatch: 'full' }, { path: "demo", diff --git a/devui/nav-sprite/doc/api-cn.md b/devui/nav-sprite/doc/api-cn.md index 0a2443b6..980c93fa 100644 --- a/devui/nav-sprite/doc/api-cn.md +++ b/devui/nav-sprite/doc/api-cn.md @@ -16,26 +16,27 @@ import { NavSpriteModule } from 'ng-devui/nav-sprite'; ## dNavSprite 参数 -| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | -| :------------------:| :---------------------------------: | :-------------------------: | :------------------------------ | -------------------------------------------- | -| target | `HTMLElement` | -- | 必选,目录存放的位置 | [基本用法](demo#basic) | -| scrollTarget | `HTMLElement` | -- | 可选,指定滚动容器 | [指定容器用法](demo#scroll) | -| view | `{top?:number,bottom?:number}` | {top:0,bottom:0} | 可选,用于可视区域的调整,比如顶部有固定位置的头部等,数值对应被遮挡的顶部或底部的高度 | [指定容器用法](demo#scroll) | -| hashSupport | `boolean` | `false` | 可选,是否支持锚点 | -- | -| mode | [`SpriteMode`](#SpriteMode) | 'default' | 可选,模式`default \| sprite` | [精灵用法](demo#sprite) | -| maxLevel | `number` | 3 | 可选,生成目录的最大层级 | [精灵用法](demo#sprite) | -| title | `string` | 'menu' | 可选,名称 | [基本用法](demo#basic) | -| isOpen | `boolean` | true | 可选,精灵模式下,目录默认展开 | -- | -| indent | `number` | 2em | 可选,缩进2个占位 | -- | -| width | `number` | 300 | 可选,高度 | [精灵用法](demo#sprite) | -| height | `number` | 400 | 可选,宽度 | [精灵用法](demo#sprite) | -| spriteOption | [`SpriteOption`](#SpriteOption) | [`defaultOption`](#defaultOption) | 可选,sprite模式下的导航初始位置 | [精灵用法](demo#sprite) | -| navItemTemplate | `TemplateRef` | -- | 可选,单条目录模板 | [精灵用法 ](demo#sprite) | +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | +| :-------------: | :-----------------------------: | :-------------------------------: | :------------------------------------------------------------------------------------- | --------------------------- | +| target | `HTMLElement` | -- | 必选,目录存放的位置 | [基本用法](demo#basic) | +| scrollTarget | `HTMLElement` | -- | 可选,指定滚动容器 | [指定容器用法](demo#scroll) | +| view | `{top?:number,bottom?:number}` | {top:0,bottom:0} | 可选,用于可视区域的调整,比如顶部有固定位置的头部等,数值对应被遮挡的顶部或底部的高度 | [指定容器用法](demo#scroll) | +| hashSupport | `boolean` | `false` | 可选,是否支持锚点 | -- | +| mode | [`SpriteMode`](#SpriteMode) | 'default' | 可选,模式`default \| sprite` | [精灵用法](demo#sprite) | +| maxLevel | `number` | 3 | 可选,生成目录的最大层级 | [精灵用法](demo#sprite) | +| title | `string` | -- | 可选,目录标题 | [基本用法](demo#basic) | +| isOpen | `boolean` | true | 可选,精灵模式下,目录默认展开 | -- | +| indent | `number` | 2em | 可选,缩进 2 个占位 | -- | +| width | `number` | 300 | 可选,高度 | [精灵用法](demo#sprite) | +| height | `number` | 400 | 可选,宽度 | [精灵用法](demo#sprite) | +| spriteOption | [`SpriteOption`](#SpriteOption) | [`defaultOption`](#defaultOption) | 可选,sprite 模式下的导航初始位置 | [精灵用法](demo#sprite) | +| navItemTemplate | `TemplateRef` | -- | 可选,单条目录模板 | [精灵用法 ](demo#sprite) | ## dNavSprite 事件 -| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | -| :------------------:| :---------------------------------: | :-------------------------: | :------------------------------ | -------------------------------------------- | -| afterNavInit | `EventEmitter` | -- | 可选,导航精灵组件实例 | [精灵用法](demo#sprite) | + +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | +| :----------: | :--------------------------------: | :--: | :--------------------- | ----------------------- | +| afterNavInit | `EventEmitter` | -- | 可选,导航精灵组件实例 | [精灵用法](demo#sprite) | # 接口 & 类型定义 @@ -43,29 +44,24 @@ import { NavSpriteModule } from 'ng-devui/nav-sprite'; ```ts export type SpriteMode = 'default' | 'sprite'; - ``` ## SpriteOption ```ts - export interface SpriteOption { top: string; left: string; zIndex: number; } - ``` ## defaultOption ```ts - const defaultOption: SpriteOption = { top: '30%', left: '80%', zIndex: 1, -} - +}; ``` diff --git a/devui/nav-sprite/doc/api-en.md b/devui/nav-sprite/doc/api-en.md index af06c014..b78bdd0a 100644 --- a/devui/nav-sprite/doc/api-en.md +++ b/devui/nav-sprite/doc/api-en.md @@ -16,27 +16,27 @@ In the page:: ## dNavSprite parameters -| Parameter | Type | Default | Description | Jump to Demo | -| :------------------:| :---------------------------------: | :-------------------------: | :------------------------------ | -------------------------------------------- | -| target | `HTMLElement` | -- | Required. Location of the generated directory | [Basic usage](demo#basic) | -| scrollTarget | `HTMLElement` | -- | Optional. Specifies the scrolling container. | [Scroll Usage](demo#scroll) | -| view | `{top?:number,bottom?:number}` | {top:0,bottom:0} | Optional. It is used to adjust the visible region, for example, the head with a fixed position on the top. The value corresponds to the height of the blocked top or bottom. | [Scroll Usage](demo#scroll) | -| hashSupport | `boolean` | `false` | Optional. Specifies whether to support anchors | -- | -| mode | [`SpriteMode`](#SpriteMode) | 'default' | Optional. mode`default \| sprite` | [mode](demo#sprite) | -| maxLevel | `number` | 3 | Optional. Maximum level of the generated directory | [maxLevel](demo#sprite) | -| title | `string` | 'menu' | Optional. title | [title](demo#basic) | -| isOpen | `boolean` | true | Optional. sprite mode. open menu | -- | -| indent | `number` | 2em | Optional. indent 2 placeholders | -- | -| width | `number` | 300 | Optional. width | [width](demo#sprite) | -| height | `number` | 400 | Optional. height | [height](demo#sprite) | -| spriteOption | [`SpriteOption`](#SpriteOption) | [`defaultOption`](#defaultOption) | Optional. sprite mode initial position | [options](demo#sprite) | -| navItemTemplate | `TemplateRef` | -- | Optional. Single Catalog Template | [template ](demo#sprite) | - +| Parameter | Type | Default | Description | Jump to Demo | +| :-------------: | :-----------------------------: | :-------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| target | `HTMLElement` | -- | Required. Location of the generated directory | [Basic usage](demo#basic) | +| scrollTarget | `HTMLElement` | -- | Optional. Specifies the scrolling container. | [Scroll Usage](demo#scroll) | +| view | `{top?:number,bottom?:number}` | {top:0,bottom:0} | Optional. It is used to adjust the visible region, for example, the head with a fixed position on the top. The value corresponds to the height of the blocked top or bottom. | [Scroll Usage](demo#scroll) | +| hashSupport | `boolean` | `false` | Optional. Specifies whether to support anchors | -- | +| mode | [`SpriteMode`](#SpriteMode) | 'default' | Optional. mode`default \| sprite` | [mode](demo#sprite) | +| maxLevel | `number` | 3 | Optional. Maximum level of the generated directory | [maxLevel](demo#sprite) | +| title | `string` | -- | Optional. Title of Navigation | [title](demo#basic) | +| isOpen | `boolean` | true | Optional. sprite mode. open menu | -- | +| indent | `number` | 2em | Optional. indent 2 placeholders | -- | +| width | `number` | 300 | Optional. width | [width](demo#sprite) | +| height | `number` | 400 | Optional. height | [height](demo#sprite) | +| spriteOption | [`SpriteOption`](#SpriteOption) | [`defaultOption`](#defaultOption) | Optional. sprite mode initial position | [options](demo#sprite) | +| navItemTemplate | `TemplateRef` | -- | Optional. Single Catalog Template | [template ](demo#sprite) | ## dNavSprite Event -| Parameter | Type | Description | Jump to Demo | -| :------------------:| :---------------------------------: | :------------------------------ | -------------------------------------------- | -| afterNavInit | `EventEmitter` | Optional. NavSpriteComponent Instance. | [精灵用法](demo#sprite) | + +| Parameter | Type | Description | Jump to Demo | +| :----------: | :--------------------------------: | :------------------------------------- | ----------------------- | +| afterNavInit | `EventEmitter` | Optional. NavSpriteComponent Instance. | [精灵用法](demo#sprite) | # Interface & Type Definition @@ -44,29 +44,24 @@ In the page:: ```ts export type SpriteMode = 'default' | 'sprite'; - ``` ## SpriteOption ```ts - export interface SpriteOption { top: string; left: string; zIndex: number; } - ``` ## defaultOption ```ts - const defaultOption: SpriteOption = { top: '30%', left: '80%', zIndex: 1, -} - +}; ``` diff --git a/devui/nav-sprite/nav-sprite.component.html b/devui/nav-sprite/nav-sprite.component.html index 54e39054..3fdefc88 100644 --- a/devui/nav-sprite/nav-sprite.component.html +++ b/devui/nav-sprite/nav-sprite.component.html @@ -10,7 +10,7 @@ (cdkDragEnded)="cdkDragEnded()" > -
    +
    {{ title }}
    @@ -22,7 +22,9 @@
    -
    {{ title }}
    +
    + {{ title }} +
    diff --git a/devui/nav-sprite/nav-sprite.component.scss b/devui/nav-sprite/nav-sprite.component.scss index 89c87159..1d603a70 100644 --- a/devui/nav-sprite/nav-sprite.component.scss +++ b/devui/nav-sprite/nav-sprite.component.scss @@ -47,10 +47,14 @@ justify-content: space-between; width: 100%; color: $devui-text; + height: 32px; line-height: 32px; font-weight: bold; font-size: $devui-font-size-card-title; - border-bottom: 1px solid $devui-dividing-line; + + &.devui-nav-sprite-header-with-title { + border-bottom: 1px solid $devui-dividing-line; + } .devui-nav-spiri-close { cursor: pointer; diff --git a/devui/nav-sprite/nav-sprite.component.ts b/devui/nav-sprite/nav-sprite.component.ts index c2832b36..cd0a0bf6 100644 --- a/devui/nav-sprite/nav-sprite.component.ts +++ b/devui/nav-sprite/nav-sprite.component.ts @@ -14,7 +14,7 @@ import { Renderer2, TemplateRef, ViewChild, - ViewChildren + ViewChildren, } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { scrollAnimate } from 'ng-devui/utils'; @@ -49,7 +49,7 @@ export class NavSpriteComponent implements OnInit, AfterViewInit, OnDestroy { @Input() maxLevel = 3; // 最大层级 - @Input() title = 'menu'; // 名称 + @Input() title; // 名称 @Input() indent = 2; // 缩进 diff --git a/devui/nav-sprite/ng-package.json b/devui/nav-sprite/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/nav-sprite/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/nav-sprite/package.json b/devui/nav-sprite/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/nav-sprite/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/number-translation/demo/basic/basic.component.html b/devui/number-translation/demo/basic/basic.component.html new file mode 100644 index 00000000..2e667c63 --- /dev/null +++ b/devui/number-translation/demo/basic/basic.component.html @@ -0,0 +1,18 @@ + +
    + + + + + + + + + + + + + + + + diff --git a/devui/number-translation/demo/basic/basic.component.ts b/devui/number-translation/demo/basic/basic.component.ts new file mode 100644 index 00000000..f31be8a8 --- /dev/null +++ b/devui/number-translation/demo/basic/basic.component.ts @@ -0,0 +1,25 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'd-basic', + templateUrl: './basic.component.html' +}) +export class BasicComponent { + data = [{ + number: 123123123.223, + type: 'comma' + }, + { + number: 232314212, + type: 'unit' + }, + { + number: 231232132, + type: 'flow' + }, + { + number: 231232132, + type: 'exponent' + }]; + +} diff --git a/devui/number-translation/demo/demo.component.html b/devui/number-translation/demo/demo.component.html new file mode 100644 index 00000000..19aa9c5a --- /dev/null +++ b/devui/number-translation/demo/demo.component.html @@ -0,0 +1,8 @@ +
    +
    +
    {{ 'components.number-trans.basicDemo.title' | translate }}
    + + + +
    +
    diff --git a/devui/number-translation/demo/demo.component.ts b/devui/number-translation/demo/demo.component.ts new file mode 100644 index 00000000..7daeeeb6 --- /dev/null +++ b/devui/number-translation/demo/demo.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; +import { DevuiSourceData } from 'ng-devui/shared/devui-codebox'; + +@Component({ + selector: 'd-demo', + templateUrl: './demo.component.html', +}) +export class DemoComponent { + basicSource: Array = [ + { title: 'HTML', language: 'xml', code: require('./basic/basic.component.html?raw') }, + { title: 'TS', language: 'typescript', code: require('./basic/basic.component.ts?raw') }, + ]; + + navItems = []; +} diff --git a/devui/number-translation/demo/demo.module.ts b/devui/number-translation/demo/demo.module.ts new file mode 100644 index 00000000..a2f58229 --- /dev/null +++ b/devui/number-translation/demo/demo.module.ts @@ -0,0 +1,39 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { RouterModule } from '@angular/router'; +import { DataTableModule } from 'ng-devui/data-table'; +import { I18nModule } from 'ng-devui/i18n'; +import { NumberTransModule } from 'ng-devui/number-translation'; +import { DevUIApiComponent } from 'ng-devui/shared/devui-api/devui-api.component'; +import { DevUIApiModule } from 'ng-devui/shared/devui-api/devui-api.module'; +import { DevUICodeboxModule } from 'ng-devui/shared/devui-codebox/devui-codebox.module'; +import { TranslateModule } from '@ngx-translate/core'; +import { BasicComponent } from './basic/basic.component'; +import { DemoComponent } from './demo.component'; + +@NgModule({ + declarations: [DemoComponent, BasicComponent], + imports: [ + TranslateModule, + CommonModule, + DataTableModule, + NumberTransModule, + I18nModule, + DevUICodeboxModule, + DevUIApiModule, + RouterModule.forChild([ + { path: '', redirectTo: 'demo', pathMatch: 'full' }, + { path: 'demo', component: DemoComponent }, + + { + path: 'api', + component: DevUIApiComponent, + data: { + 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), + 'en-us': require('!html-loader!markdown-loader!../doc/api-en.md'), + }, + }, + ]), + ], +}) +export class DemoModule {} diff --git a/devui/number-translation/doc/api-cn.md b/devui/number-translation/doc/api-cn.md new file mode 100644 index 00000000..ba5f5625 --- /dev/null +++ b/devui/number-translation/doc/api-cn.md @@ -0,0 +1,43 @@ +# 如何使用 + +在module中引入: + +```ts +import { NumberTransModule } from 'ng-devui/number-translation'; +``` + +在页面中以pipe方式使用: + +``` +
    {{ value | dNumberTrans: type }}
    +``` + +# dNumberTrans + +## pipe 参数 +| 参数 | 类型 | 默认值 | 描述 |全局配置项| +| :----------------: | :------------------: | :----------------: | :-----: | :------------------------------------------------------------- | +| value | `'string' \| 'number'` | - | pipe转换的值 | +| type | `'comma' \| 'unit' \| 'flow' \| 'exponent'` | 'comma' | pipe第一个参数,转换的四种类型,分别是千分逗号,单位,流量,科学计数法。 | +| fixedNum | `number` | 2 | pipe第二个参数,非必选,小数点保留位数 | + + +## 转换类型介绍 + +[转换标准参考](https://zh.wikipedia.org/wiki/%E5%9B%BD%E9%99%85%E5%8D%95%E4%BD%8D%E5%88%B6%E8%AF%8D%E5%A4%B4) + +### comma + +数字转换为整数区域千分位逗号类型 + +### unit + +单位类型,按照 k(千), M(百万), G(吉), T(兆)进行单位转换; + +### flow + +转换为流量单位, 按最大流量转 kb, Mb, Gb, Tb; + +### exponent + +按科学计数法转换为字符串, 如2.34e12; diff --git a/devui/number-translation/doc/api-en.md b/devui/number-translation/doc/api-en.md new file mode 100644 index 00000000..a8578614 --- /dev/null +++ b/devui/number-translation/doc/api-en.md @@ -0,0 +1,43 @@ + +# How to Use + +The following information is added to the module: + +```ts +import { NumberTransModule } from 'ng-devui/number-translation'; +``` + +Use in pipe mode on the page: + +``` +
    {{value | dNumberTrans: type}}
    +``` + +# dNumberTrans + +## Pipe parameter +|Parameter|Type|Default value|Description|Global configuration item| +| :----------------: | :------------------: | :----------------: | :-----: | :------------------------------------------------------------- | +| value | `'string' \| 'number'` | - | Value converted by pipe| +| type | `'comma' \| 'unit' \| 'flow' \| 'exponent' ` | 'comma' | pipe The first parameter indicates the four types of conversion: comma, unit, traffic, and scientific notation.| +| fixedNum | `number` | 2 | Second parameter of pipe. This parameter is optional. The number of decimal places is reserved. | + +## Introduction to Conversion Types + +[Conversion Standard Reference](https://zh.wikipedia.org/wiki/%E5%9B%BD%E9%99%85%E5%8D%95%E4%BD%8D%E5%88%B6%E8%AF%8D%E5%A4%B4) + +### comma + +Number to Integer Region Millile Comma Type + +### unit + +Unit type. The unit is converted in k (thousand), M (million), G (gi), and T (mega). + +### flow + +Convert to the unit of traffic. The unit is kb, Mb, Gb, and Tb based on the maximum traffic. + +### exponent + +Convert to a character string by scientific notation, for example, 2.34e12. diff --git a/devui/number-translation/index.ts b/devui/number-translation/index.ts new file mode 100644 index 00000000..7e1a213e --- /dev/null +++ b/devui/number-translation/index.ts @@ -0,0 +1 @@ +export * from './public-api'; diff --git a/devui/number-translation/ng-package.json b/devui/number-translation/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/number-translation/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/number-translation/number-translation.module.ts b/devui/number-translation/number-translation.module.ts new file mode 100644 index 00000000..55f10d97 --- /dev/null +++ b/devui/number-translation/number-translation.module.ts @@ -0,0 +1,12 @@ +import { NgModule } from '@angular/core'; +import { NumberTransPipe } from './number-translation.pipe'; + +@NgModule({ + declarations: [ + NumberTransPipe + ], + exports: [ + NumberTransPipe + ] +}) +export class NumberTransModule { } diff --git a/devui/number-translation/number-translation.pipe.ts b/devui/number-translation/number-translation.pipe.ts new file mode 100644 index 00000000..c4970ad0 --- /dev/null +++ b/devui/number-translation/number-translation.pipe.ts @@ -0,0 +1,77 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'dNumberTrans' +}) +export class NumberTransPipe implements PipeTransform { + + getFlowStr(value: number, fixedNum: number) { + if (value / (1024 * 1024 * 1024 * 1024) > 10) { + value = value / (1024 * 1024 * 1024 * 1024); + return value.toFixed(fixedNum) + 'Tb'; + }else if (value / (1024 * 1024 * 1024) > 10) { + value = value / (1024 * 1024 * 1024); + return value.toFixed(fixedNum) + 'Gb'; + } else if (value / (1024 * 1024) > 10) { + value = value / (1024 * 1024); + return value.toFixed(fixedNum) + 'Mb'; + } else if (value / 1024 > 10) { + value = value / 1024; + return value.toFixed(fixedNum) + 'Kb'; + } else { + return value + 'Byte'; + } + } + + getUnitStr(value: number, fixedNum: number): string { + if (value / (1000 * 1000 * 1000 * 1000) > 1) { + value = value / (1000 * 1000 * 1000 * 1000); + return value.toFixed(fixedNum) + 'T'; + } else if (value / (1000 * 1000 * 1000) > 1) { + value = value / (1000 * 1000 * 1000); + return value.toFixed(fixedNum) + 'G'; + } else if (value / (1000 * 1000) > 1) { + value = value / (1000 * 1000); + return value.toFixed(fixedNum) + 'M'; + } else if (value / (1000) > 1) { + value = value / (1000); + return value.toFixed(fixedNum) + 'k'; + } else { + return String(value); + } + + } + + transform( + value: number | string, type: 'comma' | 'unit' | 'flow' | 'exponent' = 'comma', fixedNum = 2 + ): string { + let number = Number(value); + let numberStr = ''; + + if (!number && number !== 0) { + return numberStr; + } + + if (Number(fixedNum) || fixedNum === 0) { + number = Math.floor(number * Number(`1e${fixedNum}`)) / Number(`1e${fixedNum}`); + } + + switch(type) { + case 'comma': + numberStr = number.toLocaleString(); + break; + case 'flow': + numberStr = this.getFlowStr(number, fixedNum); + break; + case 'unit': + numberStr = this.getUnitStr(number, fixedNum); + break; + case 'exponent': + numberStr = number.toExponential(fixedNum); + break; + } + + + return numberStr; + } +} diff --git a/devui/number-translation/public-api.ts b/devui/number-translation/public-api.ts new file mode 100644 index 00000000..88b4cc92 --- /dev/null +++ b/devui/number-translation/public-api.ts @@ -0,0 +1,3 @@ +export * from './number-translation.module'; +export * from './number-translation.pipe'; + diff --git a/devui/overlay-container/ng-package.json b/devui/overlay-container/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/overlay-container/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/overlay-container/package.json b/devui/overlay-container/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/overlay-container/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/package.json b/devui/package.json index 879cf71e..28e07cf9 100755 --- a/devui/package.json +++ b/devui/package.json @@ -1,6 +1,6 @@ { "name": "ng-devui", - "version": "13.3.0", + "version": "14.0.0", "license": "MIT", "description": "DevUI components based on Angular", "keywords": [ @@ -25,7 +25,7 @@ } }, "dependencies": { - "@angular/cdk": "^13.0.0", + "@angular/cdk": "^14.0.0", "date-fns": "^2.20.0", "lodash-es": "^4.17.11", "@popperjs/core": "^2.5.4", @@ -34,9 +34,9 @@ "tslib": "^2.0.0" }, "peerDependencies": { - "@angular/animations": "^13.0.0", - "@angular/common": "^13.0.0", - "@angular/core": "^13.0.0", - "@angular/forms": "^13.0.0" + "@angular/animations": "^14.0.0", + "@angular/common": "^14.0.0", + "@angular/core": "^14.0.0", + "@angular/forms": "^14.0.0" } } \ No newline at end of file diff --git a/devui/pagination/demo/pagination-demo.module.ts b/devui/pagination/demo/pagination-demo.module.ts index 9aa533cd..f928f9ab 100755 --- a/devui/pagination/demo/pagination-demo.module.ts +++ b/devui/pagination/demo/pagination-demo.module.ts @@ -25,7 +25,7 @@ import { WidgetsComponent } from './widgets/widgets.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: PaginationDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/pagination/ng-package.json b/devui/pagination/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/pagination/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/pagination/package.json b/devui/pagination/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/pagination/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/panel/demo/panel-demo.component.ts b/devui/panel/demo/panel-demo.component.ts index 090cd9dc..ba628102 100755 --- a/devui/panel/demo/panel-demo.component.ts +++ b/devui/panel/demo/panel-demo.component.ts @@ -16,7 +16,6 @@ export class PanelDemoComponent implements OnInit, OnDestroy { typeSource: Array = [ { title: 'HTML', language: 'xml', code: require('./type/type.component.html?raw') }, - { title: 'SCSS', language: 'css', code: require('./type/type.component.scss?raw') }, { title: 'TS', language: 'typescript', code: require('./type/type.component.ts?raw') }, ]; diff --git a/devui/panel/demo/panel-demo.module.ts b/devui/panel/demo/panel-demo.module.ts index 50f65282..e59c1f57 100755 --- a/devui/panel/demo/panel-demo.module.ts +++ b/devui/panel/demo/panel-demo.module.ts @@ -25,7 +25,7 @@ import { TypeComponent } from './type/type.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: PanelDemoComponent }, { path: 'api', diff --git a/devui/panel/ng-package.json b/devui/panel/ng-package.json new file mode 100644 index 00000000..3360c83b --- /dev/null +++ b/devui/panel/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "index.ts" + } +} \ No newline at end of file diff --git a/devui/panel/package.json b/devui/panel/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/panel/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/popover/demo/popover-demo.module.ts b/devui/popover/demo/popover-demo.module.ts index 97aa88e9..f9ab69d0 100755 --- a/devui/popover/demo/popover-demo.module.ts +++ b/devui/popover/demo/popover-demo.module.ts @@ -28,7 +28,7 @@ import { ScrollElementComponent } from './scroll-element/scroll-element.componen ButtonModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: PopoverDemoComponent }, { path: 'api', diff --git a/devui/popover/ng-package.json b/devui/popover/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/popover/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/popover/package.json b/devui/popover/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/popover/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/popover/popover.directive.ts b/devui/popover/popover.directive.ts index 95d08e79..b2cc7eb0 100755 --- a/devui/popover/popover.directive.ts +++ b/devui/popover/popover.directive.ts @@ -102,8 +102,8 @@ export class PopoverDirective implements OnInit, OnDestroy { // 因为鼠标移出之后如果立刻消失会很突然,所以增加略小一些的延迟,使得既不突然也反应灵敏 @Input() mouseLeaveDelay = 100; isEnter: boolean; - unsubscribe$ = new Subject(); - unsubscribeP$ = new Subject(); + unsubscribe$ = new Subject(); + unsubscribeP$ = new Subject(); document: Document; @Input() set visible(_isShow: boolean) { if (_isShow) { diff --git a/devui/portal/ng-package.json b/devui/portal/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/portal/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/portal/package.json b/devui/portal/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/portal/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/position/ng-package.json b/devui/position/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/position/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/position/package.json b/devui/position/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/position/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/progress/demo/progress-demo.module.ts b/devui/progress/demo/progress-demo.module.ts index fa495a06..303fdf33 100755 --- a/devui/progress/demo/progress-demo.module.ts +++ b/devui/progress/demo/progress-demo.module.ts @@ -22,7 +22,7 @@ import { ProgressDemoComponent } from './progress-demo.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: ProgressDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/progress/ng-package.json b/devui/progress/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/progress/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/progress/package.json b/devui/progress/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/progress/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/quadrant-diagram/demo/quadrant-diagram-demo.module.ts b/devui/quadrant-diagram/demo/quadrant-diagram-demo.module.ts index d10d621b..234a52b3 100644 --- a/devui/quadrant-diagram/demo/quadrant-diagram-demo.module.ts +++ b/devui/quadrant-diagram/demo/quadrant-diagram-demo.module.ts @@ -23,7 +23,7 @@ import { QuadrantDiagramDemoComponent } from './quadrant-diagram-demo.component' DDemoNavModule, TranslateModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: QuadrantDiagramDemoComponent }, { path: 'api', component: DevUIApiComponent, data: { diff --git a/devui/quadrant-diagram/ng-package.json b/devui/quadrant-diagram/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/quadrant-diagram/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/quadrant-diagram/package.json b/devui/quadrant-diagram/package.json deleted file mode 100644 index 3b9bd979..00000000 --- a/devui/quadrant-diagram/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } - \ No newline at end of file diff --git a/devui/radio/demo/custom/custom.component.ts b/devui/radio/demo/custom/custom.component.ts index c59bb12e..d0bad9d7 100755 --- a/devui/radio/demo/custom/custom.component.ts +++ b/devui/radio/demo/custom/custom.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { FormControl } from '@angular/forms'; +import { UntypedFormControl } from '@angular/forms'; @Component({ selector: 'd-custom', @@ -9,7 +9,7 @@ export class CustomComponent implements OnInit { values2 = ['Item1', 'Item2', 'Item3']; choose2 = 'Item3'; - valueControl = new FormControl('Item1'); + valueControl = new UntypedFormControl('Item1'); values3 = [ {name: 'Item1'}, diff --git a/devui/radio/demo/radio-demo.module.ts b/devui/radio/demo/radio-demo.module.ts index 527f3985..45791f69 100755 --- a/devui/radio/demo/radio-demo.module.ts +++ b/devui/radio/demo/radio-demo.module.ts @@ -28,7 +28,7 @@ import { VerticalComponent } from './vertical/vertical.component'; DDemoNavModule, ReactiveFormsModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: RadioDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/radio/ng-package.json b/devui/radio/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/radio/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/radio/package.json b/devui/radio/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/radio/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/rate/demo/rate-demo.module.ts b/devui/rate/demo/rate-demo.module.ts index 6a4b5cfd..1fc69238 100644 --- a/devui/rate/demo/rate-demo.module.ts +++ b/devui/rate/demo/rate-demo.module.ts @@ -27,7 +27,7 @@ import { TypeComponent } from './type/type.component'; DevUICodeboxModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: RateDemoComponent }, { path: 'api', diff --git a/devui/rate/ng-package.json b/devui/rate/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/rate/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/rate/package.json b/devui/rate/package.json deleted file mode 100644 index 3b9bd979..00000000 --- a/devui/rate/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } - \ No newline at end of file diff --git a/devui/read-tip/demo/read-tip-demo.module.ts b/devui/read-tip/demo/read-tip-demo.module.ts index 91e7d5a4..59d52175 100644 --- a/devui/read-tip/demo/read-tip-demo.module.ts +++ b/devui/read-tip/demo/read-tip-demo.module.ts @@ -26,7 +26,7 @@ import { ReadtipTemplateComponent } from './readtip-template/readtip-template.co AvatarModule, ReadTipModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: ReadTipDemoComponent }, { path: 'api', diff --git a/devui/read-tip/ng-package.json b/devui/read-tip/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/read-tip/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/read-tip/package.json b/devui/read-tip/package.json deleted file mode 100644 index 3b9bd979..00000000 --- a/devui/read-tip/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } - } - \ No newline at end of file diff --git a/devui/relative-time/demo/demo.module.ts b/devui/relative-time/demo/demo.module.ts index e1382ef5..ec00e8dd 100644 --- a/devui/relative-time/demo/demo.module.ts +++ b/devui/relative-time/demo/demo.module.ts @@ -23,7 +23,7 @@ import { DemoComponent } from './demo.component'; DevUICodeboxModule, DevUIApiModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: DemoComponent }, { diff --git a/devui/relative-time/ng-package.json b/devui/relative-time/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/relative-time/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/relative-time/package.json b/devui/relative-time/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/relative-time/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/relative-time/relative-time.pipe.ts b/devui/relative-time/relative-time.pipe.ts index be65625e..5b296980 100644 --- a/devui/relative-time/relative-time.pipe.ts +++ b/devui/relative-time/relative-time.pipe.ts @@ -8,7 +8,7 @@ import { map, takeUntil } from 'rxjs/operators'; name: 'dRelativeTime' }) export class RelativeTimePipe implements PipeTransform, OnDestroy { - private _destroyed$ = new Subject(); + private _destroyed$ = new Subject(); constructor(private i18n: I18nService) {} transform( diff --git a/devui/search/demo/search-demo.module.ts b/devui/search/demo/search-demo.module.ts index 19e23988..b709d750 100755 --- a/devui/search/demo/search-demo.module.ts +++ b/devui/search/demo/search-demo.module.ts @@ -27,7 +27,7 @@ import { SearchDemoComponent } from './search-demo.component'; DDemoNavModule, FormModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: SearchDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { 'zh-cn': require('!html-loader!markdown-loader!../doc/api-cn.md'), diff --git a/devui/search/ng-package.json b/devui/search/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/search/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/search/package.json b/devui/search/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/search/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/search/search.component.scss b/devui/search/search.component.scss index 54d66677..604e25af 100755 --- a/devui/search/search.component.scss +++ b/devui/search/search.component.scss @@ -57,7 +57,11 @@ svg.svg-icon-clear { } &.devui-search-no-border { - border: none; + background-color: unset; + } + + &.devui-search-no-border:not(:hover, :focus, :active) { + border: 1px solid transparent; } &.devui-clear-exit:not(.devui-icon-left) { diff --git a/devui/select/demo/select-demo.module.ts b/devui/select/demo/select-demo.module.ts index 58991a38..b7c0a496 100755 --- a/devui/select/demo/select-demo.module.ts +++ b/devui/select/demo/select-demo.module.ts @@ -44,7 +44,7 @@ import { UserSearchNLazyLoadComponent } from './user-search-n-lazyload/user-sear ButtonModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: SelectDemoComponent }, { path: 'api', diff --git a/devui/select/ng-package.json b/devui/select/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/select/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/select/package.json b/devui/select/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/select/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/select/select.component.ts b/devui/select/select.component.ts index c1b8907e..794ac0bc 100755 --- a/devui/select/select.component.ts +++ b/devui/select/select.component.ts @@ -34,9 +34,12 @@ import { I18nInterface, I18nService } from 'ng-devui/i18n'; import { addClassToOrigin, AppendToBodyDirection, - AppendToBodyDirectionsConfig, DevConfigService, fadeInOut, + AppendToBodyDirectionsConfig, + DevConfigService, + fadeInOut, formWithDropDown, - removeClassFromOrigin, WithConfig + removeClassFromOrigin, + WithConfig } from 'ng-devui/utils'; import { WindowRef } from 'ng-devui/window-ref'; import { BehaviorSubject, fromEvent, Observable, of, Subscription } from 'rxjs'; @@ -52,12 +55,10 @@ import { debounceTime, filter, map, switchMap } from 'rxjs/operators'; { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SelectComponent), - multi: true - } - ], - animations: [ - fadeInOut + multi: true, + }, ], + animations: [fadeInOut], preserveWhitespaces: false, }) export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewInit, OnDestroy, OnChanges { @@ -70,7 +71,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI this.toggleChange.emit(value); this.setDocumentClickListener(); if (this.selectWrapper) { - this.dropDownWidth = this.width ? this.width : (this.selectWrapper.nativeElement.offsetWidth); + this.dropDownWidth = this.width ? this.width : this.selectWrapper.nativeElement.offsetWidth; } if (value) { addClassToOrigin(this.selectWrapper); @@ -128,11 +129,9 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI */ @Input() appendToBody = false; /** - * 【可选】cdk模式overlay Positions的控制 - */ - @Input() appendToBodyDirections: Array = [ - 'rightDown', 'leftDown', 'rightUp', 'leftUp' - ]; + * 【可选】cdk模式overlay Positions的控制 + */ + @Input() appendToBodyDirections: Array = ['rightDown', 'leftDown', 'rightUp', 'leftUp']; /** * 【可选】cdk模式origin width */ @@ -299,7 +298,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI sm: 30, normal: 36, lg: 50, - space: 4 + space: 4, }; cdkConnectedOverlayOrigin: CdkOverlayOrigin; @@ -322,8 +321,8 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI private devConfigService: DevConfigService, @Inject(DOCUMENT) private doc: any ) { - this.valueParser = item => (typeof item === 'object' ? item[this.filterKey] || '' : (String(item)) ? item.toString() : ''); - this.formatter = item => (typeof item === 'object' ? item[this.filterKey] || '' : (String(item)) ? item.toString() : ''); + this.valueParser = (item) => (typeof item === 'object' ? item[this.filterKey] || '' : String(item) ? item.toString() : ''); + this.formatter = (item) => (typeof item === 'object' ? item[this.filterKey] || '' : String(item) ? item.toString() : ''); this.document = this.doc; } @@ -333,12 +332,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI return of( (this.options ? this.options : []) .map((option, index) => ({ option: option, id: index })) - .filter( - item => - this.formatter(item.option) - .toLowerCase() - .indexOf(term.toLowerCase()) !== -1 - ) + .filter((item) => this.formatter(item.option).toLowerCase().indexOf(term.toLowerCase()) !== -1) ); }; } @@ -356,7 +350,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI if (this.autoFocus && this.selectBoxElement) { setTimeout(() => { this.selectBoxElement.nativeElement.focus({ - preventScroll: this.notAutoScroll + preventScroll: this.notAutoScroll, }); }); } @@ -376,26 +370,33 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI } ngOnChanges(changes: SimpleChanges): void { - if (changes && (changes.searchFn || changes.options)) { + const { searchFn, options, appendToBodyDirections, disabled } = changes; + if (searchFn || options) { this.resetSource(); if (this.virtualScroll && this.virtualScrollViewport) { this.virtualScrollViewportSizeMightChange = true; this.virtualScrollViewport.checkViewportSize(); } } - if (changes['appendToBodyDirections']) { + if (appendToBodyDirections) { this.setPositions(); } + if (disabled && this.isOpen) { + this.toggle(); + } } + setPositions() { if (this.appendToBodyDirections && this.appendToBodyDirections.length > 0) { - this.overlayPositions = this.appendToBodyDirections.map(position => { - if (typeof position === 'string') { - return AppendToBodyDirectionsConfig[position]; - } else { - return position; - } - }).filter(position => position !== undefined); + this.overlayPositions = this.appendToBodyDirections + .map((position) => { + if (typeof position === 'string') { + return AppendToBodyDirectionsConfig[position]; + } else { + return position; + } + }) + .filter((position) => position !== undefined); } else { this.overlayPositions = undefined; } @@ -446,7 +447,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI registerFilterChange(): void { this.sourceSubscription = new BehaviorSubject(''); - this.sourceSubscription.pipe(switchMap(term => this.searchFn(term))).subscribe(options => { + this.sourceSubscription.pipe(switchMap((term) => this.searchFn(term))).subscribe((options) => { this.availableOptions = options; this.setAvailableOptions(); this.changeDetectorRef.markForCheck(); @@ -460,8 +461,8 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI // 显示数据变更,需要判断全选半选状态 if (this.isSelectAll) { const selectedItemForFilterOptions = []; - this.multiItems.forEach(item => { - this.availableOptions.forEach(option => { + this.multiItems.forEach((item) => { + this.availableOptions.forEach((option) => { if (item['id'] === option['id']) { selectedItemForFilterOptions.push(item); } @@ -469,12 +470,15 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI }); this.setChecked(selectedItemForFilterOptions); } - if (!this.multiple && (!this.value || this.availableOptions && !this.availableOptions.find(option => option.option === this.value))) { + if ( + !this.multiple && + (!this.value || (this.availableOptions && !this.availableOptions.find((option) => option.option === this.value))) + ) { this.selectIndex = this.filter && this.availableOptions && this.availableOptions.length > 0 ? 0 : -1; } }); - this.sourceSubscription.subscribe(term => { + this.sourceSubscription.subscribe((term) => { if (this.resetting && term === '') { this.writeValue(this.value); this.resetting = false; @@ -487,14 +491,15 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI searchInputValueChangeEvent() { if (this.isSearch && this.isOpen && this.filterInputElement) { this.filterInputElement.nativeElement.focus(); - if (!this.filterSubscription || this.appendToBody) { // 避免重复订阅 + if (!this.filterSubscription || this.appendToBody) { + // 避免重复订阅 this.filterSubscription = fromEvent(this.filterInputElement.nativeElement, 'input') .pipe( map((e: any) => e.target.value), - filter(term => !this.disabled && this.searchFn && term.length >= 0), + filter((term) => !this.disabled && this.searchFn && term.length >= 0), debounceTime(300) // hard code need refactory ) - .subscribe(term => { + .subscribe((term) => { this.selectIndex = -1; return this.sourceSubscription.next(term); }); @@ -518,9 +523,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI this.value = Array.isArray(this.value) ? this.value : [this.value]; this.multiItems = this.value.map((option, index) => ({ option: option, id: this.options.indexOf(option) })); } else { - const selectedItem = this.availableOptions.find( - item => this.formatter(item.option) === this.formatter(this.value) - ); + const selectedItem = this.availableOptions.find((item) => this.formatter(item.option) === this.formatter(this.value)); this.activeIndex = selectedItem ? selectedItem.id : -1; this.selectIndex = this.activeIndex ? this.activeIndex : -1; } @@ -531,9 +534,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI } writeIntoInput(value): void { - this._inputValue = this.multiple - ? (value || []).map(option => this.valueParser(option)).join(', ') - : this.valueParser(value); + this._inputValue = this.multiple ? (value || []).map((option) => this.valueParser(option)).join(', ') : this.valueParser(value); this.setAvailableOptions(); } @@ -545,10 +546,11 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI if (!this.multiple) { _value = [_value]; } - this.availableOptions = this.availableOptions - .map((item) => ({ - isChecked: _value.findIndex(i => JSON.stringify(i) === JSON.stringify(item.option)) > -1, id: item.id, option: item.option - })); + this.availableOptions = this.availableOptions.map((item) => ({ + isChecked: _value.findIndex((i) => JSON.stringify(i) === JSON.stringify(item.option)) > -1, + id: item.id, + option: item.option, + })); } choose = (option, index, $event?: Event) => { @@ -577,7 +579,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI } if (this.multiple) { - const indexOfOption = this.multiItems.findIndex(item => JSON.stringify(item.option) === JSON.stringify(option)); + const indexOfOption = this.multiItems.findIndex((item) => JSON.stringify(item.option) === JSON.stringify(option)); if (indexOfOption === -1) { this.multiItems.push({ id: index, option }); } else { @@ -586,7 +588,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI if (this.keepMultipleOrder === 'origin') { this.multiItems.sort((a, b) => a.id - b.id); } - this.value = this.multiItems.map(item => item.option); + this.value = this.multiItems.map((item) => item.option); } else { this.value = option; this.activeIndex = index; @@ -601,9 +603,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI updateCdkConnectedOverlayOrigin() { if (this.selectWrapper.nativeElement) { - this.cdkConnectedOverlayOrigin = new CdkOverlayOrigin( - formWithDropDown(this.selectWrapper) || this.selectWrapper.nativeElement - ); + this.cdkConnectedOverlayOrigin = new CdkOverlayOrigin(formWithDropDown(this.selectWrapper) || this.selectWrapper.nativeElement); } } @@ -627,7 +627,9 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI toggle() { if (this.disabled) { - this.isOpen = false; + if (this.isOpen) { + this.isOpen = false; + } return; } @@ -657,7 +659,8 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI this.startAnimation = false; } this.isOpen = !this.isOpen; - if (this.virtualScrollViewportSizeMightChange) { // 解决虚拟滚动更新options长度展开前无法获取正确高度影响 + if (this.virtualScrollViewportSizeMightChange) { + // 解决虚拟滚动更新options长度展开前无法获取正确高度影响 setTimeout(() => { if (this.virtualScrollViewportSizeMightChange && this.virtualScrollViewport) { this.virtualScrollViewportSizeMightChange = false; @@ -665,20 +668,19 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI } }, 0); } - if (this.isSearch && this.isOpen) { // 条件外移减少setTimeout - setTimeout(() => { - this.searchInputValueChangeEvent(); - }, 100); + if (this.isSearch && this.isOpen) { + // 条件外移减少setTimeout + setTimeout(() => this.searchInputValueChangeEvent(), 100); } } isBottomRectEnough() { const selectMenuElement = this.selectMenuElement.nativeElement; const selectInputElement = this.selectInputElement || this.selectInputWithLabelElement || this.selectInputWithTemplateElement; - const displayStyle = - selectMenuElement.style['display'] || (window).getComputedStyle(selectMenuElement).display; + const displayStyle = selectMenuElement.style['display'] || (window).getComputedStyle(selectMenuElement).display; let tempStyle; - if (displayStyle === 'none') { // 必要, 否则首次展开必有问题, 如果animationEnd之后设置为none也会有问题 + if (displayStyle === 'none') { + // 必要, 否则首次展开必有问题, 如果animationEnd之后设置为none也会有问题 tempStyle = { visibility: selectMenuElement.style.visibility, display: selectMenuElement.style.display, @@ -689,8 +691,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI this.renderer.setStyle(selectMenuElement, 'transform', 'translate(0, -9999)'); } const elementHeight = selectMenuElement.offsetHeight; - const bottomDistance = - this.windowRef.innerHeight - selectInputElement.nativeElement.getBoundingClientRect().bottom; + const bottomDistance = this.windowRef.innerHeight - selectInputElement.nativeElement.getBoundingClientRect().bottom; const isBottomEnough = bottomDistance >= elementHeight; if (displayStyle === 'none') { this.renderer.setStyle(selectMenuElement, 'visibility', tempStyle.visibility); @@ -738,15 +739,14 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI if (this.isOpen) { $event.preventDefault(); $event.stopPropagation(); - this.selectIndex = - this.selectIndex === this.availableOptions.length - 1 ? 0 : this.selectIndex + 1; + this.selectIndex = this.selectIndex === this.availableOptions.length - 1 ? 0 : this.selectIndex + 1; this.scrollToActive(); } } scrollToActive(): void { const that = this; - setTimeout(_ => { + setTimeout(() => { try { const selectIndex = that.selectIndex + (that.isSelectAll ? 1 : 0); // 多了个全选会导致问题,index需要加1 const scrollPane: any = that.dropdownUl.nativeElement.children[selectIndex]; @@ -759,8 +759,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI scrollPane.scrollIntoView(false); } } - } catch (e) { - } + } catch (e) {} }); } @@ -791,16 +790,13 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI selectAll() { const mutableOption = this.optionImmutableKey - ? this.availableOptions.filter(item => !item.option[this.optionImmutableKey]) + ? this.availableOptions.filter((item) => !item.option[this.optionImmutableKey]) : this.availableOptions; - const selectedImmutableOption = this.optionImmutableKey - ? this.multiItems.filter(item => item.option[this.optionImmutableKey]) - : []; - - if (mutableOption && mutableOption.length > (this.multiItems.length - selectedImmutableOption.length)) { - mutableOption.forEach(item => { - const indexOfOption = this.multiItems - .findIndex(i => JSON.stringify(i.option) === JSON.stringify(item.option)); + const selectedImmutableOption = this.optionImmutableKey ? this.multiItems.filter((item) => item.option[this.optionImmutableKey]) : []; + + if (mutableOption && mutableOption.length > this.multiItems.length - selectedImmutableOption.length) { + mutableOption.forEach((item) => { + const indexOfOption = this.multiItems.findIndex((i) => JSON.stringify(i.option) === JSON.stringify(item.option)); if (indexOfOption === -1) { this.multiItems.push({ id: item.id, option: item.option }); } @@ -808,7 +804,7 @@ export class SelectComponent implements ControlValueAccessor, OnInit, AfterViewI } else { this.multiItems = [...selectedImmutableOption]; } - this.value = this.multiItems.map(item => item.option); + this.value = this.multiItems.map((item) => item.option); this.writeIntoInput(this.value); this.onChange(this.value); this.valueChange.emit(this.multiItems); diff --git a/devui/shared/devui-api/devui-api.component.html b/devui/shared/devui-api/devui-api.component.html index dfbbb3de..d092f941 100755 --- a/devui/shared/devui-api/devui-api.component.html +++ b/devui/shared/devui-api/devui-api.component.html @@ -1,17 +1,16 @@
    -
    +
    diff --git a/devui/shared/devui-api/devui-api.component.scss b/devui/shared/devui-api/devui-api.component.scss index f54248f4..4763b2ba 100644 --- a/devui/shared/devui-api/devui-api.component.scss +++ b/devui/shared/devui-api/devui-api.component.scss @@ -3,10 +3,16 @@ d-nav-sprite { width: 240px; position: fixed; - top: 90px; + top: 160px; right: 0; height: 100%; - z-index: 1; + z-index: calc(#{$devui-z-index-framework} + 1); + padding: 8px 0 8px 8px; + border-radius: 16px; +} + +:host ::ng-deep d-nav-sprite div.devui-nav-sprite-header { + display: none !important; } @media (max-width: 1800px) { @@ -20,3 +26,12 @@ d-nav-sprite { display: none; } } + +.devui-api-container { + background-color: $devui-base-bg; + padding: 20px; + margin-top: 20px; + box-shadow: $devui-shadow-length-base $devui-light-shadow; + border-radius: 16px; + margin-bottom: 20px; +} diff --git a/devui/shared/devui-online-ide/devui-online-ide.service.ts b/devui/shared/devui-online-ide/devui-online-ide.service.ts index fd5ae00c..30862a3c 100644 --- a/devui/shared/devui-online-ide/devui-online-ide.service.ts +++ b/devui/shared/devui-online-ide/devui-online-ide.service.ts @@ -30,15 +30,15 @@ const regConfig = { export class DevuiOnlineIdeService { document: Document; dependencies = { - '@angular/animations': '^13.0.0', - '@angular/cdk': '^13.0.0', - '@angular/common': '^13.0.0', - '@angular/compiler': '^13.0.0', - '@angular/core': '^13.0.0', - '@angular/forms': '^13.0.0', - '@angular/platform-browser': '^13.0.0', - '@angular/platform-browser-dynamic': '^13.0.0', - '@angular/router': '^13.0.0', + '@angular/animations': '^14.0.0', + '@angular/cdk': '^14.0.0', + '@angular/common': '^14.0.0', + '@angular/compiler': '^14.0.0', + '@angular/core': '^14.0.0', + '@angular/forms': '^14.0.0', + '@angular/platform-browser': '^14.0.0', + '@angular/platform-browser-dynamic': '^14.0.0', + '@angular/router': '^14.0.0', "@ngx-translate/core": "^14.0.0", "lodash-es": "^4.17.15", '@devui-design/icons': '^1.2.0', diff --git a/devui/shared/devui-online-ide/files/main.ts b/devui/shared/devui-online-ide/files/main.ts index b19dd830..0eff4265 100644 --- a/devui/shared/devui-online-ide/files/main.ts +++ b/devui/shared/devui-online-ide/files/main.ts @@ -3,6 +3,18 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; +import { + devuiLightTheme, + ThemeServiceInit +} from 'ng-devui/theme'; + +import { infinityTheme } from 'ng-devui/theme-collection'; + +ThemeServiceInit({ + 'devui-light-theme': devuiLightTheme, + 'infinity-theme': infinityTheme, +}, 'infinity-theme'); + platformBrowserDynamic().bootstrapModule(AppModule).then(ref => { // Ensure Angular destroys itself on hot reloads. if (window['ngRef']) { diff --git a/devui/slider/demo/slider-demo.module.ts b/devui/slider/demo/slider-demo.module.ts index 06d3bd9b..d85e502f 100755 --- a/devui/slider/demo/slider-demo.module.ts +++ b/devui/slider/demo/slider-demo.module.ts @@ -23,7 +23,7 @@ import { SliderDemoComponent } from './slider-demo.component'; FormsModule, DDemoNavModule, RouterModule.forChild([ - {path: '', redirectTo: 'demo'}, + {path: '', redirectTo: 'demo', pathMatch: 'full'}, {path: 'demo', component: SliderDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { diff --git a/devui/slider/ng-package.json b/devui/slider/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/slider/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/slider/package.json b/devui/slider/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/slider/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/slider/slider.component.ts b/devui/slider/slider.component.ts index 230625f8..2a8b5c20 100755 --- a/devui/slider/slider.component.ts +++ b/devui/slider/slider.component.ts @@ -154,7 +154,7 @@ export class SliderComponent implements OnInit, OnChanges, ControlValueAccessor, e.stopPropagation(); e.preventDefault(); }), - pluck('pageX'), + pluck('pageX'), map((position: number) => this.mousePositionToAdaptiveValue(position)) ); this.dragEndListener = fromEvent(document, 'mouseup'); @@ -163,7 +163,7 @@ export class SliderComponent implements OnInit, OnChanges, ControlValueAccessor, e.stopPropagation(); e.preventDefault(); }), - pluck('pageX'), + pluck('pageX'), distinctUntilChanged(), map((position: number) => this.mousePositionToAdaptiveValue(position)), distinctUntilChanged(), diff --git a/devui/splitter/demo/splitter-demo.module.ts b/devui/splitter/demo/splitter-demo.module.ts index 18ab09f2..101bb344 100644 --- a/devui/splitter/demo/splitter-demo.module.ts +++ b/devui/splitter/demo/splitter-demo.module.ts @@ -29,7 +29,7 @@ import { SplitterDemoVerticalComponent } from './vertical/splitter-demo-vertical TooltipModule, DDemoNavModule, RouterModule.forChild([ - {path: '', redirectTo: 'demo'}, + {path: '', redirectTo: 'demo', pathMatch: 'full'}, {path: 'demo', component: SplitterDemoComponent}, { path: 'api', component: DevUIApiComponent, data: { diff --git a/devui/splitter/ng-package.json b/devui/splitter/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/splitter/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/splitter/package.json b/devui/splitter/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/splitter/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/status/demo/status-demo.module.ts b/devui/status/demo/status-demo.module.ts index 4cedfa58..b0fdc433 100755 --- a/devui/status/demo/status-demo.module.ts +++ b/devui/status/demo/status-demo.module.ts @@ -21,7 +21,7 @@ import { StatusDemoComponent } from './status-demo.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: StatusDemoComponent }, { path: 'api', diff --git a/devui/status/ng-package.json b/devui/status/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/status/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/status/package.json b/devui/status/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/status/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/steps-guide/demo/steps-guide-demo.component.html b/devui/steps-guide/demo/steps-guide-demo.component.html index 2f520425..10ef51fa 100644 --- a/devui/steps-guide/demo/steps-guide-demo.component.html +++ b/devui/steps-guide/demo/steps-guide-demo.component.html @@ -7,16 +7,16 @@ -
    -
    {{ 'components.steps-guide.positionDemo.title' | translate }}
    -
    {{ 'components.steps-guide.positionDemo.description' | translate }}
    +
    +
    {{ 'components.steps-guide.positionDemo.title' | translate }}
    +
    {{ 'components.steps-guide.positionDemo.description' | translate }}
    -
    -
    {{ 'components.steps-guide.customDemo.title' | translate }}
    -
    {{ 'components.steps-guide.customDemo.description' | translate }}
    +
    +
    {{ 'components.steps-guide.customDemo.title' | translate }}
    +
    {{ 'components.steps-guide.customDemo.description' | translate }}
    diff --git a/devui/steps-guide/demo/steps-guide-demo.module.ts b/devui/steps-guide/demo/steps-guide-demo.module.ts index f2dfbaf6..775e9734 100644 --- a/devui/steps-guide/demo/steps-guide-demo.module.ts +++ b/devui/steps-guide/demo/steps-guide-demo.module.ts @@ -23,7 +23,7 @@ import { StepsGuideDemoComponent } from './steps-guide-demo.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: StepsGuideDemoComponent }, { path: 'api', diff --git a/devui/steps-guide/ng-package.json b/devui/steps-guide/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/steps-guide/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/steps-guide/package.json b/devui/steps-guide/package.json deleted file mode 100644 index ded1e7a9..00000000 --- a/devui/steps-guide/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/sticky/demo/sticky-demo.module.ts b/devui/sticky/demo/sticky-demo.module.ts index 867698a9..9014ca07 100755 --- a/devui/sticky/demo/sticky-demo.module.ts +++ b/devui/sticky/demo/sticky-demo.module.ts @@ -24,7 +24,7 @@ import { StickyDemoComponent } from './sticky-demo.component'; DevUIApiModule, DDemoNavModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: StickyDemoComponent }, { path: 'api', diff --git a/devui/sticky/ng-package.json b/devui/sticky/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/sticky/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/sticky/package.json b/devui/sticky/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/sticky/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/style/core/_color.scss b/devui/style/core/_color.scss new file mode 100644 index 00000000..7c8416f7 --- /dev/null +++ b/devui/style/core/_color.scss @@ -0,0 +1 @@ +@import '../theme/color'; diff --git a/devui/style/core/_common.scss b/devui/style/core/_common.scss index c5c3bf6a..be15935c 100755 --- a/devui/style/core/_common.scss +++ b/devui/style/core/_common.scss @@ -57,7 +57,7 @@ a:hover { color: $devui-link; &:hover { - color: $devui-link-active; + color: $devui-link; text-decoration: underline; cursor: pointer; } @@ -67,7 +67,7 @@ a:hover { color: $devui-link-light; &:hover { - color: $devui-link-light-active; + color: $devui-link-light; text-decoration: underline; cursor: pointer; } @@ -95,3 +95,15 @@ a:hover { .devui-body-overflow-hidden { overflow: hidden; } + +.devui-data-table { + .devui-table-title { + font-weight: bold; + } + + .devui-table-link:hover { + text-decoration: underline; + cursor: pointer; + color: $devui-link; + } +} diff --git a/devui/style/core/_dropdown.scss b/devui/style/core/_dropdown.scss index ad23db8b..9ad0d53c 100755 --- a/devui/style/core/_dropdown.scss +++ b/devui/style/core/_dropdown.scss @@ -4,6 +4,17 @@ @import '../core/animation'; @import '../../style/theme/z-index'; +@mixin devui-no-data-tip() { + cursor: not-allowed; + color: $devui-disabled-text; + font-size: $devui-font-size; + background: $devui-base-bg; + line-height: 22px; + padding: 0; + text-align: center; + user-select: none; +} + .devui-dropdown { position: relative; vertical-align: middle; @@ -64,6 +75,7 @@ &.devui-scrollbar, .devui-scrollbar { + overflow-x: visible; overflow-y: auto; overflow-y: overlay; } @@ -147,6 +159,14 @@ } } } + + .devui-no-data-tip { + @include devui-no-data-tip(); + } +} + +.devui-dropdown-menu-wrap .devui-no-data-tip { + @include devui-no-data-tip(); } .devui-form-group.devui-has-feedback { diff --git a/devui/style/core/_form.scss b/devui/style/core/_form.scss index 5aad7ac5..512b2e75 100755 --- a/devui/style/core/_form.scss +++ b/devui/style/core/_form.scss @@ -47,7 +47,7 @@ $border-change-function: $devui-animation-ease-in-out-smooth; border: 1px solid $devui-form-control-line; border-radius: $devui-border-radius; outline: none; - background-color: $devui-base-bg; + background-color: $devui-form-control-bg; @include border-transition(); &:not([disabled]):not(.disabled):not(.devui-disabled):not(.error):not(.devui-error) { @@ -71,6 +71,10 @@ $border-change-function: $devui-animation-ease-in-out-smooth; color: $devui-disabled-text; } } + + &::placeholder { + color: $devui-placeholder; + } } .devui-form-controls textarea, @@ -107,7 +111,7 @@ $border-change-function: $devui-animation-ease-in-out-smooth; .devui-input { outline: none; - background-color: $devui-base-bg; + background-color: $devui-form-control-bg; border: 1px solid $devui-form-control-line; border-radius: $devui-border-radius; padding: 4px 8px; @@ -203,7 +207,7 @@ $border-change-function: $devui-animation-ease-in-out-smooth; .devui-form-control { color: $devui-text; - background-color: $devui-base-bg; + background-color: $devui-form-control-bg; padding: 4px 8px; border: 1px solid $devui-form-control-line; display: block; @@ -313,15 +317,18 @@ $border-change-function: $devui-animation-ease-in-out-smooth; } // css选择器不可合并,否则css解析器总是会失败 -input::-moz-placeholder { +input::-moz-placeholder, +textarea::-moz-placeholder { color: $devui-placeholder; } -input:-ms-input-placeholder { +input:-ms-input-placeholder, +textarea:-ms-input-placeholder { color: $devui-placeholder; } -input::-webkit-input-placeholder { +input::-webkit-input-placeholder, +textarea::-webkit-input-placeholder { color: $devui-placeholder; } diff --git a/devui/style/core/_index.scss b/devui/style/core/_index.scss index 14e46258..988bb05a 100755 --- a/devui/style/core/_index.scss +++ b/devui/style/core/_index.scss @@ -1,4 +1,3 @@ -@import '../mixins/index'; @import 'normalize'; @import 'reset'; @import 'common'; @@ -8,3 +7,8 @@ @import 'cdk'; @import 'icon_animation'; @import 'z-index'; +@import 'animation'; +@import 'font'; +@import 'layout'; +@import 'shadow'; +@import 'color'; diff --git a/devui/style/core/_shadow.scss b/devui/style/core/_shadow.scss new file mode 100644 index 00000000..c47bb793 --- /dev/null +++ b/devui/style/core/_shadow.scss @@ -0,0 +1 @@ +@import '../theme/shadow'; diff --git a/devui/style/devui.css b/devui/style/devui.css index b8a6e954..0b8ae77b 100644 --- a/devui/style/devui.css +++ b/devui/style/devui.css @@ -40,8 +40,7 @@ .grid { letter-spacing: -0.31em; - - /* *letter-spacing: normal; */ + *letter-spacing: normal; word-spacing: -0.43em; } @@ -75,8 +74,7 @@ .u-19-24, .u-23-24 { display: inline-block; - - /* *display: inline; */ + *display: inline; zoom: 1; letter-spacing: normal; word-spacing: normal; @@ -703,7 +701,7 @@ a:hover { background-color: #ffffff; background-color: var(--devui-connected-overlay-bg, #ffffff); box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2); - box-shadow: var(--devui-shadow-connected-overlay, 0 2px 8px 0) var(--devui-shadow, rgba(0, 0, 0, 0.2)); + box-shadow: var(--devui-shadow-length-connected-overlay, 0 2px 8px 0) var(--devui-shadow, rgba(0, 0, 0, 0.2)); outline: none; } @@ -849,7 +847,7 @@ a:hover { background: #ffffff; background: var(--devui-connected-overlay-bg, #ffffff); box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2); - box-shadow: var(--devui-shadow-connected-overlay, 0 2px 8px 0) var(--devui-shadow, rgba(0, 0, 0, 0.2)); + box-shadow: var(--devui-shadow-length-connected-overlay, 0 2px 8px 0) var(--devui-shadow, rgba(0, 0, 0, 0.2)); } .devui-dropdown .devui-dropdown-menu > li > a:not(.disabled) { diff --git a/devui/style/theme/_basic.scss b/devui/style/theme/_basic.scss index 7dba44d9..71bbcc78 100644 --- a/devui/style/theme/_basic.scss +++ b/devui/style/theme/_basic.scss @@ -1,6 +1,7 @@ // Color // 取色规则1: 所有使用颜色均需要在色板中选择 // 取色规则2: 除标签等用于功能分类及black,white的取色可以增加透明度(eg: rgba($devui-white-5,0.3),其余场景均不允许 +// need to run `node scripts/themeable/transfer-sass-var-to-theme-data.js ` when modified $devui-blue-5: #f2f5fc; $devui-blue-10: #e9edfa; @@ -134,7 +135,7 @@ $devui-slate-80: #575d6c; $devui-slate-90: #323745; $devui-slate-100: #252b3a; -$devui-zinc-5: #f8f8fa; +$devui-zinc-5: #f7f7f9; $devui-zinc-10: #f2f2f3; $devui-zinc-20: #e2e2e6; $devui-zinc-30: #d5d5db; diff --git a/devui/style/theme/_color.scss b/devui/style/theme/_color.scss index f940249d..778b9c18 100755 --- a/devui/style/theme/_color.scss +++ b/devui/style/theme/_color.scss @@ -1,4 +1,5 @@ @import './basic'; +// need to run `node scripts/themeable/transfer-sass-var-to-theme-data.js ` when modified // 基础变量 $devui-global-bg: var(--devui-global-bg, $devui-zinc-5); // 全局带底色背景 $devui-global-bg-normal: var(--devui-global-bg-normal, $devui-white-5); // 全局白色背景 @@ -93,16 +94,16 @@ $devui-contrast-active: var(--devui-contrast-active, #b12220); // 突出按钮 // 状态 $devui-danger-line: var(--devui-danger-line, $devui-red-50); // 失败边框 -$devui-danger-bg: var(--devui-danger-bg, $devui-red-5); // 失败底色 +$devui-danger-bg: var(--devui-danger-bg, $devui-red-10); // 失败底色 $devui-warning-line: var(--devui-warning-line, $devui-orange-50); // 警告边框 -$devui-warning-bg: var(--devui-warning-bg, $devui-orange-5); // 警告底色 +$devui-warning-bg: var(--devui-warning-bg, $devui-orange-10); // 警告底色 $devui-info-line: var(--devui-info-line, $devui-blue-50); // 通知边框 -$devui-info-bg: var(--devui-info-bg, $devui-blue-5); // 通知底色 +$devui-info-bg: var(--devui-info-bg, $devui-blue-10); // 通知底色 $devui-success-line: var(--devui-success-line, $devui-green-50); // 成功边框 -$devui-success-bg: var(--devui-success-bg, $devui-green-5); // 成功底色 +$devui-success-bg: var(--devui-success-bg, $devui-green-10); // 成功底色 $devui-primary-line: var(--devui-primary-line, $devui-blue-50); // 主要边框 $devui-primary-bg: var(--devui-primary-bg, $devui-blue-5); // 主要底色 diff --git a/devui/style/theme/_shadow.scss b/devui/style/theme/_shadow.scss index a86b13c3..6f418a77 100644 --- a/devui/style/theme/_shadow.scss +++ b/devui/style/theme/_shadow.scss @@ -4,9 +4,9 @@ $devui-shadow-length-base: var(--devui-shadow-length-base, 0 1px 4px 0); //直 $devui-shadow-length-slide-left: var(--devui-shadow-length-slide-left, -2px 0 8px 0); //向左滑动时出现在右侧边缘的阴影 (dataTable固定右侧列向左滑动) $devui-shadow-length-slide-right: var(--devui-shadow-length-slide-right, 2px 0 8px 0); //向右滑动时出现在左侧边缘的阴影 (dataTable固定左侧列向右滑动) -$devui-shadow-length-connected-overlay : var(--devui-shadow-connected-overlay, 0 2px 8px 0); //有连接点的弹出(覆盖)层 (DatePicker Cascader Select TagsInput Pagination的下拉菜单等) +$devui-shadow-length-connected-overlay: var(--devui-shadow-length-connected-overlay, 0 4px 8px 0); //有连接点的弹出(覆盖)层 (DatePicker Cascader Select TagsInput Pagination的下拉菜单等) -$devui-shadow-length-hover : var(--devui-shadow-length-hover, 0 4px 16px 0); //涉及到hover的地方 -$devui-shadow-length-feedback-overlay : var(--devui-shadow-length-feedback-overlay, 0 4px 16px 0); //信息提示反馈类 (PopOver Tooltip Toast StepsGuide等) +$devui-shadow-length-hover: var(--devui-shadow-length-hover, 0 8px 16px 0); //涉及到hover的地方 +$devui-shadow-length-feedback-overlay: var(--devui-shadow-length-feedback-overlay, 0 8px 16px 0); //信息提示反馈类 (PopOver Tooltip Toast StepsGuide等) -$devui-shadow-length-fullscreen-overlay: var(--devui-shadow-fullscreen-overlay, 0 8px 40px 0); //无连接点的弹出(覆盖)层 (Drawer Modal ImagePreview等) +$devui-shadow-length-fullscreen-overlay: var(--devui-shadow-length-fullscreen-overlay, 0 12px 24px 0); //无连接点的弹出(覆盖)层 (Drawer Modal ImagePreview等) diff --git a/devui/tabs/demo/big-data/big-data.component.html b/devui/tabs/demo/big-data/big-data.component.html index eb0364a2..5781c22e 100644 --- a/devui/tabs/demo/big-data/big-data.component.html +++ b/devui/tabs/demo/big-data/big-data.component.html @@ -1,9 +1,16 @@ -
    - - - - {{ item.title }} - +
    +

    Scroll mode: normal

    + + + {{ item.title }} + + +
    +

    Scroll mode: auto

    + Load Data + + + {{ item.title }}
    diff --git a/devui/tabs/demo/big-data/big-data.component.scss b/devui/tabs/demo/big-data/big-data.component.scss new file mode 100644 index 00000000..7b1e4a63 --- /dev/null +++ b/devui/tabs/demo/big-data/big-data.component.scss @@ -0,0 +1,13 @@ +section { + position: relative; +} + +d-button { + position: absolute; + left: 160px; + top: 128px; +} + +d-tabs:last-child { + margin-top: 32px; +} diff --git a/devui/tabs/demo/big-data/big-data.component.ts b/devui/tabs/demo/big-data/big-data.component.ts index c26d31ca..1580c331 100644 --- a/devui/tabs/demo/big-data/big-data.component.ts +++ b/devui/tabs/demo/big-data/big-data.component.ts @@ -1,15 +1,20 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'd-big-data', templateUrl: './big-data.component.html', + styleUrls: ['./big-data.component.scss'], }) -export class BigDataComponent implements OnInit { +export class BigDataComponent { + toggle = false; + showLoading = false; tabActiveId: string | number = 'tab1'; - tabItems = []; + baseData = [{ id: 'tab1', title: 'Tab1', content: 'Tab1 Content' }]; + staticData = []; + dynamicData = this.baseData; constructor() { for (let i = 1; i < 50; i++) { - this.tabItems.push({ + this.staticData.push({ id: `tab${i}`, title: `Tab${i}`, content: `Tab${i} Content`, @@ -17,9 +22,13 @@ export class BigDataComponent implements OnInit { } } - ngOnInit(): void { + getData() { + this.showLoading = true; setTimeout(() => { - this.tabActiveId = 'tab2'; - }, 100); + this.dynamicData = this.toggle ? this.baseData : [...this.staticData]; + this.tabActiveId = this.toggle ? 'tab1' : 'tab21'; + this.toggle = !this.toggle; + this.showLoading = false; + }, 1000); } } diff --git a/devui/tabs/demo/custom/custom.component.html b/devui/tabs/demo/custom/custom.component.html index f1aaae8c..f8b6687a 100644 --- a/devui/tabs/demo/custom/custom.component.html +++ b/devui/tabs/demo/custom/custom.component.html @@ -5,10 +5,7 @@ {{ item.title }} -
    - {{ item.content }} -
    -
    +
    {{ item.content }}
    diff --git a/devui/tabs/demo/tabs-demo.component.ts b/devui/tabs/demo/tabs-demo.component.ts index d0e04856..4025cde7 100755 --- a/devui/tabs/demo/tabs-demo.component.ts +++ b/devui/tabs/demo/tabs-demo.component.ts @@ -52,6 +52,7 @@ export class TabsDemoComponent implements OnInit, OnDestroy { BigDataSource: Array = [ { title: 'HTML', language: 'xml', code: require('./big-data/big-data.component.html?raw') }, { title: 'TS', language: 'typescript', code: require('./big-data/big-data.component.ts?raw') }, + { title: 'SCSS', language: 'css', code: require('./big-data/big-data.component.scss?raw') }, ]; navItems = []; subs: Subscription = new Subscription(); diff --git a/devui/tabs/demo/tabs-demo.module.ts b/devui/tabs/demo/tabs-demo.module.ts index c6f8b68f..02894025 100755 --- a/devui/tabs/demo/tabs-demo.module.ts +++ b/devui/tabs/demo/tabs-demo.module.ts @@ -1,7 +1,9 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; +import { ButtonModule } from 'ng-devui/button'; import { DropDownModule } from 'ng-devui/dropdown'; +import { LoadingModule } from 'ng-devui/loading'; import { ModalModule } from 'ng-devui/modal'; import { DevUIApiComponent } from 'ng-devui/shared/devui-api/devui-api.component'; import { DevUIApiModule } from 'ng-devui/shared/devui-api/devui-api.module'; @@ -25,17 +27,19 @@ import { WithoutContentComponent } from './without-content/without-content.compo @NgModule({ imports: [ + ButtonModule, CommonModule, DDemoNavModule, DevUICodeboxModule, DevUIApiModule, DropDownModule, + LoadingModule, ModalModule, TabsModule, TransferModule, TranslateModule, RouterModule.forChild([ - { path: '', redirectTo: 'demo' }, + { path: '', redirectTo: 'demo', pathMatch: 'full' }, { path: 'demo', component: TabsDemoComponent }, { path: 'api', diff --git a/devui/tabs/demo/without-content/without-content.component.html b/devui/tabs/demo/without-content/without-content.component.html index dcac4385..f6c95bf3 100755 --- a/devui/tabs/demo/without-content/without-content.component.html +++ b/devui/tabs/demo/without-content/without-content.component.html @@ -1,11 +1,9 @@
    - + - - - -
    activeID: {{ acticeTabId | json }}
    +
    +
    activeID: {{ tabActiveId | json }}
    diff --git a/devui/tabs/demo/without-content/without-content.component.ts b/devui/tabs/demo/without-content/without-content.component.ts index 3fac6a97..deadbf6d 100755 --- a/devui/tabs/demo/without-content/without-content.component.ts +++ b/devui/tabs/demo/without-content/without-content.component.ts @@ -1,15 +1,19 @@ -import { Component, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; @Component({ selector: 'd-without-content', - templateUrl: './without-content.component.html' + templateUrl: './without-content.component.html', + styles: [ + ` + pre { + border: none; + } + `, + ], }) -export class WithoutContentComponent implements OnInit { - acticeTabId: string | number = 'tab2'; - constructor() { } +export class WithoutContentComponent { + tabActiveId: string | number = 'tab2'; - ngOnInit() { - } activeTabChange(event) { console.log('switch to', event); } diff --git a/devui/tabs/doc/api-cn.md b/devui/tabs/doc/api-cn.md index 29714bec..ae35b7f9 100644 --- a/devui/tabs/doc/api-cn.md +++ b/devui/tabs/doc/api-cn.md @@ -21,32 +21,32 @@ import { TabsModule } from 'ng-devui/tabs'; ## d-tabs 参数 -| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 | -| :--: | :-------------------------------------: | :----: | :------------------: | :---------------------------- | ---------- | -| type | `tabs\|pills\|options\|wrapped\|slider` | 'tabs' | 可选,选项卡组的类型 | [Pills 类型](demo#type-pills) | -| size | `xs\|sm\|md\|lg` | 'md' | 可选,选项卡组的尺寸 | [选项卡尺寸](demo#size) | -| showContent | `boolean` | true | 可选,是否显示选项卡对应的内容 | [不设置内容](demo#no-set-content) | -| activeTab | `string` | -- | 可选,当前激活的选项卡,值为选项卡的 id | [基本用法](demo#basic-usage) | -| customWidth | `string` | -- | 可选,自定义选项卡的宽度 | | -| beforeChange | `function\|Promise\|Observable` | -- | tab 切换前的回调函数,返回 boolean 类型,返回 false 可以阻止 tab 的切换 | [拦截 tab 切换](demo#intercept-tab-switch) | -| reactivable | `boolean` | false | 可选,点击当前处于激活态的 tab 时是否触发`activeTabChange`事件,`true`为允许触发,`false`为不允许触发 | [拦截 tab 切换](demo#intercept-tab-switch) | -| closeable | `boolean` | false | 可选,是否显示删除图标 | [添加 / 删除](demo#add-delete) | -| closeableIds | `Array` | [] | 可选,指定可删除的选项卡 Id。默认为空数组,选项卡都可以被删除 | [添加 / 删除](demo#add-delete) | -| addable | `boolean` | false | 可选, 是否显示添加选项卡 | [添加 / 删除](demo#add-delete) | -| addTabTpl | `TemplateRef` | -- | 可选, 配合 addable 使用,自定义添加按钮选项卡 | | -| scrollMode | `boolean` | false | 可选, 是否启用大数据滚动显示数 | [大数据展示](demo#big-data) | +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | 全局配置项 | +| ------------ | --------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ---------- | +| type | `tabs\|pills\|options\|wrapped\|slider` | 'tabs' | 可选,选项卡组的类型 | [Pills 类型](demo#type-pills) | +| size | `xs\|sm\|md\|lg` | 'md' | 可选,选项卡组的尺寸 | [选项卡尺寸](demo#size) | +| showContent | `boolean` | true | 可选,是否显示选项卡对应的内容 | [不设置内容](demo#no-set-content) | +| activeTab | `string` | -- | 可选,当前激活的选项卡,值为选项卡的 id | [基本用法](demo#basic-usage) | +| customWidth | `string` | -- | 可选,自定义选项卡的宽度 | | +| beforeChange | `function\|Promise\|Observable` | -- | tab 切换前的回调函数,返回 boolean 类型,返回 false 可以阻止 tab 的切换 | [拦截 tab 切换](demo#intercept-tab-switch) | +| reactivable | `boolean` | false | 可选,点击当前处于激活态的 tab 时是否触发`activeTabChange`事件,`true`为允许触发,`false`为不允许触发 | [拦截 tab 切换](demo#intercept-tab-switch) | +| closeable | `boolean` | false | 可选,是否显示删除图标 | [添加 / 删除](demo#add-delete) | +| closeableIds | `Array` | [] | 可选,指定可删除的选项卡 Id。默认为空数组,选项卡都可以被删除 | [添加 / 删除](demo#add-delete) | +| addable | `boolean` | false | 可选, 是否显示添加选项卡 | [添加 / 删除](demo#add-delete) | +| addTabTpl | `TemplateRef` | -- | 可选, 配合 addable 使用,自定义添加按钮选项卡 | | +| scrollMode | `boolean \| 'normal'\| 'auto'` | false | 可选, 是否启用大数据滚动显示,normal 和 true 时为开启,auto 时会根据选项卡总宽度与容器宽度比较自动开关滚动模式 | [大数据展示](demo#big-data) | ## d-tabs 事件 -| 参数 | 类型 | 说明 | 跳转 Demo | -| :------------------: | :----------------------------: | :---------------------------------------------------------------------------------- | ------------------------------ | -| activeTabChange | `EventEmitter` | 可选,选项卡切换的回调函数,返回当前激活选项卡的 id | [基本用法](demo#basic-usage) | +| 参数 | 类型 | 说明 | 跳转 Demo | +| -------------------- | ------------------------------ | ----------------------------------------------------------------------------------- | ------------------------------ | +| activeTabChange | `EventEmitter` | 可选,选项卡切换的回调函数,返回当前激活选项卡的 id | [基本用法](demo#basic-usage) | | addOrDeleteTabChange | `EventEmitter` | 可选,添加、删除选项卡的回调函数,返回操作的选项卡 id 和 operation(add \| delete) | [添加 / 删除](demo#add-delete) | ### d-tab 参数 -| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | -| :------: | :--------------: | :---: | :-------------------------- | --------------------------------- | -| id | `number\|string` | -- | 可选,用来标识 tab 的唯一值 | [基本用法](demo#basic-usage) | -| title | `string` | -- | 可选,选项卡的标题 | [基本用法](demo#basic-usage) | -| disabled | `boolean` | false | 可选,选项卡是否不可用 | [不设置内容](demo#no-set-content) | +| 参数 | 类型 | 默认 | 说明 | 跳转 Demo | +| -------- | ---------------- | ----- | --------------------------- | --------------------------------- | +| id | `number\|string` | -- | 可选,用来标识 tab 的唯一值 | [基本用法](demo#basic-usage) | +| title | `string` | -- | 可选,选项卡的标题 | [基本用法](demo#basic-usage) | +| disabled | `boolean` | false | 可选,选项卡是否不可用 | [不设置内容](demo#no-set-content) | diff --git a/devui/tabs/doc/api-en.md b/devui/tabs/doc/api-en.md index 7ed32597..3d8ff959 100644 --- a/devui/tabs/doc/api-en.md +++ b/devui/tabs/doc/api-en.md @@ -21,31 +21,31 @@ In the page: ## d-tabs parameter -| Parameter | Type | Default | Description | Jump to Demo | Global Config | -| :----------: | :-------------------------------------: | :-----: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------ | ------------- | -| type | `tabs\|pills\|options\|wrapped\|slider` | 'tabs' | Optional. Tab group type | [Type Pills](demo#type-pills) | -| showContent | `boolean` | true | Optional. Indicating whether to display the content corresponding to the tab. | [No Content](demo#no-set-content) | -| activeTab | `string` | -- | Optional. Currently activated tab. The value is the ID of the tab. | [Basic Usage](demo#basic-usage) | -| customWidth | `string` | -- | Optional. It indicates the width of the customized tab. | | -| beforeChange | `function\|Promise\|Observable` | -- | Optional. Tab Callback function before switching. The value of this parameter is of the boolean type. If false is returned, tab switching can be prevented. | [Interception Tab Switching](demo#intercept-tab-switch) | -| reactivable | `boolean` | false | Optional. Indicates whether to trigger the `activeTabChange` event when a tab in the active state is clicked. The value true indicates that the event can be triggered, and the value false indicates that the event cannot be triggered. | [Interception Tab Switching](demo#intercept-tab-switch) | -| closeable | `boolean` | false | Optional. Specifies whether to display the deletion icon. | [Add / Remove](demo#add-delete) | -| closeableIds | `Array` | [] | Optional. Specifies the ID of the tab that can be deleted. By default, the array is empty. All tabs can be deleted. | [Add / Remove](demo#add-delete) | -| addable | `boolean` | false | Optional. Indicating whether to display the add tab. | [Add / Remove](demo#add-delete) | -| addTabTpl | `TemplateRef` | -- | Optional. Used together with addable to customize the add tab. | | -| scrollMode | `boolean` | false | Optional. Specifies whether to enable big data scrolling display. | [Big data display](demo#big-data) | +| Parameter | Type | Default | Description | Jump to Demo | Global Config | +| ------------ | --------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | ------------- | +| type | `tabs\|pills\|options\|wrapped\|slider` | 'tabs' | Optional. Tab group type | [Type Pills](demo#type-pills) | +| showContent | `boolean` | true | Optional. Indicating whether to display the content corresponding to the tab. | [No Content](demo#no-set-content) | +| activeTab | `string` | -- | Optional. Currently activated tab. The value is the ID of the tab. | [Basic Usage](demo#basic-usage) | +| customWidth | `string` | -- | Optional. It indicates the width of the customized tab. | | +| beforeChange | `function\|Promise\|Observable` | -- | Optional. Tab Callback function before switching. The value of this parameter is of the boolean type. If false is returned, tab switching can be prevented. | [Interception Tab Switching](demo#intercept-tab-switch) | +| reactivable | `boolean` | false | Optional. Indicates whether to trigger the `activeTabChange` event when a tab in the active state is clicked. The value true indicates that the event can be triggered, and the value false indicates that the event cannot be triggered. | [Interception Tab Switching](demo#intercept-tab-switch) | +| closeable | `boolean` | false | Optional. Specifies whether to display the deletion icon. | [Add / Remove](demo#add-delete) | +| closeableIds | `Array` | [] | Optional. Specifies the ID of the tab that can be deleted. By default, the array is empty. All tabs can be deleted. | [Add / Remove](demo#add-delete) | +| addable | `boolean` | false | Optional. Indicating whether to display the add tab. | [Add / Remove](demo#add-delete) | +| addTabTpl | `TemplateRef` | -- | Optional. Used together with addable to customize the add tab. | | +| scrollMode | `boolean \| 'normal'\| 'auto'` | false | Optional. Indicates whether to enable big data scrolling. The options are normal and true. The options are auto. The scrolling mode is automatically enabled based on the comparison between the total tab width and container width. | [Big data display](demo#big-data) | ## d-tabs event -| Parameter | Type | Description | Jump to Demo | -| :------------------: | :----------------------------: | :----------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | -| activeTabChange | `EventEmitter` | Optional. Callback function for switching tabs. This parameter is optional. It returns the ID of the currently activated tab. | [Basic usage](demo#basic-usage) | +| Parameter | Type | Description | Jump to Demo | +| -------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------- | +| activeTabChange | `EventEmitter` | Optional. Callback function for switching tabs. This parameter is optional. It returns the ID of the currently activated tab. | [Basic usage](demo#basic-usage) | | addOrDeleteTabChange | `EventEmitter` | Optional. Callback function for adding or deleting tabs. It returns the tab ID and operation (add \| delete) of the operation. | [Add / Remove](demo#add-delete) | ## d-tab Parameter -| Parameter | Type | Default | Description | Jump to Demo | -| :-------: | :--------------: | :-----: | :-------------------------------------------------- | --------------------------------- | -| id | `number\|string` | -- | Optional. Unique value that identifies a tab. | [Basic usage](demo#basic-usage) | -| title | `string` | -- | Optional. Tab title | [Basic usage](demo#basic-usage) | -| disabled | `boolean` | false | Optional. Indicating whether the tab is unavailable | [No Content](demo#no-set-content) | +| Parameter | Type | Default | Description | Jump to Demo | +| --------- | ---------------- | ------- | --------------------------------------------------- | --------------------------------- | +| id | `number\|string` | -- | Optional. Unique value that identifies a tab. | [Basic usage](demo#basic-usage) | +| title | `string` | -- | Optional. Tab title | [Basic usage](demo#basic-usage) | +| disabled | `boolean` | false | Optional. Indicating whether the tab is unavailable | [No Content](demo#no-set-content) | diff --git a/devui/tabs/ng-package.json b/devui/tabs/ng-package.json new file mode 100644 index 00000000..98773f3e --- /dev/null +++ b/devui/tabs/ng-package.json @@ -0,0 +1,5 @@ +{ + "lib": { + "entryFile": "public-api.ts" + } +} \ No newline at end of file diff --git a/devui/tabs/package.json b/devui/tabs/package.json deleted file mode 100755 index ded1e7a9..00000000 --- a/devui/tabs/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "ngPackage": { - "lib": { - "entryFile": "public-api.ts" - } - } -} diff --git a/devui/tabs/tab.component.ts b/devui/tabs/tab.component.ts index 16e6a92f..e92e7ec3 100755 --- a/devui/tabs/tab.component.ts +++ b/devui/tabs/tab.component.ts @@ -4,10 +4,7 @@ import { TabTitleDirective } from './tab-title.directive'; @Component({ selector: 'd-tab', - template: ` - - - `, + template: ``, preserveWhitespaces: false, }) export class TabComponent { @@ -27,5 +24,5 @@ export class TabComponent { */ @ContentChild(TabContentDirective) contentTpl: TabContentDirective; @ContentChild(TabTitleDirective) titleTpl: TabTitleDirective; - @ViewChild('innerContent', {static: true}) innerContent: TemplateRef; + @ViewChild('innerContent', { static: true }) innerContent: TemplateRef; } diff --git a/devui/tabs/tabs.component.html b/devui/tabs/tabs.component.html index 8e06e4a8..388a3e23 100755 --- a/devui/tabs/tabs.component.html +++ b/devui/tabs/tabs.component.html @@ -1,5 +1,5 @@
    -
    +
    @@ -13,8 +13,8 @@
      @@ -88,7 +88,7 @@
    -
    +
    @@ -118,7 +118,13 @@
    FirstName
    beforetypeafter translate
    {{ rowItem.number }}{{ rowItem.type }}{{ rowItem.number | dNumberTrans: rowItem.type }}