├── src
├── utils
│ ├── noop.ts
│ ├── spacing.ts
│ ├── readFileAsBase64.ts
│ ├── getCurrentGeolocation.ts
│ └── getCurrentWeather.ts
├── vite-env.d.ts
├── components
│ ├── Box.styled.ts
│ ├── Box.tsx
│ ├── Panel.tsx
│ ├── IconButton.tsx
│ ├── settings
│ │ ├── background
│ │ │ ├── SettingsBackground.styled.ts
│ │ │ └── SettingsBackground.tsx
│ │ ├── Settings.styled.ts
│ │ ├── search
│ │ │ ├── SettingsSearch.styled.ts
│ │ │ └── SettingsSearch.tsx
│ │ └── Settings.tsx
│ ├── FormSection.styled.ts
│ ├── IconTab.styled.ts
│ ├── FormSection.tsx
│ ├── Panel.styled.ts
│ ├── IconButton.styled.ts
│ ├── Clock.styled.ts
│ ├── IconTab.tsx
│ ├── Clock.tsx
│ ├── SearchBar.styled.ts
│ ├── BackgroundCanvas.styled.ts
│ ├── SearchBar.tsx
│ └── BackgroundCanvas.tsx
├── emotion.d.ts
├── main.tsx
├── stores
│ ├── session-app.ts
│ └── app.ts
├── constants
│ ├── searchEngines.ts
│ └── weather.ts
├── App.styled.ts
└── App.tsx
├── public
├── img.png
├── SUITE-Variable.woff2
└── vite.svg
├── README.md
├── res
└── screenshot.png
├── .prettierrc
├── tsconfig.json
├── vite.config.ts
├── .gitignore
├── .dockerignore
├── Dockerfile
├── tsconfig.node.json
├── index.html
├── tsconfig.app.json
├── eslint.config.js
├── package.json
└── pnpm-lock.yaml
/src/utils/noop.ts:
--------------------------------------------------------------------------------
1 | export function noop() {}
2 |
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/public/img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/async3619/startpage/HEAD/public/img.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # startpage, with some raindrops
2 |
3 | 
4 |
--------------------------------------------------------------------------------
/res/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/async3619/startpage/HEAD/res/screenshot.png
--------------------------------------------------------------------------------
/public/SUITE-Variable.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/async3619/startpage/HEAD/public/SUITE-Variable.woff2
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "singleAttributePerLine": true,
4 | "semi": false,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/src/components/Box.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Root = styled.div`
4 | border-radius: 4px;
5 |
6 | background-color: rgba(255, 255, 255, 0.3);
7 | `
8 |
--------------------------------------------------------------------------------
/src/emotion.d.ts:
--------------------------------------------------------------------------------
1 | import spacing from './utils/spacing'
2 |
3 | declare module '@emotion/react' {
4 | export interface Theme {
5 | spacing: typeof spacing
6 | contrastText: string
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "types": [
4 | "vite-plugin-glsl/ext"
5 | ],
6 | },
7 | "files": [],
8 | "references": [
9 | { "path": "./tsconfig.app.json" },
10 | { "path": "./tsconfig.node.json" }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/src/components/Box.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import * as Styled from './Box.styled'
4 |
5 | interface BoxProps extends React.HTMLAttributes {}
6 |
7 | function Box(props: BoxProps) {
8 | return
9 | }
10 |
11 | export default Box
12 |
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 |
4 | import 'normalize.css'
5 |
6 | import App from './App'
7 |
8 | createRoot(document.getElementById('root')!).render(
9 |
10 |
11 | ,
12 | )
13 |
--------------------------------------------------------------------------------
/src/components/Panel.tsx:
--------------------------------------------------------------------------------
1 | import * as Styled from './Panel.styled'
2 |
3 | interface PanelProps {
4 | open: boolean
5 | children: React.ReactNode
6 | }
7 |
8 | function Panel({ open, children }: PanelProps) {
9 | return {children}
10 | }
11 |
12 | export default Panel
13 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import glsl from 'vite-plugin-glsl'
3 | import react from '@vitejs/plugin-react'
4 | import tsconfigPaths from 'vite-tsconfig-paths'
5 |
6 | // https://vite.dev/config/
7 | export default defineConfig({
8 | plugins: [react(), glsl(), tsconfigPaths()],
9 | })
10 |
--------------------------------------------------------------------------------
/src/components/IconButton.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import * as Styled from './IconButton.styled'
3 |
4 | type ButtonProps = React.HTMLAttributes
5 |
6 | function IconButton({ children, ...rest }: ButtonProps) {
7 | return {children}
8 | }
9 |
10 | export default IconButton
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/src/stores/session-app.ts:
--------------------------------------------------------------------------------
1 | import { create } from 'zustand'
2 |
3 | interface SessionAppStore {
4 | isReady: boolean
5 | setIsReady: (isReady: boolean) => void
6 | }
7 |
8 | const useSessionAppStore = create((set) => ({
9 | isReady: false,
10 | setIsReady: (isReady: boolean) => set({ isReady }),
11 | }))
12 |
13 | export default useSessionAppStore
14 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | # Node modules
2 | node_modules
3 |
4 | # Build artifacts
5 | dist
6 |
7 | # Local configuration files
8 | *.tsbuildinfo
9 |
10 | # Environment variables
11 | .env
12 | .env.local
13 | .env.*.local
14 |
15 | # IDE/editor files
16 | .vscode
17 | .idea
18 | *.sublime-project
19 | *.sublime-workspace
20 |
21 | # Logs
22 | *.log
23 |
24 | # Other unnecessary files
25 | .DS_Store
26 | Thumbs.db
27 | README.md
28 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Stage 1: Build
2 |
3 | FROM node:20-alpine AS build
4 |
5 | RUN npm install -g pnpm
6 |
7 | WORKDIR /app
8 | COPY . .
9 |
10 | RUN pnpm install --frozen-lockfile
11 |
12 | # TODO Add checks
13 |
14 | RUN pnpm run build
15 |
16 |
17 | # Stage 2: Serve
18 |
19 | FROM caddy:alpine
20 |
21 | COPY --from=build /app/dist /usr/share/caddy
22 |
23 | EXPOSE 80
24 | CMD ["caddy", "file-server", "--root", "/usr/share/caddy"]
25 |
--------------------------------------------------------------------------------
/src/utils/spacing.ts:
--------------------------------------------------------------------------------
1 | function spacing(
2 | top: number,
3 | right: number,
4 | bottom: number,
5 | left: number,
6 | ): string
7 | function spacing(top: number, leftRight: number, bottom: number): string
8 | function spacing(vertical: number, horizontal: number): string
9 | function spacing(all: number): string
10 |
11 | function spacing(...args: number[]): string {
12 | return args.map((value) => `${value * 8}px`).join(' ')
13 | }
14 |
15 | export default spacing
16 |
--------------------------------------------------------------------------------
/src/components/settings/background/SettingsBackground.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 | import IconButton from '@components/IconButton'
3 |
4 | export const FileInput = styled.input`
5 | display: none;
6 | `
7 |
8 | export const RangeInput = styled.input`
9 | width: 100%;
10 | `
11 |
12 | export const UploadButton = styled.button`
13 | width: 100%;
14 |
15 | padding: ${({ theme }) => theme.spacing(1)};
16 |
17 | display: block;
18 | `
19 |
20 | export const Button = styled(IconButton)``
21 |
--------------------------------------------------------------------------------
/src/components/FormSection.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Title = styled.h6`
4 | margin: 0 0 ${({ theme }) => theme.spacing(1)};
5 | font-size: 1rem;
6 | `
7 |
8 | export const Description = styled.p`
9 | margin: 0 0 ${({ theme }) => theme.spacing(1)};
10 | font-size: 0.875rem;
11 | `
12 |
13 | export const Content = styled.div``
14 |
15 | export const Root = styled.section`
16 | &:not(:last-of-type) {
17 | margin: 0 0 ${({ theme }) => theme.spacing(2)};
18 | }
19 | `
20 |
--------------------------------------------------------------------------------
/src/utils/readFileAsBase64.ts:
--------------------------------------------------------------------------------
1 | function readFileAsBase64(file: File): Promise {
2 | return new Promise((resolve, reject) => {
3 | const reader = new FileReader()
4 | reader.onload = () => {
5 | const result = reader.result
6 | if (typeof result === 'string') {
7 | resolve(result)
8 | } else {
9 | reject(new Error('Failed to read file as base64'))
10 | }
11 | }
12 | reader.onerror = reject
13 | reader.readAsDataURL(file)
14 | })
15 | }
16 |
17 | export default readFileAsBase64
18 |
--------------------------------------------------------------------------------
/src/components/IconTab.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Root = styled.div`
4 | display: flex;
5 | `
6 |
7 | export const Item = styled.button<{ selected: boolean }>`
8 | margin: 0;
9 | padding: ${({ theme }) => theme.spacing(0.75)};
10 | border: 0;
11 |
12 | background-color: rgba(255, 255, 255, 0.3);
13 |
14 | cursor: pointer;
15 | opacity: ${({ selected }) => (selected ? 1 : 0.5)};
16 |
17 | > svg {
18 | width: 20px;
19 | height: 20px;
20 |
21 | display: block;
22 |
23 | fill: white;
24 | }
25 | `
26 |
--------------------------------------------------------------------------------
/src/components/FormSection.tsx:
--------------------------------------------------------------------------------
1 | import * as Styled from './FormSection.styled'
2 |
3 | interface FormSectionProps {
4 | title: string
5 | description?: string
6 | children?: React.ReactNode
7 | }
8 |
9 | function FormSection({ description, title, children }: FormSectionProps) {
10 | return (
11 |
12 | {title}
13 | {description && {description}}
14 | {children}
15 |
16 | )
17 | }
18 |
19 | export default FormSection
20 |
--------------------------------------------------------------------------------
/src/constants/searchEngines.ts:
--------------------------------------------------------------------------------
1 | export const SEARCH_ENGINES: Record<
2 | string,
3 | {
4 | name: string
5 | url: string
6 | }
7 | > = {
8 | google: {
9 | name: 'Google',
10 | url: 'https://www.google.com/search?q={}',
11 | },
12 | duckduckgo: {
13 | name: 'DuckDuckGo',
14 | url: 'https://duckduckgo.com/?q={}',
15 | },
16 | 'searx.be': {
17 | name: 'Searx.be',
18 | url: 'https://searx.be/?q={}',
19 | },
20 | custom: {
21 | name: 'Custom',
22 | url: '',
23 | },
24 | }
25 |
26 | export type SearchEngineOption = keyof typeof SEARCH_ENGINES
27 |
--------------------------------------------------------------------------------
/src/utils/getCurrentGeolocation.ts:
--------------------------------------------------------------------------------
1 | export interface LatLng {
2 | lat: number
3 | lng: number
4 | }
5 |
6 | function getCurrentGeolocation() {
7 | return new Promise((resolve, reject) => {
8 | navigator.geolocation.getCurrentPosition(
9 | (position) => {
10 | resolve({
11 | lat: position.coords.latitude,
12 | lng: position.coords.longitude,
13 | })
14 | },
15 | (error) => {
16 | reject(error)
17 | },
18 | { enableHighAccuracy: true },
19 | )
20 | })
21 | }
22 |
23 | export default getCurrentGeolocation
24 |
--------------------------------------------------------------------------------
/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2022",
4 | "lib": ["ES2023"],
5 | "module": "ESNext",
6 | "skipLibCheck": true,
7 |
8 | /* Bundler mode */
9 | "moduleResolution": "Bundler",
10 | "allowImportingTsExtensions": true,
11 | "isolatedModules": true,
12 | "moduleDetection": "force",
13 | "noEmit": true,
14 |
15 | /* Linting */
16 | "strict": true,
17 | "noUnusedLocals": true,
18 | "noUnusedParameters": true,
19 | "noFallthroughCasesInSwitch": true,
20 | "noUncheckedSideEffectImports": true
21 | },
22 | "include": ["vite.config.ts"]
23 | }
24 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 | New Tab
13 |
14 |
15 |
16 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/components/Panel.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Root = styled.div<{ visible: boolean }>`
4 | padding: ${({ theme }) => theme.spacing(2)};
5 | border-radius: 4px;
6 |
7 | position: absolute;
8 | top: 0;
9 | right: 0;
10 |
11 | visibility: ${({ visible }) => (visible ? 'visible' : 'hidden')};
12 |
13 | color: #fff;
14 | background-color: rgba(255, 255, 255, 0.3);
15 |
16 | opacity: ${({ visible }) => (visible ? 1 : 0)};
17 | transform: translateY(-100%)
18 | translateY(${({ theme, visible }) => theme.spacing(visible ? -1 : 0)});
19 | backdrop-filter: blur(16px);
20 |
21 | transition:
22 | background-color 0.2s ease,
23 | opacity 0.2s ease,
24 | transform 0.2s ease;
25 | `
26 |
--------------------------------------------------------------------------------
/src/components/IconButton.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Root = styled.button`
4 | margin: 0;
5 | padding: ${({ theme }) => theme.spacing(1)};
6 | border: none;
7 | border-radius: 4px;
8 |
9 | background-color: rgba(255, 255, 255, 0.3);
10 |
11 | transition: background-color 0.2s ease;
12 |
13 | outline: none;
14 | cursor: pointer;
15 |
16 | backdrop-filter: blur(16px);
17 |
18 | &:hover,
19 | &:focus-visible {
20 | background-color: rgba(255, 255, 255, 0.5);
21 | }
22 |
23 | &:active {
24 | background-color: rgba(255, 255, 255, 0.3);
25 | }
26 |
27 | > svg {
28 | width: ${({ theme }) => theme.spacing(3)};
29 | height: ${({ theme }) => theme.spacing(3)};
30 |
31 | display: block;
32 |
33 | fill: #fff;
34 | }
35 | `
36 |
--------------------------------------------------------------------------------
/src/components/Clock.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Root = styled.div`
4 | display: flex;
5 | flex-direction: column;
6 |
7 | user-select: none;
8 | `
9 |
10 | export const Date = styled.span`
11 | display: block;
12 |
13 | font-size: 28px;
14 | font-family: 'Azeret Mono', monospace;
15 | font-optical-sizing: auto;
16 | font-weight: 400;
17 | font-style: normal;
18 | text-align: center;
19 |
20 | color: rgba(255, 255, 255, 0.5);
21 | `
22 |
23 | export const Weather = styled(Date)`
24 | margin-top: 8px;
25 |
26 | font-size: 18px;
27 | `
28 |
29 | export const Time = styled.span`
30 | display: block;
31 |
32 | font-size: 94px;
33 | font-family: 'Azeret Mono', monospace;
34 | font-optical-sizing: auto;
35 | font-weight: 400;
36 | font-style: normal;
37 |
38 | color: rgba(255, 255, 255, 0.75);
39 | `
40 |
--------------------------------------------------------------------------------
/src/components/IconTab.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import * as Styled from './IconTab.styled'
4 |
5 | export interface IconTabItem {
6 | value: TValue
7 | icon: React.ComponentType
8 | }
9 |
10 | interface IconTabProps {
11 | value: TValue
12 | onChange: (value: TValue) => void
13 | items: IconTabItem[]
14 | }
15 |
16 | function IconTab({
17 | value: currentValue,
18 | items,
19 | onChange,
20 | }: IconTabProps) {
21 | return (
22 |
23 | {items.map(({ icon: Icon, value }) => (
24 | onChange(value)}
27 | selected={value === currentValue}
28 | >
29 |
30 |
31 | ))}
32 |
33 | )
34 | }
35 |
36 | export default IconTab
37 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "useDefineForClassFields": true,
5 | "lib": ["ES2020", "DOM", "DOM.Iterable"],
6 | "module": "ESNext",
7 | "skipLibCheck": true,
8 | "baseUrl": ".",
9 |
10 | /* Bundler mode */
11 | "moduleResolution": "Bundler",
12 | "allowImportingTsExtensions": false,
13 | "isolatedModules": true,
14 | "moduleDetection": "force",
15 | "noEmit": true,
16 | "jsx": "react-jsx",
17 |
18 | /* Linting */
19 | "strict": true,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "noFallthroughCasesInSwitch": true,
23 | "noUncheckedSideEffectImports": true,
24 |
25 | "paths": {
26 | "@components/*": ["src/components/*"],
27 | "@utils/*": ["src/utils/*"],
28 | "@stores/*": ["src/stores/*"],
29 | "@constants/*": ["src/constants/*"],
30 | }
31 | },
32 | "include": ["src"]
33 | }
34 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import js from '@eslint/js'
2 | import globals from 'globals'
3 | import reactHooks from 'eslint-plugin-react-hooks'
4 | import reactRefresh from 'eslint-plugin-react-refresh'
5 | import tseslint from 'typescript-eslint'
6 |
7 | export default tseslint.config(
8 | { ignores: ['dist'] },
9 | {
10 | extends: [js.configs.recommended, ...tseslint.configs.recommended],
11 | files: ['**/*.{ts,tsx}'],
12 | languageOptions: {
13 | ecmaVersion: 2020,
14 | globals: globals.browser,
15 | },
16 | plugins: {
17 | 'react-hooks': reactHooks,
18 | 'react-refresh': reactRefresh,
19 | },
20 | rules: {
21 | ...reactHooks.configs.recommended.rules,
22 | 'no-empty-pattern': 'off',
23 | '@typescript-eslint/no-empty-object-type': 'off',
24 | 'react-refresh/only-export-components': [
25 | 'warn',
26 | { allowConstantExport: true },
27 | ],
28 | },
29 | },
30 | )
31 |
--------------------------------------------------------------------------------
/src/components/Clock.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react'
2 |
3 | import dayjs from 'dayjs'
4 |
5 | import useAppStore from '@stores/app'
6 |
7 | import * as Styled from './Clock.styled'
8 |
9 | function Clock() {
10 | const [time, setTime] = useState(() => dayjs())
11 | const weather = useAppStore((store) => store.weather?.weather)
12 |
13 | useEffect(() => {
14 | const interval = setInterval(() => {
15 | setTime(dayjs())
16 | }, 500)
17 |
18 | return () => {
19 | clearInterval(interval)
20 | }
21 | }, [])
22 |
23 | return (
24 |
25 | {time.format('HH·mm·ss')}
26 | {time.format('YYYY·MM·DD')}
27 | {weather && (
28 |
29 | {weather.weatherName} {Math.round(weather.temperature * 10) / 10}°C
30 |
31 | )}
32 |
33 | )
34 | }
35 |
36 | export default Clock
37 |
--------------------------------------------------------------------------------
/src/components/SearchBar.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | import Box from '@components/Box'
4 |
5 | export const Root = styled(Box)`
6 | width: 100%;
7 | max-width: 764px;
8 |
9 | margin-top: ${({ theme }) => theme.spacing(6)};
10 | border-top-left-radius: 0;
11 |
12 | position: relative;
13 | `
14 |
15 | export const Input = styled.input`
16 | width: 100%;
17 |
18 | margin: 0;
19 | padding: ${({ theme }) => theme.spacing(1.5, 2)};
20 | border: 0;
21 |
22 | display: block;
23 | box-sizing: border-box;
24 |
25 | font-family: 'SUITE Variable', sans-serif;
26 |
27 | color: white;
28 | background-color: transparent;
29 |
30 | outline: none;
31 |
32 | ::placeholder {
33 | color: rgba(255, 255, 255, 0.5);
34 | }
35 | `
36 |
37 | export const IconTabWrapper = styled.div`
38 | border-top-left-radius: 4px;
39 | border-top-right-radius: 4px;
40 |
41 | position: absolute;
42 | top: 0;
43 | left: 0;
44 |
45 | overflow: hidden;
46 |
47 | transform: translateY(-100%);
48 | `
49 |
--------------------------------------------------------------------------------
/src/App.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 | import { css } from '@emotion/react'
3 |
4 | export const GlobalStyles = css`
5 | @font-face {
6 | font-family: 'SUITE Variable';
7 | font-weight: 300 900;
8 | src: url('/SUITE-Variable.woff2') format('woff2-variations');
9 | }
10 |
11 | * {
12 | font-family: 'SUITE Variable', sans-serif;
13 | }
14 |
15 | html,
16 | body {
17 | color: white;
18 | }
19 | `
20 |
21 | export const Root = styled.main``
22 |
23 | export const Content = styled.div<{ isReady: boolean }>`
24 | width: 100%;
25 |
26 | padding: ${({ theme }) => theme.spacing(2)};
27 | box-sizing: border-box;
28 |
29 | display: flex;
30 | flex-direction: column;
31 | justify-content: center;
32 | align-items: center;
33 |
34 | position: fixed;
35 | top: 0;
36 | left: 0;
37 |
38 | opacity: ${({ isReady }) => (isReady ? 1 : 0)};
39 |
40 | transition: opacity 1s;
41 |
42 | @supports (height: 100svh) {
43 | height: 100svh;
44 | }
45 |
46 | @supports not (height: 100svh) {
47 | height: 100vh;
48 | }
49 | `
50 |
--------------------------------------------------------------------------------
/src/components/BackgroundCanvas.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Root = styled.div`
4 | width: 100%;
5 | height: 100%;
6 |
7 | position: fixed;
8 | top: 0;
9 | left: 0;
10 |
11 | background-color: #000;
12 |
13 | z-index: -1;
14 | `
15 |
16 | export const Viewport = styled.canvas<{ isReady: boolean }>`
17 | width: 100%;
18 | height: 100%;
19 |
20 | display: block;
21 | position: absolute;
22 | top: 0;
23 | left: 0;
24 | z-index: 1;
25 |
26 | opacity: ${({ isReady }) => (isReady ? 1 : 0)};
27 |
28 | transition: opacity 1s;
29 | `
30 |
31 | export const Image = styled.img`
32 | width: 100%;
33 | height: 100%;
34 |
35 | display: block;
36 | position: absolute;
37 | top: 0;
38 | left: 0;
39 | z-index: 0;
40 |
41 | object-fit: cover;
42 | `
43 |
44 | export const Overlay = styled.div<{ isReady: boolean; isChanging: boolean }>`
45 | width: 100%;
46 | height: 100%;
47 |
48 | position: absolute;
49 | top: 0;
50 | left: 0;
51 | z-index: 2;
52 |
53 | transition: ${({ isChanging }) =>
54 | isChanging ? 'none' : 'backdrop-filter 1s'};
55 | `
56 |
--------------------------------------------------------------------------------
/src/components/settings/Settings.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 | import IconButton from '@components/IconButton'
3 |
4 | export const Button = styled(IconButton)``
5 |
6 | export const Root = styled.div`
7 | position: absolute;
8 | right: ${({ theme }) => theme.spacing(2)};
9 | bottom: ${({ theme }) => theme.spacing(2)};
10 |
11 | z-index: 3;
12 | `
13 |
14 | export const Content = styled.div`
15 | width: 300px;
16 | height: 300px;
17 | `
18 |
19 | export const TabHeader = styled.div`
20 | display: flex;
21 | justify-content: space-around;
22 | margin-bottom: 16px;
23 | gap: 8px;
24 | border-radius: 4px;
25 | `
26 |
27 | export const TabButton = styled.button<{ isActive?: boolean }>`
28 | flex: 1;
29 | padding: 10px 0;
30 | background-color: ${({ isActive }) => (isActive ? '#444' : 'transparent')};
31 | color: ${({ isActive }) => (isActive ? '#fff' : '#ccc')};
32 | border: ${() => '1px solid #969696'};
33 | border-radius: 4px;
34 | cursor: pointer;
35 | transition:
36 | color 0.3s,
37 | background-color 0.3s;
38 |
39 | &:hover {
40 | color: #fff;
41 | background-color: #444;
42 | }
43 | `
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "rainy-newtab",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "tsc -b && vite build",
9 | "lint": "eslint .",
10 | "preview": "vite preview"
11 | },
12 | "dependencies": {
13 | "@emotion/css": "^11.13.4",
14 | "@emotion/react": "^11.13.3",
15 | "@emotion/styled": "^11.13.0",
16 | "dayjs": "^1.11.13",
17 | "lodash": "^4.17.21",
18 | "normalize.css": "^8.0.1",
19 | "openmeteo": "^1.1.4",
20 | "raindrop-fx": "^1.0.8",
21 | "react": "^18.3.1",
22 | "react-dom": "^18.3.1",
23 | "react-icons": "^5.3.0",
24 | "zustand": "^5.0.0"
25 | },
26 | "devDependencies": {
27 | "@eslint/js": "^9.13.0",
28 | "@types/lodash": "^4.17.12",
29 | "@types/react": "^18.3.11",
30 | "@types/react-dom": "^18.3.1",
31 | "@vitejs/plugin-react": "^4.3.3",
32 | "eslint": "^9.13.0",
33 | "eslint-plugin-react-hooks": "^5.0.0",
34 | "eslint-plugin-react-refresh": "^0.4.13",
35 | "globals": "^15.11.0",
36 | "prettier": "^3.3.3",
37 | "typescript": "~5.6.2",
38 | "typescript-eslint": "^8.10.0",
39 | "vite": "^5.4.9",
40 | "vite-plugin-glsl": "^1.3.0",
41 | "vite-tsconfig-paths": "^5.0.1"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/components/settings/search/SettingsSearch.styled.ts:
--------------------------------------------------------------------------------
1 | import styled from '@emotion/styled'
2 |
3 | export const Container = styled.div`
4 | position: relative;
5 | width: 200px;
6 | `
7 |
8 | export const ToggleButton = styled.button`
9 | width: 100%;
10 | padding: 10px;
11 | background-color: #444;
12 | color: #fff;
13 | border: 0;
14 | border-radius: 4px;
15 | text-align: left;
16 | cursor: pointer;
17 | font-size: 16px;
18 |
19 | &:hover {
20 | background-color: #444;
21 | }
22 |
23 | &:after {
24 | content: '▼';
25 | float: right;
26 | font-size: 12px;
27 | }
28 | `
29 |
30 | export const Menu = styled.div<{ isOpen?: boolean }>`
31 | position: absolute;
32 | top: 100%;
33 | left: 0;
34 | width: 100%;
35 | background-color: #444;
36 | border-radius: 4px;
37 | margin-top: 4px;
38 | overflow: hidden;
39 | max-height: ${({ isOpen }) => (isOpen ? '200px' : '0')};
40 | transition: max-height 0.1s ease;
41 | z-index: 1000;
42 | `
43 |
44 | export const MenuItem = styled.div`
45 | padding: 10px;
46 | color: #fff;
47 | cursor: pointer;
48 | transition: background-color 0.2s;
49 |
50 | &:hover {
51 | background-color: #555;
52 | }
53 | `
54 |
55 | export const Input = styled.input`
56 | padding: 10px;
57 | background-color: #444;
58 | color: #fff;
59 | border: 0;
60 | border-radius: 4px;
61 | font-size: 16px;
62 | margin-top: 4px;
63 | `
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/settings/Settings.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import { MdSettings } from 'react-icons/md'
3 |
4 | import Panel from '@components/Panel'
5 |
6 | import * as Styled from './Settings.styled'
7 | import SettingsBackground from './background/SettingsBackground'
8 | import SettingsSearch from './search/SettingsSearch'
9 |
10 | type Tabs = 'background' | 'search'
11 |
12 | function Settings() {
13 | const [open, setOpen] = useState(false)
14 | const [tab, setTab] = useState('background')
15 |
16 | const handleButtonClick = () => {
17 | setOpen((prev) => !prev)
18 | }
19 |
20 | const renderTabContent = () => {
21 | if (tab === 'search') {
22 | return
23 | }
24 |
25 | return
26 | }
27 |
28 | return (
29 |
30 |
31 |
32 | setTab('background')}
34 | isActive={tab === 'background'}
35 | >
36 | Background
37 |
38 | setTab('search')}
40 | isActive={tab === 'search'}
41 | >
42 | Search
43 |
44 |
45 | {renderTabContent()}
46 |
47 |
48 |
49 |
50 |
51 | )
52 | }
53 |
54 | export default Settings
55 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react'
2 | import { Global, ThemeProvider } from '@emotion/react'
3 |
4 | import BackgroundCanvas from '@components/BackgroundCanvas'
5 | import Settings from '@components/settings/Settings'
6 | import Clock from '@components/Clock'
7 |
8 | import spacing from '@utils/spacing'
9 | import getCurrentGeolocation from '@utils/getCurrentGeolocation'
10 | import getCurrentWeather from '@utils/getCurrentWeather'
11 |
12 | import useSessionAppStore from '@stores/session-app'
13 | import useAppStore from '@stores/app'
14 |
15 | import * as Styled from './App.styled'
16 | import SearchBar from '@components/SearchBar'
17 |
18 | function App() {
19 | const isReady = useSessionAppStore((store) => store.isReady)
20 |
21 | const geolocation = useAppStore((store) => store.geolocation)
22 | const setGeolocation = useAppStore((store) => store.setGeolocation)
23 |
24 | const weather = useAppStore((store) => store.weather)
25 | const setWeather = useAppStore((store) => store.setWeather)
26 |
27 | useEffect(() => {
28 | if (geolocation) {
29 | return
30 | }
31 |
32 | getCurrentGeolocation().then(setGeolocation).catch()
33 | }, [geolocation, setGeolocation])
34 |
35 | useEffect(() => {
36 | if (!geolocation) {
37 | return
38 | }
39 |
40 | if (weather && weather.expiresAt > Date.now()) {
41 | return
42 | }
43 |
44 | getCurrentWeather(geolocation).then(setWeather).catch()
45 | }, [geolocation, setWeather, weather])
46 |
47 | return (
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | )
60 | }
61 |
62 | export default App
63 |
--------------------------------------------------------------------------------
/src/utils/getCurrentWeather.ts:
--------------------------------------------------------------------------------
1 | import { fetchWeatherApi } from 'openmeteo'
2 |
3 | import WMO_WEATHER_CODES from '@constants/weather'
4 |
5 | import { LatLng } from '@utils/getCurrentGeolocation'
6 |
7 | export interface Weather {
8 | rain: number
9 | snowfall: number
10 | humidity: number
11 | temperature: number
12 | weatherCode: number
13 | weatherName: string
14 | }
15 |
16 | async function getCurrentWeather(geolocation: LatLng): Promise {
17 | const params = {
18 | latitude: geolocation.lat,
19 | longitude: geolocation.lng,
20 | current: [
21 | 'temperature_2m',
22 | 'relative_humidity_2m',
23 | 'rain',
24 | 'showers',
25 | 'snowfall',
26 | 'weather_code',
27 | 'is_day',
28 | ],
29 | }
30 |
31 | const url = 'https://api.open-meteo.com/v1/forecast'
32 | const [response] = await fetchWeatherApi(url, params)
33 | const utcOffsetSeconds = response.utcOffsetSeconds()
34 | const current = response.current()!
35 |
36 | const weatherData = {
37 | current: {
38 | time: new Date((Number(current.time()) + utcOffsetSeconds) * 1000),
39 | temperature2m: current.variables(0)!.value(),
40 | relativeHumidity2m: current.variables(1)!.value(),
41 | rain: current.variables(2)!.value(),
42 | showers: current.variables(3)!.value(),
43 | snowfall: current.variables(4)!.value(),
44 | weatherCode: current.variables(5)!.value(),
45 | isDay: current.variables(6)!.value(),
46 | },
47 | }
48 |
49 | return {
50 | rain: weatherData.current.rain,
51 | snowfall: weatherData.current.snowfall,
52 | humidity: weatherData.current.relativeHumidity2m,
53 | temperature: weatherData.current.temperature2m,
54 | weatherCode: weatherData.current.weatherCode,
55 | weatherName:
56 | WMO_WEATHER_CODES[weatherData.current.weatherCode][
57 | weatherData.current.isDay ? 'day' : 'night'
58 | ],
59 | }
60 | }
61 |
62 | export default getCurrentWeather
63 |
--------------------------------------------------------------------------------
/src/components/settings/search/SettingsSearch.tsx:
--------------------------------------------------------------------------------
1 | import FormSection from '@components/FormSection'
2 |
3 | import * as Styled from './SettingsSearch.styled'
4 | import { useState } from 'react'
5 | import useAppStore from '@stores/app'
6 | import { SEARCH_ENGINES, SearchEngineOption } from '@constants/searchEngines'
7 |
8 | function SettingsSearch() {
9 | const {
10 | searchEngine,
11 | setSearchEngine,
12 | customSearchEngineURL,
13 | setCustomSearchEngineURL,
14 | } = useAppStore()
15 |
16 | const [isMenuOpen, setIsMenuOpen] = useState(false)
17 |
18 | const handleToggle = () => setIsMenuOpen(!isMenuOpen)
19 | const handleSelect = (item: SearchEngineOption) => {
20 | setIsMenuOpen(false)
21 | setSearchEngine(item)
22 | }
23 |
24 | return (
25 | <>
26 |
27 |
28 |
29 | {SEARCH_ENGINES[searchEngine].name}
30 |
31 |
32 | {Object.keys(SEARCH_ENGINES).map((engine) => (
33 | handleSelect(engine)}
36 | >
37 | {SEARCH_ENGINES[engine].name}
38 |
39 | ))}
40 |
41 |
42 |
43 |
44 | {searchEngine === 'custom' && (
45 |
49 | setCustomSearchEngineURL(e.target.value)}
54 | />
55 |
56 | )}
57 | >
58 | )
59 | }
60 |
61 | export default SettingsSearch
62 |
--------------------------------------------------------------------------------
/src/components/SearchBar.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { RiOpenaiFill, RiSearch2Line } from 'react-icons/ri'
3 |
4 | import IconTab, { IconTabItem } from '@components/IconTab'
5 |
6 | import * as Styled from './SearchBar.styled'
7 | import useAppStore from '@stores/app'
8 | import { SEARCH_ENGINES } from '@constants/searchEngines'
9 |
10 | type QueryMode = 'websearch' | 'chatgpt'
11 |
12 | const SEARCH_ENGiNE_ITEMS: IconTabItem[] = [
13 | {
14 | value: 'websearch',
15 | icon: RiSearch2Line,
16 | },
17 | {
18 | value: 'chatgpt',
19 | icon: RiOpenaiFill,
20 | },
21 | ]
22 |
23 | const PLACEHOLDER_TEXT: Record = {
24 | websearch: 'Search the web...',
25 | chatgpt: 'Ask ChatGPT...',
26 | }
27 |
28 | function SearchBar() {
29 | const [query, setQuery] = React.useState('')
30 | const [queryMode, setQueryMode] = React.useState('websearch')
31 | const { searchEngine, customSearchEngineURL } = useAppStore()
32 |
33 | const handleChange = (event: React.ChangeEvent) => {
34 | setQuery(event.target.value)
35 | }
36 |
37 | const handleKeyDown = (event: React.KeyboardEvent) => {
38 | if (event.key !== 'Enter') return
39 |
40 | if (queryMode === 'chatgpt') {
41 | location.href = `https://chat.openai.com/?q=${query}`
42 | return
43 | }
44 |
45 | if (queryMode === 'websearch') {
46 | const searchUrl =
47 | searchEngine === 'custom'
48 | ? customSearchEngineURL
49 | : SEARCH_ENGINES[searchEngine].url
50 |
51 | if (!searchUrl) return alert('Please set a custom search engine URL.')
52 |
53 | location.href = searchUrl.replace('{}', encodeURIComponent(query))
54 | }
55 | }
56 |
57 | return (
58 |
59 |
66 |
67 |
72 |
73 |
74 | )
75 | }
76 |
77 | export default SearchBar
78 |
--------------------------------------------------------------------------------
/src/constants/weather.ts:
--------------------------------------------------------------------------------
1 | const WMO_WEATHER_CODES: Record> = {
2 | '0': {
3 | day: 'Sunny',
4 | night: 'Clear',
5 | },
6 | '1': {
7 | day: 'Mainly Sunny',
8 | night: 'Mainly Clear',
9 | },
10 | '2': {
11 | day: 'Partly Cloudy',
12 | night: 'Partly Cloudy',
13 | },
14 | '3': {
15 | day: 'Cloudy',
16 | night: 'Cloudy',
17 | },
18 | '45': {
19 | day: 'Foggy',
20 | night: 'Foggy',
21 | },
22 | '48': {
23 | day: 'Rime Fog',
24 | night: 'Rime Fog',
25 | },
26 | '51': {
27 | day: 'Light Drizzle',
28 | night: 'Light Drizzle',
29 | },
30 | '53': {
31 | day: 'Drizzle',
32 | night: 'Drizzle',
33 | },
34 | '55': {
35 | day: 'Heavy Drizzle',
36 | night: 'Heavy Drizzle',
37 | },
38 | '56': {
39 | day: 'Light Freezing Drizzle',
40 | night: 'Light Freezing Drizzle',
41 | },
42 | '57': {
43 | day: 'Freezing Drizzle',
44 | night: 'Freezing Drizzle',
45 | },
46 | '61': {
47 | day: 'Light Rain',
48 | night: 'Light Rain',
49 | },
50 | '63': {
51 | day: 'Rain',
52 | night: 'Rain',
53 | },
54 | '65': {
55 | day: 'Heavy Rain',
56 | night: 'Heavy Rain',
57 | },
58 | '66': {
59 | day: 'Light Freezing Rain',
60 | night: 'Light Freezing Rain',
61 | },
62 | '67': {
63 | day: 'Freezing Rain',
64 | night: 'Freezing Rain',
65 | },
66 | '71': {
67 | day: 'Light Snow',
68 | night: 'Light Snow',
69 | },
70 | '73': {
71 | day: 'Snow',
72 | night: 'Snow',
73 | },
74 | '75': {
75 | day: 'Heavy Snow',
76 | night: 'Heavy Snow',
77 | },
78 | '77': {
79 | day: 'Snow Grains',
80 | night: 'Snow Grains',
81 | },
82 | '80': {
83 | day: 'Light Showers',
84 | night: 'Light Showers',
85 | },
86 | '81': {
87 | day: 'Showers',
88 | night: 'Showers',
89 | },
90 | '82': {
91 | day: 'Heavy Showers',
92 | night: 'Heavy Showers',
93 | },
94 | '85': {
95 | day: 'Light Snow Showers',
96 | night: 'Light Snow Showers',
97 | },
98 | '86': {
99 | day: 'Snow Showers',
100 | night: 'Snow Showers',
101 | },
102 | '95': {
103 | day: 'Thunderstorm',
104 | night: 'Thunderstorm',
105 | },
106 | '96': {
107 | day: 'Light Thunderstorms With Hail',
108 | night: 'Light Thunderstorms With Hail',
109 | },
110 | '99': {
111 | day: 'Thunderstorm With Hail',
112 | night: 'Thunderstorm With Hail',
113 | },
114 | }
115 |
116 | export default WMO_WEATHER_CODES
117 |
--------------------------------------------------------------------------------
/src/stores/app.ts:
--------------------------------------------------------------------------------
1 | import { create } from 'zustand'
2 | import { createJSONStorage, persist } from 'zustand/middleware'
3 |
4 | import { Weather } from '@utils/getCurrentWeather'
5 | import { SearchEngineOption } from '@constants/searchEngines'
6 |
7 | interface WeatherHolder {
8 | weather: Weather
9 | expiresAt: number
10 | }
11 |
12 | interface LatLng {
13 | lat: number
14 | lng: number
15 | }
16 |
17 | interface AppStore {
18 | backgroundImage: string | null
19 | setBackgroundImage: (backgroundImage: string) => void
20 | clearBackgroundImage: () => void
21 |
22 | dimmingAmount: number
23 | setDimmingAmount: (dimmingAmount: number) => void
24 |
25 | blurAmount: number
26 | setBlurAmount: (blurAmount: number) => void
27 |
28 | isPropertyChanging: boolean
29 | setPropertyChanging: (isPropertyChanging: boolean) => void
30 |
31 | geolocation: LatLng | null
32 | setGeolocation: (geolocation: LatLng) => void
33 |
34 | weather: WeatherHolder | null
35 | setWeather: (weather: Weather) => void
36 |
37 | searchEngine: SearchEngineOption
38 | setSearchEngine: (searchEngine: SearchEngineOption) => void
39 |
40 | customSearchEngineURL: string | null
41 | setCustomSearchEngineURL: (customSearchEngineURL: string) => void
42 | }
43 |
44 | const useAppStore = create(
45 | persist(
46 | (set) => ({
47 | backgroundImage: null,
48 | setBackgroundImage: (backgroundImage: string) => set({ backgroundImage }),
49 | clearBackgroundImage: () => set({ backgroundImage: null }),
50 |
51 | dimmingAmount: 0.5,
52 | setDimmingAmount: (dimmingAmount: number) => set({ dimmingAmount }),
53 |
54 | blurAmount: 4,
55 | setBlurAmount: (blurAmount: number) => set({ blurAmount }),
56 |
57 | isPropertyChanging: false,
58 | setPropertyChanging: (isPropertyChanging: boolean) =>
59 | set({ isPropertyChanging }),
60 |
61 | geolocation: null,
62 | setGeolocation: (geolocation: LatLng) => set({ geolocation }),
63 |
64 | weather: null,
65 | setWeather: (weather: Weather) => {
66 | const expiresAt = Date.now() + 1000 * 60 * 60 // 1 hour
67 | set({ weather: { weather, expiresAt } })
68 | },
69 |
70 | searchEngine: 'google',
71 | setSearchEngine: (searchEngine: SearchEngineOption) => set({ searchEngine }),
72 |
73 | customSearchEngineURL: null,
74 | setCustomSearchEngineURL: (customSearchEngineURL: string) =>
75 | set({ customSearchEngineURL }),
76 | }),
77 | {
78 | name: 'app-store',
79 | storage: createJSONStorage(() => localStorage),
80 | },
81 | ),
82 | )
83 |
84 | export default useAppStore
85 |
--------------------------------------------------------------------------------
/src/components/BackgroundCanvas.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react'
2 | import RaindropFX from 'raindrop-fx'
3 |
4 | import useAppStore from '@stores/app'
5 | import useSessionAppStore from '@stores/session-app'
6 |
7 | import * as Styled from './BackgroundCanvas.styled'
8 |
9 | function BackgroundCanvas() {
10 | const isReady = useSessionAppStore((store) => store.isReady)
11 | const isPropertyChanging = useAppStore((store) => store.isPropertyChanging)
12 | const dimmingAmount = useAppStore((store) => store.dimmingAmount)
13 | const blurAmount = useAppStore((store) => store.blurAmount)
14 | const backgroundImage =
15 | useAppStore((store) => store.backgroundImage) ?? '/img.png'
16 |
17 | const setIsReady = useSessionAppStore((store) => store.setIsReady)
18 |
19 | const viewportRef = useRef(null)
20 | const raindropsRef = useRef(null)
21 |
22 | const initialBlurAmount = useRef(blurAmount)
23 |
24 | useEffect(() => {
25 | if (!raindropsRef.current) {
26 | return
27 | }
28 |
29 | raindropsRef.current.options.backgroundBlurSteps = blurAmount
30 | raindropsRef.current.options.mistBlurStep = blurAmount + 1
31 | raindropsRef.current.renderer.reloadBackground()
32 | }, [blurAmount])
33 |
34 | useEffect(() => {
35 | const viewport = viewportRef.current
36 | if (!viewport) {
37 | return
38 | }
39 |
40 | const { width, height } = viewport.getBoundingClientRect()
41 | viewport.width = width
42 | viewport.height = height
43 |
44 | raindropsRef.current = new RaindropFX({
45 | canvas: viewport,
46 | backgroundBlurSteps: initialBlurAmount.current,
47 | mistBlurStep: initialBlurAmount.current + 1,
48 | })
49 |
50 | raindropsRef.current.start()
51 | raindropsRef.current.setBackground(backgroundImage).then(() => {
52 | setIsReady(true)
53 | })
54 |
55 | return () => {
56 | raindropsRef.current?.stop()
57 | }
58 | }, [backgroundImage, setIsReady])
59 |
60 | useEffect(() => {
61 | const onResize = () => {
62 | const viewport = viewportRef.current
63 | const raindrops = raindropsRef.current
64 | if (!viewport || !raindrops) {
65 | return
66 | }
67 |
68 | const { width, height } = viewport.getBoundingClientRect()
69 | raindrops.resize(width, height)
70 | }
71 |
72 | window.addEventListener('resize', onResize)
73 |
74 | return () => {
75 | window.removeEventListener('resize', onResize)
76 | }
77 | }, [])
78 |
79 | return (
80 |
81 |
82 |
86 |
93 |
94 | )
95 | }
96 |
97 | export default BackgroundCanvas
98 |
--------------------------------------------------------------------------------
/src/components/settings/background/SettingsBackground.tsx:
--------------------------------------------------------------------------------
1 | import React, { useRef } from 'react'
2 |
3 | import FormSection from '@components/FormSection'
4 |
5 | import useAppStore from '@stores/app'
6 | import readFileAsBase64 from '@utils/readFileAsBase64'
7 |
8 | import * as Styled from './SettingsBackground.styled'
9 |
10 | const MAX_FILE_SIZE = 5 * 1024 * 1024 // 5MB
11 |
12 | function SettingsBackground() {
13 | const fileInputRef = useRef(null)
14 | const changingTimeout = useRef(null)
15 |
16 | const dimmingAmount = useAppStore((store) => store.dimmingAmount)
17 | const blurAmount = useAppStore((store) => store.blurAmount)
18 |
19 | const setPropertyChanging = useAppStore((store) => store.setPropertyChanging)
20 | const setDimmingAmount = useAppStore((store) => store.setDimmingAmount)
21 | const setBlurAmount = useAppStore((store) => store.setBlurAmount)
22 | const setBackgroundImage = useAppStore((store) => store.setBackgroundImage)
23 |
24 | const doChange = (callback: () => void) => {
25 | if (changingTimeout.current) {
26 | clearTimeout(changingTimeout.current)
27 | changingTimeout.current = null
28 | }
29 |
30 | setPropertyChanging(true)
31 |
32 | callback()
33 |
34 | changingTimeout.current = setTimeout(() => {
35 | setPropertyChanging(false)
36 | changingTimeout.current = null
37 | }, 500)
38 | }
39 |
40 | const handleUploadClick = () => {
41 | fileInputRef.current?.click()
42 | }
43 |
44 | const handleFileChange = async (
45 | event: React.ChangeEvent,
46 | ) => {
47 | const file = event.target.files?.[0]
48 | if (!file) {
49 | return
50 | }
51 |
52 | if (file.size > MAX_FILE_SIZE) {
53 | alert('File size exceeds the limit of 5MB.')
54 | return
55 | }
56 |
57 | const base64 = await readFileAsBase64(file)
58 | setBackgroundImage(base64)
59 | }
60 |
61 | const handleDimmingAmountChange = (
62 | event: React.ChangeEvent,
63 | ) => {
64 | const value = parseFloat(event.target.value)
65 | doChange(() => setDimmingAmount(value))
66 | }
67 |
68 | const handleBlurAmountChange = (
69 | event: React.ChangeEvent,
70 | ) => {
71 | const value = parseFloat(event.target.value)
72 | doChange(() => setBlurAmount(value))
73 | }
74 |
75 | return (
76 | <>
77 |
81 |
86 |
90 | Upload Image
91 |
92 |
93 |
94 |
102 |
103 |
104 |
112 |
113 | >
114 | )
115 | }
116 |
117 | export default SettingsBackground
118 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: '6.0'
2 |
3 | settings:
4 | autoInstallPeers: true
5 | excludeLinksFromLockfile: false
6 |
7 | dependencies:
8 | '@emotion/css':
9 | specifier: ^11.13.4
10 | version: 11.13.4
11 | '@emotion/react':
12 | specifier: ^11.13.3
13 | version: 11.13.3(@types/react@18.3.12)(react@18.3.1)
14 | '@emotion/styled':
15 | specifier: ^11.13.0
16 | version: 11.13.0(@emotion/react@11.13.3)(@types/react@18.3.12)(react@18.3.1)
17 | dayjs:
18 | specifier: ^1.11.13
19 | version: 1.11.13
20 | lodash:
21 | specifier: ^4.17.21
22 | version: 4.17.21
23 | normalize.css:
24 | specifier: ^8.0.1
25 | version: 8.0.1
26 | openmeteo:
27 | specifier: ^1.1.4
28 | version: 1.1.4
29 | raindrop-fx:
30 | specifier: ^1.0.8
31 | version: 1.0.8
32 | react:
33 | specifier: ^18.3.1
34 | version: 18.3.1
35 | react-dom:
36 | specifier: ^18.3.1
37 | version: 18.3.1(react@18.3.1)
38 | react-icons:
39 | specifier: ^5.3.0
40 | version: 5.3.0(react@18.3.1)
41 | zustand:
42 | specifier: ^5.0.0
43 | version: 5.0.0(@types/react@18.3.12)(react@18.3.1)
44 |
45 | devDependencies:
46 | '@eslint/js':
47 | specifier: ^9.13.0
48 | version: 9.13.0
49 | '@types/lodash':
50 | specifier: ^4.17.12
51 | version: 4.17.12
52 | '@types/react':
53 | specifier: ^18.3.11
54 | version: 18.3.12
55 | '@types/react-dom':
56 | specifier: ^18.3.1
57 | version: 18.3.1
58 | '@vitejs/plugin-react':
59 | specifier: ^4.3.3
60 | version: 4.3.3(vite@5.4.10)
61 | eslint:
62 | specifier: ^9.13.0
63 | version: 9.13.0
64 | eslint-plugin-react-hooks:
65 | specifier: ^5.0.0
66 | version: 5.0.0(eslint@9.13.0)
67 | eslint-plugin-react-refresh:
68 | specifier: ^0.4.13
69 | version: 0.4.14(eslint@9.13.0)
70 | globals:
71 | specifier: ^15.11.0
72 | version: 15.11.0
73 | prettier:
74 | specifier: ^3.3.3
75 | version: 3.3.3
76 | typescript:
77 | specifier: ~5.6.2
78 | version: 5.6.3
79 | typescript-eslint:
80 | specifier: ^8.10.0
81 | version: 8.11.0(eslint@9.13.0)(typescript@5.6.3)
82 | vite:
83 | specifier: ^5.4.9
84 | version: 5.4.10
85 | vite-plugin-glsl:
86 | specifier: ^1.3.0
87 | version: 1.3.0(vite@5.4.10)
88 | vite-tsconfig-paths:
89 | specifier: ^5.0.1
90 | version: 5.0.1(typescript@5.6.3)(vite@5.4.10)
91 |
92 | packages:
93 |
94 | /@ampproject/remapping@2.3.0:
95 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
96 | engines: {node: '>=6.0.0'}
97 | dependencies:
98 | '@jridgewell/gen-mapping': 0.3.5
99 | '@jridgewell/trace-mapping': 0.3.25
100 | dev: true
101 |
102 | /@babel/code-frame@7.26.0:
103 | resolution: {integrity: sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==}
104 | engines: {node: '>=6.9.0'}
105 | dependencies:
106 | '@babel/helper-validator-identifier': 7.25.9
107 | js-tokens: 4.0.0
108 | picocolors: 1.1.1
109 |
110 | /@babel/compat-data@7.26.0:
111 | resolution: {integrity: sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==}
112 | engines: {node: '>=6.9.0'}
113 | dev: true
114 |
115 | /@babel/core@7.26.0:
116 | resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==}
117 | engines: {node: '>=6.9.0'}
118 | dependencies:
119 | '@ampproject/remapping': 2.3.0
120 | '@babel/code-frame': 7.26.0
121 | '@babel/generator': 7.26.0
122 | '@babel/helper-compilation-targets': 7.25.9
123 | '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
124 | '@babel/helpers': 7.26.0
125 | '@babel/parser': 7.26.1
126 | '@babel/template': 7.25.9
127 | '@babel/traverse': 7.25.9
128 | '@babel/types': 7.26.0
129 | convert-source-map: 2.0.0
130 | debug: 4.3.7
131 | gensync: 1.0.0-beta.2
132 | json5: 2.2.3
133 | semver: 6.3.1
134 | transitivePeerDependencies:
135 | - supports-color
136 | dev: true
137 |
138 | /@babel/generator@7.26.0:
139 | resolution: {integrity: sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==}
140 | engines: {node: '>=6.9.0'}
141 | dependencies:
142 | '@babel/parser': 7.26.1
143 | '@babel/types': 7.26.0
144 | '@jridgewell/gen-mapping': 0.3.5
145 | '@jridgewell/trace-mapping': 0.3.25
146 | jsesc: 3.0.2
147 |
148 | /@babel/helper-compilation-targets@7.25.9:
149 | resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==}
150 | engines: {node: '>=6.9.0'}
151 | dependencies:
152 | '@babel/compat-data': 7.26.0
153 | '@babel/helper-validator-option': 7.25.9
154 | browserslist: 4.24.2
155 | lru-cache: 5.1.1
156 | semver: 6.3.1
157 | dev: true
158 |
159 | /@babel/helper-module-imports@7.25.9:
160 | resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
161 | engines: {node: '>=6.9.0'}
162 | dependencies:
163 | '@babel/traverse': 7.25.9
164 | '@babel/types': 7.26.0
165 | transitivePeerDependencies:
166 | - supports-color
167 |
168 | /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0):
169 | resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
170 | engines: {node: '>=6.9.0'}
171 | peerDependencies:
172 | '@babel/core': ^7.0.0
173 | dependencies:
174 | '@babel/core': 7.26.0
175 | '@babel/helper-module-imports': 7.25.9
176 | '@babel/helper-validator-identifier': 7.25.9
177 | '@babel/traverse': 7.25.9
178 | transitivePeerDependencies:
179 | - supports-color
180 | dev: true
181 |
182 | /@babel/helper-plugin-utils@7.25.9:
183 | resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==}
184 | engines: {node: '>=6.9.0'}
185 | dev: true
186 |
187 | /@babel/helper-string-parser@7.25.9:
188 | resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
189 | engines: {node: '>=6.9.0'}
190 |
191 | /@babel/helper-validator-identifier@7.25.9:
192 | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
193 | engines: {node: '>=6.9.0'}
194 |
195 | /@babel/helper-validator-option@7.25.9:
196 | resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
197 | engines: {node: '>=6.9.0'}
198 | dev: true
199 |
200 | /@babel/helpers@7.26.0:
201 | resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==}
202 | engines: {node: '>=6.9.0'}
203 | dependencies:
204 | '@babel/template': 7.25.9
205 | '@babel/types': 7.26.0
206 | dev: true
207 |
208 | /@babel/parser@7.26.1:
209 | resolution: {integrity: sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==}
210 | engines: {node: '>=6.0.0'}
211 | hasBin: true
212 | dependencies:
213 | '@babel/types': 7.26.0
214 |
215 | /@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0):
216 | resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==}
217 | engines: {node: '>=6.9.0'}
218 | peerDependencies:
219 | '@babel/core': ^7.0.0-0
220 | dependencies:
221 | '@babel/core': 7.26.0
222 | '@babel/helper-plugin-utils': 7.25.9
223 | dev: true
224 |
225 | /@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0):
226 | resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==}
227 | engines: {node: '>=6.9.0'}
228 | peerDependencies:
229 | '@babel/core': ^7.0.0-0
230 | dependencies:
231 | '@babel/core': 7.26.0
232 | '@babel/helper-plugin-utils': 7.25.9
233 | dev: true
234 |
235 | /@babel/runtime@7.26.0:
236 | resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==}
237 | engines: {node: '>=6.9.0'}
238 | dependencies:
239 | regenerator-runtime: 0.14.1
240 | dev: false
241 |
242 | /@babel/template@7.25.9:
243 | resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==}
244 | engines: {node: '>=6.9.0'}
245 | dependencies:
246 | '@babel/code-frame': 7.26.0
247 | '@babel/parser': 7.26.1
248 | '@babel/types': 7.26.0
249 |
250 | /@babel/traverse@7.25.9:
251 | resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==}
252 | engines: {node: '>=6.9.0'}
253 | dependencies:
254 | '@babel/code-frame': 7.26.0
255 | '@babel/generator': 7.26.0
256 | '@babel/parser': 7.26.1
257 | '@babel/template': 7.25.9
258 | '@babel/types': 7.26.0
259 | debug: 4.3.7
260 | globals: 11.12.0
261 | transitivePeerDependencies:
262 | - supports-color
263 |
264 | /@babel/types@7.26.0:
265 | resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==}
266 | engines: {node: '>=6.9.0'}
267 | dependencies:
268 | '@babel/helper-string-parser': 7.25.9
269 | '@babel/helper-validator-identifier': 7.25.9
270 |
271 | /@emotion/babel-plugin@11.12.0:
272 | resolution: {integrity: sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==}
273 | dependencies:
274 | '@babel/helper-module-imports': 7.25.9
275 | '@babel/runtime': 7.26.0
276 | '@emotion/hash': 0.9.2
277 | '@emotion/memoize': 0.9.0
278 | '@emotion/serialize': 1.3.2
279 | babel-plugin-macros: 3.1.0
280 | convert-source-map: 1.9.0
281 | escape-string-regexp: 4.0.0
282 | find-root: 1.1.0
283 | source-map: 0.5.7
284 | stylis: 4.2.0
285 | transitivePeerDependencies:
286 | - supports-color
287 | dev: false
288 |
289 | /@emotion/cache@11.13.1:
290 | resolution: {integrity: sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==}
291 | dependencies:
292 | '@emotion/memoize': 0.9.0
293 | '@emotion/sheet': 1.4.0
294 | '@emotion/utils': 1.4.1
295 | '@emotion/weak-memoize': 0.4.0
296 | stylis: 4.2.0
297 | dev: false
298 |
299 | /@emotion/css@11.13.4:
300 | resolution: {integrity: sha512-CthbOD5EBw+iN0rfM96Tuv5kaZN4nxPyYDvGUs0bc7wZBBiU/0mse+l+0O9RshW2d+v5HH1cme+BAbLJ/3Folw==}
301 | dependencies:
302 | '@emotion/babel-plugin': 11.12.0
303 | '@emotion/cache': 11.13.1
304 | '@emotion/serialize': 1.3.2
305 | '@emotion/sheet': 1.4.0
306 | '@emotion/utils': 1.4.1
307 | transitivePeerDependencies:
308 | - supports-color
309 | dev: false
310 |
311 | /@emotion/hash@0.9.2:
312 | resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==}
313 | dev: false
314 |
315 | /@emotion/is-prop-valid@1.3.1:
316 | resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==}
317 | dependencies:
318 | '@emotion/memoize': 0.9.0
319 | dev: false
320 |
321 | /@emotion/memoize@0.9.0:
322 | resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==}
323 | dev: false
324 |
325 | /@emotion/react@11.13.3(@types/react@18.3.12)(react@18.3.1):
326 | resolution: {integrity: sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==}
327 | peerDependencies:
328 | '@types/react': '*'
329 | react: '>=16.8.0'
330 | peerDependenciesMeta:
331 | '@types/react':
332 | optional: true
333 | dependencies:
334 | '@babel/runtime': 7.26.0
335 | '@emotion/babel-plugin': 11.12.0
336 | '@emotion/cache': 11.13.1
337 | '@emotion/serialize': 1.3.2
338 | '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1)
339 | '@emotion/utils': 1.4.1
340 | '@emotion/weak-memoize': 0.4.0
341 | '@types/react': 18.3.12
342 | hoist-non-react-statics: 3.3.2
343 | react: 18.3.1
344 | transitivePeerDependencies:
345 | - supports-color
346 | dev: false
347 |
348 | /@emotion/serialize@1.3.2:
349 | resolution: {integrity: sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==}
350 | dependencies:
351 | '@emotion/hash': 0.9.2
352 | '@emotion/memoize': 0.9.0
353 | '@emotion/unitless': 0.10.0
354 | '@emotion/utils': 1.4.1
355 | csstype: 3.1.3
356 | dev: false
357 |
358 | /@emotion/sheet@1.4.0:
359 | resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==}
360 | dev: false
361 |
362 | /@emotion/styled@11.13.0(@emotion/react@11.13.3)(@types/react@18.3.12)(react@18.3.1):
363 | resolution: {integrity: sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==}
364 | peerDependencies:
365 | '@emotion/react': ^11.0.0-rc.0
366 | '@types/react': '*'
367 | react: '>=16.8.0'
368 | peerDependenciesMeta:
369 | '@types/react':
370 | optional: true
371 | dependencies:
372 | '@babel/runtime': 7.26.0
373 | '@emotion/babel-plugin': 11.12.0
374 | '@emotion/is-prop-valid': 1.3.1
375 | '@emotion/react': 11.13.3(@types/react@18.3.12)(react@18.3.1)
376 | '@emotion/serialize': 1.3.2
377 | '@emotion/use-insertion-effect-with-fallbacks': 1.1.0(react@18.3.1)
378 | '@emotion/utils': 1.4.1
379 | '@types/react': 18.3.12
380 | react: 18.3.1
381 | transitivePeerDependencies:
382 | - supports-color
383 | dev: false
384 |
385 | /@emotion/unitless@0.10.0:
386 | resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==}
387 | dev: false
388 |
389 | /@emotion/use-insertion-effect-with-fallbacks@1.1.0(react@18.3.1):
390 | resolution: {integrity: sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==}
391 | peerDependencies:
392 | react: '>=16.8.0'
393 | dependencies:
394 | react: 18.3.1
395 | dev: false
396 |
397 | /@emotion/utils@1.4.1:
398 | resolution: {integrity: sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==}
399 | dev: false
400 |
401 | /@emotion/weak-memoize@0.4.0:
402 | resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==}
403 | dev: false
404 |
405 | /@esbuild/aix-ppc64@0.21.5:
406 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==}
407 | engines: {node: '>=12'}
408 | cpu: [ppc64]
409 | os: [aix]
410 | requiresBuild: true
411 | dev: true
412 | optional: true
413 |
414 | /@esbuild/android-arm64@0.21.5:
415 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==}
416 | engines: {node: '>=12'}
417 | cpu: [arm64]
418 | os: [android]
419 | requiresBuild: true
420 | dev: true
421 | optional: true
422 |
423 | /@esbuild/android-arm@0.21.5:
424 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==}
425 | engines: {node: '>=12'}
426 | cpu: [arm]
427 | os: [android]
428 | requiresBuild: true
429 | dev: true
430 | optional: true
431 |
432 | /@esbuild/android-x64@0.21.5:
433 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==}
434 | engines: {node: '>=12'}
435 | cpu: [x64]
436 | os: [android]
437 | requiresBuild: true
438 | dev: true
439 | optional: true
440 |
441 | /@esbuild/darwin-arm64@0.21.5:
442 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==}
443 | engines: {node: '>=12'}
444 | cpu: [arm64]
445 | os: [darwin]
446 | requiresBuild: true
447 | dev: true
448 | optional: true
449 |
450 | /@esbuild/darwin-x64@0.21.5:
451 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==}
452 | engines: {node: '>=12'}
453 | cpu: [x64]
454 | os: [darwin]
455 | requiresBuild: true
456 | dev: true
457 | optional: true
458 |
459 | /@esbuild/freebsd-arm64@0.21.5:
460 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==}
461 | engines: {node: '>=12'}
462 | cpu: [arm64]
463 | os: [freebsd]
464 | requiresBuild: true
465 | dev: true
466 | optional: true
467 |
468 | /@esbuild/freebsd-x64@0.21.5:
469 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==}
470 | engines: {node: '>=12'}
471 | cpu: [x64]
472 | os: [freebsd]
473 | requiresBuild: true
474 | dev: true
475 | optional: true
476 |
477 | /@esbuild/linux-arm64@0.21.5:
478 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==}
479 | engines: {node: '>=12'}
480 | cpu: [arm64]
481 | os: [linux]
482 | requiresBuild: true
483 | dev: true
484 | optional: true
485 |
486 | /@esbuild/linux-arm@0.21.5:
487 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==}
488 | engines: {node: '>=12'}
489 | cpu: [arm]
490 | os: [linux]
491 | requiresBuild: true
492 | dev: true
493 | optional: true
494 |
495 | /@esbuild/linux-ia32@0.21.5:
496 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==}
497 | engines: {node: '>=12'}
498 | cpu: [ia32]
499 | os: [linux]
500 | requiresBuild: true
501 | dev: true
502 | optional: true
503 |
504 | /@esbuild/linux-loong64@0.21.5:
505 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==}
506 | engines: {node: '>=12'}
507 | cpu: [loong64]
508 | os: [linux]
509 | requiresBuild: true
510 | dev: true
511 | optional: true
512 |
513 | /@esbuild/linux-mips64el@0.21.5:
514 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==}
515 | engines: {node: '>=12'}
516 | cpu: [mips64el]
517 | os: [linux]
518 | requiresBuild: true
519 | dev: true
520 | optional: true
521 |
522 | /@esbuild/linux-ppc64@0.21.5:
523 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==}
524 | engines: {node: '>=12'}
525 | cpu: [ppc64]
526 | os: [linux]
527 | requiresBuild: true
528 | dev: true
529 | optional: true
530 |
531 | /@esbuild/linux-riscv64@0.21.5:
532 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==}
533 | engines: {node: '>=12'}
534 | cpu: [riscv64]
535 | os: [linux]
536 | requiresBuild: true
537 | dev: true
538 | optional: true
539 |
540 | /@esbuild/linux-s390x@0.21.5:
541 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==}
542 | engines: {node: '>=12'}
543 | cpu: [s390x]
544 | os: [linux]
545 | requiresBuild: true
546 | dev: true
547 | optional: true
548 |
549 | /@esbuild/linux-x64@0.21.5:
550 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==}
551 | engines: {node: '>=12'}
552 | cpu: [x64]
553 | os: [linux]
554 | requiresBuild: true
555 | dev: true
556 | optional: true
557 |
558 | /@esbuild/netbsd-x64@0.21.5:
559 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==}
560 | engines: {node: '>=12'}
561 | cpu: [x64]
562 | os: [netbsd]
563 | requiresBuild: true
564 | dev: true
565 | optional: true
566 |
567 | /@esbuild/openbsd-x64@0.21.5:
568 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==}
569 | engines: {node: '>=12'}
570 | cpu: [x64]
571 | os: [openbsd]
572 | requiresBuild: true
573 | dev: true
574 | optional: true
575 |
576 | /@esbuild/sunos-x64@0.21.5:
577 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==}
578 | engines: {node: '>=12'}
579 | cpu: [x64]
580 | os: [sunos]
581 | requiresBuild: true
582 | dev: true
583 | optional: true
584 |
585 | /@esbuild/win32-arm64@0.21.5:
586 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==}
587 | engines: {node: '>=12'}
588 | cpu: [arm64]
589 | os: [win32]
590 | requiresBuild: true
591 | dev: true
592 | optional: true
593 |
594 | /@esbuild/win32-ia32@0.21.5:
595 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==}
596 | engines: {node: '>=12'}
597 | cpu: [ia32]
598 | os: [win32]
599 | requiresBuild: true
600 | dev: true
601 | optional: true
602 |
603 | /@esbuild/win32-x64@0.21.5:
604 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==}
605 | engines: {node: '>=12'}
606 | cpu: [x64]
607 | os: [win32]
608 | requiresBuild: true
609 | dev: true
610 | optional: true
611 |
612 | /@eslint-community/eslint-utils@4.4.1(eslint@9.13.0):
613 | resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==}
614 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
615 | peerDependencies:
616 | eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
617 | dependencies:
618 | eslint: 9.13.0
619 | eslint-visitor-keys: 3.4.3
620 | dev: true
621 |
622 | /@eslint-community/regexpp@4.11.2:
623 | resolution: {integrity: sha512-2WwyTYNVaMNUWPZTOJdkax9iqTdirrApgTbk+Qoq5EPX6myqZvG8QGFRgdKmkjKVG6/G/a565vpPauHk0+hpBA==}
624 | engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
625 | dev: true
626 |
627 | /@eslint/config-array@0.18.0:
628 | resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==}
629 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
630 | dependencies:
631 | '@eslint/object-schema': 2.1.4
632 | debug: 4.3.7
633 | minimatch: 3.1.2
634 | transitivePeerDependencies:
635 | - supports-color
636 | dev: true
637 |
638 | /@eslint/core@0.7.0:
639 | resolution: {integrity: sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==}
640 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
641 | dev: true
642 |
643 | /@eslint/eslintrc@3.1.0:
644 | resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==}
645 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
646 | dependencies:
647 | ajv: 6.12.6
648 | debug: 4.3.7
649 | espree: 10.2.0
650 | globals: 14.0.0
651 | ignore: 5.3.2
652 | import-fresh: 3.3.0
653 | js-yaml: 4.1.0
654 | minimatch: 3.1.2
655 | strip-json-comments: 3.1.1
656 | transitivePeerDependencies:
657 | - supports-color
658 | dev: true
659 |
660 | /@eslint/js@9.13.0:
661 | resolution: {integrity: sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==}
662 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
663 | dev: true
664 |
665 | /@eslint/object-schema@2.1.4:
666 | resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==}
667 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
668 | dev: true
669 |
670 | /@eslint/plugin-kit@0.2.1:
671 | resolution: {integrity: sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==}
672 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
673 | dependencies:
674 | levn: 0.4.1
675 | dev: true
676 |
677 | /@humanfs/core@0.19.0:
678 | resolution: {integrity: sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==}
679 | engines: {node: '>=18.18.0'}
680 | dev: true
681 |
682 | /@humanfs/node@0.16.5:
683 | resolution: {integrity: sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==}
684 | engines: {node: '>=18.18.0'}
685 | dependencies:
686 | '@humanfs/core': 0.19.0
687 | '@humanwhocodes/retry': 0.3.1
688 | dev: true
689 |
690 | /@humanwhocodes/module-importer@1.0.1:
691 | resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
692 | engines: {node: '>=12.22'}
693 | dev: true
694 |
695 | /@humanwhocodes/retry@0.3.1:
696 | resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
697 | engines: {node: '>=18.18'}
698 | dev: true
699 |
700 | /@jridgewell/gen-mapping@0.3.5:
701 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==}
702 | engines: {node: '>=6.0.0'}
703 | dependencies:
704 | '@jridgewell/set-array': 1.2.1
705 | '@jridgewell/sourcemap-codec': 1.5.0
706 | '@jridgewell/trace-mapping': 0.3.25
707 |
708 | /@jridgewell/resolve-uri@3.1.2:
709 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
710 | engines: {node: '>=6.0.0'}
711 |
712 | /@jridgewell/set-array@1.2.1:
713 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
714 | engines: {node: '>=6.0.0'}
715 |
716 | /@jridgewell/sourcemap-codec@1.5.0:
717 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
718 |
719 | /@jridgewell/trace-mapping@0.3.25:
720 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
721 | dependencies:
722 | '@jridgewell/resolve-uri': 3.1.2
723 | '@jridgewell/sourcemap-codec': 1.5.0
724 |
725 | /@nodelib/fs.scandir@2.1.5:
726 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
727 | engines: {node: '>= 8'}
728 | dependencies:
729 | '@nodelib/fs.stat': 2.0.5
730 | run-parallel: 1.2.0
731 | dev: true
732 |
733 | /@nodelib/fs.stat@2.0.5:
734 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
735 | engines: {node: '>= 8'}
736 | dev: true
737 |
738 | /@nodelib/fs.walk@1.2.8:
739 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
740 | engines: {node: '>= 8'}
741 | dependencies:
742 | '@nodelib/fs.scandir': 2.1.5
743 | fastq: 1.17.1
744 | dev: true
745 |
746 | /@openmeteo/sdk@1.18.0:
747 | resolution: {integrity: sha512-rcx3dY4kC3KHndHi4gETJi3QpETf/GriaktoG47YVEMbZ0lXm8G9Ki8qWasXWogSP15F6REET4Z+E/aPw86Crw==}
748 | engines: {node: '>=12.0'}
749 | dependencies:
750 | flatbuffers: 24.3.25
751 | dev: false
752 |
753 | /@rollup/pluginutils@5.1.3:
754 | resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==}
755 | engines: {node: '>=14.0.0'}
756 | peerDependencies:
757 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
758 | peerDependenciesMeta:
759 | rollup:
760 | optional: true
761 | dependencies:
762 | '@types/estree': 1.0.6
763 | estree-walker: 2.0.2
764 | picomatch: 4.0.2
765 | dev: true
766 |
767 | /@rollup/rollup-android-arm-eabi@4.24.0:
768 | resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==}
769 | cpu: [arm]
770 | os: [android]
771 | requiresBuild: true
772 | dev: true
773 | optional: true
774 |
775 | /@rollup/rollup-android-arm64@4.24.0:
776 | resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==}
777 | cpu: [arm64]
778 | os: [android]
779 | requiresBuild: true
780 | dev: true
781 | optional: true
782 |
783 | /@rollup/rollup-darwin-arm64@4.24.0:
784 | resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==}
785 | cpu: [arm64]
786 | os: [darwin]
787 | requiresBuild: true
788 | dev: true
789 | optional: true
790 |
791 | /@rollup/rollup-darwin-x64@4.24.0:
792 | resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==}
793 | cpu: [x64]
794 | os: [darwin]
795 | requiresBuild: true
796 | dev: true
797 | optional: true
798 |
799 | /@rollup/rollup-linux-arm-gnueabihf@4.24.0:
800 | resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==}
801 | cpu: [arm]
802 | os: [linux]
803 | requiresBuild: true
804 | dev: true
805 | optional: true
806 |
807 | /@rollup/rollup-linux-arm-musleabihf@4.24.0:
808 | resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==}
809 | cpu: [arm]
810 | os: [linux]
811 | requiresBuild: true
812 | dev: true
813 | optional: true
814 |
815 | /@rollup/rollup-linux-arm64-gnu@4.24.0:
816 | resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==}
817 | cpu: [arm64]
818 | os: [linux]
819 | requiresBuild: true
820 | dev: true
821 | optional: true
822 |
823 | /@rollup/rollup-linux-arm64-musl@4.24.0:
824 | resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==}
825 | cpu: [arm64]
826 | os: [linux]
827 | requiresBuild: true
828 | dev: true
829 | optional: true
830 |
831 | /@rollup/rollup-linux-powerpc64le-gnu@4.24.0:
832 | resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==}
833 | cpu: [ppc64]
834 | os: [linux]
835 | requiresBuild: true
836 | dev: true
837 | optional: true
838 |
839 | /@rollup/rollup-linux-riscv64-gnu@4.24.0:
840 | resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==}
841 | cpu: [riscv64]
842 | os: [linux]
843 | requiresBuild: true
844 | dev: true
845 | optional: true
846 |
847 | /@rollup/rollup-linux-s390x-gnu@4.24.0:
848 | resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==}
849 | cpu: [s390x]
850 | os: [linux]
851 | requiresBuild: true
852 | dev: true
853 | optional: true
854 |
855 | /@rollup/rollup-linux-x64-gnu@4.24.0:
856 | resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==}
857 | cpu: [x64]
858 | os: [linux]
859 | requiresBuild: true
860 | dev: true
861 | optional: true
862 |
863 | /@rollup/rollup-linux-x64-musl@4.24.0:
864 | resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==}
865 | cpu: [x64]
866 | os: [linux]
867 | requiresBuild: true
868 | dev: true
869 | optional: true
870 |
871 | /@rollup/rollup-win32-arm64-msvc@4.24.0:
872 | resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==}
873 | cpu: [arm64]
874 | os: [win32]
875 | requiresBuild: true
876 | dev: true
877 | optional: true
878 |
879 | /@rollup/rollup-win32-ia32-msvc@4.24.0:
880 | resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==}
881 | cpu: [ia32]
882 | os: [win32]
883 | requiresBuild: true
884 | dev: true
885 | optional: true
886 |
887 | /@rollup/rollup-win32-x64-msvc@4.24.0:
888 | resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==}
889 | cpu: [x64]
890 | os: [win32]
891 | requiresBuild: true
892 | dev: true
893 | optional: true
894 |
895 | /@sardinefish/zogra-renderer@1.2.0:
896 | resolution: {integrity: sha512-0wbAzhi5AAtbHMF6zzVx3ISFPsqLmaJLhkZfm3dFbnThXDqGf/6Gj71nmXBPtzcV0oQOWm8bFpu1a0S7/pGLQg==}
897 | dependencies:
898 | gl-matrix: 3.4.3
899 | reflect-metadata: 0.1.14
900 | dev: false
901 |
902 | /@types/babel__core@7.20.5:
903 | resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
904 | dependencies:
905 | '@babel/parser': 7.26.1
906 | '@babel/types': 7.26.0
907 | '@types/babel__generator': 7.6.8
908 | '@types/babel__template': 7.4.4
909 | '@types/babel__traverse': 7.20.6
910 | dev: true
911 |
912 | /@types/babel__generator@7.6.8:
913 | resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
914 | dependencies:
915 | '@babel/types': 7.26.0
916 | dev: true
917 |
918 | /@types/babel__template@7.4.4:
919 | resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
920 | dependencies:
921 | '@babel/parser': 7.26.1
922 | '@babel/types': 7.26.0
923 | dev: true
924 |
925 | /@types/babel__traverse@7.20.6:
926 | resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
927 | dependencies:
928 | '@babel/types': 7.26.0
929 | dev: true
930 |
931 | /@types/estree@1.0.6:
932 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
933 | dev: true
934 |
935 | /@types/json-schema@7.0.15:
936 | resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
937 | dev: true
938 |
939 | /@types/lodash@4.17.12:
940 | resolution: {integrity: sha512-sviUmCE8AYdaF/KIHLDJBQgeYzPBI0vf/17NaYehBJfYD1j6/L95Slh07NlyK2iNyBNaEkb3En2jRt+a8y3xZQ==}
941 | dev: true
942 |
943 | /@types/parse-json@4.0.2:
944 | resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
945 | dev: false
946 |
947 | /@types/prop-types@15.7.13:
948 | resolution: {integrity: sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==}
949 |
950 | /@types/react-dom@18.3.1:
951 | resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==}
952 | dependencies:
953 | '@types/react': 18.3.12
954 | dev: true
955 |
956 | /@types/react@18.3.12:
957 | resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==}
958 | dependencies:
959 | '@types/prop-types': 15.7.13
960 | csstype: 3.1.3
961 |
962 | /@typescript-eslint/eslint-plugin@8.11.0(@typescript-eslint/parser@8.11.0)(eslint@9.13.0)(typescript@5.6.3):
963 | resolution: {integrity: sha512-KhGn2LjW1PJT2A/GfDpiyOfS4a8xHQv2myUagTM5+zsormOmBlYsnQ6pobJ8XxJmh6hnHwa2Mbe3fPrDJoDhbA==}
964 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
965 | peerDependencies:
966 | '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
967 | eslint: ^8.57.0 || ^9.0.0
968 | typescript: '*'
969 | peerDependenciesMeta:
970 | typescript:
971 | optional: true
972 | dependencies:
973 | '@eslint-community/regexpp': 4.11.2
974 | '@typescript-eslint/parser': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
975 | '@typescript-eslint/scope-manager': 8.11.0
976 | '@typescript-eslint/type-utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
977 | '@typescript-eslint/utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
978 | '@typescript-eslint/visitor-keys': 8.11.0
979 | eslint: 9.13.0
980 | graphemer: 1.4.0
981 | ignore: 5.3.2
982 | natural-compare: 1.4.0
983 | ts-api-utils: 1.3.0(typescript@5.6.3)
984 | typescript: 5.6.3
985 | transitivePeerDependencies:
986 | - supports-color
987 | dev: true
988 |
989 | /@typescript-eslint/parser@8.11.0(eslint@9.13.0)(typescript@5.6.3):
990 | resolution: {integrity: sha512-lmt73NeHdy1Q/2ul295Qy3uninSqi6wQI18XwSpm8w0ZbQXUpjCAWP1Vlv/obudoBiIjJVjlztjQ+d/Md98Yxg==}
991 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
992 | peerDependencies:
993 | eslint: ^8.57.0 || ^9.0.0
994 | typescript: '*'
995 | peerDependenciesMeta:
996 | typescript:
997 | optional: true
998 | dependencies:
999 | '@typescript-eslint/scope-manager': 8.11.0
1000 | '@typescript-eslint/types': 8.11.0
1001 | '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3)
1002 | '@typescript-eslint/visitor-keys': 8.11.0
1003 | debug: 4.3.7
1004 | eslint: 9.13.0
1005 | typescript: 5.6.3
1006 | transitivePeerDependencies:
1007 | - supports-color
1008 | dev: true
1009 |
1010 | /@typescript-eslint/scope-manager@8.11.0:
1011 | resolution: {integrity: sha512-Uholz7tWhXmA4r6epo+vaeV7yjdKy5QFCERMjs1kMVsLRKIrSdM6o21W2He9ftp5PP6aWOVpD5zvrvuHZC0bMQ==}
1012 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1013 | dependencies:
1014 | '@typescript-eslint/types': 8.11.0
1015 | '@typescript-eslint/visitor-keys': 8.11.0
1016 | dev: true
1017 |
1018 | /@typescript-eslint/type-utils@8.11.0(eslint@9.13.0)(typescript@5.6.3):
1019 | resolution: {integrity: sha512-ItiMfJS6pQU0NIKAaybBKkuVzo6IdnAhPFZA/2Mba/uBjuPQPet/8+zh5GtLHwmuFRShZx+8lhIs7/QeDHflOg==}
1020 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1021 | peerDependencies:
1022 | typescript: '*'
1023 | peerDependenciesMeta:
1024 | typescript:
1025 | optional: true
1026 | dependencies:
1027 | '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3)
1028 | '@typescript-eslint/utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
1029 | debug: 4.3.7
1030 | ts-api-utils: 1.3.0(typescript@5.6.3)
1031 | typescript: 5.6.3
1032 | transitivePeerDependencies:
1033 | - eslint
1034 | - supports-color
1035 | dev: true
1036 |
1037 | /@typescript-eslint/types@8.11.0:
1038 | resolution: {integrity: sha512-tn6sNMHf6EBAYMvmPUaKaVeYvhUsrE6x+bXQTxjQRp360h1giATU0WvgeEys1spbvb5R+VpNOZ+XJmjD8wOUHw==}
1039 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1040 | dev: true
1041 |
1042 | /@typescript-eslint/typescript-estree@8.11.0(typescript@5.6.3):
1043 | resolution: {integrity: sha512-yHC3s1z1RCHoCz5t06gf7jH24rr3vns08XXhfEqzYpd6Hll3z/3g23JRi0jM8A47UFKNc3u/y5KIMx8Ynbjohg==}
1044 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1045 | peerDependencies:
1046 | typescript: '*'
1047 | peerDependenciesMeta:
1048 | typescript:
1049 | optional: true
1050 | dependencies:
1051 | '@typescript-eslint/types': 8.11.0
1052 | '@typescript-eslint/visitor-keys': 8.11.0
1053 | debug: 4.3.7
1054 | fast-glob: 3.3.2
1055 | is-glob: 4.0.3
1056 | minimatch: 9.0.5
1057 | semver: 7.6.3
1058 | ts-api-utils: 1.3.0(typescript@5.6.3)
1059 | typescript: 5.6.3
1060 | transitivePeerDependencies:
1061 | - supports-color
1062 | dev: true
1063 |
1064 | /@typescript-eslint/utils@8.11.0(eslint@9.13.0)(typescript@5.6.3):
1065 | resolution: {integrity: sha512-CYiX6WZcbXNJV7UNB4PLDIBtSdRmRI/nb0FMyqHPTQD1rMjA0foPLaPUV39C/MxkTd/QKSeX+Gb34PPsDVC35g==}
1066 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1067 | peerDependencies:
1068 | eslint: ^8.57.0 || ^9.0.0
1069 | dependencies:
1070 | '@eslint-community/eslint-utils': 4.4.1(eslint@9.13.0)
1071 | '@typescript-eslint/scope-manager': 8.11.0
1072 | '@typescript-eslint/types': 8.11.0
1073 | '@typescript-eslint/typescript-estree': 8.11.0(typescript@5.6.3)
1074 | eslint: 9.13.0
1075 | transitivePeerDependencies:
1076 | - supports-color
1077 | - typescript
1078 | dev: true
1079 |
1080 | /@typescript-eslint/visitor-keys@8.11.0:
1081 | resolution: {integrity: sha512-EaewX6lxSjRJnc+99+dqzTeoDZUfyrA52d2/HRrkI830kgovWsmIiTfmr0NZorzqic7ga+1bS60lRBUgR3n/Bw==}
1082 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1083 | dependencies:
1084 | '@typescript-eslint/types': 8.11.0
1085 | eslint-visitor-keys: 3.4.3
1086 | dev: true
1087 |
1088 | /@vitejs/plugin-react@4.3.3(vite@5.4.10):
1089 | resolution: {integrity: sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==}
1090 | engines: {node: ^14.18.0 || >=16.0.0}
1091 | peerDependencies:
1092 | vite: ^4.2.0 || ^5.0.0
1093 | dependencies:
1094 | '@babel/core': 7.26.0
1095 | '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
1096 | '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
1097 | '@types/babel__core': 7.20.5
1098 | react-refresh: 0.14.2
1099 | vite: 5.4.10
1100 | transitivePeerDependencies:
1101 | - supports-color
1102 | dev: true
1103 |
1104 | /acorn-jsx@5.3.2(acorn@8.13.0):
1105 | resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
1106 | peerDependencies:
1107 | acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
1108 | dependencies:
1109 | acorn: 8.13.0
1110 | dev: true
1111 |
1112 | /acorn@8.13.0:
1113 | resolution: {integrity: sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==}
1114 | engines: {node: '>=0.4.0'}
1115 | hasBin: true
1116 | dev: true
1117 |
1118 | /ajv@6.12.6:
1119 | resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
1120 | dependencies:
1121 | fast-deep-equal: 3.1.3
1122 | fast-json-stable-stringify: 2.1.0
1123 | json-schema-traverse: 0.4.1
1124 | uri-js: 4.4.1
1125 | dev: true
1126 |
1127 | /ansi-styles@4.3.0:
1128 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
1129 | engines: {node: '>=8'}
1130 | dependencies:
1131 | color-convert: 2.0.1
1132 | dev: true
1133 |
1134 | /argparse@2.0.1:
1135 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
1136 | dev: true
1137 |
1138 | /babel-plugin-macros@3.1.0:
1139 | resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
1140 | engines: {node: '>=10', npm: '>=6'}
1141 | dependencies:
1142 | '@babel/runtime': 7.26.0
1143 | cosmiconfig: 7.1.0
1144 | resolve: 1.22.8
1145 | dev: false
1146 |
1147 | /balanced-match@1.0.2:
1148 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
1149 | dev: true
1150 |
1151 | /brace-expansion@1.1.11:
1152 | resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
1153 | dependencies:
1154 | balanced-match: 1.0.2
1155 | concat-map: 0.0.1
1156 | dev: true
1157 |
1158 | /brace-expansion@2.0.1:
1159 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
1160 | dependencies:
1161 | balanced-match: 1.0.2
1162 | dev: true
1163 |
1164 | /braces@3.0.3:
1165 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
1166 | engines: {node: '>=8'}
1167 | dependencies:
1168 | fill-range: 7.1.1
1169 | dev: true
1170 |
1171 | /browserslist@4.24.2:
1172 | resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==}
1173 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
1174 | hasBin: true
1175 | dependencies:
1176 | caniuse-lite: 1.0.30001671
1177 | electron-to-chromium: 1.5.47
1178 | node-releases: 2.0.18
1179 | update-browserslist-db: 1.1.1(browserslist@4.24.2)
1180 | dev: true
1181 |
1182 | /callsites@3.1.0:
1183 | resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
1184 | engines: {node: '>=6'}
1185 |
1186 | /caniuse-lite@1.0.30001671:
1187 | resolution: {integrity: sha512-jocyVaSSfXg2faluE6hrWkMgDOiULBMca4QLtDT39hw1YxaIPHWc1CcTCKkPmHgGH6tKji6ZNbMSmUAvENf2/A==}
1188 | dev: true
1189 |
1190 | /chalk@4.1.2:
1191 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
1192 | engines: {node: '>=10'}
1193 | dependencies:
1194 | ansi-styles: 4.3.0
1195 | supports-color: 7.2.0
1196 | dev: true
1197 |
1198 | /color-convert@2.0.1:
1199 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
1200 | engines: {node: '>=7.0.0'}
1201 | dependencies:
1202 | color-name: 1.1.4
1203 | dev: true
1204 |
1205 | /color-name@1.1.4:
1206 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
1207 | dev: true
1208 |
1209 | /concat-map@0.0.1:
1210 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
1211 | dev: true
1212 |
1213 | /convert-source-map@1.9.0:
1214 | resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
1215 | dev: false
1216 |
1217 | /convert-source-map@2.0.0:
1218 | resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
1219 | dev: true
1220 |
1221 | /cosmiconfig@7.1.0:
1222 | resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
1223 | engines: {node: '>=10'}
1224 | dependencies:
1225 | '@types/parse-json': 4.0.2
1226 | import-fresh: 3.3.0
1227 | parse-json: 5.2.0
1228 | path-type: 4.0.0
1229 | yaml: 1.10.2
1230 | dev: false
1231 |
1232 | /cross-spawn@7.0.3:
1233 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
1234 | engines: {node: '>= 8'}
1235 | dependencies:
1236 | path-key: 3.1.1
1237 | shebang-command: 2.0.0
1238 | which: 2.0.2
1239 | dev: true
1240 |
1241 | /csstype@3.1.3:
1242 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
1243 |
1244 | /dayjs@1.11.13:
1245 | resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==}
1246 | dev: false
1247 |
1248 | /debug@4.3.7:
1249 | resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
1250 | engines: {node: '>=6.0'}
1251 | peerDependencies:
1252 | supports-color: '*'
1253 | peerDependenciesMeta:
1254 | supports-color:
1255 | optional: true
1256 | dependencies:
1257 | ms: 2.1.3
1258 |
1259 | /deep-is@0.1.4:
1260 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
1261 | dev: true
1262 |
1263 | /electron-to-chromium@1.5.47:
1264 | resolution: {integrity: sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ==}
1265 | dev: true
1266 |
1267 | /error-ex@1.3.2:
1268 | resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
1269 | dependencies:
1270 | is-arrayish: 0.2.1
1271 | dev: false
1272 |
1273 | /esbuild@0.21.5:
1274 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==}
1275 | engines: {node: '>=12'}
1276 | hasBin: true
1277 | requiresBuild: true
1278 | optionalDependencies:
1279 | '@esbuild/aix-ppc64': 0.21.5
1280 | '@esbuild/android-arm': 0.21.5
1281 | '@esbuild/android-arm64': 0.21.5
1282 | '@esbuild/android-x64': 0.21.5
1283 | '@esbuild/darwin-arm64': 0.21.5
1284 | '@esbuild/darwin-x64': 0.21.5
1285 | '@esbuild/freebsd-arm64': 0.21.5
1286 | '@esbuild/freebsd-x64': 0.21.5
1287 | '@esbuild/linux-arm': 0.21.5
1288 | '@esbuild/linux-arm64': 0.21.5
1289 | '@esbuild/linux-ia32': 0.21.5
1290 | '@esbuild/linux-loong64': 0.21.5
1291 | '@esbuild/linux-mips64el': 0.21.5
1292 | '@esbuild/linux-ppc64': 0.21.5
1293 | '@esbuild/linux-riscv64': 0.21.5
1294 | '@esbuild/linux-s390x': 0.21.5
1295 | '@esbuild/linux-x64': 0.21.5
1296 | '@esbuild/netbsd-x64': 0.21.5
1297 | '@esbuild/openbsd-x64': 0.21.5
1298 | '@esbuild/sunos-x64': 0.21.5
1299 | '@esbuild/win32-arm64': 0.21.5
1300 | '@esbuild/win32-ia32': 0.21.5
1301 | '@esbuild/win32-x64': 0.21.5
1302 | dev: true
1303 |
1304 | /escalade@3.2.0:
1305 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
1306 | engines: {node: '>=6'}
1307 | dev: true
1308 |
1309 | /escape-string-regexp@4.0.0:
1310 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
1311 | engines: {node: '>=10'}
1312 |
1313 | /eslint-plugin-react-hooks@5.0.0(eslint@9.13.0):
1314 | resolution: {integrity: sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==}
1315 | engines: {node: '>=10'}
1316 | peerDependencies:
1317 | eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
1318 | dependencies:
1319 | eslint: 9.13.0
1320 | dev: true
1321 |
1322 | /eslint-plugin-react-refresh@0.4.14(eslint@9.13.0):
1323 | resolution: {integrity: sha512-aXvzCTK7ZBv1e7fahFuR3Z/fyQQSIQ711yPgYRj+Oj64tyTgO4iQIDmYXDBqvSWQ/FA4OSCsXOStlF+noU0/NA==}
1324 | peerDependencies:
1325 | eslint: '>=7'
1326 | dependencies:
1327 | eslint: 9.13.0
1328 | dev: true
1329 |
1330 | /eslint-scope@8.1.0:
1331 | resolution: {integrity: sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==}
1332 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1333 | dependencies:
1334 | esrecurse: 4.3.0
1335 | estraverse: 5.3.0
1336 | dev: true
1337 |
1338 | /eslint-visitor-keys@3.4.3:
1339 | resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
1340 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
1341 | dev: true
1342 |
1343 | /eslint-visitor-keys@4.1.0:
1344 | resolution: {integrity: sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==}
1345 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1346 | dev: true
1347 |
1348 | /eslint@9.13.0:
1349 | resolution: {integrity: sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==}
1350 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1351 | hasBin: true
1352 | peerDependencies:
1353 | jiti: '*'
1354 | peerDependenciesMeta:
1355 | jiti:
1356 | optional: true
1357 | dependencies:
1358 | '@eslint-community/eslint-utils': 4.4.1(eslint@9.13.0)
1359 | '@eslint-community/regexpp': 4.11.2
1360 | '@eslint/config-array': 0.18.0
1361 | '@eslint/core': 0.7.0
1362 | '@eslint/eslintrc': 3.1.0
1363 | '@eslint/js': 9.13.0
1364 | '@eslint/plugin-kit': 0.2.1
1365 | '@humanfs/node': 0.16.5
1366 | '@humanwhocodes/module-importer': 1.0.1
1367 | '@humanwhocodes/retry': 0.3.1
1368 | '@types/estree': 1.0.6
1369 | '@types/json-schema': 7.0.15
1370 | ajv: 6.12.6
1371 | chalk: 4.1.2
1372 | cross-spawn: 7.0.3
1373 | debug: 4.3.7
1374 | escape-string-regexp: 4.0.0
1375 | eslint-scope: 8.1.0
1376 | eslint-visitor-keys: 4.1.0
1377 | espree: 10.2.0
1378 | esquery: 1.6.0
1379 | esutils: 2.0.3
1380 | fast-deep-equal: 3.1.3
1381 | file-entry-cache: 8.0.0
1382 | find-up: 5.0.0
1383 | glob-parent: 6.0.2
1384 | ignore: 5.3.2
1385 | imurmurhash: 0.1.4
1386 | is-glob: 4.0.3
1387 | json-stable-stringify-without-jsonify: 1.0.1
1388 | lodash.merge: 4.6.2
1389 | minimatch: 3.1.2
1390 | natural-compare: 1.4.0
1391 | optionator: 0.9.4
1392 | text-table: 0.2.0
1393 | transitivePeerDependencies:
1394 | - supports-color
1395 | dev: true
1396 |
1397 | /espree@10.2.0:
1398 | resolution: {integrity: sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==}
1399 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1400 | dependencies:
1401 | acorn: 8.13.0
1402 | acorn-jsx: 5.3.2(acorn@8.13.0)
1403 | eslint-visitor-keys: 4.1.0
1404 | dev: true
1405 |
1406 | /esquery@1.6.0:
1407 | resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
1408 | engines: {node: '>=0.10'}
1409 | dependencies:
1410 | estraverse: 5.3.0
1411 | dev: true
1412 |
1413 | /esrecurse@4.3.0:
1414 | resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
1415 | engines: {node: '>=4.0'}
1416 | dependencies:
1417 | estraverse: 5.3.0
1418 | dev: true
1419 |
1420 | /estraverse@5.3.0:
1421 | resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
1422 | engines: {node: '>=4.0'}
1423 | dev: true
1424 |
1425 | /estree-walker@2.0.2:
1426 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
1427 | dev: true
1428 |
1429 | /esutils@2.0.3:
1430 | resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
1431 | engines: {node: '>=0.10.0'}
1432 | dev: true
1433 |
1434 | /fast-deep-equal@3.1.3:
1435 | resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
1436 | dev: true
1437 |
1438 | /fast-glob@3.3.2:
1439 | resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
1440 | engines: {node: '>=8.6.0'}
1441 | dependencies:
1442 | '@nodelib/fs.stat': 2.0.5
1443 | '@nodelib/fs.walk': 1.2.8
1444 | glob-parent: 5.1.2
1445 | merge2: 1.4.1
1446 | micromatch: 4.0.8
1447 | dev: true
1448 |
1449 | /fast-json-stable-stringify@2.1.0:
1450 | resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
1451 | dev: true
1452 |
1453 | /fast-levenshtein@2.0.6:
1454 | resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
1455 | dev: true
1456 |
1457 | /fastq@1.17.1:
1458 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
1459 | dependencies:
1460 | reusify: 1.0.4
1461 | dev: true
1462 |
1463 | /file-entry-cache@8.0.0:
1464 | resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
1465 | engines: {node: '>=16.0.0'}
1466 | dependencies:
1467 | flat-cache: 4.0.1
1468 | dev: true
1469 |
1470 | /fill-range@7.1.1:
1471 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
1472 | engines: {node: '>=8'}
1473 | dependencies:
1474 | to-regex-range: 5.0.1
1475 | dev: true
1476 |
1477 | /find-root@1.1.0:
1478 | resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
1479 | dev: false
1480 |
1481 | /find-up@5.0.0:
1482 | resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
1483 | engines: {node: '>=10'}
1484 | dependencies:
1485 | locate-path: 6.0.0
1486 | path-exists: 4.0.0
1487 | dev: true
1488 |
1489 | /flat-cache@4.0.1:
1490 | resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
1491 | engines: {node: '>=16'}
1492 | dependencies:
1493 | flatted: 3.3.1
1494 | keyv: 4.5.4
1495 | dev: true
1496 |
1497 | /flatbuffers@24.3.25:
1498 | resolution: {integrity: sha512-3HDgPbgiwWMI9zVB7VYBHaMrbOO7Gm0v+yD2FV/sCKj+9NDeVL7BOBYUuhWAQGKWOzBo8S9WdMvV0eixO233XQ==}
1499 | dev: false
1500 |
1501 | /flatted@3.3.1:
1502 | resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
1503 | dev: true
1504 |
1505 | /fsevents@2.3.3:
1506 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
1507 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
1508 | os: [darwin]
1509 | requiresBuild: true
1510 | dev: true
1511 | optional: true
1512 |
1513 | /function-bind@1.1.2:
1514 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
1515 | dev: false
1516 |
1517 | /gensync@1.0.0-beta.2:
1518 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
1519 | engines: {node: '>=6.9.0'}
1520 | dev: true
1521 |
1522 | /gl-matrix@3.4.3:
1523 | resolution: {integrity: sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==}
1524 | dev: false
1525 |
1526 | /glob-parent@5.1.2:
1527 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
1528 | engines: {node: '>= 6'}
1529 | dependencies:
1530 | is-glob: 4.0.3
1531 | dev: true
1532 |
1533 | /glob-parent@6.0.2:
1534 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
1535 | engines: {node: '>=10.13.0'}
1536 | dependencies:
1537 | is-glob: 4.0.3
1538 | dev: true
1539 |
1540 | /globals@11.12.0:
1541 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
1542 | engines: {node: '>=4'}
1543 |
1544 | /globals@14.0.0:
1545 | resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
1546 | engines: {node: '>=18'}
1547 | dev: true
1548 |
1549 | /globals@15.11.0:
1550 | resolution: {integrity: sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==}
1551 | engines: {node: '>=18'}
1552 | dev: true
1553 |
1554 | /globrex@0.1.2:
1555 | resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
1556 | dev: true
1557 |
1558 | /graphemer@1.4.0:
1559 | resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
1560 | dev: true
1561 |
1562 | /has-flag@4.0.0:
1563 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
1564 | engines: {node: '>=8'}
1565 | dev: true
1566 |
1567 | /hasown@2.0.2:
1568 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
1569 | engines: {node: '>= 0.4'}
1570 | dependencies:
1571 | function-bind: 1.1.2
1572 | dev: false
1573 |
1574 | /hoist-non-react-statics@3.3.2:
1575 | resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
1576 | dependencies:
1577 | react-is: 16.13.1
1578 | dev: false
1579 |
1580 | /ignore@5.3.2:
1581 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
1582 | engines: {node: '>= 4'}
1583 | dev: true
1584 |
1585 | /import-fresh@3.3.0:
1586 | resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
1587 | engines: {node: '>=6'}
1588 | dependencies:
1589 | parent-module: 1.0.1
1590 | resolve-from: 4.0.0
1591 |
1592 | /imurmurhash@0.1.4:
1593 | resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
1594 | engines: {node: '>=0.8.19'}
1595 | dev: true
1596 |
1597 | /is-arrayish@0.2.1:
1598 | resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
1599 | dev: false
1600 |
1601 | /is-core-module@2.15.1:
1602 | resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==}
1603 | engines: {node: '>= 0.4'}
1604 | dependencies:
1605 | hasown: 2.0.2
1606 | dev: false
1607 |
1608 | /is-extglob@2.1.1:
1609 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
1610 | engines: {node: '>=0.10.0'}
1611 | dev: true
1612 |
1613 | /is-glob@4.0.3:
1614 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
1615 | engines: {node: '>=0.10.0'}
1616 | dependencies:
1617 | is-extglob: 2.1.1
1618 | dev: true
1619 |
1620 | /is-number@7.0.0:
1621 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
1622 | engines: {node: '>=0.12.0'}
1623 | dev: true
1624 |
1625 | /isexe@2.0.0:
1626 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
1627 | dev: true
1628 |
1629 | /js-tokens@4.0.0:
1630 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
1631 |
1632 | /js-yaml@4.1.0:
1633 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
1634 | hasBin: true
1635 | dependencies:
1636 | argparse: 2.0.1
1637 | dev: true
1638 |
1639 | /jsesc@3.0.2:
1640 | resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==}
1641 | engines: {node: '>=6'}
1642 | hasBin: true
1643 |
1644 | /json-buffer@3.0.1:
1645 | resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
1646 | dev: true
1647 |
1648 | /json-parse-even-better-errors@2.3.1:
1649 | resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
1650 | dev: false
1651 |
1652 | /json-schema-traverse@0.4.1:
1653 | resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
1654 | dev: true
1655 |
1656 | /json-stable-stringify-without-jsonify@1.0.1:
1657 | resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
1658 | dev: true
1659 |
1660 | /json5@2.2.3:
1661 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
1662 | engines: {node: '>=6'}
1663 | hasBin: true
1664 | dev: true
1665 |
1666 | /keyv@4.5.4:
1667 | resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
1668 | dependencies:
1669 | json-buffer: 3.0.1
1670 | dev: true
1671 |
1672 | /levn@0.4.1:
1673 | resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
1674 | engines: {node: '>= 0.8.0'}
1675 | dependencies:
1676 | prelude-ls: 1.2.1
1677 | type-check: 0.4.0
1678 | dev: true
1679 |
1680 | /lines-and-columns@1.2.4:
1681 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
1682 | dev: false
1683 |
1684 | /locate-path@6.0.0:
1685 | resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
1686 | engines: {node: '>=10'}
1687 | dependencies:
1688 | p-locate: 5.0.0
1689 | dev: true
1690 |
1691 | /lodash.merge@4.6.2:
1692 | resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
1693 | dev: true
1694 |
1695 | /lodash@4.17.21:
1696 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
1697 | dev: false
1698 |
1699 | /loose-envify@1.4.0:
1700 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
1701 | hasBin: true
1702 | dependencies:
1703 | js-tokens: 4.0.0
1704 | dev: false
1705 |
1706 | /lru-cache@5.1.1:
1707 | resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
1708 | dependencies:
1709 | yallist: 3.1.1
1710 | dev: true
1711 |
1712 | /merge2@1.4.1:
1713 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
1714 | engines: {node: '>= 8'}
1715 | dev: true
1716 |
1717 | /micromatch@4.0.8:
1718 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
1719 | engines: {node: '>=8.6'}
1720 | dependencies:
1721 | braces: 3.0.3
1722 | picomatch: 2.3.1
1723 | dev: true
1724 |
1725 | /minimatch@3.1.2:
1726 | resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
1727 | dependencies:
1728 | brace-expansion: 1.1.11
1729 | dev: true
1730 |
1731 | /minimatch@9.0.5:
1732 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
1733 | engines: {node: '>=16 || 14 >=14.17'}
1734 | dependencies:
1735 | brace-expansion: 2.0.1
1736 | dev: true
1737 |
1738 | /ms@2.1.3:
1739 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
1740 |
1741 | /nanoid@3.3.7:
1742 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
1743 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
1744 | hasBin: true
1745 | dev: true
1746 |
1747 | /natural-compare@1.4.0:
1748 | resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
1749 | dev: true
1750 |
1751 | /node-releases@2.0.18:
1752 | resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==}
1753 | dev: true
1754 |
1755 | /normalize.css@8.0.1:
1756 | resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==}
1757 | dev: false
1758 |
1759 | /openmeteo@1.1.4:
1760 | resolution: {integrity: sha512-TalTDl0M7JJoeRTf+rWiFZ9SLvoxm7KkFLOQqcSjCiYs+bVMhax1qtryJqeZ1RF4W4Xfsgcl9x+VC1z39ULCxA==}
1761 | engines: {node: '>=12.0'}
1762 | dependencies:
1763 | '@openmeteo/sdk': 1.18.0
1764 | flatbuffers: 24.3.25
1765 | dev: false
1766 |
1767 | /optionator@0.9.4:
1768 | resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
1769 | engines: {node: '>= 0.8.0'}
1770 | dependencies:
1771 | deep-is: 0.1.4
1772 | fast-levenshtein: 2.0.6
1773 | levn: 0.4.1
1774 | prelude-ls: 1.2.1
1775 | type-check: 0.4.0
1776 | word-wrap: 1.2.5
1777 | dev: true
1778 |
1779 | /p-limit@3.1.0:
1780 | resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
1781 | engines: {node: '>=10'}
1782 | dependencies:
1783 | yocto-queue: 0.1.0
1784 | dev: true
1785 |
1786 | /p-locate@5.0.0:
1787 | resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
1788 | engines: {node: '>=10'}
1789 | dependencies:
1790 | p-limit: 3.1.0
1791 | dev: true
1792 |
1793 | /parent-module@1.0.1:
1794 | resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
1795 | engines: {node: '>=6'}
1796 | dependencies:
1797 | callsites: 3.1.0
1798 |
1799 | /parse-json@5.2.0:
1800 | resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
1801 | engines: {node: '>=8'}
1802 | dependencies:
1803 | '@babel/code-frame': 7.26.0
1804 | error-ex: 1.3.2
1805 | json-parse-even-better-errors: 2.3.1
1806 | lines-and-columns: 1.2.4
1807 | dev: false
1808 |
1809 | /path-exists@4.0.0:
1810 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
1811 | engines: {node: '>=8'}
1812 | dev: true
1813 |
1814 | /path-key@3.1.1:
1815 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
1816 | engines: {node: '>=8'}
1817 | dev: true
1818 |
1819 | /path-parse@1.0.7:
1820 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
1821 | dev: false
1822 |
1823 | /path-type@4.0.0:
1824 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
1825 | engines: {node: '>=8'}
1826 | dev: false
1827 |
1828 | /picocolors@1.1.1:
1829 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
1830 |
1831 | /picomatch@2.3.1:
1832 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
1833 | engines: {node: '>=8.6'}
1834 | dev: true
1835 |
1836 | /picomatch@4.0.2:
1837 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
1838 | engines: {node: '>=12'}
1839 | dev: true
1840 |
1841 | /postcss@8.4.47:
1842 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==}
1843 | engines: {node: ^10 || ^12 || >=14}
1844 | dependencies:
1845 | nanoid: 3.3.7
1846 | picocolors: 1.1.1
1847 | source-map-js: 1.2.1
1848 | dev: true
1849 |
1850 | /prelude-ls@1.2.1:
1851 | resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
1852 | engines: {node: '>= 0.8.0'}
1853 | dev: true
1854 |
1855 | /prettier@3.3.3:
1856 | resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
1857 | engines: {node: '>=14'}
1858 | hasBin: true
1859 | dev: true
1860 |
1861 | /punycode@2.3.1:
1862 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
1863 | engines: {node: '>=6'}
1864 | dev: true
1865 |
1866 | /queue-microtask@1.2.3:
1867 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
1868 | dev: true
1869 |
1870 | /raindrop-fx@1.0.8:
1871 | resolution: {integrity: sha512-KcCeENGsFN70jVpdmRTxUJiU012oUhrHdR0n6XmMy2euJu95QcB2Uv5Om/mzzZGoyRcD650+H5yP/Q54mdi1Pw==}
1872 | dependencies:
1873 | '@sardinefish/zogra-renderer': 1.2.0
1874 | dev: false
1875 |
1876 | /react-dom@18.3.1(react@18.3.1):
1877 | resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
1878 | peerDependencies:
1879 | react: ^18.3.1
1880 | dependencies:
1881 | loose-envify: 1.4.0
1882 | react: 18.3.1
1883 | scheduler: 0.23.2
1884 | dev: false
1885 |
1886 | /react-icons@5.3.0(react@18.3.1):
1887 | resolution: {integrity: sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==}
1888 | peerDependencies:
1889 | react: '*'
1890 | dependencies:
1891 | react: 18.3.1
1892 | dev: false
1893 |
1894 | /react-is@16.13.1:
1895 | resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
1896 | dev: false
1897 |
1898 | /react-refresh@0.14.2:
1899 | resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
1900 | engines: {node: '>=0.10.0'}
1901 | dev: true
1902 |
1903 | /react@18.3.1:
1904 | resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
1905 | engines: {node: '>=0.10.0'}
1906 | dependencies:
1907 | loose-envify: 1.4.0
1908 | dev: false
1909 |
1910 | /reflect-metadata@0.1.14:
1911 | resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==}
1912 | dev: false
1913 |
1914 | /regenerator-runtime@0.14.1:
1915 | resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
1916 | dev: false
1917 |
1918 | /resolve-from@4.0.0:
1919 | resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
1920 | engines: {node: '>=4'}
1921 |
1922 | /resolve@1.22.8:
1923 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
1924 | hasBin: true
1925 | dependencies:
1926 | is-core-module: 2.15.1
1927 | path-parse: 1.0.7
1928 | supports-preserve-symlinks-flag: 1.0.0
1929 | dev: false
1930 |
1931 | /reusify@1.0.4:
1932 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
1933 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
1934 | dev: true
1935 |
1936 | /rollup@4.24.0:
1937 | resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==}
1938 | engines: {node: '>=18.0.0', npm: '>=8.0.0'}
1939 | hasBin: true
1940 | dependencies:
1941 | '@types/estree': 1.0.6
1942 | optionalDependencies:
1943 | '@rollup/rollup-android-arm-eabi': 4.24.0
1944 | '@rollup/rollup-android-arm64': 4.24.0
1945 | '@rollup/rollup-darwin-arm64': 4.24.0
1946 | '@rollup/rollup-darwin-x64': 4.24.0
1947 | '@rollup/rollup-linux-arm-gnueabihf': 4.24.0
1948 | '@rollup/rollup-linux-arm-musleabihf': 4.24.0
1949 | '@rollup/rollup-linux-arm64-gnu': 4.24.0
1950 | '@rollup/rollup-linux-arm64-musl': 4.24.0
1951 | '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0
1952 | '@rollup/rollup-linux-riscv64-gnu': 4.24.0
1953 | '@rollup/rollup-linux-s390x-gnu': 4.24.0
1954 | '@rollup/rollup-linux-x64-gnu': 4.24.0
1955 | '@rollup/rollup-linux-x64-musl': 4.24.0
1956 | '@rollup/rollup-win32-arm64-msvc': 4.24.0
1957 | '@rollup/rollup-win32-ia32-msvc': 4.24.0
1958 | '@rollup/rollup-win32-x64-msvc': 4.24.0
1959 | fsevents: 2.3.3
1960 | dev: true
1961 |
1962 | /run-parallel@1.2.0:
1963 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
1964 | dependencies:
1965 | queue-microtask: 1.2.3
1966 | dev: true
1967 |
1968 | /scheduler@0.23.2:
1969 | resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
1970 | dependencies:
1971 | loose-envify: 1.4.0
1972 | dev: false
1973 |
1974 | /semver@6.3.1:
1975 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
1976 | hasBin: true
1977 | dev: true
1978 |
1979 | /semver@7.6.3:
1980 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
1981 | engines: {node: '>=10'}
1982 | hasBin: true
1983 | dev: true
1984 |
1985 | /shebang-command@2.0.0:
1986 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
1987 | engines: {node: '>=8'}
1988 | dependencies:
1989 | shebang-regex: 3.0.0
1990 | dev: true
1991 |
1992 | /shebang-regex@3.0.0:
1993 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
1994 | engines: {node: '>=8'}
1995 | dev: true
1996 |
1997 | /source-map-js@1.2.1:
1998 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
1999 | engines: {node: '>=0.10.0'}
2000 | dev: true
2001 |
2002 | /source-map@0.5.7:
2003 | resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
2004 | engines: {node: '>=0.10.0'}
2005 | dev: false
2006 |
2007 | /strip-json-comments@3.1.1:
2008 | resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
2009 | engines: {node: '>=8'}
2010 | dev: true
2011 |
2012 | /stylis@4.2.0:
2013 | resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==}
2014 | dev: false
2015 |
2016 | /supports-color@7.2.0:
2017 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
2018 | engines: {node: '>=8'}
2019 | dependencies:
2020 | has-flag: 4.0.0
2021 | dev: true
2022 |
2023 | /supports-preserve-symlinks-flag@1.0.0:
2024 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
2025 | engines: {node: '>= 0.4'}
2026 | dev: false
2027 |
2028 | /text-table@0.2.0:
2029 | resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
2030 | dev: true
2031 |
2032 | /to-regex-range@5.0.1:
2033 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
2034 | engines: {node: '>=8.0'}
2035 | dependencies:
2036 | is-number: 7.0.0
2037 | dev: true
2038 |
2039 | /ts-api-utils@1.3.0(typescript@5.6.3):
2040 | resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
2041 | engines: {node: '>=16'}
2042 | peerDependencies:
2043 | typescript: '>=4.2.0'
2044 | dependencies:
2045 | typescript: 5.6.3
2046 | dev: true
2047 |
2048 | /tsconfck@3.1.4(typescript@5.6.3):
2049 | resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==}
2050 | engines: {node: ^18 || >=20}
2051 | hasBin: true
2052 | peerDependencies:
2053 | typescript: ^5.0.0
2054 | peerDependenciesMeta:
2055 | typescript:
2056 | optional: true
2057 | dependencies:
2058 | typescript: 5.6.3
2059 | dev: true
2060 |
2061 | /type-check@0.4.0:
2062 | resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
2063 | engines: {node: '>= 0.8.0'}
2064 | dependencies:
2065 | prelude-ls: 1.2.1
2066 | dev: true
2067 |
2068 | /typescript-eslint@8.11.0(eslint@9.13.0)(typescript@5.6.3):
2069 | resolution: {integrity: sha512-cBRGnW3FSlxaYwU8KfAewxFK5uzeOAp0l2KebIlPDOT5olVi65KDG/yjBooPBG0kGW/HLkoz1c/iuBFehcS3IA==}
2070 | engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2071 | peerDependencies:
2072 | typescript: '*'
2073 | peerDependenciesMeta:
2074 | typescript:
2075 | optional: true
2076 | dependencies:
2077 | '@typescript-eslint/eslint-plugin': 8.11.0(@typescript-eslint/parser@8.11.0)(eslint@9.13.0)(typescript@5.6.3)
2078 | '@typescript-eslint/parser': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
2079 | '@typescript-eslint/utils': 8.11.0(eslint@9.13.0)(typescript@5.6.3)
2080 | typescript: 5.6.3
2081 | transitivePeerDependencies:
2082 | - eslint
2083 | - supports-color
2084 | dev: true
2085 |
2086 | /typescript@5.6.3:
2087 | resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
2088 | engines: {node: '>=14.17'}
2089 | hasBin: true
2090 | dev: true
2091 |
2092 | /update-browserslist-db@1.1.1(browserslist@4.24.2):
2093 | resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==}
2094 | hasBin: true
2095 | peerDependencies:
2096 | browserslist: '>= 4.21.0'
2097 | dependencies:
2098 | browserslist: 4.24.2
2099 | escalade: 3.2.0
2100 | picocolors: 1.1.1
2101 | dev: true
2102 |
2103 | /uri-js@4.4.1:
2104 | resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
2105 | dependencies:
2106 | punycode: 2.3.1
2107 | dev: true
2108 |
2109 | /vite-plugin-glsl@1.3.0(vite@5.4.10):
2110 | resolution: {integrity: sha512-SzEoLet9Bp5VSozjrhUiSc3xX1+u7rCTjXAsq4qWM3u8UjilI76A9ucX/T+CRGQCe25j50GSY+9mKSGUVPET1w==}
2111 | engines: {node: '>= 16.15.1', npm: '>= 8.11.0'}
2112 | peerDependencies:
2113 | vite: ^3.0.0 || ^4.0.0 || ^5.0.0
2114 | dependencies:
2115 | '@rollup/pluginutils': 5.1.3
2116 | vite: 5.4.10
2117 | transitivePeerDependencies:
2118 | - rollup
2119 | dev: true
2120 |
2121 | /vite-tsconfig-paths@5.0.1(typescript@5.6.3)(vite@5.4.10):
2122 | resolution: {integrity: sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==}
2123 | peerDependencies:
2124 | vite: '*'
2125 | peerDependenciesMeta:
2126 | vite:
2127 | optional: true
2128 | dependencies:
2129 | debug: 4.3.7
2130 | globrex: 0.1.2
2131 | tsconfck: 3.1.4(typescript@5.6.3)
2132 | vite: 5.4.10
2133 | transitivePeerDependencies:
2134 | - supports-color
2135 | - typescript
2136 | dev: true
2137 |
2138 | /vite@5.4.10:
2139 | resolution: {integrity: sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==}
2140 | engines: {node: ^18.0.0 || >=20.0.0}
2141 | hasBin: true
2142 | peerDependencies:
2143 | '@types/node': ^18.0.0 || >=20.0.0
2144 | less: '*'
2145 | lightningcss: ^1.21.0
2146 | sass: '*'
2147 | sass-embedded: '*'
2148 | stylus: '*'
2149 | sugarss: '*'
2150 | terser: ^5.4.0
2151 | peerDependenciesMeta:
2152 | '@types/node':
2153 | optional: true
2154 | less:
2155 | optional: true
2156 | lightningcss:
2157 | optional: true
2158 | sass:
2159 | optional: true
2160 | sass-embedded:
2161 | optional: true
2162 | stylus:
2163 | optional: true
2164 | sugarss:
2165 | optional: true
2166 | terser:
2167 | optional: true
2168 | dependencies:
2169 | esbuild: 0.21.5
2170 | postcss: 8.4.47
2171 | rollup: 4.24.0
2172 | optionalDependencies:
2173 | fsevents: 2.3.3
2174 | dev: true
2175 |
2176 | /which@2.0.2:
2177 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
2178 | engines: {node: '>= 8'}
2179 | hasBin: true
2180 | dependencies:
2181 | isexe: 2.0.0
2182 | dev: true
2183 |
2184 | /word-wrap@1.2.5:
2185 | resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
2186 | engines: {node: '>=0.10.0'}
2187 | dev: true
2188 |
2189 | /yallist@3.1.1:
2190 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
2191 | dev: true
2192 |
2193 | /yaml@1.10.2:
2194 | resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
2195 | engines: {node: '>= 6'}
2196 | dev: false
2197 |
2198 | /yocto-queue@0.1.0:
2199 | resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
2200 | engines: {node: '>=10'}
2201 | dev: true
2202 |
2203 | /zustand@5.0.0(@types/react@18.3.12)(react@18.3.1):
2204 | resolution: {integrity: sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==}
2205 | engines: {node: '>=12.20.0'}
2206 | peerDependencies:
2207 | '@types/react': '>=18.0.0'
2208 | immer: '>=9.0.6'
2209 | react: '>=18.0.0'
2210 | use-sync-external-store: '>=1.2.0'
2211 | peerDependenciesMeta:
2212 | '@types/react':
2213 | optional: true
2214 | immer:
2215 | optional: true
2216 | react:
2217 | optional: true
2218 | use-sync-external-store:
2219 | optional: true
2220 | dependencies:
2221 | '@types/react': 18.3.12
2222 | react: 18.3.1
2223 | dev: false
2224 |
--------------------------------------------------------------------------------