
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
@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.
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.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.