@aiera-inc/react-slots
Version:
A simple utility for adding named slots to React components, inspired by the slot pattern in Vue.
2 lines (1 loc) • 1.13 kB
JavaScript
;import{jsx as u}from"react/jsx-runtime";import{useMemo as y}from"react";const d=Symbol.for("react.fragment");export function getSlots(e,r){const s=[],o={},l=new WeakMap;let a;e?Array.isArray(e)?a=e:a=[e]:a=[];for(const t in r)Array.isArray(r[t])?(l.set(r[t][0],t),o[t]=[]):l.set(r[t],t);return a.filter(t=>t).flatMap(t=>t.type===d?t.props?.children??[]:t).reduce((t,i)=>{const c=i.type;if(typeof c!="string"&&l.has(c)){const n=l.get(c);Array.isArray(r[n])?n in t.slots?Array.isArray(t.slots[n])?t.slots[n].push(i):t.slots[n]=[t.slots[n],i]:t.slots[n]=[i]:t.slots[n]=i}else t.children.push(i);return t},{children:s,slots:o})}function S(e){return Array.isArray(e)?e[0]:typeof e=="object"&&Object.keys(e).length===1?Object.values(e)[0]:e}export function withSlots(e,r){function s(o){const{slots:l,children:a}=y(()=>getSlots(o?.children,r),[o?.children]);return u(e,{...o,slots:l,children:a})}for(const o in r)s[o]=S(r[o]);return s}export function SlottedComponent(e){return function(r){return withSlots(r,e)}}export function useSlots(e,r){const{slots:s,children:o}=y(()=>getSlots(e,r),[e,r]);return{slots:s,children:o}}