Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
138 lines
4.0 KiB
TypeScript
138 lines
4.0 KiB
TypeScript
import type {
|
|
ConsumerButtonAlign,
|
|
ConsumerButtonFill,
|
|
ConsumerButtonRadius,
|
|
ConsumerButtonSize,
|
|
ResolvedConsumerButtonStyle,
|
|
} from '@/components/consumer/consumerButtonTypes'
|
|
import { cn } from '@/lib/cn'
|
|
|
|
/** xs/sm/md/lg/xl → px heights (Figma). */
|
|
export const CONSUMER_BUTTON_HEIGHT_PX: Record<ConsumerButtonSize, number> = {
|
|
xs: 40,
|
|
sm: 44,
|
|
md: 48,
|
|
lg: 52,
|
|
xl: 60,
|
|
}
|
|
|
|
const HEIGHT_CLASS: Record<ConsumerButtonSize, string> = {
|
|
xs: 'h-10 min-h-10',
|
|
sm: 'h-11 min-h-11',
|
|
md: 'h-12 min-h-12',
|
|
lg: 'h-[52px] min-h-[52px]',
|
|
xl: 'h-[60px] min-h-[60px]',
|
|
}
|
|
|
|
const ICON_ONLY_CLASS: Record<ConsumerButtonSize, string> = {
|
|
xs: 'h-10 w-10 min-h-10 min-w-10',
|
|
sm: 'h-11 w-11 min-h-11 min-w-11',
|
|
md: 'h-12 w-12 min-h-12 min-w-12',
|
|
lg: 'h-[52px] w-[52px] min-h-[52px] min-w-[52px]',
|
|
xl: 'h-[60px] w-[60px] min-h-[60px] min-w-[60px]',
|
|
}
|
|
|
|
const RADIUS_CLASS: Record<ConsumerButtonRadius, string> = {
|
|
full: 'rounded-full',
|
|
control: 'rounded-[10px]',
|
|
}
|
|
|
|
const FILL_CLASS: Record<ConsumerButtonFill, string> = {
|
|
orange: 'bg-primary hover:bg-primary-600 active:bg-primary-700',
|
|
navy: 'bg-tertiary-900 hover:bg-tertiary-800 active:bg-tertiary-900',
|
|
fourth: 'bg-fourth-900 hover:bg-fourth-700 active:bg-fourth-900',
|
|
fifth: 'bg-fifth-900 hover:bg-fifth-700 active:bg-fifth-900',
|
|
gray: 'bg-[#F5F5F5] hover:bg-secondary-40 active:bg-secondary-200',
|
|
none: 'bg-transparent',
|
|
}
|
|
|
|
const DEFAULT_TEXT_CLASS: Record<ConsumerButtonFill, string | undefined> = {
|
|
orange: 'text-white',
|
|
navy: 'text-white',
|
|
fourth: 'text-white',
|
|
fifth: 'text-white',
|
|
gray: 'text-consumer-text',
|
|
none: undefined,
|
|
}
|
|
|
|
const DEFAULT_SIZE: Record<'default' | 'icon', ConsumerButtonSize> = {
|
|
default: 'lg',
|
|
icon: 'sm',
|
|
}
|
|
|
|
function resolveTextColorClass(textColor: string | undefined, fill: ConsumerButtonFill): string | undefined {
|
|
if (!textColor) return DEFAULT_TEXT_CLASS[fill]
|
|
if (textColor === 'white') return 'text-white'
|
|
if (textColor.startsWith('text-') || textColor.startsWith('!text-')) return textColor
|
|
|
|
return undefined
|
|
}
|
|
|
|
function resolveTextColorStyle(textColor: string | undefined): string | undefined {
|
|
if (!textColor || textColor === 'white' || textColor.startsWith('text-') || textColor.startsWith('!text-')) {
|
|
return undefined
|
|
}
|
|
|
|
if (textColor.startsWith('#')) return textColor
|
|
|
|
return undefined
|
|
}
|
|
|
|
/** وقتی از بیرون `px-*` داده شده، padding افقی پیشفرض اعمال نمیشود. */
|
|
function hasHorizontalPaddingOverride(className?: string): boolean {
|
|
return className != null && /\b!?px-/.test(className)
|
|
}
|
|
|
|
function resolveHorizontalPaddingClass(iconOnly: boolean, className?: string): string | undefined {
|
|
if (hasHorizontalPaddingOverride(className)) return undefined
|
|
|
|
return iconOnly ? 'px-0' : 'px-4'
|
|
}
|
|
|
|
export function buildConsumerButtonStyle({
|
|
align = 'center',
|
|
className,
|
|
radius = 'full',
|
|
fill = 'orange',
|
|
fontSize = 14,
|
|
fullWidth = false,
|
|
iconOnly = false,
|
|
size,
|
|
textColor,
|
|
}: {
|
|
align?: ConsumerButtonAlign
|
|
className?: string
|
|
radius?: ConsumerButtonRadius
|
|
fill?: ConsumerButtonFill
|
|
fontSize?: number
|
|
fullWidth?: boolean
|
|
iconOnly?: boolean
|
|
size?: ConsumerButtonSize
|
|
textColor?: string
|
|
}): ResolvedConsumerButtonStyle {
|
|
const resolvedSize = size ?? (iconOnly ? DEFAULT_SIZE.icon : DEFAULT_SIZE.default)
|
|
const textClass = resolveTextColorClass(textColor, fill)
|
|
const inlineColor = resolveTextColorStyle(textColor)
|
|
|
|
return {
|
|
className: cn(
|
|
'consumer-focus-ring inline-flex shrink-0 items-center gap-2 font-medium transition-colors',
|
|
'disabled:pointer-events-none disabled:opacity-50',
|
|
resolveHorizontalPaddingClass(iconOnly, className),
|
|
iconOnly
|
|
? cn(ICON_ONLY_CLASS[resolvedSize], 'justify-center')
|
|
: cn(HEIGHT_CLASS[resolvedSize], align === 'center' ? 'justify-center' : 'justify-start'),
|
|
!iconOnly && 'min-w-0',
|
|
RADIUS_CLASS[radius],
|
|
FILL_CLASS[fill],
|
|
textClass,
|
|
fullWidth && 'w-full',
|
|
className
|
|
),
|
|
style: {
|
|
fontSize,
|
|
...(inlineColor ? { color: inlineColor } : {}),
|
|
},
|
|
}
|
|
}
|