10 Commits

Author SHA1 Message Date
7e938138ff fix sidebar width, v0.1.5
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2026-02-24 11:02:17 +01:00
62590c34d1 fix ci
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2026-02-24 10:55:39 +01:00
01bbaebe5b expose sidebars sizing, v0.1.4
Some checks failed
continuous-integration/drone/push Build encountered an error
2026-02-24 10:53:29 +01:00
83d9bc78f0 update ci
Some checks failed
continuous-integration/drone/push Build encountered an error
2026-02-24 10:16:31 +01:00
ef084b893b fix ci
Some checks failed
continuous-integration/drone/push Build encountered an error
2026-02-23 23:51:24 +01:00
a382bfee01 update drone
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-23 23:34:16 +01:00
6e4f529446 update eslint
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-23 15:17:51 +01:00
cbabf43584 update prettier
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-23 14:23:46 +01:00
33d1425fbb add eslint / prettier
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-23 14:18:51 +01:00
4d1d2e6ed8 add renovate
All checks were successful
continuous-integration/drone/push Build is passing
2026-02-23 11:32:38 +01:00
28 changed files with 2169 additions and 1313 deletions

View File

@@ -13,17 +13,18 @@ trigger:
steps: steps:
- name: install - name: install
image: node:22 image: node:25
commands: commands:
- corepack enable
- corepack prepare yarn@1.22.22 --activate
- yarn install --frozen-lockfile - yarn install --frozen-lockfile
- name: build - name: lint
image: node:22 image: node:25
commands:
- yarn lint
- name: build
image: node:25
commands: commands:
- corepack enable
- corepack prepare yarn@1.22.22 --activate
- yarn build - yarn build
--- ---
@@ -32,22 +33,18 @@ type: docker
name: web-core-publish name: web-core-publish
trigger: trigger:
branch:
- main
event: event:
- promote - tag
target: ref:
- production - refs/tags/v*
steps: steps:
- name: publish-npm - name: publish-npm
image: node:22 image: node:25
environment: environment:
NEXUS_NPM_TOKEN: NEXUS_NPM_TOKEN:
from_secret: nexus_npm_token from_secret: nexus_npm_token
commands: commands:
- corepack enable
- corepack prepare yarn@1.22.22 --activate
- yarn install --frozen-lockfile - yarn install --frozen-lockfile
- npm config set //nexus.beatrice.wtf/repository/npm-hosted/:_authToken "$NEXUS_NPM_TOKEN" - npm config set //nexus.beatrice.wtf/repository/npm-hosted/:_authToken "$NEXUS_NPM_TOKEN"
- yarn publish:nexus - yarn publish:nexus

4
.prettierignore Normal file
View File

@@ -0,0 +1,4 @@
dist
coverage
node_modules
yarn.lock

7
.prettierrc Normal file
View File

@@ -0,0 +1,7 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"singleQuote": true,
"semi": true,
"printWidth": 100,
"tabWidth": 4
}

51
eslint.config.mjs Normal file
View File

@@ -0,0 +1,51 @@
import js from '@eslint/js';
import reactHooks from 'eslint-plugin-react-hooks';
import reactRefresh from 'eslint-plugin-react-refresh';
import globals from 'globals';
import tseslint from 'typescript-eslint';
export default tseslint.config(
{
ignores: [
'dist',
'coverage',
'node_modules',
'*.config.cjs',
'vite.config.js',
'vite.config.d.ts',
],
},
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
...globals.browser,
...globals.node,
},
},
rules: {
'no-empty': ['error', { allowEmptyCatch: true }],
},
},
{
files: ['src/**/*.{ts,tsx}'],
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
},
},
{
files: ['src/contexts/**/*.{ts,tsx}'],
rules: {
'react-refresh/only-export-components': 'off',
},
},
);

View File

@@ -1,5 +1,4 @@
GNU Affero General Public License # GNU Affero General Public License
=================================
_Version 3, 19 November 2007_ _Version 3, 19 November 2007_
_Copyright © 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;_ _Copyright © 2007 Free Software Foundation, Inc. &lt;<http://fsf.org/>&gt;_
@@ -201,20 +200,20 @@ You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions: terms of section 4, provided that you also meet all of these conditions:
* **a)** The work must carry prominent notices stating that you modified - **a)** The work must carry prominent notices stating that you modified
it, and giving a relevant date. it, and giving a relevant date.
* **b)** The work must carry prominent notices stating that it is - **b)** The work must carry prominent notices stating that it is
released under this License and any conditions added under section 7. released under this License and any conditions added under section 7.
This requirement modifies the requirement in section 4 to This requirement modifies the requirement in section 4 to
“keep intact all notices”. “keep intact all notices”.
* **c)** You must license the entire work, as a whole, under this - **c)** You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7 License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts, additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it. invalidate such permission if you have separately received it.
* **d)** If the work has interactive user interfaces, each must display - **d)** If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your interfaces that do not display Appropriate Legal Notices, your
work need not make them do so. work need not make them do so.
@@ -236,11 +235,11 @@ of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License, machine-readable Corresponding Source under the terms of this License,
in one of these ways: in one of these ways:
* **a)** Convey the object code in, or embodied in, a physical product - **a)** Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the (including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium Corresponding Source fixed on a durable physical medium
customarily used for software interchange. customarily used for software interchange.
* **b)** Convey the object code in, or embodied in, a physical product - **b)** Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a (including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product long as you offer spare parts or customer support for that product
@@ -251,12 +250,12 @@ in one of these ways:
more than your reasonable cost of physically performing this more than your reasonable cost of physically performing this
conveying of source, or **(2)** access to copy the conveying of source, or **(2)** access to copy the
Corresponding Source from a network server at no charge. Corresponding Source from a network server at no charge.
* **c)** Convey individual copies of the object code with a copy of the - **c)** Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord only if you received the object code with such an offer, in accord
with subsection 6b. with subsection 6b.
* **d)** Convey the object code by offering access from a designated - **d)** Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the further charge. You need not require recipients to copy the
@@ -268,7 +267,7 @@ in one of these ways:
Corresponding Source. Regardless of what server hosts the Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements. available for as long as needed to satisfy these requirements.
* **e)** Convey the object code using peer-to-peer transmission, provided - **e)** Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no Source of the work are being offered to the general public at no
charge under subsection 6d. charge under subsection 6d.
@@ -345,19 +344,19 @@ Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms: that material) supplement the terms of this License with terms:
* **a)** Disclaiming warranty or limiting liability differently from the - **a)** Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or terms of sections 15 and 16 of this License; or
* **b)** Requiring preservation of specified reasonable legal notices or - **b)** Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or Notices displayed by works containing it; or
* **c)** Prohibiting misrepresentation of the origin of that material, or - **c)** Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or reasonable ways as different from the original version; or
* **d)** Limiting the use for publicity purposes of names of licensors or - **d)** Limiting the use for publicity purposes of names of licensors or
authors of the material; or authors of the material; or
* **e)** Declining to grant rights under trademark law for use of some - **e)** Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or trade names, trademarks, or service marks; or
* **f)** Requiring indemnification of licensors and authors of that - **f)** Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on any liability that these contractual assumptions directly impose on

View File

@@ -1,6 +1,6 @@
{ {
"name": "@panic/web-core", "name": "@panic/web-core",
"version": "0.1.3", "version": "0.1.5",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"description": "Core auth and utilities for panic.haus web applications", "description": "Core auth and utilities for panic.haus web applications",
"type": "module", "type": "module",
@@ -19,6 +19,10 @@
"scripts": { "scripts": {
"clean": "rm -rf dist", "clean": "rm -rf dist",
"build": "yarn clean && vite build && tsc -p tsconfig.build.json", "build": "yarn clean && vite build && tsc -p tsconfig.build.json",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier . --write",
"format:check": "prettier . --check",
"prepublishOnly": "yarn build", "prepublishOnly": "yarn build",
"publish:nexus": "npm publish --registry ${NEXUS_NPM_REGISTRY:-https://nexus.beatrice.wtf/repository/npm-hosted/}" "publish:nexus": "npm publish --registry ${NEXUS_NPM_REGISTRY:-https://nexus.beatrice.wtf/repository/npm-hosted/}"
}, },
@@ -30,11 +34,18 @@
"react": "^19.0.0" "react": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^10",
"@types/react": "^19.0.0", "@types/react": "^19.0.0",
"@vitejs/plugin-react": "^5.0.0", "@vitejs/plugin-react": "^5.0.0",
"eslint": "^10",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.5.1",
"globals": "^17.3.0",
"prettier": "^3.8.1",
"react": "^19.0.0", "react": "^19.0.0",
"react-dom": "^19.0.0", "react-dom": "^19.0.0",
"typescript": "^5.6.2", "typescript": "^5.6.2",
"typescript-eslint": "^8.56.0",
"vite": "^7.0.0" "vite": "^7.0.0"
} }
} }

3
renovate.json Normal file
View File

@@ -0,0 +1,3 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
}

View File

