diff --git a/src/avatar.tsx b/src/avatar.tsx index a443c27..fd56c02 100644 --- a/src/avatar.tsx +++ b/src/avatar.tsx @@ -6,28 +6,22 @@ import { VStack, HStack } from "./stack" import { CodeExamples } from "./code" import { cn } from "./cn" -export type AvatarProps = { - src: string - alt?: string +export type AvatarProps = JSX.IntrinsicElements["img"] & { size?: number rounded?: boolean - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any } export const Avatar: FC = (props) => { - const { src, size = 32, rounded, class: className, style, id, ref, alt = "" } = props + const { src, size = 32, rounded, class: className, style, id, ref, alt = "", ...rest } = props const avatarStyle: JSX.CSSProperties = { width: `${size}px`, height: `${size}px`, borderRadius: rounded ? "9999px" : undefined, - ...style, + ...(style as JSX.CSSProperties), } - return {alt} + return {alt} } export const Test = () => { diff --git a/src/box.tsx b/src/box.tsx index 21c7560..6e93b5d 100644 --- a/src/box.tsx +++ b/src/box.tsx @@ -3,25 +3,23 @@ import type { FC, PropsWithChildren, JSX } from "hono/jsx" import { CodeExamples } from "./code" import { cn } from "./cn" -type BoxProps = PropsWithChildren & { +type BoxProps = JSX.IntrinsicElements["div"] & PropsWithChildren & { bg?: string color?: string p?: number - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any } -export const Box: FC = ({ children, bg, color, p, class: className, style, id, ref }) => { +export const Box: FC = (props) => { + const { children, bg, color, p, class: className, style, id, ref, ...rest } = props + const boxStyle: JSX.CSSProperties = { backgroundColor: bg, color: color, padding: p ? `${p}px` : undefined, - ...style, + ...(style as JSX.CSSProperties), } - return
{children}
+ return
{children}
} // Common demo box colors diff --git a/src/cn.ts b/src/cn.ts index 4db6805..1069c58 100644 --- a/src/cn.ts +++ b/src/cn.ts @@ -6,6 +6,6 @@ * cn('base-class', isActive && 'active', 'another-class') // => "base-class active another-class" * cn('foo', false, 'bar', null, undefined) // => "foo bar" */ -export function cn(...classes: (string | undefined | null | false)[]): string { - return classes.filter(Boolean).join(" "); +export function cn(...classes: (string | Promise | undefined | null | false)[]): string { + return classes.filter((c): c is string => typeof c === "string").join(" "); } diff --git a/src/divider.tsx b/src/divider.tsx index 30dfe5e..5e0848d 100644 --- a/src/divider.tsx +++ b/src/divider.tsx @@ -6,19 +6,16 @@ import { VStack } from "./stack" import { CodeExamples } from "./code" import { cn } from "./cn" -type DividerProps = PropsWithChildren & { - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any -} +type DividerProps = JSX.IntrinsicElements["div"] & PropsWithChildren + +export const Divider: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props -export const Divider: FC = ({ children, class: className, style, id, ref }) => { const containerStyle: JSX.CSSProperties = { display: "flex", alignItems: "center", margin: "16px 0", - ...style, + ...(style as JSX.CSSProperties), } const lineStyle: JSX.CSSProperties = { @@ -34,7 +31,7 @@ export const Divider: FC = ({ children, class: className, style, i } return ( -
+
{children && ( <> diff --git a/src/grid.tsx b/src/grid.tsx index 1fef6b0..59e17b7 100644 --- a/src/grid.tsx +++ b/src/grid.tsx @@ -8,21 +8,17 @@ import { H2, H3 } from "./text" import { CodeExamples } from "./code" import { cn } from "./cn" -type GridProps = PropsWithChildren & { +type GridCols = number | { sm?: number; md?: number; lg?: number; xl?: number } + +type GridProps = JSX.IntrinsicElements["div"] & PropsWithChildren & { cols?: GridCols gap?: TailwindSize v?: keyof typeof alignItemsMap h?: keyof typeof justifyItemsMap - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any } -type GridCols = number | { sm?: number; md?: number; lg?: number; xl?: number } - export const Grid: FC = (props) => { - const { cols = 2, gap = 4, v, h, class: className, style, id, ref, children } = props + const { cols = 2, gap = 4, v, h, class: className, style, id, ref, children, ...rest } = props const gapPx = gap * 4 @@ -42,10 +38,10 @@ export const Grid: FC = (props) => { const combinedStyles = { ...baseStyles, - ...style, + ...(style as JSX.CSSProperties), } - return
{children}
+ return
{children}
} function getColumnsValue(cols: GridCols): string { diff --git a/src/icon.tsx b/src/icon.tsx index 231e3af..0cad67f 100644 --- a/src/icon.tsx +++ b/src/icon.tsx @@ -10,22 +10,18 @@ import { cn } from "./cn" export type IconName = keyof typeof icons -type IconProps = { +type IconProps = JSX.IntrinsicElements["div"] & { name: IconName size?: number - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any } -type IconLinkProps = IconProps & { - href?: string - target?: string +type IconLinkProps = JSX.IntrinsicElements["a"] & { + name: IconName + size?: number } export const Icon: FC = (props) => { - const { name, size = 6, class: className, style, id, ref } = props + const { name, size = 6, class: className, style, id, ref, ...rest } = props const iconSvg = icons[name] @@ -39,7 +35,7 @@ export const Icon: FC = (props) => { flexShrink: "0", width: `${pixelSize}px`, height: `${pixelSize}px`, - ...style, + ...(style as JSX.CSSProperties), } // Modify the SVG string to include our custom attributes @@ -52,23 +48,23 @@ export const Icon: FC = (props) => { `` ) - return
+ return
} export const IconLink: FC = (props) => { - const { href = "#", target, class: className, style, id, ref, ...iconProps } = props + const { href = "#", target, class: className, style, id, ref, name, size, ...rest } = props const linkStyle: JSX.CSSProperties = { display: "inline-flex", alignItems: "center", justifyContent: "center", transition: "opacity 0.2s", - ...style, + ...(style as JSX.CSSProperties), } return ( - - + + ) } diff --git a/src/image.tsx b/src/image.tsx index 89565b2..3c2a1d2 100644 --- a/src/image.tsx +++ b/src/image.tsx @@ -7,27 +7,23 @@ import { Grid } from "./grid" import { CodeExamples } from "./code" import { cn } from "./cn" -export type ImageProps = { - src: string - alt?: string +export type ImageProps = JSX.IntrinsicElements["img"] & { width?: number height?: number objectFit?: "cover" | "contain" | "fill" | "none" | "scale-down" - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any } -export const Image: FC = ({ src, alt = "", width, height, objectFit, class: className, style, id, ref }) => { +export const Image: FC = (props) => { + const { src, alt = "", width, height, objectFit, class: className, style, id, ref, ...rest } = props + const imageStyle: JSX.CSSProperties = { width: width ? `${width}px` : undefined, height: height ? `${height}px` : undefined, objectFit: objectFit, - ...style, + ...(style as JSX.CSSProperties), } - return {alt} + return {alt} } export const Test = () => { diff --git a/src/section.tsx b/src/section.tsx index d07cd5f..02159c6 100644 --- a/src/section.tsx +++ b/src/section.tsx @@ -4,18 +4,16 @@ import { VStack } from "./stack" import type { TailwindSize } from "./types" import { CodeExamples } from "./code" -type SectionProps = PropsWithChildren & { +type SectionProps = JSX.IntrinsicElements["div"] & PropsWithChildren & { gap?: TailwindSize maxWidth?: string - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any } -export const Section: FC = ({ children, gap = 8, maxWidth, class: className, style, id, ref }) => { +export const Section: FC = (props) => { + const { children, gap = 8, maxWidth, class: className, style, id, ref, ...rest } = props + return ( - + {children} ) diff --git a/src/stack.tsx b/src/stack.tsx index 2b235fc..d683e23 100644 --- a/src/stack.tsx +++ b/src/stack.tsx @@ -9,61 +9,66 @@ import { CodeExamples } from "./code" import { cn } from "./cn" export const VStack: FC = (props) => { + const { v, h, wrap, gap, maxWidth, rows, class: className, style, id, ref, children, ...rest } = props return ( - {props.children} + {children} ) } export const HStack: FC = (props) => { + const { h, v, wrap, gap, maxWidth, cols, class: className, style, id, ref, children, ...rest } = props return ( - {props.children} + {children} ) } const Stack: FC = (props) => { - const gapPx = props.gap ? props.gap * 4 : 0 + const { direction, mainAxis, crossAxis, wrap, gap, maxWidth, gridSizes, componentName, class: className, style, id, ref, children, ...rest } = props + const gapPx = gap ? gap * 4 : 0 // Use CSS Grid when gridSizes (cols/rows) is provided - if (props.gridSizes) { - const gridTemplate = props.gridSizes.map(size => `${size}fr`).join(" ") + if (gridSizes) { + const gridTemplate = gridSizes.map(size => `${size}fr`).join(" ") const gridStyles: JSX.CSSProperties = { display: "grid", gap: `${gapPx}px`, - maxWidth: props.maxWidth, + maxWidth: maxWidth, } - if (props.direction === "row") { + if (direction === "row") { gridStyles.gridTemplateColumns = gridTemplate } else { gridStyles.gridTemplateRows = gridTemplate @@ -71,35 +76,35 @@ const Stack: FC = (props) => { const combinedStyles = { ...gridStyles, - ...props.style, + ...(style as JSX.CSSProperties), } - return
{props.children}
+ return
{children}
} // Default flexbox behavior const baseStyles: JSX.CSSProperties = { display: "flex", - flexDirection: props.direction === "row" ? "row" : "column", - flexWrap: props.wrap ? "wrap" : "nowrap", + flexDirection: direction === "row" ? "row" : "column", + flexWrap: wrap ? "wrap" : "nowrap", gap: `${gapPx}px`, - maxWidth: props.maxWidth, + maxWidth: maxWidth, } - if (props.mainAxis) { - baseStyles.justifyContent = getJustifyContent(props.mainAxis) + if (mainAxis) { + baseStyles.justifyContent = getJustifyContent(mainAxis) } - if (props.crossAxis) { - baseStyles.alignItems = getAlignItems(props.crossAxis) + if (crossAxis) { + baseStyles.alignItems = getAlignItems(crossAxis) } const combinedStyles = { ...baseStyles, - ...props.style, + ...(style as JSX.CSSProperties), } - return
{props.children}
+ return
{children}
} export const Test = () => { @@ -284,7 +289,7 @@ export const Test = () => { type StackDirection = "row" | "col" -type StackProps = { +type StackProps = JSX.IntrinsicElements["div"] & { direction: StackDirection mainAxis?: string crossAxis?: string @@ -293,24 +298,15 @@ type StackProps = { maxWidth?: string gridSizes?: number[] // cols for row, rows for col componentName?: string // for data-howl attribute - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any - children?: any } type MainAxisOpts = "start" | "center" | "end" | "between" | "around" | "evenly" type CrossAxisOpts = "start" | "center" | "end" | "stretch" | "baseline" -type CommonStackProps = PropsWithChildren & { +type CommonStackProps = JSX.IntrinsicElements["div"] & PropsWithChildren & { wrap?: boolean gap?: TailwindSize maxWidth?: string - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any } type VStackProps = CommonStackProps & { diff --git a/src/text.tsx b/src/text.tsx index 0353a2f..bbf9d2d 100644 --- a/src/text.tsx +++ b/src/text.tsx @@ -3,40 +3,40 @@ import type { FC, PropsWithChildren, JSX } from "hono/jsx" import { CodeExamples } from "./code" import { cn } from "./cn" -type TextProps = PropsWithChildren & { - class?: string - style?: JSX.CSSProperties - id?: string - ref?: any +export const H1: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props + return

{children}

} -export const H1: FC = ({ children, class: className, style, id, ref }) => ( -

{children}

-) +export const H2: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props + return

{children}

+} -export const H2: FC = ({ children, class: className, style, id, ref }) => ( -

{children}

-) +export const H3: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props + return

{children}

+} -export const H3: FC = ({ children, class: className, style, id, ref }) => ( -

{children}

-) +export const H4: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props + return

{children}

+} -export const H4: FC = ({ children, class: className, style, id, ref }) => ( -

{children}

-) +export const H5: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props + return
{children}
+} -export const H5: FC = ({ children, class: className, style, id, ref }) => ( -
{children}
-) +export const Text: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props + return

{children}

+} -export const Text: FC = ({ children, class: className, style, id, ref }) => ( -

{children}

-) - -export const SmallText: FC = ({ children, class: className, style, id, ref }) => ( -

{children}

-) +export const SmallText: FC = (props) => { + const { children, class: className, style, id, ref, ...rest } = props + return

{children}

+} export const Test = () => { return (