import * as React from 'react'; import classNames from 'classnames'; import {generateId} from '../utils'; export type IconTypeType = | 'academic_cap' | 'achievement' | 'add_more' | 'ai' | 'all_questions' | 'answer_bubble' | 'answer' | 'answers' | 'apple' | 'archive_checked' | 'archive' | 'arrow_double_right' | 'arrow_down' | 'arrow_left' | 'arrow_right' | 'arrow_top_right' | 'arrow_up' | 'ask_bubble' | 'ask_parent_to_pay' | 'attachment' | 'autopublish' | 'bell_checked' | 'bell_outlined' | 'best_answer' | 'block' | 'bold' | 'brainly_oval' | 'brainly_parallelogram' | 'bulb_checked' | 'bulb_filled' | 'bulb' | 'bulleted_list' | 'calendar' | 'camera' | 'caret_down' | 'caret_up' | 'chapter' | 'chat' | 'check' | 'check_circle' | 'chevron_double_down' | 'chevron_double_right' | 'chevron_down' | 'chevron_left' | 'chevron_right' | 'chevron_up' | 'chevrons_horizontal' | 'circle' | 'clear' | 'clipboard' | 'clipboard_outlined' | 'close' | 'collapse' | 'comment_outlined' | 'comment' | 'counter' | 'credit_card' | 'crop' | 'crown_outlined' | 'crown' | 'cup' | 'cursor_select' | 'cyrillic' | 'discord' | 'document' | 'dot' | 'draw' | 'drawing_mode' | 'envelope' | 'equation' | 'eraser' | 'european' | 'exclamation_mark' | 'expand' | 'facebook' | 'filters' | 'forwad' | 'friend_add' | 'friend_checked' | 'friend_pending' | 'friend_remove' | 'friends' | 'fullscreen' | 'funnel' | 'ginny' | 'globe' | 'google' | 'graph' | 'greek' | 'heading' | 'heart_outlined' | 'heart' | 'highlight' | 'home' | 'how_to_scan' | 'image_library' | 'image' | 'influence' | 'info_outlined' | 'info' | 'instagram' | 'italic' | 'keyboard' | 'less' | 'line' | 'link' | 'linkedin' | 'lock_with_play' | 'logout' | 'math_scan' | 'medium' | 'megaphone' | 'menu' | 'message_new' | 'messages' | 'mic' | 'minimize' | 'mic_muted' | 'minus_in_circle_outlined' | 'money_transfer' | 'more' | 'multiselect_checked' | 'multiselect_unchecked' | 'notifications' | 'numbered_list' | 'open_in_new_tab' | 'options' | 'padlock_open' | 'padlock' | 'pause' | 'pdf' | 'pencil' | 'pi' | 'play' | 'plus' | 'points' | 'printer' | 'profile_settings' | 'profile_view' | 'profile' | 'question_alt' | 'question' | 'quote' | 'recent_questions_alt' | 'recent_questions' | 'rectangle' | 'reload' | 'report_flag_outlined' | 'report_flag' | 'rotate_90' | 'rotate' | 'search' | 'search_add' | 'seen' | 'send' | 'settings' | 'share' | 'shield' | 'sidebar_left' | 'sidebar_right' | 'smartphone' | 'sms' | 'spark' | 'sparks' | 'star_half_outlined' | 'star_half' | 'star_outlined' | 'star' | 'subtitle' | 'sup_sub' | 'symbols' | 'textbook' | 'thumb_down_outlined' | 'thumb_down' | 'thumb_up_outlined' | 'thumb_up' | 'title' | 'tiktok' | 'toughest_questions_alt' | 'toughest_questions' | 'trash' | 'triangle' | 'twitter' | 'underlined' | 'unseen' | 'upload' | 'user_block' | 'verified' | 'view_checked' | 'warning' | 'youtube' | 'gift'; export type IconColorType = | 'adaptive' | 'icon-black' | 'icon-white' | 'icon-blue-50' | 'icon-blue-60' | 'icon-indigo-50' | 'icon-indigo-60' | 'icon-green-50' | 'icon-green-60' | 'icon-yellow-50' | 'icon-yellow-60' | 'icon-red-50' | 'icon-red-60' | 'icon-gray-70' | 'icon-gray-60' | 'icon-gray-50' | 'icon-gray-40'; export type IconAsType = 'div' | 'span'; export type IconSizeType = 16 | 24 | 32 | 40 | 56 | 80 | 104; export const TYPE = { ACADEMIC_CAP: 'academic_cap', ACHIEVEMENT: 'achievement', ADD_MORE: 'add_more', AI: 'ai', ALL_QUESTIONS: 'all_questions', ANSWER_BUBBLE: 'answer_bubble', ANSWER: 'answer', ANSWERS: 'answers', APPLE: 'apple', ARCHIVE_CHECKED: 'archive_checked', ARCHIVE: 'archive', ARROW_DOUBLE_RIGHT: 'arrow_double_right', ARROW_DOWN: 'arrow_down', ARROW_LEFT: 'arrow_left', ARROW_RIGHT: 'arrow_right', ARROW_TOP_RIGHT: 'arrow_top_right', ARROW_UP: 'arrow_up', ASK_BUBBLE: 'ask_bubble', ASK_PARENT_TO_PAY: 'ask_parent_to_pay', ATTACHMENT: 'attachment', AUTOPUBLISH: 'autopublish', BELL_CHECKED: 'bell_checked', BELL_OUTLINED: 'bell_outlined', BEST_ANSWER: 'best_answer', BLOCK: 'block', BOLD: 'bold', BRAINLY_OVAL: 'brainly_oval', BRAINLY_PARALLELOGRAM: 'brainly_parallelogram', BULB_CHECKED: 'bulb_checked', BULB_FILLED: 'bulb_filled', BULB: 'bulb', BULLETED_LIST: 'bulleted_list', CALENDAR: 'calendar', CAMERA: 'camera', CARET_DOWN: 'caret_down', CARET_UP: 'caret_up', CHAPTER: 'chapter', CHECK: 'check', CHAT: 'chat', CHECK_CIRCLE: 'check_circle', CHEVRON_DOUBLE_DOWN: 'chevron_double_down', CHEVRON_DOUBLE_RIGHT: 'chevron_double_right', CHEVRON_DOWN: 'chevron_down', CHEVRON_LEFT: 'chevron_left', CHEVRON_RIGHT: 'chevron_right', CHEVRON_UP: 'chevron_up', CHEVRONS_HORIZONTAL: 'chevrons_horizontal', CIRCLE: 'circle', CLEAR: 'clear', CLIPBOARD: 'clipboard', CLIPBOARD_OUTLINED: 'clipboard_outlined', CLOSE: 'close', COLLAPSE: 'collapse', COMMENT_OUTLINED: 'comment_outlined', COMMENT: 'comment', COUNTER: 'counter', CREDIT_CARD: 'credit_card', CROP: 'crop', CROWN_OUTLINED: 'crown_outlined', CROWN: 'crown', CUP: 'cup', CURSOR_SELECT: 'cursor_select', CYRILLIC: 'cyrillic', DOCUMENT: 'document', DOT: 'dot', DISCORD: 'discord', DRAW: 'draw', DRAWING_MODE: 'drawing_mode', ENVELOPE: 'envelope', EQUATION: 'equation', ERASER: 'eraser', EUROPEAN: 'european', EXCLAMATION_MARK: 'exclamation_mark', EXPAND: 'expand', FACEBOOK: 'facebook', FILTERS: 'filters', FORWARD: 'forward', FRIEND_ADD: 'friend_add', FRIEND_CHECKED: 'friend_checked', FRIEND_PENDING: 'friend_pending', FRIEND_REMOVE: 'friend_remove', FRIENDS: 'friends', FULLSCREEN: 'fullscreen', FUNNEL: 'funnel', GINNY: 'ginny', GLOBE: 'globe', GOOGLE: 'google', GRAPH: 'graph', GREEK: 'greek', HEADING: 'heading', HEART_OUTLINED: 'heart_outlined', HEART: 'heart', HIGHLIGHT: 'highlight', HOME: 'home', HOW_TO_SCAN: 'how_to_scan', IMAGE_LIBRARY: 'image_library', IMAGE: 'image', INFLUENCE: 'influence', INFO_OUTLINED: 'info_outlined', INFO: 'info', INSTRAGRAM: 'instagram', ITALIC: 'italic', KEYBOARD: 'keyboard', LESS: 'less', LINE: 'line', LINK: 'link', LINKEDIN: 'linkedin', LOCK_WITH_PLAY: 'lock_with_play', LOGOUT: 'logout', MATH_SCAN: 'math_scan', MEDIUM: 'medium', MEGAPHONE: 'megaphone', MENU: 'menu', MESSAGE_NEW: 'message_new', MESSAGES: 'messages', MIC: 'mic', MINIMIZE: 'minimize', MIC_MUTED: 'mic_muted', MINUS_IN_CIRCLE_OUTLIEND: 'minus_in_circle_outlined', MONEY_TRANSFER: 'money_transfer', MORE: 'more', MULTISELECT_CHECKED: 'multiselect_checked', MULTISELECT_UNCHECKED: 'multiselect_unchecked', NOTIFICATIONS: 'notifications', NUMBERED_LIST: 'numbered_list', OPEN_IN_NEW_TAB: 'open_in_new_tab', OPTIONS: 'options', PADLOCK_OPEN: 'padlock_open', PADLOCK: 'padlock', PAUSE: 'pause', PDF: 'pdf', PENCIL: 'pencil', PI: 'pi', PLAY: 'play', PLUS: 'plus', POINTS: 'points', PRINTER: 'printer', PROFILE_SETTINGS: 'profile_settings', PROFILE_VIEW: 'profile_view', PROFILE: 'profile', QUESTION_ALT: 'question_alt', QUESTION: 'question', QUOTE: 'quote', RECENT_QUESTIONS_ALT: 'recent_questions_alt', RECENT_QUESTIONS: 'recent_questions', RECTANGLE: 'rectangle', RELOAD: 'reload', REPORT_FLAG_OUTLINED: 'report_flag_outlined', REPORT_FLAG: 'report_flag', ROTATE_90: 'rotate_90', ROTATE: 'rotate', SEARCH: 'search', SEARCH_ADD: 'search_add', SEEN: 'seen', SEND: 'send', SETTINGS: 'settings', SHARE: 'share', SHIELD: 'shield', SIDEBAR_LEFT: 'sidebar_left', SIDEBAR_RIGHT: 'sidebar_right', SMARTPHONE: 'smartphone', SMS: 'sms', SPARK: 'spark', SPARKS: 'sparks', STAR_HALF_OUTLINED: 'star_half_outlined', STAR_HALF: 'star_half', STAR_OUTLINED: 'star_outlined', STAR: 'star', SUBTITLE: 'subtitle', SUP_SUB: 'sup_sub', SYMBOLS: 'symbols', TEXTBOOK: 'textbook', THUMB_DOWN_OUTLINED: 'thumb_down_outlined', THUMB_DOWN: 'thumb_down', THUMB_UP_OUTLINED: 'thumb_up_outlined', THUMB_UP: 'thumb_up', TITLE: 'title', TIKTOK: 'tiktok', TOUGHEST_QUESTIONS_ALT: 'toughest_questions_alt', TOUGHEST_QUESTIONS: 'toughest_questions', TRASH: 'trash', TRIANGLE: 'triangle', TWITTER: 'twitter', UNDERLINED: 'underlined', UNSEEN: 'unseen', UPLOAD: 'upload', USER_BLOCK: 'user_block', VERIFIED: 'verified', VIEW_CHECKED: 'view_checked', WARNING: 'warning', YOUTUBE: 'youtube', GIFT: 'gift', } as const; export const ICON_COLOR = { ADAPTIVE: 'adaptive', 'icon-black': 'icon-black', 'icon-white': 'icon-white', 'icon-blue-50': 'icon-blue-50', 'icon-blue-60': 'icon-blue-60', 'icon-indigo-50': 'icon-indigo-50', 'icon-indigo-60': 'icon-indigo-60', 'icon-green-50': 'icon-green-50', 'icon-green-60': 'icon-green-60', 'icon-yellow-50': 'icon-yellow-50', 'icon-yellow-60': 'icon-yellow-60', 'icon-red-50': 'icon-red-50', 'icon-red-60': 'icon-red-60', 'icon-gray-70': 'icon-gray-70', 'icon-gray-60': 'icon-gray-60', 'icon-gray-50': 'icon-gray-50', 'icon-gray-40': 'icon-gray-40', } as const; export const ICON_TAG_TYPE = { DIV: 'div', SPAN: 'span', } as const; export const SIZE = [16, 24, 32, 40, 56, 80, 104]; export type IconPropsType = | ({ /** * Additional class names */ className?: string | null | undefined; /** * Icons colors example, see more in SG interactive * @example * @see color="adaptive" https://styleguide.brainly.com/latest/docs/interactive.html?color=adaptive#icons */ color?: IconColorType | null | undefined; /** * Icons size example, see more in SG interactive * @example * @see size="24" https://styleguide.brainly.com/latest/docs/interactive.html?size=24#icons */ size?: IconSizeType | null | undefined; /** * Icons types example, see more in SG interactive * @example * @see type="heart" https://styleguide.brainly.com/latest/docs/interactive.html?type=heart#icons */ type: IconTypeType; /** * Option to change tag to span, which allows correct HTML structure * @example */ as?: IconAsType; /** * An accessible, short-text description; defaults to `type` */ title?: string; /** * An accessible, long-text description */ description?: string; } & Omit< React.AllHTMLAttributes, 'className' | 'color' | 'size' | 'type' | 'as' | 'title' | 'description' >) | ({ /** * Children to be rendered inside Icon */ children: React.ReactNode; /** * Additional class names */ className?: string | null | undefined; /** * Icons colors example, see more in SG interactive * @example * @see color="adaptive" https://styleguide.brainly.com/latest/docs/interactive.html?color=adaptive#icons */ color?: IconColorType | null | undefined; /** * Icons size example, see more in SG interactive * @example * @see size="24" https://styleguide.brainly.com/latest/docs/interactive.html?size=24#icons */ size?: IconSizeType | null | undefined; /** * Option to change tag to span, which allows correct HTML structure * @example */ as?: IconAsType; /** * An accessible, short-text description; defaults to `type` */ title?: string; /** * An accessible, long-text description */ description?: string; } & Omit< React.AllHTMLAttributes, | 'children' | 'className' | 'color' | 'size' | 'as' | 'title' | 'description' >); function generateIdSuffix(type: string) { return `${type}-${generateId()}`; } const Icon = ({ color = ICON_COLOR['icon-white'], size = 24, type, children, as = 'div', className, title, description, ...props }: IconPropsType) => { const iconClass = classNames( 'sg-icon', { [`sg-icon--${String(color)}`]: color, [`sg-icon--x${String(size)}`]: size, }, className ); const iconType = `#icon-${type}`; const Tag = as; // @ts-ignore TS2345 const idSuffix = generateIdSuffix(type); const titleId = `title-${idSuffix}`; const defaultTitle = String(type).replace(/_/g, ' '); const descId = `desc-${idSuffix}`; const labelledBy = description ? `${titleId} ${descId}` : titleId; const ariaLabel = type ? undefined : [title, description].filter(Boolean).join(', '); // suppressHydrationWarning is used until 'useId' hook is available return ( {type ? ( ' {...{ ...(React.version.startsWith('18') && { suppressHydrationWarning: true, }), }} > ' {...{ ...(React.version.startsWith('18') && { suppressHydrationWarning: true, }), }} > {title || defaultTitle} {description && {description}} ) : ( children )} ); }; export default Icon;