diff --git a/src/components/MoonIcon/MoonIcon.tsx b/src/components/MoonIcon/MoonIcon.tsx index 43c3b31..a4d9c26 100644 --- a/src/components/MoonIcon/MoonIcon.tsx +++ b/src/components/MoonIcon/MoonIcon.tsx @@ -23,9 +23,9 @@ function MoonIcon({ ); diff --git a/src/components/SunIcon/SunIcon.tsx b/src/components/SunIcon/SunIcon.tsx index 7488b99..0abb099 100644 --- a/src/components/SunIcon/SunIcon.tsx +++ b/src/components/SunIcon/SunIcon.tsx @@ -23,9 +23,9 @@ function SunIcon({ ); diff --git a/src/emotion.d.ts b/src/emotion.d.ts index 31b7385..9b7f296 100644 --- a/src/emotion.d.ts +++ b/src/emotion.d.ts @@ -22,9 +22,21 @@ declare module '@emotion/react' { normal: string; contrast: string; }; - primary: string; - secondary: string; - tertiary: string; + primary: { + dim: string; + normal: string; + contrast: string; + }; + secondary: { + dim: string; + normal: string; + contrast: string; + }; + tertiary: { + dim: string; + normal: string; + contrast: string; + }; }; }; } diff --git a/src/pages/home/Home.styled.ts b/src/pages/home/Home.styled.ts index 329e7fe..5037624 100644 --- a/src/pages/home/Home.styled.ts +++ b/src/pages/home/Home.styled.ts @@ -8,7 +8,7 @@ import TasksQueueBase from './sections/TasksQueue/TasksQueue.tsx'; import MicroTasksQueueBase from './sections/MicroTasksQueue/MicroTasksQueue.tsx'; import InfoBase from './sections/Info/Info.tsx'; import ConfiguratorBase from './sections/Configurator/Configurator.tsx'; -import EventLoopBase from './sections/Wheel/Wheel.tsx'; +import EventLoopBase from 'pages/home/sections/EventLoop/EventLoop.tsx'; export const sharedColumnStyles = ({ theme }: { theme: Theme }) => css` display: flex; diff --git a/src/pages/home/sections/Wheel/Wheel.modal.tsx b/src/pages/home/sections/EventLoop/EventLoop.modal.tsx similarity index 90% rename from src/pages/home/sections/Wheel/Wheel.modal.tsx rename to src/pages/home/sections/EventLoop/EventLoop.modal.tsx index 5c41f21..8a0765c 100644 --- a/src/pages/home/sections/Wheel/Wheel.modal.tsx +++ b/src/pages/home/sections/EventLoop/EventLoop.modal.tsx @@ -1,7 +1,7 @@ -import * as Styled from './Wheel.styled.ts'; +import * as Styled from './EventLoop.styled.ts'; import InfoModal from 'components/Modal/Modal.tsx'; -function WheelModal({ +function EventLoopModal({ isOpened, toggle, }: { @@ -38,4 +38,4 @@ function WheelModal({ ); } -export default WheelModal; +export default EventLoopModal; diff --git a/src/pages/home/sections/EventLoop/EventLoop.styled.ts b/src/pages/home/sections/EventLoop/EventLoop.styled.ts new file mode 100644 index 0000000..b7e91d8 --- /dev/null +++ b/src/pages/home/sections/EventLoop/EventLoop.styled.ts @@ -0,0 +1,17 @@ +import styled from '@emotion/styled'; +import InfoClosed from 'components/CloseIcon/InfoIcon.tsx'; + +export const CloseIcon = styled(InfoClosed)` + position: absolute; + top: 16px; + right: 16px; +`; + +export const EventLoopBody = styled.div` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + flex: 1; + padding-top: 10px; +`; diff --git a/src/pages/home/sections/EventLoop/EventLoop.tsx b/src/pages/home/sections/EventLoop/EventLoop.tsx new file mode 100644 index 0000000..45b7375 --- /dev/null +++ b/src/pages/home/sections/EventLoop/EventLoop.tsx @@ -0,0 +1,24 @@ +import * as Styled from './EventLoop.styled.ts'; +import InfoIcon from 'components/InfoIcon/InfoIcon.tsx'; +import useBoolean from 'utils/hooks/useBoolean.ts'; +import { BaseLayoutElement } from 'pages/home/Home.styled.ts'; +import { EVENT_LOOP_ID } from 'utils/constants.ts'; +import EventLoopModal from './EventLoop.modal.tsx'; +import Wheel from 'pages/home/sections/EventLoop/Wheel/Wheel.tsx'; + +function EventLoop({ className }: { className?: string }) { + const [isOpened, toggle] = useBoolean(false); + + return ( + +

Event Loop

+ + + + + +
+ ); +} + +export default EventLoop; diff --git a/src/pages/home/sections/Wheel/Wheel.types.ts b/src/pages/home/sections/EventLoop/EventLoop.types.ts similarity index 100% rename from src/pages/home/sections/Wheel/Wheel.types.ts rename to src/pages/home/sections/EventLoop/EventLoop.types.ts diff --git a/src/pages/home/sections/Wheel/Wheel.data.ts b/src/pages/home/sections/EventLoop/Wheel/Wheel.data.ts similarity index 92% rename from src/pages/home/sections/Wheel/Wheel.data.ts rename to src/pages/home/sections/EventLoop/Wheel/Wheel.data.ts index 9735dbe..fb15ff6 100644 --- a/src/pages/home/sections/Wheel/Wheel.data.ts +++ b/src/pages/home/sections/EventLoop/Wheel/Wheel.data.ts @@ -1,4 +1,4 @@ -import { EventInterface } from './Wheel.types.ts'; +import { EventInterface } from '../EventLoop.types.ts'; export const events: EventInterface[] = [ { diff --git a/src/pages/home/sections/Wheel/Wheel.styled.ts b/src/pages/home/sections/EventLoop/Wheel/Wheel.styled.ts similarity index 85% rename from src/pages/home/sections/Wheel/Wheel.styled.ts rename to src/pages/home/sections/EventLoop/Wheel/Wheel.styled.ts index 8733d1a..e061338 100644 --- a/src/pages/home/sections/Wheel/Wheel.styled.ts +++ b/src/pages/home/sections/EventLoop/Wheel/Wheel.styled.ts @@ -1,6 +1,5 @@ import styled from '@emotion/styled'; import { css } from '@emotion/react'; -import InfoClosed from 'components/CloseIcon/InfoIcon.tsx'; export const CircleContainer = styled.div( ({ theme }) => css` @@ -79,18 +78,3 @@ export const Sector = styled.div<{ } `; }); - -export const CloseIcon = styled(InfoClosed)` - position: absolute; - top: 16px; - right: 16px; -`; - -export const EventLoopBody = styled.div` - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - flex: 1; - padding-top: 10px; -`; diff --git a/src/pages/home/sections/EventLoop/Wheel/Wheel.tsx b/src/pages/home/sections/EventLoop/Wheel/Wheel.tsx new file mode 100644 index 0000000..db704ca --- /dev/null +++ b/src/pages/home/sections/EventLoop/Wheel/Wheel.tsx @@ -0,0 +1,227 @@ +import * as Styled from './Wheel.styled.ts'; +import { useTheme } from '@emotion/react'; +import { useTimeStore, useWheelStore } from 'store/store.ts'; +import { useEffect } from 'react'; + +const POINTER_TOP_ID = 'wheel-pointer-top'; +const POINTER_BOTTOM_ID = 'wheel-pointer-bottom'; +const POINTER_LEFT_ID = 'wheel-pointer-left'; +const POINTER_RIGHT_ID = 'wheel-pointer-right'; +const WHEEL_ID = 'wheel'; + +const MICROTASK_CLASS = 'microtask'; +const MACROTASK_CLASS = 'macrotask'; +const RENDER_CLASS = 'render'; + +const SEGMENT_OFFSET = -9; +const POINTER_OFFSET = -99; + +function Wheel() { + const theme = useTheme(); + const { render, macrotask, microtask } = useWheelStore((state) => state); + + const colors = { + text: theme.custom.colors.onContainer.contrast, + pointer: theme.custom.colors.onContainer.contrast, + wheel: theme.custom.colors.onContainer.dim, + background: theme.custom.colors.container, + microtask: { + disabled: theme.custom.colors.primary.dim, + enabled: theme.custom.colors.primary.contrast, + }, + macrotask: { + disabled: theme.custom.colors.secondary.dim, + enabled: theme.custom.colors.secondary.contrast, + }, + render: { + disabled: theme.custom.colors.tertiary.dim, + enabled: theme.custom.colors.tertiary.contrast, + }, + }; + + const fill = { + render: render ? colors.render.enabled : colors.render.disabled, + macrotask: macrotask ? colors.macrotask.enabled : colors.macrotask.disabled, + microtask: microtask ? colors.microtask.enabled : colors.microtask.disabled, + }; + + useEffect(() => { + return useTimeStore.subscribe(({ grad }) => { + const top = document.getElementById(POINTER_TOP_ID); + const right = document.getElementById(POINTER_RIGHT_ID); + const left = document.getElementById(POINTER_LEFT_ID); + const bottom = document.getElementById(POINTER_BOTTOM_ID); + + const corrected = grad + POINTER_OFFSET; + + if (top && right && left && bottom) { + top.style.transform = `rotate(${corrected}deg)`; + right.style.transform = `rotate(${corrected + 18}deg)`; + left.style.transform = `rotate(${corrected}deg)`; + bottom.style.transform = `rotate(${corrected}deg)`; + } + }); + }, []); + + return ( + + + + + + + + + Microtask + + + Render + + + Microtask + + + Microtask + + + Task + + + Microtask + + + + + + + + mTMicrotask + + + mTMicrotask + + + mTMicrotask + + + mTMicrotask + + + RRender + + + TTask + + + + ); +} + +export default Wheel; diff --git a/src/pages/home/sections/Wheel/CircleLabels/CircleLabels.styled.ts b/src/pages/home/sections/Wheel/CircleLabels/CircleLabels.styled.ts deleted file mode 100644 index c9b764f..0000000 --- a/src/pages/home/sections/Wheel/CircleLabels/CircleLabels.styled.ts +++ /dev/null @@ -1,22 +0,0 @@ -import styled from '@emotion/styled'; -import { css } from '@emotion/react'; - -export const LabelsWrapper = styled.div` - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; -`; - -export const Label = styled.p<{ left: number; top: number }>( - ({ left, top }) => css` - position: absolute; - left: ${left}px; - top: ${top}px; - margin: 0; - transform: translate(-50%, -50%); - padding: 10px 7px; - cursor: default; - ` -); diff --git a/src/pages/home/sections/Wheel/CircleLabels/CircleLabels.tsx b/src/pages/home/sections/Wheel/CircleLabels/CircleLabels.tsx deleted file mode 100644 index 4670b37..0000000 --- a/src/pages/home/sections/Wheel/CircleLabels/CircleLabels.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { events } from '../Wheel.data.ts'; -import * as Styled from './CircleLabels.styled.ts'; -import { Tooltip } from '@mui/material'; - -const enhancedEvents = events.map((event) => { - const cos = Math.cos((event.degree * Math.PI) / 180); - const sin = Math.sin((event.degree * Math.PI) / 180); - const leftOffset = 150 + cos * (150 - 25); - const topOffset = 150 + sin * (150 - 25); - return { - ...event, - leftOffset, - topOffset, - }; -}); - -function CircleLabels() { - return ( - - {enhancedEvents.map( - ({ title, longTitle, leftOffset, topOffset, degree, placement }) => ( - - - {title} - - - ) - )} - - ); -} - -export default CircleLabels; diff --git a/src/pages/home/sections/Wheel/Pointer/Pointer.styled.ts b/src/pages/home/sections/Wheel/Pointer/Pointer.styled.ts deleted file mode 100644 index b1dfb65..0000000 --- a/src/pages/home/sections/Wheel/Pointer/Pointer.styled.ts +++ /dev/null @@ -1,94 +0,0 @@ -import styled from '@emotion/styled'; -import { css } from '@emotion/react'; - -export const SectorWithInnerBorder = styled.div( - ({ - theme: { - custom: { - widths: { - eventLoopRadius, - eventLoopDiameter, - eventLoopWheelWidth, - eventLoopPointerBorderWidth, - }, - colors, - }, - }, - }) => css` - height: ${eventLoopRadius - - eventLoopWheelWidth + - eventLoopPointerBorderWidth}px; - width: ${eventLoopDiameter - - eventLoopWheelWidth * 2 + - eventLoopPointerBorderWidth * 2}px; - left: ${eventLoopWheelWidth - eventLoopPointerBorderWidth}px; - top: ${eventLoopWheelWidth - eventLoopPointerBorderWidth}px; - overflow: hidden; - position: absolute; - transform-origin: 50% 100%; - transform: rotate(279.5deg); - border-image: linear-gradient( - to right, - transparent 50%, - ${colors.onContainer.contrast} 50% - ); - box-sizing: border-box; - - &:before { - height: inherit; - width: inherit; - position: absolute; - content: ''; - border-radius: ${eventLoopRadius - - eventLoopWheelWidth + - eventLoopPointerBorderWidth}px - ${eventLoopRadius - eventLoopWheelWidth + eventLoopPointerBorderWidth}px - 0 0; - transform-origin: 50% 100%; - transform: rotate(160deg); - border-left: ${eventLoopPointerBorderWidth}px solid - ${colors.onContainer.contrast}; - box-sizing: border-box; - left: 0; - } - ` -); - -export const SectorWithOuterBorder = styled.div( - ({ - theme: { - custom: { widths, colors }, - }, - }) => css` - height: ${widths.eventLoopRadius}px; - width: ${widths.eventLoopDiameter}px; - overflow: hidden; - position: absolute; - transform-origin: 50% 100%; - transform: rotate(280deg); - border-bottom: ${widths.eventLoopPointerBorderWidth}px solid transparent; - border-image: linear-gradient( - to right, - transparent 50%, - ${colors.onContainer.contrast} 50% - ) - 1; - box-sizing: border-box; - - &:before { - height: inherit; - width: inherit; - position: absolute; - content: ''; - border-radius: ${widths.eventLoopRadius}px ${widths.eventLoopRadius}px 0 0; - border-bottom: ${widths.eventLoopPointerBorderWidth}px solid - ${colors.onContainer.contrast}; - transform-origin: 50% 100%; - transform: rotate(160deg); - border-left: ${widths.eventLoopPointerBorderWidth}px solid - ${colors.onContainer.contrast}; - box-sizing: border-box; - left: 0; - } - ` -); diff --git a/src/pages/home/sections/Wheel/Pointer/Pointer.tsx b/src/pages/home/sections/Wheel/Pointer/Pointer.tsx deleted file mode 100644 index f62c16a..0000000 --- a/src/pages/home/sections/Wheel/Pointer/Pointer.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import * as Styled from './Pointer.styled.ts'; -import { useTimeStore } from 'store/store.ts'; -import { useEffect } from 'react'; - -const INNER_POINTER_ID = 'InnerPointerId'; -const OUTER_POINTER_ID = 'OuterPointerId'; - -function Pointer() { - useEffect(() => { - return useTimeStore.subscribe(({ grad }) => { - const innerBorder = document.getElementById(INNER_POINTER_ID); - const outerBorder = document.getElementById(OUTER_POINTER_ID); - - if (innerBorder && outerBorder) { - innerBorder.style.transform = `rotate(${grad - 80}deg)`; - outerBorder.style.transform = `rotate(${grad - 80}deg)`; - } - }); - }, []); - - return ( - <> - - - - ); -} - -export default Pointer; diff --git a/src/pages/home/sections/Wheel/Wheel.tsx b/src/pages/home/sections/Wheel/Wheel.tsx deleted file mode 100644 index 190d726..0000000 --- a/src/pages/home/sections/Wheel/Wheel.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import Pointer from './Pointer/Pointer.tsx'; -import CircleLabels from './CircleLabels/CircleLabels.tsx'; -import { events } from './Wheel.data.ts'; -import * as Styled from './Wheel.styled.ts'; -import { useTheme } from '@emotion/react'; -import InfoIcon from 'components/InfoIcon/InfoIcon.tsx'; -import useBoolean from 'utils/hooks/useBoolean.ts'; -import { BaseLayoutElement } from 'pages/home/Home.styled.ts'; -import { EVENT_LOOP_ID } from 'utils/constants.ts'; -import WheelModal from './Wheel.modal.tsx'; -import { useWheelStore } from 'store/store.ts'; - -function Wheel({ className }: { className?: string }) { - const microtask = useWheelStore((state) => state.microtask); - const render = useWheelStore((state) => state.render); - const macrotask = useWheelStore((state) => state.macrotask); - const stops = { microtask, render, macrotask }; - const theme = useTheme(); - const [isOpened, toggle] = useBoolean(false); - - const { primary, secondary, tertiary } = theme.custom.colors; - const colors = { - microtask: primary, - macrotask: secondary, - render: tertiary, - }; - - return ( - -

Event Loop

- - - - - {events.map(({ degree, type }) => { - const enabled = stops[type]; - const background = colors[type]; - return ( - - ); - })} - - - - - - -
- ); -} - -export default Wheel; diff --git a/src/theme/colors.ts b/src/theme/colors.ts index 41b908e..69dff05 100644 --- a/src/theme/colors.ts +++ b/src/theme/colors.ts @@ -14,9 +14,21 @@ export const colorsDark = { normal: palette.primary['50'], contrast: palette.primary['90'], }, - primary: palette.primary['60'], - secondary: palette.secondary['60'], - tertiary: palette.tertiary['60'], + primary: { + dim: 'rgba(86, 121, 135, 0.3)', + normal: palette.primary['60'], + contrast: 'rgba(86, 121, 135, 1)', + }, + secondary: { + dim: 'rgba(95, 161, 101, 0.3)', + normal: palette.secondary['60'], + contrast: 'rgba(95, 161, 101, 1)', + }, + tertiary: { + dim: 'rgba(181, 92, 101, 0.3)', + normal: palette.tertiary['60'], + contrast: 'rgba(181, 92, 101, 1)', + }, }, }; @@ -31,8 +43,20 @@ export const colorsLight = { normal: palette.primary['50'], contrast: palette.primary['30'], }, - primary: palette.primary['50'], - secondary: palette.secondary['50'], - tertiary: palette.tertiary['50'], + primary: { + dim: 'rgba(86, 121, 135, 0.3)', + normal: palette.primary['50'], + contrast: 'rgba(86, 121, 135, 1)', + }, + secondary: { + dim: 'rgba(95, 161, 101, 0.3)', + normal: palette.secondary['50'], + contrast: 'rgba(95, 161, 101, 1)', + }, + tertiary: { + dim: 'rgba(181, 92, 101, 0.3)', + normal: palette.tertiary['50'], + contrast: 'rgba(181, 92, 101, 1)', + }, }, };