@loke/ui
Version:
2 lines (1 loc) • 2.41 kB
JavaScript
import{useComposedRefs}from"@loke/ui/compose-refs";import{createContextScope}from"@loke/ui/context";import{createSlot}from"@loke/ui/slot";import React from"react";import{jsx}from"react/jsx-runtime";function createCollection(name){let PROVIDER_NAME=`${name}CollectionProvider`,[createCollectionContext,createCollectionScope]=createContextScope(PROVIDER_NAME),[CollectionProviderImpl,useCollectionContext]=createCollectionContext(PROVIDER_NAME,{collectionRef:{current:null},itemMap:new Map}),CollectionProvider=(props)=>{let{scope,children}=props,ref=React.useRef(null),itemMap=React.useRef(new Map).current;return jsx(CollectionProviderImpl,{collectionRef:ref,itemMap,scope,children})};CollectionProvider.displayName=PROVIDER_NAME;let COLLECTION_SLOT_NAME=`${name}CollectionSlot`,CollectionSlotImpl=createSlot(COLLECTION_SLOT_NAME),CollectionSlot=React.forwardRef((props,forwardedRef)=>{let{scope,children}=props,context=useCollectionContext(COLLECTION_SLOT_NAME,scope),composedRefs=useComposedRefs(forwardedRef,context.collectionRef);return jsx(CollectionSlotImpl,{ref:composedRefs,children})});CollectionSlot.displayName=COLLECTION_SLOT_NAME;let ITEM_SLOT_NAME=`${name}CollectionItemSlot`,ITEM_DATA_ATTR="data-squared-collection-item",CollectionItemSlotImpl=createSlot(ITEM_SLOT_NAME),CollectionItemSlot=React.forwardRef((props,forwardedRef)=>{let{scope,children,...itemData}=props,ref=React.useRef(null),composedRefs=useComposedRefs(forwardedRef,ref),context=useCollectionContext(ITEM_SLOT_NAME,scope);return React.useEffect(()=>{return context.itemMap.set(ref,{ref,...itemData}),()=>{context.itemMap.delete(ref)}}),jsx(CollectionItemSlotImpl,{...{[ITEM_DATA_ATTR]:""},ref:composedRefs,children})});CollectionItemSlot.displayName=ITEM_SLOT_NAME;function useCollection(scope){let context=useCollectionContext(`${name}CollectionConsumer`,scope);return React.useCallback(()=>{let collectionNode=context.collectionRef.current;if(!collectionNode)return[];let orderedNodes=Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`));return Array.from(context.itemMap.values()).sort((a,b)=>{if(!(a.ref.current&&b.ref.current))return 0;return orderedNodes.indexOf(a.ref.current)-orderedNodes.indexOf(b.ref.current)})},[context.collectionRef,context.itemMap])}return[{ItemSlot:CollectionItemSlot,Provider:CollectionProvider,Slot:CollectionSlot},useCollection,createCollectionScope]}export{createCollection};