
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
@diskette/composed-props
Advanced tools
A TypeScript-first React hooks library that enables component libraries to provide render props functionality with type inference and runtime validation.
A TypeScript-first React hooks library that enables component libraries to provide render props functionality with type inference and runtime validation.
npm install @diskette/composed-props
yarn add @diskette/composed-props
pnpm add @diskette/composed-props
useRenderProps hooks tailored to your component's needsComposableProp<T, V>The ComposableProp<T, V> type represents a prop that can be either:
V(state: T) => V that computes the value from component stateimport type { ComposableProp } from '@diskette/composed-props'
interface ButtonState {
isHovered: boolean
isPressed: boolean
}
interface ButtonProps {
// Must explicitly use ComposableProp for each prop
backgroundColor: ComposableProp<ButtonState, string>
opacity: ComposableProp<ButtonState, number>
// Non-composable props remain normal
onClick?: () => void
}
// Static usage
<Button backgroundColor="#007bff" opacity={1} />
// Dynamic usage
<Button
backgroundColor={({ isHovered, isPressed }) =>
isPressed ? '#0056b3' : isHovered ? '#0069d9' : '#007bff'
}
opacity={({ isHovered }) => isHovered ? 0.8 : 1}
/>
createUseRenderProps<Config>(config)Creates a type-safe useRenderProps hook based on a configuration schema. This is the primary tool for component library authors.
import { createUseRenderProps } from '@diskette/composed-props'
import type { ComposableProp } from '@diskette/composed-props'
// Define your component's state shapes
interface TabsState {
activeTab: string
hoveredTab: string | null
}
interface ThemeState {
theme: 'light' | 'dark'
}
// Props interface using ComposableProp explicitly
interface TabsProps {
className?: ComposableProp<TabsState, string>
style?: ComposableProp<ThemeState, CSSProperties> // Different state type!
'data-active': ComposableProp<TabsState, boolean> // Required prop
children?: ComposableProp<TabsState, ReactNode>
// Non-composable props
onTabChange?: (tab: string) => void
}
// Create the hook factory with validation
const useTabsRenderProps = createUseRenderProps({
className: { type: 'string' },
style: { type: (value): value is CSSProperties => typeof value === 'object' },
'data-active': { type: 'boolean', required: true },
children: { type: (value): value is ReactNode => true },
})
// Component library implementation
function Tabs(props: TabsProps) {
const [activeTab, setActiveTab] = useState('tab1')
const [hoveredTab, setHoveredTab] = useState<string | null>(null)
const [theme, setTheme] = useState<'light' | 'dark'>('light')
const tabsState: TabsState = { activeTab, hoveredTab }
const themeState: ThemeState = { theme }
const { composed, rest } = useTabsRenderProps(props)
// Option 1: Use individual functions
const className = composed.className?.(tabsState)
const style = composed.style?.(themeState)
return (
<div
className={className}
style={style}
data-active={composed['data-active']?.(tabsState)}
{...rest}
>
{composed.children?.(tabsState)}
</div>
)
// Option 2: Use props helper with multi-state support
// const resolvedProps = composed.props({
// className: tabsState, // TabsState for className
// style: themeState, // ThemeState for style (different state!)
// 'data-active': tabsState, // TabsState for data-active
// children: tabsState // TabsState for children
// })
//
// return <div {...resolvedProps} /> // rest is already included!
}
const { composed, rest } = useAccordionRenderProps(props, {
// Options for defaults and transforms
duration: {
default: ({ isExpanded }) => (isExpanded ? 300 : 200),
},
className: {
transform: (className, { isAnimating }) =>
isAnimating ? `${className} accordion--animating` : className,
},
})
// Approach 1: Individual functions (fine-grained control)
const className = composed.className?.(accordionState)
const style = composed.style?.(themeState)
const duration = composed.duration?.(accordionState)
return (
<div className={className} style={style} data-duration={duration} {...rest}>
{composed.children?.(accordionState)}
</div>
)
// Approach 2: Props helper
const resolvedProps = composed.props({
className: accordionState,
style: themeState, // Different state type for style!
duration: accordionState,
children: accordionState,
})
return <div {...resolvedProps} /> // rest already included
FAQs
A TypeScript-first React hooks library that enables component libraries to provide render props functionality with type inference and runtime validation.
The npm package @diskette/composed-props receives a total of 11 weekly downloads. As such, @diskette/composed-props popularity was classified as not popular.
We found that @diskette/composed-props demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.