feat: ✨ setup PandaCSS, ArkUI, ParkUI Preset and Lucide-React
parent
12820974c5
commit
a69f2c6932
@ -0,0 +1,30 @@
|
||||
import { createPreset } from "@park-ui/panda-preset";
|
||||
import { defineConfig } from "@pandacss/dev";
|
||||
|
||||
export default defineConfig({
|
||||
// Whether to use css reset
|
||||
preflight: true,
|
||||
|
||||
presets: [
|
||||
"@pandacss/preset-base",
|
||||
createPreset({
|
||||
accentColor: "red",
|
||||
}),
|
||||
],
|
||||
|
||||
// Where to look for your css declarations
|
||||
include: ["./src/**/*.{js,jsx,ts,tsx}", "./pages/**/*.{js,jsx,ts,tsx}"],
|
||||
|
||||
// Files to exclude
|
||||
exclude: [],
|
||||
|
||||
// Useful for theme customization
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
|
||||
// The output directory for your css system
|
||||
outdir: "styled-system",
|
||||
|
||||
jsxFramework: "react",
|
||||
});
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://park-ui.com/registry/latest/schema.json",
|
||||
"jsFramework": "react",
|
||||
"outputPath": "./src/components/ui"
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'@pandacss/dev/postcss': {},
|
||||
},
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
import { forwardRef } from 'react'
|
||||
import { Center, styled } from 'styled-system/jsx'
|
||||
import { Spinner } from './spinner'
|
||||
import { Button as StyledButton, type ButtonProps as StyledButtonProps } from './styled/button'
|
||||
|
||||
interface ButtonLoadingProps {
|
||||
loading?: boolean
|
||||
loadingText?: React.ReactNode
|
||||
}
|
||||
|
||||
export interface ButtonProps extends StyledButtonProps, ButtonLoadingProps {}
|
||||
|
||||
export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
|
||||
const { loading, disabled, loadingText, children, ...rest } = props
|
||||
|
||||
const trulyDisabled = loading || disabled
|
||||
|
||||
return (
|
||||
<StyledButton disabled={trulyDisabled} ref={ref} {...rest}>
|
||||
{loading && !loadingText ? (
|
||||
<>
|
||||
<ButtonSpinner />
|
||||
<styled.span opacity={0}>{children}</styled.span>
|
||||
</>
|
||||
) : loadingText ? (
|
||||
loadingText
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</StyledButton>
|
||||
)
|
||||
})
|
||||
|
||||
Button.displayName = 'Button'
|
||||
|
||||
const ButtonSpinner = () => (
|
||||
<Center inline position="absolute" transform="translate(-50%, -50%)" top="50%" insetStart="50%">
|
||||
<Spinner colorPalette="gray" />
|
||||
</Center>
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
import { ark } from '@ark-ui/react/factory'
|
||||
import { styled } from 'styled-system/jsx'
|
||||
import { button } from 'styled-system/recipes'
|
||||
import type { ComponentProps } from 'styled-system/types'
|
||||
|
||||
export type ButtonProps = ComponentProps<typeof Button>
|
||||
export const Button = styled(ark.button, button)
|
@ -0,0 +1,95 @@
|
||||
import {
|
||||
type ElementType,
|
||||
type ForwardRefExoticComponent,
|
||||
type PropsWithoutRef,
|
||||
type RefAttributes,
|
||||
createContext,
|
||||
forwardRef,
|
||||
useContext,
|
||||
} from 'react'
|
||||
import { cx } from 'styled-system/css'
|
||||
import { type StyledComponent, isCssProperty, styled } from 'styled-system/jsx'
|
||||
|
||||
type Props = Record<string, unknown>
|
||||
type Recipe = {
|
||||
(props?: Props): Props
|
||||
splitVariantProps: (props: Props) => [Props, Props]
|
||||
}
|
||||
type Slot<R extends Recipe> = keyof ReturnType<R>
|
||||
type Options = { forwardProps?: string[] }
|
||||
|
||||
const shouldForwardProp = (prop: string, variantKeys: string[], options: Options = {}) =>
|
||||
options.forwardProps?.includes(prop) || (!variantKeys.includes(prop) && !isCssProperty(prop))
|
||||
|
||||
export const createStyleContext = <R extends Recipe>(recipe: R) => {
|
||||
const StyleContext = createContext<Record<Slot<R>, string> | null>(null)
|
||||
|
||||
const withRootProvider = <P extends {}>(Component: ElementType) => {
|
||||
const StyledComponent = (props: P) => {
|
||||
const [variantProps, otherProps] = recipe.splitVariantProps(props)
|
||||
const slotStyles = recipe(variantProps) as Record<Slot<R>, string>
|
||||
|
||||
return (
|
||||
<StyleContext.Provider value={slotStyles}>
|
||||
<Component {...otherProps} />
|
||||
</StyleContext.Provider>
|
||||
)
|
||||
}
|
||||
return StyledComponent
|
||||
}
|
||||
|
||||
const withProvider = <T, P extends { className?: string | undefined }>(
|
||||
Component: ElementType,
|
||||
slot: Slot<R>,
|
||||
options?: Options,
|
||||
): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>> => {
|
||||
const StyledComponent = styled(
|
||||
Component,
|
||||
{},
|
||||
{
|
||||
shouldForwardProp: (prop, variantKeys) => shouldForwardProp(prop, variantKeys, options),
|
||||
},
|
||||
) as StyledComponent<ElementType>
|
||||
const StyledSlotProvider = forwardRef<T, P>((props, ref) => {
|
||||
const [variantProps, otherProps] = recipe.splitVariantProps(props)
|
||||
const slotStyles = recipe(variantProps) as Record<Slot<R>, string>
|
||||
|
||||
return (
|
||||
<StyleContext.Provider value={slotStyles}>
|
||||
<StyledComponent
|
||||
{...otherProps}
|
||||
ref={ref}
|
||||
className={cx(slotStyles?.[slot], props.className)}
|
||||
/>
|
||||
</StyleContext.Provider>
|
||||
)
|
||||
})
|
||||
// @ts-expect-error
|
||||
StyledSlotProvider.displayName = Component.displayName || Component.name
|
||||
|
||||
return StyledSlotProvider
|
||||
}
|
||||
|
||||
const withContext = <T, P extends { className?: string | undefined }>(
|
||||
Component: ElementType,
|
||||
slot: Slot<R>,
|
||||
): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>> => {
|
||||
const StyledComponent = styled(Component)
|
||||
const StyledSlotComponent = forwardRef<T, P>((props, ref) => {
|
||||
const slotStyles = useContext(StyleContext)
|
||||
return (
|
||||
<StyledComponent {...props} ref={ref} className={cx(slotStyles?.[slot], props.className)} />
|
||||
)
|
||||
})
|
||||
// @ts-expect-error
|
||||
StyledSlotComponent.displayName = Component.displayName || Component.name
|
||||
|
||||
return StyledSlotComponent
|
||||
}
|
||||
|
||||
return {
|
||||
withRootProvider,
|
||||
withProvider,
|
||||
withContext,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue