Slot
tetra-ui/slotFreeComponent
A utility component that allows merging props onto an optional child component.
Live preview
live · rendered by the registry
Rendered by tetra-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://tetra-ui.com/r/slot.jsonSource
1import { Children, cloneElement, isValidElement } from "react";2import type { Pressable as RNPressable, View as RNView } from "react-native";3import { mergeRefs } from "@/lib/utils";45// Constants6const HANDLER_REGEX = /^on[A-Z]/;78// Types9type AnyProps = Record<string, unknown>;1011// Components12const View = ({13 ref,14 children,15 ...viewProps16}: React.ComponentPropsWithRef<typeof RNView>) => {17 const child = Children.only(children) as React.ReactElement<18 React.ComponentPropsWithRef<typeof RNView>19 >;2021 if (!isValidElement(child)) {22 console.warn("View expects a single React element as children");23 return null;24 }2526 const childRef = "ref" in child ? child.ref : undefined;27 const mergedRef = childRef28 ? mergeRefs(ref, childRef as React.Ref<RNView>)29 : ref;3031 return cloneElement(child, {32 ...mergeProps(viewProps, child.props as AnyProps),33 ref: mergedRef,34 });35};3637const Pressable = ({38 ref,39 children,40 ...pressableProps41}: React.ComponentPropsWithRef<typeof RNPressable>) => {42 const child = Children.only(children) as React.ReactElement<43 React.ComponentProps<typeof RNPressable>44 >;4546 if (!isValidElement(child)) {47 console.warn("Pressable expects a single React element as children");48 return null;49 }5051 const childRef = "ref" in child ? child.ref : undefined;52 const mergedRef = childRef53 ? mergeRefs(ref, childRef as React.Ref<RNView>)54 : ref;5556 return cloneElement(child, {57 ...mergeProps(pressableProps, child.props as AnyProps),58 ref: mergedRef,59 });60};6162// Utils63function mergeHandler(64 slotPropValue: unknown,65 childPropValue: unknown66): ((...args: unknown[]) => unknown) | unknown {67 if (68 slotPropValue &&69 childPropValue &&70 typeof childPropValue === "function" &&71 typeof slotPropValue === "function"72 ) {73 return (...args: unknown[]) => {74 const result = childPropValue(...args);75 slotPropValue(...args);76 return result;77 };78 }79 return slotPropValue || childPropValue;80}8182function mergeStyle(slotPropValue: unknown, childPropValue: unknown) {83 return [slotPropValue, childPropValue];84}8586function mergeClassName(slotPropValue: unknown, childPropValue: unknown) {87 return [slotPropValue, childPropValue].filter(Boolean).join(" ");88}8990function mergeProps(slotProps: AnyProps, childProps: AnyProps) {91 // all child props should override92 const overrideProps = { ...childProps };9394 for (const propName in childProps) {95 if (!Object.hasOwn(childProps, propName)) {96// … truncated
Files it writes
More from tetra-ui
All 41 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | tetra-ui | Components | Free | 1 dep | |
| Action Inputaction-input | tetra-ui | Components | Free | no deps | |
| Alertalert | tetra-ui | Components | Free | no deps | |
| Avataravatar | tetra-ui | Components | Free | no deps | |
| Badgebadge | tetra-ui | Components | Free | no deps | |
| Bottom Sheetbottom-sheet | tetra-ui | Components | Free | 4 deps · 7 files | |
| Buttonbutton | tetra-ui | Components | Free | no deps | |
| Cardcard | tetra-ui | Components | Free | no deps |
