Преглед на файлове

fix: autoComplete can't scroll when keyboard up and down, #1530 (#2501)

* fix: autoComplete can't scroll when keyboard up and down, #1530

* test: Unify the case issues in test cases
pointhalo преди 1 година
родител
ревизия
f79576d9ce

+ 1 - 0
.vscode/settings.json

@@ -42,6 +42,7 @@
     ],
     "cSpell.words": [
         "backtop",
+        "douyinfe",
         "Splited"
     ]
 }

+ 4 - 4
package.json

@@ -2,7 +2,7 @@
     "name": "semi",
     "version": "0.0.1",
     "description": "Semi monorepo main project",
-    "author": "",
+    "author": "DouyinFe",
     "workspaces": [
         "packages/**"
     ],
@@ -60,6 +60,7 @@
         "@visactor/vchart-semi-theme": "^1.10.4",
         "aos": "^2.3.4",
         "camelcase": "^6.2.0",
+        "chalk": "^5.3.0",
         "chroma-js": "^2.1.2",
         "classnames": "^2.3.1",
         "copy-text-to-clipboard": "^2.2.0",
@@ -138,6 +139,7 @@
         "@storybook/cli": "^7.0.7",
         "@storybook/react": "^7.0.7",
         "@svgr/webpack": "^5.5.0",
+        "@testing-library/react": "^12",
         "@types/classnames": "^2.3.0",
         "@types/enhanced-resolve": "^3.0.7",
         "@types/fs-extra": "^9.0.12",
@@ -153,7 +155,6 @@
         "@types/webpack": "^4.41.30",
         "@typescript-eslint/eslint-plugin": "^4.29.1",
         "@typescript-eslint/parser": "^4.29.1",
-        "awesome-typescript-loader": "^5.2.1",
         "axios": "^0.21.1",
         "babel-core": "^7.0.0-bridge.0",
         "babel-jest": "^24.9.0",
@@ -170,7 +171,6 @@
         "enzyme": "^3.11.0",
         "enzyme-adapter-react-16": "^1.15.6",
         "enzyme-to-json": "^3.6.2",
-        "@testing-library/react": "^12",
         "esbuild": "^0.14.47",
         "esbuild-loader": "^2.14.0",
         "eslint": "^7.32.0",
@@ -215,7 +215,7 @@
         "ts-loader": "^5.4.5",
         "typescript": "^4.8.3",
         "webpack": "^5.77.0",
-        "webpack-cli": "^3.3.12",
+        "webpack-cli": "^5.1.4",
         "webpack-dev-server": "^3.11.2",
         "webpackbar": "^5.0.0-3"
     },

+ 2 - 3
packages/semi-foundation/autoComplete/constants.ts

@@ -3,9 +3,8 @@ import { BASE_CLASS_PREFIX, VALIDATE_STATUS } from '../base/constants';
 
 const cssClasses = {
     PREFIX: `${BASE_CLASS_PREFIX}-autocomplete`,
-    PREFIX_OPTION: `${BASE_CLASS_PREFIX}-autoComplete-option`,
-    PREFIX_GROUP: `${BASE_CLASS_PREFIX}-autoComplete-group`,
-    
+    PREFIX_OPTION: `${BASE_CLASS_PREFIX}-autocomplete-option`,
+    PREFIX_GROUP: `${BASE_CLASS_PREFIX}-autocomplete-group`,
 };
 
 const strings = {

+ 2 - 0
packages/semi-foundation/autoComplete/foundation.ts

@@ -29,6 +29,7 @@ export interface AutoCompleteAdapter<P = Record<string, any>, S = Record<string,
     updateInputValue: (inputValue: string | number) => void;
     toggleListVisible: (isShow: boolean) => void;
     updateOptionList: (optionList: Array<StateOptionItem>) => void;
+    updateScrollTop: (index: number) => void;
     updateSelection: (selection: Map<any, any>) => void;
     notifySearch: (inputValue: string) => void;
     notifyChange: (value: string | number) => void;
@@ -387,6 +388,7 @@ class AutoCompleteFoundation<P = Record<string, any>, S = Record<string, any>> e
             index = nearestActiveOption;
         }
         this._adapter.updateFocusIndex(index);
