Animate Slot
azemmur/primitives-slotFreeComponent
A slot component that allows you to use motion components with any element.
Install it
npx shadcn@latest add https://azemmur.raouf.codes/r/primitives-slot.jsonSource
1//Copyright (c) 2025 Elliot Sutton23'use client';45import { cn } from '@/lib/utils';6import { motion, isMotionComponent, type HTMLMotionProps } from 'motion/react';7import * as React from 'react';89type AnyProps = Record<string, unknown>;1011type DOMMotionProps<T extends HTMLElement = HTMLElement> = Omit<12 HTMLMotionProps<keyof HTMLElementTagNameMap>,13 'ref'14> & { ref?: React.Ref<T> };1516type WithAsChild<Base extends object> =17 | (Base & { asChild: true; children: React.ReactElement })18 | (Base & { asChild?: false | undefined });1920type SlotProps<T extends HTMLElement = HTMLElement> = {21 // eslint-disable-next-line @typescript-eslint/no-explicit-any22 children?: any;23} & DOMMotionProps<T>;2425function mergeRefs<T>(26 ...refs: (React.Ref<T> | undefined)[]27): React.RefCallback<T> {28 return (node) => {29 refs.forEach((ref) => {30 if (!ref) return;31 if (typeof ref === 'function') {32 ref(node);33 } else {34 (ref as React.RefObject<T | null>).current = node;35 }36 });37 };38}3940function mergeProps<T extends HTMLElement>(41 childProps: AnyProps,42 slotProps: DOMMotionProps<T>,43): AnyProps {44 const merged: AnyProps = { ...childProps, ...slotProps };4546 if (childProps.className || slotProps.className) {47 merged.className = cn(48 childProps.className as string,49 slotProps.className as string,50 );51 }5253 if (childProps.style || slotProps.style) {54 merged.style = {55 ...(childProps.style as React.CSSProperties),56 ...(slotProps.style as React.CSSProperties),57 };58 }5960 return merged;61}6263function Slot<T extends HTMLElement = HTMLElement>({64 children,65 ref,66 ...props67}: SlotProps<T>) {68 const isAlreadyMotion =69 typeof children.type === 'object' &&70 children.type !== null &&71 isMotionComponent(children.type);7273 const Base = React.useMemo(74 () =>75 isAlreadyMotion76 ? (children.type as React.ElementType)77 : motion.create(children.type as React.ElementType),78 [isAlreadyMotion, children.type],79 );8081 if (!React.isValidElement(children)) return null;8283 const { ref: childRef, ...childProps } = children.props as AnyProps;8485 const mergedProps = mergeProps(childProps, props);8687 return (88 <Base {...mergedProps} ref={mergeRefs(childRef as React.Ref<T>, ref)} />89 );90}9192export {93 Slot,94 type SlotProps,95 type WithAsChild,96 type DOMMotionProps,97 type AnyProps,98};
What it pulls in
npm packages
Files it writes
More from Azemmur
All 27 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Blur Imagecomponents-blur-image | Azemmur | Components | Free | 1 dep | |
| Buttoncomponents-button | Azemmur | Components | Free | 1 dep | |
| Floating Dockcomponents-floating-dock | Azemmur | Components | Free | 2 deps · 6 files | |
| Speed Dialcomponents-speed-dial | Azemmur | Components | Free | 2 deps · 7 files | |
| Tabscomponents-tabs | Azemmur | Components | Free | 2 deps · 9 files | |
| Theme Switchcomponents-theme-switch | Azemmur | Components | Free | 4 deps | |
| Timelinecomponents-timeline | Azemmur | Components | Free | 2 deps · 8 files | |
| Blur Image Demodemo-components-blur-image | Azemmur | Components | Free | no deps |
