@mctinetti/react-multiselectbox 1.0.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/README.md +21 -0
- package/dist/react-multiselectbox.js +2 -0
- package/dist/react-multiselectbox.js.LICENSE.txt +15 -0
- package/package.json +34 -0
- package/react-multiselectbox.jsx +261 -0
package/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# react-multiselectbox
|
2
|
+
|
3
|
+
A React multiselect box, it can also be a dropdown by parametrization.
|
4
|
+
|
5
|
+
## Build for prod
|
6
|
+
1. copy myapp\react-multiselectbox
|
7
|
+
2. cd \react-multiselectbox
|
8
|
+
3. npm install
|
9
|
+
4. npm run build
|
10
|
+
|
11
|
+
## Developement
|
12
|
+
If you want to do developement:
|
13
|
+
1. copy myapp\react-multiselectbox
|
14
|
+
2. cd react-multiselectbox
|
15
|
+
3. npm install
|
16
|
+
4. cd react-multiselectbox\example
|
17
|
+
5. npx webpack serve
|
18
|
+
|
19
|
+
### [Changelog](CHANGELOG.md)
|
20
|
+
|
21
|
+
### [MIT Licensed](LICENSE.md)
|
@@ -0,0 +1,2 @@
|
|
1
|
+
/*! For license information please see react-multiselectbox.js.LICENSE.txt */
|
2
|
+
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var r=t();for(var n in r)("object"==typeof exports?exports:e)[n]=r[n]}}(self,(()=>(()=>{var e={287:(e,t)=>{"use strict";var r=Symbol.for("react.element"),n=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),u=Symbol.for("react.profiler"),a=Symbol.for("react.provider"),c=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),s=Symbol.for("react.suspense"),f=Symbol.for("react.memo"),d=Symbol.for("react.lazy"),p=Symbol.iterator,y={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},m=Object.assign,b={};function v(e,t,r){this.props=e,this.context=t,this.refs=b,this.updater=r||y}function h(){}function g(e,t,r){this.props=e,this.context=t,this.refs=b,this.updater=r||y}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},h.prototype=v.prototype;var S=g.prototype=new h;S.constructor=g,m(S,v.prototype),S.isPureReactComponent=!0;var E=Array.isArray,_=Object.prototype.hasOwnProperty,O={current:null},k={key:!0,ref:!0,__self:!0,__source:!0};function w(e,t,n){var o,i={},u=null,a=null;if(null!=t)for(o in void 0!==t.ref&&(a=t.ref),void 0!==t.key&&(u=""+t.key),t)_.call(t,o)&&!k.hasOwnProperty(o)&&(i[o]=t[o]);var c=arguments.length-2;if(1===c)i.children=n;else if(1<c){for(var l=Array(c),s=0;s<c;s++)l[s]=arguments[s+2];i.children=l}if(e&&e.defaultProps)for(o in c=e.defaultProps)void 0===i[o]&&(i[o]=c[o]);return{$$typeof:r,type:e,key:u,ref:a,props:i,_owner:O.current}}function j(e){return"object"==typeof e&&null!==e&&e.$$typeof===r}var x=/\/+/g;function C(e,t){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var t={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return t[e]}))}(""+e.key):t.toString(36)}function P(e,t,o,i,u){var a=typeof e;"undefined"!==a&&"boolean"!==a||(e=null);var c=!1;if(null===e)c=!0;else switch(a){case"string":case"number":c=!0;break;case"object":switch(e.$$typeof){case r:case n:c=!0}}if(c)return u=u(c=e),e=""===i?"."+C(c,0):i,E(u)?(o="",null!=e&&(o=e.replace(x,"$&/")+"/"),P(u,t,o,"",(function(e){return e}))):null!=u&&(j(u)&&(u=function(e,t){return{$$typeof:r,type:e.type,key:t,ref:e.ref,props:e.props,_owner:e._owner}}(u,o+(!u.key||c&&c.key===u.key?"":(""+u.key).replace(x,"$&/")+"/")+e)),t.push(u)),1;if(c=0,i=""===i?".":i+":",E(e))for(var l=0;l<e.length;l++){var s=i+C(a=e[l],l);c+=P(a,t,o,s,u)}else if(s=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=p&&e[p]||e["@@iterator"])?e:null}(e),"function"==typeof s)for(e=s.call(e),l=0;!(a=e.next()).done;)c+=P(a=a.value,t,o,s=i+C(a,l++),u);else if("object"===a)throw t=String(e),Error("Objects are not valid as a React child (found: "+("[object Object]"===t?"object with keys {"+Object.keys(e).join(", ")+"}":t)+"). If you meant to render a collection of children, use an array instead.");return c}function N(e,t,r){if(null==e)return e;var n=[],o=0;return P(e,n,"","",(function(e){return t.call(r,e,o++)})),n}function I(e){if(-1===e._status){var t=e._result;(t=t()).then((function(t){0!==e._status&&-1!==e._status||(e._status=1,e._result=t)}),(function(t){0!==e._status&&-1!==e._status||(e._status=2,e._result=t)})),-1===e._status&&(e._status=0,e._result=t)}if(1===e._status)return e._result.default;throw e._result}var R={current:null},T={transition:null},A={ReactCurrentDispatcher:R,ReactCurrentBatchConfig:T,ReactCurrentOwner:O};function D(){throw Error("act(...) is not supported in production builds of React.")}t.Children={map:N,forEach:function(e,t,r){N(e,(function(){t.apply(this,arguments)}),r)},count:function(e){var t=0;return N(e,(function(){t++})),t},toArray:function(e){return N(e,(function(e){return e}))||[]},only:function(e){if(!j(e))throw Error("React.Children.only expected to receive a single React element child.");return e}},t.Component=v,t.Fragment=o,t.Profiler=u,t.PureComponent=g,t.StrictMode=i,t.Suspense=s,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=A,t.act=D,t.cloneElement=function(e,t,n){if(null==e)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+e+".");var o=m({},e.props),i=e.key,u=e.ref,a=e._owner;if(null!=t){if(void 0!==t.ref&&(u=t.ref,a=O.current),void 0!==t.key&&(i=""+t.key),e.type&&e.type.defaultProps)var c=e.type.defaultProps;for(l in t)_.call(t,l)&&!k.hasOwnProperty(l)&&(o[l]=void 0===t[l]&&void 0!==c?c[l]:t[l])}var l=arguments.length-2;if(1===l)o.children=n;else if(1<l){c=Array(l);for(var s=0;s<l;s++)c[s]=arguments[s+2];o.children=c}return{$$typeof:r,type:e.type,key:i,ref:u,props:o,_owner:a}},t.createContext=function(e){return(e={$$typeof:c,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null}).Provider={$$typeof:a,_context:e},e.Consumer=e},t.createElement=w,t.createFactory=function(e){var t=w.bind(null,e);return t.type=e,t},t.createRef=function(){return{current:null}},t.forwardRef=function(e){return{$$typeof:l,render:e}},t.isValidElement=j,t.lazy=function(e){return{$$typeof:d,_payload:{_status:-1,_result:e},_init:I}},t.memo=function(e,t){return{$$typeof:f,type:e,compare:void 0===t?null:t}},t.startTransition=function(e){var t=T.transition;T.transition={};try{e()}finally{T.transition=t}},t.unstable_act=D,t.useCallback=function(e,t){return R.current.useCallback(e,t)},t.useContext=function(e){return R.current.useContext(e)},t.useDebugValue=function(){},t.useDeferredValue=function(e){return R.current.useDeferredValue(e)},t.useEffect=function(e,t){return R.current.useEffect(e,t)},t.useId=function(){return R.current.useId()},t.useImperativeHandle=function(e,t,r){return R.current.useImperativeHandle(e,t,r)},t.useInsertionEffect=function(e,t){return R.current.useInsertionEffect(e,t)},t.useLayoutEffect=function(e,t){return R.current.useLayoutEffect(e,t)},t.useMemo=function(e,t){return R.current.useMemo(e,t)},t.useReducer=function(e,t,r){return R.current.useReducer(e,t,r)},t.useRef=function(e){return R.current.useRef(e)},t.useState=function(e){return R.current.useState(e)},t.useSyncExternalStore=function(e,t,r){return R.current.useSyncExternalStore(e,t,r)},t.useTransition=function(){return R.current.useTransition()},t.version="18.3.1"},540:(e,t,r)=>{"use strict";e.exports=r(287)},556:(e,t,r)=>{e.exports=r(694)()},694:(e,t,r)=>{"use strict";var n=r(925);function o(){}function i(){}i.resetWarningCache=o,e.exports=function(){function e(e,t,r,o,i,u){if(u!==n){var a=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw a.name="Invariant Violation",a}}function t(){return e}e.isRequired=e;var r={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:o};return r.PropTypes=r,r}},925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},942:(e,t)=>{var r;!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e="",t=0;t<arguments.length;t++){var r=arguments[t];r&&(e=u(e,i(r)))}return e}function i(e){if("string"==typeof e||"number"==typeof e)return e;if("object"!=typeof e)return"";if(Array.isArray(e))return o.apply(null,e);if(e.toString!==Object.prototype.toString&&!e.toString.toString().includes("[native code]"))return e.toString();var t="";for(var r in e)n.call(e,r)&&e[r]&&(t=u(t,r));return t}function u(e,t){return t?e?e+" "+t:e+t:e}e.exports?(o.default=o,e.exports=o):void 0===(r=function(){return o}.apply(t,[]))||(e.exports=r)}()}},t={};function r(n){var o=t[n];if(void 0!==o)return o.exports;var i=t[n]={exports:{}};return e[n](i,i.exports,r),i.exports}r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var n={};return(()=>{"use strict";r.r(n),r.d(n,{default:()=>b});var e=r(540),t=r(556),o=r.n(t),i=r(942),u=r.n(i);function a(e){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},a(e)}function c(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?c(Object(r),!0).forEach((function(t){s(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):c(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function s(e,t,r){return(t=function(e){var t=function(e){if("object"!=a(e)||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var r=t.call(e,"string");if("object"!=a(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==a(t)?t:t+""}(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function f(e){return function(e){if(Array.isArray(e))return y(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||p(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,o,i,u,a=[],c=!0,l=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;c=!1}else for(;!(c=(n=i.call(r)).done)&&(a.push(n.value),a.length!==t);c=!0);}catch(e){l=!0,o=e}finally{try{if(!c&&null!=r.return&&(u=r.return(),Object(u)!==u))return}finally{if(l)throw o}}return a}}(e,t)||p(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function p(e,t){if(e){if("string"==typeof e)return y(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?y(e,t):void 0}}function y(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}var m=function(t){var r=t.id,n=t.name,o=(t.value,t.options),i=t.selectedItems,a=t.placeholder,c=t.disabled,s=t.onChange,p=(t.onBlur,t.onFocus,t.autoFocus),y=t.autoComplete,m=t.displayAsDropdown,b=void 0!==m&&m,v=d((0,e.useState)(""),2),h=v[0],g=v[1],S=d((0,e.useState)(!1),2),E=S[0],_=S[1],O=d((0,e.useState)(o),2),k=O[0],w=O[1],j=d((0,e.useState)(o.map((function(e,t){return{id:e.id,sortOrder:t}}))),2),x=j[0],C=j[1],P=d((0,e.useState)(i),2),N=P[0],I=P[1],R=d((0,e.useState)(!1),2),T=R[0],A=R[1],D=function(e,t){return e.filter((function(e){return e.label.toLowerCase().includes(t.toLowerCase())}))};(0,e.useEffect)((function(){C(o.map((function(e,t){return{id:e.id,sortOrder:t}}))),w(o),I(N.filter((function(e){return o.some((function(t){return t.id===e.id}))})))}),[o]);(0,e.useEffect)((function(){var e;e=h&&!b?D(N,h).filter((function(e){return!e.disabled})).length:N.filter((function(e){return!e.disabled})).length,_(k.filter((function(e){return!e.disabled})).length==e&&0!=k.length)}),[N]);var $=(0,e.useCallback)((function(e){b&&(L.current&&L.current.contains(e.target)?A(!0):(A(!1),g(""),w(o),N.length==o.length&&0!=o.length?_(!0):_(!1)))}),[o,N]),L=(0,e.useRef)(null);(0,e.useEffect)((function(){return document.addEventListener("click",$),function(){document.removeEventListener("click",$)}}),[$]);var V=e.createElement("label",{className:"itemlabel"},e.createElement("input",{type:"checkbox",className:"notVisible",checked:E,onChange:function(e){return function(e){var t;_(e.target.checked),t=0==e.target.checked?N.filter((function(e){return!k.some((function(t){return t.id===e.id&&!t.disabled}))})):[].concat(f(N),f(k.filter((function(e){return 1!=e.disabled})))).filter((function(e,t,r){return t===r.findIndex((function(t){return t.id===e.id}))})),I(t),s&&s(t,"selectedItems"),b&&w(o)}(e)}}),e.createElement("span",{className:"checkbox-custom"}),"Select All");return e.createElement("div",{className:"containerMultiSelectBox",ref:L},e.createElement("div",{id:"box1",className:u()(b?"boxDropDown":"box")},e.createElement("div",{className:"firstline"},e.createElement("div",{className:"leftDivs"},e.createElement("input",{autoFocus:p,autoComplete:y,type:"text",id:r,name:n,value:T?h:b?function(e,t){var r=e.map((function(e){return l(l({},e),{},{sortOrder:t.find((function(t){return t.id==e.id})).sortOrder})})).sort((function(e,t){return e.sortOrder-t.sortOrder})).map((function(e){return e.label})).join(", ");return r.length>30?"".concat(r.substring(0,30),"..."):r}(N,x):h,className:"searchField",disabled:c,placeholder:a||"Search...",onChange:function(e){return function(e){g(e.target.value);var t=e.target.value.trim(),r=o;t&&(r=D(o,t)),w(r),_(r.filter((function(e){return!e.disabled})).every((function(e){return N.some((function(t){return e.id===t.id}))}))&&r.length>0)}(e)}}))),e.createElement("div",{className:u()("items","selectAllLine",b?"notVisible":"")},V),e.createElement("div",{className:b?T?"itemsListScrollDropDown":"itemsListScrollDropDown notVisible":"itemsListScroll"},e.createElement("div",{className:u()("items","selectAllLine",b&&T?"":"notVisible")},V),e.createElement("div",{className:b?0==k.length?"itemsListScroll noItemsToList":"itemsListScroll":0==k.length?"noItemsToList inheritHeight":""},0==k.length?"No Items...":"",k.map((function(t,r){return e.createElement("div",{key:"chd01-"+t.id,className:u()("items",N.some((function(e){return e.id===t.id}))?"paintGray":"paintWhite")},e.createElement("label",{key:"chd02-"+t.id,className:u()("itemlabel",t.disabled?"itemlabeldisabled":"")},e.createElement("input",{key:"chd03-"+t.id,id:t.id,className:"notVisible",type:"checkbox",checked:1==N.some((function(e){return e.id===t.id}))||"",onChange:function(e){return function(e,t,r,n){var o,i={id:e.target.id,label:t,disabled:r,data:n};o=0==e.target.checked?N.filter((function(t){return t.id!==e.target.id})):[].concat(f(N),[i]),I(o),s&&s(o,"selectedItems")}(e,t.label,t.disabled,t.data)},disabled:t.disabled}),e.createElement("span",{className:"checkbox-custom"}),t.label," "))}))))),b?"":e.createElement("div",{id:"box2",className:"box",style:{backgroundColor:"white"}},e.createElement("div",{className:"firstline"},e.createElement("div",{className:"rightDivs"},N.length>0?N.length:"None"," Selected"),e.createElement("div",{className:"rightDivs"}," ",e.createElement("a",{href:"#",onClick:function(){f(N.filter((function(e){return e.disabled}))),I(f(N.filter((function(e){return e.disabled})))),s&&s(o,"selectedItems")},className:"link_clear"},"Clear All")," ")),e.createElement("div",{className:u()("itemsListScrollRight",0==N.length?"noItemsToList":"")},0==N.length?"No Items...":"",N.map((function(e){return l(l({},e),{},{sortOrder:x.find((function(t){return t.id==e.id})).sortOrder})})).sort((function(e,t){return e.sortOrder-t.sortOrder})).map((function(t){return e.createElement("div",{key:"chd04-"+t.id,className:u()("items","delete-div"),onClick:function(){return function(e){var t=N.filter((function(t){return t.id!=e||t.disabled}));I(t),s&&s(t,"selectedItems")}(t.id)}},e.createElement("label",{key:"chd02-"+t.id,className:u()("itemlabel",t.disabled?"itemlabeldisabled":"")},t.label),t.disabled?"":e.createElement("button",{key:"chd05-"+t.id,type:"button",className:"buttonDelete"},"x"))})))))};m.propTypes={id:o().string,options:o().array,selectedItems:o().array,name:o().string,value:o().any,placeholder:o().string,disabled:o().bool,onChange:o().func,onBlur:o().func,onFocus:o().func,autoFocus:o().any,autoComplete:o().any,displayAsDropdown:o().bool};const b=m})(),n})()));
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*!
|
2
|
+
Copyright (c) 2018 Jed Watson.
|
3
|
+
Licensed under the MIT License (MIT), see
|
4
|
+
http://jedwatson.github.io/classnames
|
5
|
+
*/
|
6
|
+
|
7
|
+
/**
|
8
|
+
* @license React
|
9
|
+
* react.production.min.js
|
10
|
+
*
|
11
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
12
|
+
*
|
13
|
+
* This source code is licensed under the MIT license found in the
|
14
|
+
* LICENSE file in the root directory of this source tree.
|
15
|
+
*/
|
package/package.json
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
{
|
2
|
+
"name": "@mctinetti/react-multiselectbox",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"private": false,
|
5
|
+
"license": "MIT",
|
6
|
+
"description": "multiselectbox with option search.",
|
7
|
+
"package_json_docs": "https://docs.npmjs.com/files/package.json",
|
8
|
+
"main": "dist/react-multiselectbox.js",
|
9
|
+
"files": [
|
10
|
+
"react-multiselectbox.jsx",
|
11
|
+
"dist"
|
12
|
+
],
|
13
|
+
"scripts": {
|
14
|
+
"build": "webpack"
|
15
|
+
},
|
16
|
+
"author": "Cristina Tinetti",
|
17
|
+
"dependencies": {
|
18
|
+
"classnames": "^2.5.1",
|
19
|
+
"css-loader": "^7.1.2",
|
20
|
+
"prop-types": "^15.8.1",
|
21
|
+
"react": "^18.3.1",
|
22
|
+
"react-dom": "^18.3.1",
|
23
|
+
"style-loader": "^4.0.0"
|
24
|
+
},
|
25
|
+
"devDependencies": {
|
26
|
+
"@babel/core": "^7.26.7",
|
27
|
+
"@babel/preset-env": "^7.26.7",
|
28
|
+
"@babel/preset-react": "^7.26.3",
|
29
|
+
"babel-loader": "^9.2.1",
|
30
|
+
"webpack": "^5.97.1",
|
31
|
+
"webpack-cli": "^6.0.1",
|
32
|
+
"webpack-dev-server": "^5.2.0"
|
33
|
+
}
|
34
|
+
}
|
@@ -0,0 +1,261 @@
|
|
1
|
+
import React, { useEffect, useRef, useState, useCallback } from 'react';
|
2
|
+
import PropTypes from "prop-types";
|
3
|
+
import classNames from 'classnames';
|
4
|
+
|
5
|
+
const MultiSelectBox = ({
|
6
|
+
id,
|
7
|
+
name,
|
8
|
+
value,
|
9
|
+
options,
|
10
|
+
selectedItems,
|
11
|
+
placeholder,
|
12
|
+
disabled,
|
13
|
+
onChange,
|
14
|
+
//onClick,
|
15
|
+
onBlur,
|
16
|
+
onFocus,
|
17
|
+
autoFocus,
|
18
|
+
autoComplete,
|
19
|
+
displayAsDropdown = false,
|
20
|
+
}) => {
|
21
|
+
let [searchValue, setSearchValue] = useState("")
|
22
|
+
let [checkedAllValue, setcheckedAllValue] = useState(false) // SelectAll
|
23
|
+
let [optionsMyState, setOptionsMyState] = useState(options)
|
24
|
+
|
25
|
+
let [optionsSortMyState, setOptionsSortMyState] = useState(options.map((item, index) => ({ // Items selected but I added orderSort
|
26
|
+
id:item.id,
|
27
|
+
sortOrder: index
|
28
|
+
})))
|
29
|
+
let [selectedItemsMyState, setSelectedItemsMyState] = useState( selectedItems )
|
30
|
+
const [isOpen, setIsOpen] = useState(false)
|
31
|
+
|
32
|
+
const filterProcess = (options, searchValue) => {
|
33
|
+
return options.filter(item => item.label.toLowerCase().includes(searchValue.toLowerCase()))
|
34
|
+
}
|
35
|
+
|
36
|
+
const handleChangeOnSearch = (e) => { //Search ...
|
37
|
+
setSearchValue(e.target.value);
|
38
|
+
const searchValue = e.target.value.trim()
|
39
|
+
|
40
|
+
let newOptions = options
|
41
|
+
if(searchValue){
|
42
|
+
newOptions = filterProcess(options,searchValue)
|
43
|
+
}
|
44
|
+
setOptionsMyState(newOptions)
|
45
|
+
setcheckedAllValue(newOptions.filter(i=>!i.disabled).every(itemA => selectedItemsMyState.some(itemB => itemA.id === itemB.id)) && newOptions.length > 0)
|
46
|
+
};
|
47
|
+
|
48
|
+
useEffect(() => {
|
49
|
+
setOptionsSortMyState(options.map((item, index) => ({ // Items selected but I added orderSort
|
50
|
+
id:item.id,
|
51
|
+
sortOrder: index
|
52
|
+
})))
|
53
|
+
setOptionsMyState(options)
|
54
|
+
setSelectedItemsMyState(selectedItemsMyState.filter(item => options.some(option => option.id === item.id))) // Removing items from the selectedItemsMyState if they are not in the options list
|
55
|
+
}, [options]);
|
56
|
+
|
57
|
+
const handleChangeCheckAll = (e) => { // SelectAll
|
58
|
+
setcheckedAllValue(e.target.checked)
|
59
|
+
|
60
|
+
let newSelectedItems
|
61
|
+
if (e.target.checked == false) {
|
62
|
+
//Remove the items listed on page
|
63
|
+
newSelectedItems = selectedItemsMyState.filter(itemA => !optionsMyState.some(option => option.id === itemA.id && !option.disabled ) );
|
64
|
+
} else {
|
65
|
+
//Add the items listed on page
|
66
|
+
newSelectedItems = [...selectedItemsMyState, ...optionsMyState.filter(ite=>ite.disabled!=true)].filter((value, index, self) =>
|
67
|
+
index === self.findIndex((t) => (
|
68
|
+
t.id === value.id
|
69
|
+
))
|
70
|
+
)
|
71
|
+
}
|
72
|
+
setSelectedItemsMyState(newSelectedItems)
|
73
|
+
if (onChange) onChange(newSelectedItems,'selectedItems')
|
74
|
+
|
75
|
+
if (displayAsDropdown) setOptionsMyState(options)
|
76
|
+
}
|
77
|
+
|
78
|
+
const handleChangeIndividualCheck = (e, labeltxt, disabled, data) => {
|
79
|
+
let newSelectedItems
|
80
|
+
const newItem = { id: e.target.id, label: labeltxt, disabled: disabled, data: data};
|
81
|
+
|
82
|
+
newSelectedItems = e.target.checked == false ? (selectedItemsMyState.filter((item) => item.id !== e.target.id)) // removing
|
83
|
+
: ([...selectedItemsMyState,newItem]) // adding
|
84
|
+
|
85
|
+
setSelectedItemsMyState(newSelectedItems)
|
86
|
+
if (onChange) onChange(newSelectedItems,'selectedItems')
|
87
|
+
}
|
88
|
+
|
89
|
+
const handleBlur = (e) => {
|
90
|
+
// lose focus
|
91
|
+
};
|
92
|
+
|
93
|
+
const handleClickToClearAll = () =>{
|
94
|
+
let newSelectedItems = [ ...selectedItemsMyState.filter(item=>item.disabled)]
|
95
|
+
setSelectedItemsMyState([ ...selectedItemsMyState.filter(item=>item.disabled)])
|
96
|
+
if (onChange) onChange(options,'selectedItems') // sent to the main component all the list
|
97
|
+
}
|
98
|
+
|
99
|
+
const handleClickToRemoveItem = (id) =>{
|
100
|
+
let newSelectedItems = selectedItemsMyState.filter(item=> item.id != id || item.disabled )
|
101
|
+
setSelectedItemsMyState(newSelectedItems)
|
102
|
+
if (onChange) onChange(newSelectedItems,'selectedItems')
|
103
|
+
}
|
104
|
+
|
105
|
+
useEffect(()=> { // this effect it's basically to set the Select All checkbox
|
106
|
+
let selectedItemsLen
|
107
|
+
if(searchValue && !displayAsDropdown){
|
108
|
+
selectedItemsLen = filterProcess(selectedItemsMyState,searchValue).filter(option=>!option.disabled).length
|
109
|
+
} else{
|
110
|
+
|
111
|
+
selectedItemsLen = selectedItemsMyState.filter(option=>!option.disabled).length
|
112
|
+
}
|
113
|
+
setcheckedAllValue( optionsMyState.filter(option=>!option.disabled).length == selectedItemsLen ? optionsMyState.length==0 ? false : true
|
114
|
+
: false);
|
115
|
+
},[selectedItemsMyState])
|
116
|
+
|
117
|
+
|
118
|
+
const handleClickOnElement = useCallback((event) => {
|
119
|
+
if (displayAsDropdown) {
|
120
|
+
if(ref.current && ref.current.contains(event.target)){
|
121
|
+
setIsOpen(true)
|
122
|
+
}else{
|
123
|
+
setIsOpen(false) // Close the item list
|
124
|
+
setSearchValue('') // Clean the search value in case it has value
|
125
|
+
setOptionsMyState(options) // Reset the options
|
126
|
+
selectedItemsMyState.length==options.length && options.length!=0 ? setcheckedAllValue(true) : setcheckedAllValue(false) // Check if Select All should be mark or not
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}, [options, selectedItemsMyState]);
|
130
|
+
|
131
|
+
// Code to handle clicks in/outside the component
|
132
|
+
const ref = useRef(null);
|
133
|
+
useEffect(() => {
|
134
|
+
//Mount
|
135
|
+
document.addEventListener("click", handleClickOnElement);
|
136
|
+
//Unmount
|
137
|
+
return () => {
|
138
|
+
document.removeEventListener("click", handleClickOnElement);
|
139
|
+
};
|
140
|
+
}, [handleClickOnElement]);
|
141
|
+
|
142
|
+
const generatePreview = (selectedItems,optionsSort) => {
|
143
|
+
const preview = selectedItems.map(item => ({
|
144
|
+
...item,
|
145
|
+
sortOrder: optionsSort.find(option => option.id == item.id).sortOrder
|
146
|
+
})).sort((a,b) => a.sortOrder - b.sortOrder).map(item => item.label).join(', ')
|
147
|
+
return preview.length > 30 ? `${preview.substring(0, 30)}...` : preview
|
148
|
+
}
|
149
|
+
|
150
|
+
const checkboxSelectAll = <label className={"itemlabel"}>
|
151
|
+
<input type="checkbox" className="notVisible" checked={checkedAllValue} onChange={(e) => handleChangeCheckAll(e)}/>
|
152
|
+
<span className="checkbox-custom"></span>
|
153
|
+
Select All
|
154
|
+
</label>
|
155
|
+
|
156
|
+
return(
|
157
|
+
<div className={"containerMultiSelectBox"} ref={ref}>
|
158
|
+
<div id="box1" className={ classNames(displayAsDropdown?"boxDropDown":"box")} >
|
159
|
+
<div className='firstline'>
|
160
|
+
<div className='leftDivs'>
|
161
|
+
<input
|
162
|
+
autoFocus={autoFocus}
|
163
|
+
autoComplete={autoComplete}
|
164
|
+
type='text'
|
165
|
+
id={id}
|
166
|
+
name={name}
|
167
|
+
value= { isOpen ? searchValue : displayAsDropdown ? generatePreview(selectedItemsMyState, optionsSortMyState)
|
168
|
+
: searchValue }
|
169
|
+
className={'searchField'}
|
170
|
+
disabled={disabled}
|
171
|
+
placeholder={placeholder?placeholder:'Search...'}
|
172
|
+
onChange={(e) => handleChangeOnSearch(e)}
|
173
|
+
//onClick={(e) => handleClickOnSearch(e)}
|
174
|
+
//onBlur={(e) => handleBlur(e)}
|
175
|
+
//onFocus={(e) => handleFocus(e)} classNames("items", "selectAllLine", displayAsDropdown ? isOpen ? "":"notVisible" :'')
|
176
|
+
/>
|
177
|
+
</div>
|
178
|
+
</div>
|
179
|
+
|
180
|
+
<div className={ classNames("items", "selectAllLine", displayAsDropdown ? "notVisible" :'') }>
|
181
|
+
{checkboxSelectAll}
|
182
|
+
</div>
|
183
|
+
|
184
|
+
|
185
|
+
<div className= { displayAsDropdown ? isOpen ? "itemsListScrollDropDown":"itemsListScrollDropDown notVisible" :'itemsListScroll' }>
|
186
|
+
|
187
|
+
<div className={ classNames("items", "selectAllLine", displayAsDropdown ? isOpen ? "":"notVisible" :'notVisible') }>
|
188
|
+
{checkboxSelectAll}
|
189
|
+
</div>
|
190
|
+
|
191
|
+
<div className={ displayAsDropdown ? optionsMyState.length == 0 ? "itemsListScroll noItemsToList":"itemsListScroll" : optionsMyState.length == 0 ? "noItemsToList inheritHeight":"" }>
|
192
|
+
{ optionsMyState.length == 0? 'No Items...':'' }
|
193
|
+
{
|
194
|
+
optionsMyState.map(( (item, index) => (
|
195
|
+
<div key={'chd01-'+item.id}
|
196
|
+
className={ classNames("items", selectedItemsMyState.some((itemSelected) => itemSelected.id === item.id)? "paintGray" : "paintWhite" )}>
|
197
|
+
|
198
|
+
<label key={'chd02-'+item.id} className={ classNames("itemlabel", item.disabled?"itemlabeldisabled":"")}>
|
199
|
+
|
200
|
+
<input key={'chd03-'+item.id}
|
201
|
+
id={item.id}
|
202
|
+
className="notVisible"
|
203
|
+
type="checkbox"
|
204
|
+
checked={ selectedItemsMyState.some((itemSelected) => itemSelected.id === item.id)==true? true : "" }
|
205
|
+
onChange={(e) => handleChangeIndividualCheck(e, item.label, item.disabled, item.data) }
|
206
|
+
disabled={item.disabled}
|
207
|
+
/>
|
208
|
+
<span className="checkbox-custom"></span>
|
209
|
+
|
210
|
+
{item.label} </label>
|
211
|
+
</div>
|
212
|
+
) ))
|
213
|
+
}
|
214
|
+
</div>
|
215
|
+
</div>
|
216
|
+
</div>
|
217
|
+
|
218
|
+
{ displayAsDropdown ? '' :
|
219
|
+
<div id="box2" className="box" style={{backgroundColor:'white'}}>
|
220
|
+
<div className='firstline'>
|
221
|
+
<div className='rightDivs' >{selectedItemsMyState.length>0?selectedItemsMyState.length:'None'} Selected</div>
|
222
|
+
<div className='rightDivs'> <a href="#" onClick={handleClickToClearAll} className='link_clear'>Clear All</a> </div>
|
223
|
+
</div>
|
224
|
+
<div className={ classNames("itemsListScrollRight", selectedItemsMyState.length==0?"noItemsToList":"")}>
|
225
|
+
{ selectedItemsMyState.length == 0? 'No Items...':'' }
|
226
|
+
{
|
227
|
+
selectedItemsMyState.map(item => ({
|
228
|
+
...item,
|
229
|
+
sortOrder: optionsSortMyState.find(option => option.id == item.id).sortOrder
|
230
|
+
})).sort((a,b) => a.sortOrder - b.sortOrder).map(( (items) => (
|
231
|
+
<div key={'chd04-'+items.id} className={ classNames("items", "delete-div")} onClick={()=>handleClickToRemoveItem(items.id)} >
|
232
|
+
<label key={'chd02-'+items.id} className={ classNames("itemlabel", items.disabled?"itemlabeldisabled":"")}>{items.label}</label>
|
233
|
+
{items.disabled?"":<button key={'chd05-'+items.id} type="button" className='buttonDelete'>x</button>}
|
234
|
+
</div>
|
235
|
+
)))
|
236
|
+
}
|
237
|
+
</div>
|
238
|
+
</div>
|
239
|
+
}
|
240
|
+
</div>
|
241
|
+
)
|
242
|
+
};
|
243
|
+
|
244
|
+
MultiSelectBox.propTypes = {
|
245
|
+
id: PropTypes.string,
|
246
|
+
options: PropTypes.array,
|
247
|
+
selectedItems: PropTypes.array,
|
248
|
+
name: PropTypes.string,
|
249
|
+
value: PropTypes.any,
|
250
|
+
placeholder: PropTypes.string,
|
251
|
+
disabled: PropTypes.bool,
|
252
|
+
onChange: PropTypes.func,
|
253
|
+
//onClick: PropTypes.func,
|
254
|
+
onBlur: PropTypes.func,
|
255
|
+
onFocus: PropTypes.func,
|
256
|
+
autoFocus: PropTypes.any,
|
257
|
+
autoComplete: PropTypes.any,
|
258
|
+
displayAsDropdown: PropTypes.bool,
|
259
|
+
}
|
260
|
+
|
261
|
+
export default MultiSelectBox;
|