diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..ab905aa --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "singleQuote": true, + "semi": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 3 +} diff --git a/README.md b/README.md index 820935e..0817e84 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # 2주차 과제: React Todo + # 서론 안녕하세요 🙌🏻 22기 프론트엔드 운영진 **권동욱**입니다. @@ -25,7 +26,7 @@ - VSCode, Prettier를 이용하여 개발환경을 관리합니다. - React의 기초를 이해합니다. - React를 통한 어플리케이션 상태 관리 방법을 이해합니다. -- React Hooks에 대한 기초를 이해합니다. +- React Hooks에 대한 기초를 이해합니다. - Vite를 통한 React 프로젝트 개발환경 구축을 익힙니다. - Styled-Components를 통한 CSS-in-JS 및 CSS Preprocessor의 사용법을 익힙니다. @@ -40,14 +41,15 @@ - React 컴포넌트 생명주기에 대해서 설명해주세요. ## 필수 요건 + - 1주차 미션의 결과물을 그대로 React로 구현합니다. (‼️ todo / done 개수 잊지 마세요 ‼️) - Styled-Component를 사용합니다. -- React Hooks만을 사용해 상태를 관리합니다.(전역 상태관리 라이브러리 사용 XX) +- React Hooks만을 사용해 상태를 관리합니다.(전역 상태관리 라이브러리 사용 XX) - Vite를 활용하여 React 프로젝트 환경 구축을 진행합니다 ## 선택 요건 -- 기존 Todo-list에 여러분들이 추가하고 싶은 기능과 디자인을 자유롭게 추가해보세요. +- 기존 Todo-list에 여러분들이 추가하고 싶은 기능과 디자인을 자유롭게 추가해보세요. - TypeScript를 활용하여 프로젝트를 진행해보세요. ## 로컬 실행방법 @@ -64,6 +66,6 @@ - [useState, useEffect hooks](https://velog.io/@velopert/react-hooks#1-usestate) - [styled-component](https://styled-components.com/docs/basics#getting-started)
 - [create react app (CRA) 지원종료 공식문서](https://react.dev/blog/2025/02/14/sunsetting-create-react-app)
 -- [create react app 지원종료관련 okky 커뮤니티 게시글](https://okky.kr/articles/1527414) -- [cra 대신에 vite로 React 프로젝트 시작하기](https://www.daleseo.com/vite-react/) +- [create react app 지원종료관련 okky 커뮤니티 게시글](https://okky.kr/articles/1527414) +- [cra 대신에 vite로 React 프로젝트 시작하기](https://www.daleseo.com/vite-react/) - [Vite 실무 적용기 - 설명 + 프로젝트 설정](https://blog.hectodata.co.kr/bonjour-vite/) diff --git a/demoscript.js b/demoscript.js new file mode 100644 index 0000000..70a8e3c --- /dev/null +++ b/demoscript.js @@ -0,0 +1,233 @@ +document.addEventListener('DOMContentLoaded', () => { + //menu tab + const menuTab = document.getElementById('menuTab'); + const openBtn = document.querySelector('.menu'); + const closeBtn = document.getElementById('closeMenu'); + + //open and close menu drawer + const openDrawer = () => { + menuTab.classList.add('active'); + }; + const closeDrawer = () => { + menuTab.classList.remove('active'); + }; + + openBtn.addEventListener('click', openDrawer); + closeBtn.addEventListener('click', closeDrawer); + + //close menu when clicked outside of menu tab + document.addEventListener('click', (e) => { + if ( + menuTab.classList.contains('active') && + !menuTab.contains(e.target) && + !openBtn.contains(e.target) + ) { + closeDrawer(); + } + }); + + //close menu when user presses esc + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && menuTab.classList.contains('active')) closeDrawer(); + }); + + //define date manipulating buttons + const today = document.querySelector('.today'); + const prevBtn = document.getElementById('yesterday'); + const nextBtn = document.getElementById('tomorrow'); + + //get date + let current = new Date(); + const fmt = { year: 'numeric', month: 'long', day: 'numeric' }; + + //Date manipulation + function render() { + today.textContent = current.toLocaleDateString(undefined, fmt); + } + render(); + + //define next and last week buttons in menu + const nWeek = document.querySelector('.nWeek'); + const lWeek = document.querySelector('.lWeek'); + + //피드백 주신 대로 changWeek함수를 만들고 +7/-7을 인자로 남겨 처리했습니다 + function changeDays(offSetDays) { + current.setDate(current.getDate() + offSetDays); + render(); + loadList(current); + ifNoEvents(); + } + nWeek.addEventListener('click', () => { + changeDays(7); + }); + lWeek.addEventListener('click', () => { + changeDays(-7); + }); + + prevBtn.addEventListener('click', () => { + changeDays(-1); + }); + + nextBtn.addEventListener('click', () => { + changeDays(1); + }); + + //when the date is clicked on, change current date to today + today.addEventListener('click', () => { + current = new Date(); + render(); + loadList(current); + }); + + const dateKey = (d) => new Date(d).toLocaleDateString('en-CA'); + // "YYYY-MM-DD" in local time + const storageKey = (d) => `${dateKey(d)}`; + + const numEvent = document.querySelector('.numEvent'); + + //saves the events for a date + function saveList(date) { + const dateData = { + dateTodoEl: todoEl.innerHTML, + dateTodos: todos, + }; + sessionStorage.setItem(storageKey(date), JSON.stringify(dateData)); + } + + //loads the events for a date + function loadList(date) { + const raw = sessionStorage.getItem(storageKey(date) || ''); + if (raw) { + const parsed = JSON.parse(raw); + todoEl.innerHTML = parsed.dateTodoEl; + todos = parsed.dateTodos; + } else { + todos = []; + todoEl.innerHTML = ''; + } + getNumEvent(); + } + + const input = document.querySelector('.input'); + const add = document.querySelector('.register'); + const todoEl = document.querySelector('.todoEl'); + const clearAll = document.querySelector('.clearAll'); + + let todos = []; + + //event listener that is restored once loaded from storage + todoEl.addEventListener('click', (e) => { + //선택된 li + const li = e.target.closest('li'); + //선택된 li의 index number을 idx라 명명 + const id = li.dataset.id; + const idx = todos.findIndex((t) => t.id === id); + + //delete button + if (e.target && e.target.classList.contains('delEvent')) { + todos.splice(idx, 1); + } + + //done button + if (e.target && e.target.classList.contains('doneEvent')) { + todos[idx].done = !todos[idx].done; + console.log('done'); + } + //pin and unpin events + if (e.target && e.target.classList.contains('pinEvent')) { + todos[idx].pinned = !todos[idx].pinned; + } + + renderTodos(); + saveList(current); + ifNoEvents(); + getNumEvent(); + }); + + //add event using enter and button click + add.addEventListener('click', () => { + if (input.value !== '') { + addToList(input.value); + input.value = ''; + saveList(current); + } + }); + input.addEventListener('keydown', (e) => { + if (e.key === 'Enter' && input.value !== '') { + addToList(input.value); + input.value = ''; + saveList(current); + } + }); + + function addToList(text) { + const newTodo = { + id: crypto.randomUUID(), + done: false, + pinned: false, + text: text, + }; + todos.push(newTodo); + saveList(); + renderTodos(); + } + + function renderTodos() { + const sorted = [...todos].sort((a, b) => b.pinned - a.pinned); + todoEl.innerHTML = ''; + + for (const t of sorted) { + const li = document.createElement('li'); + li.dataset.id = t.id; + li.className = t.pinned ? 'pinned' : ''; + li.innerHTML = ` + + ${t.text} + + + `; + todoEl.appendChild(li); + } + getNumEvent(); + } + + //clear all events for a date + function clearALlEvents(date) { + todos = []; + renderTodos(); + saveList(current); + ifNoEvents(); + } + clearAll.addEventListener('click', () => { + clearALlEvents(current); + getNumEvent(); + }); + + function ifNoEvents() { + if (todos.length === 0) { + sessionStorage.removeItem(storageKey(current)); + } + } + + //get the number of Events + function getNumEvent() { + numEvent.textContent = 'To-do: ' + todoEl.children.length; + } + + //calendar manipulation + const menuContent = document.getElementById('menuContent'); + const datePickerEl = document.createElement('input'); + datePickerEl.type = 'date'; + datePickerEl.className = 'menuDatePicker'; // make it obvious + menuContent.appendChild(datePickerEl); + datePickerEl.addEventListener('change', () => { + if (!datePickerEl.value) return; + const [y, m, d] = datePickerEl.value.split('-').map(Number); + saveList(current); + current = new Date(y, m - 1, d); + render(); + loadList(current); + }); +}); diff --git a/index.html b/index.html new file mode 100644 index 0000000..daf38b2 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + react-todo 백승선 + + + +
+ + + + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..be09eb4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1233 @@ +{ + "name": "assignment2", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "assignment2", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1", + "styled-components": "^6.1.19" + }, + "devDependencies": { + "prettier": "^3.6.2", + "vite": "^7.1.6" + } + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", + "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", + "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz", + "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz", + "integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", + "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", + "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", + "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", + "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz", + "integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz", + "integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", + "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", + "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", + "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", + "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", + "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz", + "integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz", + "integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", + "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", + "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", + "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz", + "integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", + "license": "MIT" + }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/react": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.1" + } + }, + "node_modules/rollup": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz", + "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.50.2", + "@rollup/rollup-android-arm64": "4.50.2", + "@rollup/rollup-darwin-arm64": "4.50.2", + "@rollup/rollup-darwin-x64": "4.50.2", + "@rollup/rollup-freebsd-arm64": "4.50.2", + "@rollup/rollup-freebsd-x64": "4.50.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", + "@rollup/rollup-linux-arm-musleabihf": "4.50.2", + "@rollup/rollup-linux-arm64-gnu": "4.50.2", + "@rollup/rollup-linux-arm64-musl": "4.50.2", + "@rollup/rollup-linux-loong64-gnu": "4.50.2", + "@rollup/rollup-linux-ppc64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-musl": "4.50.2", + "@rollup/rollup-linux-s390x-gnu": "4.50.2", + "@rollup/rollup-linux-x64-gnu": "4.50.2", + "@rollup/rollup-linux-x64-musl": "4.50.2", + "@rollup/rollup-openharmony-arm64": "4.50.2", + "@rollup/rollup-win32-arm64-msvc": "4.50.2", + "@rollup/rollup-win32-ia32-msvc": "4.50.2", + "@rollup/rollup-win32-x64-msvc": "4.50.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/styled-components": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.19.tgz", + "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==", + "license": "MIT", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.49", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" + }, + "node_modules/vite": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.6.tgz", + "integrity": "sha512-SRYIB8t/isTwNn8vMB3MR6E+EQZM/WG1aKmmIUCfDXfVvKfc20ZpamngWHKzAmmu9ppsgxsg4b2I7c90JZudIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c8a45c6 --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "name": "assignment2", + "version": "1.0.0", + "description": "안녕하세요 🙌🏻 22기 프론트엔드 운영진 **권동욱**입니다.", + "main": "index.js", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "react": "^19.1.1", + "react-dom": "^19.1.1", + "styled-components": "^6.1.19" + }, + "devDependencies": { + "prettier": "^3.6.2", + "vite": "^7.1.6" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/baekseungsun/react-todo-22nd.git" + }, + "bugs": { + "url": "https://github.com/baekseungsun/react-todo-22nd/issues" + }, + "homepage": "https://github.com/baekseungsun/react-todo-22nd#readme" +} diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..a2843e5 --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,464 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import styled, { createGlobalStyle } from 'styled-components'; + +const GlobalStyle = createGlobalStyle` + * { box-sizing: border-box; } + body { margin: 0; font-family: Arial, sans-serif; background: #e2e8f0; color:#0f172a;} + button { cursor: pointer; } +`; + +//Styled components 이전 css파일에서 그대로 옮겨서 작성 +const Header = styled.header` + display: flex; + align-items: center; + justify-content: center; + background: #0f172a; + color: white; + padding: 14px 16px; + position: relative; +`; +const Title = styled.h1` + margin: 0; + font-size: 35px; + font-weight: 600; +`; +const MenuBtn = styled.button` + position: absolute; + left: 16px; + background: none; + border: none; + padding: 8px; +`; +const MenuIcon = styled.div` + width: 24px; + height: 2px; + background: white; + border-radius: 2px; + position: relative; + &::before, + &::after { + content: ''; + position: absolute; + left: 0; + width: 24px; + height: 2px; + background: white; + border-radius: 2px; + } + &::before { + top: -10px; + } + &::after { + top: 10px; + } +`; + +const Drawer = styled.aside` + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: 300px; + background: #e2e8f0; + transform: translateX(${(p) => (p.open ? '0' : '-100%')}); + transition: transform 0.25s ease; + z-index: 10; +`; +const DrawerInner = styled.nav` + display: flex; + height: 100%; + flex-direction: column; + gap: 8px; + font-size: 15px; + position: relative; + padding: 20px; +`; +const CloseBtn = styled.button` + position: absolute; + left: 20px; + top: 15px; + font-size: 30px; + width: 28px; + height: 28px; + background: none; + border: none; +`; +const DrawerOptions = styled.div` + display: flex; + flex-direction: column; + align-items: center; + gap: 110px; + margin-top: 80px; +`; +const WeekBtn = styled.button` + width: 120px; + height: 30px; + font-size: 16px; + border-radius: 10px; +`; + +const DateRow = styled.div` + display: flex; + align-items: center; + justify-content: center; + gap: 20px; + margin: 30px; +`; +const DateBtn = styled.button` + font-size: 20px; + background: none; + border: none; +`; +const TodayBtn = styled.button` + font-size: 20px; + background: none; + border: none; + color: #0f172a; +`; + +const InputRow = styled.div` + display: flex; + justify-content: center; + gap: 20px; + margin: 40px auto; + background: #fff; + border-radius: 20px; + padding-left: 10px; + width: 400px; + height: 50px; + align-items: center; +`; +const TextInput = styled.input` + flex: 1; + font-size: 23px; + border: none; + outline: none; + background: none; + color: #0f172a; +`; +const AddBtn = styled.button` + font-size: 15px; + width: 60px; + height: 25px; + border-radius: 13px; + border: 2px solid black; + background: #0f172a; + color: white; + margin-right: 6px; +`; + +const ListWrap = styled.div` + display: flex; + flex-direction: column; + gap: 6px; + height: 425px; + width: 600px; + margin: 0 auto; + background: whitesmoke; + border: 6px solid #0f172a; + border-radius: 20px; +`; +const TopRow = styled.div` + display: flex; +`; +const ClearBtn = styled.button` + color: #0f172a; + font-size: 20px; + border-radius: 20px; + width: 120px; + margin: 5px 0 0 10px; + background: #e2e8f0; +`; +const NumToDos = styled.div` + line-height: 1.5; + color: #0f172a; + font-size: 18px; + border-radius: 20px; + width: 120px; + margin-top: 5px; + margin-left: auto; + margin-right: 10px; + background: #e2e8f0; + border: 2px solid #0f172a; + padding-left: 20px; +`; + +const UL = styled.ul` + list-style: none; + padding: 0; + margin: 5px; + max-height: 350px; + overflow: auto; + display: flex; + flex-direction: column; + align-items: center; + gap: 14px; + font-size: 26px; +`; + +const LI = styled.li` + display: flex; + align-items: center; + gap: 8px; + padding: 10px 5px; + border: 3px solid #0f172a; + border-radius: 15px; + width: 550px; + background: #e2e8f0; +`; +const Txt = styled.span` + margin-left: 10px; + margin-right: auto; + font-size: 20px; +`; +const SmallBtn = styled.button` + border-radius: 20px; + font-size: 15px; + padding: 4px 10px; + border: ${(p) => (p.outline ? '1px solid black' : 'none')}; + background: ${(p) => (p.solid ? '#0f172a' : 'none')}; + color: ${(p) => (p.solid ? 'white' : '#0f172a')}; +`; +const DoneBtn = styled(SmallBtn)` + background: ${(p) => (p.active ? 'grey' : '#0f172a')}; + color: ${(p) => (p.active ? 'black' : 'white')}; +`; + +const PinBtn = styled(SmallBtn)` + background: ${(p) => (p.active ? 'crimson' : 'none')}; + color: ${(p) => (p.active ? 'white' : '#0f172a')}; +`; + + + +//Functions +const toDateKey = (d) => new Date(d).toLocaleDateString('en-CA'); // YYYY-MM-DD in local time + +export default function App() { + // 날짜와 메뉴 상태 + const [current, setCurrent] = useState(() => new Date()); + const [open, setOpen] = useState(false); + + // 날짜별 todos 저장용 + const [byDate, setByDate] = useState(() => { + return {}; + }); + + // 현재 날짜의 todos + const dateKey = toDateKey(current); + const todos = byDate[dateKey] ?? []; + + // pin기준 정렬 + const sorted = useMemo( + () => [...todos].sort((a, b) => Number(b.pinned) - Number(a.pinned)), + [todos], + ); + const total = todos.length; + + // 첫 로드 시 + useEffect(() => { + const raw = sessionStorage.getItem(dateKey); + if (raw) { + try { + const arr = JSON.parse(raw); + setByDate((prev) => ({...prev, [dateKey]: arr})); + } catch { + /* ignore */ + } + } else { + setByDate((prev) => ({...prev, [dateKey]: []})); + } + }, []); + + // 날짜 바뀜에 따라 롣드 + useEffect(() => { + const raw = sessionStorage.getItem(dateKey); + if (raw) { + try { + const arr = JSON.parse(raw); + setByDate((prev) => ({...prev, [dateKey]: arr})); + } catch { + setByDate((prev) => ({...prev, [dateKey]: []})); + } + } else { + setByDate((prev) => ({...prev, [dateKey]: []})); + } + }, [dateKey]); + + // 현재 날짜 todos 저장, 비어 있다면 해당 날짜 key 삭제 + const persist = useCallback( + (nextList) => { + if (!nextList || nextList.length === 0) { + sessionStorage.removeItem(dateKey); + } else { + sessionStorage.setItem(dateKey, JSON.stringify(nextList)); + } + }, + [dateKey], + ); + + //투두 추가 + const [text, setText] = useState(''); + const addTodo = useCallback(() => { + const v = text.trim(); + if (!v) return; + const next = [ + ...todos, + { id: crypto.randomUUID?.() || String(Date.now()), text: v, done: false, pinned: false }, + ]; + setByDate((prev) => ({ ...prev, [dateKey]: next })); + persist(next); + setText(''); + }, [text, todos, dateKey, persist]); + + //제거 + const deleteTodo = useCallback( + (id) => { + const next = todos.filter((t) => t.id !== id); + setByDate((prev) => ({ ...prev, [dateKey]: next })); + persist(next); + }, + [todos, dateKey, persist], + ); + + + //투두 done + const toggleDone = useCallback( + (id) => { + const next = todos.map((t) => (t.id === id ? { ...t, done: !t.done } : t)); + setByDate((prev) => ({ ...prev, [dateKey]: next })); + persist(next); + }, + [todos, dateKey, persist], + ); + + //투두 pin + const togglePin = useCallback( + (id) => { + const next = todos.map((t) => (t.id === id ? { ...t, pinned: !t.pinned } : t)); + setByDate((prev) => ({ ...prev, [dateKey]: next })); + persist(next); + }, + [todos, dateKey, persist], + ); + + //전체삭제 + const clearAll = useCallback(() => { + setByDate((prev) => ({ ...prev, [dateKey]: [] })); + sessionStorage.removeItem(dateKey); + }, [dateKey]); + + + + // 날짜 조작 + const changeDays = useCallback((offset) => { + setCurrent((prev) => { + const d = new Date(prev); + d.setDate(d.getDate() + offset); + return d; + }); + }, []); + const goToday = useCallback(() => setCurrent(new Date()), []); + const onPickDate = useCallback((e) => { + if (!e.target.value) return; + const [y, m, d] = e.target.value.split('-').map(Number); + setCurrent(new Date(y, m - 1, d)); + }, []); + + // 메뉴탭 + const drawerRef = useRef(null); + const menuBtnRef = useRef(null); + useEffect(() => { + const onClick = (e) => { + //닫혀 있다면 아무 액션 없이 return + if (!open) return; + if (drawerRef.current?.contains(e.target)) return; + if (menuBtnRef.current?.contains(e.target)) return; + setOpen(false); + }; + const onKey = (e) => { + if (open && e.key === 'Escape') setOpen(false); + }; + document.addEventListener('click', onClick); + document.addEventListener('keydown', onKey); + return () => { + document.removeEventListener('click', onClick); + document.removeEventListener('keydown', onKey); + }; + }, [open]); + + const fmt = useMemo(() => ({ year: 'numeric', month: 'long', day: 'numeric' }), []); + const dateLabel = useMemo(() => current.toLocaleDateString(undefined, fmt), [current, fmt]); + + return ( + <> + + +
+ setOpen(true)}> + + + To Do +
+ + + + setOpen(false)}>x + + + changeDays(-7)}>Last Week + changeDays(7)}>Next Week + + + + + + + changeDays(-1)}>◀ + {dateLabel} + changeDays(1)}>▶ + + + + setText(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') addTodo(); + }} + /> + Add + + + + + Clear all + To-do: {total} + + + + + + ); +} + + + + + diff --git a/src/main.jsx b/src/main.jsx new file mode 100644 index 0000000..1b79458 --- /dev/null +++ b/src/main.jsx @@ -0,0 +1,9 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App'; + +ReactDOM.createRoot(document.getElementById('root')).render( + + + , +); diff --git a/style.css b/style.css new file mode 100644 index 0000000..6f78dc4 --- /dev/null +++ b/style.css @@ -0,0 +1,281 @@ +/*reset*/ +body { + margin: 0; + font-family: arial, sans-serif; + background: #e2e8f0; +} + +/* Header layout with flexbox */ +.header { + display: flex; + align-items: center; + justify-content: center; + background: #0f172a; + color: white; + padding: 14px 16px; +} + +.menu { + position: absolute; + left: 16px; + background: none; + border: none; + cursor: pointer; + padding: 8px; +} + +.menuIcon, +.menuIcon::before, +.menuIcon::after { + display: block; + width: 24px; + height: 2px; + background: white; + border-radius: 2px; + content: ''; + position: relative; +} + +.menuIcon::before, +.menuIcon::after { + position: absolute; + left: 0; +} + +.menuIcon::before { + top: -10px; +} +.menuIcon::after { + top: 10px; +} + +.menuTab { + position: fixed; + background: #e2e8f0; + width: 300px; + top: 0; + left: 0; + bottom: 0; + transform: translateX(-100%); + transition: transform 0.25s ease; +} + +.menuTab.active { + transform: translateX(0); +} + +.menuContent { + display: flex; + height: 100%; + flex-direction: column; + gap: 8px; + font-size: 15px; +} + +.options { + display: flex; + flex-direction: column; + justify-content: center; + margin-top: 80px; + align-items: center; + gap: 110px; + padding: 20px; +} + +.nWeek, +.lWeek { + width: 120px; + height: 30px; + font-size: 16px; + border-radius: 10px; +} + +.menuDatePicker { + margin-top: 80px; + margin-left: 71px; + font-size: 16px; + width: 160px; + height: 30px; + border-radius: 10px; +} + +#closeMenu { + position: absolute; + font-size: 30px; + width: 22px; + margin-top: 15px; + margin-left: 20px; + background: none; + border: none; + cursor: pointer; +} +/* Centered title */ +.title { + margin: 0; + font-size: 35px; + font-weight: 600; +} + +.dateSelector { + display: flex; + align-items: center; + justify-content: center; + background: none; + margin: 30px; + gap: 20px; +} + +.date { + font-size: 20px; + background: none; + border: none; +} + +.today { + display: flex; + color: #0f172a; + font-size: 20px; + background: none; + border: none; +} + +.inputContainer { + display: flex; + justify-content: center; + gap: 20px; + margin: 40px auto; + background: whitesmoke; + border-radius: 20px; + padding-left: 10px; + width: 400px; + height: 50px; +} + +.input { + font-size: 23px; + border: none; + outline: none; + background: none; + color: #0f172a; +} + +.register { + font-size: 15px; + width: 60px; + height: 25px; + border-radius: 13px; + border: 2px solid black; + cursor: pointer; + background: #0f172a; + color: white; + margin-right: 1px; + margin-top: auto; + margin-bottom: auto; +} + +.list { + display: flex; + flex-direction: column; + gap: 6px; + height: 425px; + width: 600px; + margin: 0 auto; + background: whitesmoke; + border: 6px solid #0f172a; + border-radius: 20px; +} + +.todoEl { + display: flex; + flex-direction: column; + align-items: center; + gap: 14px; + font-size: 26px; + padding: 0; + margin: 5px; + max-height: 350px; + overflow-y: auto; +} + +.topRowList { + display: flex; +} + +.clearAll { + color: #0f172a; + font-size: 20px; + border-radius: 20px; + width: 120px; + margin-top: 5px; + margin-left: 10px; + background: #e2e8f0; +} + +.numEvent { + line-height: 1.5; + color: #0f172a; + font-size: 18px; + border-radius: 20px; + width: 120px; + margin-top: 5px; + margin-left: auto; + margin-right: 10px; + background: #e2e8f0; + border: 2px solid #0f172a; + padding-left: 20px; +} +.todoEl li { + line-height: 1.5; + display: flex; + padding: 10px 5px; + border: 3px solid #0f172a; + border-radius: 15px; + height: 30px; + width: 550px; + background: #e2e8f0; +} + +.delEvent { + background: #0f172a; + color: white; + border: none; + font-size: 16px; + border-radius: 20px; +} + +.text { + margin-left: 10px; + margin-right: auto; + font-size: 20px; +} + +.pinEvent { + background: none; + color: white; + border: black solid 1px; + font-size: 15px; + border-radius: 20px; + margin-right: 8px; +} + +.doneEvent { + background: #0f172a; + color: white; + border: none; + font-size: 15px; + border-radius: 20px; +} + +.markDone { + text-decoration: line-through; + text-decoration-color: red; + color: grey; +} + +.markPin { + background: red; +} + +body.invert { + filter: invert(1); +}