diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 2c19cae2d..6cf8f2165 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -20,6 +20,12 @@ From the project root, run the following commands - __Install the project dependencies__ by running `pnpm i` - __Run dev mode__ by running `turbo dev` +### Debugging backend +To debug backend code in Node.js: +- Open two separate terminals and navigate to the `apps/client` and `apps/server` directories. +- In each terminal, run the command `pnpm dev` to start the development servers for both the client and server applications. +- If you need to set breakpoints and inspect the code execution, enable Node.js inspect mode by running `pnpm dev:inspect`. + ## TESTING Generally we have 2 types of tests. diff --git a/apps/client/.stylelintrc b/apps/client/.stylelintrc deleted file mode 100644 index 5a9002904..000000000 --- a/apps/client/.stylelintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": [ - "stylelint-config-standard-scss", - "stylelint-config-prettier" - ] -} diff --git a/apps/client/package.json b/apps/client/package.json index 81db38c6c..d71fd4ab9 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -1,9 +1,9 @@ { "name": "ontime-ui", - "version": "2.0.2", + "version": "2.0.9", "private": true, "dependencies": { - "@chakra-ui/react": "^2.5.5", + "@chakra-ui/react": "^2.7.0", "@dnd-kit/core": "^6.0.8", "@dnd-kit/sortable": "^7.0.2", "@dnd-kit/utilities": "^3.2.1", @@ -14,7 +14,8 @@ "@sentry/tracing": "^7.46.0", "@tanstack/react-query": "^4.28.0", "@tanstack/react-query-devtools": "^4.29.0", - "autosize": "^5.0.2", + "@tanstack/react-table": "^8.9.2", + "autosize": "^6.0.1", "axios": "^1.2.0", "color": "^4.2.3", "csv-stringify": "^6.2.3", @@ -27,7 +28,6 @@ "react-hook-form": "^7.43.5", "react-qr-code": "^2.0.11", "react-router-dom": "^6.3.0", - "react-table": "^7.7.0", "typeface-open-sans": "^1.1.13", "web-vitals": "^3.1.1", "zustand": "^4.3.6" @@ -40,7 +40,6 @@ "build:local": "cross-env NODE_ENV=local vite build", "build:docker": "vite build", "lint": "eslint .", - "stylelint": "npx stylelint \"**/*.scss\"\n", "test": "vitest", "test:pipeline": "vitest run", "cleanup": "rm -rf .turbo && rm -rf node_modules && rm -rf build" @@ -65,7 +64,6 @@ "@testing-library/user-event": "^14.1.1", "@types/color": "^3.0.3", "@types/luxon": "^3.2.0", - "@types/prop-types": "^15.7.5", "@types/react": "^18.0.26", "@types/react-dom": "^18.0.10", "@types/testing-library__jest-dom": "^5.14.5", @@ -84,11 +82,7 @@ "ontime-types": "workspace:*", "ontime-utils": "workspace:*", "prettier": "^2.8.3", - "prop-types": "^15.8.1", "sass": "^1.57.1", - "stylelint": "^14.16.1", - "stylelint-config-prettier": "^9.0.4", - "stylelint-config-standard-scss": "^6.1.0", "typescript": "^4.9.4", "vite": "^4.3.1", "vite-plugin-compression2": "^0.9.0", diff --git a/apps/client/src/App.tsx b/apps/client/src/App.tsx index e2aa429b9..1cb17bfb9 100644 --- a/apps/client/src/App.tsx +++ b/apps/client/src/App.tsx @@ -9,6 +9,7 @@ import { AppContextProvider } from './common/context/AppContext'; import { ContextMenuProvider } from './common/context/ContextMenuContext'; import useElectronEvent from './common/hooks/useElectronEvent'; import { ontimeQueryClient } from './common/queryClient'; +import { socketClientName } from './common/stores/connectionName'; import { connectSocket } from './common/utils/socket'; import theme from './theme/theme'; import { TranslationProvider } from './translation/TranslationProvider'; @@ -18,7 +19,8 @@ import AppRouter from './AppRouter'; // @ts-expect-error no types from font import import('typeface-open-sans'); -connectSocket(); +const preferredClientName = socketClientName.getState().name; +connectSocket(preferredClientName); function App() { const { isElectron, sendToElectron } = useElectronEvent(); diff --git a/apps/client/src/AppRouter.tsx b/apps/client/src/AppRouter.tsx index 10b24a984..694989cc2 100644 --- a/apps/client/src/AppRouter.tsx +++ b/apps/client/src/AppRouter.tsx @@ -5,7 +5,7 @@ import useAliases from './common/hooks-query/useAliases'; import withData from './features/viewers/ViewWrapper'; const Editor = lazy(() => import('./features/editors/ProtectedEditor')); -const Table = lazy(() => import('./features/table/ProtectedTable')); +const Cuesheet = lazy(() => import('./features/cuesheet/ProtectedCuesheet')); const Operator = lazy(() => import('./features/operator/Operator')); const TimerView = lazy(() => import('./features/viewers/timer/Timer')); @@ -80,9 +80,9 @@ export default function AppRouter() { {/*/!* Protected Routes *!/*/} } /> - } /> - } /> - } /> + } /> + } /> + } /> {/*/!* Protected Routes - Elements *!/*/} ) { return axios.put(rundownURL, data); } -/** - * @description HTTP request to modify event - * @return {Promise} - */ -export async function requestPatchEvent(data: OntimeRundownEntry) { - return axios.patch(rundownURL, data); -} - export type ReorderEntry = { eventId: string; from: number; diff --git a/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx b/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx index 5cbb1e595..dcd522a08 100644 --- a/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx +++ b/apps/client/src/common/components/error-boundary/ErrorBoundary.jsx @@ -3,6 +3,9 @@ import React from 'react'; // skipcq: JS-C1003 - sentry does not expose itself as an ES Module. import * as Sentry from '@sentry/react'; +import { runtime } from '@/common/stores/runtime'; +import { hasConnected, reconnectAttempts, shouldReconnect } from '@/common/utils/socket'; + import style from './ErrorBoundary.module.scss'; class ErrorBoundary extends React.Component { @@ -25,7 +28,9 @@ class ErrorBoundary extends React.Component { }); Sentry.withScope((scope) => { - scope.setExtras(error); + scope.setExtras('error', error); + scope.setExtras('store', runtime.getState()); + scope.setExtras('hasSocket', { hasConnected, shouldReconnect, reconnectAttempts }); const eventId = Sentry.captureException(error); this.setState({ eventId, info }); }); diff --git a/apps/client/src/common/components/input/auto-text-area/AutoTextArea.tsx b/apps/client/src/common/components/input/auto-text-area/AutoTextArea.tsx index 2ed97a970..5150b3e0d 100644 --- a/apps/client/src/common/components/input/auto-text-area/AutoTextArea.tsx +++ b/apps/client/src/common/components/input/auto-text-area/AutoTextArea.tsx @@ -3,12 +3,7 @@ import { Textarea, TextareaProps } from '@chakra-ui/react'; // @ts-expect-error no types from library import autosize from 'autosize/dist/autosize'; -interface AutoTextAreaProps extends TextareaProps { - isDark?: boolean; -} - -export const AutoTextArea = (props: AutoTextAreaProps) => { - const { isDark, ...rest } = props; +export const AutoTextArea = (props: TextareaProps) => { const ref = useRef(null); useEffect(() => { @@ -26,8 +21,8 @@ export const AutoTextArea = (props: AutoTextAreaProps) => { resize='none' ref={ref} transition='height none' - variant={isDark ? 'ontime-filled' : 'ontime-filled-on-light'} - {...rest} + variant='ontime-transparent' + {...props} /> ); }; diff --git a/apps/client/src/common/components/navigation-menu/NavigationMenu.tsx b/apps/client/src/common/components/navigation-menu/NavigationMenu.tsx index 7195e668e..23dfbcf79 100644 --- a/apps/client/src/common/components/navigation-menu/NavigationMenu.tsx +++ b/apps/client/src/common/components/navigation-menu/NavigationMenu.tsx @@ -1,6 +1,7 @@ -import { KeyboardEvent, useEffect, useRef, useState } from 'react'; +import { KeyboardEvent, memo, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { Link, useLocation, useSearchParams } from 'react-router-dom'; +import { useDisclosure } from '@chakra-ui/react'; import { IoApps } from '@react-icons/all-files/io5/IoApps'; import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp'; import { IoContract } from '@react-icons/all-files/io5/IoContract'; @@ -14,9 +15,11 @@ import useFullscreen from '../../hooks/useFullscreen'; import { useKeyDown } from '../../hooks/useKeyDown'; import { useViewOptionsStore } from '../../stores/viewOptions'; +import RenameClientModal from './rename-client-modal/RenameClientModal'; + import style from './NavigationMenu.module.scss'; -export default function NavigationMenu() { +function NavigationMenu() { const location = useLocation(); const { isFullScreen, toggleFullScreen } = useFullscreen(); @@ -27,8 +30,10 @@ export default function NavigationMenu() { const menuRef = useRef(null); useClickOutside(menuRef, () => setShowMenu(false)); + const { isOpen, onOpen, onClose } = useDisclosure(); + const toggleMenu = () => setShowMenu((prev) => !prev); - useKeyDown(toggleMenu, ' ', { isDisabled: searchParams.get('edit') === 'true' }); + useKeyDown(toggleMenu, ' ', { isDisabled: searchParams.get('edit') === 'true' || isOpen }); useEffect(() => { let fadeOut: NodeJS.Timeout | null = null; @@ -51,6 +56,7 @@ export default function NavigationMenu() { const isKeyEnter = (event: KeyboardEvent) => event.key === 'Enter'; const handleFullscreen = () => toggleFullScreen(); const handleMirror = () => toggleMirror(); + const showEditFormDrawer = () => { searchParams.append('edit', 'true'); setSearchParams(searchParams); @@ -58,6 +64,7 @@ export default function NavigationMenu() { return createPortal(
+ + Cuesheet + + +
{navigatorConstants.map((route) => ( void; +} + +export default function RenameClientModal({ isOpen, onClose }: RenameClientModalProps) { + const { name: clientName, persistName } = useSocketClientName(); + const [newName, setNewName] = useState(clientName); + + useEffect(() => { + setNewName(clientName); + }, [isOpen, clientName]); + + const handleRename = async () => { + if (newName) { + await setClientName(newName); + persistName(newName); + onClose(); + } + }; + + return ( + + + + Rename client + + + setNewName(e.target.value)} + variant='ontime-filled-on-light' + /> + + + + + ); +} diff --git a/apps/client/src/common/components/view-params-editor/ParamInput.tsx b/apps/client/src/common/components/view-params-editor/ParamInput.tsx index 73af5dab6..54fb5a183 100644 --- a/apps/client/src/common/components/view-params-editor/ParamInput.tsx +++ b/apps/client/src/common/components/view-params-editor/ParamInput.tsx @@ -15,12 +15,12 @@ export default function ParamInput({ paramField }: EditFormInputProps) { if (type === 'option') { const optionFromParams = searchParams.get(id); - const defaultOptionValue = paramField.values.find((value) => value === optionFromParams); + const defaultOptionValue = optionFromParams || undefined; return ( {column.Header} - - ))} - -
- - - - -
- - ); -} - -TableSettings.propTypes = { - columns: PropTypes.array, - handleResetResizing: PropTypes.func.isRequired, - handleResetReordering: PropTypes.func.isRequired, - handleResetToggles: PropTypes.func.isRequired, - handleClearToggles: PropTypes.func.isRequired, -}; diff --git a/apps/client/src/features/table/tableRows/BlockRow.jsx b/apps/client/src/features/table/tableRows/BlockRow.jsx deleted file mode 100644 index 1bdb089ac..000000000 --- a/apps/client/src/features/table/tableRows/BlockRow.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import PropTypes from 'prop-types'; - -import style from '../Table.module.scss'; - -export default function BlockRow(props) { - const { row } = props; - return ( - - {row.original?.title || 'Block'} - - ); -} - -BlockRow.propTypes = { - row: PropTypes.object.isRequired, -}; diff --git a/apps/client/src/features/table/tableRows/DelayRow.jsx b/apps/client/src/features/table/tableRows/DelayRow.jsx deleted file mode 100644 index fb24298dd..000000000 --- a/apps/client/src/features/table/tableRows/DelayRow.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import PropTypes from 'prop-types'; - -import { millisToDelayString } from '../../../common/utils/dateConfig'; - -import style from '../Table.module.scss'; - -export default function DelayRow(props) { - const { row } = props; - const delayVal = row.original.duration; - const delayTime = delayVal !== 0 ? millisToDelayString(delayVal) : null; - - return ( - - {delayTime} - - ); -} - -DelayRow.propTypes = { - row: PropTypes.object.isRequired, -}; diff --git a/apps/client/src/features/table/tableRows/EventRow.jsx b/apps/client/src/features/table/tableRows/EventRow.jsx deleted file mode 100644 index 0cb1079ac..000000000 --- a/apps/client/src/features/table/tableRows/EventRow.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import PropTypes from 'prop-types'; - -import { getAccessibleColour } from '../../../common/utils/styleUtils'; - -import style from '../Table.module.scss'; - -export default function EventRow(props) { - const { row, index, selectedId, delay } = props; - const selected = row.original.id === selectedId; - - const colours = row.original.colour - ? getAccessibleColour(row.original.colour) - : {}; - - return ( - - {index} - {row.cells.map((cell) => { - const { key, style, ...restCellProps } = cell.getCellProps(); - const dynamicStyles = { ...style, ...colours }; - - - // Inject delay value if exits - if (delay !== 0 && delay != null) { - const col = cell.column.Header; - if (col === 'End' || col === 'Start') { - cell.delayed = cell.value + delay; - } - } - - return ( - - {cell.render('Cell')} - - ); - })} - - ); -} - -EventRow.propTypes = { - row: PropTypes.object.isRequired, - index: PropTypes.number.isRequired, - selectedId: PropTypes.string, - delay: PropTypes.number, -}; diff --git a/apps/client/src/features/viewers/backstage/Backstage.scss b/apps/client/src/features/viewers/backstage/Backstage.scss index 5fd1ae1ec..1144ab9a7 100644 --- a/apps/client/src/features/viewers/backstage/Backstage.scss +++ b/apps/client/src/features/viewers/backstage/Backstage.scss @@ -1,4 +1,5 @@ @use '../../../theme/viewerDefs' as *; +@use '../../../theme/v2Styles' as *; .backstage { margin: 0; @@ -86,6 +87,10 @@ background-color: var(--card-background-color-override, $viewer-card-bg-color); padding: 16px 24px; border-radius: 8px; + + &.blink { + animation: blink 0.5s ease-in-out 3; + } } .timer-group { @@ -119,7 +124,7 @@ grid-area: schedule; overflow: hidden; height: 100%; - margin-left: clamp(16px, 5vw, 64px);; + margin-left: clamp(16px, 5vw, 64px); } .schedule-nav-container { @@ -143,9 +148,20 @@ } .qr { - margin-left: clamp(16px, 5vw, 64px);; + margin-left: clamp(16px, 5vw, 64px); padding: 4px; background-color: white; } } } + +/* =================== AMIMATION ===================*/ + +@keyframes blink { + 0% { + background-color: var(--card-background-color-blink-override, $playback-start); + } + 20% { + background-color: var(--card-background-color-override, $viewer-card-bg-color); + } +} diff --git a/apps/client/src/features/viewers/backstage/Backstage.tsx b/apps/client/src/features/viewers/backstage/Backstage.tsx index d2846070b..d6901c466 100644 --- a/apps/client/src/features/viewers/backstage/Backstage.tsx +++ b/apps/client/src/features/viewers/backstage/Backstage.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import QRCode from 'react-qr-code'; import { AnimatePresence, motion } from 'framer-motion'; import { EventData, Message, OntimeEvent, ViewSettings } from 'ontime-types'; @@ -43,12 +43,24 @@ export default function Backstage(props: BackstageProps) { const { isMirrored, publ, title, time, backstageEvents, selectedId, general, viewSettings } = props; const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL); const { getLocalizedString } = useTranslation(); + const [blinkClass, setBlinkClass] = useState(false); // Set window title useEffect(() => { document.title = 'ontime - Backstage Screen'; }, []); + // blink on change + useEffect(() => { + setBlinkClass(false); + + const timer = setTimeout(() => { + setBlinkClass(true); + }, 10); + + return () => clearTimeout(timer); + }, [selectedId]); + // defer rendering until we load stylesheets if (!shouldRender) { return null; @@ -57,7 +69,9 @@ export default function Backstage(props: BackstageProps) { const clock = formatTime(time.clock, formatOptions); const startedAt = formatTime(time.startedAt, formatOptions); const isNegative = (time.current ?? 0) < 0; - const expectedFinish = isNegative ? 'In overtime' : formatTime(time.expectedFinish, formatOptions); + const expectedFinish = isNegative + ? getLocalizedString('countdown.overtime') + : formatTime(time.expectedFinish, formatOptions); const qrSize = Math.max(window.innerWidth / 15, 128); const filteredEvents = getEventsWithDelay(backstageEvents); @@ -99,7 +113,7 @@ export default function Backstage(props: BackstageProps) { {title.showNow && ( ([]); const activeIndicators = [...Array(12).keys()]; const secondsIndicators = [...Array(60).keys()]; @@ -59,16 +67,16 @@ export default function StudioClock(props) { } const delayed = getEventsWithDelay(backstageEvents); - const events = delayed.filter((e) => e.type === 'event'); - const trimmed = trimRundown(events, selectedId, MAX_TITLES); - const formatted = formatEventList(trimmed, selectedId, nextId, { + const trimmed = trimRundown(delayed, selectedId || '', MAX_TITLES); + + const formatted = formatEventList(trimmed, selectedId || '', nextId || '', { showEnd: false, }); setSchedule(formatted); }, [backstageEvents, nextId, selectedId]); const clock = formatTime(time.clock, formatOptions); - const [, , secondsNow] = millisToString(time.clock).split(':'); + const secondsNow = secondsInMillis(time.clock); const isNegative = (time.current ?? 0) < 0; return ( diff --git a/apps/client/src/index.scss b/apps/client/src/index.scss index 66aab9aa0..c7299401e 100644 --- a/apps/client/src/index.scss +++ b/apps/client/src/index.scss @@ -30,7 +30,6 @@ html, } @media (min-width: 1450px) and (max-width: 1666px) { - body, html, .App { diff --git a/apps/client/src/index.tsx b/apps/client/src/index.tsx index 8a8271d53..a203885e2 100644 --- a/apps/client/src/index.tsx +++ b/apps/client/src/index.tsx @@ -18,6 +18,8 @@ Sentry.init({ tracesSampleRate: 1.0, release: ONTIME_VERSION, enabled: import.meta.env.PROD, + ignoreErrors: ['top.GLOBALS', 'Unable to preload CSS'], + denyUrls: [/extensions\//i, /^chrome:\/\//i, /^chrome-extension:\/\//i], }); root.render( diff --git a/apps/client/src/theme/_main.scss b/apps/client/src/theme/_main.scss deleted file mode 100644 index ab5f09f7c..000000000 --- a/apps/client/src/theme/_main.scss +++ /dev/null @@ -1,132 +0,0 @@ -@use "./ontimeColours" as *; - -$transition-time-action: 0.1s; -$transition-time-feedback: 0.3s; - -//////////////////////////////////// general app colours - -$bg-black-gradient: #202020; -$bg-black: #121212; -$bg-black-100: #070707; -$bg-black-200: #1a1a1a; // container borders -$bg-black-300: #1f1f1f; // container text -$bg-gray-1100: #232323; // container borders -$bg-gray-1050: #242424; // container borders -$bg-gray-1000: #262626; // container borders -$bg-gray-950: #292929; -$bg-gray-900: #303030; -$bg-gray-800: #404040; -$bg-gray-700: #505050; -$bg-gray-500: #666666; -$bg-gray-100: #c0c0c0; // borders and whatnot - -$bg-overlay: rgba(0, 0, 0, 0.85); - -// $ontime-accent: #4bffab); -$ontime-accent: #58A151; -$ontime-accent-text: mix($bg-black, $ontime-accent, 10%); -$ontime-pink: #ff7597; -$ontime-pink-variant: #ff6969; -$ontime-roll: #0274B6; -$ontime-delay: #F57C13; -$action-blue: #3182ce; -$ontime-paused: #c05621; -$opacity-disabled: 0.4; -$ontime-red: #E4281E; - -//rgba(255, 255, 255, 0.39); - $bg-gray-700 -//rgba(255, 255, 255, 0.13); - $bg-gray-900 -//rgba(255, 255, 255, 0.05); - $bg-gray-1000 -//rgba(255, 255, 255, 0.07) - $bg-gray-1000 -// text input bg - -// was rgba(255, 255, 255, 0.03) -// container level 1 - $bg-gray-1000 -// container level 2 - $bg-gray-1100 -// container level 2 border - rgba(0, 0, 0, 0.05) -// indent in level 2 - $bg-black-300 -// outdent in level2 - $bg-gray-950 -//////////////////////////////////// editor - -$notes-color: #f6f6f6; - -$text-white: #fffffa; -$text-gray-disabled: #505050; -$label-gray: #aaa; -$header-gray: $label-gray; -$clocks: #ddd; -$bg-gray: #f4f4f8; -$text-delay: #F57C13; - -$light-bg: #2b6cb0; -$light-bg-transparent: #2b6cb055; -$light-text: #2b6cb022; - -$info-gray: #aaa; -$info-gray-hover: #ddd; -$warning-orange: #dd6b20; -$error-red: #e53e3e; - -//////////////////////////////////// viewers -$title-white: #fffd; - -//////////////////////////////////// block elements -$bg-container-over: #0b1521; -$bg-container-over-l1: #132337; -$bg-container-l1: #202020; -$bg-container-l2: #232323; -$bg-container-l3: #2b2b2b; -$border-l1: 1px solid $bg-gray-1000; -$border-l3: 1px solid $bg-gray-900; - -$block-delay-color: #E2720D; -$delay-text: #d69e2e; -$block-delay-border: #d69e2e55; -$block-block-color: #7347AD; -$block-border: 1px solid $bg-gray-1100; - -//////////////////////////////////// utils - -@mixin ellipsis { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -//////////////////////////////////// custom inputs -$input-bg: rgba(255, 255, 255, 0.03); -$input-hover-bg: rgba(255, 255, 255, 0.13); -$input-bg-delayed: rgba(214, 158, 46, 0.07); -$input-hover-bg-delayed: rgba(214, 158, 46, 0.17); -$input-border: 1px solid transparent; -$input-delayed-border: 1px solid $block-delay-border; - -//////////////////////////////////// general app element overriders - -// no decoration on lists -ul { - list-style-type: none; -} - -// no resizing on text areas -textarea { - resize: none !important; -} - -// Define style for a link -a:hover { - color: $ontime-pink; -} - -// horizontal separator -.hSeparator { - width: 100%; - border-bottom: 1px solid $light-bg; - margin: 1em auto; - display: flex; - align-items: center; -} - -// inline vertical separator -.vSpan { - margin: 0 0.5em; -} diff --git a/apps/client/src/theme/_v2Styles.scss b/apps/client/src/theme/_v2Styles.scss index 74b0c7771..c299fb8e8 100644 --- a/apps/client/src/theme/_v2Styles.scss +++ b/apps/client/src/theme/_v2Styles.scss @@ -24,7 +24,7 @@ $ontime-delay-text: #E69056; $ontime-paused: #c05621; $ontime-stop: #E4281E; $playback-negative: $red-500; -$active-indicator: #899948; +$active-indicator: #8bb33d; $text-black: $gray-1350; // interface panels @@ -51,8 +51,8 @@ $ontime-font-family: "Open Sans", "Segoe UI", sans-serif; $label-gray: $gray-400; $secondary-text-gray: $gray-400; $section-white: $ui-white; -$inner-section-text-size: 14px; -$text-body-size: 15px; +$inner-section-text-size: calc(1rem - 2px); +$text-body-size: calc(1rem - 1px); .blink { animation: blink $blinking-time linear infinite; diff --git a/apps/client/src/theme/ontimeTextInputs.ts b/apps/client/src/theme/ontimeTextInputs.ts index e185e5a5a..c135d589e 100644 --- a/apps/client/src/theme/ontimeTextInputs.ts +++ b/apps/client/src/theme/ontimeTextInputs.ts @@ -36,6 +36,13 @@ export const ontimeInputFilledOnLight = { export const ontimeTextAreaFilled = { ...commonStyles, }; +export const ontimeTextAreaTransparent = { + ...commonStyles, + backgroundColor: 'transparent', + _hover: { + backgroundColor: 'rgba(255, 255, 255, 0.10)', // $white-10 + }, +}; export const ontimeTextAreaFilledOnLight = { borderRadius: '3px', diff --git a/apps/client/src/theme/theme.ts b/apps/client/src/theme/theme.ts index 44d2dcfe3..d1b89a58b 100644 --- a/apps/client/src/theme/theme.ts +++ b/apps/client/src/theme/theme.ts @@ -23,6 +23,7 @@ import { ontimeInputFilledOnLight, ontimeTextAreaFilled, ontimeTextAreaFilledOnLight, + ontimeTextAreaTransparent, } from './ontimeTextInputs'; import { ontimeTooltip } from './ontimeTooltip'; @@ -96,6 +97,7 @@ const theme = extendTheme({ }, variants: { 'ontime-filled': { ...ontimeTextAreaFilled }, + 'ontime-transparent': { ...ontimeTextAreaTransparent }, 'ontime-filled-on-light': { ...ontimeTextAreaFilledOnLight }, }, }, diff --git a/apps/client/src/translation/Translation.types.ts b/apps/client/src/translation/Translation.types.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/client/src/translation/languages/de.ts b/apps/client/src/translation/languages/de.ts index 65a1c3fee..751f2d6d1 100644 --- a/apps/client/src/translation/languages/de.ts +++ b/apps/client/src/translation/languages/de.ts @@ -1,4 +1,4 @@ -import { TranslationObject } from '../Translation.types'; +import { TranslationObject } from './en'; export const langDe: TranslationObject = { 'common.end_time': 'Endzeit', @@ -15,4 +15,5 @@ export const langDe: TranslationObject = { 'countdown.select_event': 'Wählen Sie eine Veranstaltung aus, um sie zu verfolgen', 'countdown.to_start': 'Zeit bis zum Start', 'countdown.waiting': 'Warten auf den Veranstaltungsbeginn', + 'countdown.overtime': 'überfällig', }; diff --git a/apps/client/src/translation/languages/en.ts b/apps/client/src/translation/languages/en.ts index 81f9a0ddf..e6ec906cc 100644 --- a/apps/client/src/translation/languages/en.ts +++ b/apps/client/src/translation/languages/en.ts @@ -13,4 +13,7 @@ export const langEn = { 'countdown.select_event': 'Select an event to follow', 'countdown.to_start': 'Time to start', 'countdown.waiting': 'Waiting for event start', + 'countdown.overtime': 'in overtime', }; + +export type TranslationObject = Record; diff --git a/apps/client/src/translation/languages/es.ts b/apps/client/src/translation/languages/es.ts index 3216855e8..c931c796a 100644 --- a/apps/client/src/translation/languages/es.ts +++ b/apps/client/src/translation/languages/es.ts @@ -1,4 +1,4 @@ -import { TranslationObject } from '../Translation.types'; +import { TranslationObject } from './en'; export const langEs: TranslationObject = { 'common.end_time': 'Hora de finalización', @@ -9,10 +9,11 @@ export const langEs: TranslationObject = { 'common.start_time': 'Hora de inicio', 'common.stage_timer': 'Temporizador de presentador', 'common.started_at': 'Iniciado en', - 'common.time_now': 'Hora actual', + 'common.time_now': 'Ahora', 'countdown.ended': 'Evento finalizado a las', 'countdown.running': 'Evento en curso', 'countdown.select_event': 'Seleccionar un evento para seguir', 'countdown.to_start': 'Tiempo para comenzar', 'countdown.waiting': 'Esperando el inicio del evento', + 'countdown.overtime': 'en tiempo extra', }; diff --git a/apps/client/src/translation/languages/no.ts b/apps/client/src/translation/languages/no.ts index 2d2795d64..b61eb2236 100644 --- a/apps/client/src/translation/languages/no.ts +++ b/apps/client/src/translation/languages/no.ts @@ -1,4 +1,4 @@ -import { TranslationObject } from '../Translation.types'; +import { TranslationObject } from './en'; export const langNo: TranslationObject = { 'common.end_time': 'Sluttid', @@ -9,10 +9,11 @@ export const langNo: TranslationObject = { 'common.start_time': 'Starttid', 'common.stage_timer': 'Scenetimer', 'common.started_at': 'Startet', - 'common.time_now': 'Tid nå', + 'common.time_now': 'Klokken nå', 'countdown.ended': 'Hendelse avsluttet', 'countdown.running': 'Hendelse pågår', 'countdown.select_event': 'Velg en hendelse å følge', 'countdown.to_start': 'Tid til start', 'countdown.waiting': 'Venter på start', + 'countdown.overtime': 'i overtiden', }; diff --git a/apps/client/src/translation/languages/pt.ts b/apps/client/src/translation/languages/pt.ts index aceeb2963..4eb1108af 100644 --- a/apps/client/src/translation/languages/pt.ts +++ b/apps/client/src/translation/languages/pt.ts @@ -1,4 +1,4 @@ -import { TranslationObject } from '../Translation.types'; +import { TranslationObject } from './en'; export const langPt: TranslationObject = { 'common.end_time': 'Hora de término', @@ -15,4 +15,5 @@ export const langPt: TranslationObject = { 'countdown.select_event': 'Selecione um evento para acompanhar', 'countdown.to_start': 'Tempo para iniciar', 'countdown.waiting': 'Aguardando o início do evento', + 'countdown.overtime': 'em tempo extra', }; diff --git a/apps/client/src/translation/languages/sv.ts b/apps/client/src/translation/languages/sv.ts index 5ad271c69..98211a237 100644 --- a/apps/client/src/translation/languages/sv.ts +++ b/apps/client/src/translation/languages/sv.ts @@ -1,4 +1,4 @@ -import { TranslationObject } from '../Translation.types'; +import { TranslationObject } from './en'; export const langSv: TranslationObject = { 'common.end_time': 'Sluttid', @@ -9,10 +9,11 @@ export const langSv: TranslationObject = { 'common.start_time': 'Starttid', 'common.stage_timer': 'Timer för scenen', 'common.started_at': 'Började vid', - 'common.time_now': 'Tid nu', + 'common.time_now': 'Klockan nu', 'countdown.ended': 'Evenemanget avslutades vid', 'countdown.running': 'Evenemang pågår', 'countdown.select_event': 'Välj ett evenemang att följa', 'countdown.to_start': 'Tid till start', 'countdown.waiting': '"Väntar på att evenemanget ska starta', + 'countdown.overtime': 'i övertid', }; diff --git a/apps/electron/package.json b/apps/electron/package.json index 906e0b19b..1edf35f45 100644 --- a/apps/electron/package.json +++ b/apps/electron/package.json @@ -1,6 +1,6 @@ { "name": "ontime", - "version": "2.0.2", + "version": "2.0.9", "author": "Carlos Valente", "description": "Time keeping for live events", "repository": "https://github.com/cpvalente/ontime", diff --git a/apps/server/package.json b/apps/server/package.json index 242ee3921..29503f694 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -2,7 +2,7 @@ "name": "ontime-server", "type": "module", "main": "src/index.ts", - "version": "2.0.2", + "version": "2.0.9", "exports": "./src/index.js", "dependencies": { "body-parser": "^1.20.0", @@ -44,6 +44,7 @@ "setdb": "shx cp ../../demo-db/db.json src/preloaded-db/db.json", "postinstall": "pnpm addversion && pnpm setdb", "dev": "cross-env NODE_ENV=development nodemon --exec \"ts-node-esm\" ./src/index.ts", + "dev:inspect": "cross-env NODE_ENV=development nodemon --exec \"node --inspect --loader ts-node/esm\" ./src/index.ts", "dev:test": "cross-env IS_TEST=true nodemon --exec \"ts-node-esm\" ./src/index.ts", "prebuild": "pnpm setdb", "build": "pnpm prebuild && esbuild src/app.ts --log-level=error --platform=node --format=cjs --bundle --minify --outfile=dist/index.cjs", diff --git a/apps/server/src/adapters/OscAdapter.ts b/apps/server/src/adapters/OscAdapter.ts index 9a61dfbbe..d1a3a3ead 100644 --- a/apps/server/src/adapters/OscAdapter.ts +++ b/apps/server/src/adapters/OscAdapter.ts @@ -1,5 +1,6 @@ +import { LogOrigin, OSCSettings } from 'ontime-types'; + import { Server } from 'node-osc'; -import { OSCSettings } from 'ontime-types'; import { IAdapter } from './IAdapter.js'; import { dispatchFromAdapter } from '../controllers/integrationController.js'; @@ -25,13 +26,13 @@ export class OscServer implements IAdapter { // get first part before (ontime) if (address !== 'ontime') { - logger.error('RX', `OSC IN: OSC messages to ontime must start with /ontime/, received: ${msg}`); + logger.error(LogOrigin.Rx, `OSC IN: OSC messages to ontime must start with /ontime/, received: ${msg}`); return; } // get second part (command) if (!path) { - logger.error('RX', 'OSC IN: No path found'); + logger.error(LogOrigin.Rx, 'OSC IN: No path found'); return; } @@ -42,7 +43,7 @@ export class OscServer implements IAdapter { this.osc.emit(topic, payload); } } catch (error) { - logger.error('RX', `OSC IN: ${error}`); + logger.error(LogOrigin.Rx, `OSC IN: ${error}`); } }); } diff --git a/apps/server/src/adapters/WebsocketAdapter.ts b/apps/server/src/adapters/WebsocketAdapter.ts index d5fe7d000..b5668c784 100644 --- a/apps/server/src/adapters/WebsocketAdapter.ts +++ b/apps/server/src/adapters/WebsocketAdapter.ts @@ -14,6 +14,8 @@ * Payload: adds necessary payload for the request to be completed */ +import { LogOrigin } from 'ontime-types'; + import { WebSocket, WebSocketServer } from 'ws'; import getRandomName from '../utils/getRandomName.js'; @@ -45,9 +47,9 @@ export class SocketServer implements IAdapter { this.wss = new WebSocketServer({ path: '/ws', server }); this.wss.on('connection', (ws) => { - const clientId = getRandomName(); + let clientId = getRandomName(); this.clientIds.add(clientId); - logger.info('RX', `${this.wss.clients.size} Connections with new: ${clientId}`); + logger.info(LogOrigin.Client, `${this.wss.clients.size} Connections with new: ${clientId}`); // send store payload on connect ws.send( @@ -57,10 +59,17 @@ export class SocketServer implements IAdapter { }), ); + ws.send( + JSON.stringify({ + type: 'client-name', + payload: clientId, + }), + ); + ws.on('error', console.error); ws.on('close', () => { - logger.info('RX', `${this.wss.clients.size} Connections with disconnected: ${clientId}`); + logger.info(LogOrigin.Client, `${this.wss.clients.size} Connections with disconnected: ${clientId}`); this.clientIds.delete(clientId); }); @@ -69,20 +78,37 @@ export class SocketServer implements IAdapter { ws.close(); } - // TODO: protocol specific stuff should be handled here - // eg: rename-client - // socket.on('rename-client', (newName) => { - // if (newName) { - // const previousName = this._clientNames[socket.id]; - // this._clientNames[socket.id] = newName; - // this.info('CLIENT', `Client ${previousName} renamed to ${newName}`); - // } - // }); - try { const message = JSON.parse(data); const { type, payload } = message; + if (type === 'get-client-name') { + ws.send( + JSON.stringify({ + type: 'client-name', + payload: clientId, + }), + ); + return; + } + + if (type === 'set-client-name') { + if (payload) { + const previousName = clientId; + clientId = payload; + this.clientIds.delete(previousName); + this.clientIds.add(clientId); + logger.info(LogOrigin.Client, `Client ${previousName} renamed to ${clientId}`); + } + ws.send( + JSON.stringify({ + type: 'client-name', + payload: clientId, + }), + ); + return; + } + if (type === 'hello') { ws.send('hi'); return; @@ -95,6 +121,7 @@ export class SocketServer implements IAdapter { return; } + // Protocol specific stuff handled above try { const reply = dispatchFromAdapter(type, payload, 'ws'); if (reply) { @@ -102,7 +129,7 @@ export class SocketServer implements IAdapter { ws.send(topic, payload); } } catch (error) { - logger.error('RX', `WS IN: ${error}`); + logger.error(LogOrigin.Rx, `WS IN: ${error}`); } } catch (_) { // we ignore unknown diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 86a639750..f27f49e54 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -9,7 +9,7 @@ import { join, resolve } from 'path'; import { currentDirectory, environment, externalsStartDirectory, isProduction, resolvedPath } from './setup.js'; import { ONTIME_VERSION } from './ONTIME_VERSION.js'; -import { OSCSettings } from 'ontime-types'; +import { LogOrigin, OSCSettings } from 'ontime-types'; // Import Routes import { router as rundownRouter } from './routes/rundownRouter.js'; @@ -159,7 +159,7 @@ export const startOSCServer = async (overrideConfig = null) => { const { osc } = DataProvider.getData(); if (!osc.enabledIn) { - logger.info('RX', 'OSC Input Disabled'); + logger.info(LogOrigin.Rx, 'OSC Input Disabled'); return; } @@ -170,7 +170,7 @@ export const startOSCServer = async (overrideConfig = null) => { }; // Start OSC Server - logger.info('RX', `Starting OSC Server on port: ${oscSettings.portIn}`); + logger.info(LogOrigin.Rx, `Starting OSC Server on port: ${oscSettings.portIn}`); oscServer = new OscServer(oscSettings); }; @@ -187,7 +187,7 @@ export const startIntegrations = async (config?: { osc: OSCSettings }) => { } const { success, message } = oscIntegration.init(osc); - logger.info('RX', message); + logger.info(LogOrigin.Rx, message); if (success) { integrationService.register(oscIntegration); @@ -214,12 +214,12 @@ export const shutdown = async (exitCode = 0) => { process.on('exit', (code) => console.log(`Ontime exited with code: ${code}`)); process.on('unhandledRejection', async (error) => { - logger.error('SERVER', `Error: unhandled rejection ${error}`); + logger.error(LogOrigin.Server, `Error: unhandled rejection ${error}`); await shutdown(1); }); process.on('uncaughtException', async (error) => { - logger.error('SERVER', `Error: uncaught exception ${error}`); + logger.error(LogOrigin.Server, `Error: uncaught exception ${error}`); await shutdown(1); }); diff --git a/apps/server/src/classes/data-provider/DataProvider.ts b/apps/server/src/classes/data-provider/DataProvider.ts index b727d8d81..66f705ac2 100644 --- a/apps/server/src/classes/data-provider/DataProvider.ts +++ b/apps/server/src/classes/data-provider/DataProvider.ts @@ -2,7 +2,7 @@ * Class Event Provider is a mediator for handling the local db * and adds logic specific to ontime data */ -import { EventData, SupportedEvent, ViewSettings } from 'ontime-types'; +import { EventData, ViewSettings } from 'ontime-types'; import { data, db } from '../../modules/loadDb.js'; import { safeMerge } from './DataProvider.utils.js'; @@ -27,31 +27,14 @@ export class DataProvider { await this.persist(); } + static getIndexOf(eventId) { + return data.rundown.findIndex((e) => e.id === eventId); + } + static getEventById(eventId) { return data.rundown.find((e) => e.id === eventId); } - static async updateEventById(eventId, newData) { - const eventIndex = data.rundown.findIndex((e) => e.id === eventId); - const persistedEvent = data.rundown[eventIndex]; - const newEvent = { ...persistedEvent, ...newData }; - if (newEvent.type === SupportedEvent.Event) { - newEvent.revision++; - } - data.rundown[eventIndex] = newEvent; - await this.persist(); - return data.rundown[eventIndex]; - } - - static async deleteEvent(eventId) { - const eventIndex = data.rundown.findIndex((e) => e.id === eventId); - - if (eventIndex !== -1) { - data.rundown.splice(eventIndex, 1); - await this.persist(); - } - } - static getRundownLength() { return data.rundown.length; } @@ -62,53 +45,6 @@ export class DataProvider { await db.write(); } - /** - * Insets an event after a given index - * @param entry - * @param index - * @return {Promise} - */ - static async insertEventAt(entry, index) { - // get events - const events = DataProvider.getRundown(); - const count = events.length; - const order = entry.order; - - // Remove order field from object - delete entry.order; - - // Insert at beginning - if (order === 0) { - events.unshift(entry); - } - - // insert at end - else if (order >= count) { - events.push(entry); - } - - // insert in the middle - else { - events.splice(index, 0, entry); - } - - // save events - await DataProvider.setRundown(events); - } - - /** - * @description Inserts an entry after an element with given ID - * @param entry - * @param id - * @return {Promise} - */ - static async insertEventAfterId(entry, id) { - const index = [...data.rundown].findIndex((event) => event.id === id); - // eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars -- we are just getting rid of after parameter - const { after, ...sanitisedEvent } = entry; - await DataProvider.insertEventAt(sanitisedEvent, index + 1); - } - static getSettings() { return data.settings; } diff --git a/apps/server/src/classes/event-loader/EventLoader.ts b/apps/server/src/classes/event-loader/EventLoader.ts index 0074bb429..e2821d443 100644 --- a/apps/server/src/classes/event-loader/EventLoader.ts +++ b/apps/server/src/classes/event-loader/EventLoader.ts @@ -1,4 +1,4 @@ -import { Loaded, OntimeEvent, TitleBlock } from 'ontime-types'; +import { Loaded, OntimeEvent, SupportedEvent, TitleBlock } from 'ontime-types'; import { DataProvider } from '../data-provider/DataProvider.js'; import { getRollTimers } from '../../services/rollUtils.js'; @@ -34,8 +34,7 @@ export class EventLoader { * @return {array} */ static getTimedEvents(): OntimeEvent[] { - // return mockLoaderData.filter((event) => event.type === 'event'); - return DataProvider.getRundown().filter((event) => event.type === 'event'); + return DataProvider.getRundown().filter((event) => event.type === SupportedEvent.Event) as OntimeEvent[]; } /** @@ -43,8 +42,9 @@ export class EventLoader { * @return {array} */ static getPlayableEvents(): OntimeEvent[] { - // return mockLoaderData.filter((event) => event.type === 'event' && !event.skip); - return DataProvider.getRundown().filter((event) => event.type === 'event' && !event.skip); + return DataProvider.getRundown().filter( + (event) => event.type === SupportedEvent.Event && !event.skip, + ) as OntimeEvent[]; } /** diff --git a/apps/server/src/controllers/ontimeController.ts b/apps/server/src/controllers/ontimeController.ts index 0e2db0821..c5cd3c4dc 100644 --- a/apps/server/src/controllers/ontimeController.ts +++ b/apps/server/src/controllers/ontimeController.ts @@ -1,6 +1,8 @@ +import { Alias, EventData, LogOrigin } from 'ontime-types'; + import fs from 'fs'; -import type { Alias, EventData } from 'ontime-types'; import { networkInterfaces } from 'os'; + import { fileHandler } from '../utils/parser.js'; import { DataProvider } from '../classes/data-provider/DataProvider.js'; import { failEmptyObjects, failIsNotArray } from '../utils/routerUtils.js'; @@ -10,7 +12,7 @@ import { eventStore } from '../stores/EventStore.js'; import { resolveDbPath } from '../setup.js'; import { oscIntegration } from '../services/integration-service/OscIntegration.js'; import { logger } from '../classes/Logger.js'; -import { deleteAllEvents, forceReset } from '../services/RundownService.js'; +import { deleteAllEvents, forceReset } from '../services/rundown-service/RundownService.js'; // Create controller for GET request to '/ontime/poll' // Returns data for current state @@ -281,7 +283,7 @@ export const postOscSubscriptions = async (req, res) => { // TODO: this update could be more granular, checking that relevant data was changed const { message } = oscIntegration.init(oscSettings); - logger.info('RX', message); + logger.info(LogOrigin.Rx, message); res.send(oscSettings).status(200); } catch (error) { @@ -302,7 +304,7 @@ export const postOSC = async (req, res) => { // TODO: this update could be more granular, checking that relevant data was changed const { message } = oscIntegration.init(oscSettings); - logger.info('RX', message); + logger.info(LogOrigin.Rx, message); res.send(oscSettings).status(200); } catch (error) { diff --git a/apps/server/src/controllers/playbackController.js b/apps/server/src/controllers/playbackController.ts similarity index 100% rename from apps/server/src/controllers/playbackController.js rename to apps/server/src/controllers/playbackController.ts diff --git a/apps/server/src/controllers/rundownController.js b/apps/server/src/controllers/rundownController.ts similarity index 85% rename from apps/server/src/controllers/rundownController.js rename to apps/server/src/controllers/rundownController.ts index 77f746367..46b3346ab 100644 --- a/apps/server/src/controllers/rundownController.js +++ b/apps/server/src/controllers/rundownController.ts @@ -1,4 +1,4 @@ -import { DataProvider } from '../classes/data-provider/DataProvider.ts'; +import { OntimeEvent } from 'ontime-types'; import { failEmptyObjects } from '../utils/routerUtils.js'; import { addEvent, @@ -7,18 +7,14 @@ import { deleteEvent, editEvent, reorderEvent, -} from '../services/RundownService.ts'; +} from '../services/rundown-service/RundownService.js'; +import { getDelayedRundown } from '../services/rundown-service/delayedRundown.utils.js'; // Create controller for GET request to '/events' // Returns - export const rundownGetAll = async (req, res) => { - res.json(DataProvider.getRundown()); -}; - -// Create controller for GET request to '/events/:eventId' -// Returns - -export const getEventById = async (req, res) => { - res.json(DataProvider.getEventById(req.params?.eventId)); + const delayedRundown = getDelayedRundown(); + res.json(delayedRundown); }; // Create controller for POST request to '/events/' diff --git a/apps/server/src/controllers/rundownController.validate.js b/apps/server/src/controllers/rundownController.validate.ts similarity index 100% rename from apps/server/src/controllers/rundownController.validate.js rename to apps/server/src/controllers/rundownController.validate.ts diff --git a/apps/server/src/external/styles/override.css b/apps/server/src/external/styles/override.css index 5f886e2d5..958388070 100644 --- a/apps/server/src/external/styles/override.css +++ b/apps/server/src/external/styles/override.css @@ -6,6 +6,7 @@ --label-color-override: #6c6c6c; --timer-color-override: #202020; --card-background-color-override: #fff; + --card-background-color-blink-override: #339e4e; --font-family-override: "Open Sans"; --font-family-bold-override: "Arial Black"; --timer-progress-bg-override: #fff; diff --git a/apps/server/src/models/eventsDefinition.ts b/apps/server/src/models/eventsDefinition.ts index 82d21a119..b8b8adf0f 100644 --- a/apps/server/src/models/eventsDefinition.ts +++ b/apps/server/src/models/eventsDefinition.ts @@ -1,6 +1,6 @@ import { EndAction, OntimeBlock, OntimeDelay, OntimeEvent, SupportedEvent, TimerType } from 'ontime-types'; -export const event: Omit = { +export const event: Omit = { title: '', subtitle: '', presenter: '', diff --git a/apps/server/src/routes/rundownRouter.ts b/apps/server/src/routes/rundownRouter.ts index 4191d88ea..e4957f53f 100644 --- a/apps/server/src/routes/rundownRouter.ts +++ b/apps/server/src/routes/rundownRouter.ts @@ -1,7 +1,6 @@ import express from 'express'; import { deleteEventById, - getEventById, rundownApplyDelay, rundownDelete, rundownGetAll, @@ -21,9 +20,6 @@ export const router = express.Router(); // create route between controller and '/events/' endpoint router.get('/', rundownGetAll); -// create route between controller and '/events/:eventId' endpoint -router.get('/:eventId', paramsMustHaveEventId, getEventById); - // create route between controller and '/events/' endpoint router.post('/', rundownPostValidator, rundownPost); diff --git a/apps/server/src/services/PlaybackService.ts b/apps/server/src/services/PlaybackService.ts index 5831a2376..c463e5cce 100644 --- a/apps/server/src/services/PlaybackService.ts +++ b/apps/server/src/services/PlaybackService.ts @@ -1,4 +1,5 @@ -import { OntimeEvent, Playback } from 'ontime-types'; +import { LogOrigin, OntimeEvent, Playback } from 'ontime-types'; +import { validatePlayback } from 'ontime-utils'; import { eventLoader, EventLoader } from '../classes/event-loader/EventLoader.js'; import { eventStore } from '../stores/EventStore.js'; @@ -19,9 +20,9 @@ export class PlaybackService { static loadEvent(event: OntimeEvent): boolean { let success = false; if (!event) { - logger.error('PLAYBACK', 'No event found'); + logger.error(LogOrigin.Playback, 'No event found'); } else if (event.skip) { - logger.warning('PLAYBACK', `Refused playback of skipped event ID ${event.id}`); + logger.warning(LogOrigin.Playback, `Refused playback of skipped event ID ${event.id}`); } else { eventLoader.loadEvent(event); eventTimer.load(event); @@ -40,7 +41,7 @@ export class PlaybackService { const event = EventLoader.getEventWithId(eventId); const success = PlaybackService.loadEvent(event); if (success) { - logger.info('PLAYBACK', `Loaded event with ID ${event.id}`); + logger.info(LogOrigin.Playback, `Loaded event with ID ${event.id}`); PlaybackService.start(); } return success; @@ -55,7 +56,7 @@ export class PlaybackService { const event = EventLoader.getEventAtIndex(eventIndex); const success = PlaybackService.loadEvent(event); if (success) { - logger.info('PLAYBACK', `Loaded event with ID ${event.id}`); + logger.info(LogOrigin.Playback, `Loaded event with ID ${event.id}`); PlaybackService.start(); } return success; @@ -70,7 +71,7 @@ export class PlaybackService { const event = EventLoader.getEventWithId(eventId); const success = PlaybackService.loadEvent(event); if (success) { - logger.info('PLAYBACK', `Loaded event with ID ${event.id}`); + logger.info(LogOrigin.Playback, `Loaded event with ID ${event.id}`); } return success; } @@ -84,7 +85,7 @@ export class PlaybackService { const event = EventLoader.getEventAtIndex(eventIndex); const success = PlaybackService.loadEvent(event); if (success) { - logger.info('PLAYBACK', `Loaded event with ID ${event.id}`); + logger.info(LogOrigin.Playback, `Loaded event with ID ${event.id}`); } return success; } @@ -97,7 +98,7 @@ export class PlaybackService { if (previousEvent) { const success = PlaybackService.loadEvent(previousEvent); if (success) { - logger.info('PLAYBACK', `Loaded event with ID ${previousEvent.id}`); + logger.info(LogOrigin.Playback, `Loaded event with ID ${previousEvent.id}`); } } } @@ -112,19 +113,19 @@ export class PlaybackService { if (nextEvent) { const success = PlaybackService.loadEvent(nextEvent); if (success) { - logger.info('PLAYBACK', `Loaded event with ID ${nextEvent.id}`); + logger.info(LogOrigin.Playback, `Loaded event with ID ${nextEvent.id}`); return true; } } else if (fallbackAction === 'stop') { - logger.info('PLAYBACK', 'No next event found! Stopping playback'); + logger.info(LogOrigin.Playback, 'No next event found! Stopping playback'); PlaybackService.stop(); return false; } else if (fallbackAction === 'pause') { - logger.info('PLAYBACK', 'No next event found! Pausing playback'); + logger.info(LogOrigin.Playback, 'No next event found! Pausing playback'); PlaybackService.pause(); return false; } else { - logger.info('PLAYBACK', 'No next event found! Continuing playback'); + logger.info(LogOrigin.Playback, 'No next event found! Continuing playback'); return false; } } @@ -133,10 +134,10 @@ export class PlaybackService { * Starts playback on selected event */ static start() { - if (eventTimer.playback === Playback.Armed || eventTimer.playback === Playback.Pause) { + if (validatePlayback(eventTimer.playback).start) { eventTimer.start(); const newState = eventTimer.playback; - logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`); + logger.info(LogOrigin.Playback, `Play Mode ${newState.toUpperCase()}`); } } @@ -155,10 +156,10 @@ export class PlaybackService { * Pauses playback on selected event */ static pause() { - if (eventTimer.playback === Playback.Play) { + if (validatePlayback(eventTimer.playback).pause) { eventTimer.pause(); const newState = eventTimer.playback; - logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`); + logger.info(LogOrigin.Playback, `Play Mode ${newState.toUpperCase()}`); } } @@ -166,11 +167,11 @@ export class PlaybackService { * Stops timer and unloads any events */ static stop() { - if (eventTimer.playback !== Playback.Stop) { + if (validatePlayback(eventTimer.playback).stop) { eventLoader.reset(); eventTimer.stop(); const newState = eventTimer.playback; - logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`); + logger.info(LogOrigin.Playback, `Play Mode ${newState.toUpperCase()}`); } } @@ -192,14 +193,14 @@ export class PlaybackService { // nothing to play if (rollTimers === null) { - logger.warning('SERVER', 'Roll: no events found'); + logger.warning(LogOrigin.Server, 'Roll: no events found'); PlaybackService.stop(); return; } const { currentEvent, nextEvent } = rollTimers; if (!currentEvent && !nextEvent) { - logger.warning('SERVER', 'Roll: no events found'); + logger.warning(LogOrigin.Server, 'Roll: no events found'); PlaybackService.stop(); return; } @@ -207,7 +208,7 @@ export class PlaybackService { eventTimer.roll(currentEvent, nextEvent); const newState = eventTimer.playback; - logger.info('PLAYBACK', `Play Mode ${newState.toUpperCase()}`); + logger.info(LogOrigin.Playback, `Play Mode ${newState.toUpperCase()}`); } } @@ -220,8 +221,8 @@ export class PlaybackService { const delayInMs = delayTime * 1000 * 60; eventTimer.delay(delayInMs); delayInMs > 0 - ? logger.info('PLAYBACK', `Added ${delayTime} min delay`) - : logger.info('PLAYBACK', `Removed ${delayTime} min delay`); + ? logger.info(LogOrigin.Playback, `Added ${delayTime} min delay`) + : logger.info(LogOrigin.Playback, `Removed ${delayTime} min delay`); } } } diff --git a/apps/server/src/services/TimerService.ts b/apps/server/src/services/TimerService.ts index 96c985283..8831692fb 100644 --- a/apps/server/src/services/TimerService.ts +++ b/apps/server/src/services/TimerService.ts @@ -7,6 +7,13 @@ import { DAY_TO_MS } from '../utils/time.js'; import { integrationService } from './integration-service/IntegrationService.js'; import { getCurrent, getElapsed, getExpectedFinish } from './timerUtils.js'; import { clock } from './Clock.js'; +import { logger } from '../classes/Logger.js'; + +type initialLoadingData = { + startedAt?: number | null; + expectedFinish?: number | null; + current?: number | null; +}; export class TimerService { private readonly _interval: NodeJS.Timer; @@ -113,7 +120,7 @@ export class TimerService { * @param {string} timer.timerType * @param {boolean} timer.skip */ - load(timer) { + load(timer, initialData?: initialLoadingData) { if (timer.skip) { throw new Error('Refuse load of skipped event'); } @@ -129,6 +136,10 @@ export class TimerService { this.pausedTime = 0; this.pausedAt = 0; + if (typeof initialData !== 'undefined') { + this.timer = { ...this.timer, ...initialData }; + } + this._onLoad(); } @@ -146,6 +157,9 @@ export class TimerService { start() { if (!this.loadedTimerId) { + if (this.playback === Playback.Roll) { + logger.error('PLAYBACK', 'Cannot start while waiting for event'); + } return; } @@ -155,12 +169,12 @@ export class TimerService { this.timer.clock = clock.timeNow(); - // add paused time + // add paused time if it exists if (this.pausedTime) { this.timer.addedTime += this.pausedTime; this.pausedAt = null; this.pausedTime = 0; - } else { + } else if (this.timer.startedAt === null) { this.timer.startedAt = this.timer.clock; } @@ -188,10 +202,6 @@ export class TimerService { } pause() { - if (this.playback !== Playback.Play) { - return; - } - this.playback = Playback.Pause; this.timer.clock = clock.timeNow(); this.pausedAt = this.timer.clock; @@ -309,7 +319,11 @@ export class TimerService { } update(force = false) { + const previousTime = this.timer.clock; this.timer.clock = clock.timeNow(); + if (previousTime > this.timer.clock) { + force = true; + } // we call integrations if we update timers let shouldNotify = false; @@ -370,9 +384,11 @@ export class TimerService { // when we load a timer in roll, we do the same things as before // but also pre-populate some data as to the running state - this.load(currentEvent); - this.timer.startedAt = currentEvent.timeStart; - this.timer.expectedFinish = currentEvent.timeEnd; + this.load(currentEvent, { + startedAt: currentEvent.timeStart, + expectedFinish: currentEvent.timeEnd, + current: currentEvent.timeEnd - this.timer.clock, + }); } else if (nextEvent) { // account for day after const nextStart = nextEvent.timeStart < this.timer.clock ? nextEvent.timeStart + DAY_TO_MS : nextEvent.timeStart; diff --git a/apps/server/src/services/RundownService.ts b/apps/server/src/services/rundown-service/RundownService.ts similarity index 54% rename from apps/server/src/services/RundownService.ts rename to apps/server/src/services/rundown-service/RundownService.ts index 0dc8aeb94..f1db79314 100644 --- a/apps/server/src/services/RundownService.ts +++ b/apps/server/src/services/rundown-service/RundownService.ts @@ -1,11 +1,30 @@ -import { OntimeBaseEvent, OntimeBlock, OntimeDelay, OntimeEvent, SupportedEvent } from 'ontime-types'; +import { + LogOrigin, + OntimeBaseEvent, + OntimeBlock, + OntimeDelay, + OntimeEvent, + OntimeRundown, + SupportedEvent, +} from 'ontime-types'; import { generateId } from 'ontime-utils'; -import { DataProvider } from '../classes/data-provider/DataProvider.js'; -import { block as blockDef, delay as delayDef, event as eventDef } from '../models/eventsDefinition.js'; -import { MAX_EVENTS } from '../settings.js'; -import { EventLoader, eventLoader } from '../classes/event-loader/EventLoader.js'; -import { eventTimer } from './TimerService.js'; -import { sendRefetch } from '../adapters/websocketAux.js'; +import { DataProvider } from '../../classes/data-provider/DataProvider.js'; +import { block as blockDef, delay, delay as delayDef, event as eventDef } from '../../models/eventsDefinition.js'; +import { MAX_EVENTS } from '../../settings.js'; +import { EventLoader, eventLoader } from '../../classes/event-loader/EventLoader.js'; +import { eventTimer } from '../TimerService.js'; +import { sendRefetch } from '../../adapters/websocketAux.js'; +import { runtimeCacheStore } from '../../stores/cachingStore.js'; +import { + cachedAdd, + cachedDelete, + cachedEdit, + cachedReorder, + calculateRuntimeDelaysFrom, + delayedRundownCacheKey, + getDelayedRundown, +} from './delayedRundown.utils.js'; +import { logger } from '../../classes/Logger.js'; /** * Forces rundown to be recalculated @@ -14,6 +33,7 @@ import { sendRefetch } from '../adapters/websocketAux.js'; export function forceReset() { eventLoader.reset(); sendRefetch(); + runtimeCacheStore.invalidate(delayedRundownCacheKey); } /** @@ -73,7 +93,7 @@ const isNewNext = () => { }; /** - * Updates timer object + * Updates timer service when a relevant piece of data changes */ export function updateTimer(affectedIds?: string[]) { const runningEventId = eventLoader.loaded.selectedEventId; @@ -130,44 +150,54 @@ export async function addEvent(eventData: Partial | Partial = {}; const id = generateId(); + // TODO: filter the parameters that exist in the event, use the parserUtils switch (eventData.type) { - case 'event': - newEvent = { ...eventDef, ...eventData, id } as Partial; + case SupportedEvent.Event: + newEvent = { ...eventDef, ...eventData, id }; break; - case 'delay': - newEvent = { ...delayDef, ...eventData, id } as Partial; + case SupportedEvent.Delay: + newEvent = { ...delayDef, ...eventData, id }; break; - case 'block': - newEvent = { ...blockDef, ...eventData, id } as Partial; + case SupportedEvent.Block: + newEvent = { ...blockDef, ...eventData, id }; break; } - try { - const afterId = newEvent?.after; - if (typeof afterId === 'undefined') { - await DataProvider.insertEventAt(newEvent, 0); + let insertIndex = 0; + if (typeof newEvent?.after !== 'undefined') { + const index = DataProvider.getIndexOf(newEvent.after); + if (index < 0) { + logger.warning(LogOrigin.Server, `Could not find event with id ${newEvent.after}`); } else { - delete newEvent.after; - await DataProvider.insertEventAfterId(newEvent, afterId); + insertIndex = index + 1; } - } catch (error) { - throw new Error(error); + delete newEvent.after; } + + // modify rundown + await cachedAdd(insertIndex, newEvent as OntimeEvent | OntimeDelay | OntimeBlock); + + // notify timer service of changed events updateTimer([id]); + + // notify event loader that rundown size has changed updateChangeNumEvents(); + + // advice socket subscribers of change sendRefetch(); + return newEvent; } -export async function editEvent(eventData) { - const eventId = eventData.id; - const eventInMemory = DataProvider.getEventById(eventId); - if (typeof eventInMemory === 'undefined') { - throw new Error('No event with ID found'); - } - const newEvent = await DataProvider.updateEventById(eventId, eventData); - updateTimer([eventId]); +export async function editEvent(eventData: Partial | Partial | Partial) { + const newEvent = await cachedEdit(eventData.id, eventData); + + // notify timer service of changed events + updateTimer([newEvent.id]); + + // advice socket subscribers of change sendRefetch(); + return newEvent; } @@ -177,9 +207,18 @@ export async function editEvent(eventData) { * @returns {Promise} */ export async function deleteEvent(eventId) { - await DataProvider.deleteEvent(eventId); + await cachedDelete(eventId); + + // notify timer service of changed events updateTimer([eventId]); + + // notify event loader that rundown size has changed updateChangeNumEvents(); + + // invalidate cache + runtimeCacheStore.invalidate(delayedRundownCacheKey); + + // advice socket subscribers of change sendRefetch(); } @@ -190,78 +229,83 @@ export async function deleteEvent(eventId) { export async function deleteAllEvents() { await DataProvider.clearRundown(); updateTimer(); - updateChangeNumEvents(); - sendRefetch(); + forceReset(); } /** * reorders a given event - * @param {string} eventId - * @param {number} from - * @param {number} to + * @param {string} eventId - ID of event from, for sanity check + * @param {number} from - index of event from + * @param {number} to - index of event to * @returns {Promise} */ -export async function reorderEvent(eventId, from, to) { - const rundown = DataProvider.getRundown(); - const index = rundown.findIndex((event) => event.id === eventId); +export async function reorderEvent(eventId: string, from: number, to: number) { + const reorderedItem = await cachedReorder(eventId, from, to); - if (index !== from) { - throw new Error('ID not found at index'); - } - const [reorderedItem] = rundown.splice(from, 1); - - // reinsert item at to - rundown.splice(to, 0, reorderedItem); - - // save rundown - await DataProvider.setRundown(rundown); + // notify timer service of changed events updateTimer(); + + // advice socket subscribers of change sendRefetch(); return reorderedItem; } +export function _applyDelay( + eventId: string, + rundown: OntimeRundown, +): { + delayIndex: number | null; + updatedRundown: OntimeRundown; +} { + const updatedRundown = [...rundown]; + let delayIndex = null; + let delayValue = 0; + + for (const [index, event] of updatedRundown.entries()) { + // look for delay + if (delayIndex === null) { + if (event.type === SupportedEvent.Delay && event.id === eventId) { + delayValue = event.duration; + delayIndex = index; + + if (delayValue === 0) { + // nothing to apply + break; + } + } + continue; + } + + // once delay is found, apply delay value to all items until block or end + if (event.type === SupportedEvent.Event) { + updatedRundown[index] = { + ...event, + timeStart: Math.max(0, event.timeStart + delayValue), + timeEnd: Math.max(event.duration, event.timeEnd + delayValue), + revision: event.revision + 1, + }; + } else if (event.type === SupportedEvent.Block) { + break; + } + } + + return { delayIndex, updatedRundown }; +} + /** * applies delay value for given event * @param eventId * @returns {Promise} */ export async function applyDelay(eventId: string) { - const rundown = DataProvider.getRundown(); - let delayIndex = null; - let delayValue = 0; - - for (const [index, event] of rundown.entries()) { - // look for delay - if (delayIndex === null) { - if (event.id === eventId && event.type === SupportedEvent.Delay) { - delayValue = event.duration; - delayIndex = index; - } - } - - // apply delay value to all items until block or end - else { - if (event.type === SupportedEvent.Event) { - event.timeStart = Math.max(0, event.timeStart + delayValue); - event.timeEnd = Math.max(event.duration, event.timeStart + delayValue); - event.revision += 1; - } else if (event.type === SupportedEvent.Block) { - break; - } - } - } - + const rundown: OntimeRundown = DataProvider.getRundown(); + const { delayIndex, updatedRundown } = _applyDelay(eventId, rundown); if (delayIndex === null) { throw new Error(`Delay event with ID ${eventId} not found`); } - // delete delay - rundown.splice(delayIndex, 1); - - // update rundown - await DataProvider.setRundown(rundown); - updateTimer(); - sendRefetch(); + await DataProvider.setRundown(updatedRundown); + await deleteEvent(eventId); } /** diff --git a/apps/server/src/services/rundown-service/__tests__/RundownService.test.ts b/apps/server/src/services/rundown-service/__tests__/RundownService.test.ts new file mode 100644 index 000000000..a4b9e928f --- /dev/null +++ b/apps/server/src/services/rundown-service/__tests__/RundownService.test.ts @@ -0,0 +1,319 @@ +import { EndAction, OntimeRundown, SupportedEvent, TimerType } from 'ontime-types'; +import { _applyDelay } from '../RundownService.js'; + +describe('applyDelay()', () => { + it('applies its duration to following events', () => { + const rundown: OntimeRundown = [ + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 4, + id: '659e1', + }, + { + duration: 600000, + type: SupportedEvent.Delay, + revision: 0, + id: '07986', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 4, + id: 'd48c2', + }, + ]; + + const eventId = rundown[1].id; + const { delayIndex, updatedRundown } = _applyDelay(eventId, rundown); + + expect(delayIndex).toBe(1); + // we do not delay delays anymore + expect(updatedRundown.length).toBe(3); + expect(rundown.length).toBe(3); + expect(updatedRundown[0].timeStart).toBe(rundown[0].timeStart); + expect(updatedRundown[2].timeStart).toBe(rundown[1].duration + rundown[2].timeStart); + expect(updatedRundown[2].timeEnd).toBe(rundown[1].duration + rundown[2].timeEnd); + }); + it('stops propagating on blocks', () => { + const rundown: OntimeRundown = [ + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '659e1', + }, + { + duration: 600000, + type: SupportedEvent.Delay, + revision: 0, + id: '07986', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: 'd48c2', + }, + { + title: '', + type: SupportedEvent.Block, + id: '9870d', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1800000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 2, + id: '2f185', + }, + ]; + + const eventId = rundown[1].id; + const { updatedRundown } = _applyDelay(eventId, rundown); + + expect(updatedRundown[0].timeStart).toBe(rundown[0].timeStart); + expect(updatedRundown[2].timeStart).toBe(rundown[1].duration + rundown[2].timeStart); + expect(updatedRundown[4].timeStart).toBe(rundown[4].timeStart); + }); + it('only applies given delay', () => { + const rundown: OntimeRundown = [ + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '659e1', + }, + { + duration: 600000, + type: SupportedEvent.Delay, + revision: 0, + id: '07986', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1200000, + duration: 0, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '1c48f', + }, + { + duration: 1200000, + type: SupportedEvent.Delay, + revision: 0, + id: '7db42', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: 'd48c2', + }, + { + title: '', + type: SupportedEvent.Block, + id: '9870d', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1800000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '2f185', + }, + ]; + + const eventId = rundown[1].id; + const { updatedRundown } = _applyDelay(eventId, rundown); + + expect(updatedRundown[0].timeStart).toBe(rundown[0].timeStart); + expect(updatedRundown[2].timeStart).toBe(rundown[1].duration + rundown[2].timeStart); + expect(updatedRundown[4].timeStart).toBe(rundown[1].duration + rundown[4].timeStart); + }); +}); diff --git a/apps/server/src/services/rundown-service/__tests__/delayedRundown.utils.test.ts b/apps/server/src/services/rundown-service/__tests__/delayedRundown.utils.test.ts new file mode 100644 index 000000000..48d9740c9 --- /dev/null +++ b/apps/server/src/services/rundown-service/__tests__/delayedRundown.utils.test.ts @@ -0,0 +1,445 @@ +import { EndAction, OntimeRundown, SupportedEvent, TimerType } from 'ontime-types'; + +import { calculateRuntimeDelays, calculateRuntimeDelaysFrom, getDelayAt } from '../delayedRundown.utils.js'; + +describe('calculateRuntimeDelays', () => { + it('calculates all delays in a given rundown', () => { + const rundown: OntimeRundown = [ + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '659e1', + }, + { + duration: 600000, + type: SupportedEvent.Delay, + revision: 0, + id: '07986', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1200000, + duration: 0, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '1c48f', + }, + { + duration: 1200000, + type: SupportedEvent.Delay, + revision: 0, + id: '7db42', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: 'd48c2', + }, + { + title: '', + type: SupportedEvent.Block, + id: '9870d', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1800000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '2f185', + }, + ]; + + const updatedRundown = calculateRuntimeDelays(rundown); + + expect(rundown.length).toBe(updatedRundown.length); + expect(updatedRundown[0].delay).toBe(0); + expect(updatedRundown[2].delay).toBe(600000); + expect(updatedRundown[4].delay).toBe(600000 + 1200000); + expect(updatedRundown[6].delay).toBe(0); + }); +}); + +describe('getDelayAt()', () => { + const delayedRundown: OntimeRundown = [ + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '659e1', + delay: 0, + }, + { + duration: 600000, + type: SupportedEvent.Delay, + revision: 0, + id: '07986', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1200000, + duration: 0, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '1c48f', + delay: 600000, + }, + { + duration: 1200000, + type: SupportedEvent.Delay, + revision: 0, + id: '7db42', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: 'd48c2', + delay: 1800000, + }, + { + title: '', + type: SupportedEvent.Block, + id: '9870d', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1800000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '2f185', + delay: 0, + }, + ]; + + it('calculates delay in a rundown', () => { + const delayAtStart = getDelayAt(0, delayedRundown); + const delayOnFirstEvent = getDelayAt(2, delayedRundown); + const delayOnSecondEvent = getDelayAt(4, delayedRundown); + const delayOnBlockedEvent = getDelayAt(0, delayedRundown); + + expect(delayAtStart).toBe(0); + expect(delayOnFirstEvent).toBe(600000); + expect(delayOnSecondEvent).toBe(600000 + 1200000); + expect(delayOnBlockedEvent).toBe(0); + }); + it('finds delay before a delay block', () => { + const valueOnFirstDelayBlock = getDelayAt(1, delayedRundown); + const valueOnSecondDelayBlock = getDelayAt(3, delayedRundown); + const valueAfterSecondDelayBlock = getDelayAt(4, delayedRundown); + + expect(valueOnFirstDelayBlock).toBe(0); + expect(valueOnSecondDelayBlock).toBe(600000); + expect(valueAfterSecondDelayBlock).toBe(600000 + 1200000); + }); + it('returns 0 after blocks', () => { + const valueOnBlock = getDelayAt(6, delayedRundown); + expect(valueOnBlock).toBe(0); + }); +}); + +describe('calculateRuntimeDelaysFrom()', () => { + it('updates delays from given id', () => { + const delayedRundown: OntimeRundown = [ + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '659e1', + delay: 0, + }, + { + duration: 600000, + type: SupportedEvent.Delay, + revision: 0, + id: '07986', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1200000, + duration: 0, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '1c48f', + delay: 0, + }, + { + duration: 1200000, + type: SupportedEvent.Delay, + revision: 0, + id: '7db42', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 600000, + timeEnd: 1200000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: 'd48c2', + delay: 1800000, + }, + { + title: '', + type: SupportedEvent.Block, + id: '9870d', + }, + { + title: '', + subtitle: '', + presenter: '', + note: '', + endAction: EndAction.None, + timerType: TimerType.CountDown, + timeStart: 1200000, + timeEnd: 1800000, + duration: 600000, + isPublic: true, + skip: false, + colour: '', + user0: '', + user1: '', + user2: '', + user3: '', + user4: '', + user5: '', + user6: '', + user7: '', + user8: '', + user9: '', + type: SupportedEvent.Event, + revision: 0, + id: '2f185', + delay: 0, + }, + ]; + + const updatedRundown = calculateRuntimeDelaysFrom('07986', delayedRundown); + + // we only update from the 4th on + expect(updatedRundown[0].delay).toBe(0); + // 1 + 3 + expect(updatedRundown[4].delay).toBe(600000 + 1200000); + }); +}); diff --git a/apps/server/src/services/rundown-service/delayedRundown.utils.ts b/apps/server/src/services/rundown-service/delayedRundown.utils.ts new file mode 100644 index 000000000..1d1b2cc6d --- /dev/null +++ b/apps/server/src/services/rundown-service/delayedRundown.utils.ts @@ -0,0 +1,261 @@ +import { OntimeBlock, OntimeDelay, OntimeEvent, OntimeRundown, SupportedEvent } from 'ontime-types'; +import { DataProvider } from '../../classes/data-provider/DataProvider.js'; +import { getCached, runtimeCacheStore } from '../../stores/cachingStore.js'; +import { isProduction } from '../../setup.js'; +import { deleteAtIndex, insertAtIndex, reorderArray } from '../../utils/arrayUtils.js'; + +/** + * Key of rundown in cache + */ +export const delayedRundownCacheKey = 'delayed-rundown'; + +/** + * Invalidates the cached rundown when an inconsistency is found + * will throw when not in production + * @param errorMessage + */ +export function invalidateFromError(errorMessage = 'Found mismatch between store and cache') { + if (isProduction) { + runtimeCacheStore.invalidate(delayedRundownCacheKey); + } else { + throw new Error(errorMessage); + } +} + +/** + * Returns rundown with calculated delays + * Ensures request goes through the caching layer + */ +export function getDelayedRundown(): OntimeRundown { + function calculateRundown() { + const rundown = DataProvider.getRundown(); + return calculateRuntimeDelays(rundown); + } + + return getCached(delayedRundownCacheKey, calculateRundown); +} + +/** + * Adds an event in the rundown at given index, ensuring replication to delayed rundown cache + * @param eventIndex + * @param event + */ +export async function cachedAdd(eventIndex: number, event: OntimeEvent | OntimeDelay | OntimeBlock) { + // TODO: create wrapper function + const rundown = DataProvider.getRundown(); + const newRundown = insertAtIndex(eventIndex, event, rundown); + + const delayedRundown = getDelayedRundown(); + let newDelayedRundown = insertAtIndex(eventIndex, event, delayedRundown); + + // update delay cache + if (event.type === SupportedEvent.Event) { + // if it is an event, we need its delay + (newDelayedRundown[eventIndex] as OntimeEvent).delay = getDelayAt(eventIndex, newDelayedRundown); + } else { + // if it is a block or delay, we invalidate from here + newDelayedRundown = calculateRuntimeDelaysFromIndex(eventIndex, newDelayedRundown); + } + + runtimeCacheStore.setCached(delayedRundownCacheKey, newDelayedRundown); + // we need to delay updating this to ensure add operation happens on same dataset + await DataProvider.setRundown(newRundown); +} + +/** + * Edits an event in rundown, ensuring replication to delayed rundown cache + * @param eventId + * @param patchObject + */ +export async function cachedEdit( + eventId: string, + patchObject: Partial | Partial | Partial, +) { + const indexInMemory = DataProvider.getIndexOf(eventId); + if (indexInMemory < 0) { + throw new Error('No event with ID found'); + } + + const updatedRundown = DataProvider.getRundown(); + const newEvent = { ...updatedRundown[indexInMemory], ...patchObject }; + if (newEvent.type === SupportedEvent.Event) { + newEvent.revision++; + } + // @ts-expect-error -- this merge is safe + updatedRundown[indexInMemory] = newEvent; + + let newDelayedRundown = getDelayedRundown(); + if (newDelayedRundown?.[indexInMemory].id !== newEvent.id) { + invalidateFromError(); + } else { + // @ts-expect-error -- this merge is safe + newDelayedRundown[indexInMemory] = newEvent; + if (newEvent.type === SupportedEvent.Event) { + (newDelayedRundown[indexInMemory] as OntimeEvent).delay = getDelayAt(indexInMemory, newDelayedRundown); + } else if (newEvent.type === SupportedEvent.Delay) { + // blocks have no reason to change the rundown, from delays we need to recalculate + newDelayedRundown = calculateRuntimeDelaysFromIndex(indexInMemory, newDelayedRundown); + } + + runtimeCacheStore.setCached(delayedRundownCacheKey, newDelayedRundown); + } + + // we need to delay updating this to ensure edit operation happens on same dataset + await DataProvider.setRundown(updatedRundown); + + return newEvent; +} + +/** + * Deletes an event with given id from rundown, ensuring replication to delayed rundown cache + * @param eventId + */ +export async function cachedDelete(eventId: string) { + const eventIndex = DataProvider.getIndexOf(eventId); + let delayedRundown = getDelayedRundown(); + + if (eventIndex < 0) { + if (delayedRundown.findIndex((event) => event.id === eventId) >= 0) { + invalidateFromError(); + } + return; + } + + let updatedRundown = DataProvider.getRundown(); + const eventType = updatedRundown[eventIndex].type; + updatedRundown = deleteAtIndex(eventIndex, updatedRundown); + if (eventId !== delayedRundown[eventIndex].id) { + invalidateFromError(); + } else { + delayedRundown = deleteAtIndex(eventIndex, delayedRundown); + if (eventType === SupportedEvent.Delay || eventType === SupportedEvent.Block) { + // for events, we do not have to worry + // the following event, would have taken the place of the deleted event by now + delayedRundown = calculateRuntimeDelaysFromIndex(eventIndex, delayedRundown); + } + runtimeCacheStore.setCached(delayedRundownCacheKey, delayedRundown); + } + // we need to delay updating this to ensure edit operation happens on same dataset + await DataProvider.setRundown(updatedRundown); +} + +/** + * Reorders an event in the rundown, ensuring replication to delayed rundown cache + * @param eventId + * @param from + * @param to + */ +export async function cachedReorder(eventId: string, from: number, to: number) { + const indexCheck = DataProvider.getIndexOf(eventId); + if (indexCheck !== from) { + invalidateFromError(); + throw new Error('ID not found at index'); + } + + let updatedRundown = DataProvider.getRundown(); + const reorderedEvent = updatedRundown[from]; + updatedRundown = reorderArray(updatedRundown, from, to); + + const delayedRundown = getDelayedRundown(); + if (eventId !== delayedRundown[from].id) { + invalidateFromError(); + } else { + // TODO: could we be more granular about updates + // I fear we need to update both from and to, which could signify more iterations + runtimeCacheStore.invalidate(delayedRundownCacheKey); + } + + // we need to delay updating this to ensure edit operation happens on same dataset + await DataProvider.setRundown(updatedRundown); + + return reorderedEvent; +} + +/** + * Calculates all delays in a given rundown + * @param rundown + */ +export function calculateRuntimeDelays(rundown: OntimeRundown) { + let accumulatedDelay = 0; + const updatedRundown = [...rundown]; + + for (const [index, event] of updatedRundown.entries()) { + if (event.type === SupportedEvent.Delay) { + accumulatedDelay += event.duration; + } else if (event.type === SupportedEvent.Block) { + accumulatedDelay = 0; + } else if (event.type === SupportedEvent.Event) { + updatedRundown[index] = { + ...event, + delay: accumulatedDelay, + }; + } + } + return updatedRundown; +} + +/** + * Calculate delays in rundown from a given index + * @param eventIndex + * @param rundown + */ +export function calculateRuntimeDelaysFromIndex(eventIndex: number, rundown: OntimeRundown) { + if (eventIndex === -1) { + throw new Error('ID not found at index'); + } + + let accumulatedDelay = getDelayAt(eventIndex, rundown); + const updatedRundown = [...rundown]; + + for (let i = eventIndex; i < rundown.length; i++) { + const event = rundown[i]; + if (event.type === SupportedEvent.Delay) { + accumulatedDelay += event.duration; + } else if (event.type === SupportedEvent.Block) { + if (i === eventIndex) { + accumulatedDelay = 0; + } else { + break; + } + } else if (event.type === SupportedEvent.Event) { + updatedRundown[i] = { + ...event, + delay: accumulatedDelay, + }; + } + } + return updatedRundown; +} + +/** + * Calculate delays in rundown from an event with given id + * @param eventId + * @param rundown + */ +export function calculateRuntimeDelaysFrom(eventId: string, rundown: OntimeRundown) { + const index = rundown.findIndex((event) => event.id === eventId); + return calculateRuntimeDelaysFromIndex(index, rundown); +} + +/** + * Calculates delay to an event at a given index + * @param eventIndex + * @param rundown + */ +export function getDelayAt(eventIndex: number, rundown: OntimeRundown): number { + if (eventIndex < 1) { + return 0; + } + + // we need to check the event before + const event = rundown[eventIndex - 1]; + + if (event.type === SupportedEvent.Delay) { + return event.duration + getDelayAt(eventIndex - 1, rundown); + } else if (event.type === SupportedEvent.Block) { + return 0; + } else if (event.type === SupportedEvent.Event) { + return event.delay ?? 0; + } + return 0; +} diff --git a/apps/server/src/setup.ts b/apps/server/src/setup.ts index f31e72b81..4684362a1 100644 --- a/apps/server/src/setup.ts +++ b/apps/server/src/setup.ts @@ -41,7 +41,7 @@ export const isDocker = env === 'docker'; // ================================================= // resolve path to external -const productionPath = '../../Resources/extraResources/client'; +const productionPath = '../../resources/extraResources/client'; const devPath = '../../client/build/'; const dockerPath = 'client/'; diff --git a/apps/server/src/stores/__tests__/cachingStore.test.ts b/apps/server/src/stores/__tests__/cachingStore.test.ts new file mode 100644 index 000000000..6f91878a0 --- /dev/null +++ b/apps/server/src/stores/__tests__/cachingStore.test.ts @@ -0,0 +1,67 @@ +import { runtimeCacheStore } from '../cachingStore.js'; + +describe('cachingStore()', () => { + beforeEach(() => { + runtimeCacheStore.clear(); // Clear the cache before each test + }); + + it('should check if an item is cached', () => { + // Add an item to the cache + runtimeCacheStore.setCached('key', 'value'); + + // Check if the item is cached + expect(runtimeCacheStore.checkCached('key')).toBe(true); + expect(runtimeCacheStore.checkCached('non-existent-key')).toBe(false); + }); + + it('should get an item from the cache', () => { + // Add an item to the cache + runtimeCacheStore.setCached('key', 'value'); + + // Get the item from the cache + const result = runtimeCacheStore.getCached('key', () => 'default-value'); + + // Check the returned value + expect(result).toBe('value'); + }); + + it('should retrieve default value when item is not cached', () => { + // Get an item that is not in the cache + const result = runtimeCacheStore.getCached('non-existent-key', () => 'default-value'); + + // Check the returned value + expect(result).toBe('default-value'); + }); + + it('should set an item in the cache', () => { + // Set an item in the cache + runtimeCacheStore.setCached('key', 'value'); + + // Check if the item is cached + expect(runtimeCacheStore.checkCached('key')).toBe(true); + }); + + it('should invalidate an item in the cache', () => { + // Add an item to the cache + runtimeCacheStore.setCached('key', 'value'); + + // Invalidate the item + runtimeCacheStore.invalidate('key'); + + // Check if the item is no longer cached + expect(runtimeCacheStore.checkCached('key')).toBe(false); + }); + + it('should clear the cache', () => { + // Add items to the cache + runtimeCacheStore.setCached('key1', 'value1'); + runtimeCacheStore.setCached('key2', 'value2'); + + // Clear the cache + runtimeCacheStore.clear(); + + // Check if the cache is empty + expect(runtimeCacheStore.checkCached('key1')).toBe(false); + expect(runtimeCacheStore.checkCached('key2')).toBe(false); + }); +}); diff --git a/apps/server/src/stores/cachingStore.ts b/apps/server/src/stores/cachingStore.ts new file mode 100644 index 000000000..a5ac8d05d --- /dev/null +++ b/apps/server/src/stores/cachingStore.ts @@ -0,0 +1,47 @@ +interface CacheData { + data: unknown; +} + +const runtimeCache: Map = new Map(); + +export function checkCached(key: string): boolean { + return runtimeCache.has(key); +} + +export function getCached(key: string, callback: () => T): T { + if (!runtimeCache.has(key)) { + try { + const data = callback(); + runtimeCache.set(key, { data }); + } catch (error) { + console.log(`Failed retrieving data from callback: ${error}`); + } + } + + return runtimeCache.get(key).data as T; +} + +export function setCached(key: string, value: T): T { + runtimeCache.set(key, { data: value }); + return runtimeCache.get(key).data as T; +} + +export function invalidate(key) { + runtimeCache.delete(key); +} + +export function clear() { + runtimeCache.clear(); +} + +function createCacheStore() { + return { + checkCached, + getCached, + setCached, + invalidate, + clear, + }; +} + +export const runtimeCacheStore = createCacheStore(); diff --git a/apps/server/src/utils/__tests__/arrayUtils.tests.ts b/apps/server/src/utils/__tests__/arrayUtils.tests.ts new file mode 100644 index 000000000..947fc3a21 --- /dev/null +++ b/apps/server/src/utils/__tests__/arrayUtils.tests.ts @@ -0,0 +1,54 @@ +import { insertAtIndex, reorderArray } from '../arrayUtils.js'; + +describe('insertAtIndex', () => { + it('should insert an item at the beginning of the array', () => { + const array = [2, 3, 4]; + const result = insertAtIndex(0, 1, array); + expect(result).toEqual([1, 2, 3, 4]); + }); + + it('should insert an item at the end of the array', () => { + const array = [1, 2, 3]; + const result = insertAtIndex(3, 4, array); + expect(result).toEqual([1, 2, 3, 4]); + }); + + it('should insert an item in the middle of the array', () => { + const array = [1, 2, 4]; + const result = insertAtIndex(2, 3, array); + expect(result).toEqual([1, 2, 3, 4]); + }); + + it('should return a new array and not modify the original array', () => { + const array = [1, 2, 3]; + const result = insertAtIndex(1, 5, array); + expect(result).toEqual([1, 5, 2, 3]); + expect(array).toEqual([1, 2, 3]); // Original array should remain unchanged + }); +}); + +describe('reorderArray', () => { + it('should reorder an item in the array', () => { + const array = ['a', 'b', 'c', 'd']; + const result = reorderArray(array, 1, 3); + expect(result).toEqual(['a', 'c', 'd', 'b']); + }); + + it('should return the original array if fromIndex and toIndex are the same', () => { + const array = ['a', 'b', 'c']; + const result = reorderArray(array, 1, 1); + expect(result).toEqual(array); + }); + + it('should handle reordering to the beginning of the array', () => { + const array = ['a', 'b', 'c']; + const result = reorderArray(array, 2, 0); + expect(result).toEqual(['c', 'a', 'b']); + }); + + it('should handle reordering to the end of the array', () => { + const array = ['a', 'b', 'c']; + const result = reorderArray(array, 0, 2); + expect(result).toEqual(['b', 'c', 'a']); + }); +}); diff --git a/apps/server/src/utils/arrayUtils.ts b/apps/server/src/utils/arrayUtils.ts new file mode 100644 index 000000000..49cb8780a --- /dev/null +++ b/apps/server/src/utils/arrayUtils.ts @@ -0,0 +1,50 @@ +/** + * Inserts an item in an array at a given index + * @param index + * @param item + * @param array + */ +export function insertAtIndex(index: number, item: T, array: T[]): T[] { + const modifiedArray = [...array]; + + // Insert at beginning + if (index === 0) { + modifiedArray.unshift(item); + } + + // insert at end + else if (index >= modifiedArray.length) { + modifiedArray.push(item); + } + + // insert in the middle + else { + modifiedArray.splice(index, 0, item); + } + + return modifiedArray; +} + +/** + * Deletes array element at a given index + * @param index + * @param array + */ +export function deleteAtIndex(index: number, array: T[]) { + return array.filter((_, i) => i !== index); +} + +export function reorderArray(array: T[], fromIndex: number, toIndex: number) { + if (fromIndex === toIndex) { + return array; // No change needed, return the original array + } + + const modifiedArray = [...array]; + + // delete in from + const [reorderedItem] = modifiedArray.splice(fromIndex, 1); + + // reinsert item at to + modifiedArray.splice(toIndex, 0, reorderedItem); + return modifiedArray; +} diff --git a/e2e/tests/features/202-cuesheet.spec.ts b/e2e/tests/features/202-cuesheet.spec.ts new file mode 100644 index 000000000..1c9547252 --- /dev/null +++ b/e2e/tests/features/202-cuesheet.spec.ts @@ -0,0 +1,62 @@ +import { expect, test } from '@playwright/test'; +import fs from 'fs'; + +test('cuesheet displays events and exports csv', async ({ page }) => { + // ensure elements exist in editor + await page.goto('http://localhost:4001/editor'); + await page.getByText('First test event').click(); + await page.getByText('Second test event').click(); + await page.getByText('Third test event').click(); + await page.getByText('Add timeSubtract timeApplyCancel').click(); + await page.getByText('Lunch').click(); + + // same elements in cuesheet + await page.goto('http://localhost:4001/cuesheet'); + await page.getByText('All about Carlos demo event').click(); + await page.getByRole('cell', { name: 'First test event' }).click(); + await page.getByRole('cell', { name: 'Second test event' }).click(); + await page.getByRole('cell', { name: 'Third test event' }).click(); + await page.getByRole('cell', { name: '+10 min' }).click(); + await page.getByRole('cell', { name: 'Lunch' }).click(); + const downloadPromise = page.waitForEvent('download'); + await page.getByTestId('cuesheet').getByText('CSV').click(); + + // From here we test the CSV download feature + + function validateCSV(contents) { + // We should try to keep this in sync with the implementation over at cuesheetUtils.ts + const expectedHeader = ['All about Carlos demo event', 'www.getontime.no']; + const expectedColumns = [ + 'Time Start', + 'Time End', + 'Event Title', + 'Presenter Name', + 'Event Subtitle', + 'Public', + 'Note', + 'Colour', + 'End Action', + 'Timer Type', + 'Skip', + 'user0', + 'user1', + 'user2', + 'user3', + 'user4', + 'user5', + 'user6', + 'user7', + 'user8', + 'user9', + ]; + const expectedValues = ['First test event', 'Second test event', 'Third test event', 'Lunch']; + + const allExpected = [...expectedHeader, ...expectedColumns, ...expectedValues]; + return allExpected.every((value) => contents.includes(value)); + } + + const download = await downloadPromise; + const contents = await fs.promises.readFile(await download.path(), 'utf-8'); + expect(contents).toContain('All about Carlos demo event'); + expect(validateCSV(contents)).toBe(true); +}); diff --git a/package.json b/package.json index 964cbdc7b..df56270ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ontime", - "version": "2.0.2", + "version": "2.0.9", "description": "Time keeping for live events", "keywords": [ "lighdev", diff --git a/packages/types/src/definitions/core/OntimeEvent.type.ts b/packages/types/src/definitions/core/OntimeEvent.type.ts index 8b0342b1a..a5f4e8b79 100644 --- a/packages/types/src/definitions/core/OntimeEvent.type.ts +++ b/packages/types/src/definitions/core/OntimeEvent.type.ts @@ -30,8 +30,8 @@ export type OntimeEvent = OntimeBaseEvent & { subtitle: string; presenter: string; note: string; - endAction: EndAction, - timerType: TimerType, + endAction: EndAction; + timerType: TimerType; timeStart: number; timeEnd: number; duration: number; @@ -49,4 +49,5 @@ export type OntimeEvent = OntimeBaseEvent & { user8: string; user9: string; revision: number; + delay?: number; // calculated at runtime }; diff --git a/packages/types/src/definitions/core/Rundown.type.ts b/packages/types/src/definitions/core/Rundown.type.ts index 8f018b2d2..9a4890e50 100644 --- a/packages/types/src/definitions/core/Rundown.type.ts +++ b/packages/types/src/definitions/core/Rundown.type.ts @@ -1,4 +1,7 @@ -import { OntimeBlock, OntimeDelay, OntimeEvent } from './OntimeEvent.type'; +import { OntimeBlock, OntimeDelay, OntimeEvent } from './OntimeEvent.type.js'; export type OntimeRundownEntry = OntimeDelay | OntimeBlock | OntimeEvent; export type OntimeRundown = OntimeRundownEntry[]; + +// we need to create a manual union type since keys cannot be used in type unions +export type OntimeEntryCommonKeys = keyof OntimeEvent | keyof OntimeDelay | keyof OntimeBlock; diff --git a/packages/types/src/definitions/runtime/Logger.type.ts b/packages/types/src/definitions/runtime/Logger.type.ts index 1ff25e82f..0a903f97f 100644 --- a/packages/types/src/definitions/runtime/Logger.type.ts +++ b/packages/types/src/definitions/runtime/Logger.type.ts @@ -16,3 +16,12 @@ export type LogMessage = { type: 'ontime-log'; payload: Log; }; + +export enum LogOrigin { + Client = 'CLIENT', + Playback = 'PLAYBACK', + Rx = 'RX', + Server = 'SERVER', + Tx = 'TX', + User = 'USER' +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 302a3fe92..8dd8526c4 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -10,11 +10,11 @@ import { OntimeEvent, SupportedEvent, } from './definitions/core/OntimeEvent.type.js'; -import { OntimeRundown, OntimeRundownEntry } from './definitions/core/Rundown.type.js'; +import { OntimeEntryCommonKeys, OntimeRundown, OntimeRundownEntry } from './definitions/core/Rundown.type.js'; import { OSCSettings, OscSubscription, OscSubscriptionOptions } from './definitions/core/OscSettings.type.js'; import { Playback } from './definitions/runtime/Playback.type.js'; import { Loaded } from './definitions/runtime/Playlist.type.js'; -import { Log, LogLevel, LogMessage } from './definitions/runtime/Logger.type.js'; +import { Log, LogLevel, LogMessage, LogOrigin } from './definitions/runtime/Logger.type.js'; import { RuntimeStore } from './definitions/runtime/RuntimeStore.type.js'; import { Settings } from './definitions/core/Settings.type.js'; import { TimerLifeCycle } from './definitions/core/TimerLifecycle.type.js'; @@ -32,7 +32,7 @@ export { TimerType }; export { EndAction }; export { SupportedEvent }; export type { OntimeBaseEvent, OntimeBlock, OntimeDelay, OntimeEvent }; -export type { OntimeRundown, OntimeRundownEntry }; +export type { OntimeEntryCommonKeys, OntimeRundown, OntimeRundownEntry }; // ---> Event export type { EventData }; @@ -57,6 +57,7 @@ export type { OscSubscription, OSCSettings, OscSubscriptionOptions }; // SERVER RUNTIME export { LogLevel }; export type { Log, LogMessage }; +export { LogOrigin }; export { Playback }; export { TimerLifeCycle }; diff --git a/packages/utils/index.ts b/packages/utils/index.ts index 323704a96..6fceea01a 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -3,3 +3,4 @@ export { formatFromMillis } from './src/date-utils/formatFromMillis.js'; export { isTimeString } from './src/date-utils/isTimeString.js'; export { millisToString } from './src/date-utils/millisToString.js'; export { generateId } from './src/generate-id/generateId.js'; +export { validatePlayback } from './src/validate-action/validatePlayback.js'; diff --git a/packages/utils/package.json b/packages/utils/package.json index f2e3b63d9..71dd461c5 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -2,7 +2,7 @@ "name": "ontime-utils", "type": "module", "exports": "./index.ts", - "version": "2.0.2", + "version": "2.0.9", "private": true, "description": "shared logic for ontime", "scripts": { @@ -23,6 +23,7 @@ "eslint-config-prettier": "^8.6.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-simple-import-sort": "^8.0.0", + "ontime-types": "workspace:*", "prettier": "^2.8.3", "typescript": "^4.9.4", "vitest": "^0.30.1" diff --git a/packages/utils/src/date-utils/millisToString.ts b/packages/utils/src/date-utils/millisToString.ts index 7820eba17..0a35a0dd8 100644 --- a/packages/utils/src/date-utils/millisToString.ts +++ b/packages/utils/src/date-utils/millisToString.ts @@ -8,7 +8,7 @@ import { DateTime } from 'luxon'; * @returns {string} String representing time 00:12:02 */ export function millisToString(millis: number | null, showSeconds = true, fallback = '...') { - if (millis === null) { + if (millis == null) { return fallback; } diff --git a/packages/utils/src/validate-action/validatePlayback.ts b/packages/utils/src/validate-action/validatePlayback.ts new file mode 100644 index 000000000..6911c73ff --- /dev/null +++ b/packages/utils/src/validate-action/validatePlayback.ts @@ -0,0 +1,10 @@ +import { Playback } from 'ontime-types'; + +export function validatePlayback(currentPlayback: Playback) { + return { + start: currentPlayback !== Playback.Stop, + pause: currentPlayback === Playback.Play || currentPlayback === Playback.Roll, + roll: true, + stop: currentPlayback !== Playback.Stop, + }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a98f14cc8..26c69ec68 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,7 +30,7 @@ importers: apps/client: specifiers: - '@chakra-ui/react': ^2.5.5 + '@chakra-ui/react': ^2.7.0 '@dnd-kit/core': ^6.0.8 '@dnd-kit/sortable': ^7.0.2 '@dnd-kit/utilities': ^3.2.1 @@ -43,19 +43,19 @@ importers: '@tanstack/eslint-plugin-query': ^4.26.2 '@tanstack/react-query': ^4.28.0 '@tanstack/react-query-devtools': ^4.29.0 + '@tanstack/react-table': ^8.9.2 '@testing-library/jest-dom': ^5.16.5 '@testing-library/react': ^13.1.1 '@testing-library/user-event': ^14.1.1 '@types/color': ^3.0.3 '@types/luxon': ^3.2.0 - '@types/prop-types': ^15.7.5 '@types/react': ^18.0.26 '@types/react-dom': ^18.0.10 '@types/testing-library__jest-dom': ^5.14.5 '@typescript-eslint/eslint-plugin': ^5.48.1 '@typescript-eslint/parser': ^5.48.1 '@vitejs/plugin-react': ^3.0.1 - autosize: ^5.0.2 + autosize: ^6.0.1 axios: ^1.2.0 color: ^4.2.3 csv-stringify: ^6.2.3 @@ -73,7 +73,6 @@ importers: ontime-types: workspace:* ontime-utils: workspace:* prettier: ^2.8.3 - prop-types: ^15.8.1 react: ^18.2.0 react-colorful: ^5.6.1 react-dom: ^18.2.0 @@ -81,11 +80,7 @@ importers: react-hook-form: ^7.43.5 react-qr-code: ^2.0.11 react-router-dom: ^6.3.0 - react-table: ^7.7.0 sass: ^1.57.1 - stylelint: ^14.16.1 - stylelint-config-prettier: ^9.0.4 - stylelint-config-standard-scss: ^6.1.0 typeface-open-sans: ^1.1.13 typescript: ^4.9.4 vite: ^4.3.1 @@ -96,7 +91,7 @@ importers: web-vitals: ^3.1.1 zustand: ^4.3.6 dependencies: - '@chakra-ui/react': 2.5.5_tlyz7qwuzzubgapow55lw5vriq + '@chakra-ui/react': 2.7.0_tlyz7qwuzzubgapow55lw5vriq '@dnd-kit/core': 6.0.8_biqbaboplfbrettd7655fr4n2y '@dnd-kit/sortable': 7.0.2_52scne4zmdeyjh2otzkgz2xfvu '@dnd-kit/utilities': 3.2.1_react@18.2.0 @@ -107,7 +102,8 @@ importers: '@sentry/tracing': 7.46.0 '@tanstack/react-query': 4.28.0_biqbaboplfbrettd7655fr4n2y '@tanstack/react-query-devtools': 4.29.0_q4teel2yjbizrm4naiaqcdpjum - autosize: 5.0.2 + '@tanstack/react-table': 8.9.2_biqbaboplfbrettd7655fr4n2y + autosize: 6.0.1 axios: 1.2.2 color: 4.2.3 csv-stringify: 6.2.3 @@ -120,7 +116,6 @@ importers: react-hook-form: 7.43.5_react@18.2.0 react-qr-code: 2.0.11_react@18.2.0 react-router-dom: 6.6.2_biqbaboplfbrettd7655fr4n2y - react-table: 7.8.0_react@18.2.0 typeface-open-sans: 1.1.13 web-vitals: 3.1.1 zustand: 4.3.6_react@18.2.0 @@ -132,7 +127,6 @@ importers: '@testing-library/user-event': 14.4.3 '@types/color': 3.0.3 '@types/luxon': 3.2.0 - '@types/prop-types': 15.7.5 '@types/react': 18.0.26 '@types/react-dom': 18.0.10 '@types/testing-library__jest-dom': 5.14.5 @@ -151,11 +145,7 @@ importers: ontime-types: link:../../packages/types ontime-utils: link:../../packages/utils prettier: 2.8.3 - prop-types: 15.8.1 sass: 1.57.1 - stylelint: 14.16.1 - stylelint-config-prettier: 9.0.4_stylelint@14.16.1 - stylelint-config-standard-scss: 6.1.0_stylelint@14.16.1 typescript: 4.9.4 vite: 4.3.1_sass@1.57.1 vite-plugin-compression2: 0.9.0 @@ -267,6 +257,7 @@ importers: eslint-plugin-simple-import-sort: ^8.0.0 luxon: ^3.3.0 nanoid: ^4.0.1 + ontime-types: workspace:* prettier: ^2.8.3 typescript: ^4.9.4 vitest: ^0.30.1 @@ -281,6 +272,7 @@ importers: eslint-config-prettier: 8.6.0_eslint@8.31.0 eslint-plugin-prettier: 4.2.1_do5yx3dogbskqc4h5x5ilvlwyy eslint-plugin-simple-import-sort: 8.0.0_eslint@8.31.0 + ontime-types: link:../types prettier: 2.8.3 typescript: 4.9.4 vitest: 0.30.1 @@ -495,6 +487,13 @@ packages: regenerator-runtime: 0.13.11 dev: false + /@babel/runtime/7.22.5: + resolution: {integrity: sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: false + /@babel/template/7.20.7: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} @@ -530,36 +529,36 @@ packages: '@babel/helper-validator-identifier': 7.19.1 to-fast-properties: 2.0.0 - /@chakra-ui/accordion/2.1.11_i6fhfa2wvtxv5b2jykryjj4lam: - resolution: {integrity: sha512-mfVPmqETp9pyRDHJ33AdF19oHv/LyxVzQJtlxUByuvs8Cj9QQZ2LQLg5kejm+b3mj03A7A6yfbuo3RNaI4Bhsg==} + /@chakra-ui/accordion/2.2.0_xdwvxhu5ub5hflmtgd6mbsauaa: + resolution: {integrity: sha512-2IK1iLzTZ22u8GKPPPn65mqJdZidn4AvkgAbv17ISdKA07VHJ8jSd4QF1T5iCXjKfZ0XaXozmhP4kDhjwF2IbQ==} peerDependencies: '@chakra-ui/system': '>=2.0.0' framer-motion: '>=4.0.0' react: '>=18' dependencies: '@chakra-ui/descendant': 3.0.14_react@18.2.0 - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-use-controllable-state': 2.0.8_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba '@chakra-ui/transition': 2.0.16_bdsblprzt47ebwyq2agncnzwpe framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y react: 18.2.0 dev: false - /@chakra-ui/alert/2.1.0_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/alert/2.1.0_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-OcfHwoXI5VrmM+tHJTHT62Bx6TfyfCxSa0PWUOueJzSyhlUOKBND5we6UtrOB7D0jwX45qKKEDJOLG5yCG21jQ==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/spinner': 2.0.13_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/spinner': 2.0.13_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -567,21 +566,21 @@ packages: resolution: {integrity: sha512-pKfOS/mztc4sUXHNc8ypJ1gPWSolWT770jrgVRfolVbYlki8y5Y+As996zMF6k5lewTu6j9DQequ7Cc9a69IVQ==} dev: false - /@chakra-ui/avatar/2.2.8_lze4h7kxffpjhokvtqbtrlfkmq: - resolution: {integrity: sha512-uBs9PMrqyK111tPIYIKnOM4n3mwgKqGpvYmtwBnnbQLTNLg4gtiWWVbpTuNMpyu1av0xQYomjUt8Doed8w6p8g==} + /@chakra-ui/avatar/2.2.11_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-CJFkoWvlCTDJTUBrKA/aVyG5Zz6TBEIVmmsJtqC6VcQuVDTxkWod8ruXnjb0LT2DUveL7xR5qZM9a5IXcsH3zg==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/image': 2.0.15_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/image': 2.0.16_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-children-utils': 2.0.6_react@18.2.0 '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/breadcrumb/2.1.5_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/breadcrumb/2.1.5_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-p3eQQrHQBkRB69xOmNyBJqEdfCrMt+e0eOH+Pm/DjFWfIVIbnIaFbmDCeWClqlLa21Ypc6h1hR9jEmvg8kmOog==} peerDependencies: '@chakra-ui/system': '>=2.0.0' @@ -590,7 +589,7 @@ packages: '@chakra-ui/react-children-utils': 2.0.6_react@18.2.0 '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -600,7 +599,7 @@ packages: '@chakra-ui/shared-utils': 2.0.5 dev: false - /@chakra-ui/button/2.0.18_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/button/2.0.18_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-E3c99+lOm6ou4nQVOTLkG+IdOPMjsQK+Qe7VyP8A/xeAMFONuibrWPRPpprr4ZkB4kEoLMfNuyH2+aEza3ScUA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' @@ -609,29 +608,29 @@ packages: '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/spinner': 2.0.13_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/spinner': 2.0.13_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/card/2.1.6_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/card/2.1.6_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-fFd/WAdRNVY/WOSQv4skpy0WeVhhI0f7dTY1Sm0jVl0KLmuP/GnpsWtKtqWjNcV00K963EXDyhlk6+9oxbP4gw==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/checkbox/2.2.14_lze4h7kxffpjhokvtqbtrlfkmq: - resolution: {integrity: sha512-uqo6lFWLqYBujPglrvRhTAErtuIXpmdpc5w0W4bjK7kyvLhxOpUh1hlDb2WoqlNpfRn/OaNeF6VinPnf9BJL8w==} + /@chakra-ui/checkbox/2.2.15_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-Ju2yQjX8azgFa5f6VLPuwdGYobZ+rdbcYqjiks848JvPc75UsPhpS05cb4XlrKT7M16I8txDA5rPJdqqFicHCA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/form-control': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/form-control': 2.0.18_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-types': 2.0.7_react@18.2.0 '@chakra-ui/react-use-callback-ref': 2.0.7_react@18.2.0 @@ -640,8 +639,8 @@ packages: '@chakra-ui/react-use-safe-layout-effect': 2.0.5_react@18.2.0 '@chakra-ui/react-use-update-effect': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba - '@chakra-ui/visually-hidden': 2.0.15_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/visually-hidden': 2.0.15_62ez5scglruzijw4rniqq4y54y '@zag-js/focus-visible': 0.2.2 react: 18.2.0 dev: false @@ -656,14 +655,14 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/close-button/2.0.17_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/close-button/2.0.17_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-05YPXk456t1Xa3KpqTrvm+7smx+95dmaPiwjiBN3p7LHUQVHJd8ZXSDB0V+WKi419k3cVQeJUdU/azDO2f40sw==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -676,13 +675,13 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/control-box/2.0.13_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/control-box/2.0.13_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-FEyrU4crxati80KUF/+1Z1CU3eZK6Sa0Yv7Z/ydtz9/tvGblXW9NFanoomXAOvcIFLbaLQPPATm9Gmpr7VG05A==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -697,8 +696,8 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/css-reset/2.1.1_3og6jmu6wvzuytygvdoxepq3x4: - resolution: {integrity: sha512-jwEOfIAWmQsnChHQTW/eRE+dfE4MjmhvSvoUug5nkV1pI7veC/20noFlIZxzi82EbiQI8Fs0+Jnusgxr2yaOHA==} + /@chakra-ui/css-reset/2.1.2_3og6jmu6wvzuytygvdoxepq3x4: + resolution: {integrity: sha512-4ySTLd+3iRpp4lX0yI9Yo2uQm2f+qwYGNOZF0cNcfN+4UJCd3IsaWxYRR/Anz+M51NVldZbYzC+TEYC/kpJc4A==} peerDependencies: '@emotion/react': '>=10.0.35' react: '>=18' @@ -717,12 +716,12 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/dom-utils/2.0.6: - resolution: {integrity: sha512-PVtDkPrDD5b8aoL6Atg7SLjkwhWb7BwMcLOF1L449L3nZN+DAO3nyAh6iUhZVJyunELj9d0r65CDlnMREyJZmA==} + /@chakra-ui/dom-utils/2.1.0: + resolution: {integrity: sha512-ZmF2qRa1QZ0CMLU8M1zCfmw29DmPNtfjR9iTo74U5FPr3i1aoAh7fbJ4qAlZ197Xw9eAW28tvzQuoVWeL5C7fQ==} dev: false - /@chakra-ui/editable/2.0.21_lze4h7kxffpjhokvtqbtrlfkmq: - resolution: {integrity: sha512-oYuXbHnggxSYJN7P9Pn0Scs9tPC91no4z1y58Oe+ILoJKZ+bFAEHtL7FEISDNJxw++MEukeFu7GU1hVqmdLsKQ==} + /@chakra-ui/editable/3.0.0_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-q/7C/TM3iLaoQKlEiM8AY565i9NoaXtS6N6N4HWIEL5mZJPbMeHKxrCHUZlHxYuQJqFOGc09ZPD9fAFx1GkYwQ==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' @@ -736,7 +735,7 @@ packages: '@chakra-ui/react-use-safe-layout-effect': 2.0.5_react@18.2.0 '@chakra-ui/react-use-update-effect': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -744,35 +743,35 @@ packages: resolution: {integrity: sha512-IGM/yGUHS+8TOQrZGpAKOJl/xGBrmRYJrmbHfUE7zrG3PpQyXvbLDP1M+RggkCFVgHlJi2wpYIf0QtQlU0XZfw==} dev: false - /@chakra-ui/focus-lock/2.0.16_kzbn2opkn2327fwg5yzwzya5o4: - resolution: {integrity: sha512-UuAdGCPVrCa1lecoAvpOQD7JFT7a9RdmhKWhFt5ioIcekSLJcerdLHuuL3w0qz//8kd1/SOt7oP0aJqdAJQrCw==} + /@chakra-ui/focus-lock/2.0.17_kzbn2opkn2327fwg5yzwzya5o4: + resolution: {integrity: sha512-V+m4Ml9E8QY66DUpHX/imInVvz5XJ5zx59Tl0aNancXgeVY1Rt/ZdxuZdPLCAmPC/MF3GUOgnEA+WU8i+VL6Gw==} peerDependencies: react: '>=18' dependencies: - '@chakra-ui/dom-utils': 2.0.6 + '@chakra-ui/dom-utils': 2.1.0 react: 18.2.0 react-focus-lock: 2.9.4_kzbn2opkn2327fwg5yzwzya5o4 transitivePeerDependencies: - '@types/react' dev: false - /@chakra-ui/form-control/2.0.18_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/form-control/2.0.18_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-I0a0jG01IAtRPccOXSNugyRdUAe8Dy40ctqedZvznMweOXzbMCF1m+sHPLdWeWC/VI13VoAispdPY0/zHOdjsQ==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-types': 2.0.7_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/hooks/2.1.6_react@18.2.0: - resolution: {integrity: sha512-oMSOeoOF6/UpwTVlDFHSROAA4hPY8WgJ0erdHs1ZkuwAwHv7UzjDkvrb6xYzAAH9qHoFzc5RIBm6jVoh3LCc+Q==} + /@chakra-ui/hooks/2.2.0_react@18.2.0: + resolution: {integrity: sha512-GZE64mcr20w+3KbCUPqQJHHmiFnX5Rcp8jS3YntGA4D5X2qU85jka7QkjfBwv/iduZ5Ei0YpCMYGCpi91dhD1Q==} peerDependencies: react: '>=18' dependencies: @@ -783,57 +782,57 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/icon/3.0.16_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/icon/3.0.16_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-RpA1X5Ptz8Mt39HSyEIW1wxAz2AXyf9H0JJ5HVx/dBdMZaGMDJ0HyyPBVci0m4RCoJuyG1HHG/DXJaVfUTVAeg==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/image/2.0.15_lze4h7kxffpjhokvtqbtrlfkmq: - resolution: {integrity: sha512-w2rElXtI3FHXuGpMCsSklus+pO1Pl2LWDwsCGdpBQUvGFbnHfl7MftQgTlaGHeD5OS95Pxva39hKrA2VklKHiQ==} + /@chakra-ui/image/2.0.16_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-iFypk1slgP3OK7VIPOtkB0UuiqVxNalgA59yoRM43xLIeZAEZpKngUVno4A2kFS61yKN0eIY4hXD3Xjm+25EJA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: '@chakra-ui/react-use-safe-layout-effect': 2.0.5_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/input/2.0.21_lze4h7kxffpjhokvtqbtrlfkmq: - resolution: {integrity: sha512-AIWjjg6MgcOtlvKmVoZfPPfgF+sBSWL3Zq2HSCAMvS6h7jfxz/Xv0UTFGPk5F4Wt0YHT7qMySg0Jsm0b78HZJg==} + /@chakra-ui/input/2.0.22_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-dCIC0/Q7mjZf17YqgoQsnXn0bus6vgriTRn8VmxOc+WcVl+KBSTBWujGrS5yu85WIFQ0aeqQvziDnDQybPqAbA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/form-control': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/object-utils': 2.0.8 + '@chakra-ui/form-control': 2.0.18_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/object-utils': 2.1.0 '@chakra-ui/react-children-utils': 2.0.6_react@18.2.0 '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/layout/2.1.18_lze4h7kxffpjhokvtqbtrlfkmq: - resolution: {integrity: sha512-F4Gh2e+DGdaWdWT5NZduIFD9NM7Bnuh8sXARFHWPvIu7yvAwZ3ddqC9GK4F3qUngdmkJxDLWQqRSwSh96Lxbhw==} + /@chakra-ui/layout/2.2.0_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-WvfsWQjqzbCxv7pbpPGVKxj9eQr7MC2i37ag4Wn7ClIG7uPuwHYTUWOnjnu27O3H/zA4cRVZ4Hs3GpSPbojZFQ==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: '@chakra-ui/breakpoint-utils': 2.0.8 - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/object-utils': 2.0.8 + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/object-utils': 2.1.0 '@chakra-ui/react-children-utils': 2.0.6_react@18.2.0 '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -849,7 +848,7 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/media-query/3.2.12_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/media-query/3.2.12_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-8pSLDf3oxxhFrhd40rs7vSeIBfvOmIKHA7DJlGUC/y+9irD24ZwgmCtFnn+y3gI47hTJsopbSX+wb8nr7XPswA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' @@ -858,12 +857,12 @@ packages: '@chakra-ui/breakpoint-utils': 2.0.8 '@chakra-ui/react-env': 3.0.0_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/menu/2.1.12_i6fhfa2wvtxv5b2jykryjj4lam: - resolution: {integrity: sha512-ylNK1VJlr/3/EGg9dLPZ87cBJJjeiYXeU/gOAphsKXMnByrXWhbp4YVnyyyha2KZ0zEw0aPU4nCZ+A69aT9wrg==} + /@chakra-ui/menu/2.1.15_xdwvxhu5ub5hflmtgd6mbsauaa: + resolution: {integrity: sha512-+1fh7KBKZyhy8wi7Q6nQAzrvjM6xggyhGMnSna0rt6FJVA2jlfkjb5FozyIVPnkfJKjkKd8THVhrs9E7pHNV/w==} peerDependencies: '@chakra-ui/system': '>=2.0.0' framer-motion: '>=4.0.0' @@ -872,58 +871,58 @@ packages: '@chakra-ui/clickable': 2.0.14_react@18.2.0 '@chakra-ui/descendant': 3.0.14_react@18.2.0 '@chakra-ui/lazy-utils': 2.0.5 - '@chakra-ui/popper': 3.0.13_react@18.2.0 + '@chakra-ui/popper': 3.0.14_react@18.2.0 '@chakra-ui/react-children-utils': 2.0.6_react@18.2.0 '@chakra-ui/react-context': 2.0.8_react@18.2.0 - '@chakra-ui/react-use-animation-state': 2.0.8_react@18.2.0 + '@chakra-ui/react-use-animation-state': 2.0.9_react@18.2.0 '@chakra-ui/react-use-controllable-state': 2.0.8_react@18.2.0 '@chakra-ui/react-use-disclosure': 2.0.8_react@18.2.0 - '@chakra-ui/react-use-focus-effect': 2.0.9_react@18.2.0 + '@chakra-ui/react-use-focus-effect': 2.0.11_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 - '@chakra-ui/react-use-outside-click': 2.0.7_react@18.2.0 + '@chakra-ui/react-use-outside-click': 2.1.0_react@18.2.0 '@chakra-ui/react-use-update-effect': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba '@chakra-ui/transition': 2.0.16_bdsblprzt47ebwyq2agncnzwpe framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y react: 18.2.0 dev: false - /@chakra-ui/modal/2.2.11_tmy6ru2c6di5zbchaoptqbokzi: - resolution: {integrity: sha512-2J0ZUV5tEzkPiawdkgPz6bmex7NXAde1VXooMwdvK+vuT8PV3U61yorTJOZVLdw7TjjI1Yo94mzsp6UwBud43Q==} + /@chakra-ui/modal/2.2.12_mifiypkmkwrvofebk2kkbeehoy: + resolution: {integrity: sha512-F1nNmYGvyqlmxidbwaBM3y57NhZ/Qeyc8BE9tb1FL1v9nxQhkfrPvMQ9miK0O1syPN6aZ5MMj+uD3AsRFE+/tA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' framer-motion: '>=4.0.0' react: '>=18' react-dom: '>=18' dependencies: - '@chakra-ui/close-button': 2.0.17_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/focus-lock': 2.0.16_kzbn2opkn2327fwg5yzwzya5o4 + '@chakra-ui/close-button': 2.0.17_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/focus-lock': 2.0.17_kzbn2opkn2327fwg5yzwzya5o4 '@chakra-ui/portal': 2.0.16_biqbaboplfbrettd7655fr4n2y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-types': 2.0.7_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba '@chakra-ui/transition': 2.0.16_bdsblprzt47ebwyq2agncnzwpe aria-hidden: 1.2.3 framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y react: 18.2.0 react-dom: 18.2.0_react@18.2.0 - react-remove-scroll: 2.5.5_kzbn2opkn2327fwg5yzwzya5o4 + react-remove-scroll: 2.5.6_kzbn2opkn2327fwg5yzwzya5o4 transitivePeerDependencies: - '@types/react' dev: false - /@chakra-ui/number-input/2.0.19_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/number-input/2.0.19_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-HDaITvtMEqOauOrCPsARDxKD9PSHmhWywpcyCSOX0lMe4xx2aaGhU0QQFhsJsykj8Er6pytMv6t0KZksdDv3YA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: '@chakra-ui/counter': 2.0.14_react@18.2.0 - '@chakra-ui/form-control': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/form-control': 2.0.18_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-types': 2.0.7_react@18.2.0 '@chakra-ui/react-use-callback-ref': 2.0.7_react@18.2.0 @@ -933,7 +932,7 @@ packages: '@chakra-ui/react-use-safe-layout-effect': 2.0.5_react@18.2.0 '@chakra-ui/react-use-update-effect': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -941,11 +940,11 @@ packages: resolution: {integrity: sha512-yOGxBjXNvLTBvQyhMDqGU0Oj26s91mbAlqKHiuw737AXHt0aPllOthVUqQMeaYLwLCjGMg0jtI7JReRzyi94Dg==} dev: false - /@chakra-ui/object-utils/2.0.8: - resolution: {integrity: sha512-2upjT2JgRuiupdrtBWklKBS6tqeGMA77Nh6Q0JaoQuH/8yq+15CGckqn3IUWkWoGI0Fg3bK9LDlbbD+9DLw95Q==} + /@chakra-ui/object-utils/2.1.0: + resolution: {integrity: sha512-tgIZOgLHaoti5PYGPTwK3t/cqtcycW0owaiOXoZOcpwwX/vlVb+H1jFsQyWiiwQVPt9RkoSLtxzXamx+aHH+bQ==} dev: false - /@chakra-ui/pin-input/2.0.20_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/pin-input/2.0.20_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-IHVmerrtHN8F+jRB3W1HnMir1S1TUCWhI7qDInxqPtoRffHt6mzZgLZ0izx8p1fD4HkW4c1d4/ZLEz9uH9bBRg==} peerDependencies: '@chakra-ui/system': '>=2.0.0' @@ -957,41 +956,41 @@ packages: '@chakra-ui/react-use-controllable-state': 2.0.8_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/popover/2.1.9_i6fhfa2wvtxv5b2jykryjj4lam: - resolution: {integrity: sha512-OMJ12VVs9N32tFaZSOqikkKPtwAVwXYsES/D1pff/amBrE3ngCrpxJSIp4uvTdORfIYDojJqrR52ZplDKS9hRQ==} + /@chakra-ui/popover/2.1.12_xdwvxhu5ub5hflmtgd6mbsauaa: + resolution: {integrity: sha512-Corh8trA1f3ydcMQqomgSvYNNhAlpxiBpMY2sglwYazOJcueHA8CI05cJVD0T/wwoTob7BShabhCGFZThn61Ng==} peerDependencies: '@chakra-ui/system': '>=2.0.0' framer-motion: '>=4.0.0' react: '>=18' dependencies: - '@chakra-ui/close-button': 2.0.17_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/close-button': 2.0.17_62ez5scglruzijw4rniqq4y54y '@chakra-ui/lazy-utils': 2.0.5 - '@chakra-ui/popper': 3.0.13_react@18.2.0 + '@chakra-ui/popper': 3.0.14_react@18.2.0 '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-types': 2.0.7_react@18.2.0 - '@chakra-ui/react-use-animation-state': 2.0.8_react@18.2.0 + '@chakra-ui/react-use-animation-state': 2.0.9_react@18.2.0 '@chakra-ui/react-use-disclosure': 2.0.8_react@18.2.0 - '@chakra-ui/react-use-focus-effect': 2.0.9_react@18.2.0 + '@chakra-ui/react-use-focus-effect': 2.0.11_react@18.2.0 '@chakra-ui/react-use-focus-on-pointer-down': 2.0.6_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y react: 18.2.0 dev: false - /@chakra-ui/popper/3.0.13_react@18.2.0: - resolution: {integrity: sha512-FwtmYz80Ju8oK3Z1HQfisUE7JIMmDsCQsRBu6XuJ3TFQnBHit73yjZmxKjuRJ4JgyT4WBnZoTF3ATbRKSagBeg==} + /@chakra-ui/popper/3.0.14_react@18.2.0: + resolution: {integrity: sha512-RDMmmSfjsmHJbVn2agDyoJpTbQK33fxx//njwJdeyM0zTG/3/4xjI/Cxru3acJ2Y+1jFGmPqhO81stFjnbtfIw==} peerDependencies: react: '>=18' dependencies: '@chakra-ui/react-types': 2.0.7_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 - '@popperjs/core': 2.11.6 + '@popperjs/core': 2.11.8 react: 18.2.0 dev: false @@ -1007,29 +1006,29 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false - /@chakra-ui/progress/2.1.6_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/progress/2.1.6_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-hHh5Ysv4z6bK+j2GJbi/FT9CVyto2PtNUNwBmr3oNMVsoOUMoRjczfXvvYqp0EHr9PCpxqrq7sRwgQXUzhbDSw==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: '@chakra-ui/react-context': 2.0.8_react@18.2.0 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/provider/2.2.2_fbxtuirhogpez7m7qjkm3itwca: - resolution: {integrity: sha512-UVwnIDnAWq1aKroN5AF+OpNpUqLVeIUk7tKvX3z4CY9FsPFFi6LTEhRHdhpwaU1Tau3Tf9agEu5URegpY7S8BA==} + /@chakra-ui/provider/2.3.0_fbxtuirhogpez7m7qjkm3itwca: + resolution: {integrity: sha512-vKgmjoLVS3NnHW8RSYwmhhda2ZTi3fQc1egkYSVwngGky4CsN15I+XDhxJitVd66H41cjah/UNJyoeq7ACseLA==} peerDependencies: '@emotion/react': ^11.0.0 '@emotion/styled': ^11.0.0 react: '>=18' react-dom: '>=18' dependencies: - '@chakra-ui/css-reset': 2.1.1_3og6jmu6wvzuytygvdoxepq3x4 + '@chakra-ui/css-reset': 2.1.2_3og6jmu6wvzuytygvdoxepq3x4 '@chakra-ui/portal': 2.0.16_biqbaboplfbrettd7655fr4n2y '@chakra-ui/react-env': 3.0.0_react@18.2.0 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba '@chakra-ui/utils': 2.0.15 '@emotion/react': 11.10.6_kzbn2opkn2327fwg5yzwzya5o4 '@emotion/styled': 11.10.6_qry7xzgsc55pr5ngbiorqn3fpa @@ -1037,18 +1036,18 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false - /@chakra-ui/radio/2.0.22_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/radio/2.0.22_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-GsQ5WAnLwivWl6gPk8P1x+tCcpVakCt5R5T0HumF7DGPXKdJbjS+RaFySrbETmyTJsKY4QrfXn+g8CWVrMjPjw==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/form-control': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/form-control': 2.0.18_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-types': 2.0.7_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba '@zag-js/focus-visible': 0.2.2 react: 18.2.0 dev: false @@ -1086,12 +1085,12 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/react-use-animation-state/2.0.8_react@18.2.0: - resolution: {integrity: sha512-xv9zSF2Rd1mHWQ+m5DLBWeh4atF8qrNvsOs3MNrvxKYBS3f79N3pqcQGrWAEvirXWXfiCeje2VAkEggqFRIo+Q==} + /@chakra-ui/react-use-animation-state/2.0.9_react@18.2.0: + resolution: {integrity: sha512-WFoD5OG03PBmzJCoRwM8rVfU442AvKBPPgA0yGGlKioH29OGuX7W78Ml+cYdXxonTiB03YSRZzUwaUnP4wAy1Q==} peerDependencies: react: '>=18' dependencies: - '@chakra-ui/dom-utils': 2.0.6 + '@chakra-ui/dom-utils': 2.1.0 '@chakra-ui/react-use-event-listener': 2.0.7_react@18.2.0 react: 18.2.0 dev: false @@ -1131,12 +1130,12 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/react-use-focus-effect/2.0.9_react@18.2.0: - resolution: {integrity: sha512-20nfNkpbVwyb41q9wxp8c4jmVp6TUGAPE3uFTDpiGcIOyPW5aecQtPmTXPMJH+2aa8Nu1wyoT1btxO+UYiQM3g==} + /@chakra-ui/react-use-focus-effect/2.0.11_react@18.2.0: + resolution: {integrity: sha512-/zadgjaCWD50TfuYsO1vDS2zSBs2p/l8P2DPEIA8FuaowbBubKrk9shKQDWmbfDU7KArGxPxrvo+VXvskPPjHw==} peerDependencies: react: '>=18' dependencies: - '@chakra-ui/dom-utils': 2.0.6 + '@chakra-ui/dom-utils': 2.1.0 '@chakra-ui/react-use-event-listener': 2.0.7_react@18.2.0 '@chakra-ui/react-use-safe-layout-effect': 2.0.5_react@18.2.0 '@chakra-ui/react-use-update-effect': 2.0.7_react@18.2.0 @@ -1177,8 +1176,8 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/react-use-outside-click/2.0.7_react@18.2.0: - resolution: {integrity: sha512-MsAuGLkwYNxNJ5rb8lYNvXApXxYMnJ3MzqBpQj1kh5qP/+JSla9XMjE/P94ub4fSEttmNSqs43SmPPrmPuihsQ==} + /@chakra-ui/react-use-outside-click/2.1.0_react@18.2.0: + resolution: {integrity: sha512-JanCo4QtWvMl9ZZUpKJKV62RlMWDFdPCE0Q64a7eWTOQgWWcpyBW7TOYRunQTqrK30FqkYFJCOlAWOtn+6Rw7A==} peerDependencies: react: '>=18' dependencies: @@ -1248,8 +1247,8 @@ packages: react: 18.2.0 dev: false - /@chakra-ui/react/2.5.5_tlyz7qwuzzubgapow55lw5vriq: - resolution: {integrity: sha512-aBVMUtdWv2MrptD/tKSqICPsuJ+I+jvauegffO1qPUDlK3RrXIDeOHkLGWohgXNcjY5bGVWguFEzJm97//0ooQ==} + /@chakra-ui/react/2.7.0_tlyz7qwuzzubgapow55lw5vriq: + resolution: {integrity: sha512-+FcUFQMsPfhWuM9Iu7uqufwwhmHN2IX6FWsBixYGOalO86dpgETsILMZP9PuWfgj7GpWiy2Dum6HXekh0Tk2Mg==} peerDependencies: '@emotion/react': ^11.0.0 '@emotion/styled': ^11.0.0 @@ -1257,57 +1256,58 @@ packages: react: '>=18' react-dom: '>=18' dependencies: - '@chakra-ui/accordion': 2.1.11_i6fhfa2wvtxv5b2jykryjj4lam - '@chakra-ui/alert': 2.1.0_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/avatar': 2.2.8_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/breadcrumb': 2.1.5_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/button': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/card': 2.1.6_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/checkbox': 2.2.14_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/close-button': 2.0.17_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/control-box': 2.0.13_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/accordion': 2.2.0_xdwvxhu5ub5hflmtgd6mbsauaa + '@chakra-ui/alert': 2.1.0_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/avatar': 2.2.11_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/breadcrumb': 2.1.5_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/button': 2.0.18_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/card': 2.1.6_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/checkbox': 2.2.15_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/close-button': 2.0.17_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/control-box': 2.0.13_62ez5scglruzijw4rniqq4y54y '@chakra-ui/counter': 2.0.14_react@18.2.0 - '@chakra-ui/css-reset': 2.1.1_3og6jmu6wvzuytygvdoxepq3x4 - '@chakra-ui/editable': 2.0.21_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/focus-lock': 2.0.16_kzbn2opkn2327fwg5yzwzya5o4 - '@chakra-ui/form-control': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/hooks': 2.1.6_react@18.2.0 - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/image': 2.0.15_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/input': 2.0.21_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/layout': 2.1.18_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/css-reset': 2.1.2_3og6jmu6wvzuytygvdoxepq3x4 + '@chakra-ui/editable': 3.0.0_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/focus-lock': 2.0.17_kzbn2opkn2327fwg5yzwzya5o4 + '@chakra-ui/form-control': 2.0.18_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/hooks': 2.2.0_react@18.2.0 + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/image': 2.0.16_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/input': 2.0.22_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/layout': 2.2.0_62ez5scglruzijw4rniqq4y54y '@chakra-ui/live-region': 2.0.13_react@18.2.0 - '@chakra-ui/media-query': 3.2.12_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/menu': 2.1.12_i6fhfa2wvtxv5b2jykryjj4lam - '@chakra-ui/modal': 2.2.11_tmy6ru2c6di5zbchaoptqbokzi - '@chakra-ui/number-input': 2.0.19_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/pin-input': 2.0.20_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/popover': 2.1.9_i6fhfa2wvtxv5b2jykryjj4lam - '@chakra-ui/popper': 3.0.13_react@18.2.0 + '@chakra-ui/media-query': 3.2.12_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/menu': 2.1.15_xdwvxhu5ub5hflmtgd6mbsauaa + '@chakra-ui/modal': 2.2.12_mifiypkmkwrvofebk2kkbeehoy + '@chakra-ui/number-input': 2.0.19_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/pin-input': 2.0.20_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/popover': 2.1.12_xdwvxhu5ub5hflmtgd6mbsauaa + '@chakra-ui/popper': 3.0.14_react@18.2.0 '@chakra-ui/portal': 2.0.16_biqbaboplfbrettd7655fr4n2y - '@chakra-ui/progress': 2.1.6_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/provider': 2.2.2_fbxtuirhogpez7m7qjkm3itwca - '@chakra-ui/radio': 2.0.22_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/progress': 2.1.6_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/provider': 2.3.0_fbxtuirhogpez7m7qjkm3itwca + '@chakra-ui/radio': 2.0.22_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-env': 3.0.0_react@18.2.0 - '@chakra-ui/select': 2.0.19_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/skeleton': 2.0.24_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/slider': 2.0.23_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/spinner': 2.0.13_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/stat': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/styled-system': 2.8.0 - '@chakra-ui/switch': 2.0.26_i6fhfa2wvtxv5b2jykryjj4lam - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba - '@chakra-ui/table': 2.0.17_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/tabs': 2.1.9_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/tag': 3.0.0_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/textarea': 2.0.19_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/theme': 3.0.1_wv7sq5bj4kx5i3evdevscgumbi - '@chakra-ui/theme-utils': 2.0.15 - '@chakra-ui/toast': 6.1.1_dsh6aqeljrnpc2ytvot4skb6iy - '@chakra-ui/tooltip': 2.2.7_dsh6aqeljrnpc2ytvot4skb6iy + '@chakra-ui/select': 2.0.19_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/skeleton': 2.0.24_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/slider': 2.0.25_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/spinner': 2.0.13_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/stat': 2.0.18_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/stepper': 2.2.0_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/styled-system': 2.9.1 + '@chakra-ui/switch': 2.0.27_xdwvxhu5ub5hflmtgd6mbsauaa + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/table': 2.0.17_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/tabs': 2.1.9_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/tag': 3.0.0_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/textarea': 2.0.19_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/theme': 3.1.2_hq32mhfiotloi5hecuixt2e454 + '@chakra-ui/theme-utils': 2.0.18 + '@chakra-ui/toast': 6.1.4_mqgjs6i23b3kxqr2rvhzy7z5lq + '@chakra-ui/tooltip': 2.2.9_mqgjs6i23b3kxqr2rvhzy7z5lq '@chakra-ui/transition': 2.0.16_bdsblprzt47ebwyq2agncnzwpe '@chakra-ui/utils': 2.0.15 - '@chakra-ui/visually-hidden': 2.0.15_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/visually-hidden': 2.0.15_62ez5scglruzijw4rniqq4y54y '@emotion/react': 11.10.6_kzbn2opkn2327fwg5yzwzya5o4 '@emotion/styled': 11.10.6_qry7xzgsc55pr5ngbiorqn3fpa framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y @@ -1317,15 +1317,15 @@ packages: - '@types/react' dev: false - /@chakra-ui/select/2.0.19_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/select/2.0.19_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-eAlFh+JhwtJ17OrB6fO6gEAGOMH18ERNrXLqWbYLrs674Le7xuREgtuAYDoxUzvYXYYTTdOJtVbcHGriI3o6rA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/form-control': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/form-control': 2.0.18_62ez5scglruzijw4rniqq4y54y '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -1333,21 +1333,21 @@ packages: resolution: {integrity: sha512-4/Wur0FqDov7Y0nCXl7HbHzCg4aq86h+SXdoUeuCMD3dSj7dpsVnStLYhng1vxvlbUnLpdF4oz5Myt3i/a7N3Q==} dev: false - /@chakra-ui/skeleton/2.0.24_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/skeleton/2.0.24_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-1jXtVKcl/jpbrJlc/TyMsFyI651GTXY5ma30kWyTXoby2E+cxbV6OR8GB/NMZdGxbQBax8/VdtYVjI0n+OBqWA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/media-query': 3.2.12_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/media-query': 3.2.12_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-use-previous': 2.0.5_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/slider/2.0.23_lze4h7kxffpjhokvtqbtrlfkmq: - resolution: {integrity: sha512-/eyRUXLla+ZdBUPXpakE3SAS2JS8mIJR6qcUYiPVKSpRAi6tMyYeQijAXn2QC1AUVd2JrG8Pz+1Jy7Po3uA7cA==} + /@chakra-ui/slider/2.0.25_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-FnWSi0AIXP+9sHMCPboOKGqm902k8dJtsJ7tu3D0AcKkE62WtYLZ2sTqvwJxCfSl4KqVI1i571SrF9WadnnJ8w==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' @@ -1362,68 +1362,81 @@ packages: '@chakra-ui/react-use-pan-event': 2.0.9_react@18.2.0 '@chakra-ui/react-use-size': 2.0.10_react@18.2.0 '@chakra-ui/react-use-update-effect': 2.0.7_react@18.2.0 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/spinner/2.0.13_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/spinner/2.0.13_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-T1/aSkVpUIuiYyrjfn1+LsQEG7Onbi1UE9ccS/evgf61Dzy4GgTXQUnDuWFSgpV58owqirqOu6jn/9eCwDlzlg==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/stat/2.0.18_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/stat/2.0.18_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-wKyfBqhVlIs9bkSerUc6F9KJMw0yTIEKArW7dejWwzToCLPr47u+CtYO6jlJHV6lRvkhi4K4Qc6pyvtJxZ3VpA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/styled-system/2.8.0: - resolution: {integrity: sha512-bmRv/8ACJGGKGx84U1npiUddwdNifJ+/ETklGwooS5APM0ymwUtBYZpFxjYNJrqvVYpg3mVY6HhMyBVptLS7iA==} + /@chakra-ui/stepper/2.2.0_62ez5scglruzijw4rniqq4y54y: + resolution: {integrity: sha512-8ZLxV39oghSVtOUGK8dX8Z6sWVSQiKVmsK4c3OQDa8y2TvxP0VtFD0Z5U1xJlOjQMryZRWhGj9JBc3iQLukuGg==} + peerDependencies: + '@chakra-ui/system': '>=2.0.0' + react: '>=18' + dependencies: + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/react-context': 2.0.8_react@18.2.0 + '@chakra-ui/shared-utils': 2.0.5 + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba + react: 18.2.0 + dev: false + + /@chakra-ui/styled-system/2.9.1: + resolution: {integrity: sha512-jhYKBLxwOPi9/bQt9kqV3ELa/4CjmNNruTyXlPp5M0v0+pDMUngPp48mVLoskm9RKZGE0h1qpvj/jZ3K7c7t8w==} dependencies: '@chakra-ui/shared-utils': 2.0.5 - csstype: 3.1.1 + csstype: 3.1.2 lodash.mergewith: 4.6.2 dev: false - /@chakra-ui/switch/2.0.26_i6fhfa2wvtxv5b2jykryjj4lam: - resolution: {integrity: sha512-x62lF6VazSZJQuVxosChVR6+0lIJe8Pxgkl/C9vxjhp2yVYb3mew5tcX/sDOu0dYZy8ro/9hMfGkdN4r9xEU8A==} + /@chakra-ui/switch/2.0.27_xdwvxhu5ub5hflmtgd6mbsauaa: + resolution: {integrity: sha512-z76y2fxwMlvRBrC5W8xsZvo3gP+zAEbT3Nqy5P8uh/IPd5OvDsGeac90t5cgnQTyxMOpznUNNK+1eUZqtLxWnQ==} peerDependencies: '@chakra-ui/system': '>=2.0.0' framer-motion: '>=4.0.0' react: '>=18' dependencies: - '@chakra-ui/checkbox': 2.2.14_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/checkbox': 2.2.15_62ez5scglruzijw4rniqq4y54y '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y react: 18.2.0 dev: false - /@chakra-ui/system/2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba: - resolution: {integrity: sha512-52BIp/Zyvefgxn5RTByfkTeG4J+y81LWEjWm8jCaRFsLVm8IFgqIrngtcq4I7gD5n/UKbneHlb4eLHo4uc5yDQ==} + /@chakra-ui/system/2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba: + resolution: {integrity: sha512-Vy8UUaCxikOzOGE54IP8tKouvU38rEYU1HCSquU9+oe7Jd70HaiLa4vmUKvHyMUmxkOzDHIkgZLbVQCubSnN5w==} peerDependencies: '@emotion/react': ^11.0.0 '@emotion/styled': ^11.0.0 react: '>=18' dependencies: '@chakra-ui/color-mode': 2.1.12_react@18.2.0 - '@chakra-ui/object-utils': 2.0.8 + '@chakra-ui/object-utils': 2.1.0 '@chakra-ui/react-utils': 2.0.12_react@18.2.0 - '@chakra-ui/styled-system': 2.8.0 - '@chakra-ui/theme-utils': 2.0.15 + '@chakra-ui/styled-system': 2.9.1 + '@chakra-ui/theme-utils': 2.0.18 '@chakra-ui/utils': 2.0.15 '@emotion/react': 11.10.6_kzbn2opkn2327fwg5yzwzya5o4 '@emotion/styled': 11.10.6_qry7xzgsc55pr5ngbiorqn3fpa @@ -1431,7 +1444,7 @@ packages: react-fast-compare: 3.2.1 dev: false - /@chakra-ui/table/2.0.17_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/table/2.0.17_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-OScheTEp1LOYvTki2NFwnAYvac8siAhW9BI5RKm5f5ORL2gVJo4I72RUqE0aKe1oboxgm7CYt5afT5PS5cG61A==} peerDependencies: '@chakra-ui/system': '>=2.0.0' @@ -1439,11 +1452,11 @@ packages: dependencies: '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/tabs/2.1.9_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/tabs/2.1.9_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-Yf8e0kRvaGM6jfkJum0aInQ0U3ZlCafmrYYni2lqjcTtThqu+Yosmo3iYlnullXxCw5MVznfrkb9ySvgQowuYg==} peerDependencies: '@chakra-ui/system': '>=2.0.0' @@ -1458,104 +1471,105 @@ packages: '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/react-use-safe-layout-effect': 2.0.5_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/tag/3.0.0_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/tag/3.0.0_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-YWdMmw/1OWRwNkG9pX+wVtZio+B89odaPj6XeMn5nfNN8+jyhIEpouWv34+CO9G0m1lupJTxPSfgLAd7cqXZMA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/icon': 3.0.16_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/icon': 3.0.16_62ez5scglruzijw4rniqq4y54y '@chakra-ui/react-context': 2.0.8_react@18.2.0 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/textarea/2.0.19_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/textarea/2.0.19_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-adJk+qVGsFeJDvfn56CcJKKse8k7oMGlODrmpnpTdF+xvlsiTM+1GfaJvgNSpHHuQFdz/A0z1uJtfGefk0G2ZA==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/form-control': 2.0.18_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/form-control': 2.0.18_62ez5scglruzijw4rniqq4y54y '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false - /@chakra-ui/theme-tools/2.0.17_wv7sq5bj4kx5i3evdevscgumbi: - resolution: {integrity: sha512-Auu38hnihlJZQcPok6itRDBbwof3TpXGYtDPnOvrq4Xp7jnab36HLt7KEXSDPXbtOk3ZqU99pvI1en5LbDrdjg==} + /@chakra-ui/theme-tools/2.0.18_hq32mhfiotloi5hecuixt2e454: + resolution: {integrity: sha512-MbiRuXb2tb41FbnW41zhsYYAU0znlpfYZnu0mxCf8U2otCwPekJCfESUGYypjq4JnydQ7TDOk+Kz/Wi974l4mw==} peerDependencies: '@chakra-ui/styled-system': '>=2.0.0' dependencies: '@chakra-ui/anatomy': 2.1.2 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/styled-system': 2.8.0 - color2k: 2.0.1 + '@chakra-ui/styled-system': 2.9.1 + color2k: 2.0.2 dev: false - /@chakra-ui/theme-utils/2.0.15: - resolution: {integrity: sha512-UuxtEgE7gwMTGDXtUpTOI7F5X0iHB9ekEOG5PWPn2wWBL7rlk2JtPI7UP5Um5Yg6vvBfXYGK1ySahxqsgf+87g==} + /@chakra-ui/theme-utils/2.0.18: + resolution: {integrity: sha512-aSbkUUiFpc1NHC7lQdA6uYlr6EcZFXz6b4aJ7VRDpqTiywvqYnvfGzhmsB0z94vgtS9qXc6HoIwBp25jYGV2MA==} dependencies: '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/styled-system': 2.8.0 - '@chakra-ui/theme': 3.0.1_wv7sq5bj4kx5i3evdevscgumbi + '@chakra-ui/styled-system': 2.9.1 + '@chakra-ui/theme': 3.1.2_hq32mhfiotloi5hecuixt2e454 lodash.mergewith: 4.6.2 dev: false - /@chakra-ui/theme/3.0.1_wv7sq5bj4kx5i3evdevscgumbi: - resolution: {integrity: sha512-92kDm/Ux/51uJqhRKevQo/O/rdwucDYcpHg2QuwzdAxISCeYvgtl2TtgOOl5EnqEP0j3IEAvZHZUlv8TTbawaw==} + /@chakra-ui/theme/3.1.2_hq32mhfiotloi5hecuixt2e454: + resolution: {integrity: sha512-ebUXMS3LZw2OZxEQNYaFw3/XuA3jpyprhS/frjHMvZKSOaCjMW+c9z25S0jp1NnpQff08VGI8EWbyVZECXU1QA==} peerDependencies: - '@chakra-ui/styled-system': '>=2.0.0' + '@chakra-ui/styled-system': '>=2.8.0' dependencies: '@chakra-ui/anatomy': 2.1.2 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/styled-system': 2.8.0 - '@chakra-ui/theme-tools': 2.0.17_wv7sq5bj4kx5i3evdevscgumbi + '@chakra-ui/styled-system': 2.9.1 + '@chakra-ui/theme-tools': 2.0.18_hq32mhfiotloi5hecuixt2e454 dev: false - /@chakra-ui/toast/6.1.1_dsh6aqeljrnpc2ytvot4skb6iy: - resolution: {integrity: sha512-JtjIKkPVjEu8okGGCipCxNVgK/15h5AicTATZ6RbG2MsHmr4GfKG3fUCvpbuZseArqmLqGLQZQJjVE9vJzaSkQ==} + /@chakra-ui/toast/6.1.4_mqgjs6i23b3kxqr2rvhzy7z5lq: + resolution: {integrity: sha512-wAcPHq/N/ar4jQxkUGhnsbp+lx2eKOpHxn1KaWdHXUkqCNUA1z09fvBsoMyzObSiiwbDuQPZG5RxsOhzfPZX4Q==} peerDependencies: - '@chakra-ui/system': 2.5.5 + '@chakra-ui/system': 2.5.8 framer-motion: '>=4.0.0' react: '>=18' react-dom: '>=18' dependencies: - '@chakra-ui/alert': 2.1.0_lze4h7kxffpjhokvtqbtrlfkmq - '@chakra-ui/close-button': 2.0.17_lze4h7kxffpjhokvtqbtrlfkmq + '@chakra-ui/alert': 2.1.0_62ez5scglruzijw4rniqq4y54y + '@chakra-ui/close-button': 2.0.17_62ez5scglruzijw4rniqq4y54y '@chakra-ui/portal': 2.0.16_biqbaboplfbrettd7655fr4n2y '@chakra-ui/react-context': 2.0.8_react@18.2.0 '@chakra-ui/react-use-timeout': 2.0.5_react@18.2.0 '@chakra-ui/react-use-update-effect': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/styled-system': 2.8.0 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba - '@chakra-ui/theme': 3.0.1_wv7sq5bj4kx5i3evdevscgumbi + '@chakra-ui/styled-system': 2.9.1 + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/theme': 3.1.2_hq32mhfiotloi5hecuixt2e454 framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y react: 18.2.0 react-dom: 18.2.0_react@18.2.0 dev: false - /@chakra-ui/tooltip/2.2.7_dsh6aqeljrnpc2ytvot4skb6iy: - resolution: {integrity: sha512-ImUJ6NnVqARaYqpgtO+kzucDRmxo8AF3jMjARw0bx2LxUkKwgRCOEaaRK5p5dHc0Kr6t5/XqjDeUNa19/sLauA==} + /@chakra-ui/tooltip/2.2.9_mqgjs6i23b3kxqr2rvhzy7z5lq: + resolution: {integrity: sha512-ZoksllanqXRUyMDaiogvUVJ+RdFXwZrfrwx3RV22fejYZIQ602hZ3QHtHLB5ZnKFLbvXKMZKM23HxFTSb0Ytqg==} peerDependencies: '@chakra-ui/system': '>=2.0.0' framer-motion: '>=4.0.0' react: '>=18' react-dom: '>=18' dependencies: - '@chakra-ui/popper': 3.0.13_react@18.2.0 + '@chakra-ui/dom-utils': 2.1.0 + '@chakra-ui/popper': 3.0.14_react@18.2.0 '@chakra-ui/portal': 2.0.16_biqbaboplfbrettd7655fr4n2y '@chakra-ui/react-types': 2.0.7_react@18.2.0 '@chakra-ui/react-use-disclosure': 2.0.8_react@18.2.0 '@chakra-ui/react-use-event-listener': 2.0.7_react@18.2.0 '@chakra-ui/react-use-merge-refs': 2.0.7_react@18.2.0 '@chakra-ui/shared-utils': 2.0.5 - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba framer-motion: 10.11.2_biqbaboplfbrettd7655fr4n2y react: 18.2.0 react-dom: 18.2.0_react@18.2.0 @@ -1581,13 +1595,13 @@ packages: lodash.mergewith: 4.6.2 dev: false - /@chakra-ui/visually-hidden/2.0.15_lze4h7kxffpjhokvtqbtrlfkmq: + /@chakra-ui/visually-hidden/2.0.15_62ez5scglruzijw4rniqq4y54y: resolution: {integrity: sha512-WWULIiucYRBIewHKFA7BssQ2ABLHLVd9lrUo3N3SZgR0u4ZRDDVEUNOy+r+9ruDze8+36dGbN9wsN1IdELtdOw==} peerDependencies: '@chakra-ui/system': '>=2.0.0' react: '>=18' dependencies: - '@chakra-ui/system': 2.5.5_xqp3pgpqjlfxxa3zxu4zoc4fba + '@chakra-ui/system': 2.5.8_xqp3pgpqjlfxxa3zxu4zoc4fba react: 18.2.0 dev: false @@ -1598,17 +1612,6 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true - /@csstools/selector-specificity/2.0.2_wajs5nedgkikc5pcuwett7legi: - resolution: {integrity: sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==} - engines: {node: ^12 || ^14 || >=16} - peerDependencies: - postcss: ^8.2 - postcss-selector-parser: ^6.0.10 - dependencies: - postcss: 8.4.21 - postcss-selector-parser: 6.0.11 - dev: true - /@develar/schema-utils/2.6.5: resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==} engines: {node: '>= 8.9.0'} @@ -2178,8 +2181,8 @@ packages: fsevents: 2.3.2 dev: true - /@popperjs/core/2.11.6: - resolution: {integrity: sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==} + /@popperjs/core/2.11.8: + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} dev: false /@react-icons/all-files/4.1.0_react@18.2.0: @@ -2551,6 +2554,23 @@ packages: use-sync-external-store: 1.2.0_react@18.2.0 dev: false + /@tanstack/react-table/8.9.2_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-Irvw4wqVF9hhuYzmNrlae4IKdlmgSyoRWnApSLebvYzqHoi5tEsYzBj6YPd0hX78aB/L+4w/jgK2eBQVpGfThQ==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + dependencies: + '@tanstack/table-core': 8.9.2 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + + /@tanstack/table-core/8.9.2: + resolution: {integrity: sha512-ajc0OF+karBAdaSz7OK09rCoAHB1XI1+wEhu+tDNMPc+XcO+dTlXXN/Vc0a8vym4kElvEjXEDd9c8Zfgt4bekA==} + engines: {node: '>=12'} + dev: false + /@testing-library/dom/8.19.1: resolution: {integrity: sha512-P6iIPyYQ+qH8CvGauAqanhVnjrnRe0IZFSYCeGkSRW9q3u8bdVn2NPI+lasFyVsEQn1J/IFmp5Aax41+dAP9wg==} engines: {node: '>=12'} @@ -2776,10 +2796,6 @@ packages: dev: true optional: true - /@types/minimist/1.2.2: - resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} - dev: true - /@types/ms/0.7.31: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} dev: true @@ -2808,10 +2824,6 @@ packages: resolution: {integrity: sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==} dev: true - /@types/normalize-package-data/2.4.1: - resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} - dev: true - /@types/parse-json/4.0.0: resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} @@ -3317,15 +3329,6 @@ packages: uri-js: 4.4.1 dev: true - /ajv/8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -3411,7 +3414,7 @@ packages: resolution: {integrity: sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==} engines: {node: '>=10'} dependencies: - tslib: 2.5.0 + tslib: 2.5.3 dev: false /aria-query/5.1.3: @@ -3460,11 +3463,6 @@ packages: get-intrinsic: 1.1.3 dev: true - /arrify/1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - dev: true - /asar/3.2.0: resolution: {integrity: sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==} engines: {node: '>=10.12.0'} @@ -3494,6 +3492,7 @@ packages: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} dev: true + optional: true /async-exit-hook/2.0.1: resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==} @@ -3512,8 +3511,8 @@ packages: engines: {node: '>= 4.0.0'} dev: true - /autosize/5.0.2: - resolution: {integrity: sha512-FPVt5ynkqUAA9gcMZnJHka1XfQgr1WNd/yRfIjmj5WGmjua+u5Hl9hn8M2nU5CNy2bEIcj1ZUwXq7IOHsfZG9w==} + /autosize/6.0.1: + resolution: {integrity: sha512-f86EjiUKE6Xvczc4ioP1JBlWG7FKrE13qe/DxBCpe8GCipCq2nFw73aO8QEBKHfSbYGDN5eB9jXWKen7tspDqQ==} dev: false /available-typed-arrays/1.0.5: @@ -3544,10 +3543,6 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true - /balanced-match/2.0.0: - resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} - dev: true - /base64-js/1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} requiresBuild: true @@ -3747,20 +3742,6 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - /camelcase-keys/6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - dev: true - - /camelcase/5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - /camelcase/6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -3910,14 +3891,10 @@ packages: color-string: 1.9.1 dev: false - /color2k/2.0.1: - resolution: {integrity: sha512-iCg+xrEqtYISsSJZN1z44fyhv4EfX8lSkcDhodt6VnMf1+iMwZxAtmGXchTCeMUnTbXunGvUVK6E3skkApPnZw==} + /color2k/2.0.2: + resolution: {integrity: sha512-kJhwH5nAwb34tmyuqq/lgjEKzlFXn1U99NlnB6Ws4qVaERcRUYeYP1cBw6BJ4vxaWStAUEef4WMr7WjOCnBt8w==} dev: false - /colord/2.9.3: - resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - dev: true - /colors/1.0.3: resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==} engines: {node: '>=0.1.90'} @@ -4088,21 +4065,10 @@ packages: tiny-invariant: 1.3.1 dev: false - /css-functions-list/3.1.0: - resolution: {integrity: sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==} - engines: {node: '>=12.22'} - dev: true - /css.escape/1.5.1: resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} dev: true - /cssesc/3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true - /cssom/0.3.8: resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} dev: true @@ -4121,6 +4087,10 @@ packages: /csstype/3.1.1: resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} + /csstype/3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + dev: false + /csv-stringify/6.2.3: resolution: {integrity: sha512-4qGjUMwnlaRc00gc2jrIYh2w/h1fo25B0mTuY9K8fBiIgtmCX3LcgUbrEGViL98Ci4Se/F5LFEtu8k+dItJVZQ==} dev: false @@ -4175,19 +4145,6 @@ packages: ms: 2.1.2 dev: true - /decamelize-keys/1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - dev: true - - /decamelize/1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} - dev: true - /decimal.js/10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} dev: true @@ -5038,11 +4995,6 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true - /fastest-levenshtein/1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - dev: true - /fastq/1.15.0: resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} dependencies: @@ -5094,14 +5046,6 @@ packages: resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} dev: false - /find-up/4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - /find-up/5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -5126,7 +5070,7 @@ packages: resolution: {integrity: sha512-KSuV3ur4gf2KqMNoZx3nXNVhqCkn42GuTYCX4tXPEwf0MjpFQmNMiN6m7dXaUXgIoivL6/65agoUMg4RLS0Vbg==} engines: {node: '>=10'} dependencies: - tslib: 2.5.0 + tslib: 2.5.3 dev: false /follow-redirects/1.15.2: @@ -5344,22 +5288,6 @@ packages: dev: true optional: true - /global-modules/2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} - dependencies: - global-prefix: 3.0.0 - dev: true - - /global-prefix/3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - dev: true - /globals/11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -5391,10 +5319,6 @@ packages: slash: 3.0.0 dev: true - /globjoin/0.1.4: - resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} - dev: true - /globrex/0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} dev: true @@ -5434,11 +5358,6 @@ packages: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} dev: true - /hard-rejection/2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - dev: true - /has-bigints/1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -5486,10 +5405,6 @@ packages: react-is: 16.13.1 dev: false - /hosted-git-info/2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - dev: true - /hosted-git-info/4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} @@ -5504,11 +5419,6 @@ packages: whatwg-encoding: 2.0.0 dev: true - /html-tags/3.2.0: - resolution: {integrity: sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==} - engines: {node: '>=8'} - dev: true - /http-cache-semantics/4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} dev: true @@ -5604,11 +5514,6 @@ packages: parent-module: 1.0.1 resolve-from: 4.0.0 - /import-lazy/4.0.0: - resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} - engines: {node: '>=8'} - dev: true - /imurmurhash/0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -5629,10 +5534,6 @@ packages: /inherits/2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - /ini/1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: true - /internal-slot/1.0.4: resolution: {integrity: sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==} engines: {node: '>= 0.4'} @@ -5769,16 +5670,6 @@ packages: engines: {node: '>=8'} dev: true - /is-plain-obj/1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - dev: true - - /is-plain-object/5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} - engines: {node: '>=0.10.0'} - dev: true - /is-potential-custom-element-name/1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true @@ -6012,10 +5903,6 @@ packages: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true - /json-schema-traverse/1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - /json-stable-stringify-without-jsonify/1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true @@ -6063,15 +5950,6 @@ packages: json-buffer: 3.0.1 dev: true - /kind-of/6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /known-css-properties/0.26.0: - resolution: {integrity: sha512-5FZRzrZzNTBruuurWpvZnvP9pum+fe0HcK8z/ooo+U+Hmp4vtbyp1/QDsqmufirXy4egGzbaH/y2uCZf+6W5Kg==} - dev: true - /lazy-val/1.0.5: resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==} dev: true @@ -6100,13 +5978,6 @@ packages: engines: {node: '>=14'} dev: true - /locate-path/5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - /locate-path/6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -6122,10 +5993,6 @@ packages: resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} dev: false - /lodash.truncate/4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true - /lodash/4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -6198,16 +6065,6 @@ packages: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true - /map-obj/1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - dev: true - - /map-obj/4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - dev: true - /matcher/3.0.0: resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} engines: {node: '>=10'} @@ -6216,10 +6073,6 @@ packages: dev: true optional: true - /mathml-tag-names/2.1.3: - resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} - dev: true - /md5-hex/3.0.1: resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==} engines: {node: '>=8'} @@ -6232,24 +6085,6 @@ packages: engines: {node: '>= 0.6'} dev: false - /meow/9.0.0: - resolution: {integrity: sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==} - engines: {node: '>=10'} - dependencies: - '@types/minimist': 1.2.2 - camelcase-keys: 6.2.2 - decamelize: 1.2.0 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 3.0.3 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.18.1 - yargs-parser: 20.2.9 - dev: true - /merge-descriptors/1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} dev: false @@ -6328,15 +6163,6 @@ packages: brace-expansion: 2.0.1 dev: true - /minimist-options/4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - dev: true - /minimist/1.2.7: resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} @@ -6493,25 +6319,6 @@ packages: abbrev: 1.1.1 dev: true - /normalize-package-data/2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.1 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 - dev: true - - /normalize-package-data/3.0.3: - resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} - engines: {node: '>=10'} - dependencies: - hosted-git-info: 4.1.0 - is-core-module: 2.11.0 - semver: 7.3.8 - validate-npm-package-license: 3.0.4 - dev: true - /normalize-path/3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -6644,13 +6451,6 @@ packages: engines: {node: '>=8'} dev: true - /p-limit/2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - /p-limit/3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -6665,13 +6465,6 @@ packages: yocto-queue: 1.0.0 dev: true - /p-locate/4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - /p-locate/5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} @@ -6679,11 +6472,6 @@ packages: p-limit: 3.1.0 dev: true - /p-try/2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - /parent-module/1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -6804,42 +6592,6 @@ packages: xmlbuilder: 15.1.1 dev: true - /postcss-media-query-parser/0.2.3: - resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} - dev: true - - /postcss-resolve-nested-selector/0.1.1: - resolution: {integrity: sha512-HvExULSwLqHLgUy1rl3ANIqCsvMS0WHss2UOsXhXnQaZ9VCc2oBvIpXrl00IUFT5ZDITME0o6oiXeiHr2SAIfw==} - dev: true - - /postcss-safe-parser/6.0.0_postcss@8.4.21: - resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.3.3 - dependencies: - postcss: 8.4.21 - dev: true - - /postcss-scss/4.0.6: - resolution: {integrity: sha512-rLDPhJY4z/i4nVFZ27j9GqLxj1pwxE80eAzUNRMXtcpipFYIeowerzBgG3yJhMtObGEXidtIgbUpQ3eLDsf5OQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.4.19 - dev: true - - /postcss-selector-parser/6.0.11: - resolution: {integrity: sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: true - - /postcss-value-parser/4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true - /postcss/8.4.21: resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} engines: {node: ^10 || ^12 || >=14} @@ -6968,11 +6720,6 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true - /quick-lru/4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - dev: true - /quick-lru/5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -7003,7 +6750,7 @@ packages: peerDependencies: react: ^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 dependencies: - '@babel/runtime': 7.21.0 + '@babel/runtime': 7.22.5 react: 18.2.0 dev: false @@ -7043,7 +6790,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.21.0 + '@babel/runtime': 7.22.5 '@types/react': 18.0.26 focus-lock: 0.11.6 prop-types: 15.8.1 @@ -7105,11 +6852,11 @@ packages: '@types/react': 18.0.26 react: 18.2.0 react-style-singleton: 2.2.1_kzbn2opkn2327fwg5yzwzya5o4 - tslib: 2.5.0 + tslib: 2.5.3 dev: false - /react-remove-scroll/2.5.5_kzbn2opkn2327fwg5yzwzya5o4: - resolution: {integrity: sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw==} + /react-remove-scroll/2.5.6_kzbn2opkn2327fwg5yzwzya5o4: + resolution: {integrity: sha512-bO856ad1uDYLefgArk559IzUNeQ6SWH4QnrevIUjH+GczV56giDfl3h0Idptf2oIKxQmd1p9BN25jleKodTALg==} engines: {node: '>=10'} peerDependencies: '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -7122,7 +6869,7 @@ packages: react: 18.2.0 react-remove-scroll-bar: 2.3.4_kzbn2opkn2327fwg5yzwzya5o4 react-style-singleton: 2.2.1_kzbn2opkn2327fwg5yzwzya5o4 - tslib: 2.5.0 + tslib: 2.5.3 use-callback-ref: 1.3.0_kzbn2opkn2327fwg5yzwzya5o4 use-sidecar: 1.1.2_kzbn2opkn2327fwg5yzwzya5o4 dev: false @@ -7164,15 +6911,7 @@ packages: get-nonce: 1.0.1 invariant: 2.2.4 react: 18.2.0 - tslib: 2.5.0 - dev: false - - /react-table/7.8.0_react@18.2.0: - resolution: {integrity: sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==} - peerDependencies: - react: ^16.8.3 || ^17.0.0-0 || ^18.0.0 - dependencies: - react: 18.2.0 + tslib: 2.5.3 dev: false /react/18.2.0: @@ -7192,25 +6931,6 @@ packages: lazy-val: 1.0.5 dev: true - /read-pkg-up/7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - dev: true - - /read-pkg/5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - dependencies: - '@types/normalize-package-data': 2.4.1 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - dev: true - /readable-stream/2.3.7: resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} dependencies: @@ -7271,11 +6991,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /require-from-string/2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - /requires-port/1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: true @@ -7288,11 +7003,6 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - /resolve-from/5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - /resolve/1.22.1: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} hasBin: true @@ -7521,10 +7231,6 @@ packages: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} dev: true - /signal-exit/3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - /simple-swizzle/0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} dependencies: @@ -7554,15 +7260,6 @@ packages: dev: true optional: true - /slice-ansi/4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - /smart-buffer/4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -7593,28 +7290,6 @@ packages: requiresBuild: true dev: true - /spdx-correct/3.1.1: - resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.12 - dev: true - - /spdx-exceptions/2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - dev: true - - /spdx-expression-parse/3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.12 - dev: true - - /spdx-license-ids/3.0.12: - resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} - dev: true - /sprintf-js/1.1.2: resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} dev: true @@ -7738,126 +7413,6 @@ packages: acorn: 8.8.2 dev: true - /style-search/0.1.0: - resolution: {integrity: sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==} - dev: true - - /stylelint-config-prettier/9.0.4_stylelint@14.16.1: - resolution: {integrity: sha512-38nIGTGpFOiK5LjJ8Ma1yUgpKENxoKSOhbDNSemY7Ep0VsJoXIW9Iq/2hSt699oB9tReynfWicTAoIHiq8Rvbg==} - engines: {node: '>= 12'} - hasBin: true - peerDependencies: - stylelint: '>=11.0.0' - dependencies: - stylelint: 14.16.1 - dev: true - - /stylelint-config-recommended-scss/8.0.0_stylelint@14.16.1: - resolution: {integrity: sha512-BxjxEzRaZoQb7Iinc3p92GS6zRdRAkIuEu2ZFLTxJK2e1AIcCb5B5MXY9KOXdGTnYFZ+KKx6R4Fv9zU6CtMYPQ==} - peerDependencies: - postcss: ^8.3.3 - stylelint: ^14.10.0 - peerDependenciesMeta: - postcss: - optional: true - dependencies: - postcss-scss: 4.0.6 - stylelint: 14.16.1 - stylelint-config-recommended: 9.0.0_stylelint@14.16.1 - stylelint-scss: 4.3.0_stylelint@14.16.1 - dev: true - - /stylelint-config-recommended/9.0.0_stylelint@14.16.1: - resolution: {integrity: sha512-9YQSrJq4NvvRuTbzDsWX3rrFOzOlYBmZP+o513BJN/yfEmGSr0AxdvrWs0P/ilSpVV/wisamAHu5XSk8Rcf4CQ==} - peerDependencies: - stylelint: ^14.10.0 - dependencies: - stylelint: 14.16.1 - dev: true - - /stylelint-config-standard-scss/6.1.0_stylelint@14.16.1: - resolution: {integrity: sha512-iZ2B5kQT2G3rUzx+437cEpdcnFOQkwnwqXuY8Z0QUwIHQVE8mnYChGAquyKFUKZRZ0pRnrciARlPaR1RBtPb0Q==} - peerDependencies: - postcss: ^8.3.3 - stylelint: ^14.14.0 - peerDependenciesMeta: - postcss: - optional: true - dependencies: - stylelint: 14.16.1 - stylelint-config-recommended-scss: 8.0.0_stylelint@14.16.1 - stylelint-config-standard: 29.0.0_stylelint@14.16.1 - dev: true - - /stylelint-config-standard/29.0.0_stylelint@14.16.1: - resolution: {integrity: sha512-uy8tZLbfq6ZrXy4JKu3W+7lYLgRQBxYTUUB88vPgQ+ZzAxdrvcaSUW9hOMNLYBnwH+9Kkj19M2DHdZ4gKwI7tg==} - peerDependencies: - stylelint: ^14.14.0 - dependencies: - stylelint: 14.16.1 - stylelint-config-recommended: 9.0.0_stylelint@14.16.1 - dev: true - - /stylelint-scss/4.3.0_stylelint@14.16.1: - resolution: {integrity: sha512-GvSaKCA3tipzZHoz+nNO7S02ZqOsdBzMiCx9poSmLlb3tdJlGddEX/8QzCOD8O7GQan9bjsvLMsO5xiw6IhhIQ==} - peerDependencies: - stylelint: ^14.5.1 - dependencies: - lodash: 4.17.21 - postcss-media-query-parser: 0.2.3 - postcss-resolve-nested-selector: 0.1.1 - postcss-selector-parser: 6.0.11 - postcss-value-parser: 4.2.0 - stylelint: 14.16.1 - dev: true - - /stylelint/14.16.1: - resolution: {integrity: sha512-ErlzR/T3hhbV+a925/gbfc3f3Fep9/bnspMiJPorfGEmcBbXdS+oo6LrVtoUZ/w9fqD6o6k7PtUlCOsCRdjX/A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dependencies: - '@csstools/selector-specificity': 2.0.2_wajs5nedgkikc5pcuwett7legi - balanced-match: 2.0.0 - colord: 2.9.3 - cosmiconfig: 7.1.0 - css-functions-list: 3.1.0 - debug: 4.3.4 - fast-glob: 3.2.12 - fastest-levenshtein: 1.0.16 - file-entry-cache: 6.0.1 - global-modules: 2.0.0 - globby: 11.1.0 - globjoin: 0.1.4 - html-tags: 3.2.0 - ignore: 5.2.4 - import-lazy: 4.0.0 - imurmurhash: 0.1.4 - is-plain-object: 5.0.0 - known-css-properties: 0.26.0 - mathml-tag-names: 2.1.3 - meow: 9.0.0 - micromatch: 4.0.5 - normalize-path: 3.0.0 - picocolors: 1.0.0 - postcss: 8.4.21 - postcss-media-query-parser: 0.2.3 - postcss-resolve-nested-selector: 0.1.1 - postcss-safe-parser: 6.0.0_postcss@8.4.21 - postcss-selector-parser: 6.0.11 - postcss-value-parser: 4.2.0 - resolve-from: 5.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - style-search: 0.1.0 - supports-hyperlinks: 2.3.0 - svg-tags: 1.0.0 - table: 6.8.1 - v8-compile-cache: 2.3.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - /stylis/4.1.3: resolution: {integrity: sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==} dev: false @@ -7891,14 +7446,6 @@ packages: has-flag: 4.0.0 dev: true - /supports-hyperlinks/2.3.0: - resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - supports-color: 7.2.0 - dev: true - /supports-preserve-symlinks-flag/1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -7907,25 +7454,10 @@ packages: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} dev: true - /svg-tags/1.0.0: - resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} - dev: true - /symbol-tree/3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true - /table/6.8.1: - resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} - engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.12.0 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - /tar/6.1.13: resolution: {integrity: sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==} engines: {node: '>=10'} @@ -8033,11 +7565,6 @@ packages: punycode: 2.1.1 dev: true - /trim-newlines/3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - dev: true - /truncate-utf8-bytes/1.0.2: resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==} dependencies: @@ -8103,6 +7630,10 @@ packages: resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} dev: false + /tslib/2.5.3: + resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} + dev: false + /tsutils/3.21.0_typescript@4.9.4: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -8199,26 +7730,11 @@ packages: dev: true optional: true - /type-fest/0.18.1: - resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} - engines: {node: '>=10'} - dev: true - /type-fest/0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} dev: true - /type-fest/0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - dev: true - - /type-fest/0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - dev: true - /type-is/1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -8338,7 +7854,7 @@ packages: dependencies: '@types/react': 18.0.26 react: 18.2.0 - tslib: 2.5.0 + tslib: 2.5.3 dev: false /use-sidecar/1.1.2_kzbn2opkn2327fwg5yzwzya5o4: @@ -8354,7 +7870,7 @@ packages: '@types/react': 18.0.26 detect-node-es: 1.1.0 react: 18.2.0 - tslib: 2.5.0 + tslib: 2.5.3 dev: false /use-sync-external-store/1.2.0_react@18.2.0: @@ -8371,6 +7887,7 @@ packages: /util-deprecate/1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false /utils-merge/1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} @@ -8381,17 +7898,6 @@ packages: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true - /v8-compile-cache/2.3.0: - resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} - dev: true - - /validate-npm-package-license/3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - dependencies: - spdx-correct: 3.1.1 - spdx-expression-parse: 3.0.1 - dev: true - /validator/13.7.0: resolution: {integrity: sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==} engines: {node: '>= 0.10'} @@ -8818,13 +8324,6 @@ packages: is-typed-array: 1.1.10 dev: true - /which/1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - /which/2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -8870,14 +8369,6 @@ packages: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true - /write-file-atomic/4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - dev: true - /ws/8.12.0: resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==} engines: {node: '>=10.0.0'} @@ -8955,11 +8446,6 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - /yargs-parser/20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true - /yargs-parser/21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'}