From bc567e18269ece6123d4cc27fbfad8476c3b25a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E6=9C=BA=E5=99=A8=E4=BA=BA?= Date: Mon, 2 Sep 2019 09:55:52 +0800 Subject: [PATCH] Virtual scroll & Accessibility support (#420) * accessibility * Ref typescript define * Update test case * re-design active logic * support selection * options * support multiple select * label in value * measure support * measure with flex layout * adjust style * input should trigger open * update filter & active logic * back to first of active * autoClearSearchValue works * allowClear * not allow clear when input is full * merge accessibility text * use combobox to active item accessibility * use clear lock to prevent quick backspace * adjust opacity of prev value logic * support disabled * dropdown match width * move focus logic out * add demo * focus not trigger input when tabs * add getPopupContainer * patch demo * update typescript define * arrow will scroll to index item * single node will auto active item when open * support tokenSeparators * support notFound * support optionLabelProp * placeholder of it * support inputIcon * removeIonc * support loading * legacy support of options * ts define * init combobox demo * active input * update deps to fix scrollTo bug * tmp of combobox * support onInputKeyDown * update demo * pass customize input * rm Context * fix tab to blink popup * tmp refactor * fix select combo logic * reset active value * fix icon * add motion support * add animate * add missing props * update demo * getPopupContainer * loading * multi tags * fix clear logic * backspace not trigger open * multiple * fix single demo * fix combobox display logic * fix combobox display logic & label sync * init test * add test case * add part of test * add test case * update snapshot * add missing class * check selected class * onChange support second param * search test * focus test * useLayoutEffect only works on client side * focus test * blur test * update icon name * warning in generator * dropdown test * start combobox tests * start multiple test * clean up * support multiple test * refact optionLabelProp * paste change should close * selections test * multiple test finished * refactor of trigger change logic * refactor triggerSelect event * tmp of tags miss value * tags should list option when not provided * tags should keep missing value order * adjust useMemo logicc * tags logicc * selecttrigger test case * lint generate * fix lint * fix example lint * util lint fix * fix generator ts define * fix enabled lint * support dropdown number * clean up ci * update jest config * clean up example * fix combobox open logic * fix icon logic * fix className of trans btn * immutaple of content * updatee snapshot * test env should not generate uuid * 100% line coverage --- .circleci/config.yml | 2 - .eslintrc.js | 13 + .fatherrc.js | 8 + .gitignore | 2 - assets/index.less | 696 +++---- examples/{combobox.js => combobox.tsx} | 54 +- examples/common.less | 10 + .../{tbFetchSuggest.js => tbFetchSuggest.tsx} | 4 +- examples/{controlled.js => controlled.tsx} | 30 +- examples/{custom-icon.js => custom-icon.tsx} | 71 +- .../{dropdownRender.js => dropdownRender.tsx} | 20 +- examples/{email.js => email.tsx} | 8 +- .../{force-suggest.js => force-suggest.tsx} | 17 +- ...opupContainer.js => getPopupContainer.tsx} | 4 +- examples/{loading.js => loading.tsx} | 12 +- examples/{mul-suggest.js => mul-suggest.tsx} | 19 +- ...mul-tag-suggest.js => mul-tag-suggest.tsx} | 18 +- ...iple-readonly.js => multiple-readonly.tsx} | 11 +- examples/{multiple.js => multiple.tsx} | 18 +- examples/{optgroup.js => optgroup.tsx} | 4 +- examples/optionFilterProp.js | 36 - examples/optionFilterProp.tsx | 39 + examples/optionLabelProp.js | 28 - examples/optionLabelProp.tsx | 29 + ...ngle-animation.js => single-animation.tsx} | 4 +- examples/{single.js => single.tsx} | 40 +- examples/{suggest.js => suggest.tsx} | 12 +- examples/tags.js | 92 - examples/tags.tsx | 78 + .../{update-option.js => update-option.tsx} | 26 +- jest.config.js | 3 + now.json | 2 +- package.json | 85 +- src/DropdownMenu.tsx | 246 --- src/OptGroup.tsx | 26 +- src/Option.tsx | 30 +- src/OptionList.tsx | 301 +++ src/PropTypes.ts | 177 -- src/Select.tsx | 1697 +---------------- src/SelectTrigger.tsx | 314 +-- src/Selector/Input.tsx | 79 + src/Selector/MultipleSelector.tsx | 188 ++ src/Selector/SingleSelector.tsx | 74 + src/Selector/index.tsx | 160 ++ src/TransBtn.tsx | 55 + src/generate.tsx | 863 +++++++++ src/hooks/useDelayReset.ts | 31 + src/hooks/useLayoutEffect.ts | 17 + src/hooks/useLock.ts | 33 + src/index.ts | 11 +- src/interface/generator.ts | 52 + src/interface/index.ts | 42 + src/util.ts | 206 -- src/utils/commonUtil.ts | 107 ++ src/utils/legacyUtil.ts | 43 + src/utils/valueUtil.ts | 282 +++ src/utils/warningPropsUtil.ts | 155 ++ tests/Combobox.test.tsx | 334 ++++ tests/DropdownMenu.spec.tsx | 95 - tests/Group.test.tsx | 37 + tests/Hooks.test.tsx | 30 + tests/Multiple.test.tsx | 242 +++ tests/OptionList.test.tsx | 140 ++ tests/Select.combobox.spec.tsx | 401 ---- tests/Select.multiple.spec.tsx | 271 --- tests/Select.optGroup.spec.tsx | 20 - tests/Select.tags.spec.tsx | 241 --- tests/{Select.spec.tsx => Select.test.tsx} | 941 ++++----- tests/SelectTrigger.spec.tsx | 28 +- tests/Tags.test.tsx | 214 +++ tests/__mocks__/rc-virtual-list.tsx | 3 + tests/__snapshots__/Combobox.test.tsx.snap | 33 + .../__snapshots__/DropdownMenu.spec.tsx.snap | 48 - tests/__snapshots__/Multiple.test.tsx.snap | 78 + tests/__snapshots__/OptionList.test.tsx.snap | 92 + .../Select.combobox.spec.tsx.snap | 108 -- .../Select.multiple.spec.tsx.snap | 568 ------ tests/__snapshots__/Select.spec.tsx.snap | 954 --------- tests/__snapshots__/Select.tags.spec.tsx.snap | 1246 ------------ tests/__snapshots__/Select.test.tsx.snap | 922 +++++++++ .../__snapshots__/SelectTrigger.spec.tsx.snap | 7 - tests/__snapshots__/Tags.test.tsx.snap | 275 +++ tests/setup.ts | 6 - tests/shared/allowClearTest.tsx | 8 +- tests/shared/blurTest.tsx | 115 +- tests/shared/dynamicChildrenTest.tsx | 65 +- tests/shared/focusTest.tsx | 135 +- tests/shared/hoverTest.tsx | 7 +- tests/shared/inputFilterTest.tsx | 26 +- tests/shared/keyDownTest.tsx | 6 +- tests/shared/openControlledTest.tsx | 12 +- tests/shared/removeSelectedTest.tsx | 72 +- tests/shared/renderTest.tsx | 108 +- tests/shared/throwOptionValue.tsx | 31 +- tests/util.spec.ts | 112 -- tests/utils.test.jsx | 67 + tests/utils/common.ts | 69 + 97 files changed, 6626 insertions(+), 8225 deletions(-) create mode 100644 .eslintrc.js create mode 100644 .fatherrc.js rename examples/{combobox.js => combobox.tsx} (58%) create mode 100644 examples/common.less rename examples/common/{tbFetchSuggest.js => tbFetchSuggest.tsx} (89%) rename examples/{controlled.js => controlled.tsx} (79%) rename examples/{custom-icon.js => custom-icon.tsx} (81%) rename examples/{dropdownRender.js => dropdownRender.tsx} (82%) rename examples/{email.js => email.tsx} (89%) rename examples/{force-suggest.js => force-suggest.tsx} (88%) rename examples/{getPopupContainer.js => getPopupContainer.tsx} (95%) rename examples/{loading.js => loading.tsx} (88%) rename examples/{mul-suggest.js => mul-suggest.tsx} (82%) rename examples/{mul-tag-suggest.js => mul-tag-suggest.tsx} (85%) rename examples/{multiple-readonly.js => multiple-readonly.tsx} (84%) rename examples/{multiple.js => multiple.tsx} (90%) rename examples/{optgroup.js => optgroup.tsx} (95%) delete mode 100644 examples/optionFilterProp.js create mode 100644 examples/optionFilterProp.tsx delete mode 100644 examples/optionLabelProp.js create mode 100644 examples/optionLabelProp.tsx rename examples/{single-animation.js => single-animation.tsx} (94%) rename examples/{single.js => single.tsx} (79%) rename examples/{suggest.js => suggest.tsx} (85%) delete mode 100644 examples/tags.js create mode 100644 examples/tags.tsx rename examples/{update-option.js => update-option.tsx} (75%) create mode 100644 jest.config.js delete mode 100644 src/DropdownMenu.tsx create mode 100644 src/OptionList.tsx delete mode 100644 src/PropTypes.ts create mode 100644 src/Selector/Input.tsx create mode 100644 src/Selector/MultipleSelector.tsx create mode 100644 src/Selector/SingleSelector.tsx create mode 100644 src/Selector/index.tsx create mode 100644 src/TransBtn.tsx create mode 100644 src/generate.tsx create mode 100644 src/hooks/useDelayReset.ts create mode 100644 src/hooks/useLayoutEffect.ts create mode 100644 src/hooks/useLock.ts create mode 100644 src/interface/generator.ts create mode 100644 src/interface/index.ts delete mode 100644 src/util.ts create mode 100644 src/utils/commonUtil.ts create mode 100644 src/utils/legacyUtil.ts create mode 100644 src/utils/valueUtil.ts create mode 100644 src/utils/warningPropsUtil.ts create mode 100644 tests/Combobox.test.tsx delete mode 100644 tests/DropdownMenu.spec.tsx create mode 100644 tests/Group.test.tsx create mode 100644 tests/Hooks.test.tsx create mode 100644 tests/Multiple.test.tsx create mode 100644 tests/OptionList.test.tsx delete mode 100644 tests/Select.combobox.spec.tsx delete mode 100644 tests/Select.multiple.spec.tsx delete mode 100644 tests/Select.optGroup.spec.tsx delete mode 100644 tests/Select.tags.spec.tsx rename tests/{Select.spec.tsx => Select.test.tsx} (50%) create mode 100644 tests/Tags.test.tsx create mode 100644 tests/__mocks__/rc-virtual-list.tsx create mode 100644 tests/__snapshots__/Combobox.test.tsx.snap delete mode 100644 tests/__snapshots__/DropdownMenu.spec.tsx.snap create mode 100644 tests/__snapshots__/Multiple.test.tsx.snap create mode 100644 tests/__snapshots__/OptionList.test.tsx.snap delete mode 100644 tests/__snapshots__/Select.combobox.spec.tsx.snap delete mode 100644 tests/__snapshots__/Select.multiple.spec.tsx.snap delete mode 100644 tests/__snapshots__/Select.spec.tsx.snap delete mode 100644 tests/__snapshots__/Select.tags.spec.tsx.snap create mode 100644 tests/__snapshots__/Select.test.tsx.snap delete mode 100644 tests/__snapshots__/SelectTrigger.spec.tsx.snap create mode 100644 tests/__snapshots__/Tags.test.tsx.snap delete mode 100644 tests/setup.ts delete mode 100644 tests/util.spec.ts create mode 100644 tests/utils.test.jsx create mode 100644 tests/utils/common.ts diff --git a/.circleci/config.yml b/.circleci/config.yml index d23e109fc..da9cc7b50 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,6 @@ jobs: keys: - v1-dependencies-{{ checksum "package.json" }} - run: npm install - - run: npm run init-tslint - save_cache: paths: - node_modules @@ -25,7 +24,6 @@ jobs: keys: - v1-dependencies-{{ checksum "package.json" }} - run: npm install - - run: npm run init-tslint - save_cache: paths: - node_modules diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..a3b2c02a1 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,13 @@ +const base = require('@umijs/fabric/dist/eslint'); +const path = require('path'); + +module.exports = { + ...base, + rules: { + ...base.rules, + 'default-case': 0, + 'jsx-a11y/interactive-supports-focus': 0, + 'jsx-a11y/no-autofocus': 0, + 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], + }, +}; diff --git a/.fatherrc.js b/.fatherrc.js new file mode 100644 index 000000000..767a2abfe --- /dev/null +++ b/.fatherrc.js @@ -0,0 +1,8 @@ +export default { + cjs: 'babel', + esm: { type: 'babel', importLibToEs: true }, + preCommit: { + eslint: true, + prettier: true, + }, +}; diff --git a/.gitignore b/.gitignore index b6935787c..ba5c1b418 100644 --- a/.gitignore +++ b/.gitignore @@ -32,10 +32,8 @@ package-lock.json src/*.js src/*.map .prettierrc -jest.config.js tslint.json tsconfig.test.json -.eslintrc.js .prettierignore .storybook storybook/index.js diff --git a/assets/index.less b/assets/index.less index c74bb20e3..dad6f7162 100644 --- a/assets/index.less +++ b/assets/index.less @@ -1,541 +1,335 @@ -@selectPrefixCls: rc-select; +@select-prefix: ~'rc-select'; -@keyframes select-ring { - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } +* { + box-sizing: border-box; } -.effect() { - animation-duration: 0.3s; - animation-fill-mode: both; - transform-origin: 0 0; +.search-input-without-border() { + .@{select-prefix}-selection-search-input { + border: none; + outline: none; + background: rgba(255, 0, 0, 0.2); + width: 100%; + } } -.@{selectPrefixCls} { - box-sizing: border-box; +.@{select-prefix} { display: inline-block; + font-size: 12px; + width: 100px; position: relative; - vertical-align: middle; - color: #666; - line-height: 28px; - - ul, - li { - margin: 0; - padding: 0; - list-style: none; - } - > ul > li > a { - padding: 0; - background-color: #fff; - } - - // arrow - &-arrow { - height: 26px; - position: absolute; - top: 1px; - right: 1px; - width: 20px; - outline: none; - } - - &-arrow &-arrow-loading { - display: inline-block; - width: 18px; - height: 18px; - margin-top: 6px; - margin-left: -4px; - &:after { - content: ' '; - display: block; - width: 12px; - height: 12px; - margin: 2px; - border-radius: 50%; - border: 2px solid #999999; - border-color: #999999 transparent #999999 transparent; - animation: select-ring 1.2s linear infinite; + &-disabled { + &, + & input { + cursor: not-allowed; } - } - - &-arrow &-arrow-icon { - border-color: #999999 transparent transparent transparent; - border-style: solid; - border-width: 5px 4px 0 4px; - height: 0; - width: 0; - margin-left: -4px; - margin-top: -2px; - position: absolute; - top: 50%; - left: 50%; - } - // select with arrow or loader - &:not(.@{selectPrefixCls}-no-arrow), - &-loading { - .@{selectPrefixCls}-selection--multiple { - .@{selectPrefixCls}-selection__clear { - right: 20px; - } + .@{select-prefix}-selector { + opacity: 0.3; } } - &-selection { - outline: none; - user-select: none; - -webkit-user-select: none; - - box-sizing: border-box; - display: block; - - background-color: #fff; - border-radius: 6px; - border: 1px solid #d9d9d9; - - &__placeholder { - position: absolute; - top: 0; - color: #aaa; - } + &-show-arrow&-loading { + .@{select-prefix}-arrow { + &-icon::after { + box-sizing: border-box; + width: 12px; + height: 12px; + border-radius: 100%; + border: 2px solid #999; + border-top-color: transparent; + border-bottom-color: transparent; + transform: none; + margin-top: 4px; - &__clear { - font-weight: bold; - position: absolute; - line-height: 28px; - &-icon { - font-style: normal; + animation: rcSelectLoadingIcon 0.5s infinite; } } } - &-focused &-selection { - border-color: #23c0fa; - box-shadow: 0 0 2px fadeout(#2db7f5, 20%); + // ============== Selector =============== + .@{select-prefix}-selection-placeholder { + opacity: 0.4; } - &-enabled &-selection { - &:hover { - border-color: #23c0fa; - box-shadow: 0 0 2px fadeout(#2db7f5, 20%); - } - &:active { - border-color: #2db7f5; - } - } - - &-selection--single { - height: 28px; - line-height: 28px; - cursor: pointer; - position: relative; - - .@{selectPrefixCls}-selection-selected-value { - pointer-events: none; - position: absolute; - left: 0; - top: 0; - } - - .@{selectPrefixCls}-selection__rendered { - height: 28px; + // --------------- Single ---------------- + &-single { + .@{select-prefix}-selector { + display: flex; position: relative; - display: block; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - margin-left: 10px; - line-height: 28px; - } - .@{selectPrefixCls}-selection__clear { - top: 0; - right: 20px; - } - } + .@{select-prefix}-selection-search { + width: 100%; - &-disabled { - color: #ccc; - cursor: not-allowed; - - .@{selectPrefixCls}-selection--single, - .@{selectPrefixCls}-selection__choice__remove { - cursor: not-allowed; - color: #ccc; + &-input { + width: 100%; + } + } - &:hover { - cursor: not-allowed; - color: #ccc; + .@{select-prefix}-selection-item, + .@{select-prefix}-selection-placeholder { + position: absolute; + top: 1px; + left: 3px; + pointer-events: none; } } - } - &-search__field__wrap { - display: inline-block; - } + // Not customize + &:not(.@{select-prefix}-customize-input) { + .@{select-prefix}-selector { + padding: 1px; + border: 1px solid #000; - &-search__field__placeholder { - position: absolute; - top: 0; - left: 3px; - color: #aaa; - } - - &-search--inline { - width: 100%; - .@{selectPrefixCls}-search__field__wrap { - width: 100%; - } - .@{selectPrefixCls}-search__field { - border: none; - font-size: 100%; - //margin-top: 5px; - background: transparent; - outline: 0; - width: 100%; - &::-ms-clear { - display: none; + .search-input-without-border(); } } - .@{selectPrefixCls}-search__field__mirror { - position: absolute; - top: -999px; - left: 0; - white-space: pre; - } - > i { - float: right; - } - } - - &-enabled&-selection--multiple { - cursor: text; } - &-selection--multiple { - min-height: 28px; - - .@{selectPrefixCls}-search--inline { - float: left; - width: auto; - .@{selectPrefixCls}-search__field { - &__wrap { - width: auto; - } - width: 0.75em; + // -------------- Multiple --------------- + &-multiple .@{select-prefix}-selector { + display: flex; + flex-wrap: wrap; + padding: 1px; + border: 1px solid #000; + + .@{select-prefix}-selection-item { + flex: none; + background: #bbb; + border-radius: 4px; + margin-right: 2px; + padding: 0 8px; + + &-disabled { + cursor: not-allowed; + opacity: 0.5; } } - .@{selectPrefixCls}-search__field__placeholder { - top: 5px; - left: 8px; - } - - .@{selectPrefixCls}-selection__rendered { + .@{select-prefix}-selection-search { position: relative; - overflow: hidden; - text-overflow: ellipsis; - margin-left: 8px; - padding-bottom: 2px; - .@{selectPrefixCls}-selection__choice { - margin-top: 4px; - line-height: 20px; + &-input, + &-mirror { + padding: 1px; + font-family: system-ui; } - } - .@{selectPrefixCls}-selection__clear { - top: 1px; - right: 8px; - } - } - - &-enabled { - .@{selectPrefixCls}-selection__choice { - cursor: default; - &:hover { - .@{selectPrefixCls}-selection__choice__remove { - opacity: 1; - transform: scale(1); - } - .@{selectPrefixCls}-selection__choice__content { - margin-left: -8px; - margin-right: 8px; - } + &-mirror { + position: absolute; + z-index: 999; + white-space: nowrap; + position: none; + left: 0; + top: 0; + visibility: hidden; } } - .@{selectPrefixCls}-selection__choice__disabled { - cursor: not-allowed; - &:hover { - .@{selectPrefixCls}-selection__choice__content { - margin-left: 0; - margin-right: 0; - } - } - } + .search-input-without-border(); } - & &-selection__choice { - background-color: #f3f3f3; - border-radius: 4px; - float: left; - padding: 0 15px; - margin-right: 4px; - position: relative; - overflow: hidden; - transition: padding 0.3s cubic-bezier(0.6, -0.28, 0.735, 0.045), - width 0.3s cubic-bezier(0.6, -0.28, 0.735, 0.045); - - &__content { - margin-left: 0; - margin-right: 0; - transition: margin 0.3s cubic-bezier(0.165, 0.84, 0.44, 1); + // ================ Icons ================ + &-allow-clear { + &.@{select-prefix}-multiple .@{select-prefix}-selector { + padding-right: 20px; } - &-zoom-enter, - &-zoom-appear, - &-zoom-leave { - .effect(); - opacity: 0; - animation-play-state: paused; - animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275); - } - - &-zoom-leave { - opacity: 1; - animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045); - } - - &-zoom-enter.@{selectPrefixCls}-selection__choice-zoom-enter-active, - &-zoom-appear.@{selectPrefixCls}-selection__choice-zoom-appear-active { - animation-play-state: running; - animation-name: rcSelectChoiceZoomIn; - } - - &-zoom-leave.@{selectPrefixCls}-selection__choice-zoom-leave-active { - animation-play-state: running; - animation-name: rcSelectChoiceZoomOut; - } - - @keyframes rcSelectChoiceZoomIn { - 0% { - transform: scale(0.6); - opacity: 0; - } - 100% { - transform: scale(1); - opacity: 1; - } + .@{select-prefix}-clear { + position: absolute; + right: 20px; + top: 0; } + } - @keyframes rcSelectChoiceZoomOut { - to { - transform: scale(0); - opacity: 0; - } + &-show-arrow { + &.@{select-prefix}-multiple .@{select-prefix}-selector { + padding-right: 20px; } - &__remove { - color: #919191; - cursor: pointer; - font-weight: bold; - padding: 0 0 0 8px; + .@{select-prefix}-arrow { + pointer-events: none; position: absolute; - opacity: 0; - transform: scale(0); + right: 5px; top: 0; - right: 2px; - transition: opacity 0.3s, transform 0.3s; - &-icon { - font-style: normal; + &-icon::after { + content: ''; + border: 5px solid transparent; + width: 0; + height: 0; + display: inline-block; + border-top-color: #999; + transform: translateY(5px); } + } + } - &:hover { - color: #333; - } + // =============== Focused =============== + &-focused { + .@{select-prefix}-selector { + border-color: blue !important; } } + // ============== Dropdown =============== &-dropdown { - background-color: white; - border: 1px solid #d9d9d9; - box-shadow: 0 0px 4px #d9d9d9; - border-radius: 4px; - box-sizing: border-box; - z-index: 100; - left: -9999px; - top: -9999px; + border: 1px solid green; + min-height: 100px; position: absolute; - outline: none; + background: #fff; - &:empty, &-hidden { display: none; } + } + + // =============== Option ================ + &-item { + font-size: 16px; + line-height: 1.5; + padding: 4px 16px; + + // >>> Group + &-group { + color: #999; + font-weight: bold; + font-size: 80%; + } - &-menu { - outline: none; - margin: 0; - padding: 0; - list-style: none; - z-index: 9999; + // >>> Option + &-option { + position: relative; - > li { - margin: 0; - padding: 0; + &-grouped { + padding-left: 24px; } - &-item-group-list { - margin: 0; - padding: 0; + .@{select-prefix}-item-option-state { + position: absolute; + right: 0; + top: 4px; + pointer-events: none; + } - > li.@{selectPrefixCls}-menu-item { - padding-left: 20px; - } + // ------- Active ------- + &-active { + background: green; } - &-item-group-title { + // ------ Disabled ------ + &-disabled { color: #999; - line-height: 1.5; - padding: 8px 10px; - border-bottom: 1px solid #dedede; } + } - li&-item { - margin: 0; - position: relative; - display: block; - padding: 7px 10px; - font-weight: normal; - color: #666; - white-space: nowrap; + // >>> Empty + &-empty { + text-align: center; + color: #999; + } + } +} - &-disabled { - color: #ccc; - cursor: not-allowed; - } +.@{select-prefix}-selection__choice-zoom { + transition: all 0.3s; +} - &-selected { - color: #666; - background-color: #ddd; - } +.@{select-prefix}-selection__choice-zoom-appear { + opacity: 0; + transform: scale(0.5); - &-active { - background-color: #5897fb; - color: white; - cursor: pointer; - } + &&-active { + opacity: 1; + transform: scale(1); + } +} +.@{select-prefix}-selection__choice-zoom-leave { + opacity: 1; + transform: scale(1); - &-divider { - height: 1px; - margin: 1px 0; - overflow: hidden; - background-color: #e5e5e5; - line-height: 0; - } - } - } + &&-active { + opacity: 0; + transform: scale(0.5); + } +} - &-slide-up-enter, - &-slide-up-appear { - .effect(); - opacity: 0; - animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1); - animation-play-state: paused; - } +.effect() { + animation-duration: 0.3s; + animation-fill-mode: both; + transform-origin: 0 0; +} - &-slide-up-leave { - .effect(); - opacity: 1; - animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34); - animation-play-state: paused; - } +.@{select-prefix}-dropdown { + &-slide-up-enter, + &-slide-up-appear { + .effect(); + opacity: 0; + animation-timing-function: cubic-bezier(0.08, 0.82, 0.17, 1); + animation-play-state: paused; + } - &-slide-up-enter&-slide-up-enter-active&-placement-bottomLeft, - &-slide-up-appear&-slide-up-appear-active&-placement-bottomLeft { - animation-name: rcSelectDropdownSlideUpIn; - animation-play-state: running; - } + &-slide-up-leave { + .effect(); + opacity: 1; + animation-timing-function: cubic-bezier(0.6, 0.04, 0.98, 0.34); + animation-play-state: paused; + } - &-slide-up-leave&-slide-up-leave-active&-placement-bottomLeft { - animation-name: rcSelectDropdownSlideUpOut; - animation-play-state: running; - } + &-slide-up-enter&-slide-up-enter-active&-placement-bottomLeft, + &-slide-up-appear&-slide-up-appear-active&-placement-bottomLeft { + animation-name: rcSelectDropdownSlideUpIn; + animation-play-state: running; + } - &-slide-up-enter&-slide-up-enter-active&-placement-topLeft, - &-slide-up-appear&-slide-up-appear-active&-placement-topLeft { - animation-name: rcSelectDropdownSlideDownIn; - animation-play-state: running; - } + &-slide-up-leave&-slide-up-leave-active&-placement-bottomLeft { + animation-name: rcSelectDropdownSlideUpOut; + animation-play-state: running; + } - &-slide-up-leave&-slide-up-leave-active&-placement-topLeft { - animation-name: rcSelectDropdownSlideDownOut; - animation-play-state: running; - } + &-slide-up-enter&-slide-up-enter-active&-placement-topLeft, + &-slide-up-appear&-slide-up-appear-active&-placement-topLeft { + animation-name: rcSelectDropdownSlideDownIn; + animation-play-state: running; + } - @keyframes rcSelectDropdownSlideUpIn { - 0% { - opacity: 0; - transform-origin: 0% 0%; - transform: scaleY(0); - } - 100% { - opacity: 1; - transform-origin: 0% 0%; - transform: scaleY(1); - } - } - @keyframes rcSelectDropdownSlideUpOut { - 0% { - opacity: 1; - transform-origin: 0% 0%; - transform: scaleY(1); - } - 100% { - opacity: 0; - transform-origin: 0% 0%; - transform: scaleY(0); - } - } + &-slide-up-leave&-slide-up-leave-active&-placement-topLeft { + animation-name: rcSelectDropdownSlideDownOut; + animation-play-state: running; + } +} - @keyframes rcSelectDropdownSlideDownIn { - 0% { - opacity: 0; - transform-origin: 0% 100%; - transform: scaleY(0); - } - 100% { - opacity: 1; - transform-origin: 0% 100%; - transform: scaleY(1); - } - } - @keyframes rcSelectDropdownSlideDownOut { - 0% { - opacity: 1; - transform-origin: 0% 100%; - transform: scaleY(1); - } - 100% { - opacity: 0; - transform-origin: 0% 100%; - transform: scaleY(0); - } - } +@keyframes rcSelectDropdownSlideUpIn { + 0% { + opacity: 0; + transform-origin: 0% 0%; + transform: scaleY(0); + } + 100% { + opacity: 1; + transform-origin: 0% 0%; + transform: scaleY(1); } +} +@keyframes rcSelectDropdownSlideUpOut { + 0% { + opacity: 1; + transform-origin: 0% 0%; + transform: scaleY(1); + } + 100% { + opacity: 0; + transform-origin: 0% 0%; + transform: scaleY(0); + } +} - &-open { - .@{selectPrefixCls}-arrow b { - border-color: transparent transparent #888 transparent; - border-width: 0 4px 5px 4px; - } +@keyframes rcSelectLoadingIcon { + 0% { + transform: rotate(0); + } + 100% { + transform: rotate(360deg); } } diff --git a/examples/combobox.js b/examples/combobox.tsx similarity index 58% rename from examples/combobox.js rename to examples/combobox.tsx index 10f2b5991..0c8b2a48f 100644 --- a/examples/combobox.js +++ b/examples/combobox.tsx @@ -1,15 +1,17 @@ -/* eslint no-console: 0 */ - +/* eslint-disable no-console */ import React from 'react'; -import Select, { Option, SelectPropTypes } from '../src'; +import Select, { Option } from '../src'; import '../assets/index.less'; class Combobox extends React.Component { state = { disabled: false, value: '', + options: [], }; + timeoutId: number; + onChange = (value, option) => { console.log('onChange', value, option); this.setState({ @@ -28,6 +30,24 @@ class Combobox extends React.Component { console.log('onSelect', v, option); }; + onSearch = (text: string) => { + console.log('onSearch:', text); + }; + + onAsyncChange = value => { + window.clearTimeout(this.timeoutId); + + this.setState({ + options: [], + }); + + this.timeoutId = window.setTimeout(() => { + this.setState({ + options: [{ value }, { value: `${value}-${value}` }], + }); + }, 1000); + }; + toggleDisabled = () => { const { disabled } = this.state; this.setState({ @@ -45,18 +65,19 @@ class Combobox extends React.Component { toggle disabled

-
+
+ +

Customize Input Element

+