event.preventDefault()}\n onClick={() => {\n setIsLinkEditMode(false);\n }}\n />\n\n
event.preventDefault()}\n onClick={handleLinkSubmission}\n />\n
\n
\n {linkUrl}\n \n
event.preventDefault()}\n onClick={() => {\n setEditedLinkUrl(linkUrl);\n setIsLinkEditMode(true);\n }}\n />\n
event.preventDefault()}\n onClick={() => {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);\n }}\n />\n
\n )}\n
\n );\n}\n\nfunction useFloatingLinkEditorToolbar(\n editor: LexicalEditor,\n anchorElem: HTMLElement,\n isLinkEditMode: boolean,\n setIsLinkEditMode: Dispatch
,\n): JSX.Element | null {\n const [activeEditor, setActiveEditor] = useState(editor);\n const [isLink, setIsLink] = useState(false);\n\n useEffect(() => {\n function updateToolbar() {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const node = getSelectedNode(selection);\n const linkParent = $findMatchingParent(node, $isLinkNode);\n const autoLinkParent = $findMatchingParent(node, $isAutoLinkNode);\n // We don't want this menu to open for auto links.\n if (linkParent !== null && autoLinkParent === null) {\n setIsLink(true);\n } else {\n setIsLink(false);\n }\n }\n }\n return mergeRegister(\n editor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n updateToolbar();\n });\n }),\n editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n (_payload, newEditor) => {\n updateToolbar();\n setActiveEditor(newEditor);\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n ),\n editor.registerCommand(\n CLICK_COMMAND,\n payload => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const node = getSelectedNode(selection);\n const linkNode = $findMatchingParent(node, $isLinkNode);\n if ($isLinkNode(linkNode) && (payload.metaKey || payload.ctrlKey)) {\n window.open(linkNode.getURL(), '_blank');\n return true;\n }\n }\n return false;\n },\n COMMAND_PRIORITY_LOW,\n ),\n );\n }, [editor]);\n\n return createPortal(\n ,\n anchorElem,\n );\n}\n\nexport default function FloatingLinkEditorPlugin({\n anchorElem = document.body,\n isLinkEditMode,\n setIsLinkEditMode,\n}: {\n anchorElem?: HTMLElement;\n isLinkEditMode: boolean;\n setIsLinkEditMode: Dispatch;\n}): JSX.Element | null {\n const [editor] = useLexicalComposerContext();\n return useFloatingLinkEditorToolbar(\n editor,\n anchorElem,\n isLinkEditMode,\n setIsLinkEditMode,\n );\n}\n","import { Dispatch, useCallback, useEffect, useState } from 'react';\nimport { $isLinkNode, TOGGLE_LINK_COMMAND } from '@lexical/link';\nimport {\n $isListNode,\n INSERT_ORDERED_LIST_COMMAND,\n INSERT_UNORDERED_LIST_COMMAND,\n ListNode,\n REMOVE_LIST_COMMAND,\n} from '@lexical/list';\nimport { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';\nimport {\n $createHeadingNode,\n $isHeadingNode,\n HeadingTagType,\n} from '@lexical/rich-text';\nimport { $setBlocksType } from '@lexical/selection';\nimport { $isTableNode } from '@lexical/table';\nimport {\n $findMatchingParent,\n $getNearestNodeOfType,\n mergeRegister,\n} from '@lexical/utils';\nimport {\n $createParagraphNode,\n $getSelection,\n $isRangeSelection,\n $isRootOrShadowRoot,\n CAN_REDO_COMMAND,\n CAN_UNDO_COMMAND,\n COMMAND_PRIORITY_CRITICAL,\n COMMAND_PRIORITY_NORMAL,\n DEPRECATED_$isGridSelection,\n FORMAT_TEXT_COMMAND,\n KEY_MODIFIER_COMMAND,\n LexicalEditor,\n REDO_COMMAND,\n SELECTION_CHANGE_COMMAND,\n UNDO_COMMAND,\n} from 'lexical';\n\nimport { IS_APPLE, getSelectedNode, sanitizeUrl } from '../utils';\nimport DropDown, { DropDownItem } from '../ui/DropDown';\n\nconst blockTypeToBlockName = {\n bullet: 'Bulleted List',\n check: 'Check List',\n code: 'Code Block',\n h1: 'Heading 1',\n h2: 'Heading 2',\n h3: 'Heading 3',\n h4: 'Heading 4',\n h5: 'Heading 5',\n h6: 'Heading 6',\n number: 'Numbered List',\n paragraph: 'Normal',\n quote: 'Quote',\n};\n\nconst rootTypeToRootName = {\n root: 'Root',\n table: 'Table',\n};\n\nfunction dropDownActiveClass(active: boolean) {\n if (active) return 'active dropdown-item-active';\n else return '';\n}\n\nfunction BlockFormatDropDown({\n editor,\n blockType,\n rootType,\n disabled = false,\n}: {\n blockType: keyof typeof blockTypeToBlockName;\n rootType: keyof typeof rootTypeToRootName;\n editor: LexicalEditor;\n disabled?: boolean;\n}): JSX.Element {\n const formatParagraph = () => {\n editor.update(() => {\n const selection = $getSelection();\n if (\n $isRangeSelection(selection) ||\n DEPRECATED_$isGridSelection(selection)\n ) {\n $setBlocksType(selection, () => $createParagraphNode());\n }\n });\n };\n\n const formatHeading = (headingSize: HeadingTagType) => {\n if (blockType !== headingSize) {\n editor.update(() => {\n const selection = $getSelection();\n if (\n $isRangeSelection(selection) ||\n DEPRECATED_$isGridSelection(selection)\n ) {\n $setBlocksType(selection, () => $createHeadingNode(headingSize));\n }\n });\n }\n };\n\n const formatBulletList = () => {\n if (blockType !== 'bullet') {\n editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n }\n };\n\n const formatNumberedList = () => {\n if (blockType !== 'number') {\n editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);\n } else {\n editor.dispatchCommand(REMOVE_LIST_COMMAND, undefined);\n }\n };\n\n return (\n \n \n \n Normal\n \n formatHeading('h1')}\n >\n \n Heading 1\n \n formatHeading('h2')}\n >\n \n Heading 2\n \n formatHeading('h3')}\n >\n \n Heading 3\n \n \n \n Bullet List\n \n \n \n Numbered List\n \n \n );\n}\n\nfunction Divider(): JSX.Element {\n return ;\n}\n\nexport default function ToolbarPlugin({\n setIsLinkEditMode,\n}: {\n setIsLinkEditMode: Dispatch;\n}): JSX.Element {\n const [editor] = useLexicalComposerContext();\n const [activeEditor, setActiveEditor] = useState(editor);\n const [blockType, setBlockType] =\n useState('paragraph');\n const [rootType, setRootType] =\n useState('root');\n const [isLink, setIsLink] = useState(false);\n const [isBold, setIsBold] = useState(false);\n const [isItalic, setIsItalic] = useState(false);\n const [canUndo, setCanUndo] = useState(false);\n const [canRedo, setCanRedo] = useState(false);\n const [isEditable, setIsEditable] = useState(() => editor.isEditable());\n\n const $updateToolbar = useCallback(() => {\n const selection = $getSelection();\n if ($isRangeSelection(selection)) {\n const anchorNode = selection.anchor.getNode();\n let element =\n anchorNode.getKey() === 'root'\n ? anchorNode\n : $findMatchingParent(anchorNode, e => {\n const parent = e.getParent();\n return parent !== null && $isRootOrShadowRoot(parent);\n });\n\n if (element === null) {\n element = anchorNode.getTopLevelElementOrThrow();\n }\n\n const elementKey = element.getKey();\n const elementDOM = activeEditor.getElementByKey(elementKey);\n\n setIsBold(selection.hasFormat('bold'));\n setIsItalic(selection.hasFormat('italic'));\n\n const node = getSelectedNode(selection);\n const parent = node.getParent();\n if ($isLinkNode(parent) || $isLinkNode(node)) {\n setIsLink(true);\n } else {\n setIsLink(false);\n }\n\n const tableNode = $findMatchingParent(node, $isTableNode);\n if ($isTableNode(tableNode)) {\n setRootType('table');\n } else {\n setRootType('root');\n }\n\n if (elementDOM !== null) {\n if ($isListNode(element)) {\n const parentList = $getNearestNodeOfType(\n anchorNode,\n ListNode,\n );\n const type = parentList\n ? parentList.getListType()\n : element.getListType();\n setBlockType(type);\n } else {\n const type = $isHeadingNode(element)\n ? element.getTag()\n : element.getType();\n if (type in blockTypeToBlockName) {\n setBlockType(type as keyof typeof blockTypeToBlockName);\n }\n }\n }\n }\n }, [activeEditor]);\n\n useEffect(() => {\n return editor.registerCommand(\n SELECTION_CHANGE_COMMAND,\n (_payload, newEditor) => {\n $updateToolbar();\n setActiveEditor(newEditor);\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n );\n }, [editor, $updateToolbar]);\n\n useEffect(() => {\n return mergeRegister(\n editor.registerEditableListener(editable => {\n setIsEditable(editable);\n }),\n activeEditor.registerUpdateListener(({ editorState }) => {\n editorState.read(() => {\n $updateToolbar();\n });\n }),\n activeEditor.registerCommand(\n CAN_UNDO_COMMAND,\n payload => {\n setCanUndo(payload);\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n ),\n activeEditor.registerCommand(\n CAN_REDO_COMMAND,\n payload => {\n setCanRedo(payload);\n return false;\n },\n COMMAND_PRIORITY_CRITICAL,\n ),\n );\n }, [$updateToolbar, activeEditor, editor]);\n\n useEffect(() => {\n return activeEditor.registerCommand(\n KEY_MODIFIER_COMMAND,\n payload => {\n const event: KeyboardEvent = payload;\n const { code, ctrlKey, metaKey } = event;\n\n if (code === 'KeyK' && (ctrlKey || metaKey)) {\n event.preventDefault();\n if (!isLink) {\n setIsLinkEditMode(true);\n } else {\n setIsLinkEditMode(false);\n }\n return activeEditor.dispatchCommand(\n TOGGLE_LINK_COMMAND,\n sanitizeUrl('https://'),\n );\n }\n return false;\n },\n COMMAND_PRIORITY_NORMAL,\n );\n }, [activeEditor, isLink, setIsLinkEditMode]);\n\n const insertLink = useCallback(() => {\n if (!isLink) {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl('https://'));\n } else {\n editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);\n }\n }, [editor, isLink]);\n\n return (\n \n
\n
\n
\n {blockType in blockTypeToBlockName && activeEditor === editor && (\n <>\n
\n
\n >\n )}\n
\n
\n
\n
\n );\n}\n","import {\n createContext,\n KeyboardEvent,\n MouseEvent as ReactMouseEvent,\n ReactNode,\n Ref,\n RefObject,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\ntype DropDownContextType = {\n registerItem: (ref: RefObject) => void;\n};\n\nconst DropDownContext = createContext(null);\n\nconst dropDownPadding = 4;\n\nexport function DropDownItem({\n children,\n className,\n onClick,\n title,\n}: {\n children: ReactNode;\n className: string;\n onClick: (event: ReactMouseEvent) => void;\n title?: string;\n}) {\n const ref = useRef(null);\n\n const dropDownContext = useContext(DropDownContext);\n\n if (dropDownContext === null) {\n throw new Error('DropDownItem must be used within a DropDown');\n }\n\n const { registerItem } = dropDownContext;\n\n useEffect(() => {\n if (ref && ref.current) {\n registerItem(ref);\n }\n }, [ref, registerItem]);\n\n return (\n \n );\n}\n\nfunction DropDownItems({\n children,\n dropDownRef,\n onClose,\n}: {\n children: ReactNode;\n dropDownRef: Ref;\n onClose: () => void;\n}) {\n const [items, setItems] = useState[]>();\n const [highlightedItem, setHighlightedItem] =\n useState>();\n\n const registerItem = useCallback(\n (itemRef: RefObject) => {\n setItems(prev => (prev ? [...prev, itemRef] : [itemRef]));\n },\n [setItems],\n );\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (!items) return;\n\n const key = event.key;\n\n if (['Escape', 'ArrowUp', 'ArrowDown', 'Tab'].includes(key)) {\n event.preventDefault();\n }\n\n if (key === 'Escape' || key === 'Tab') {\n onClose();\n } else if (key === 'ArrowUp') {\n setHighlightedItem(prev => {\n if (!prev) return items[0];\n const index = items.indexOf(prev) - 1;\n return items[index === -1 ? items.length - 1 : index];\n });\n } else if (key === 'ArrowDown') {\n setHighlightedItem(prev => {\n if (!prev) return items[0];\n return items[items.indexOf(prev) + 1];\n });\n }\n };\n\n const contextValue = useMemo(\n () => ({\n registerItem,\n }),\n [registerItem],\n );\n\n useEffect(() => {\n if (items && !highlightedItem) {\n setHighlightedItem(items[0]);\n }\n\n if (highlightedItem && highlightedItem.current) {\n highlightedItem.current.focus();\n }\n }, [items, highlightedItem]);\n\n return (\n \n \n {children}\n
\n \n );\n}\n\nexport default function DropDown({\n disabled = false,\n buttonLabel,\n buttonAriaLabel,\n buttonClassName,\n buttonIconClassName,\n children,\n stopCloseOnClickSelf,\n}: {\n disabled?: boolean;\n buttonAriaLabel?: string;\n buttonClassName: string;\n buttonIconClassName?: string;\n buttonLabel?: string;\n children: ReactNode;\n stopCloseOnClickSelf?: boolean;\n}): JSX.Element {\n const dropDownRef = useRef(null);\n const buttonRef = useRef(null);\n const [showDropDown, setShowDropDown] = useState(false);\n\n const handleClose = () => {\n setShowDropDown(false);\n if (buttonRef && buttonRef.current) {\n buttonRef.current.focus();\n }\n };\n\n useEffect(() => {\n const button = buttonRef.current;\n const dropDown = dropDownRef.current;\n\n if (showDropDown && button !== null && dropDown !== null) {\n const { top, left } = button.getBoundingClientRect();\n dropDown.style.top = `${top + button.offsetHeight + dropDownPadding}px`;\n dropDown.style.left = `${Math.min(\n left,\n window.innerWidth - dropDown.offsetWidth - 20,\n )}px`;\n }\n }, [dropDownRef, buttonRef, showDropDown]);\n\n useEffect(() => {\n const button = buttonRef.current;\n\n if (button !== null && showDropDown) {\n const handle = (event: MouseEvent) => {\n const target = event.target;\n if (stopCloseOnClickSelf) {\n if (\n dropDownRef.current &&\n dropDownRef.current.contains(target as Node)\n )\n return;\n }\n if (!button.contains(target as Node)) {\n setShowDropDown(false);\n }\n };\n document.addEventListener('click', handle);\n\n return () => {\n document.removeEventListener('click', handle);\n };\n }\n }, [dropDownRef, buttonRef, showDropDown, stopCloseOnClickSelf]);\n\n useEffect(() => {\n const handleButtonPositionUpdate = () => {\n if (showDropDown) {\n const button = buttonRef.current;\n const dropDown = dropDownRef.current;\n if (button !== null && dropDown !== null) {\n const { top } = button.getBoundingClientRect();\n const newPosition = top + button.offsetHeight + dropDownPadding;\n if (newPosition !== dropDown.getBoundingClientRect().top) {\n dropDown.style.top = `${newPosition}px`;\n }\n }\n }\n };\n\n document.addEventListener('scroll', handleButtonPositionUpdate);\n\n return () => {\n document.removeEventListener('scroll', handleButtonPositionUpdate);\n };\n }, [buttonRef, dropDownRef, showDropDown]);\n\n return (\n <>\n \n\n {showDropDown &&\n createPortal(\n \n {children}\n ,\n document.body,\n )}\n >\n );\n}\n","import { HTMLInputTypeAttribute } from 'react';\n\ntype Props = Readonly<{\n 'data-test-id'?: string;\n label: string;\n onChange: (val: string) => void;\n placeholder?: string;\n value: string;\n type?: HTMLInputTypeAttribute;\n}>;\n\nexport default function TextInput({\n label,\n value,\n onChange,\n placeholder = '',\n 'data-test-id': dataTestId,\n type = 'text',\n}: Props): JSX.Element {\n return (\n \n \n {\n onChange(e.target.value);\n }}\n data-test-id={dataTestId}\n />\n
\n );\n}\n","export const CAN_USE_DOM: boolean =\n typeof window !== 'undefined' &&\n typeof window.document !== 'undefined' &&\n typeof window.document.createElement !== 'undefined';\n\ndeclare global {\n interface Document {\n documentMode?: unknown;\n }\n\n interface Window {\n MSStream?: unknown;\n }\n}\n\nconst documentMode =\n CAN_USE_DOM && 'documentMode' in document ? document.documentMode : null;\n\nexport const IS_APPLE: boolean =\n CAN_USE_DOM && /Mac|iPod|iPhone|iPad/.test(navigator.platform);\n\nexport const IS_FIREFOX: boolean =\n CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);\n\nexport const CAN_USE_BEFORE_INPUT: boolean =\n CAN_USE_DOM && 'InputEvent' in window && !documentMode\n ? 'getTargetRanges' in new window.InputEvent('input')\n : false;\n\nexport const IS_SAFARI: boolean =\n CAN_USE_DOM && /Version\\/[\\d.]+.*Safari/.test(navigator.userAgent);\n\nexport const IS_IOS: boolean =\n CAN_USE_DOM &&\n /iPad|iPhone|iPod/.test(navigator.userAgent) &&\n !window.MSStream;\n\nexport const IS_ANDROID: boolean =\n CAN_USE_DOM && /Android/.test(navigator.userAgent);\n\nexport const IS_CHROME: boolean =\n CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent);\n\nexport const IS_APPLE_WEBKIT =\n CAN_USE_DOM && /AppleWebKit\\/[\\d.]+/.test(navigator.userAgent) && !IS_CHROME;\n","import { $isAtNodeEnd } from '@lexical/selection';\nimport { ElementNode, RangeSelection, TextNode } from 'lexical';\n\nexport function getSelectedNode(\n selection: RangeSelection,\n): TextNode | ElementNode {\n const anchor = selection.anchor;\n const focus = selection.focus;\n const anchorNode = selection.anchor.getNode();\n const focusNode = selection.focus.getNode();\n if (anchorNode === focusNode) {\n return anchorNode;\n }\n const isBackward = selection.isBackward();\n if (isBackward) {\n return $isAtNodeEnd(focus) ? anchorNode : focusNode;\n } else {\n return $isAtNodeEnd(anchor) ? anchorNode : focusNode;\n }\n}\n","const VERTICAL_GAP = 10;\nconst HORIZONTAL_OFFSET = 5;\n\nexport function setFloatingElemPositionForLinkEditor(\n targetRect: DOMRect | null,\n floatingElem: HTMLElement,\n anchorElem: HTMLElement,\n verticalGap: number = VERTICAL_GAP,\n horizontalOffset: number = HORIZONTAL_OFFSET,\n): void {\n const scrollerElem = anchorElem.parentElement;\n\n if (targetRect === null || !scrollerElem) {\n floatingElem.style.opacity = '0';\n floatingElem.style.transform = 'translate(-10000px, -10000px)';\n return;\n }\n\n const floatingElemRect = floatingElem.getBoundingClientRect();\n const anchorElementRect = anchorElem.getBoundingClientRect();\n const editorScrollerRect = scrollerElem.getBoundingClientRect();\n\n let top = targetRect.top - verticalGap;\n let left = targetRect.left - horizontalOffset;\n\n if (top < editorScrollerRect.top) {\n top += floatingElemRect.height + targetRect.height + verticalGap * 2;\n }\n\n if (left + floatingElemRect.width > editorScrollerRect.right) {\n left = editorScrollerRect.right - floatingElemRect.width - horizontalOffset;\n }\n\n top -= anchorElementRect.top;\n left -= anchorElementRect.left;\n\n floatingElem.style.opacity = '1';\n floatingElem.style.transform = `translate(${left}px, ${top}px)`;\n}\n","const SUPPORTED_URL_PROTOCOLS = new Set([\n 'http:',\n 'https:',\n 'mailto:',\n 'sms:',\n 'tel:',\n]);\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsedUrl = new URL(url);\n if (!SUPPORTED_URL_PROTOCOLS.has(parsedUrl.protocol)) {\n return 'about:blank';\n }\n } catch {\n return url;\n }\n return url;\n}\n\nconst urlRegExp = new RegExp(\n /((([A-Za-z]{3,9}:(?:\\/\\/)?)(?:[-;:&=+$,\\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\\w]+@)[A-Za-z0-9.-]+)((?:\\/[+~%/.\\w-_]*)?\\??(?:[-+=&;%@.\\w_]*)#?(?:[\\w]*))?)/,\n);\n\nexport function validateUrl(url: string): boolean {\n return url === 'https://' || urlRegExp.test(url);\n}\n","import {\n Question as QuestionType,\n QuizSubmissionMetric,\n VrTask,\n VideoTask,\n} from '../models/Task';\nimport { MCQuestion, Modal, SuccessOrFail } from './MCQModal/';\n\ntype Props = {\n question: QuestionType;\n handleMCQAnswerSelection: (questionId: string, answerId: string) => void;\n handleReplay: () => void;\n quizSubmissionReady: boolean;\n onSubmit: () => void;\n quizResult: QuizSubmissionMetric | null;\n nextTask: VrTask | VideoTask | null;\n lessonUrl: string;\n};\n\nconst MCQModal = ({\n question,\n handleMCQAnswerSelection,\n handleReplay,\n quizSubmissionReady,\n onSubmit,\n quizResult,\n nextTask,\n lessonUrl,\n}: Props) => {\n return (\n \n {quizResult === null ? (\n \n ) : (\n \n )}\n \n );\n};\n\nexport default MCQModal;\n","import { useEffect, useState } from 'react';\nimport styled from 'styled-components';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport { faRotateLeft } from '@fortawesome/free-solid-svg-icons';\n\nimport { Question as QuestionType } from '../../models/Task';\nimport { SPACE_LARGE, SPACE_SMALL } from './';\n\nconst Question = styled.div`\n width: 100%;\n color: white;\n margin-bottom: ${SPACE_LARGE}px;\n & > h3 {\n font-size: 1.5rem;\n font-weight: bold;\n }\n`;\n\nconst OptionsAndImgContainer = styled.div`\n width: 100%;\n border-radius: 17px;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n\n @media (max-width: 600px) and (orientation: portrait) {\n flex-direction: column-reverse;\n }\n`;\n\nconst OptionsContainer = styled.div`\n width: 60%;\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n align-items: center;\n\n @media (max-width: 600px) and (orientation: portrait) {\n width: 100%;\n }\n`;\n\nconst Option = styled.div<{ selected: boolean }>`\n width: 100%;\n height: 45px;\n padding-left: 16px;\n display: flex;\n justify-content: start;\n align-items: center;\n font-size: 0.875rem;\n margin-bottom: ${SPACE_LARGE}px;\n border-radius: 12px;\n color: ${props => (props.selected ? 'white' : '#2c2c2c')};\n background: ${props => (props.selected ? '#0452EC' : 'white')};\n &:hover {\n cursor: pointer;\n opacity: 0.9;\n }\n\n @media (max-width: 600px) and (orientation: portrait) {\n margin-bottom: ${SPACE_SMALL}px;\n }\n`;\n\nconst QuestionImage = styled.div`\n width: 40%;\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 20px;\n\n & > img {\n width: 180px;\n height: auto;\n flex-grow: 0;\n }\n\n @media (max-width: 600px) and (orientation: portrait) {\n width: 100%;\n }\n`;\n\nconst ButtonContainer = styled.div`\n width: 100%;\n display: flex;\n justify-content: space-between;\n align-items: center;\n`;\n\nconst SubmitButton = styled.button`\n max-width: 170px;\n height: 45px;\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.7;\n }\n\n @media (max-width: 600px) and (orientation: portrait) {\n max-width: none;\n width: auto;\n }\n`;\n\nconst ReplayButtonContainer = styled.div`\n width: 45px;\n height: 55px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n\n & > p {\n font-size: 0.75rem;\n color: #c1c3c3;\n white-space: nowrap;\n }\n\n @media (max-width: 600px) and (orientation: portrait) {\n height: auto;\n margin: 0 20px;\n & > p {\n font-size: 0.6rem;\n }\n }\n`;\n\nconst ReplayButton = styled.button`\n min-height: 45px;\n min-width: 45px;\n border-radius: 10px;\n border: 1px solid #82caff;\n padding: 0%;\n padding-top: 2px;\n margin-bottom: 4px;\n background: transparent;\n\n &:hover {\n cursor: pointer;\n filter: brightness(110%);\n }\n\n & > svg {\n color: #82caff;\n height: 25px;\n width: 25px;\n }\n\n @media (max-width: 600px) and (orientation: portrait) {\n border: none;\n min-height: 40px;\n min-width: 40px;\n margin-bottom: 0px;\n }\n`;\n\ntype Props = {\n question: QuestionType;\n handleMCQAnswerSelection: (questionId: string, answerId: string) => void;\n handleReplay: () => void;\n quizSubmissionReady: boolean;\n onSubmit: () => void;\n};\n\nexport const MCQuestion = ({\n question,\n handleMCQAnswerSelection,\n handleReplay,\n quizSubmissionReady,\n onSubmit,\n}: Props) => {\n const [selectedOptionId, setSelectedOptionId] = useState(null);\n\n useEffect(() => {\n if (selectedOptionId === null || question === null) {\n return;\n }\n handleMCQAnswerSelection(question.databaseId, selectedOptionId);\n }, [question, selectedOptionId, handleMCQAnswerSelection]);\n\n return (\n <>\n \n {question.question}
\n \n \n \n {question.options.map(opt => (\n \n ))}\n \n \n
\n \n \n \n onSubmit()}\n disabled={!quizSubmissionReady}\n >\n Submit Answer\n \n \n \n \n \n Replay Video
\n \n \n >\n );\n};\n","import { ReactNode } from 'react';\nimport styled from 'styled-components';\n\nexport const SPACE_LARGE = 18;\nexport const SPACE_SMALL = 12;\n\nconst ModalContainer = styled.div`\n width: 100vw;\n padding: 32px 92px 20px 92px;\n display: flex;\n align-items: center;\n justify-content: center;\n\n @media (max-width: 600px) and (orientation: portrait) {\n padding: 20px;\n padding-bottom: 0;\n }\n`;\n\nconst ModalMain = styled.div`\n width: 100%;\n min-height: 400px;\n padding: 20px 38px;\n border-radius: 17px;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #2c2c2c;\n\n @media (max-width: 600px) and (orientation: portrait) {\n padding: ${SPACE_LARGE}px;\n }\n`;\n\nexport const Modal = ({ children }: { children: ReactNode }) => {\n return (\n \n {children}\n \n );\n};\n","import styled from 'styled-components';\n\nimport { SPACE_SMALL } from './';\nimport { VrTask, VideoTask } from '../../models/Task';\n\nconst Title = styled.div`\n margin-bottom: 28px;\n & > h3 {\n font-size: 1.5rem;\n font-weight: bold;\n }\n`;\n\nconst Subtitle = styled.div`\n margin-bottom: 42px;\n text-align: center;\n & > h4 {\n font-size: 0.875rem;\n }\n`;\n\nconst ButtonContainer = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n`;\n\nconst ButtonPassCta = styled.a`\n width: auto;\n max-width: 125px;\n height: 45px;\n margin-right: ${SPACE_SMALL}px;\n`;\n\nconst ButtonTryAgainCta = styled.button`\n width: auto;\n max-width: 125px;\n height: 45px;\n margin-right: ${SPACE_SMALL}px;\n`;\n\nconst ButtonSecondary = styled.a`\n width: auto;\n max-width: 150px;\n height: 45px;\n`;\n\ntype Props = {\n pass: boolean;\n nextTask: VrTask | VideoTask | null;\n handleReplay: () => void;\n lessonUrl: string;\n};\n\nexport const SuccessOrFail = ({\n pass,\n nextTask,\n handleReplay,\n lessonUrl,\n}: Props) => {\n return (\n <>\n \n {pass ? 'Congratulations' : 'Unsuccessful'}
\n \n \n {pass ? (\n \n You have passed.\n
\n Well done on completing your quiz.\n
\n ) : (\n Please either try again or return to the lesson.
\n )}\n \n \n {nextTask && pass && (\n \n Next Video\n \n )}\n {!pass && (\n \n Try Again\n \n )}\n \n Return to Lesson\n \n \n >\n );\n};\n","'use client';\n\n/* eslint-disable no-constant-condition */\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\nimport * as React from 'react';\nimport { unstable_setRef as setRef, unstable_useEventCallback as useEventCallback, unstable_useControlled as useControlled, unstable_useId as useId, usePreviousProps } from '@mui/utils';\n\n// https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript\n// Give up on IE11 support for this feature\nfunction stripDiacritics(string) {\n return typeof string.normalize !== 'undefined' ? string.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '') : string;\n}\nexport function createFilterOptions(config = {}) {\n const {\n ignoreAccents = true,\n ignoreCase = true,\n limit,\n matchFrom = 'any',\n stringify,\n trim = false\n } = config;\n return (options, {\n inputValue,\n getOptionLabel\n }) => {\n let input = trim ? inputValue.trim() : inputValue;\n if (ignoreCase) {\n input = input.toLowerCase();\n }\n if (ignoreAccents) {\n input = stripDiacritics(input);\n }\n const filteredOptions = !input ? options : options.filter(option => {\n let candidate = (stringify || getOptionLabel)(option);\n if (ignoreCase) {\n candidate = candidate.toLowerCase();\n }\n if (ignoreAccents) {\n candidate = stripDiacritics(candidate);\n }\n return matchFrom === 'start' ? candidate.indexOf(input) === 0 : candidate.indexOf(input) > -1;\n });\n return typeof limit === 'number' ? filteredOptions.slice(0, limit) : filteredOptions;\n };\n}\n\n// To replace with .findIndex() once we stop IE11 support.\nfunction findIndex(array, comp) {\n for (let i = 0; i < array.length; i += 1) {\n if (comp(array[i])) {\n return i;\n }\n }\n return -1;\n}\nconst defaultFilterOptions = createFilterOptions();\n\n// Number of options to jump in list box when `Page Up` and `Page Down` keys are used.\nconst pageSize = 5;\nconst defaultIsActiveElementInListbox = listboxRef => {\n var _listboxRef$current$p;\n return listboxRef.current !== null && ((_listboxRef$current$p = listboxRef.current.parentElement) == null ? void 0 : _listboxRef$current$p.contains(document.activeElement));\n};\nconst MULTIPLE_DEFAULT_VALUE = [];\nfunction useAutocomplete(props) {\n const {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_isActiveElementInListbox = defaultIsActiveElementInListbox,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n unstable_classNamePrefix = 'Mui',\n autoComplete = false,\n autoHighlight = false,\n autoSelect = false,\n blurOnSelect = false,\n clearOnBlur = !props.freeSolo,\n clearOnEscape = false,\n componentName = 'useAutocomplete',\n defaultValue = props.multiple ? MULTIPLE_DEFAULT_VALUE : null,\n disableClearable = false,\n disableCloseOnSelect = false,\n disabled: disabledProp,\n disabledItemsFocusable = false,\n disableListWrap = false,\n filterOptions = defaultFilterOptions,\n filterSelectedOptions = false,\n freeSolo = false,\n getOptionDisabled,\n getOptionKey,\n getOptionLabel: getOptionLabelProp = option => {\n var _option$label;\n return (_option$label = option.label) != null ? _option$label : option;\n },\n groupBy,\n handleHomeEndKeys = !props.freeSolo,\n id: idProp,\n includeInputInList = false,\n inputValue: inputValueProp,\n isOptionEqualToValue = (option, value) => option === value,\n multiple = false,\n onChange,\n onClose,\n onHighlightChange,\n onInputChange,\n onOpen,\n open: openProp,\n openOnFocus = false,\n options,\n readOnly = false,\n selectOnFocus = !props.freeSolo,\n value: valueProp\n } = props;\n const id = useId(idProp);\n let getOptionLabel = getOptionLabelProp;\n getOptionLabel = option => {\n const optionLabel = getOptionLabelProp(option);\n if (typeof optionLabel !== 'string') {\n if (process.env.NODE_ENV !== 'production') {\n const erroneousReturn = optionLabel === undefined ? 'undefined' : `${typeof optionLabel} (${optionLabel})`;\n console.error(`MUI: The \\`getOptionLabel\\` method of ${componentName} returned ${erroneousReturn} instead of a string for ${JSON.stringify(option)}.`);\n }\n return String(optionLabel);\n }\n return optionLabel;\n };\n const ignoreFocus = React.useRef(false);\n const firstFocus = React.useRef(true);\n const inputRef = React.useRef(null);\n const listboxRef = React.useRef(null);\n const [anchorEl, setAnchorEl] = React.useState(null);\n const [focusedTag, setFocusedTag] = React.useState(-1);\n const defaultHighlighted = autoHighlight ? 0 : -1;\n const highlightedIndexRef = React.useRef(defaultHighlighted);\n const [value, setValueState] = useControlled({\n controlled: valueProp,\n default: defaultValue,\n name: componentName\n });\n const [inputValue, setInputValueState] = useControlled({\n controlled: inputValueProp,\n default: '',\n name: componentName,\n state: 'inputValue'\n });\n const [focused, setFocused] = React.useState(false);\n const resetInputValue = React.useCallback((event, newValue) => {\n // retain current `inputValue` if new option isn't selected and `clearOnBlur` is false\n // When `multiple` is enabled, `newValue` is an array of all selected items including the newly selected item\n const isOptionSelected = multiple ? value.length < newValue.length : newValue !== null;\n if (!isOptionSelected && !clearOnBlur) {\n return;\n }\n let newInputValue;\n if (multiple) {\n newInputValue = '';\n } else if (newValue == null) {\n newInputValue = '';\n } else {\n const optionLabel = getOptionLabel(newValue);\n newInputValue = typeof optionLabel === 'string' ? optionLabel : '';\n }\n if (inputValue === newInputValue) {\n return;\n }\n setInputValueState(newInputValue);\n if (onInputChange) {\n onInputChange(event, newInputValue, 'reset');\n }\n }, [getOptionLabel, inputValue, multiple, onInputChange, setInputValueState, clearOnBlur, value]);\n const [open, setOpenState] = useControlled({\n controlled: openProp,\n default: false,\n name: componentName,\n state: 'open'\n });\n const [inputPristine, setInputPristine] = React.useState(true);\n const inputValueIsSelectedValue = !multiple && value != null && inputValue === getOptionLabel(value);\n const popupOpen = open && !readOnly;\n const filteredOptions = popupOpen ? filterOptions(options.filter(option => {\n if (filterSelectedOptions && (multiple ? value : [value]).some(value2 => value2 !== null && isOptionEqualToValue(option, value2))) {\n return false;\n }\n return true;\n }),\n // we use the empty string to manipulate `filterOptions` to not filter any options\n // i.e. the filter predicate always returns true\n {\n inputValue: inputValueIsSelectedValue && inputPristine ? '' : inputValue,\n getOptionLabel\n }) : [];\n const previousProps = usePreviousProps({\n filteredOptions,\n value,\n inputValue\n });\n React.useEffect(() => {\n const valueChange = value !== previousProps.value;\n if (focused && !valueChange) {\n return;\n }\n\n // Only reset the input's value when freeSolo if the component's value changes.\n if (freeSolo && !valueChange) {\n return;\n }\n resetInputValue(null, value);\n }, [value, resetInputValue, focused, previousProps.value, freeSolo]);\n const listboxAvailable = open && filteredOptions.length > 0 && !readOnly;\n if (process.env.NODE_ENV !== 'production') {\n if (value !== null && !freeSolo && options.length > 0) {\n const missingValue = (multiple ? value : [value]).filter(value2 => !options.some(option => isOptionEqualToValue(option, value2)));\n if (missingValue.length > 0) {\n console.warn([`MUI: The value provided to ${componentName} is invalid.`, `None of the options match with \\`${missingValue.length > 1 ? JSON.stringify(missingValue) : JSON.stringify(missingValue[0])}\\`.`, 'You can use the `isOptionEqualToValue` prop to customize the equality test.'].join('\\n'));\n }\n }\n }\n const focusTag = useEventCallback(tagToFocus => {\n if (tagToFocus === -1) {\n inputRef.current.focus();\n } else {\n anchorEl.querySelector(`[data-tag-index=\"${tagToFocus}\"]`).focus();\n }\n });\n\n // Ensure the focusedTag is never inconsistent\n React.useEffect(() => {\n if (multiple && focusedTag > value.length - 1) {\n setFocusedTag(-1);\n focusTag(-1);\n }\n }, [value, multiple, focusedTag, focusTag]);\n function validOptionIndex(index, direction) {\n if (!listboxRef.current || index < 0 || index >= filteredOptions.length) {\n return -1;\n }\n let nextFocus = index;\n while (true) {\n const option = listboxRef.current.querySelector(`[data-option-index=\"${nextFocus}\"]`);\n\n // Same logic as MenuList.js\n const nextFocusDisabled = disabledItemsFocusable ? false : !option || option.disabled || option.getAttribute('aria-disabled') === 'true';\n if (option && option.hasAttribute('tabindex') && !nextFocusDisabled) {\n // The next option is available\n return nextFocus;\n }\n\n // The next option is disabled, move to the next element.\n // with looped index\n if (direction === 'next') {\n nextFocus = (nextFocus + 1) % filteredOptions.length;\n } else {\n nextFocus = (nextFocus - 1 + filteredOptions.length) % filteredOptions.length;\n }\n\n // We end up with initial index, that means we don't have available options.\n // All of them are disabled\n if (nextFocus === index) {\n return -1;\n }\n }\n }\n const setHighlightedIndex = useEventCallback(({\n event,\n index,\n reason = 'auto'\n }) => {\n highlightedIndexRef.current = index;\n\n // does the index exist?\n if (index === -1) {\n inputRef.current.removeAttribute('aria-activedescendant');\n } else {\n inputRef.current.setAttribute('aria-activedescendant', `${id}-option-${index}`);\n }\n if (onHighlightChange) {\n onHighlightChange(event, index === -1 ? null : filteredOptions[index], reason);\n }\n if (!listboxRef.current) {\n return;\n }\n const prev = listboxRef.current.querySelector(`[role=\"option\"].${unstable_classNamePrefix}-focused`);\n if (prev) {\n prev.classList.remove(`${unstable_classNamePrefix}-focused`);\n prev.classList.remove(`${unstable_classNamePrefix}-focusVisible`);\n }\n let listboxNode = listboxRef.current;\n if (listboxRef.current.getAttribute('role') !== 'listbox') {\n listboxNode = listboxRef.current.parentElement.querySelector('[role=\"listbox\"]');\n }\n\n // \"No results\"\n if (!listboxNode) {\n return;\n }\n if (index === -1) {\n listboxNode.scrollTop = 0;\n return;\n }\n const option = listboxRef.current.querySelector(`[data-option-index=\"${index}\"]`);\n if (!option) {\n return;\n }\n option.classList.add(`${unstable_classNamePrefix}-focused`);\n if (reason === 'keyboard') {\n option.classList.add(`${unstable_classNamePrefix}-focusVisible`);\n }\n\n // Scroll active descendant into view.\n // Logic copied from https://www.w3.org/WAI/content-assets/wai-aria-practices/patterns/combobox/examples/js/select-only.js\n // In case of mouse clicks and touch (in mobile devices) we avoid scrolling the element and keep both behaviors same.\n // Consider this API instead once it has a better browser support:\n // .scrollIntoView({ scrollMode: 'if-needed', block: 'nearest' });\n if (listboxNode.scrollHeight > listboxNode.clientHeight && reason !== 'mouse' && reason !== 'touch') {\n const element = option;\n const scrollBottom = listboxNode.clientHeight + listboxNode.scrollTop;\n const elementBottom = element.offsetTop + element.offsetHeight;\n if (elementBottom > scrollBottom) {\n listboxNode.scrollTop = elementBottom - listboxNode.clientHeight;\n } else if (element.offsetTop - element.offsetHeight * (groupBy ? 1.3 : 0) < listboxNode.scrollTop) {\n listboxNode.scrollTop = element.offsetTop - element.offsetHeight * (groupBy ? 1.3 : 0);\n }\n }\n });\n const changeHighlightedIndex = useEventCallback(({\n event,\n diff,\n direction = 'next',\n reason = 'auto'\n }) => {\n if (!popupOpen) {\n return;\n }\n const getNextIndex = () => {\n const maxIndex = filteredOptions.length - 1;\n if (diff === 'reset') {\n return defaultHighlighted;\n }\n if (diff === 'start') {\n return 0;\n }\n if (diff === 'end') {\n return maxIndex;\n }\n const newIndex = highlightedIndexRef.current + diff;\n if (newIndex < 0) {\n if (newIndex === -1 && includeInputInList) {\n return -1;\n }\n if (disableListWrap && highlightedIndexRef.current !== -1 || Math.abs(diff) > 1) {\n return 0;\n }\n return maxIndex;\n }\n if (newIndex > maxIndex) {\n if (newIndex === maxIndex + 1 && includeInputInList) {\n return -1;\n }\n if (disableListWrap || Math.abs(diff) > 1) {\n return maxIndex;\n }\n return 0;\n }\n return newIndex;\n };\n const nextIndex = validOptionIndex(getNextIndex(), direction);\n setHighlightedIndex({\n index: nextIndex,\n reason,\n event\n });\n\n // Sync the content of the input with the highlighted option.\n if (autoComplete && diff !== 'reset') {\n if (nextIndex === -1) {\n inputRef.current.value = inputValue;\n } else {\n const option = getOptionLabel(filteredOptions[nextIndex]);\n inputRef.current.value = option;\n\n // The portion of the selected suggestion that has not been typed by the user,\n // a completion string, appears inline after the input cursor in the textbox.\n const index = option.toLowerCase().indexOf(inputValue.toLowerCase());\n if (index === 0 && inputValue.length > 0) {\n inputRef.current.setSelectionRange(inputValue.length, option.length);\n }\n }\n }\n });\n const getPreviousHighlightedOptionIndex = () => {\n const isSameValue = (value1, value2) => {\n const label1 = value1 ? getOptionLabel(value1) : '';\n const label2 = value2 ? getOptionLabel(value2) : '';\n return label1 === label2;\n };\n if (highlightedIndexRef.current !== -1 && previousProps.filteredOptions && previousProps.filteredOptions.length !== filteredOptions.length && previousProps.inputValue === inputValue && (multiple ? value.length === previousProps.value.length && previousProps.value.every((val, i) => getOptionLabel(value[i]) === getOptionLabel(val)) : isSameValue(previousProps.value, value))) {\n const previousHighlightedOption = previousProps.filteredOptions[highlightedIndexRef.current];\n if (previousHighlightedOption) {\n return findIndex(filteredOptions, option => {\n return getOptionLabel(option) === getOptionLabel(previousHighlightedOption);\n });\n }\n }\n return -1;\n };\n const syncHighlightedIndex = React.useCallback(() => {\n if (!popupOpen) {\n return;\n }\n\n // Check if the previously highlighted option still exists in the updated filtered options list and if the value and inputValue haven't changed\n // If it exists and the value and the inputValue haven't changed, just update its index, otherwise continue execution\n const previousHighlightedOptionIndex = getPreviousHighlightedOptionIndex();\n if (previousHighlightedOptionIndex !== -1) {\n highlightedIndexRef.current = previousHighlightedOptionIndex;\n return;\n }\n const valueItem = multiple ? value[0] : value;\n\n // The popup is empty, reset\n if (filteredOptions.length === 0 || valueItem == null) {\n changeHighlightedIndex({\n diff: 'reset'\n });\n return;\n }\n if (!listboxRef.current) {\n return;\n }\n\n // Synchronize the value with the highlighted index\n if (valueItem != null) {\n const currentOption = filteredOptions[highlightedIndexRef.current];\n\n // Keep the current highlighted index if possible\n if (multiple && currentOption && findIndex(value, val => isOptionEqualToValue(currentOption, val)) !== -1) {\n return;\n }\n const itemIndex = findIndex(filteredOptions, optionItem => isOptionEqualToValue(optionItem, valueItem));\n if (itemIndex === -1) {\n changeHighlightedIndex({\n diff: 'reset'\n });\n } else {\n setHighlightedIndex({\n index: itemIndex\n });\n }\n return;\n }\n\n // Prevent the highlighted index to leak outside the boundaries.\n if (highlightedIndexRef.current >= filteredOptions.length - 1) {\n setHighlightedIndex({\n index: filteredOptions.length - 1\n });\n return;\n }\n\n // Restore the focus to the previous index.\n setHighlightedIndex({\n index: highlightedIndexRef.current\n });\n // Ignore filteredOptions (and options, isOptionEqualToValue, getOptionLabel) not to break the scroll position\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n // Only sync the highlighted index when the option switch between empty and not\n filteredOptions.length,\n // Don't sync the highlighted index with the value when multiple\n // eslint-disable-next-line react-hooks/exhaustive-deps\n multiple ? false : value, filterSelectedOptions, changeHighlightedIndex, setHighlightedIndex, popupOpen, inputValue, multiple]);\n const handleListboxRef = useEventCallback(node => {\n setRef(listboxRef, node);\n if (!node) {\n return;\n }\n syncHighlightedIndex();\n });\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n React.useEffect(() => {\n if (!inputRef.current || inputRef.current.nodeName !== 'INPUT') {\n if (inputRef.current && inputRef.current.nodeName === 'TEXTAREA') {\n console.warn([`A textarea element was provided to ${componentName} where input was expected.`, `This is not a supported scenario but it may work under certain conditions.`, `A textarea keyboard navigation may conflict with Autocomplete controls (for example enter and arrow keys).`, `Make sure to test keyboard navigation and add custom event handlers if necessary.`].join('\\n'));\n } else {\n console.error([`MUI: Unable to find the input element. It was resolved to ${inputRef.current} while an HTMLInputElement was expected.`, `Instead, ${componentName} expects an input element.`, '', componentName === 'useAutocomplete' ? 'Make sure you have bound getInputProps correctly and that the normal ref/effect resolutions order is guaranteed.' : 'Make sure you have customized the input component correctly.'].join('\\n'));\n }\n }\n }, [componentName]);\n }\n React.useEffect(() => {\n syncHighlightedIndex();\n }, [syncHighlightedIndex]);\n const handleOpen = event => {\n if (open) {\n return;\n }\n setOpenState(true);\n setInputPristine(true);\n if (onOpen) {\n onOpen(event);\n }\n };\n const handleClose = (event, reason) => {\n if (!open) {\n return;\n }\n setOpenState(false);\n if (onClose) {\n onClose(event, reason);\n }\n };\n const handleValue = (event, newValue, reason, details) => {\n if (multiple) {\n if (value.length === newValue.length && value.every((val, i) => val === newValue[i])) {\n return;\n }\n } else if (value === newValue) {\n return;\n }\n if (onChange) {\n onChange(event, newValue, reason, details);\n }\n setValueState(newValue);\n };\n const isTouch = React.useRef(false);\n const selectNewValue = (event, option, reasonProp = 'selectOption', origin = 'options') => {\n let reason = reasonProp;\n let newValue = option;\n if (multiple) {\n newValue = Array.isArray(value) ? value.slice() : [];\n if (process.env.NODE_ENV !== 'production') {\n const matches = newValue.filter(val => isOptionEqualToValue(option, val));\n if (matches.length > 1) {\n console.error([`MUI: The \\`isOptionEqualToValue\\` method of ${componentName} does not handle the arguments correctly.`, `The component expects a single value to match a given option but found ${matches.length} matches.`].join('\\n'));\n }\n }\n const itemIndex = findIndex(newValue, valueItem => isOptionEqualToValue(option, valueItem));\n if (itemIndex === -1) {\n newValue.push(option);\n } else if (origin !== 'freeSolo') {\n newValue.splice(itemIndex, 1);\n reason = 'removeOption';\n }\n }\n resetInputValue(event, newValue);\n handleValue(event, newValue, reason, {\n option\n });\n if (!disableCloseOnSelect && (!event || !event.ctrlKey && !event.metaKey)) {\n handleClose(event, reason);\n }\n if (blurOnSelect === true || blurOnSelect === 'touch' && isTouch.current || blurOnSelect === 'mouse' && !isTouch.current) {\n inputRef.current.blur();\n }\n };\n function validTagIndex(index, direction) {\n if (index === -1) {\n return -1;\n }\n let nextFocus = index;\n while (true) {\n // Out of range\n if (direction === 'next' && nextFocus === value.length || direction === 'previous' && nextFocus === -1) {\n return -1;\n }\n const option = anchorEl.querySelector(`[data-tag-index=\"${nextFocus}\"]`);\n\n // Same logic as MenuList.js\n if (!option || !option.hasAttribute('tabindex') || option.disabled || option.getAttribute('aria-disabled') === 'true') {\n nextFocus += direction === 'next' ? 1 : -1;\n } else {\n return nextFocus;\n }\n }\n }\n const handleFocusTag = (event, direction) => {\n if (!multiple) {\n return;\n }\n if (inputValue === '') {\n handleClose(event, 'toggleInput');\n }\n let nextTag = focusedTag;\n if (focusedTag === -1) {\n if (inputValue === '' && direction === 'previous') {\n nextTag = value.length - 1;\n }\n } else {\n nextTag += direction === 'next' ? 1 : -1;\n if (nextTag < 0) {\n nextTag = 0;\n }\n if (nextTag === value.length) {\n nextTag = -1;\n }\n }\n nextTag = validTagIndex(nextTag, direction);\n setFocusedTag(nextTag);\n focusTag(nextTag);\n };\n const handleClear = event => {\n ignoreFocus.current = true;\n setInputValueState('');\n if (onInputChange) {\n onInputChange(event, '', 'clear');\n }\n handleValue(event, multiple ? [] : null, 'clear');\n };\n const handleKeyDown = other => event => {\n if (other.onKeyDown) {\n other.onKeyDown(event);\n }\n if (event.defaultMuiPrevented) {\n return;\n }\n if (focusedTag !== -1 && ['ArrowLeft', 'ArrowRight'].indexOf(event.key) === -1) {\n setFocusedTag(-1);\n focusTag(-1);\n }\n\n // Wait until IME is settled.\n if (event.which !== 229) {\n switch (event.key) {\n case 'Home':\n if (popupOpen && handleHomeEndKeys) {\n // Prevent scroll of the page\n event.preventDefault();\n changeHighlightedIndex({\n diff: 'start',\n direction: 'next',\n reason: 'keyboard',\n event\n });\n }\n break;\n case 'End':\n if (popupOpen && handleHomeEndKeys) {\n // Prevent scroll of the page\n event.preventDefault();\n changeHighlightedIndex({\n diff: 'end',\n direction: 'previous',\n reason: 'keyboard',\n event\n });\n }\n break;\n case 'PageUp':\n // Prevent scroll of the page\n event.preventDefault();\n changeHighlightedIndex({\n diff: -pageSize,\n direction: 'previous',\n reason: 'keyboard',\n event\n });\n handleOpen(event);\n break;\n case 'PageDown':\n // Prevent scroll of the page\n event.preventDefault();\n changeHighlightedIndex({\n diff: pageSize,\n direction: 'next',\n reason: 'keyboard',\n event\n });\n handleOpen(event);\n break;\n case 'ArrowDown':\n // Prevent cursor move\n event.preventDefault();\n changeHighlightedIndex({\n diff: 1,\n direction: 'next',\n reason: 'keyboard',\n event\n });\n handleOpen(event);\n break;\n case 'ArrowUp':\n // Prevent cursor move\n event.preventDefault();\n changeHighlightedIndex({\n diff: -1,\n direction: 'previous',\n reason: 'keyboard',\n event\n });\n handleOpen(event);\n break;\n case 'ArrowLeft':\n handleFocusTag(event, 'previous');\n break;\n case 'ArrowRight':\n handleFocusTag(event, 'next');\n break;\n case 'Enter':\n if (highlightedIndexRef.current !== -1 && popupOpen) {\n const option = filteredOptions[highlightedIndexRef.current];\n const disabled = getOptionDisabled ? getOptionDisabled(option) : false;\n\n // Avoid early form validation, let the end-users continue filling the form.\n event.preventDefault();\n if (disabled) {\n return;\n }\n selectNewValue(event, option, 'selectOption');\n\n // Move the selection to the end.\n if (autoComplete) {\n inputRef.current.setSelectionRange(inputRef.current.value.length, inputRef.current.value.length);\n }\n } else if (freeSolo && inputValue !== '' && inputValueIsSelectedValue === false) {\n if (multiple) {\n // Allow people to add new values before they submit the form.\n event.preventDefault();\n }\n selectNewValue(event, inputValue, 'createOption', 'freeSolo');\n }\n break;\n case 'Escape':\n if (popupOpen) {\n // Avoid Opera to exit fullscreen mode.\n event.preventDefault();\n // Avoid the Modal to handle the event.\n event.stopPropagation();\n handleClose(event, 'escape');\n } else if (clearOnEscape && (inputValue !== '' || multiple && value.length > 0)) {\n // Avoid Opera to exit fullscreen mode.\n event.preventDefault();\n // Avoid the Modal to handle the event.\n event.stopPropagation();\n handleClear(event);\n }\n break;\n case 'Backspace':\n // Remove the value on the left of the \"cursor\"\n if (multiple && !readOnly && inputValue === '' && value.length > 0) {\n const index = focusedTag === -1 ? value.length - 1 : focusedTag;\n const newValue = value.slice();\n newValue.splice(index, 1);\n handleValue(event, newValue, 'removeOption', {\n option: value[index]\n });\n }\n break;\n case 'Delete':\n // Remove the value on the right of the \"cursor\"\n if (multiple && !readOnly && inputValue === '' && value.length > 0 && focusedTag !== -1) {\n const index = focusedTag;\n const newValue = value.slice();\n newValue.splice(index, 1);\n handleValue(event, newValue, 'removeOption', {\n option: value[index]\n });\n }\n break;\n default:\n }\n }\n };\n const handleFocus = event => {\n setFocused(true);\n if (openOnFocus && !ignoreFocus.current) {\n handleOpen(event);\n }\n };\n const handleBlur = event => {\n // Ignore the event when using the scrollbar with IE11\n if (unstable_isActiveElementInListbox(listboxRef)) {\n inputRef.current.focus();\n return;\n }\n setFocused(false);\n firstFocus.current = true;\n ignoreFocus.current = false;\n if (autoSelect && highlightedIndexRef.current !== -1 && popupOpen) {\n selectNewValue(event, filteredOptions[highlightedIndexRef.current], 'blur');\n } else if (autoSelect && freeSolo && inputValue !== '') {\n selectNewValue(event, inputValue, 'blur', 'freeSolo');\n } else if (clearOnBlur) {\n resetInputValue(event, value);\n }\n handleClose(event, 'blur');\n };\n const handleInputChange = event => {\n const newValue = event.target.value;\n if (inputValue !== newValue) {\n setInputValueState(newValue);\n setInputPristine(false);\n if (onInputChange) {\n onInputChange(event, newValue, 'input');\n }\n }\n if (newValue === '') {\n if (!disableClearable && !multiple) {\n handleValue(event, null, 'clear');\n }\n } else {\n handleOpen(event);\n }\n };\n const handleOptionMouseMove = event => {\n const index = Number(event.currentTarget.getAttribute('data-option-index'));\n if (highlightedIndexRef.current !== index) {\n setHighlightedIndex({\n event,\n index,\n reason: 'mouse'\n });\n }\n };\n const handleOptionTouchStart = event => {\n setHighlightedIndex({\n event,\n index: Number(event.currentTarget.getAttribute('data-option-index')),\n reason: 'touch'\n });\n isTouch.current = true;\n };\n const handleOptionClick = event => {\n const index = Number(event.currentTarget.getAttribute('data-option-index'));\n selectNewValue(event, filteredOptions[index], 'selectOption');\n isTouch.current = false;\n };\n const handleTagDelete = index => event => {\n const newValue = value.slice();\n newValue.splice(index, 1);\n handleValue(event, newValue, 'removeOption', {\n option: value[index]\n });\n };\n const handlePopupIndicator = event => {\n if (open) {\n handleClose(event, 'toggleInput');\n } else {\n handleOpen(event);\n }\n };\n\n // Prevent input blur when interacting with the combobox\n const handleMouseDown = event => {\n // Prevent focusing the input if click is anywhere outside the Autocomplete\n if (!event.currentTarget.contains(event.target)) {\n return;\n }\n if (event.target.getAttribute('id') !== id) {\n event.preventDefault();\n }\n };\n\n // Focus the input when interacting with the combobox\n const handleClick = event => {\n // Prevent focusing the input if click is anywhere outside the Autocomplete\n if (!event.currentTarget.contains(event.target)) {\n return;\n }\n inputRef.current.focus();\n if (selectOnFocus && firstFocus.current && inputRef.current.selectionEnd - inputRef.current.selectionStart === 0) {\n inputRef.current.select();\n }\n firstFocus.current = false;\n };\n const handleInputMouseDown = event => {\n if (!disabledProp && (inputValue === '' || !open)) {\n handlePopupIndicator(event);\n }\n };\n let dirty = freeSolo && inputValue.length > 0;\n dirty = dirty || (multiple ? value.length > 0 : value !== null);\n let groupedOptions = filteredOptions;\n if (groupBy) {\n // used to keep track of key and indexes in the result array\n const indexBy = new Map();\n let warn = false;\n groupedOptions = filteredOptions.reduce((acc, option, index) => {\n const group = groupBy(option);\n if (acc.length > 0 && acc[acc.length - 1].group === group) {\n acc[acc.length - 1].options.push(option);\n } else {\n if (process.env.NODE_ENV !== 'production') {\n if (indexBy.get(group) && !warn) {\n console.warn(`MUI: The options provided combined with the \\`groupBy\\` method of ${componentName} returns duplicated headers.`, 'You can solve the issue by sorting the options with the output of `groupBy`.');\n warn = true;\n }\n indexBy.set(group, true);\n }\n acc.push({\n key: index,\n index,\n group,\n options: [option]\n });\n }\n return acc;\n }, []);\n }\n if (disabledProp && focused) {\n handleBlur();\n }\n return {\n getRootProps: (other = {}) => _extends({\n 'aria-owns': listboxAvailable ? `${id}-listbox` : null\n }, other, {\n onKeyDown: handleKeyDown(other),\n onMouseDown: handleMouseDown,\n onClick: handleClick\n }),\n getInputLabelProps: () => ({\n id: `${id}-label`,\n htmlFor: id\n }),\n getInputProps: () => ({\n id,\n value: inputValue,\n onBlur: handleBlur,\n onFocus: handleFocus,\n onChange: handleInputChange,\n onMouseDown: handleInputMouseDown,\n // if open then this is handled imperatively so don't let react override\n // only have an opinion about this when closed\n 'aria-activedescendant': popupOpen ? '' : null,\n 'aria-autocomplete': autoComplete ? 'both' : 'list',\n 'aria-controls': listboxAvailable ? `${id}-listbox` : undefined,\n 'aria-expanded': listboxAvailable,\n // Disable browser's suggestion that might overlap with the popup.\n // Handle autocomplete but not autofill.\n autoComplete: 'off',\n ref: inputRef,\n autoCapitalize: 'none',\n spellCheck: 'false',\n role: 'combobox',\n disabled: disabledProp\n }),\n getClearProps: () => ({\n tabIndex: -1,\n type: 'button',\n onClick: handleClear\n }),\n getPopupIndicatorProps: () => ({\n tabIndex: -1,\n type: 'button',\n onClick: handlePopupIndicator\n }),\n getTagProps: ({\n index\n }) => _extends({\n key: index,\n 'data-tag-index': index,\n tabIndex: -1\n }, !readOnly && {\n onDelete: handleTagDelete(index)\n }),\n getListboxProps: () => ({\n role: 'listbox',\n id: `${id}-listbox`,\n 'aria-labelledby': `${id}-label`,\n ref: handleListboxRef,\n onMouseDown: event => {\n // Prevent blur\n event.preventDefault();\n }\n }),\n getOptionProps: ({\n index,\n option\n }) => {\n var _getOptionKey;\n const selected = (multiple ? value : [value]).some(value2 => value2 != null && isOptionEqualToValue(option, value2));\n const disabled = getOptionDisabled ? getOptionDisabled(option) : false;\n return {\n key: (_getOptionKey = getOptionKey == null ? void 0 : getOptionKey(option)) != null ? _getOptionKey : getOptionLabel(option),\n tabIndex: -1,\n role: 'option',\n id: `${id}-option-${index}`,\n onMouseMove: handleOptionMouseMove,\n onClick: handleOptionClick,\n onTouchStart: handleOptionTouchStart,\n 'data-option-index': index,\n 'aria-disabled': disabled,\n 'aria-selected': selected\n };\n },\n id,\n inputValue,\n value,\n dirty,\n expanded: popupOpen && anchorEl,\n popupOpen,\n focused: focused || focusedTag !== -1,\n anchorEl,\n setAnchorEl,\n focusedTag,\n groupedOptions\n };\n}\nexport default useAutocomplete;","'use client';\n\nimport * as React from 'react';\nconst usePreviousProps = value => {\n const ref = React.useRef({});\n React.useEffect(() => {\n ref.current = value;\n });\n return ref.current;\n};\nexport default usePreviousProps;","import generateUtilityClasses from '@mui/utils/generateUtilityClasses';\nimport generateUtilityClass from '@mui/utils/generateUtilityClass';\nexport function getListSubheaderUtilityClass(slot) {\n return generateUtilityClass('MuiListSubheader', slot);\n}\nconst listSubheaderClasses = generateUtilityClasses('MuiListSubheader', ['root', 'colorPrimary', 'colorInherit', 'gutters', 'inset', 'sticky']);\nexport default listSubheaderClasses;","'use client';\n\nimport _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\nconst _excluded = [\"className\", \"color\", \"component\", \"disableGutters\", \"disableSticky\", \"inset\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport composeClasses from '@mui/utils/composeClasses';\nimport styled from '../styles/styled';\nimport { useDefaultProps } from '../DefaultPropsProvider';\nimport capitalize from '../utils/capitalize';\nimport { getListSubheaderUtilityClass } from './listSubheaderClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nconst useUtilityClasses = ownerState => {\n const {\n classes,\n color,\n disableGutters,\n inset,\n disableSticky\n } = ownerState;\n const slots = {\n root: ['root', color !== 'default' && `color${capitalize(color)}`, !disableGutters && 'gutters', inset && 'inset', !disableSticky && 'sticky']\n };\n return composeClasses(slots, getListSubheaderUtilityClass, classes);\n};\nconst ListSubheaderRoot = styled('li', {\n name: 'MuiListSubheader',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.root, ownerState.color !== 'default' && styles[`color${capitalize(ownerState.color)}`], !ownerState.disableGutters && styles.gutters, ownerState.inset && styles.inset, !ownerState.disableSticky && styles.sticky];\n }\n})(({\n theme,\n ownerState\n}) => _extends({\n boxSizing: 'border-box',\n lineHeight: '48px',\n listStyle: 'none',\n color: (theme.vars || theme).palette.text.secondary,\n fontFamily: theme.typography.fontFamily,\n fontWeight: theme.typography.fontWeightMedium,\n fontSize: theme.typography.pxToRem(14)\n}, ownerState.color === 'primary' && {\n color: (theme.vars || theme).palette.primary.main\n}, ownerState.color === 'inherit' && {\n color: 'inherit'\n}, !ownerState.disableGutters && {\n paddingLeft: 16,\n paddingRight: 16\n}, ownerState.inset && {\n paddingLeft: 72\n}, !ownerState.disableSticky && {\n position: 'sticky',\n top: 0,\n zIndex: 1,\n backgroundColor: (theme.vars || theme).palette.background.paper\n}));\nconst ListSubheader = /*#__PURE__*/React.forwardRef(function ListSubheader(inProps, ref) {\n const props = useDefaultProps({\n props: inProps,\n name: 'MuiListSubheader'\n });\n const {\n className,\n color = 'default',\n component = 'li',\n disableGutters = false,\n disableSticky = false,\n inset = false\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n const ownerState = _extends({}, props, {\n color,\n component,\n disableGutters,\n disableSticky,\n inset\n });\n const classes = useUtilityClasses(ownerState);\n return /*#__PURE__*/_jsx(ListSubheaderRoot, _extends({\n as: component,\n className: clsx(classes.root, className),\n ref: ref,\n ownerState: ownerState\n }, other));\n});\nListSubheader.muiSkipListHighlight = true;\nprocess.env.NODE_ENV !== \"production\" ? ListSubheader.propTypes /* remove-proptypes */ = {\n // ┌────────────────────────────── Warning ──────────────────────────────┐\n // │ These PropTypes are generated from the TypeScript type definitions. │\n // │ To update them, edit the d.ts file and run `pnpm proptypes`. │\n // └─────────────────────────────────────────────────────────────────────┘\n /**\n * The content of the component.\n */\n children: PropTypes.node,\n /**\n * Override or extend the styles applied to the component.\n */\n classes: PropTypes.object,\n /**\n * @ignore\n */\n className: PropTypes.string,\n /**\n * The color of the component. It supports those theme colors that make sense for this component.\n * @default 'default'\n */\n color: PropTypes.oneOf(['default', 'inherit', 'primary']),\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes.elementType,\n /**\n * If `true`, the List Subheader will not have gutters.\n * @default false\n */\n disableGutters: PropTypes.bool,\n /**\n * If `true`, the List Subheader will not stick to the top during scroll.\n * @default false\n */\n disableSticky: PropTypes.bool,\n /**\n * If `true`, the List Subheader is indented.\n * @default false\n */\n inset: PropTypes.bool,\n /**\n * The system prop that allows defining system overrides as well as additional CSS styles.\n */\n sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])\n} : void 0;\nexport default ListSubheader;","import generateUtilityClasses from '@mui/utils/generateUtilityClasses';\nimport generateUtilityClass from '@mui/utils/generateUtilityClass';\nexport function getIconButtonUtilityClass(slot) {\n return generateUtilityClass('MuiIconButton', slot);\n}\nconst iconButtonClasses = generateUtilityClasses('MuiIconButton', ['root', 'disabled', 'colorInherit', 'colorPrimary', 'colorSecondary', 'colorError', 'colorInfo', 'colorSuccess', 'colorWarning', 'edgeStart', 'edgeEnd', 'sizeSmall', 'sizeMedium', 'sizeLarge']);\nexport default iconButtonClasses;","'use client';\n\nimport _objectWithoutPropertiesLoose from \"@babel/runtime/helpers/esm/objectWithoutPropertiesLoose\";\nimport _extends from \"@babel/runtime/helpers/esm/extends\";\nconst _excluded = [\"edge\", \"children\", \"className\", \"color\", \"disabled\", \"disableFocusRipple\", \"size\"];\nimport * as React from 'react';\nimport PropTypes from 'prop-types';\nimport clsx from 'clsx';\nimport chainPropTypes from '@mui/utils/chainPropTypes';\nimport composeClasses from '@mui/utils/composeClasses';\nimport { alpha } from '@mui/system/colorManipulator';\nimport styled from '../styles/styled';\nimport { useDefaultProps } from '../DefaultPropsProvider';\nimport ButtonBase from '../ButtonBase';\nimport capitalize from '../utils/capitalize';\nimport iconButtonClasses, { getIconButtonUtilityClass } from './iconButtonClasses';\nimport { jsx as _jsx } from \"react/jsx-runtime\";\nconst useUtilityClasses = ownerState => {\n const {\n classes,\n disabled,\n color,\n edge,\n size\n } = ownerState;\n const slots = {\n root: ['root', disabled && 'disabled', color !== 'default' && `color${capitalize(color)}`, edge && `edge${capitalize(edge)}`, `size${capitalize(size)}`]\n };\n return composeClasses(slots, getIconButtonUtilityClass, classes);\n};\nconst IconButtonRoot = styled(ButtonBase, {\n name: 'MuiIconButton',\n slot: 'Root',\n overridesResolver: (props, styles) => {\n const {\n ownerState\n } = props;\n return [styles.root, ownerState.color !== 'default' && styles[`color${capitalize(ownerState.color)}`], ownerState.edge && styles[`edge${capitalize(ownerState.edge)}`], styles[`size${capitalize(ownerState.size)}`]];\n }\n})(({\n theme,\n ownerState\n}) => _extends({\n textAlign: 'center',\n flex: '0 0 auto',\n fontSize: theme.typography.pxToRem(24),\n padding: 8,\n borderRadius: '50%',\n overflow: 'visible',\n // Explicitly set the default value to solve a bug on IE11.\n color: (theme.vars || theme).palette.action.active,\n transition: theme.transitions.create('background-color', {\n duration: theme.transitions.duration.shortest\n })\n}, !ownerState.disableRipple && {\n '&:hover': {\n backgroundColor: theme.vars ? `rgba(${theme.vars.palette.action.activeChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(theme.palette.action.active, theme.palette.action.hoverOpacity),\n // Reset on touch devices, it doesn't add specificity\n '@media (hover: none)': {\n backgroundColor: 'transparent'\n }\n }\n}, ownerState.edge === 'start' && {\n marginLeft: ownerState.size === 'small' ? -3 : -12\n}, ownerState.edge === 'end' && {\n marginRight: ownerState.size === 'small' ? -3 : -12\n}), ({\n theme,\n ownerState\n}) => {\n var _palette;\n const palette = (_palette = (theme.vars || theme).palette) == null ? void 0 : _palette[ownerState.color];\n return _extends({}, ownerState.color === 'inherit' && {\n color: 'inherit'\n }, ownerState.color !== 'inherit' && ownerState.color !== 'default' && _extends({\n color: palette == null ? void 0 : palette.main\n }, !ownerState.disableRipple && {\n '&:hover': _extends({}, palette && {\n backgroundColor: theme.vars ? `rgba(${palette.mainChannel} / ${theme.vars.palette.action.hoverOpacity})` : alpha(palette.main, theme.palette.action.hoverOpacity)\n }, {\n // Reset on touch devices, it doesn't add specificity\n '@media (hover: none)': {\n backgroundColor: 'transparent'\n }\n })\n }), ownerState.size === 'small' && {\n padding: 5,\n fontSize: theme.typography.pxToRem(18)\n }, ownerState.size === 'large' && {\n padding: 12,\n fontSize: theme.typography.pxToRem(28)\n }, {\n [`&.${iconButtonClasses.disabled}`]: {\n backgroundColor: 'transparent',\n color: (theme.vars || theme).palette.action.disabled\n }\n });\n});\n\n/**\n * Refer to the [Icons](/material-ui/icons/) section of the documentation\n * regarding the available icon options.\n */\nconst IconButton = /*#__PURE__*/React.forwardRef(function IconButton(inProps, ref) {\n const props = useDefaultProps({\n props: inProps,\n name: 'MuiIconButton'\n });\n const {\n edge = false,\n children,\n className,\n color = 'default',\n disabled = false,\n disableFocusRipple = false,\n size = 'medium'\n } = props,\n other = _objectWithoutPropertiesLoose(props, _excluded);\n const ownerState = _extends({}, props, {\n edge,\n color,\n disabled,\n disableFocusRipple,\n size\n });\n const classes = useUtilityClasses(ownerState);\n return /*#__PURE__*/_jsx(IconButtonRoot, _extends({\n className: clsx(classes.root, className),\n centerRipple: true,\n focusRipple: !disableFocusRipple,\n disabled: disabled,\n ref: ref\n }, other, {\n ownerState: ownerState,\n children: children\n }));\n});\nprocess.env.NODE_ENV !== \"production\" ? IconButton.propTypes /* remove-proptypes */ = {\n // ┌────────────────────────────── Warning ──────────────────────────────┐\n // │ These PropTypes are generated from the TypeScript type definitions. │\n // │ To update them, edit the d.ts file and run `pnpm proptypes`. │\n // └─────────────────────────────────────────────────────────────────────┘\n /**\n * The icon to display.\n */\n children: chainPropTypes(PropTypes.node, props => {\n const found = React.Children.toArray(props.children).some(child => /*#__PURE__*/React.isValidElement(child) && child.props.onClick);\n if (found) {\n return new Error(['MUI: You are providing an onClick event listener to a child of a button element.', 'Prefer applying it to the IconButton directly.', 'This guarantees that the whole