@expofp/floorplan
Version:
Interactive floor plan library for expos and events
2 lines (1 loc) • 3.35 kB
JavaScript
import{Fragment as oe,jsx as c,jsxs as F}from"react/jsx-runtime";import"./Autocomplete.scss";import re from"classnames";import{useEffect as N,useId as le,useMemo as se,useRef as b,useState as v}from"react";import{createPortal as ce}from"react-dom";import ie from"../shared/hooks/useOnClickOutside";const ue=({placeholder:S,options:i,value:k,showClear:A=!1,onChange:T,renderTarget:B,noOptionsLabel:j,ariaLabel:P,clearLabel:K})=>{const E=B,f=b(null),a=b(null),m=b(null),d=b(null),x=le(),L=e=>`${x}-option-${e}`,M=e=>e.value,O=e=>e.label,V=(e,t)=>e.value===t.value&&e.exhibitorId===t.exhibitorId,R=e=>i.findIndex(t=>V(t,e)),z=e=>i.find(t=>V(t,e)),[r,w]=v(null),[n,l]=v(null),[o,u]=v(!1),[g,U]=v({top:0,left:0,width:0}),h=k?z(k):void 0,I=h?R(h):null,D=r!==null?r:h?O(h):"",s=se(()=>{if(!r)return[];const e=r.toLowerCase();return i.filter(t=>O(t).toLowerCase().includes(e))},[r,i]),p=()=>{if(f.current&&o){const e=f.current.getBoundingClientRect();U({top:e.bottom+window.scrollY+4,left:e.left+window.scrollX,width:e.width})}};N(()=>{if(o)return p(),window.addEventListener("scroll",p,!0),window.addEventListener("resize",p),()=>{window.removeEventListener("scroll",p,!0),window.removeEventListener("resize",p)}},[o]),N(()=>{if(n===null||!m.current)return;m.current.querySelectorAll("li")[n]?.scrollIntoView({block:"nearest"})},[n]),ie([f,m],()=>{u(!1)}),N(()=>()=>{d.current&&clearTimeout(d.current)},[]);const _=e=>{w(null),T?.(e)},q=e=>{_(e),l(null),u(!1),a.current?.blur()},$=(e=!1)=>{_(void 0),l(null),e&&a.current?.focus()},X=()=>{u(!0)},Y=()=>{d.current&&clearTimeout(d.current),d.current=setTimeout(()=>{w(null)},200)},G=()=>{if(!D&&n===null||r&&n===null)return;const e=s.length>0?s:i;if(n!==null&&e[n]){const t=e[n];_(t)}l(null),u(!1),a.current?.blur()},H=()=>{!o||n===0||n===null||l(n-1)},J=()=>{if(!o){l(I??0),u(!0);return}const e=s.length>0?s:i,t=n===null?0:n+1;t<e.length&&l(t)},Q=e=>{switch(e.key){case"Enter":G();break;case"ArrowUp":H();break;case"ArrowDown":J();break;case"Delete":$(!0);break;case"Escape":r?(w(null),l(I)):(e.preventDefault(),u(!1),a.current?.blur());break}},W=e=>{w(e.target.value),u(!0),l(null)},Z=()=>{const e=s.length>0?s:i;return r&&s.length===0?c("div",{className:"efp-autocomplete__empty",children:j}):c("ul",{role:"listbox",id:x,children:e.map((t,y)=>{const ee=y===n,C=s.length===0&&y===I,te=ee?"is-focus":C?"is-active":void 0;return c("li",{id:L(y),role:"option","aria-selected":C,className:te,onMouseDown:ne=>ne.preventDefault(),onClick:()=>q(t),children:O(t)},`${M(t)}-${t.exhibitorId??""}`)})})};return F(oe,{children:[c("div",{ref:f,className:re("efp-autocomplete",{"is-open":o,"with-clear":o&&A}),children:F("div",{className:"efp-autocomplete__inner",children:[c("input",{type:"search",className:"efp-autocomplete__input",role:"combobox","aria-label":P,"aria-autocomplete":"list","aria-expanded":o,"aria-controls":o?x:void 0,"aria-activedescendant":o&&n!==null?L(n):void 0,onChange:W,onFocus:X,onBlur:Y,onKeyDown:Q,value:D,placeholder:S,ref:a}),A&&o&&D&&c("button",{type:"button",className:"efp-autocomplete__clear","aria-label":K,onMouseDown:e=>{e.preventDefault(),$(!0)}})]})}),o&&E&&ce(c("div",{ref:m,className:"efp-autocomplete-options",style:{top:`${g.top}px`,left:`${g.left}px`,width:`${g.width}px`},children:c("div",{className:"efp-autocomplete-options__scroll",children:Z()})}),E)]})};export default ue;