UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 12.2 kB
{"version":3,"file":"badge.cjs","sources":["../../../../../src/components/ui/badge/badge.tsx"],"sourcesContent":["import { useTheme } from \"@/theme/context\";\nimport { type StyledProps, getColorVariant } from \"@/theme/styled\";\nimport { css } from \"@emotion/react\";\nimport styled from \"@emotion/styled\";\nimport React from \"react\";\n\nexport interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {\n /** Badge variant */\n variant?: \"solid\" | \"flat\" | \"bordered\" | \"shadow\" | \"dot\";\n /** Badge color theme */\n color?: \"primary\" | \"secondary\" | \"success\" | \"warning\" | \"danger\";\n /** Badge size */\n size?: \"sm\" | \"md\" | \"lg\";\n /** Badge content */\n content?: React.ReactNode | number | string;\n /** Maximum count to display (shows count+ when exceeded) */\n max?: number;\n /** Show badge as dot without content */\n isDot?: boolean;\n /** Hide badge when content is 0 or empty */\n showZero?: boolean;\n /** Badge placement relative to children */\n placement?: \"top-right\" | \"top-left\" | \"bottom-right\" | \"bottom-left\";\n /** Disable badge */\n isDisabled?: boolean;\n /** Badge shape */\n shape?: \"rectangle\" | \"circle\";\n /** Custom class name */\n className?: string;\n /** Custom styles */\n css?: any;\n /** Children to wrap with badge */\n children?: React.ReactNode;\n}\n\ntype StyledBadgeProps = StyledProps<BadgeProps>;\n\nconst getBadgeVariantStyles = (props: StyledBadgeProps) => {\n const { theme, variant = \"solid\", color = \"primary\", isDisabled } = props;\n const baseColor = getColorVariant(theme, color, 500);\n const lightColor = getColorVariant(theme, color, 50);\n const darkColor = getColorVariant(theme, color, 700);\n\n if (isDisabled) {\n return css`\n opacity: 0.5;\n cursor: not-allowed;\n `;\n }\n\n switch (variant) {\n case \"solid\":\n return css`\n background-color: ${baseColor};\n color: ${theme.colors.text.inverse};\n border: 1px solid transparent;\n `;\n\n case \"flat\":\n return css`\n background-color: ${getColorVariant(theme, color, 100)};\n color: ${baseColor};\n border: 1px solid transparent;\n `;\n\n case \"bordered\":\n return css`\n background-color: ${theme.colors.background.primary};\n color: ${baseColor};\n border: 1px solid ${baseColor};\n `;\n\n case \"shadow\":\n return css`\n background-color: ${baseColor};\n color: ${theme.colors.text.inverse};\n border: 1px solid transparent;\n box-shadow: ${theme.shadows.sm};\n `;\n\n case \"dot\":\n return css`\n background-color: ${baseColor};\n border: 2px solid ${theme.colors.background.primary};\n width: 8px;\n height: 8px;\n padding: 0;\n min-width: 8px;\n `;\n\n default:\n return css``;\n }\n};\n\nconst getBadgeSizeStyles = (props: StyledBadgeProps) => {\n const { theme, size = \"md\", variant, shape = \"rectangle\" } = props;\n\n if (variant === \"dot\") {\n switch (size) {\n case \"sm\":\n return css`\n width: 6px;\n height: 6px;\n min-width: 6px;\n `;\n case \"md\":\n return css`\n width: 8px;\n height: 8px;\n min-width: 8px;\n `;\n case \"lg\":\n return css`\n width: 10px;\n height: 10px;\n min-width: 10px;\n `;\n }\n }\n\n const isCircle = shape === \"circle\";\n\n switch (size) {\n case \"sm\":\n return css`\n min-width: ${isCircle ? theme.spacing[4] : theme.spacing[4]};\n height: ${theme.spacing[4]};\n padding: ${isCircle ? \"0\" : `0 ${theme.spacing[1]}`};\n font-size: ${theme.fontSizes.xs};\n `;\n case \"md\":\n return css`\n min-width: ${isCircle ? theme.spacing[5] : theme.spacing[5]};\n height: ${theme.spacing[5]};\n padding: ${isCircle ? \"0\" : `0 ${theme.spacing[2]}`};\n font-size: ${theme.fontSizes.xs};\n `;\n case \"lg\":\n return css`\n min-width: ${isCircle ? theme.spacing[6] : theme.spacing[6]};\n height: ${theme.spacing[6]};\n padding: ${isCircle ? \"0\" : `0 ${theme.spacing[2]}`};\n font-size: ${theme.fontSizes.sm};\n `;\n default:\n return css``;\n }\n};\n\nconst getBadgeShapeStyles = (props: StyledBadgeProps) => {\n const { theme, shape = \"rectangle\", variant } = props;\n\n if (variant === \"dot\") {\n return css`border-radius: ${theme.borderRadius.full};`;\n }\n\n switch (shape) {\n case \"circle\":\n return css`border-radius: ${theme.borderRadius.full};`;\n case \"rectangle\":\n return css`border-radius: ${theme.borderRadius.sm};`;\n default:\n return css`border-radius: ${theme.borderRadius.sm};`;\n }\n};\n\nconst StyledBadge = styled.span<StyledBadgeProps>`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-family: inherit;\n font-weight: ${(props) => props.theme.fontWeights.medium};\n line-height: ${(props) => props.theme.lineHeights.tight};\n white-space: nowrap;\n user-select: none;\n transition: all ${(props) => props.theme.transitions.normal};\n box-sizing: border-box;\n\n ${getBadgeVariantStyles}\n ${getBadgeSizeStyles}\n ${getBadgeShapeStyles}\n\n /* Custom CSS prop */\n ${(props) => props.css}\n`;\n\nconst BadgeWrapper = styled.span<{ placement: string }>`\n position: relative;\n display: inline-flex;\n\n ${StyledBadge} {\n position: absolute;\n z-index: ${(props) => props.theme.zIndex.docked};\n\n ${(props) => {\n switch (props.placement) {\n case \"top-right\":\n return css`\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n `;\n case \"top-left\":\n return css`\n top: 0;\n left: 0;\n transform: translate(-50%, -50%);\n `;\n case \"bottom-right\":\n return css`\n bottom: 0;\n right: 0;\n transform: translate(50%, 50%);\n `;\n case \"bottom-left\":\n return css`\n bottom: 0;\n left: 0;\n transform: translate(-50%, 50%);\n `;\n default:\n return css`\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n `;\n }\n }}\n }\n`;\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n (\n {\n children,\n content,\n variant = \"solid\",\n color = \"primary\",\n size = \"md\",\n max = 99,\n isDot = false,\n showZero = false,\n placement = \"top-right\",\n isDisabled = false,\n shape = \"rectangle\",\n className,\n css,\n ...props\n },\n ref,\n ) => {\n const { theme } = useTheme();\n\n // Determine if badge should be shown\n const shouldShowBadge = () => {\n if (isDot) return true;\n if (content === 0 || content === \"0\") return showZero;\n return content !== undefined && content !== null && content !== \"\";\n };\n\n // Format badge content\n const getBadgeContent = () => {\n if (isDot || variant === \"dot\") return null;\n\n if (typeof content === \"number\") {\n return content > max ? `${max}+` : content.toString();\n }\n\n return content;\n };\n\n const badgeProps = {\n ...props,\n variant: isDot ? \"dot\" : variant,\n color,\n size,\n shape: isDot ? \"circle\" : shape,\n isDisabled,\n className,\n css,\n };\n\n const badgeElement = shouldShowBadge() ? (\n <StyledBadge theme={theme} ref={ref} {...badgeProps}>\n {getBadgeContent()}\n </StyledBadge>\n ) : null;\n\n // If no children, return just the badge\n if (!children) {\n return badgeElement;\n }\n\n // If children exist, wrap them with positioned badge\n return (\n <BadgeWrapper theme={theme} placement={placement}>\n {children}\n {badgeElement}\n </BadgeWrapper>\n );\n },\n);\n\nBadge.displayName = \"Badge\";"],"names":["getBadgeVariantStyles","props","theme","variant","color","isDisabled","baseColor","getColorVariant","css","getBadgeSizeStyles","size","shape","isCircle","getBadgeShapeStyles","StyledBadge","styled","BadgeWrapper","Badge","React","children","content","max","isDot","showZero","placement","className","ref","useTheme","shouldShowBadge","getBadgeContent","badgeProps","badgeElement","jsx","jsxs"],"mappings":"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"}