@@ -30,7 +30,7 @@ export class ApiError extends Error {
code, code,
requestId, requestId,
details, details,
rawMessage rawMessage,
}: { }: {
message: string; message: string;
status: number; status: number;
@@ -59,7 +59,7 @@ function parseErrorPayload(data: unknown) {
code: undefined as string | undefined, code: undefined as string | undefined,
rawMessage: undefined as string | undefined, rawMessage: undefined as string | undefined,
requestId: undefined as string | undefined, requestId: undefined as string | undefined,
details: undefined as unknown details: undefined as unknown,
}; };
} }
@@ -88,7 +88,7 @@ export function createApiClient(config: CreateApiClientConfig) {
baseUrl, baseUrl,
resolveError = defaultResolveError, resolveError = defaultResolveError,
inferErrorCodeFromStatus, inferErrorCodeFromStatus,
fetchImpl fetchImpl,
} = config; } = config;
async function request<T>(path: string, options: RequestOptions = {}): Promise<T> { async function request<T>(path: string, options: RequestOptions = {}): Promise<T> {
@@ -99,9 +99,9 @@ export function createApiClient(config: CreateApiClientConfig) {
method, method,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}) ...(token ? { Authorization: `Bearer ${token}` } : {}),
}, },
body: body ? JSON.stringify(body) : undefined body: body ? JSON.stringify(body) : undefined,
}); });
const data = await response.json().catch(() => null); const data = await response.json().catch(() => null);
@@ -112,7 +112,7 @@ export function createApiClient(config: CreateApiClientConfig) {
const message = resolveError({ const message = resolveError({
code, code,
status: response.status, status: response.status,
fallbackMessage: parsed.rawMessage fallbackMessage: parsed.rawMessage,
}); });
throw new ApiError({ throw new ApiError({
@@ -121,7 +121,7 @@ export function createApiClient(config: CreateApiClientConfig) {
code, code,
requestId: parsed.requestId, requestId: parsed.requestId,
details: parsed.details, details: parsed.details,
rawMessage: parsed.rawMessage rawMessage: parsed.rawMessage,
}); });
} }
@@ -129,6 +129,6 @@ export function createApiClient(config: CreateApiClientConfig) {
} }
return { return {
request request,
}; };
} }

View File

@@ -11,7 +11,7 @@ export function buildListQuery({
page = 1, page = 1,
pageSize = 10, pageSize = 10,
sort, sort,
defaultSort defaultSort,
}: BuildListQueryOptions): string { }: BuildListQueryOptions): string {
const query = new URLSearchParams(); const query = new URLSearchParams();
const normalizedQuery = q?.trim(); const normalizedQuery = q?.trim();

View File

@@ -41,18 +41,21 @@ export function createAuthContext<TUser>(options: CreateAuthContextOptions = {})
return { return {
authToken, authToken,
refreshToken, refreshToken,
currentUser: null currentUser: null,
}; };
} }
function AuthProvider({ children }: Readonly<{ children: ReactNode }>) { function AuthProvider({ children }: Readonly<{ children: ReactNode }>) {
const [state, setState] = useState<AuthState<TUser>>(readStoredSession); const [state, setState] = useState<AuthState<TUser>>(readStoredSession);
const setSession = useCallback((authToken: string, refreshToken: string, currentUser: TUser) => { const setSession = useCallback(
(authToken: string, refreshToken: string, currentUser: TUser) => {
localStorage.setItem(authTokenKey, authToken); localStorage.setItem(authTokenKey, authToken);
localStorage.setItem(refreshTokenKey, refreshToken); localStorage.setItem(refreshTokenKey, refreshToken);
setState({ authToken, refreshToken, currentUser }); setState({ authToken, refreshToken, currentUser });
}, []); },
[],
);
const clearSession = useCallback(() => { const clearSession = useCallback(() => {
localStorage.removeItem(authTokenKey); localStorage.removeItem(authTokenKey);
@@ -64,12 +67,15 @@ export function createAuthContext<TUser>(options: CreateAuthContextOptions = {})
setState((prev) => ({ ...prev, currentUser })); setState((prev) => ({ ...prev, currentUser }));
}, []); }, []);
const value = useMemo<AuthContextValue<TUser>>(() => ({ const value = useMemo<AuthContextValue<TUser>>(
() => ({
...state, ...state,
setSession, setSession,
setCurrentUser, setCurrentUser,
clearSession clearSession,
}), [state, setSession, setCurrentUser, clearSession]); }),
[state, setSession, setCurrentUser, clearSession],
);
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>; return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
} }
@@ -85,6 +91,6 @@ export function createAuthContext<TUser>(options: CreateAuthContextOptions = {})
return { return {
AuthProvider, AuthProvider,
useAuth, useAuth,
AuthContext AuthContext,
}; };
} }

View File