+        this._adapter.updateScrollTop(index);
     }
 
     _handleArrowKeyDown(offset: number): void {

+ 1 - 1
packages/semi-foundation/autoComplete/option.scss

@@ -1,4 +1,4 @@
-$module: #{$prefix}-autoComplete;
+$module: #{$prefix}-autocomplete;
 $filterable: #{$module}-filterable;
 
 .#{$module}-option {

+ 6 - 6
packages/semi-ui/autoComplete/__test__/autoComplete.test.js

@@ -191,7 +191,7 @@ describe('AutoComplete', () => {
         };
         let ac = getAc(props);
         expect(ac.exists(`.${BASE_CLASS_PREFIX}-autocomplete-loading-wrapper`)).toEqual(true);
-        expect(ac.exists(`.${BASE_CLASS_PREFIX}-autoComplete-option`)).toEqual(false);
+        expect(ac.exists(`.${BASE_CLASS_PREFIX}-autocomplete-option`)).toEqual(false);
     });
 
     it('【onSelect】trigger onSelect when click candidate option', () => {
@@ -204,7 +204,7 @@ describe('AutoComplete', () => {
             ...commonProps,
         };
         let ac = getAc(props);
-        let options = ac.find(`.${BASE_CLASS_PREFIX}-autoComplete-option`);
+        let options = ac.find(`.${BASE_CLASS_PREFIX}-autocomplete-option`);
         let firstOption = options.at(0);
         const nativeEvent = { nativeEvent: { stopImmediatePropagation: noop } };
         firstOption.simulate('click', nativeEvent);
@@ -223,7 +223,7 @@ describe('AutoComplete', () => {
             ...commonProps,
         };
         let ac = getAc(props);
-        let options = ac.find(`.${BASE_CLASS_PREFIX}-autoComplete-option`);
+        let options = ac.find(`.${BASE_CLASS_PREFIX}-autocomplete-option`);
         let firstOption = options.at(0);
         const nativeEvent = { nativeEvent: { stopImmediatePropagation: noop } };
         firstOption.simulate('click', nativeEvent);
@@ -269,7 +269,7 @@ describe('AutoComplete', () => {
             renderSelectedItem: option => option.email,
         };
         let ac = getAc(props);
-        let options = ac.find(`.${BASE_CLASS_PREFIX}-autoComplete-option`);
+        let options = ac.find(`.${BASE_CLASS_PREFIX}-autocomplete-option`);
         let firstOption = options.at(0);
         const nativeEvent = { nativeEvent: { stopImmediatePropagation: noop } };
         firstOption.simulate('click', nativeEvent);
@@ -306,7 +306,7 @@ describe('AutoComplete', () => {
             value: '',
         };
         const ac = getAc(props);
-        ac.find(`.${BASE_CLASS_PREFIX}-autoComplete-option`)
+        ac.find(`.${BASE_CLASS_PREFIX}-autocomplete-option`)
             .at(0)
             .simulate('click');
         expect(fakeOnChange.calledWith('XK')).toEqual(true);
@@ -374,7 +374,7 @@ describe('AutoComplete', () => {
         let event = { target: { value: 'abc' } };
         component.find('input').simulate('change', event);
         expect(spyOnChange.calledWith('abc')).toEqual(true);
-        let options = component.find(`.${BASE_CLASS_PREFIX}-autoComplete-option`);
+        let options = component.find(`.${BASE_CLASS_PREFIX}-autocomplete-option`);
         let firstOption = options.at(0);
         const nativeEvent = { nativeEvent: { stopImmediatePropagation: noop } };
         firstOption.simulate('click', nativeEvent);

+ 45 - 1
packages/semi-ui/autoComplete/_story/autoComplete.stories.jsx

@@ -2,7 +2,7 @@ import React, { Component, useState } from 'react';
 
 import CustomTrigger from './CustomTrigger';
 import AutoComplete from '../index';
-import { Form } from '../../index';
+import { Form, Avatar } from '../../index';
 import { IconSearch } from '@douyinfe/semi-icons';
 
 export default {
@@ -371,3 +371,47 @@ export const ControlledOnSelectWithObjectDemo = () => {
         </Form>
     );
 };
+
+
+export const AutoScrollToKeyboardUpDown = () => {
+
+    const [data, setData] = useState([]);
+    const getData = (v) => {
+        let newData = Array.from({ length: 20 }, (v, i) => ({ label: `option-${i}`, value: i, 'data-cy': `option-${i}` }));
+        setData(newData);
+    };
+    
+    const renderOption = (item) => {
+        let optionStyle = {
+            display: 'flex',
+        };
+        return (
+            <>
+                <Avatar color={'cyan'} size="small">
+                    Semi
+                </Avatar>
+                <div style={{ marginLeft: 4 }}>
+                    <div style={{ fontSize: 14, marginLeft: 4 }}>{item.label}</div>
+                    <div style={{ marginLeft: 4 }}>{item.value}</div>
+                </div>
+            </>
+        );
+    }
+
+    return <>
+        <AutoComplete
+            data={data}
+            onSearch={(v) => getData(v)}
+            style={{ width: 320 }}
+        >
+        </AutoComplete>
+        <AutoComplete
+            placeholder='with render'
+            data={data}
+            renderItem={renderOption}
+            onSearch={(v) => getData(v)}
+            style={{ width: 320 }}
+        >
+        </AutoComplete>
+    </>
+}

+ 34 - 2
packages/semi-ui/autoComplete/index.tsx

@@ -6,7 +6,7 @@ import { isEqual, noop } from 'lodash';
 import { strings, cssClasses } from '@douyinfe/semi-foundation/autoComplete/constants';
 import AutoCompleteFoundation, { AutoCompleteAdapter, StateOptionItem, DataItem } from '@douyinfe/semi-foundation/autoComplete/foundation';
 import { numbers as popoverNumbers } from '@douyinfe/semi-foundation/popover/constants';
-import getDataAttr from '@douyinfe/semi-foundation/utils/getDataAttr';
+import { getUuidShort } from '@douyinfe/semi-foundation/utils/uuid';
 import BaseComponent, { ValidateStatus } from '../_base/baseComponent';
 import { Position } from '../tooltip';
 import Spin from '../spin';
@@ -199,6 +199,7 @@ class AutoComplete<T extends AutoCompleteItems> extends BaseComponent<AutoComple
 
     triggerRef: React.RefObject<HTMLDivElement> | null;
     optionsRef: React.RefObject<HTMLDivElement> | null;
+    optionListId: string;
 
     private clickOutsideHandler: (e: Event) => void | null;
 
@@ -222,6 +223,7 @@ class AutoComplete<T extends AutoCompleteItems> extends BaseComponent<AutoComple
         this.triggerRef = React.createRef();
         this.optionsRef = React.createRef();
         this.clickOutsideHandler = null;
+        this.optionListId = '';
 
         warning(
             'triggerRender' in this.props && typeof this.props.triggerRender === 'function',
@@ -247,6 +249,30 @@ class AutoComplete<T extends AutoCompleteItems> extends BaseComponent<AutoComple
             updateFocusIndex: (focusIndex: number): void => {
                 this.setState({ focusIndex });
             },
+            updateScrollTop: (index?: number) => {
+                let optionClassName;
+                /**
+                 * Unlike Select which needs to process renderOptionItem separately, when renderItem is enabled in autocomplete
+                 *  the content passed by the user is still wrapped in the selector of .semi-autocomplete-option
+                 * so the selector does not need to be judged separately.
+                 */
+                optionClassName = `.${prefixCls}-option-selected`;
+                if (index !== undefined) {
+                    optionClassName = `.${prefixCls}-option:nth-child(${index + 1})`;
+                }
+
+                let destNode = document.querySelector(`#${prefixCls}-${this.optionListId} ${optionClassName}`) as HTMLDivElement;
+                if (Array.isArray(destNode)) {
+                    destNode = destNode[0];
+                }
+                if (destNode) {
+                    const destParent = destNode.parentNode as HTMLDivElement;
+                    destParent.scrollTop = destNode.offsetTop -
+                        destParent.offsetTop -
+                        (destParent.clientHeight / 2) +
+                        (destNode.clientHeight / 2);
+                }
+            },
         };
         return {
             ...super.adapter,
@@ -329,6 +355,7 @@ class AutoComplete<T extends AutoCompleteItems> extends BaseComponent<AutoComple
 
     componentDidMount() {
         this.foundation.init();
+        this.optionListId = getUuidShort();
     }
 
     componentWillUnmount() {
@@ -497,7 +524,12 @@ class AutoComplete<T extends AutoCompleteItems> extends BaseComponent<AutoComple
             ...dropdownStyle,
         };
         return (
-            <div className={listCls} role="listbox" style={style}>
+            <div
+                className={listCls}
+                role="listbox"
+                style={style}
+                id={`${prefixCls}-${this.optionListId}`}
+            >
                 {!loading ? optionsNode : this.renderLoading()}
             </div>
         );

+ 82 - 63
yarn.lock

@@ -1532,7 +1532,7 @@
     debug "^3.1.0"
     lodash.once "^4.1.1"
 
-"@discoveryjs/json-ext@^0.5.3":
+"@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3":
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
   integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
@@ -6531,6 +6531,21 @@
     "@webassemblyjs/wast-parser" "1.9.0"
     "@xtuc/long" "4.2.2"
 
+"@webpack-cli/configtest@^2.1.1":
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646"
+  integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==
+
+"@webpack-cli/info@^2.0.2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd"
+  integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==
+
+"@webpack-cli/serve@^2.0.5":
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e"
+  integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
+
 "@xtuc/ieee754@^1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@@ -7460,20 +7475,6 @@ available-typed-arrays@^1.0.7:
   dependencies:
     possible-typed-array-names "^1.0.0"
 
-awesome-typescript-loader@^5.2.1:
-  version "5.2.1"
-  resolved "https://registry.yarnpkg.com/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz#a41daf7847515f4925cdbaa3075d61f289e913fc"
-  integrity sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==
-  dependencies:
-    chalk "^2.4.1"
-    enhanced-resolve "^4.0.0"
-    loader-utils "^1.1.0"
-    lodash "^4.17.5"
-    micromatch "^3.1.9"
-    mkdirp "^0.5.1"
-    source-map-support "^0.5.3"
-    webpack-log "^1.2.0"
-
 aws-sign2@~0.7.0:
   version "0.7.0"
   resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
@@ -8525,6 +8526,11 @@ chalk@^3.0.0:
     ansi-styles "^4.1.0"
     supports-color "^7.1.0"
 
+chalk@^5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
+  integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
+
 change-case@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/change-case/-/change-case-3.1.0.tgz#0e611b7edc9952df2e8513b27b42de72647dd17e"
@@ -9027,7 +9033,7 @@ color@^3.0.0:
     color-convert "^1.9.3"
     color-string "^1.6.0"
 
-colorette@^2.0.10, colorette@^2.0.16:
+colorette@^2.0.10, colorette@^2.0.14, colorette@^2.0.16:
   version "2.0.20"
   resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
   integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
@@ -9067,6 +9073,11 @@ commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3:
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
   integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
 
+commander@^10.0.1:
+  version "10.0.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
+  integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
+
 commander@^6.2.0, commander@^6.2.1:
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
@@ -10993,7 +11004,7 @@ engine.io@~4.1.0:
     engine.io-parser "~4.0.0"
     ws "~7.4.2"
 
-enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0:
+enhanced-resolve@^4.0.0, enhanced-resolve@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec"
   integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==
@@ -12834,6 +12845,11 @@ flat-cache@^3.0.4:
     keyv "^4.5.3"
     rimraf "^3.0.2"
 
+flat@^5.0.2:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
+  integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
+
 flatted@^2.0.0:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
@@ -15308,6 +15324,11 @@ interpret@^1.0.0, interpret@^1.4.0:
   resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
   integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
 
+interpret@^3.1.1:
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
+  integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
+
 intl-format-cache@^4.2.21:
   version "4.3.1"
   resolved "https://registry.yarnpkg.com/intl-format-cache/-/intl-format-cache-4.3.1.tgz#484d31a9872161e6c02139349b259a6229ade377"
@@ -17630,13 +17651,6 @@ [email protected], lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 
-log-symbols@^2.1.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
-  integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
-  dependencies:
-    chalk "^2.0.1"
-
 log-symbols@^4.0.0, log-symbols@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
@@ -17660,14 +17674,6 @@ loglevel@^1.6.8:
   resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7"
   integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==
 
-loglevelnext@^1.0.1:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.5.tgz#36fc4f5996d6640f539ff203ba819641680d75a2"
-  integrity sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==
-  dependencies:
-    es6-symbol "^3.1.1"
-    object.assign "^4.1.0"
-
 lolex@^2.7.5:
   version "2.7.5"
   resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.5.tgz#113001d56bfc7e02d56e36291cc5c413d1aa0733"
@@ -19156,7 +19162,7 @@ micromark@~2.11.0:
     debug "^4.0.0"
     parse-entities "^2.0.0"
 
-micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.9:
+micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
   version "3.1.10"
   resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
   integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
@@ -23002,6 +23008,13 @@ rechoir@^0.6.2:
   dependencies:
     resolve "^1.1.6"
 
+rechoir@^0.8.0:
+  version "0.8.0"
+  resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22"
+  integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==
+  dependencies:
+    resolve "^1.20.0"
+
 [email protected]:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.1.tgz#90ef231d0778c5ce093c9a48d74e5c5422d13a99"
@@ -23652,7 +23665,7 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
   integrity sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==
 
-resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.3.2, resolve@^1.4.0:
+resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.3.2, resolve@^1.4.0:
   version "1.22.8"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
   integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
@@ -24640,7 +24653,7 @@ source-map-resolve@^0.5.0, source-map-resolve@^0.5.2:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
-source-map-support@^0.5.16, source-map-support@^0.5.17, source-map-support@^0.5.19, source-map-support@^0.5.3, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
+source-map-support@^0.5.16, source-map-support@^0.5.17, source-map-support@^0.5.19, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20:
   version "0.5.21"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
   integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
@@ -27078,7 +27091,7 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
   integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
 
[email protected], uuid@^3.1.0, uuid@^3.3.2:
[email protected], uuid@^3.3.2:
   version "3.4.0"
   resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
   integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
@@ -27103,7 +27116,7 @@ uvu@^0.5.0:
     kleur "^4.0.3"
     sade "^1.7.3"
 
-v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1, v8-compile-cache@^2.2.0, v8-compile-cache@^2.3.0:
+v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0, v8-compile-cache@^2.3.0:
   version "2.4.0"
   resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128"
   integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==
@@ -27414,22 +27427,24 @@ webidl-conversions@^6.1.0:
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
   integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
 
-webpack-cli@^3.3.12:
-  version "3.3.12"
-  resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a"
-  integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==
-  dependencies:
-    chalk "^2.4.2"
-    cross-spawn "^6.0.5"
-    enhanced-resolve "^4.1.1"
-    findup-sync "^3.0.0"
-    global-modules "^2.0.0"
-    import-local "^2.0.0"
-    interpret "^1.4.0"
-    loader-utils "^1.4.0"
-    supports-color "^6.1.0"
-    v8-compile-cache "^2.1.1"
-    yargs "^13.3.2"
+webpack-cli@^5.1.4:
+  version "5.1.4"
+  resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b"
+  integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==
+  dependencies:
+    "@discoveryjs/json-ext" "^0.5.0"
+    "@webpack-cli/configtest" "^2.1.1"
+    "@webpack-cli/info" "^2.0.2"
+    "@webpack-cli/serve" "^2.0.5"
+    colorette "^2.0.14"
+    commander "^10.0.1"
+    cross-spawn "^7.0.3"
+    envinfo "^7.7.3"
+    fastest-levenshtein "^1.0.12"
+    import-local "^3.0.2"
+    interpret "^3.1.1"
+    rechoir "^0.8.0"
+    webpack-merge "^5.7.3"
 
 webpack-dev-middleware@^3.7.2:
   version "3.7.3"
@@ -27501,16 +27516,6 @@ webpack-hot-middleware@^2.25.0, webpack-hot-middleware@^2.25.1:
     html-entities "^2.1.0"
     strip-ansi "^6.0.0"
 
-webpack-log@^1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d"
-  integrity sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==
-  dependencies:
-    chalk "^2.1.0"
-    log-symbols "^2.1.0"
-    loglevelnext "^1.0.1"
-    uuid "^3.1.0"
-
 webpack-log@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
@@ -27526,6 +27531,15 @@ webpack-merge@^4.2.2:
   dependencies:
     lodash "^4.17.15"
 
+webpack-merge@^5.7.3:
+  version "5.10.0"
+  resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177"
+  integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==
+  dependencies:
+    clone-deep "^4.0.1"
+    flat "^5.0.2"
+    wildcard "^2.0.0"
+
 webpack-sources@^0.2.0:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb"
@@ -27781,6 +27795,11 @@ widest-line@^3.1.0:
   dependencies:
     string-width "^4.0.0"
 
+wildcard@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
+  integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
+
 word-wrap@^1.2.5, word-wrap@~1.2.3:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"