nested-select-react
Version:
A flexible, accessible nested select component for React
3 lines (2 loc) • 6.78 kB
JavaScript
import*as e from"react";import t,{useRef as r,useState as n,useEffect as l,useCallback as a}from"react";const s=t=>e.createElement("svg",Object.assign({},t,{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,className:"lucide lucide-check"}),e.createElement("path",{d:"M20 6 9 17l-5-5"})),o=t=>e.createElement("svg",Object.assign({},t,{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,className:"lucide lucide-chevron-down"}),e.createElement("path",{d:"m6 9 6 6 6-6"})),c=t=>e.createElement("svg",Object.assign({},t,{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,className:"lucide lucide-chevron-left"}),e.createElement("path",{d:"m15 18-6-6 6-6"})),i=t=>e.createElement("svg",Object.assign({},t,{xmlns:"http://www.w3.org/2000/svg",width:24,height:24,fill:"none",stroke:"currentColor",strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,className:"lucide lucide-chevron-right"}),e.createElement("path",{d:"m9 18 6-6-6-6"}));"function"==typeof SuppressedError&&SuppressedError;const u=e=>{var{variant:r="default",size:n="md",children:l,className:a=""}=e,s=function(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var l=0;for(n=Object.getOwnPropertySymbols(e);l<n.length;l++)t.indexOf(n[l])<0&&Object.prototype.propertyIsEnumerable.call(e,n[l])&&(r[n[l]]=e[n[l]])}return r}(e,["variant","size","children","className"]);const o=`inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 ${{default:"bg-gray-100 text-gray-900 hover:bg-gray-200",primary:"bg-blue-600 text-white hover:bg-blue-700",ghost:"bg-transparent hover:bg-gray-100"}[r]} ${{sm:"h-8 px-3 text-xs",md:"h-10 px-4 text-sm",lg:"h-12 px-6 text-base"}[n]} ${a}`;return t.createElement("button",Object.assign({className:o},s),l)};function m({items:e,selectedItemId:m=null,onSelect:d,idKey:h="id",labelKey:g="name",childrenKey:f="children",placeholder:v="Select an item...",maxHeight:p="15rem",className:b="",dropdownClassName:x="",showSelectAll:w=!0,showBreadcrumb:y=!0,renderItem:E,renderTrigger:N,renderBreadcrumb:k,renderEmpty:j,disableItem:S,filterItems:O,searchPlaceholder:C="Search..."}){const L=r(null),I=r(null),[z,$]=n(!1),[B,P]=n([]),[W,H]=n(""),[K,T]=n(!1),A=B.length?B[B.length-1].id:null,[F,M]=n(null);l((()=>{if(null===m)return void M(null);const t=(e,r)=>{var n;for(const l of e){if(String(l[h])===String(r))return l;if(null===(n=l[f])||void 0===n?void 0:n.length){const e=t(l[f],r);if(e)return e}}return null},r=t(e,m);M(r)}),[m,e,h,f]);const q=a((()=>{if(!A)return e;const t=(e,r)=>{var n;for(const l of e){if(String(l[h])===String(r))return l[f]||[];if(null===(n=l[f])||void 0===n?void 0:n.length){const e=t(l[f],r);if(e.length)return e}}return[]};return t(e,A)}),[e,A,h,f]),D=a((()=>{let e=q();return W&&O?O(e,W):e}),[q,W,O]),G=a((e=>{var t,r;if(null==S?void 0:S(e))return;(null===(t=e[f])||void 0===t?void 0:t.length)>0?(P((t=>[...t,{id:e[h],label:e[g],parentId:A}])),K&&(null===(r=I.current)||void 0===r||r.focus())):(d(e,B),M(e),$(!1),H(""),T(!1))}),[d,h,g,f,S,A,K,B]),J=a((()=>{P((e=>e.slice(0,-1))),H("")}),[]),Q=a((()=>{$(!1),P([]),H(""),T(!1)}),[]),R=a((()=>{T(!K),K?H(""):setTimeout((()=>{var e;null===(e=I.current)||void 0===e||e.focus()}),0)}),[K]),U=a((()=>{if(A){const t=(e,r)=>{var n;for(const l of e){if(l[h]===r)return l;if(null===(n=l[f])||void 0===n?void 0:n.length){const e=t(l[f],r);if(e)return e}}return null},r=t(e,A);r&&(d(r,B),M(r),$(!1),H(""),T(!1))}}),[A,e,h,f,d,B]),V=a(((e,r,n)=>t.createElement("div",{className:"flex items-center justify-between w-full"},t.createElement("span",{className:"truncate"},e[g]),n?t.createElement(i,{className:"h-4 w-4 text-gray-500"}):r&&t.createElement(s,{className:"h-4 w-4 text-blue-500"}))),[g]),X=a(((e,r)=>t.createElement("div",{className:"flex items-center justify-between w-full"},t.createElement("span",{className:"truncate"},e?e[g]:r),t.createElement(o,{className:"h-4 w-4 text-gray-500"}))),[g]),Y=a((e=>t.createElement("div",{className:"flex items-center text-xs text-gray-500 truncate overflow-hidden"},e.map(((e,r)=>t.createElement(t.Fragment,{key:e.id},r>0&&t.createElement(i,{className:"h-3 w-3 mx-1 flex-shrink-0"}),t.createElement("span",{className:"truncate"},e.label)))))),[]),Z=a((()=>t.createElement("div",{className:"p-4 text-center text-sm text-gray-500"},"No items found")),[]);l((()=>{const e=e=>{L.current&&!L.current.contains(e.target)&&Q()};return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)}),[Q]);const _=D(),ee=0===_.length;return t.createElement("div",{className:`relative ${b}`,ref:L},t.createElement("button",{type:"button",onClick:()=>$(!z),className:"w-full px-3 py-2 text-sm bg-white border rounded-lg shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500","aria-expanded":z,"aria-haspopup":"listbox"},N?N(F,v):X(F,v)),z&&t.createElement("div",{className:`absolute z-50 w-full mt-1 bg-white rounded-lg shadow-lg border ${x}`,role:"listbox"},t.createElement("div",{className:"p-2 border-b flex items-center justify-between"},B.length>0?t.createElement("button",{type:"button",onClick:J,className:"flex items-center text-sm text-gray-600 hover:text-gray-900"},t.createElement(c,{className:"h-4 w-4 mr-1"}),"Back"):t.createElement("div",null),t.createElement(u,{type:"button",variant:"ghost",size:"sm",onClick:R,className:"text-xs"},K?"Hide Search":"Search")),K&&t.createElement("div",{className:"p-2 border-b"},t.createElement("input",{ref:I,type:"text",placeholder:C,value:W,onChange:e=>H(e.target.value),className:"w-full px-3 py-1 text-sm border rounded"})),y&&B.length>0&&t.createElement("div",{className:"px-3 py-2 border-b"},k?k(B):Y(B),w&&t.createElement(u,{type:"button",variant:"ghost",size:"sm",onClick:U,className:"mt-1 text-xs w-full"},"Select this level")),t.createElement("div",{className:"overflow-auto",style:{maxHeight:p}},ee?j?j():Z():_.map((e=>{var r;const n=(null==F?void 0:F[h])===e[h],l=null==S?void 0:S(e),a=Boolean(null===(r=e[f])||void 0===r?void 0:r.length);return t.createElement("button",{type:"button",key:e[h],onClick:()=>G(e),disabled:l,className:"w-full px-3 py-2 text-sm text-left "+(l?"opacity-50 cursor-not-allowed":n?"bg-blue-50 hover:bg-blue-100":"hover:bg-gray-50"),"aria-selected":n,role:"option"},E?E(e,n,a):V(e,n,a))})))))}export{m as NestedSelect};
//# sourceMappingURL=index.js.map