@@ -7,7 +7,7 @@ import {
useRef, useRef,
useState, useState,
type CSSProperties, type CSSProperties,
type ReactNode type ReactNode,
} from 'react'; } from 'react';
import { isDesktopViewport, useSidePanelMachine } from '../panels/useSidePanelMachine'; import { isDesktopViewport, useSidePanelMachine } from '../panels/useSidePanelMachine';
@@ -18,6 +18,13 @@ const SIDEBAR_MIN_WIDTH = 220;
const SIDEBAR_MAX_WIDTH = 420; const SIDEBAR_MAX_WIDTH = 420;
const SIDEBAR_COLLAPSED_WIDTH = 56; const SIDEBAR_COLLAPSED_WIDTH = 56;
export type LeftMenuSizing = {
defaultWidth?: number;
minWidth?: number;
maxWidth?: number;
collapsedWidth?: number;
};
export type LeftMenuRenderState = { export type LeftMenuRenderState = {
collapsed: boolean; collapsed: boolean;
mobileOpen: boolean; mobileOpen: boolean;
@@ -53,10 +60,40 @@ type LeftMenuProviderProps = {
children: ReactNode; children: ReactNode;
defaultContent: LeftMenuContent; defaultContent: LeftMenuContent;
closeOnPathname?: string; closeOnPathname?: string;
sizing?: LeftMenuSizing;
}; };
const LeftMenuContext = createContext<LeftMenuContextValue | undefined>(undefined); const LeftMenuContext = createContext<LeftMenuContextValue | undefined>(undefined);
function readSizingValue(value: number | undefined, fallback: number): number {
if (!Number.isFinite(value) || value == null || value <= 0) {
return fallback;
}
return value;
}
function resolveLeftMenuSizing(sizing: LeftMenuSizing | undefined) {
const requestedMinWidth = readSizingValue(sizing?.minWidth, SIDEBAR_MIN_WIDTH);
const requestedMaxWidth = readSizingValue(sizing?.maxWidth, SIDEBAR_MAX_WIDTH);
const minWidth = Math.min(requestedMinWidth, requestedMaxWidth);
const maxWidth = Math.max(requestedMinWidth, requestedMaxWidth);
const requestedDefaultWidth = readSizingValue(sizing?.defaultWidth, SIDEBAR_DEFAULT_WIDTH);
const defaultWidth = Math.min(maxWidth, Math.max(minWidth, requestedDefaultWidth));
const requestedCollapsedWidth = readSizingValue(
sizing?.collapsedWidth,
SIDEBAR_COLLAPSED_WIDTH,
);
const collapsedWidth = Math.min(minWidth, requestedCollapsedWidth);
return {
defaultWidth,
minWidth,
maxWidth,
collapsedWidth,
};
}
function readStoredCollapsed(): boolean { function readStoredCollapsed(): boolean {
if (!globalThis.window) { if (!globalThis.window) {
return false; return false;
@@ -68,8 +105,10 @@ function readStoredCollapsed(): boolean {
export function LeftMenuProvider({ export function LeftMenuProvider({
children, children,
defaultContent, defaultContent,
closeOnPathname closeOnPathname,
sizing,
}: Readonly<LeftMenuProviderProps>) { }: Readonly<LeftMenuProviderProps>) {
const { defaultWidth, minWidth, maxWidth, collapsedWidth } = resolveLeftMenuSizing(sizing);
const [collapsed, setCollapsed] = useState<boolean>(() => readStoredCollapsed()); const [collapsed, setCollapsed] = useState<boolean>(() => readStoredCollapsed());
const [mobileOpen, setMobileOpen] = useState(false); const [mobileOpen, setMobileOpen] = useState(false);
const [content, setContent] = useState<LeftMenuContent>(defaultContent); const [content, setContent] = useState<LeftMenuContent>(defaultContent);
@@ -123,7 +162,8 @@ export function LeftMenuProvider({
closeMobile(); closeMobile();
}, [collapseMenu, closeMobile]); }, [collapseMenu, closeMobile]);
const openMenu = useCallback((nextContent?: LeftMenuContent) => { const openMenu = useCallback(
(nextContent?: LeftMenuContent) => {
if (nextContent) { if (nextContent) {
setContent(nextContent); setContent(nextContent);
} }
@@ -134,9 +174,12 @@ export function LeftMenuProvider({
} }
setMobileOpen(true); setMobileOpen(true);
}, [expandMenu]); },
[expandMenu],
);
const toggleMenu = useCallback((nextContent?: LeftMenuContent) => { const toggleMenu = useCallback(
(nextContent?: LeftMenuContent) => {
if (nextContent) { if (nextContent) {
setContent(nextContent); setContent(nextContent);
} }
@@ -147,7 +190,9 @@ export function LeftMenuProvider({
} }
setMobileOpen((previous) => !previous); setMobileOpen((previous) => !previous);
}, [toggleCollapsed]); },
[toggleCollapsed],
);
const handleCloseOnPathname = useCallback(() => { const handleCloseOnPathname = useCallback(() => {
setMobileOpen(false); setMobileOpen(false);
@@ -156,9 +201,9 @@ export function LeftMenuProvider({
const { width, startResize } = useSidePanelMachine({ const { width, startResize } = useSidePanelMachine({
storageKey: SIDEBAR_WIDTH_KEY, storageKey: SIDEBAR_WIDTH_KEY,
defaultWidth: SIDEBAR_DEFAULT_WIDTH, defaultWidth,
minWidth: SIDEBAR_MIN_WIDTH, minWidth,
maxWidth: SIDEBAR_MAX_WIDTH, maxWidth,
resizeAxis: 'from-left', resizeAxis: 'from-left',
resizingBodyClass: 'auth-sidebar-resizing', resizingBodyClass: 'auth-sidebar-resizing',
isOpen: mobileOpen, isOpen: mobileOpen,
@@ -166,46 +211,48 @@ export function LeftMenuProvider({
shouldPersistWidth: !collapsed, shouldPersistWidth: !collapsed,
closeOnPathname, closeOnPathname,
onCloseOnPathname: handleCloseOnPathname, onCloseOnPathname: handleCloseOnPathname,
onEscape: closeMobile onEscape: closeMobile,
}); });
const desktopMenuStyle = useMemo<LeftMenuStyle>(() => ({ const desktopMenuStyle = useMemo<LeftMenuStyle>(
'--auth-sidebar-width': `${collapsed ? SIDEBAR_COLLAPSED_WIDTH : width}px` () => ({
}), [collapsed, width]); '--auth-sidebar-width': `${collapsed ? collapsedWidth : width}px`,
}),
const value = useMemo<LeftMenuContextValue>(() => ({ [collapsed, collapsedWidth, width],
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize
}), [
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize
]);
return (
<LeftMenuContext.Provider value={value}>
{children}
</LeftMenuContext.Provider>
); );
const value = useMemo<LeftMenuContextValue>(
() => ({
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize,
}),
[
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize,
],
);
return <LeftMenuContext.Provider value={value}>{children}</LeftMenuContext.Provider>;
} }
export function useLeftMenu() { export function useLeftMenu() {

View File

@@ -5,7 +5,7 @@ import {
useMemo, useMemo,
useState, useState,
type CSSProperties, type CSSProperties,
type ReactNode type ReactNode,
} from 'react'; } from 'react';
import { isDesktopViewport, useSidePanelMachine } from '../panels/useSidePanelMachine'; import { isDesktopViewport, useSidePanelMachine } from '../panels/useSidePanelMachine';
@@ -14,6 +14,12 @@ const RIGHT_SIDEBAR_DEFAULT_WIDTH = 320;
const RIGHT_SIDEBAR_MIN_WIDTH = 260; const RIGHT_SIDEBAR_MIN_WIDTH = 260;
const RIGHT_SIDEBAR_MAX_WIDTH = 480; const RIGHT_SIDEBAR_MAX_WIDTH = 480;
export type RightSidebarSizing = {
defaultWidth?: number;
minWidth?: number;
maxWidth?: number;
};
export type RightSidebarContent = { export type RightSidebarContent = {
title: string; title: string;
content: ReactNode; content: ReactNode;
@@ -39,15 +45,44 @@ type RightSidebarProviderProps = {
children: ReactNode; children: ReactNode;
closeOnPathname?: string; closeOnPathname?: string;
onMobileOpenRequest?: () => void; onMobileOpenRequest?: () => void;
sizing?: RightSidebarSizing;
}; };
const RightSidebarContext = createContext<RightSidebarContextValue | undefined>(undefined); const RightSidebarContext = createContext<RightSidebarContextValue | undefined>(undefined);
function readSizingValue(value: number | undefined, fallback: number): number {
if (!Number.isFinite(value) || value == null || value <= 0) {
return fallback;
}
return value;
}
function resolveRightSidebarSizing(sizing: RightSidebarSizing | undefined) {
const requestedMinWidth = readSizingValue(sizing?.minWidth, RIGHT_SIDEBAR_MIN_WIDTH);
const requestedMaxWidth = readSizingValue(sizing?.maxWidth, RIGHT_SIDEBAR_MAX_WIDTH);
const minWidth = Math.min(requestedMinWidth, requestedMaxWidth);
const maxWidth = Math.max(requestedMinWidth, requestedMaxWidth);
const requestedDefaultWidth = readSizingValue(
sizing?.defaultWidth,
RIGHT_SIDEBAR_DEFAULT_WIDTH,
);
const defaultWidth = Math.min(maxWidth, Math.max(minWidth, requestedDefaultWidth));
return {
defaultWidth,
minWidth,
maxWidth,
};
}
export function RightSidebarProvider({ export function RightSidebarProvider({
children, children,
closeOnPathname, closeOnPathname,
onMobileOpenRequest onMobileOpenRequest,
sizing,
}: Readonly<RightSidebarProviderProps>) { }: Readonly<RightSidebarProviderProps>) {
const { defaultWidth, minWidth, maxWidth } = resolveRightSidebarSizing(sizing);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [content, setContent] = useState<RightSidebarContent | null>(null); const [content, setContent] = useState<RightSidebarContent | null>(null);
@@ -60,7 +95,8 @@ export function RightSidebarProvider({
setContent(nextContent); setContent(nextContent);
}, []); }, []);
const openSidebar = useCallback((nextContent?: RightSidebarContent) => { const openSidebar = useCallback(
(nextContent?: RightSidebarContent) => {
const resolvedContent = nextContent ?? content; const resolvedContent = nextContent ?? content;
if (!resolvedContent) { if (!resolvedContent) {
return; return;
@@ -73,22 +109,27 @@ export function RightSidebarProvider({
onMobileOpenRequest?.(); onMobileOpenRequest?.();
} }
setIsOpen(true); setIsOpen(true);
}, [content, onMobileOpenRequest]); },
[content, onMobileOpenRequest],
);
const toggleSidebar = useCallback((nextContent?: RightSidebarContent) => { const toggleSidebar = useCallback(
(nextContent?: RightSidebarContent) => {
if (isOpen) { if (isOpen) {
closeSidebar(); closeSidebar();
return; return;
} }
openSidebar(nextContent); openSidebar(nextContent);
}, [isOpen, closeSidebar, openSidebar]); },
[isOpen, closeSidebar, openSidebar],
);
const { width, startResize } = useSidePanelMachine({ const { width, startResize } = useSidePanelMachine({
storageKey: RIGHT_SIDEBAR_WIDTH_KEY, storageKey: RIGHT_SIDEBAR_WIDTH_KEY,
defaultWidth: RIGHT_SIDEBAR_DEFAULT_WIDTH, defaultWidth,
minWidth: RIGHT_SIDEBAR_MIN_WIDTH, minWidth,
maxWidth: RIGHT_SIDEBAR_MAX_WIDTH, maxWidth,
resizeAxis: 'from-right', resizeAxis: 'from-right',
resizingBodyClass: 'auth-right-sidebar-resizing', resizingBodyClass: 'auth-right-sidebar-resizing',
isOpen, isOpen,
@@ -96,38 +137,40 @@ export function RightSidebarProvider({
shouldPersistWidth: true, shouldPersistWidth: true,
closeOnPathname, closeOnPathname,
onCloseOnPathname: closeSidebar, onCloseOnPathname: closeSidebar,
onEscape: closeSidebar onEscape: closeSidebar,
}); });
const desktopSidebarStyle = useMemo<RightSidebarStyle>(() => ({ const desktopSidebarStyle = useMemo<RightSidebarStyle>(
'--auth-right-sidebar-width': `${width}px` () => ({
}), [width]); '--auth-right-sidebar-width': `${width}px`,
}),
const value = useMemo<RightSidebarContextValue>(() => ({ [width],
isOpen,
content,
openSidebar,
closeSidebar,
toggleSidebar,
setSidebarContent,
desktopSidebarStyle,
startResize
}), [
isOpen,
content,
openSidebar,
closeSidebar,
toggleSidebar,
setSidebarContent,
desktopSidebarStyle,
startResize
]);
return (
<RightSidebarContext.Provider value={value}>
{children}
</RightSidebarContext.Provider>
); );
const value = useMemo<RightSidebarContextValue>(
() => ({
isOpen,
content,
openSidebar,
closeSidebar,
toggleSidebar,
setSidebarContent,
desktopSidebarStyle,
startResize,
}),
[
isOpen,
content,
openSidebar,
closeSidebar,
toggleSidebar,
setSidebarContent,
desktopSidebarStyle,
startResize,
],
);
return <RightSidebarContext.Provider value={value}>{children}</RightSidebarContext.Provider>;
} }
export function useRightSidebar() { export function useRightSidebar() {

View File

@@ -30,7 +30,7 @@ export function createErrorResolver(config: CreateErrorResolverConfig) {
defaultContext = 'default', defaultContext = 'default',
contextOverrides = {}, contextOverrides = {},
inferCodeFromStatus, inferCodeFromStatus,
inferCodeFromLegacyMessage inferCodeFromLegacyMessage,
} = config; } = config;
const knownCodes = new Set(Object.keys(catalog)); const knownCodes = new Set(Object.keys(catalog));
@@ -51,16 +51,12 @@ export function createErrorResolver(config: CreateErrorResolverConfig) {
} }
function resolveErrorMessage(options: ResolveErrorMessageOptions): string { function resolveErrorMessage(options: ResolveErrorMessageOptions): string {
const { const { code, status, context = defaultContext, fallbackMessage } = options;
code,
status,
context = defaultContext,
fallbackMessage
} = options;
const resolvedCode = normalizeErrorCode(code) const resolvedCode =
?? inferCodeFromLegacyMessage?.(fallbackMessage) normalizeErrorCode(code) ??
?? inferErrorCodeFromStatus(status); inferCodeFromLegacyMessage?.(fallbackMessage) ??
inferErrorCodeFromStatus(status);
if (resolvedCode) { if (resolvedCode) {
const contextMessage = contextOverrides[context]?.[resolvedCode]; const contextMessage = contextOverrides[context]?.[resolvedCode];
@@ -96,7 +92,10 @@ export function createErrorResolver(config: CreateErrorResolverConfig) {
return 'Request failed. Please try again.'; return 'Request failed. Please try again.';
} }
function resolveOptionalErrorMessage(code?: string | null, context: string = defaultContext): string | undefined { function resolveOptionalErrorMessage(
code?: string | null,
context: string = defaultContext,
): string | undefined {
if (!code) { if (!code) {
return undefined; return undefined;
} }
@@ -108,14 +107,15 @@ export function createErrorResolver(config: CreateErrorResolverConfig) {
const errorLike = err as ErrorLike; const errorLike = err as ErrorLike;
const code = typeof errorLike.code === 'string' ? errorLike.code : undefined; const code = typeof errorLike.code === 'string' ? errorLike.code : undefined;
const status = typeof errorLike.status === 'number' ? errorLike.status : undefined; const status = typeof errorLike.status === 'number' ? errorLike.status : undefined;
const rawMessage = typeof errorLike.rawMessage === 'string' ? errorLike.rawMessage : undefined; const rawMessage =
typeof errorLike.rawMessage === 'string' ? errorLike.rawMessage : undefined;
const message = typeof errorLike.message === 'string' ? errorLike.message : undefined; const message = typeof errorLike.message === 'string' ? errorLike.message : undefined;
return resolveErrorMessage({ return resolveErrorMessage({
code, code,
status, status,
context, context,
fallbackMessage: rawMessage ?? message fallbackMessage: rawMessage ?? message,
}); });
} }
@@ -127,6 +127,6 @@ export function createErrorResolver(config: CreateErrorResolverConfig) {
inferErrorCodeFromStatus, inferErrorCodeFromStatus,
resolveErrorMessage, resolveErrorMessage,
resolveOptionalErrorMessage, resolveOptionalErrorMessage,
toErrorMessage toErrorMessage,
}; };
} }

View File

@@ -23,6 +23,6 @@ export function useCooldownTimer(seconds = 0, enabled = true) {
return { return {
cooldown, cooldown,
startCooldown startCooldown,
}; };
} }

View File

@@ -10,7 +10,7 @@ type UseEditableFormOptions<TValues> = {
export function useEditableForm<TValues extends Record<string, string>>({ export function useEditableForm<TValues extends Record<string, string>>({
initialValues, initialValues,
validate validate,
}: UseEditableFormOptions<TValues>) { }: UseEditableFormOptions<TValues>) {
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
@@ -23,30 +23,42 @@ export function useEditableForm<TValues extends Record<string, string>>({
validateAll, validateAll,
setFieldError, setFieldError,
setErrors, setErrors,
clearErrors clearErrors,
} = useValidatedFields({ } = useValidatedFields({
initialValues, initialValues,
validate validate,
}); });
const startEditing = useCallback((sourceValues: TValues) => { const startEditing = useCallback(
(sourceValues: TValues) => {
setValues(sourceValues, { validate: true }); setValues(sourceValues, { validate: true });
setIsEditing(true); setIsEditing(true);
}, [setValues]); },
[setValues],
);
const discardChanges = useCallback((sourceValues: TValues) => { const discardChanges = useCallback(
(sourceValues: TValues) => {
setValues(sourceValues, { clearErrors: true }); setValues(sourceValues, { clearErrors: true });
setIsEditing(false); setIsEditing(false);
}, [setValues]); },
[setValues],
);
const loadFromSource = useCallback((sourceValues: TValues) => { const loadFromSource = useCallback(
(sourceValues: TValues) => {
setValues(sourceValues, { clearErrors: true }); setValues(sourceValues, { clearErrors: true });
}, [setValues]); },
[setValues],
);
const commitSaved = useCallback((sourceValues: TValues) => { const commitSaved = useCallback(
(sourceValues: TValues) => {
setValues(sourceValues, { clearErrors: true }); setValues(sourceValues, { clearErrors: true });
setIsEditing(false); setIsEditing(false);
}, [setValues]); },
[setValues],
);
return { return {
values, values,
@@ -63,6 +75,6 @@ export function useEditableForm<TValues extends Record<string, string>>({
discardChanges, discardChanges,
loadFromSource, loadFromSource,
commitSaved, commitSaved,
setIsEditing setIsEditing,
}; };
} }

View File

@@ -9,7 +9,12 @@ type PaginatedResourceResponse<TItem> = {
}; };
type UsePaginatedResourceOptions<TItem> = { type UsePaginatedResourceOptions<TItem> = {
load: (params: { q: string; page: number; pageSize: number; sort?: string }) => Promise<PaginatedResourceResponse<TItem>>; load: (params: {
q: string;
page: number;
pageSize: number;
sort?: string;
}) => Promise<PaginatedResourceResponse<TItem>>;
sort?: string; sort?: string;
debounceMs?: number; debounceMs?: number;
initialQuery?: string; initialQuery?: string;
@@ -23,7 +28,7 @@ export function usePaginatedResource<TItem>({
debounceMs = 250, debounceMs = 250,
initialQuery = '', initialQuery = '',
initialPage = 1, initialPage = 1,
initialPageSize = 10 initialPageSize = 10,
}: UsePaginatedResourceOptions<TItem>) { }: UsePaginatedResourceOptions<TItem>) {
const [items, setItems] = useState<TItem[]>([]); const [items, setItems] = useState<TItem[]>([]);
const [q, setQ] = useState(initialQuery); const [q, setQ] = useState(initialQuery);
@@ -46,7 +51,7 @@ export function usePaginatedResource<TItem>({
q, q,
page, page,
pageSize, pageSize,
sort sort,
}); });
if (cancelled) { if (cancelled) {
@@ -60,7 +65,11 @@ export function usePaginatedResource<TItem>({
setPageSize(response.pageSize); setPageSize(response.pageSize);
} catch (err) { } catch (err) {
if (!cancelled) { if (!cancelled) {
setError(err instanceof Error ? err.message : 'Request failed. Please try again.'); setError(
err instanceof Error
? err.message
: 'Request failed. Please try again.',
);
} }
} finally { } finally {
if (!cancelled) { if (!cancelled) {
@@ -97,6 +106,6 @@ export function usePaginatedResource<TItem>({
isLoading, isLoading,
setQuery, setQuery,
setPage, setPage,
setPageSize: setPageSizeAndResetPage setPageSize: setPageSizeAndResetPage,
}; };
} }

View File

@@ -31,7 +31,8 @@ export function useSorting(defaultSort?: SortState | null): UseSortingResult {
const activeSort = overrideSort ?? defaultSort ?? null; const activeSort = overrideSort ?? defaultSort ?? null;
const toggleSort = useCallback((field: string) => { const toggleSort = useCallback(
(field: string) => {
setOverrideSort((previousOverride) => { setOverrideSort((previousOverride) => {
const baselineSort = defaultSort ?? null; const baselineSort = defaultSort ?? null;
const currentSort = previousOverride ?? baselineSort; const currentSort = previousOverride ?? baselineSort;
@@ -56,7 +57,9 @@ export function useSorting(defaultSort?: SortState | null): UseSortingResult {
return { field, direction: 'desc' }; return { field, direction: 'desc' };
}); });
}, [defaultSort]); },
[defaultSort],
);
const setSort = useCallback((next: SortState | null) => { const setSort = useCallback((next: SortState | null) => {
setOverrideSort(next); setOverrideSort(next);
@@ -73,6 +76,6 @@ export function useSorting(defaultSort?: SortState | null): UseSortingResult {
sortParam, sortParam,
toggleSort, toggleSort,
setSort, setSort,
resetSort resetSort,
}; };
} }

View File

@@ -26,6 +26,6 @@ export function useSubmitState<TStatus = string | null>(initialStatus: TStatus)
finishSubmitting, finishSubmitting,
setSubmitError, setSubmitError,
setStatus, setStatus,
clearFeedback clearFeedback,
}; };
} }

View File

@@ -28,7 +28,7 @@ function hasErrors<TValues>(errors: FieldErrors<TValues>): boolean {
function pickTouchedErrors<TValues>( function pickTouchedErrors<TValues>(
errors: FieldErrors<TValues>, errors: FieldErrors<TValues>,
touched: TouchedFields<TValues> touched: TouchedFields<TValues>,
): FieldErrors<TValues> { ): FieldErrors<TValues> {
const next: FieldErrors<TValues> = {}; const next: FieldErrors<TValues> = {};
@@ -53,13 +53,14 @@ function touchAll<TValues extends Record<string, string>>(values: TValues): Touc
export function useValidatedFields<TValues extends Record<string, string>>({ export function useValidatedFields<TValues extends Record<string, string>>({
initialValues, initialValues,
validate validate,
}: UseValidatedFieldsOptions<TValues>) { }: UseValidatedFieldsOptions<TValues>) {
const [values, setValues] = useState<TValues>(initialValues); const [values, setValues] = useState<TValues>(initialValues);
const [allErrors, setAllErrors] = useState<FieldErrors<TValues>>(() => validate(initialValues)); const [allErrors, setAllErrors] = useState<FieldErrors<TValues>>(() => validate(initialValues));
const [touched, setTouched] = useState<TouchedFields<TValues>>({}); const [touched, setTouched] = useState<TouchedFields<TValues>>({});
const updateValues = useCallback((nextValues: TValues, options: SetValuesOptions = {}) => { const updateValues = useCallback(
(nextValues: TValues, options: SetValuesOptions = {}) => {
const { validate: shouldValidate = false, clearErrors = false } = options; const { validate: shouldValidate = false, clearErrors = false } = options;
setValues(nextValues); setValues(nextValues);
@@ -70,26 +71,29 @@ export function useValidatedFields<TValues extends Record<string, string>>({
if (clearErrors) { if (clearErrors) {
setTouched({}); setTouched({});
} }
}, [validate]); },
[validate],
);
const setFieldValue = useCallback(<K extends keyof TValues>( const setFieldValue = useCallback(
<K extends keyof TValues>(
key: K, key: K,
value: TValues[K], value: TValues[K],
options: SetFieldValueOptions = {} options: SetFieldValueOptions = {},
) => { ) => {
const { validate: shouldValidate = true, touch = true } = options; const { validate: shouldValidate = true, touch = true } = options;
if (touch) { if (touch) {
setTouched((current) => ({ setTouched((current) => ({
...current, ...current,
[key]: true [key]: true,
})); }));
} }
setValues((current) => { setValues((current) => {
const nextValues = { const nextValues = {
...current, ...current,
[key]: value [key]: value,
}; };
if (shouldValidate) { if (shouldValidate) {
@@ -98,9 +102,12 @@ export function useValidatedFields<TValues extends Record<string, string>>({
return nextValues; return nextValues;
}); });
}, [validate]); },
[validate],
);
const validateAll = useCallback((options: ValidateAllOptions = {}) => { const validateAll = useCallback(
(options: ValidateAllOptions = {}) => {
const { touchAll: shouldTouchAll = true } = options; const { touchAll: shouldTouchAll = true } = options;
const nextErrors = validate(values); const nextErrors = validate(values);
@@ -111,17 +118,19 @@ export function useValidatedFields<TValues extends Record<string, string>>({
} }
return nextErrors; return nextErrors;
}, [validate, values]); },
[validate, values],
);
const setFieldError = useCallback(<K extends keyof TValues>(key: K, message?: string) => { const setFieldError = useCallback(<K extends keyof TValues>(key: K, message?: string) => {
setTouched((current) => ({ setTouched((current) => ({
...current, ...current,
[key]: true [key]: true,
})); }));
setAllErrors((current) => ({ setAllErrors((current) => ({
...current, ...current,
[key]: message [key]: message,
})); }));
}, []); }, []);
@@ -136,7 +145,7 @@ export function useValidatedFields<TValues extends Record<string, string>>({
setTouched((current) => ({ setTouched((current) => ({
...current, ...current,
...nextTouched ...nextTouched,
})); }));
setAllErrors(nextErrors); setAllErrors(nextErrors);
}, []); }, []);
@@ -161,6 +170,6 @@ export function useValidatedFields<TValues extends Record<string, string>>({
validateAll, validateAll,
setFieldError, setFieldError,
setErrors: updateErrors, setErrors: updateErrors,
clearErrors clearErrors,
}; };
} }

View File

@@ -1,15 +1,27 @@
export { createAuthContext } from './auth/createAuthContext'; export { createAuthContext } from './auth/createAuthContext';
export type { AuthContextValue, AuthState, CreateAuthContextOptions } from './auth/createAuthContext'; export type {
AuthContextValue,
AuthState,
CreateAuthContextOptions,
} from './auth/createAuthContext';
export { decodeJwtPayload, isJwtExpired } from './auth/jwt'; export { decodeJwtPayload, isJwtExpired } from './auth/jwt';
export { createApiClient, ApiError } from './api/createApiClient'; export { createApiClient, ApiError } from './api/createApiClient';
export type { CreateApiClientConfig, RequestOptions, ResolveErrorInput } from './api/createApiClient'; export type {
CreateApiClientConfig,
RequestOptions,
ResolveErrorInput,
} from './api/createApiClient';
export { buildListQuery } from './api/query'; export { buildListQuery } from './api/query';
export { createErrorResolver } from './errors/createErrorResolver'; export { createErrorResolver } from './errors/createErrorResolver';
export type { CreateErrorResolverConfig, ErrorCatalog, ResolveErrorMessageOptions } from './errors/createErrorResolver'; export type {
CreateErrorResolverConfig,
ErrorCatalog,
ResolveErrorMessageOptions,
} from './errors/createErrorResolver';
export { useValidatedFields } from './hooks/useValidatedFields'; export { useValidatedFields } from './hooks/useValidatedFields';
export { useEditableForm } from './hooks/useEditableForm'; export { useEditableForm } from './hooks/useEditableForm';
@@ -20,9 +32,18 @@ export type { SortDirection, SortState } from './hooks/useSorting';
export { useCooldownTimer } from './hooks/useCooldownTimer'; export { useCooldownTimer } from './hooks/useCooldownTimer';
export { LeftMenuProvider, useLeftMenu } from './contexts/LeftMenuContext'; export { LeftMenuProvider, useLeftMenu } from './contexts/LeftMenuContext';
export type { LeftMenuContent, LeftMenuRenderState, LeftMenuStyle } from './contexts/LeftMenuContext'; export type {
LeftMenuContent,
LeftMenuRenderState,
LeftMenuSizing,
LeftMenuStyle,
} from './contexts/LeftMenuContext';
export { RightSidebarProvider, useRightSidebar } from './contexts/RightSidebarContext'; export { RightSidebarProvider, useRightSidebar } from './contexts/RightSidebarContext';
export type { RightSidebarContent, RightSidebarStyle } from './contexts/RightSidebarContext'; export type {
RightSidebarContent,
RightSidebarSizing,
RightSidebarStyle,
} from './contexts/RightSidebarContext';
export { formatDate, capitalize, splitAndCapitalize } from './utils/formatting'; export { formatDate, capitalize, splitAndCapitalize } from './utils/formatting';
export type { SplitMode } from './utils/formatting'; export type { SplitMode } from './utils/formatting';

View File

@@ -1,4 +1,10 @@
import { useCallback, useEffect, useRef, useState, type PointerEvent as ReactPointerEvent } from 'react'; import {
useCallback,
useEffect,
useRef,
useState,
type PointerEvent as ReactPointerEvent,
} from 'react';
const DEFAULT_DESKTOP_BREAKPOINT = 1024; const DEFAULT_DESKTOP_BREAKPOINT = 1024;
@@ -51,15 +57,18 @@ export function useSidePanelMachine({
closeOnPathname, closeOnPathname,
onCloseOnPathname, onCloseOnPathname,
onEscape, onEscape,
desktopBreakpoint = DEFAULT_DESKTOP_BREAKPOINT desktopBreakpoint = DEFAULT_DESKTOP_BREAKPOINT,
}: SidePanelMachineOptions): SidePanelMachineResult { }: SidePanelMachineOptions): SidePanelMachineResult {
const isResizingRef = useRef(false); const isResizingRef = useRef(false);
const resizeStartXRef = useRef(0); const resizeStartXRef = useRef(0);
const resizeStartWidthRef = useRef(0); const resizeStartWidthRef = useRef(0);
const clampWidth = useCallback((value: number) => { const clampWidth = useCallback(
(value: number) => {
return Math.min(maxWidth, Math.max(minWidth, value)); return Math.min(maxWidth, Math.max(minWidth, value));
}, [maxWidth, minWidth]); },
[maxWidth, minWidth],
);
const readStoredWidth = useCallback(() => { const readStoredWidth = useCallback(() => {
if (!globalThis.window) { if (!globalThis.window) {
@@ -67,6 +76,10 @@ export function useSidePanelMachine({
} }
const storedValue = localStorage.getItem(storageKey); const storedValue = localStorage.getItem(storageKey);
if (storedValue == null || storedValue.trim() === '') {
return defaultWidth;
}
const parsed = Number(storedValue); const parsed = Number(storedValue);
if (!Number.isFinite(parsed)) { if (!Number.isFinite(parsed)) {
return defaultWidth; return defaultWidth;
@@ -154,7 +167,8 @@ export function useSidePanelMachine({
}; };
}, [isOpen, onEscape]); }, [isOpen, onEscape]);
const startResize = useCallback((event: ReactPointerEvent<HTMLDivElement>) => { const startResize = useCallback(
(event: ReactPointerEvent<HTMLDivElement>) => {
if (!canResize || !isDesktopViewport(desktopBreakpoint)) { if (!canResize || !isDesktopViewport(desktopBreakpoint)) {
return; return;
} }
@@ -164,11 +178,13 @@ export function useSidePanelMachine({
resizeStartWidthRef.current = width; resizeStartWidthRef.current = width;
document.body.classList.add(resizingBodyClass); document.body.classList.add(resizingBodyClass);
event.preventDefault(); event.preventDefault();
}, [canResize, desktopBreakpoint, resizingBodyClass, width]); },
[canResize, desktopBreakpoint, resizingBodyClass, width],
);
return { return {
width, width,
isDesktop: isDesktopViewport(desktopBreakpoint), isDesktop: isDesktopViewport(desktopBreakpoint),
startResize startResize,
}; };
} }

View File

@@ -1,21 +1,24 @@
export function formatDate(value: string, seconds = false): string { export function formatDate(value: string, seconds = false): string {
const options: Intl.DateTimeFormatOptions = { const options: Intl.DateTimeFormatOptions = {
year: "numeric", year: 'numeric',
month: "2-digit", month: '2-digit',
day: "2-digit", day: '2-digit',
hour: "2-digit", hour: '2-digit',
minute: "2-digit", minute: '2-digit',
...(seconds ? { second: "2-digit" } : {}), ...(seconds ? { second: '2-digit' } : {}),
}; };
return new Date(value).toLocaleString("it-IT", options); return new Date(value).toLocaleString('it-IT', options);
} }
export const capitalize = (str: string) => export const capitalize = (str: string) =>
str.toLowerCase().split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); str
.toLowerCase()
.split(' ')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
export type SplitMode = "underscore" | "camel" | "auto"; export type SplitMode = 'underscore' | 'camel' | 'auto';
/** Title-case a string while preserving short all-caps acronyms (e.g., XML) */ /** Title-case a string while preserving short all-caps acronyms (e.g., XML) */
const toTitleCase = (s: string) => const toTitleCase = (s: string) =>
@@ -23,23 +26,23 @@ const toTitleCase = (s: string) =>
.trim() .trim()
.toLowerCase() .toLowerCase()
.split(/\s+/) .split(/\s+/)
.map(w => .map((w) =>
/^[A-Z]{2,4}$/.test(w) ? w : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase() /^[A-Z]{2,4}$/.test(w) ? w : w.charAt(0).toUpperCase() + w.slice(1).toLowerCase(),
) )
.join(" "); .join(' ');
const splitUnderscoreHyphen = (s: string) => s.replaceAll(/[_-]+/g, " "); const splitUnderscoreHyphen = (s: string) => s.replaceAll(/[_-]+/g, ' ');
/** Insert spaces at camelCase boundaries and around digit/letter edges */ /** Insert spaces at camelCase boundaries and around digit/letter edges */
const splitCamel = (s: string) => const splitCamel = (s: string) =>
s s
// fooBar -> foo Bar ; foo2D -> foo 2D // fooBar -> foo Bar ; foo2D -> foo 2D
.replaceAll(/([a-z0-9])([A-Z])/g, "$1 $2") .replaceAll(/([a-z0-9])([A-Z])/g, '$1 $2')
// XMLHttp -> XML Http (acronym + word) // XMLHttp -> XML Http (acronym + word)
.replaceAll(/([A-Z])([A-Z][a-z])/g, "$1 $2") .replaceAll(/([A-Z])([A-Z][a-z])/g, '$1 $2')
// letter<->digit boundaries // letter<->digit boundaries
.replaceAll(/([a-zA-Z])([0-9])/g, "$1 $2") .replaceAll(/([a-zA-Z])([0-9])/g, '$1 $2')
.replaceAll(/([0-9])([a-zA-Z])/g, "$1 $2"); .replaceAll(/([0-9])([a-zA-Z])/g, '$1 $2');
/** /**
* Split and capitalize either by underscores/hyphens or camelCase. * Split and capitalize either by underscores/hyphens or camelCase.
@@ -48,17 +51,15 @@ const splitCamel = (s: string) =>
* - "camel": split on camelCase boundaries * - "camel": split on camelCase boundaries
* - "auto": pick underscore if present, otherwise camel * - "auto": pick underscore if present, otherwise camel
*/ */
export function splitAndCapitalize(str?: string, mode: SplitMode = "auto"): string { export function splitAndCapitalize(str?: string, mode: SplitMode = 'auto'): string {
if (!str) return ""; if (!str) return '';
// normalize underscores/hyphens first for auto decision // normalize underscores/hyphens first for auto decision
const hasUnderscoreLike = /[_-]/.test(str); const hasUnderscoreLike = /[_-]/.test(str);
const chosen: SplitMode = const chosen: SplitMode = mode === 'auto' ? (hasUnderscoreLike ? 'underscore' : 'camel') : mode;
mode === "auto" ? (hasUnderscoreLike ? "underscore" : "camel") : mode;
const spaced = const spaced = chosen === 'underscore' ? splitUnderscoreHyphen(str) : splitCamel(str);
chosen === "underscore" ? splitUnderscoreHyphen(str) : splitCamel(str);
// collapse extra spaces, then title-case // collapse extra spaces, then title-case
return toTitleCase(spaced.replaceAll(/\s+/g, " ").trim()); return toTitleCase(spaced.replaceAll(/\s+/g, ' ').trim());
} }

View File

@@ -9,10 +9,10 @@ export default defineConfig({
entry: resolve(__dirname, 'src/index.ts'), entry: resolve(__dirname, 'src/index.ts'),
name: 'PanicCore', name: 'PanicCore',
formats: ['es'], formats: ['es'],
fileName: () => 'index.js' fileName: () => 'index.js',
}, },
rollupOptions: { rollupOptions: {
external: ['react'] external: ['react'],
} },
} },
}); });

625
yarn.lock
View File

@@ -16,7 +16,7 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@babel/compat-data/-/compat-data-7.29.0.tgz#00d03e8c0ac24dd9be942c5370990cbe1f17d88d" resolved "https://nexus.beatrice.wtf/repository/npm-group/@babel/compat-data/-/compat-data-7.29.0.tgz#00d03e8c0ac24dd9be942c5370990cbe1f17d88d"
integrity sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg== integrity sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==
"@babel/core@^7.29.0": "@babel/core@^7.24.4", "@babel/core@^7.29.0":
version "7.29.0" version "7.29.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@babel/core/-/core-7.29.0.tgz#5286ad785df7f79d656e88ce86e650d16ca5f322" resolved "https://nexus.beatrice.wtf/repository/npm-group/@babel/core/-/core-7.29.0.tgz#5286ad785df7f79d656e88ce86e650d16ca5f322"
integrity sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA== integrity sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==
@@ -109,7 +109,7 @@
"@babel/template" "^7.28.6" "@babel/template" "^7.28.6"
"@babel/types" "^7.28.6" "@babel/types" "^7.28.6"
"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0": "@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.4", "@babel/parser@^7.28.6", "@babel/parser@^7.29.0":
version "7.29.0" version "7.29.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@babel/parser/-/parser-7.29.0.tgz#669ef345add7d057e92b7ed15f0bac07611831b6" resolved "https://nexus.beatrice.wtf/repository/npm-group/@babel/parser/-/parser-7.29.0.tgz#669ef345add7d057e92b7ed15f0bac07611831b6"
integrity sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww== integrity sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==
@@ -290,6 +290,82 @@
resolved "https://nexus.beatrice.wtf/repository/npm-group/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz#0eaf705c941a218a43dba8e09f1df1d6cd2f1f17" resolved "https://nexus.beatrice.wtf/repository/npm-group/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz#0eaf705c941a218a43dba8e09f1df1d6cd2f1f17"
integrity sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA== integrity sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==
"@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1":
version "4.9.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595"
integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==
dependencies:
eslint-visitor-keys "^3.4.3"
"@eslint-community/regexpp@^4.12.2":
version "4.12.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b"
integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==
"@eslint/config-array@^0.23.2":
version "0.23.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/config-array/-/config-array-0.23.2.tgz#db85beeff7facc685a5775caacb1c845669b9470"
integrity sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A==
dependencies:
"@eslint/object-schema" "^3.0.2"
debug "^4.3.1"
minimatch "^10.2.1"
"@eslint/config-helpers@^0.5.2":
version "0.5.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/config-helpers/-/config-helpers-0.5.2.tgz#314c7b03d02a371ad8c0a7f6821d5a8a8437ba9d"
integrity sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ==
dependencies:
"@eslint/core" "^1.1.0"
"@eslint/core@^1.1.0":
version "1.1.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/core/-/core-1.1.0.tgz#51f5cd970e216fbdae6721ac84491f57f965836d"
integrity sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==
dependencies:
"@types/json-schema" "^7.0.15"
"@eslint/js@^10":
version "10.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/js/-/js-10.0.1.tgz#1e8a876f50117af8ab67e47d5ad94d38d6622583"
integrity sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==
"@eslint/object-schema@^3.0.2":
version "3.0.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/object-schema/-/object-schema-3.0.2.tgz#c59c6a94aa4b428ed7f1615b6a4495c0a21f7a22"
integrity sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw==
"@eslint/plugin-kit@^0.6.0":
version "0.6.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz#e0cb12ec66719cb2211ad36499fb516f2a63899d"
integrity sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==
dependencies:
"@eslint/core" "^1.1.0"
levn "^0.4.1"
"@humanfs/core@^0.19.1":
version "0.19.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77"
integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==
"@humanfs/node@^0.16.6":
version "0.16.7"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26"
integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==
dependencies:
"@humanfs/core" "^0.19.1"
"@humanwhocodes/retry" "^0.4.0"
"@humanwhocodes/module-importer@^1.0.1":
version "1.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2":
version "0.4.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba"
integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==
"@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5": "@jridgewell/gen-mapping@^0.3.12", "@jridgewell/gen-mapping@^0.3.5":
version "0.3.13" version "0.3.13"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" resolved "https://nexus.beatrice.wtf/repository/npm-group/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f"
@@ -487,11 +563,21 @@
dependencies: dependencies:
"@babel/types" "^7.28.2" "@babel/types" "^7.28.2"
"@types/estree@1.0.8": "@types/esrecurse@^4.3.1":
version "4.3.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/esrecurse/-/esrecurse-4.3.1.tgz#6f636af962fbe6191b830bd676ba5986926bccec"
integrity sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==
"@types/estree@1.0.8", "@types/estree@^1.0.6", "@types/estree@^1.0.8":
version "1.0.8" version "1.0.8"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e"
integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
"@types/json-schema@^7.0.15":
version "7.0.15"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
"@types/react@^19.0.0": "@types/react@^19.0.0":
version "19.2.14" version "19.2.14"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/react/-/react-19.2.14.tgz#39604929b5e3957e3a6fa0001dafb17c7af70bad" resolved "https://nexus.beatrice.wtf/repository/npm-group/@types/react/-/react-19.2.14.tgz#39604929b5e3957e3a6fa0001dafb17c7af70bad"
@@ -499,6 +585,102 @@
dependencies: dependencies:
csstype "^3.2.2" csstype "^3.2.2"
"@typescript-eslint/eslint-plugin@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz#5aec3db807a6b8437ea5d5ebf7bd16b4119aba8d"
integrity sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==
dependencies:
"@eslint-community/regexpp" "^4.12.2"
"@typescript-eslint/scope-manager" "8.56.0"
"@typescript-eslint/type-utils" "8.56.0"
"@typescript-eslint/utils" "8.56.0"
"@typescript-eslint/visitor-keys" "8.56.0"
ignore "^7.0.5"
natural-compare "^1.4.0"
ts-api-utils "^2.4.0"
"@typescript-eslint/parser@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/parser/-/parser-8.56.0.tgz#8ecff1678b8b1a742d29c446ccf5eeea7f971d72"
integrity sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==
dependencies:
"@typescript-eslint/scope-manager" "8.56.0"
"@typescript-eslint/types" "8.56.0"
"@typescript-eslint/typescript-estree" "8.56.0"
"@typescript-eslint/visitor-keys" "8.56.0"
debug "^4.4.3"
"@typescript-eslint/project-service@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/project-service/-/project-service-8.56.0.tgz#bb8562fecd8f7922e676fc6a1189c20dd7991d73"
integrity sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==
dependencies:
"@typescript-eslint/tsconfig-utils" "^8.56.0"
"@typescript-eslint/types" "^8.56.0"
debug "^4.4.3"
"@typescript-eslint/scope-manager@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz#604030a4c6433df3728effdd441d47f45a86edb4"
integrity sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==
dependencies:
"@typescript-eslint/types" "8.56.0"
"@typescript-eslint/visitor-keys" "8.56.0"
"@typescript-eslint/tsconfig-utils@8.56.0", "@typescript-eslint/tsconfig-utils@^8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz#2538ce83cbc376e685487960cbb24b65fe2abc4e"
integrity sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==
"@typescript-eslint/type-utils@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz#72b4edc1fc73988998f1632b3ec99c2a66eaac6e"
integrity sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==
dependencies:
"@typescript-eslint/types" "8.56.0"
"@typescript-eslint/typescript-estree" "8.56.0"
"@typescript-eslint/utils" "8.56.0"
debug "^4.4.3"
ts-api-utils "^2.4.0"
"@typescript-eslint/types@8.56.0", "@typescript-eslint/types@^8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/types/-/types-8.56.0.tgz#a2444011b9a98ca13d70411d2cbfed5443b3526a"
integrity sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==
"@typescript-eslint/typescript-estree@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz#fadbc74c14c5bac947db04980ff58bb178701c2e"
integrity sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==
dependencies:
"@typescript-eslint/project-service" "8.56.0"
"@typescript-eslint/tsconfig-utils" "8.56.0"
"@typescript-eslint/types" "8.56.0"
"@typescript-eslint/visitor-keys" "8.56.0"
debug "^4.4.3"
minimatch "^9.0.5"
semver "^7.7.3"
tinyglobby "^0.2.15"
ts-api-utils "^2.4.0"
"@typescript-eslint/utils@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/utils/-/utils-8.56.0.tgz#063ce6f702ec603de1b83ee795ed5e877d6f7841"
integrity sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==
dependencies:
"@eslint-community/eslint-utils" "^4.9.1"
"@typescript-eslint/scope-manager" "8.56.0"
"@typescript-eslint/types" "8.56.0"
"@typescript-eslint/typescript-estree" "8.56.0"
"@typescript-eslint/visitor-keys@8.56.0":
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz#7d6592ab001827d3ce052155edf7ecad19688d7d"
integrity sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==
dependencies:
"@typescript-eslint/types" "8.56.0"
eslint-visitor-keys "^5.0.0"
"@vitejs/plugin-react@^5.0.0": "@vitejs/plugin-react@^5.0.0":
version "5.1.4" version "5.1.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz#5b477e060bf612a7394c4febacc5de33a219b0e4" resolved "https://nexus.beatrice.wtf/repository/npm-group/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz#5b477e060bf612a7394c4febacc5de33a219b0e4"
@@ -511,11 +693,43 @@
"@types/babel__core" "^7.20.5" "@types/babel__core" "^7.20.5"
react-refresh "^0.18.0" react-refresh "^0.18.0"
acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn@^8.16.0:
version "8.16.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a"
integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==
ajv@^6.12.4:
version "6.14.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a"
integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
balanced-match@^4.0.2:
version "4.0.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/balanced-match/-/balanced-match-4.0.4.tgz#bfb10662feed8196a2c62e7c68e17720c274179a"
integrity sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==
baseline-browser-mapping@^2.9.0: baseline-browser-mapping@^2.9.0:
version "2.10.0" version "2.10.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz#5b09935025bf8a80e29130251e337c6a7fc8cbb9" resolved "https://nexus.beatrice.wtf/repository/npm-group/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz#5b09935025bf8a80e29130251e337c6a7fc8cbb9"
integrity sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA== integrity sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==
brace-expansion@^5.0.2:
version "5.0.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/brace-expansion/-/brace-expansion-5.0.3.tgz#6a9c6c268f85b53959ec527aeafe0f7300258eef"
integrity sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==
dependencies:
balanced-match "^4.0.2"
browserslist@^4.24.0: browserslist@^4.24.0:
version "4.28.1" version "4.28.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95" resolved "https://nexus.beatrice.wtf/repository/npm-group/browserslist/-/browserslist-4.28.1.tgz#7f534594628c53c63101079e27e40de490456a95"
@@ -537,18 +751,32 @@ convert-source-map@^2.0.0:
resolved "https://nexus.beatrice.wtf/repository/npm-group/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" resolved "https://nexus.beatrice.wtf/repository/npm-group/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
cross-spawn@^7.0.6:
version "7.0.6"
resolved "https://nexus.beatrice.wtf/repository/npm-group/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
dependencies:
path-key "^3.1.0"
shebang-command "^2.0.0"
which "^2.0.1"
csstype@^3.2.2: csstype@^3.2.2:
version "3.2.3" version "3.2.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a" resolved "https://nexus.beatrice.wtf/repository/npm-group/csstype/-/csstype-3.2.3.tgz#ec48c0f3e993e50648c86da559e2610995cf989a"
integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ== integrity sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==
debug@^4.1.0, debug@^4.3.1: debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.4.3:
version "4.4.3" version "4.4.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" resolved "https://nexus.beatrice.wtf/repository/npm-group/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
dependencies: dependencies:
ms "^2.1.3" ms "^2.1.3"
deep-is@^0.1.3:
version "0.1.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
electron-to-chromium@^1.5.263: electron-to-chromium@^1.5.263:
version "1.5.302" version "1.5.302"
resolved "https://nexus.beatrice.wtf/repository/npm-group/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz#032a5802b31f7119269959c69fe2015d8dad5edb" resolved "https://nexus.beatrice.wtf/repository/npm-group/electron-to-chromium/-/electron-to-chromium-1.5.302.tgz#032a5802b31f7119269959c69fe2015d8dad5edb"
@@ -591,11 +819,164 @@ escalade@^3.2.0:
resolved "https://nexus.beatrice.wtf/repository/npm-group/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" resolved "https://nexus.beatrice.wtf/repository/npm-group/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
eslint-plugin-react-hooks@^7.0.1:
version "7.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz#66e258db58ece50723ef20cc159f8aa908219169"
integrity sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==
dependencies:
"@babel/core" "^7.24.4"
"@babel/parser" "^7.24.4"
hermes-parser "^0.25.1"
zod "^3.25.0 || ^4.0.0"
zod-validation-error "^3.5.0 || ^4.0.0"
eslint-plugin-react-refresh@^0.5.1:
version "0.5.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.1.tgz#d13f1cfea4718a108060a41219d1849287278adc"
integrity sha512-Y5sJsreCUdGcF4mLD70iJNa47Z6CX4MsqJoJBARDC/fBhmacSby7k73UuValr0F9M7GfWKpEqS4NMsniWkVxQw==
eslint-scope@^9.1.1:
version "9.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-scope/-/eslint-scope-9.1.1.tgz#f6a209486e38bd28356b5feb07d445cc99c89967"
integrity sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==
dependencies:
"@types/esrecurse" "^4.3.1"
"@types/estree" "^1.0.8"
esrecurse "^4.3.0"
estraverse "^5.2.0"
eslint-visitor-keys@^3.4.3:
version "3.4.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint-visitor-keys@^5.0.0, eslint-visitor-keys@^5.0.1:
version "5.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be"
integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==
eslint@^10:
version "10.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/eslint/-/eslint-10.0.1.tgz#b5c5f7706782a21590ba6451e7a30d2947273c2d"
integrity sha512-20MV9SUdeN6Jd84xESsKhRly+/vxI+hwvpBMA93s+9dAcjdCuCojn4IqUGS3lvVaqjVYGYHSRMCpeFtF2rQYxQ==
dependencies:
"@eslint-community/eslint-utils" "^4.8.0"
"@eslint-community/regexpp" "^4.12.2"
"@eslint/config-array" "^0.23.2"
"@eslint/config-helpers" "^0.5.2"
"@eslint/core" "^1.1.0"
"@eslint/plugin-kit" "^0.6.0"
"@humanfs/node" "^0.16.6"
"@humanwhocodes/module-importer" "^1.0.1"
"@humanwhocodes/retry" "^0.4.2"
"@types/estree" "^1.0.6"
ajv "^6.12.4"
cross-spawn "^7.0.6"
debug "^4.3.2"
escape-string-regexp "^4.0.0"
eslint-scope "^9.1.1"
eslint-visitor-keys "^5.0.1"
espree "^11.1.1"
esquery "^1.7.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
file-entry-cache "^8.0.0"
find-up "^5.0.0"
glob-parent "^6.0.2"
ignore "^5.2.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
json-stable-stringify-without-jsonify "^1.0.1"
minimatch "^10.2.1"
natural-compare "^1.4.0"
optionator "^0.9.3"
espree@^11.1.1:
version "11.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/espree/-/espree-11.1.1.tgz#866f6bc9ccccd6f28876b7a6463abb281b9cb847"
integrity sha512-AVHPqQoZYc+RUM4/3Ly5udlZY/U4LS8pIG05jEjWM2lQMU/oaZ7qshzAl2YP1tfNmXfftH3ohurfwNAug+MnsQ==
dependencies:
acorn "^8.16.0"
acorn-jsx "^5.3.2"
eslint-visitor-keys "^5.0.1"
esquery@^1.7.0:
version "1.7.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d"
integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==
dependencies:
estraverse "^5.1.0"
esrecurse@^4.3.0:
version "4.3.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
dependencies:
estraverse "^5.2.0"
estraverse@^5.1.0, estraverse@^5.2.0:
version "5.3.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
esutils@^2.0.2:
version "2.0.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
fast-levenshtein@^2.0.6:
version "2.0.6"
resolved "https://nexus.beatrice.wtf/repository/npm-group/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fdir@^6.5.0: fdir@^6.5.0:
version "6.5.0" version "6.5.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" resolved "https://nexus.beatrice.wtf/repository/npm-group/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
file-entry-cache@^8.0.0:
version "8.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
dependencies:
flat-cache "^4.0.0"
find-up@^5.0.0:
version "5.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
dependencies:
locate-path "^6.0.0"
path-exists "^4.0.0"
flat-cache@^4.0.0:
version "4.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
dependencies:
flatted "^3.2.9"
keyv "^4.5.4"
flatted@^3.2.9:
version "3.3.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358"
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==
fsevents@~2.3.2, fsevents@~2.3.3: fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3" version "2.3.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" resolved "https://nexus.beatrice.wtf/repository/npm-group/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
@@ -606,6 +987,62 @@ gensync@^1.0.0-beta.2:
resolved "https://nexus.beatrice.wtf/repository/npm-group/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" resolved "https://nexus.beatrice.wtf/repository/npm-group/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
glob-parent@^6.0.2:
version "6.0.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
dependencies:
is-glob "^4.0.3"
globals@^17.3.0:
version "17.3.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/globals/-/globals-17.3.0.tgz#8b96544c2fa91afada02747cc9731c002a96f3b9"
integrity sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==
hermes-estree@0.25.1:
version "0.25.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/hermes-estree/-/hermes-estree-0.25.1.tgz#6aeec17d1983b4eabf69721f3aa3eb705b17f480"
integrity sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==
hermes-parser@^0.25.1:
version "0.25.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/hermes-parser/-/hermes-parser-0.25.1.tgz#5be0e487b2090886c62bd8a11724cd766d5f54d1"
integrity sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==
dependencies:
hermes-estree "0.25.1"
ignore@^5.2.0:
version "5.3.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
ignore@^7.0.5:
version "7.0.5"
resolved "https://nexus.beatrice.wtf/repository/npm-group/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9"
integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
is-extglob@^2.1.1:
version "2.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
is-glob@^4.0.0, is-glob@^4.0.3:
version "4.0.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
dependencies:
is-extglob "^2.1.1"
isexe@^2.0.0:
version "2.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
js-tokens@^4.0.0: js-tokens@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" resolved "https://nexus.beatrice.wtf/repository/npm-group/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -616,11 +1053,48 @@ jsesc@^3.0.2:
resolved "https://nexus.beatrice.wtf/repository/npm-group/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" resolved "https://nexus.beatrice.wtf/repository/npm-group/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
json-buffer@3.0.1:
version "3.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
json5@^2.2.3: json5@^2.2.3:
version "2.2.3" version "2.2.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" resolved "https://nexus.beatrice.wtf/repository/npm-group/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
keyv@^4.5.4:
version "4.5.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
dependencies:
json-buffer "3.0.1"
levn@^0.4.1:
version "0.4.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
dependencies:
prelude-ls "^1.2.1"
type-check "~0.4.0"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
dependencies:
p-locate "^5.0.0"
lru-cache@^5.1.1: lru-cache@^5.1.1:
version "5.1.1" version "5.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" resolved "https://nexus.beatrice.wtf/repository/npm-group/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -628,6 +1102,20 @@ lru-cache@^5.1.1:
dependencies: dependencies:
yallist "^3.0.2" yallist "^3.0.2"
minimatch@^10.2.1:
version "10.2.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/minimatch/-/minimatch-10.2.2.tgz#361603ee323cfb83496fea2ae17cc44ea4e1f99f"
integrity sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==
dependencies:
brace-expansion "^5.0.2"
minimatch@^9.0.5:
version "9.0.6"
resolved "https://nexus.beatrice.wtf/repository/npm-group/minimatch/-/minimatch-9.0.6.tgz#a7e3bccfcb3d78ec1bf8d51c9ba749080237a5c8"
integrity sha512-kQAVowdR33euIqeA0+VZTDqU+qo1IeVY+hrKYtZMio3Pg0P0vuh/kwRylLUddJhB6pf3q/botcOvRtx4IN1wqQ==
dependencies:
brace-expansion "^5.0.2"
ms@^2.1.3: ms@^2.1.3:
version "2.1.3" version "2.1.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" resolved "https://nexus.beatrice.wtf/repository/npm-group/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
@@ -638,11 +1126,52 @@ nanoid@^3.3.11:
resolved "https://nexus.beatrice.wtf/repository/npm-group/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" resolved "https://nexus.beatrice.wtf/repository/npm-group/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
node-releases@^2.0.27: node-releases@^2.0.27:
version "2.0.27" version "2.0.27"
resolved "https://nexus.beatrice.wtf/repository/npm-group/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" resolved "https://nexus.beatrice.wtf/repository/npm-group/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e"
integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==
optionator@^0.9.3:
version "0.9.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734"
integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==
dependencies:
deep-is "^0.1.3"
fast-levenshtein "^2.0.6"
levn "^0.4.1"
prelude-ls "^1.2.1"
type-check "^0.4.0"
word-wrap "^1.2.5"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
dependencies:
yocto-queue "^0.1.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
dependencies:
p-limit "^3.0.2"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
path-key@^3.1.0:
version "3.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
picocolors@^1.1.1: picocolors@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" resolved "https://nexus.beatrice.wtf/repository/npm-group/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
@@ -662,6 +1191,21 @@ postcss@^8.5.6:
picocolors "^1.1.1" picocolors "^1.1.1"
source-map-js "^1.2.1" source-map-js "^1.2.1"
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
prettier@^3.8.1:
version "3.8.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/prettier/-/prettier-3.8.1.tgz#edf48977cf991558f4fcbd8a3ba6015ba2a3a173"
integrity sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==
punycode@^2.1.0:
version "2.3.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
react-dom@^19.0.0: react-dom@^19.0.0:
version "19.2.4" version "19.2.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/react-dom/-/react-dom-19.2.4.tgz#6fac6bd96f7db477d966c7ec17c1a2b1ad8e6591" resolved "https://nexus.beatrice.wtf/repository/npm-group/react-dom/-/react-dom-19.2.4.tgz#6fac6bd96f7db477d966c7ec17c1a2b1ad8e6591"
@@ -723,6 +1267,23 @@ semver@^6.3.1:
resolved "https://nexus.beatrice.wtf/repository/npm-group/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" resolved "https://nexus.beatrice.wtf/repository/npm-group/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.7.3:
version "7.7.4"
resolved "https://nexus.beatrice.wtf/repository/npm-group/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a"
integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==
shebang-command@^2.0.0:
version "2.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
dependencies:
shebang-regex "^3.0.0"
shebang-regex@^3.0.0:
version "3.0.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
source-map-js@^1.2.1: source-map-js@^1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" resolved "https://nexus.beatrice.wtf/repository/npm-group/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
@@ -736,6 +1297,28 @@ tinyglobby@^0.2.15:
fdir "^6.5.0" fdir "^6.5.0"
picomatch "^4.0.3" picomatch "^4.0.3"
ts-api-utils@^2.4.0:
version "2.4.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/ts-api-utils/-/ts-api-utils-2.4.0.tgz#2690579f96d2790253bdcf1ca35d569ad78f9ad8"
integrity sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==
type-check@^0.4.0, type-check@~0.4.0:
version "0.4.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
dependencies:
prelude-ls "^1.2.1"
typescript-eslint@^8.56.0:
version "8.56.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/typescript-eslint/-/typescript-eslint-8.56.0.tgz#f4686ccaaf2fb86daf0133820da40ca5961a2236"
integrity sha512-c7toRLrotJ9oixgdW7liukZpsnq5CZ7PuKztubGYlNppuTqhIoWfhgHo/7EU0v06gS2l/x0i2NEFK1qMIf0rIg==
dependencies:
"@typescript-eslint/eslint-plugin" "8.56.0"
"@typescript-eslint/parser" "8.56.0"
"@typescript-eslint/typescript-estree" "8.56.0"
"@typescript-eslint/utils" "8.56.0"
typescript@^5.6.2: typescript@^5.6.2:
version "5.9.3" version "5.9.3"
resolved "https://nexus.beatrice.wtf/repository/npm-group/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" resolved "https://nexus.beatrice.wtf/repository/npm-group/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f"
@@ -749,6 +1332,13 @@ update-browserslist-db@^1.2.0:
escalade "^3.2.0" escalade "^3.2.0"
picocolors "^1.1.1" picocolors "^1.1.1"
uri-js@^4.2.2:
version "4.4.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
vite@^7.0.0: vite@^7.0.0:
version "7.3.1" version "7.3.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507" resolved "https://nexus.beatrice.wtf/repository/npm-group/vite/-/vite-7.3.1.tgz#7f6cfe8fb9074138605e822a75d9d30b814d6507"
@@ -763,7 +1353,34 @@ vite@^7.0.0:
optionalDependencies: optionalDependencies:
fsevents "~2.3.3" fsevents "~2.3.3"
which@^2.0.1:
version "2.0.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
dependencies:
isexe "^2.0.0"
word-wrap@^1.2.5:
version "1.2.5"
resolved "https://nexus.beatrice.wtf/repository/npm-group/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
yallist@^3.0.2: yallist@^3.0.2:
version "3.1.1" version "3.1.1"
resolved "https://nexus.beatrice.wtf/repository/npm-group/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" resolved "https://nexus.beatrice.wtf/repository/npm-group/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://nexus.beatrice.wtf/repository/npm-group/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
"zod-validation-error@^3.5.0 || ^4.0.0":
version "4.0.2"
resolved "https://nexus.beatrice.wtf/repository/npm-group/zod-validation-error/-/zod-validation-error-4.0.2.tgz#bc605eba49ce0fcd598c127fee1c236be3f22918"
integrity sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==
"zod@^3.25.0 || ^4.0.0":
version "4.3.6"
resolved "https://nexus.beatrice.wtf/repository/npm-group/zod/-/zod-4.3.6.tgz#89c56e0aa7d2b05107d894412227087885ab112a"
integrity sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==