UNPKG

@visa/nova-react

Version:

Visa Product Design System Nova React library

18 lines (17 loc) 2.05 kB
/** * Copyright (c) 2025 Visa, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **/ import{useRef as e,useState as t,useCallback as r,useEffect as l}from"react";const n={autoSelect:!1,defaultSelected:-1},a=a=>{const{defaultSelected:o,...c}={...n,...a},u=e([]),s=e(null),[i,d]=t(Array.isArray(o)?o.length?o[0]:-1:o),[f,S]=t([]),[b,m]=t(o),x=Array.isArray(b),y=-1===i?0:f.indexOf(i),p=f.length,g=p-1,w=c?.ref||u,A=r((e=>x?b.includes(e):b===e),[x,b]),h=r((e=>{m(x?t=>A(e)?t.filter((t=>t!==e)):[...t,e]:A(e)?-1:e),d(e)}),[A,x]);return l((()=>{if(x&&c.autoSelect)throw new Error("ERROR useListbox: autoSelect is not compatible with multi select listbox, try removing {autoSelect: true} or set autoSelect to false, or make only one element in the listbox selected by default")}),[c,x]),l((()=>{S(w.current?.map(((e,t)=>(!e?.ariaDisabled||"false"===e?.ariaDisabled)&&t)).filter((e=>!1!==e)))}),[w]),{isIndexSelected:A,getTabIndex:(e,t=!1)=>(t||null!==s.current||(s.current=e),x?i===e||-1===i&&s.current===e?0:-1:b===e||-1===b&&s.current===e?0:-1),onKeyNavigation:e=>{const t=e.key;let r=null;if("ArrowDown"===t?r=(y+1)%p:"ArrowUp"===t?r=y-1<0?g:y-1:"End"===t?r=g:"Home"===t&&(r=0),"Enter"!==t&&" "!==t||h(f[y]),"Tab"===t&&d(x?f[y]:b),w.current&&null!==r&&p){e.preventDefault();const t=f[r];c.autoSelect&&m(t),d(t),w.current[t]?.focus()}},ref:w,selectedIndex:b,selectedIndices:b,toggleIndexSelected:h}};a.displayName="useListbox",a.defaultProps={autoSelect:!1,defaultSelected:-1};export{a as default,a as useListbox};