@onewelcome/react-lib-components 6.5.0 → 6.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Form/Select/MultiSelect/MultiOption.cjs.js +1 -1
- package/dist/cjs/Form/Select/MultiSelect/MultiOption.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/MultiSelect/MultiSelect.cjs.js +1 -1
- package/dist/cjs/Form/Select/MultiSelect/MultiSelect.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/MultiSelect/MultiSelect.module.cjs.js +1 -1
- package/dist/cjs/Form/Select/MultiSelect/SelectButton.cjs.js +1 -1
- package/dist/cjs/Form/Select/MultiSelect/SelectButton.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/MultiSelect/SelectButton.module.cjs.js +1 -1
- package/dist/cjs/Form/Select/MultiSelect/SelectedOptions.cjs.js +1 -1
- package/dist/cjs/Form/Select/MultiSelect/SelectedOptions.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/MultiSelect/useArrowNavigation.cjs.js +2 -0
- package/dist/cjs/Form/Select/MultiSelect/useArrowNavigation.cjs.js.map +1 -0
- package/dist/cjs/Form/Select/MultiSelect/useSearch.cjs.js +2 -0
- package/dist/cjs/Form/Select/MultiSelect/useSearch.cjs.js.map +1 -0
- package/dist/cjs/Form/Select/SingleSelect/Option.cjs.js +1 -1
- package/dist/cjs/Form/Select/SingleSelect/Option.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/SingleSelect/Select.cjs.js +1 -1
- package/dist/cjs/Form/Select/SingleSelect/Select.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/SingleSelect/Select.module.cjs.js +1 -1
- package/dist/cjs/Form/Select/SingleSelect/useArrowNavigation.cjs.js +2 -0
- package/dist/cjs/Form/Select/SingleSelect/useArrowNavigation.cjs.js.map +1 -0
- package/dist/cjs/Form/Select/SingleSelect/useSearch.cjs.js +2 -0
- package/dist/cjs/Form/Select/SingleSelect/useSearch.cjs.js.map +1 -0
- package/dist/cjs/Form/Select/useAddNewBtn.cjs.js +1 -1
- package/dist/cjs/Form/Select/useAddNewBtn.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/useAddNewBtn.module.cjs.js +1 -1
- package/dist/cjs/Form/Select/useSelectPositionList.cjs.js +2 -0
- package/dist/cjs/Form/Select/useSelectPositionList.cjs.js.map +1 -0
- package/dist/cjs/src/components/Form/Select/MultiSelect/MultiSelect.test.d.ts +63 -1
- package/dist/cjs/src/components/Form/Select/MultiSelect/MultiSelectKeyboardNavigation.test.d.ts +1 -0
- package/dist/cjs/src/components/Form/Select/MultiSelect/SelectedOptions.d.ts +2 -1
- package/dist/cjs/src/components/Form/Select/MultiSelect/useArrowNavigation.d.ts +16 -0
- package/dist/cjs/src/components/Form/Select/MultiSelect/useSearch.d.ts +34 -0
- package/dist/cjs/src/components/Form/Select/Select.interfaces.d.ts +1 -0
- package/dist/cjs/src/components/Form/Select/SingleSelect/Option.d.ts +1 -0
- package/dist/cjs/src/components/Form/Select/SingleSelect/useArrowNavigation.d.ts +5 -0
- package/dist/cjs/src/components/Form/Select/{useSearch.d.ts → SingleSelect/useSearch.d.ts} +2 -1
- package/dist/cjs/src/components/Form/Select/useAddNewBtn.d.ts +10 -3
- package/dist/cjs/src/components/Form/Select/useSelectPositionList.d.ts +12 -0
- package/dist/cjs/src/util/helper.cjs.js +1 -1
- package/dist/cjs/src/util/helper.cjs.js.map +1 -1
- package/dist/cjs/src/util/helper.d.ts +1 -0
- package/dist/esm/Form/Select/MultiSelect/MultiOption.esm.js +1 -1
- package/dist/esm/Form/Select/MultiSelect/MultiOption.esm.js.map +1 -1
- package/dist/esm/Form/Select/MultiSelect/MultiSelect.esm.js +1 -1
- package/dist/esm/Form/Select/MultiSelect/MultiSelect.esm.js.map +1 -1
- package/dist/esm/Form/Select/MultiSelect/MultiSelect.module.esm.js +1 -1
- package/dist/esm/Form/Select/MultiSelect/SelectButton.esm.js +1 -1
- package/dist/esm/Form/Select/MultiSelect/SelectButton.esm.js.map +1 -1
- package/dist/esm/Form/Select/MultiSelect/SelectButton.module.esm.js +1 -1
- package/dist/esm/Form/Select/MultiSelect/SelectedOptions.esm.js +1 -1
- package/dist/esm/Form/Select/MultiSelect/SelectedOptions.esm.js.map +1 -1
- package/dist/esm/Form/Select/MultiSelect/useArrowNavigation.esm.js +2 -0
- package/dist/esm/Form/Select/MultiSelect/useArrowNavigation.esm.js.map +1 -0
- package/dist/esm/Form/Select/MultiSelect/useSearch.esm.js +2 -0
- package/dist/esm/Form/Select/MultiSelect/useSearch.esm.js.map +1 -0
- package/dist/esm/Form/Select/SingleSelect/Option.esm.js +1 -1
- package/dist/esm/Form/Select/SingleSelect/Option.esm.js.map +1 -1
- package/dist/esm/Form/Select/SingleSelect/Select.esm.js +1 -1
- package/dist/esm/Form/Select/SingleSelect/Select.esm.js.map +1 -1
- package/dist/esm/Form/Select/SingleSelect/Select.module.esm.js +1 -1
- package/dist/esm/Form/Select/SingleSelect/useArrowNavigation.esm.js +2 -0
- package/dist/esm/Form/Select/SingleSelect/useArrowNavigation.esm.js.map +1 -0
- package/dist/esm/Form/Select/SingleSelect/useSearch.esm.js +2 -0
- package/dist/esm/Form/Select/SingleSelect/useSearch.esm.js.map +1 -0
- package/dist/esm/Form/Select/useAddNewBtn.esm.js +1 -1
- package/dist/esm/Form/Select/useAddNewBtn.esm.js.map +1 -1
- package/dist/esm/Form/Select/useAddNewBtn.module.esm.js +1 -1
- package/dist/esm/Form/Select/useSelectPositionList.esm.js +2 -0
- package/dist/esm/Form/Select/useSelectPositionList.esm.js.map +1 -0
- package/dist/esm/src/components/Form/Select/MultiSelect/MultiSelect.test.d.ts +63 -1
- package/dist/esm/src/components/Form/Select/MultiSelect/MultiSelectKeyboardNavigation.test.d.ts +1 -0
- package/dist/esm/src/components/Form/Select/MultiSelect/SelectedOptions.d.ts +2 -1
- package/dist/esm/src/components/Form/Select/MultiSelect/useArrowNavigation.d.ts +16 -0
- package/dist/esm/src/components/Form/Select/MultiSelect/useSearch.d.ts +34 -0
- package/dist/esm/src/components/Form/Select/Select.interfaces.d.ts +1 -0
- package/dist/esm/src/components/Form/Select/SingleSelect/Option.d.ts +1 -0
- package/dist/esm/src/components/Form/Select/SingleSelect/useArrowNavigation.d.ts +5 -0
- package/dist/esm/src/components/Form/Select/{useSearch.d.ts → SingleSelect/useSearch.d.ts} +2 -1
- package/dist/esm/src/components/Form/Select/useAddNewBtn.d.ts +10 -3
- package/dist/esm/src/components/Form/Select/useSelectPositionList.d.ts +12 -0
- package/dist/esm/src/util/helper.d.ts +1 -0
- package/dist/esm/src/util/helper.esm.js +1 -1
- package/dist/esm/src/util/helper.esm.js.map +1 -1
- package/package.json +6 -6
- package/src/components/Form/Select/MultiSelect/MultiOption.tsx +36 -3
- package/src/components/Form/Select/MultiSelect/MultiSelect.module.scss +29 -19
- package/src/components/Form/Select/MultiSelect/MultiSelect.tsx +85 -62
- package/src/components/Form/Select/MultiSelect/SelectButton.module.scss +1 -1
- package/src/components/Form/Select/MultiSelect/SelectButton.tsx +1 -1
- package/src/components/Form/Select/MultiSelect/SelectedOptions.tsx +5 -4
- package/src/components/Form/Select/MultiSelect/useArrowNavigation.ts +128 -0
- package/src/components/Form/Select/MultiSelect/useSearch.tsx +126 -0
- package/src/components/Form/Select/Select.interfaces.ts +1 -0
- package/src/components/Form/Select/SingleSelect/Option.tsx +15 -4
- package/src/components/Form/Select/SingleSelect/Select.module.scss +13 -2
- package/src/components/Form/Select/SingleSelect/Select.tsx +7 -3
- package/src/components/Form/Select/{SelectService.ts → SingleSelect/useArrowNavigation.ts} +1 -101
- package/src/components/Form/Select/{useSearch.tsx → SingleSelect/useSearch.tsx} +3 -2
- package/src/components/Form/Select/useAddNewBtn.module.scss +18 -4
- package/src/components/Form/Select/useAddNewBtn.tsx +42 -8
- package/src/components/Form/Select/useSelectPositionList.ts +113 -0
- package/src/util/helper.tsx +2 -0
- package/dist/cjs/Form/Select/SelectService.cjs.js +0 -2
- package/dist/cjs/Form/Select/SelectService.cjs.js.map +0 -1
- package/dist/cjs/Form/Select/useSearch.cjs.js +0 -2
- package/dist/cjs/Form/Select/useSearch.cjs.js.map +0 -1
- package/dist/cjs/src/components/Form/Select/SelectService.d.ts +0 -17
- package/dist/esm/Form/Select/SelectService.esm.js +0 -2
- package/dist/esm/Form/Select/SelectService.esm.js.map +0 -1
- package/dist/esm/Form/Select/useSearch.esm.js +0 -2
- package/dist/esm/Form/Select/useSearch.esm.js.map +0 -1
- package/dist/esm/src/components/Form/Select/SelectService.d.ts +0 -17
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const t=(t=15,e)=>{let r=["1","2","3","4","5","6","7","8","9","0","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];let o="";for(let n=0;n<t&&o.length<t;n++){let t=typeof e==="string"&&(e===null||e===void 0?void 0:e[n])!==void 0&&!/\s/.test(e[n])?e[n]:"";o=o+t+r[Math.floor(Math.random()*r.length)]}return o.slice(0,t)};const e=(t,e,r=true)=>{if(r)return Object.keys(t).reduce(((r,o)=>{if(e.test(o))r[o]=t[o];return r}),{});else return Object.entries(t).filter((([t])=>!e.test(t))).reduce(((t,e)=>({...t,[e[0]]:e[1]})),{})};const r=(t,e)=>{let r;return function o(...n){const l=()=>{clearTimeout(r);t(...n)};clearTimeout(r);r=setTimeout(l,e)}};const o=(t,e)=>{let r=0;return function(){let o=Date.now();if(o-r>=e){t();r=o}}};const n=t=>t*parseFloat(getComputedStyle(document.documentElement).fontSize);const l=(t,e)=>{if(!e)return t;let r={...t};for(let o in e)if(Object.prototype.hasOwnProperty.call(e,o))if(typeof e[o]==="object"&&e[o]!==null&&Object.prototype.hasOwnProperty.call(t,o)&&!Array.isArray(e[o]))r[o]=l(t[o],e[o]);else r[o]=e[o];return r};export{r as debounce,l as deepMerge,e as filterProps,t as generateID,n as remToPx,o as throttle};
|
|
1
|
+
const t=(t=15,e)=>{let r=["1","2","3","4","5","6","7","8","9","0","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];let o="";for(let n=0;n<t&&o.length<t;n++){let t=typeof e==="string"&&(e===null||e===void 0?void 0:e[n])!==void 0&&!/\s/.test(e[n])?e[n]:"";o=o+t+r[Math.floor(Math.random()*r.length)]}return o.slice(0,t)};const e=(t,e,r=true)=>{if(r)return Object.keys(t).reduce(((r,o)=>{if(e.test(o))r[o]=t[o];return r}),{});else return Object.entries(t).filter((([t])=>!e.test(t))).reduce(((t,e)=>({...t,[e[0]]:e[1]})),{})};const r=(t,e)=>{let r;return function o(...n){const l=()=>{clearTimeout(r);t(...n)};clearTimeout(r);r=setTimeout(l,e)}};const o=(t,e)=>{let r=0;return function(){let o=Date.now();if(o-r>=e){t();r=o}}};const n=t=>t*parseFloat(getComputedStyle(document.documentElement).fontSize);const l=(t,e)=>{if(!e)return t;let r={...t};for(let o in e)if(Object.prototype.hasOwnProperty.call(e,o))if(typeof e[o]==="object"&&e[o]!==null&&Object.prototype.hasOwnProperty.call(t,o)&&!Array.isArray(e[o]))r[o]=l(t[o],e[o]);else r[o]=e[o];return r};const c=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");export{r as debounce,l as deepMerge,c as escapeRegExp,e as filterProps,t as generateID,n as remToPx,o as throttle};
|
|
2
2
|
//# sourceMappingURL=helper.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.esm.js","sources":["../../../../../../src/util/helper.tsx"],"sourcesContent":["/*\n * Copyright 2022 OneWelcome B.V.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype KeyValuePair = { [key: string]: unknown };\n\nexport const generateID = (length = 15, stringToWeaveIn?: string) => {\n /** We will make sure to mesh the generate id and name property together to basically create a unique ID */\n let hashCharacters = [\n \"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"0\",\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\n \"G\",\n \"H\",\n \"I\",\n \"J\",\n \"K\",\n \"L\",\n \"M\",\n \"N\",\n \"O\",\n \"P\",\n \"Q\",\n \"R\",\n \"S\",\n \"T\",\n \"U\",\n \"V\",\n \"W\",\n \"X\",\n \"Y\",\n \"Z\",\n \"a\",\n \"b\",\n \"c\",\n \"d\",\n \"e\",\n \"f\",\n \"g\",\n \"h\",\n \"i\",\n \"j\",\n \"k\",\n \"l\",\n \"m\",\n \"n\",\n \"o\",\n \"p\",\n \"q\",\n \"r\",\n \"s\",\n \"t\",\n \"u\",\n \"v\",\n \"w\",\n \"x\",\n \"y\",\n \"z\"\n ];\n\n let id = \"\";\n\n /** Generate an id of x characters in length */\n for (let i = 0; i < length && id.length < length; i++) {\n let stringCharacter =\n typeof stringToWeaveIn === \"string\" &&\n stringToWeaveIn?.[i] !== undefined &&\n !/\\s/.test(stringToWeaveIn[i])\n ? stringToWeaveIn[i]\n : \"\";\n id = id + stringCharacter + hashCharacters[Math.floor(Math.random() * hashCharacters.length)];\n }\n\n return id.slice(0, length);\n};\n\nexport const filterProps = (props: any, regexPattern: RegExp, returnFiltered: boolean = true) => {\n if (returnFiltered) {\n return Object.keys(props).reduce((acc: KeyValuePair, key) => {\n if (regexPattern.test(key)) {\n acc[key] = props[key];\n }\n\n return acc;\n }, {});\n } else {\n return Object.entries(props)\n .filter(([key]) => !regexPattern.test(key))\n .reduce(\n (prevObj, currKeyValPair) => ({ ...prevObj, [currKeyValPair[0]]: currKeyValPair[1] }),\n {}\n );\n }\n};\n\nexport const debounce = (fn: (...args: unknown[]) => unknown, delay: number) => {\n let timeout: undefined | ReturnType<typeof setTimeout>;\n\n return function executedFunction(...args: unknown[]) {\n const later = () => {\n clearTimeout(timeout);\n fn(...args);\n };\n\n clearTimeout(timeout);\n\n timeout = setTimeout(later, delay);\n };\n};\n\nexport const throttle = (fn: (...args: unknown[]) => unknown, delay: number) => {\n let lastTime = 0;\n\n return function () {\n let now = Date.now();\n\n if (now - lastTime >= delay) {\n fn();\n lastTime = now;\n }\n };\n};\n\nexport const isEqual = (x: any, y: any): boolean => {\n const typesCoincide = x && y && typeof x === \"object\" && typeof y === \"object\";\n return typesCoincide\n ? Object.keys(x).length === Object.keys(y).length &&\n Object.keys(x).every(key => isEqual(x[key], y[key]))\n : x === y;\n};\n\nexport const areArraysDifferent = (\n arr1: Record<string, any>[],\n arr2: Record<string, any>[],\n key: string\n) => {\n if (arr1.length !== arr2.length) {\n return true;\n } else {\n const firstFilteredArray = arr1.filter(arr1Item =>\n arr2.some((arr2Item: { [x: string]: any }) => !isEqual(arr1Item[key], arr2Item[key]))\n );\n const secondFilteredArray = arr2.filter(arr2Item =>\n arr1.some((arr1Item: { [x: string]: any }) => !isEqual(arr1Item[key], arr2Item[key]))\n );\n\n return !!firstFilteredArray.length || !!secondFilteredArray.length;\n }\n};\n\nexport const getValueByPath = (obj: { [key: string]: any }, path: string): any => {\n return path.split(\".\").reduce((res, prop) => {\n return res[prop];\n }, obj);\n};\n\n/** Source: https://stackoverflow.com/a/42769683/5084110 */\nexport const remToPx = (rem: number): number => {\n return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);\n};\n\nexport const isJsonString = (str: any) => {\n try {\n JSON.parse(str);\n } catch (e) {\n return false;\n }\n return true;\n};\n\ntype ObjectType = { [key: string]: any };\n\nexport const deepMerge = <T extends {}>(obj1: ObjectType, obj2: ObjectType | false): T => {\n if (!obj2) return obj1 as T;\n\n let result: ObjectType = { ...obj1 };\n\n for (let key in obj2) {\n if (Object.prototype.hasOwnProperty.call(obj2, key)) {\n if (\n typeof obj2[key] === \"object\" &&\n obj2[key] !== null &&\n Object.prototype.hasOwnProperty.call(obj1, key) &&\n !Array.isArray(obj2[key])\n ) {\n result[key] = deepMerge(obj1[key], obj2[key]);\n } else {\n result[key] = obj2[key];\n }\n }\n }\n\n return result as T;\n};\n"],"names":["generateID","length","stringToWeaveIn","hashCharacters","id","i","stringCharacter","undefined","test","Math","floor","random","slice","filterProps","props","regexPattern","returnFiltered","Object","keys","reduce","acc","key","entries","filter","prevObj","currKeyValPair","debounce","fn","delay","timeout","executedFunction","args","later","clearTimeout","setTimeout","throttle","lastTime","now","Date","remToPx","rem","parseFloat","getComputedStyle","document","documentElement","fontSize","deepMerge","obj1","obj2","result","prototype","hasOwnProperty","call","Array","isArray"],"mappings":"AAkBa,MAAAA,EAAa,CAACC,EAAS,GAAIC,KAEtC,IAAIC,EAAiB,CACnB,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,KAGF,IAAIC,EAAK,GAGT,IAAK,IAAIC,EAAI,EAAGA,EAAIJ,GAAUG,EAAGH,OAASA,EAAQI,IAAK,CACrD,IAAIC,SACKJ,IAAoB,WAC3BA,UAAAA,SAAe,OAAA,EAAfA,EAAkBG,WAAOE,IACxB,KAAKC,KAAKN,EAAgBG,IACvBH,EAAgBG,GAChB,GACND,EAAKA,EAAKE,EAAkBH,EAAeM,KAAKC,MAAMD,KAAKE,SAAWR,EAAeF,QACtF,CAED,OAAOG,EAAGQ,MAAM,EAAGX,EAAO,EAGrB,MAAMY,EAAc,CAACC,EAAYC,EAAsBC,EAA0B,QACtF,GAAIA,EACF,OAAOC,OAAOC,KAAKJ,GAAOK,QAAO,CAACC,EAAmBC,KACnD,GAAIN,EAAaP,KAAKa,GACpBD,EAAIC,GAAOP,EAAMO,GAGnB,OAAOD,CAAG,GACT,CAAE,QAEL,OAAOH,OAAOK,QAAQR,GACnBS,QAAO,EAAEF,MAAUN,EAAaP,KAAKa,KACrCF,QACC,CAACK,EAASC,KAAc,IAAWD,EAAS,CAACC,EAAe,IAAKA,EAAe,MAChF,CAAE,EAEP,QAGUC,EAAW,CAACC,EAAqCC,KAC5D,IAAIC,EAEJ,OAAO,SAASC,KAAoBC,GAClC,MAAMC,EAAQ,KACZC,aAAaJ,GACbF,KAAMI,EAAK,EAGbE,aAAaJ,GAEbA,EAAUK,WAAWF,EAAOJ,EAC9B,CAAC,QAGUO,EAAW,CAACR,EAAqCC,KAC5D,IAAIQ,EAAW,EAEf,OAAO,WACL,IAAIC,EAAMC,KAAKD,MAEf,GAAIA,EAAMD,GAAYR,EAAO,CAC3BD,IACAS,EAAWC,CACZ,CACH,CAAC,EAqCU,MAAAE,EAAWC,GACfA,EAAMC,WAAWC,iBAAiBC,SAASC,iBAAiBC,gBAcxDC,EAAY,CAAeC,EAAkBC,KACxD,IAAKA,EAAM,OAAOD,EAElB,IAAIE,EAAqB,IAAKF,GAE9B,IAAK,IAAI1B,KAAO2B,EACd,GAAI/B,OAAOiC,UAAUC,eAAeC,KAAKJ,EAAM3B,GAC7C,UACS2B,EAAK3B,KAAS,UACrB2B,EAAK3B,KAAS,MACdJ,OAAOiC,UAAUC,eAAeC,KAAKL,EAAM1B,KAC1CgC,MAAMC,QAAQN,EAAK3B,IAEpB4B,EAAO5B,GAAOyB,EAAUC,EAAK1B,GAAM2B,EAAK3B,SAExC4B,EAAO5B,GAAO2B,EAAK3B,GAKzB,OAAO4B,CAAW"}
|
|
1
|
+
{"version":3,"file":"helper.esm.js","sources":["../../../../../../src/util/helper.tsx"],"sourcesContent":["/*\n * Copyright 2022 OneWelcome B.V.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ntype KeyValuePair = { [key: string]: unknown };\n\nexport const generateID = (length = 15, stringToWeaveIn?: string) => {\n /** We will make sure to mesh the generate id and name property together to basically create a unique ID */\n let hashCharacters = [\n \"1\",\n \"2\",\n \"3\",\n \"4\",\n \"5\",\n \"6\",\n \"7\",\n \"8\",\n \"9\",\n \"0\",\n \"A\",\n \"B\",\n \"C\",\n \"D\",\n \"E\",\n \"F\",\n \"G\",\n \"H\",\n \"I\",\n \"J\",\n \"K\",\n \"L\",\n \"M\",\n \"N\",\n \"O\",\n \"P\",\n \"Q\",\n \"R\",\n \"S\",\n \"T\",\n \"U\",\n \"V\",\n \"W\",\n \"X\",\n \"Y\",\n \"Z\",\n \"a\",\n \"b\",\n \"c\",\n \"d\",\n \"e\",\n \"f\",\n \"g\",\n \"h\",\n \"i\",\n \"j\",\n \"k\",\n \"l\",\n \"m\",\n \"n\",\n \"o\",\n \"p\",\n \"q\",\n \"r\",\n \"s\",\n \"t\",\n \"u\",\n \"v\",\n \"w\",\n \"x\",\n \"y\",\n \"z\"\n ];\n\n let id = \"\";\n\n /** Generate an id of x characters in length */\n for (let i = 0; i < length && id.length < length; i++) {\n let stringCharacter =\n typeof stringToWeaveIn === \"string\" &&\n stringToWeaveIn?.[i] !== undefined &&\n !/\\s/.test(stringToWeaveIn[i])\n ? stringToWeaveIn[i]\n : \"\";\n id = id + stringCharacter + hashCharacters[Math.floor(Math.random() * hashCharacters.length)];\n }\n\n return id.slice(0, length);\n};\n\nexport const filterProps = (props: any, regexPattern: RegExp, returnFiltered: boolean = true) => {\n if (returnFiltered) {\n return Object.keys(props).reduce((acc: KeyValuePair, key) => {\n if (regexPattern.test(key)) {\n acc[key] = props[key];\n }\n\n return acc;\n }, {});\n } else {\n return Object.entries(props)\n .filter(([key]) => !regexPattern.test(key))\n .reduce(\n (prevObj, currKeyValPair) => ({ ...prevObj, [currKeyValPair[0]]: currKeyValPair[1] }),\n {}\n );\n }\n};\n\nexport const debounce = (fn: (...args: unknown[]) => unknown, delay: number) => {\n let timeout: undefined | ReturnType<typeof setTimeout>;\n\n return function executedFunction(...args: unknown[]) {\n const later = () => {\n clearTimeout(timeout);\n fn(...args);\n };\n\n clearTimeout(timeout);\n\n timeout = setTimeout(later, delay);\n };\n};\n\nexport const throttle = (fn: (...args: unknown[]) => unknown, delay: number) => {\n let lastTime = 0;\n\n return function () {\n let now = Date.now();\n\n if (now - lastTime >= delay) {\n fn();\n lastTime = now;\n }\n };\n};\n\nexport const isEqual = (x: any, y: any): boolean => {\n const typesCoincide = x && y && typeof x === \"object\" && typeof y === \"object\";\n return typesCoincide\n ? Object.keys(x).length === Object.keys(y).length &&\n Object.keys(x).every(key => isEqual(x[key], y[key]))\n : x === y;\n};\n\nexport const areArraysDifferent = (\n arr1: Record<string, any>[],\n arr2: Record<string, any>[],\n key: string\n) => {\n if (arr1.length !== arr2.length) {\n return true;\n } else {\n const firstFilteredArray = arr1.filter(arr1Item =>\n arr2.some((arr2Item: { [x: string]: any }) => !isEqual(arr1Item[key], arr2Item[key]))\n );\n const secondFilteredArray = arr2.filter(arr2Item =>\n arr1.some((arr1Item: { [x: string]: any }) => !isEqual(arr1Item[key], arr2Item[key]))\n );\n\n return !!firstFilteredArray.length || !!secondFilteredArray.length;\n }\n};\n\nexport const getValueByPath = (obj: { [key: string]: any }, path: string): any => {\n return path.split(\".\").reduce((res, prop) => {\n return res[prop];\n }, obj);\n};\n\n/** Source: https://stackoverflow.com/a/42769683/5084110 */\nexport const remToPx = (rem: number): number => {\n return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);\n};\n\nexport const isJsonString = (str: any) => {\n try {\n JSON.parse(str);\n } catch (e) {\n return false;\n }\n return true;\n};\n\ntype ObjectType = { [key: string]: any };\n\nexport const deepMerge = <T extends {}>(obj1: ObjectType, obj2: ObjectType | false): T => {\n if (!obj2) return obj1 as T;\n\n let result: ObjectType = { ...obj1 };\n\n for (let key in obj2) {\n if (Object.prototype.hasOwnProperty.call(obj2, key)) {\n if (\n typeof obj2[key] === \"object\" &&\n obj2[key] !== null &&\n Object.prototype.hasOwnProperty.call(obj1, key) &&\n !Array.isArray(obj2[key])\n ) {\n result[key] = deepMerge(obj1[key], obj2[key]);\n } else {\n result[key] = obj2[key];\n }\n }\n }\n\n return result as T;\n};\n\nexport const escapeRegExp = (str: string) => str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n"],"names":["generateID","length","stringToWeaveIn","hashCharacters","id","i","stringCharacter","undefined","test","Math","floor","random","slice","filterProps","props","regexPattern","returnFiltered","Object","keys","reduce","acc","key","entries","filter","prevObj","currKeyValPair","debounce","fn","delay","timeout","executedFunction","args","later","clearTimeout","setTimeout","throttle","lastTime","now","Date","remToPx","rem","parseFloat","getComputedStyle","document","documentElement","fontSize","deepMerge","obj1","obj2","result","prototype","hasOwnProperty","call","Array","isArray","escapeRegExp","str","replace"],"mappings":"AAkBa,MAAAA,EAAa,CAACC,EAAS,GAAIC,KAEtC,IAAIC,EAAiB,CACnB,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,IACA,KAGF,IAAIC,EAAK,GAGT,IAAK,IAAIC,EAAI,EAAGA,EAAIJ,GAAUG,EAAGH,OAASA,EAAQI,IAAK,CACrD,IAAIC,SACKJ,IAAoB,WAC3BA,UAAAA,SAAe,OAAA,EAAfA,EAAkBG,WAAOE,IACxB,KAAKC,KAAKN,EAAgBG,IACvBH,EAAgBG,GAChB,GACND,EAAKA,EAAKE,EAAkBH,EAAeM,KAAKC,MAAMD,KAAKE,SAAWR,EAAeF,QACtF,CAED,OAAOG,EAAGQ,MAAM,EAAGX,EAAO,EAGrB,MAAMY,EAAc,CAACC,EAAYC,EAAsBC,EAA0B,QACtF,GAAIA,EACF,OAAOC,OAAOC,KAAKJ,GAAOK,QAAO,CAACC,EAAmBC,KACnD,GAAIN,EAAaP,KAAKa,GACpBD,EAAIC,GAAOP,EAAMO,GAGnB,OAAOD,CAAG,GACT,CAAE,QAEL,OAAOH,OAAOK,QAAQR,GACnBS,QAAO,EAAEF,MAAUN,EAAaP,KAAKa,KACrCF,QACC,CAACK,EAASC,KAAc,IAAWD,EAAS,CAACC,EAAe,IAAKA,EAAe,MAChF,CAAE,EAEP,QAGUC,EAAW,CAACC,EAAqCC,KAC5D,IAAIC,EAEJ,OAAO,SAASC,KAAoBC,GAClC,MAAMC,EAAQ,KACZC,aAAaJ,GACbF,KAAMI,EAAK,EAGbE,aAAaJ,GAEbA,EAAUK,WAAWF,EAAOJ,EAC9B,CAAC,QAGUO,EAAW,CAACR,EAAqCC,KAC5D,IAAIQ,EAAW,EAEf,OAAO,WACL,IAAIC,EAAMC,KAAKD,MAEf,GAAIA,EAAMD,GAAYR,EAAO,CAC3BD,IACAS,EAAWC,CACZ,CACH,CAAC,EAqCU,MAAAE,EAAWC,GACfA,EAAMC,WAAWC,iBAAiBC,SAASC,iBAAiBC,gBAcxDC,EAAY,CAAeC,EAAkBC,KACxD,IAAKA,EAAM,OAAOD,EAElB,IAAIE,EAAqB,IAAKF,GAE9B,IAAK,IAAI1B,KAAO2B,EACd,GAAI/B,OAAOiC,UAAUC,eAAeC,KAAKJ,EAAM3B,GAC7C,UACS2B,EAAK3B,KAAS,UACrB2B,EAAK3B,KAAS,MACdJ,OAAOiC,UAAUC,eAAeC,KAAKL,EAAM1B,KAC1CgC,MAAMC,QAAQN,EAAK3B,IAEpB4B,EAAO5B,GAAOyB,EAAUC,EAAK1B,GAAM2B,EAAK3B,SAExC4B,EAAO5B,GAAO2B,EAAK3B,GAKzB,OAAO4B,CAAW,EAGP,MAAAM,EAAgBC,GAAgBA,EAAIC,QAAQ,sBAAuB"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"homepage": "http://onewelcome.github.io/react-lib-components",
|
|
3
3
|
"name": "@onewelcome/react-lib-components",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.6.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "OneWelcome B.V.",
|
|
7
7
|
"main": "dist/cjs/src/index.cjs.js",
|
|
@@ -82,14 +82,14 @@
|
|
|
82
82
|
"@testing-library/user-event": "^14.5.2",
|
|
83
83
|
"@types/jest": "^29.5.12",
|
|
84
84
|
"@types/mdx": "^2.0.12",
|
|
85
|
-
"@types/react": "^18.2.
|
|
86
|
-
"@types/react-dom": "^18.2.
|
|
85
|
+
"@types/react": "^18.2.73",
|
|
86
|
+
"@types/react-dom": "^18.2.23",
|
|
87
87
|
"@types/react-router": "^5.1.20",
|
|
88
88
|
"@types/react-router-dom": "^5.3.3",
|
|
89
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
90
|
-
"@typescript-eslint/parser": "^
|
|
89
|
+
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
|
90
|
+
"@typescript-eslint/parser": "^7.5.0",
|
|
91
91
|
"babel-loader": "^9.1.3",
|
|
92
|
-
"chromatic": "^
|
|
92
|
+
"chromatic": "^11.2.0",
|
|
93
93
|
"css-loader": "^6.10.0",
|
|
94
94
|
"eslint": "^8.57.0",
|
|
95
95
|
"eslint-config-prettier": "^9.1.0",
|
|
@@ -14,18 +14,51 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import React, { ForwardRefRenderFunction } from "react";
|
|
17
|
+
import React, { ForwardRefRenderFunction, RefObject, createRef, useEffect } from "react";
|
|
18
18
|
import { Props as SelectOptionProps, Option as SelectOption } from "../SingleSelect/Option";
|
|
19
19
|
|
|
20
|
+
import classes from "./MultiSelect.module.scss";
|
|
21
|
+
|
|
20
22
|
export interface Props extends SelectOptionProps {
|
|
21
23
|
fixed?: boolean;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const MultiOptionComponent: ForwardRefRenderFunction<HTMLLIElement, Props> = (
|
|
25
|
-
{ fixed: _fixed, ...rest }: Props,
|
|
27
|
+
{ fixed: _fixed, hasFocus, className, ...rest }: Props,
|
|
26
28
|
ref
|
|
27
29
|
) => {
|
|
28
|
-
|
|
30
|
+
let innerOptionRef = (ref as RefObject<HTMLLIElement>) || createRef<HTMLLIElement>();
|
|
31
|
+
|
|
32
|
+
const additionalClasses = [];
|
|
33
|
+
className && additionalClasses.push(className);
|
|
34
|
+
hasFocus && additionalClasses.push(classes["focus"]);
|
|
35
|
+
|
|
36
|
+
const scrollToSelectedElement = (element: HTMLLIElement) => {
|
|
37
|
+
const listbox = element.parentElement;
|
|
38
|
+
const listboxWrapper = element.parentElement?.parentElement;
|
|
39
|
+
const isListboxWrapperScrollable = !!listboxWrapper?.style.maxHeight;
|
|
40
|
+
if (isListboxWrapperScrollable) {
|
|
41
|
+
listboxWrapper?.scrollTo(0, element.offsetTop - (listboxWrapper?.offsetHeight ?? 1) / 2);
|
|
42
|
+
}
|
|
43
|
+
listbox?.scrollTo(0, element.offsetTop - (listbox?.offsetHeight ?? 1) / 2);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (innerOptionRef.current && hasFocus) {
|
|
48
|
+
scrollToSelectedElement(innerOptionRef.current);
|
|
49
|
+
}
|
|
50
|
+
}, [hasFocus, innerOptionRef]);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<SelectOption
|
|
54
|
+
ref={innerOptionRef}
|
|
55
|
+
isSelected={hasFocus}
|
|
56
|
+
disableDefaultSelectedStyle
|
|
57
|
+
className={additionalClasses.join(" ")}
|
|
58
|
+
aria-disabled={false}
|
|
59
|
+
{...rest}
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
29
62
|
};
|
|
30
63
|
|
|
31
64
|
export const MultiOption = React.forwardRef(MultiOptionComponent);
|
|
@@ -90,6 +90,7 @@ $listItemHeight: 2.5rem;
|
|
|
90
90
|
display: flex;
|
|
91
91
|
align-items: center;
|
|
92
92
|
padding: 0.1875rem 0;
|
|
93
|
+
gap: 0.375rem;
|
|
93
94
|
}
|
|
94
95
|
}
|
|
95
96
|
|
|
@@ -143,9 +144,21 @@ $listItemHeight: 2.5rem;
|
|
|
143
144
|
opacity: 0.05;
|
|
144
145
|
}
|
|
145
146
|
|
|
146
|
-
&:focus
|
|
147
|
-
|
|
148
|
-
outline
|
|
147
|
+
&:focus,
|
|
148
|
+
&.focus {
|
|
149
|
+
outline: none;
|
|
150
|
+
|
|
151
|
+
&::before {
|
|
152
|
+
@include mixins.focusVisibleOutline($outlineOffset: 0, $selectors: null);
|
|
153
|
+
content: "";
|
|
154
|
+
position: absolute;
|
|
155
|
+
top: 0;
|
|
156
|
+
left: 0.125rem;
|
|
157
|
+
height: 100%;
|
|
158
|
+
width: calc(100% - 0.25rem);
|
|
159
|
+
opacity: 1;
|
|
160
|
+
z-index: calc(variables.$popover-z-index + 1);
|
|
161
|
+
}
|
|
149
162
|
}
|
|
150
163
|
|
|
151
164
|
&:hover:after,
|
|
@@ -166,20 +179,6 @@ $listItemHeight: 2.5rem;
|
|
|
166
179
|
}
|
|
167
180
|
}
|
|
168
181
|
|
|
169
|
-
.selected-option {
|
|
170
|
-
&:before {
|
|
171
|
-
content: "";
|
|
172
|
-
position: absolute;
|
|
173
|
-
top: 0;
|
|
174
|
-
left: 0;
|
|
175
|
-
height: 100%;
|
|
176
|
-
border-top-right-radius: 0.125rem;
|
|
177
|
-
border-bottom-right-radius: 0.125rem;
|
|
178
|
-
border-left: 0.25rem solid var(--color-primary);
|
|
179
|
-
}
|
|
180
|
-
color: var(--color-primary);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
182
|
.status {
|
|
184
183
|
padding: 0.3125rem;
|
|
185
184
|
display: flex;
|
|
@@ -210,11 +209,22 @@ $listItemHeight: 2.5rem;
|
|
|
210
209
|
}
|
|
211
210
|
|
|
212
211
|
.select-search {
|
|
213
|
-
|
|
214
|
-
width: 100%;
|
|
212
|
+
flex: 1;
|
|
215
213
|
box-sizing: border-box;
|
|
216
214
|
border-bottom-left-radius: 0;
|
|
217
215
|
border-bottom-right-radius: 0;
|
|
216
|
+
border: 0;
|
|
217
|
+
background-color: transparent;
|
|
218
|
+
color: var(--default);
|
|
219
|
+
font-family: var(--font-family);
|
|
220
|
+
line-height: 1.3333;
|
|
221
|
+
margin: 0;
|
|
222
|
+
padding: 0;
|
|
223
|
+
|
|
224
|
+
&:focus-visible,
|
|
225
|
+
&:focus {
|
|
226
|
+
outline: none;
|
|
227
|
+
}
|
|
218
228
|
}
|
|
219
229
|
|
|
220
230
|
.disabled {
|
|
@@ -17,28 +17,35 @@
|
|
|
17
17
|
import classes from "./MultiSelect.module.scss";
|
|
18
18
|
|
|
19
19
|
import React, {
|
|
20
|
-
createRef,
|
|
21
20
|
ForwardRefRenderFunction,
|
|
22
21
|
Fragment,
|
|
23
22
|
ReactElement,
|
|
23
|
+
createRef,
|
|
24
24
|
useEffect,
|
|
25
25
|
useRef,
|
|
26
26
|
useState
|
|
27
27
|
} from "react";
|
|
28
|
-
import { Icon, Icons } from "../../../Icon/Icon";
|
|
29
28
|
import { useBodyClick } from "../../../../hooks/useBodyClick";
|
|
30
|
-
import readyclasses from "../../../../readyclasses.module.scss";
|
|
31
|
-
import { filterProps } from "../../../../util/helper";
|
|
32
|
-
import { useArrowNavigation, useSelectPositionList } from "../SelectService";
|
|
33
29
|
import { useDetermineStatusIcon } from "../../../../hooks/useDetermineStatusIcon";
|
|
34
|
-
import
|
|
35
|
-
import {
|
|
30
|
+
import readyclasses from "../../../../readyclasses.module.scss";
|
|
31
|
+
import { escapeRegExp, filterProps, generateID } from "../../../../util/helper";
|
|
32
|
+
import { Icon, Icons } from "../../../Icon/Icon";
|
|
36
33
|
import { MultiSelectProps } from "../Select.interfaces";
|
|
37
|
-
import { useSearch } from "../useSearch";
|
|
38
34
|
import { useAddNewBtn } from "../useAddNewBtn";
|
|
35
|
+
import { useSelectPositionList } from "../useSelectPositionList";
|
|
36
|
+
import { SelectButton } from "./SelectButton";
|
|
37
|
+
import { Display, SelectedOptions } from "./SelectedOptions";
|
|
38
|
+
import { useArrowNavigation } from "./useArrowNavigation";
|
|
39
|
+
import { useSearch } from "./useSearch";
|
|
40
|
+
|
|
41
|
+
const getOptionId = (multiSelectId: string, optionIndex: number) =>
|
|
42
|
+
`${multiSelectId}_option${optionIndex}`;
|
|
43
|
+
|
|
44
|
+
const getListboxId = (multiSelectId: string) => `${multiSelectId}_listbox`;
|
|
39
45
|
|
|
40
46
|
const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSelectProps> = (
|
|
41
47
|
{
|
|
48
|
+
id,
|
|
42
49
|
children,
|
|
43
50
|
name,
|
|
44
51
|
disabled = false,
|
|
@@ -56,42 +63,51 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
56
63
|
noResultsLabel = "No results found",
|
|
57
64
|
onChange,
|
|
58
65
|
addNew,
|
|
59
|
-
search,
|
|
66
|
+
search = { enabled: true, renderThreshold: 0 },
|
|
60
67
|
...rest
|
|
61
68
|
}: MultiSelectProps,
|
|
62
69
|
ref
|
|
63
70
|
) => {
|
|
71
|
+
const multiSelectId = useRef(id ?? generateID(20));
|
|
64
72
|
const [expanded, setExpanded] = useState(false);
|
|
65
|
-
const [display, setDisplay] = useState<
|
|
73
|
+
const [display, setDisplay] = useState<Display[]>([]);
|
|
66
74
|
const containerReference = useRef<HTMLDivElement>(null);
|
|
67
75
|
const optionListReference = useRef<HTMLDivElement>(null);
|
|
68
|
-
const [focusedSelectItem, setFocusedSelectItem] = useState(
|
|
76
|
+
const [focusedSelectItem, setFocusedSelectItem] = useState(0);
|
|
69
77
|
const [shouldClick, setShouldClick] =
|
|
70
78
|
useState(
|
|
71
79
|
false
|
|
72
80
|
); /** We need this, because whenever we use the arrow keys to select the select item, and we focus the currently selected item it fires the "click" listener in Option component. Instead, we only want this to fire if we press "enter" or "spacebar" so we set this to true whenever that is the case, and back to false when it has been executed. */
|
|
73
81
|
const [shouldFocusButtonAfterClose, setShouldFocusButtonAfterClose] = useState(false);
|
|
74
|
-
const optionsVisibleCount =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
searchInputRef,
|
|
80
|
-
setIsSearching,
|
|
81
|
-
searchThreshold,
|
|
82
|
-
searchVisible
|
|
83
|
-
} = useSearch({
|
|
82
|
+
const [optionsVisibleCount, setOptionsVisibleCount] = useState(
|
|
83
|
+
React.Children.count(children) - display.length
|
|
84
|
+
);
|
|
85
|
+
const { filter, renderSearch, searchInputRef, resetSearchState, searchVisible } = useSearch({
|
|
86
|
+
selectId: multiSelectId.current,
|
|
84
87
|
expanded,
|
|
85
88
|
search,
|
|
86
89
|
searchInputClassName: classes["select-search"],
|
|
87
90
|
optionsCount: optionsVisibleCount,
|
|
91
|
+
focusedSelectItem,
|
|
88
92
|
setFocusedSelectItem,
|
|
89
93
|
searchInputProps,
|
|
90
|
-
searchPlaceholder
|
|
94
|
+
searchPlaceholder,
|
|
95
|
+
describedBy,
|
|
96
|
+
getOptionId,
|
|
97
|
+
getListboxId
|
|
91
98
|
});
|
|
92
99
|
const { addBtnRef, addNewBtnOptionsContainerClassName, renderAddNew } = useAddNewBtn({
|
|
100
|
+
id: getOptionId(multiSelectId.current, optionsVisibleCount),
|
|
93
101
|
addNew,
|
|
94
|
-
filter
|
|
102
|
+
filter,
|
|
103
|
+
focusedSelectItem,
|
|
104
|
+
optionsCount: optionsVisibleCount,
|
|
105
|
+
searchInputRef,
|
|
106
|
+
shouldClick,
|
|
107
|
+
onClickCallback: () => {
|
|
108
|
+
setShouldClick(false);
|
|
109
|
+
resetSearchState();
|
|
110
|
+
}
|
|
95
111
|
});
|
|
96
112
|
|
|
97
113
|
const nativeSelect = (ref as React.RefObject<HTMLSelectElement>) || createRef();
|
|
@@ -110,8 +126,8 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
110
126
|
});
|
|
111
127
|
nativeSelect.current.dispatchEvent(new Event("change", { bubbles: true }));
|
|
112
128
|
}
|
|
113
|
-
|
|
114
129
|
setExpanded(false);
|
|
130
|
+
resetSearchState();
|
|
115
131
|
};
|
|
116
132
|
|
|
117
133
|
const onSelectedOptionRemoveHandler = (value: string) => {
|
|
@@ -126,33 +142,24 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
126
142
|
const { onArrowNavigation } = useArrowNavigation({
|
|
127
143
|
expanded,
|
|
128
144
|
setExpanded,
|
|
129
|
-
isSearching,
|
|
130
|
-
setIsSearching,
|
|
131
145
|
setFocusedSelectItem,
|
|
132
|
-
onOptionChangeHandler,
|
|
133
146
|
childrenCount: optionsVisibleCount,
|
|
134
147
|
setShouldClick,
|
|
135
|
-
searchInputRef,
|
|
136
148
|
addBtnRef,
|
|
137
|
-
|
|
149
|
+
searchInputRef,
|
|
150
|
+
customSelectButtonRef,
|
|
151
|
+
onClose: resetSearchState
|
|
138
152
|
});
|
|
139
153
|
|
|
140
154
|
const { listPosition, opacity, optionsListMaxHeight, setListPosition, setOpacity } =
|
|
141
155
|
useSelectPositionList({ expanded, optionListReference, containerReference, addBtnRef });
|
|
142
156
|
|
|
143
|
-
const syncDisplayValue = (
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
fixed: curOption.props.fixed
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
return prevOption;
|
|
153
|
-
},
|
|
154
|
-
{} as Record<string, Display>
|
|
155
|
-
);
|
|
157
|
+
const syncDisplayValue = (values: string[]) => {
|
|
158
|
+
const options = React.Children.map(children, child => child);
|
|
159
|
+
const displayArray: Display[] = values.map(value => {
|
|
160
|
+
const option = options.find(option => option.props.value === value);
|
|
161
|
+
return { value, label: option?.props.children, fixed: option?.props.fixed };
|
|
162
|
+
});
|
|
156
163
|
setDisplay(displayArray);
|
|
157
164
|
};
|
|
158
165
|
|
|
@@ -177,31 +184,37 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
177
184
|
type ReactChildrenType = ReturnType<typeof React.Children.toArray>;
|
|
178
185
|
|
|
179
186
|
const filterOutSelectedChildren = (internalChildren: ReactChildrenType) => {
|
|
180
|
-
const selectedValues = Object.keys(display);
|
|
181
187
|
return internalChildren.filter(
|
|
182
188
|
child =>
|
|
183
189
|
typeof child === "object" &&
|
|
184
190
|
"props" in child &&
|
|
185
|
-
!
|
|
191
|
+
!display.find(option => option.value === child.props.value)
|
|
186
192
|
);
|
|
187
193
|
};
|
|
188
194
|
|
|
189
|
-
|
|
195
|
+
let results;
|
|
196
|
+
if (filter !== "") {
|
|
190
197
|
const filteredChildren = React.Children.toArray(children).filter(
|
|
191
198
|
child =>
|
|
192
|
-
(child as ReactElement).props.children
|
|
199
|
+
(child as ReactElement).props.children
|
|
200
|
+
.toLowerCase()
|
|
201
|
+
.match(escapeRegExp(filter.toLowerCase())) !== null
|
|
193
202
|
);
|
|
194
203
|
|
|
195
|
-
|
|
204
|
+
results = _internalRenderChildren(filterOutSelectedChildren(filteredChildren));
|
|
205
|
+
} else {
|
|
206
|
+
results = _internalRenderChildren(
|
|
207
|
+
filterOutSelectedChildren(React.Children.toArray(children))
|
|
208
|
+
);
|
|
209
|
+
}
|
|
196
210
|
|
|
197
|
-
|
|
198
|
-
return <li className={classes["no-results"]}>{noResultsLabel}</li>;
|
|
199
|
-
}
|
|
211
|
+
optionsVisibleCount !== results.length && setOptionsVisibleCount(results.length);
|
|
200
212
|
|
|
201
|
-
|
|
213
|
+
if (results.length === 0) {
|
|
214
|
+
return <li className={classes["no-results"]}>{noResultsLabel}</li>;
|
|
202
215
|
}
|
|
203
216
|
|
|
204
|
-
return
|
|
217
|
+
return results;
|
|
205
218
|
|
|
206
219
|
function _internalRenderChildren(internalChildren: ReactChildrenType) {
|
|
207
220
|
return React.Children.map(internalChildren, (child, index) => {
|
|
@@ -211,13 +224,15 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
211
224
|
},
|
|
212
225
|
onOptionSelect: (optionRef: React.RefObject<HTMLLIElement>) => {
|
|
213
226
|
onOptionChangeHandler(optionRef.current);
|
|
227
|
+
setExpanded(false);
|
|
214
228
|
setShouldClick(false);
|
|
215
229
|
},
|
|
216
|
-
isSearching:
|
|
230
|
+
isSearching: false,
|
|
217
231
|
selectOpened: expanded,
|
|
218
232
|
childIndex: index,
|
|
219
233
|
hasFocus: focusedSelectItem === index,
|
|
220
|
-
shouldClick: shouldClick
|
|
234
|
+
shouldClick: shouldClick,
|
|
235
|
+
id: getOptionId(multiSelectId.current, index)
|
|
221
236
|
});
|
|
222
237
|
});
|
|
223
238
|
}
|
|
@@ -238,16 +253,21 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
238
253
|
};
|
|
239
254
|
|
|
240
255
|
useEffect(() => {
|
|
241
|
-
if (expanded) {
|
|
242
|
-
setFocusedSelectItem(0);
|
|
256
|
+
if (expanded && searchInputRef.current) {
|
|
243
257
|
setShouldFocusButtonAfterClose(true);
|
|
258
|
+
searchInputRef.current.focus();
|
|
244
259
|
}
|
|
245
260
|
|
|
246
261
|
if (!expanded && customSelectButtonRef.current && shouldFocusButtonAfterClose) {
|
|
247
|
-
customSelectButtonRef.current.focus();
|
|
248
262
|
setShouldFocusButtonAfterClose(false);
|
|
263
|
+
customSelectButtonRef.current.focus();
|
|
249
264
|
}
|
|
250
|
-
}, [
|
|
265
|
+
}, [
|
|
266
|
+
expanded,
|
|
267
|
+
customSelectButtonRef.current,
|
|
268
|
+
shouldFocusButtonAfterClose,
|
|
269
|
+
searchInputRef.current
|
|
270
|
+
]);
|
|
251
271
|
|
|
252
272
|
useEffect(() => {
|
|
253
273
|
syncDisplayValue(value);
|
|
@@ -272,7 +292,8 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
272
292
|
success && additionalClasses.push(classes.success);
|
|
273
293
|
|
|
274
294
|
const onSelectButtonClick = () => {
|
|
275
|
-
setExpanded(!expanded);
|
|
295
|
+
setExpanded(expanded => !expanded);
|
|
296
|
+
setShouldClick(false);
|
|
276
297
|
};
|
|
277
298
|
|
|
278
299
|
/** The native select is purely for external form libraries. We use it to emit an onChange with native select event object so they know exactly what's happening. */
|
|
@@ -295,16 +316,16 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
295
316
|
</select>
|
|
296
317
|
<div
|
|
297
318
|
{...filterProps(rest, /^data-/)}
|
|
319
|
+
id={multiSelectId.current}
|
|
298
320
|
ref={containerReference}
|
|
299
321
|
onKeyDown={onArrowNavigation}
|
|
300
322
|
className={`custom-select ${classes.select} ${additionalClasses.join(" ")} ${
|
|
301
323
|
className ?? ""
|
|
302
324
|
}`}
|
|
303
325
|
>
|
|
304
|
-
{searchVisible && renderSearch()}
|
|
305
326
|
<div
|
|
306
327
|
className={`${classes["custom-select"]} ${additionalClasses.join(" ")} `}
|
|
307
|
-
style={{ display:
|
|
328
|
+
style={{ display: "flex" }}
|
|
308
329
|
>
|
|
309
330
|
<div className={classes["display-container"]} data-display>
|
|
310
331
|
<SelectButton
|
|
@@ -331,10 +352,10 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
331
352
|
onRemove={onSelectedOptionRemoveHandler}
|
|
332
353
|
/>
|
|
333
354
|
)}
|
|
355
|
+
{searchVisible && renderSearch()}
|
|
334
356
|
</div>
|
|
335
357
|
<div className={classes["status"]}>{icon || renderChevronIcon()}</div>
|
|
336
358
|
</div>
|
|
337
|
-
|
|
338
359
|
<div
|
|
339
360
|
ref={optionListReference}
|
|
340
361
|
className={`list-wrapper ${classes["list-wrapper"]}`}
|
|
@@ -347,8 +368,10 @@ const MultiSelectComponent: ForwardRefRenderFunction<HTMLSelectElement, MultiSel
|
|
|
347
368
|
}}
|
|
348
369
|
>
|
|
349
370
|
<ul
|
|
371
|
+
id={getListboxId(multiSelectId.current)}
|
|
350
372
|
className={addNewBtnOptionsContainerClassName}
|
|
351
373
|
role="listbox"
|
|
374
|
+
aria-multiselectable="true"
|
|
352
375
|
style={{ maxHeight: optionsListMaxHeight.list }}
|
|
353
376
|
>
|
|
354
377
|
{renderOptions()}
|
|
@@ -20,12 +20,13 @@ import { Tag } from "../../../Tag/Tag";
|
|
|
20
20
|
import classes from "./SelectedOptions.module.scss";
|
|
21
21
|
|
|
22
22
|
export type Display = {
|
|
23
|
+
value: string;
|
|
23
24
|
label: string;
|
|
24
25
|
fixed?: boolean;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
export interface Props extends ComponentPropsWithRef<"div"> {
|
|
28
|
-
display:
|
|
29
|
+
display: Display[];
|
|
29
30
|
onRemove: (value: string) => void;
|
|
30
31
|
disabled: boolean;
|
|
31
32
|
}
|
|
@@ -36,9 +37,9 @@ const SelectedOptionsComponent: ForwardRefRenderFunction<HTMLDivElement, Props>
|
|
|
36
37
|
) => {
|
|
37
38
|
return (
|
|
38
39
|
<div {...rest} className={classes["options"]} ref={ref}>
|
|
39
|
-
{
|
|
40
|
+
{display.map(item => (
|
|
40
41
|
<Tag
|
|
41
|
-
key={value}
|
|
42
|
+
key={item.value}
|
|
42
43
|
onClick={(e: React.MouseEvent<HTMLDivElement>) => {
|
|
43
44
|
e.stopPropagation();
|
|
44
45
|
}}
|
|
@@ -48,7 +49,7 @@ const SelectedOptionsComponent: ForwardRefRenderFunction<HTMLDivElement, Props>
|
|
|
48
49
|
? {
|
|
49
50
|
onRemove: (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
50
51
|
e.stopPropagation();
|
|
51
|
-
onRemove(value);
|
|
52
|
+
onRemove(item.value);
|
|
52
53
|
},
|
|
53
54
|
className: classes["remove-btn"]
|
|
54
55
|
}
|