creates video voice memos from audio clips; with bluesky integration. trill.ptr.pet
at main 2.7 kB view raw
1import { type JSX, createContext, useContext } from 'solid-js' 2import { Dynamic } from 'solid-js/web' 3import { cx } from 'styled-system/css' 4import { isCssProperty, styled } from 'styled-system/jsx' 5import type { ElementType, StyledComponent } from 'styled-system/types' 6 7type Props = Record<string, unknown> 8type Recipe = { 9 (props?: Props): Props 10 splitVariantProps: (props: Props) => [Props, Props] 11} 12 13type Slot<R extends Recipe> = keyof ReturnType<R> 14type Options = { forwardProps?: string[] } 15 16const shouldForwardProp = (prop: string, variantKeys: string[], options: Options = {}) => 17 options.forwardProps?.includes(prop) || (!variantKeys.includes(prop) && !isCssProperty(prop)) 18 19export const createStyleContext = <R extends Recipe>(recipe: R) => { 20 const StyleContext = createContext<Record<Slot<R>, string> | null>(null) 21 22 const withRootProvider = <P extends {}>(Component: ElementType): ((props: P) => JSX.Element) => { 23 const StyledComponent = (props: P) => { 24 const [variantProps, localProps] = recipe.splitVariantProps(props) 25 const slotStyles = recipe(variantProps) as Record<Slot<R>, string> 26 27 return ( 28 <StyleContext.Provider value={slotStyles}> 29 <Component {...localProps} /> 30 </StyleContext.Provider> 31 ) 32 } 33 return StyledComponent 34 } 35 36 const withProvider = <P extends { class?: string }>( 37 Component: ElementType, 38 slot: Slot<R>, 39 options?: Options, 40 ): ((props: P) => JSX.Element) => { 41 const StyledComponent = styled( 42 Component, 43 {}, 44 { 45 shouldForwardProp: (prop, variantKeys) => shouldForwardProp(prop, variantKeys, options), 46 }, 47 ) as StyledComponent<ElementType> 48 49 return (props: P) => { 50 const [variantProps, localProps] = recipe.splitVariantProps(props) 51 const slotStyles = recipe(variantProps) as Record<Slot<R>, string> 52 53 return ( 54 <StyleContext.Provider value={slotStyles}> 55 <Dynamic 56 component={StyledComponent} 57 {...localProps} 58 class={cx(slotStyles?.[slot], props.class)} 59 /> 60 </StyleContext.Provider> 61 ) 62 } 63 } 64 65 const withContext = <P extends { class?: string }>( 66 Component: ElementType, 67 slot: Slot<R>, 68 ): ((props: P) => JSX.Element) => { 69 const StyledComponent = styled(Component) 70 71 const Foo = (props: P) => { 72 const slotStyles = useContext(StyleContext) 73 return ( 74 <Dynamic 75 component={StyledComponent} 76 {...props} 77 class={cx(slotStyles?.[slot], props.class)} 78 /> 79 ) 80 } 81 return Foo 82 } 83 84 return { 85 withRootProvider, 86 withProvider, 87 withContext, 88 } 89}