mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Style mobile pairing QR codes (#2775)
## Summary - render mobile pairing QR codes locally with Wallet-inspired styling - hide the raw pairing URI behind a matching copy button - add focused rendering and dialog coverage ## Test plan - desktop lint and 3,489 desktop tests - focused pairing dialog Playwright test - decoded the rendered QR back to the exact pairing URI
This commit is contained in:
@@ -66,6 +66,7 @@
|
||||
"jdenticon": "^3.3.0",
|
||||
"lucide-react": "^1.0.0",
|
||||
"motion": "^12.38.0",
|
||||
"qrcode": "^1.5.4",
|
||||
"qrcode.react": "^4.2.0",
|
||||
"react": "^19.1.0",
|
||||
"react-diff-view": "^3.3.2",
|
||||
|
||||
@@ -112,6 +112,7 @@ export default defineConfig({
|
||||
"**/onboarding-backup.spec.ts",
|
||||
"**/onboarding-agent-defaults.spec.ts",
|
||||
"**/nostr-bind.spec.ts",
|
||||
"**/mobile-pairing-qr.spec.ts",
|
||||
"**/profile-nsec-reveal.spec.ts",
|
||||
"**/signout-confirmation.spec.ts",
|
||||
"**/agent-provider-dropdowns.spec.ts",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { QRCodeSVG } from "qrcode.react";
|
||||
import {
|
||||
Check,
|
||||
Copy,
|
||||
@@ -19,6 +18,7 @@ import {
|
||||
startPairing,
|
||||
} from "@/shared/api/tauri";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import { StyledQrCode } from "@/shared/ui/styled-qr-code";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -176,11 +176,11 @@ function PairingDialog({
|
||||
return (
|
||||
<Dialog onOpenChange={handleOpenChange} open={open}>
|
||||
<DialogContent
|
||||
className="max-w-md overflow-hidden p-0"
|
||||
className="max-w-md gap-0 overflow-hidden border-0 px-6 pb-6 pt-6"
|
||||
data-testid="mobile-pairing-dialog"
|
||||
>
|
||||
<div className="flex max-h-[85vh] flex-col">
|
||||
<DialogHeader className="border-b border-border/60 px-6 py-5 pr-14">
|
||||
<DialogHeader className="shrink-0 pb-5 pr-8">
|
||||
<DialogTitle>Pair Mobile Device</DialogTitle>
|
||||
<DialogDescription>
|
||||
{step === "sas"
|
||||
@@ -191,7 +191,7 @@ function PairingDialog({
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex-1 overflow-y-auto px-6 py-4">
|
||||
<div className="min-h-0 flex-1 overflow-y-auto pt-4">
|
||||
{step === "error" && error ? (
|
||||
<div className="flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive">
|
||||
<TriangleAlert className="mt-0.5 h-4 w-4 shrink-0" />
|
||||
@@ -205,35 +205,30 @@ function PairingDialog({
|
||||
</p>
|
||||
</div>
|
||||
) : step === "qr" && qrUri ? (
|
||||
<div className="space-y-4">
|
||||
<div className="flex justify-center rounded-lg border border-border/70 bg-white p-4">
|
||||
<QRCodeSVG
|
||||
<div className="mx-auto grid w-fit gap-4">
|
||||
<div
|
||||
className="rounded-lg border border-border/70 bg-white p-3"
|
||||
data-testid="mobile-pairing-qr-container"
|
||||
>
|
||||
<StyledQrCode
|
||||
centerImageSrc="/app-icon@2x.png"
|
||||
data-testid="mobile-pairing-qr"
|
||||
level="M"
|
||||
size={240}
|
||||
title="Mobile pairing QR code"
|
||||
value={qrUri}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<p className="text-xs font-medium text-muted-foreground">
|
||||
Pairing code
|
||||
</p>
|
||||
<button
|
||||
className="flex w-full min-w-0 items-center gap-2 break-all rounded-lg border border-border bg-muted/50 px-3 py-2 text-left text-xs transition-colors hover:bg-muted/70"
|
||||
data-testid="copy-pairing-code"
|
||||
onClick={handleCopy}
|
||||
title="Copy pairing code"
|
||||
type="button"
|
||||
>
|
||||
<code className="min-w-0 flex-1 break-all">{qrUri}</code>
|
||||
<Copy className="h-4 w-4 shrink-0" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="text-center text-xs text-muted-foreground">
|
||||
Waiting for mobile device to scan...
|
||||
</p>
|
||||
<Button
|
||||
className="w-full"
|
||||
data-testid="copy-pairing-code"
|
||||
onClick={handleCopy}
|
||||
type="button"
|
||||
variant="outline"
|
||||
>
|
||||
<Copy className="mr-1.5 h-4 w-4" />
|
||||
Copy pairing code
|
||||
</Button>
|
||||
</div>
|
||||
) : step === "sas" && sasCode ? (
|
||||
<div className="space-y-4">
|
||||
@@ -297,17 +292,6 @@ function PairingDialog({
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end border-t border-border/60 bg-background/95 px-6 py-4">
|
||||
<Button
|
||||
data-testid="mobile-pairing-done"
|
||||
onClick={() => handleOpenChange(false)}
|
||||
size="sm"
|
||||
variant="outline"
|
||||
>
|
||||
{step === "done" ? "Done" : "Close"}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import React from "react";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
|
||||
import { StyledQrCode } from "./styled-qr-code.tsx";
|
||||
|
||||
const TEST_PAIRING_URI =
|
||||
"nostrpair://8f4b8db31967ce14fef970a1ff1e8eecf19a430aa1c83875e2f5be68dcac0f1a?relay=wss%3A%2F%2Frelay.example.com&secret=87d5a8cfd5807a0cb44f728b67d88d6dcb8daf99be137c158f21a50c1e913c0a&v=1";
|
||||
|
||||
test("renders the Wallet-style QR geometry locally", () => {
|
||||
const html = renderToStaticMarkup(
|
||||
React.createElement(StyledQrCode, {
|
||||
centerImageSrc: "/app-icon@2x.png",
|
||||
title: "Mobile pairing QR code",
|
||||
value: TEST_PAIRING_URI,
|
||||
}),
|
||||
);
|
||||
|
||||
assert.match(html, /aria-label="Mobile pairing QR code"/);
|
||||
assert.match(html, /data-qr-matrix-size="57"/);
|
||||
assert.equal((html.match(/data-qr-finder-pattern=""/g) ?? []).length, 3);
|
||||
assert.ok(
|
||||
(html.match(/<circle /g) ?? []).length > 100,
|
||||
"expected the QR payload to render as individual circular data cells",
|
||||
);
|
||||
assert.match(html, /href="\/app-icon@2x\.png"/);
|
||||
});
|
||||
|
||||
test("uses a deterministic lower-density matrix for the same payload", () => {
|
||||
const first = renderToStaticMarkup(
|
||||
React.createElement(StyledQrCode, { value: TEST_PAIRING_URI }),
|
||||
);
|
||||
const second = renderToStaticMarkup(
|
||||
React.createElement(StyledQrCode, { value: TEST_PAIRING_URI }),
|
||||
);
|
||||
|
||||
assert.equal(first, second);
|
||||
});
|
||||
@@ -0,0 +1,203 @@
|
||||
import { useId, useMemo, type ReactNode, type SVGProps } from "react";
|
||||
import { create } from "qrcode";
|
||||
|
||||
const CELL_SPACING_RATIO = 0.2;
|
||||
const FINDER_PATTERN_SIZE = 7;
|
||||
const QUIET_ZONE_SIZE = 4;
|
||||
const MAX_CENTER_OBSCURED_RATIO = 0.1;
|
||||
const CENTER_ICON_SIZE_RATIO = 0.8;
|
||||
|
||||
type StyledQrCodeProps = Omit<
|
||||
SVGProps<SVGSVGElement>,
|
||||
"children" | "height" | "title" | "width"
|
||||
> & {
|
||||
backgroundColor?: string;
|
||||
centerImageSrc?: string;
|
||||
foregroundColor?: string;
|
||||
size?: number;
|
||||
title?: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
function isFinderCell(row: number, column: number, matrixSize: number) {
|
||||
const isTop = row < FINDER_PATTERN_SIZE;
|
||||
const isLeft = column < FINDER_PATTERN_SIZE;
|
||||
const isRight = column >= matrixSize - FINDER_PATTERN_SIZE;
|
||||
const isBottom = row >= matrixSize - FINDER_PATTERN_SIZE;
|
||||
|
||||
return (isTop && isLeft) || (isTop && isRight) || (isBottom && isLeft);
|
||||
}
|
||||
|
||||
function getCenterAreaSize(matrixSize: number) {
|
||||
const maxArea = matrixSize * matrixSize * MAX_CENTER_OBSCURED_RATIO;
|
||||
const maxSide = Math.floor(Math.sqrt(maxArea));
|
||||
return maxSide % 2 === 0 ? maxSide - 1 : maxSide;
|
||||
}
|
||||
|
||||
function FinderPattern({
|
||||
backgroundColor,
|
||||
foregroundColor,
|
||||
x,
|
||||
y,
|
||||
}: {
|
||||
backgroundColor: string;
|
||||
foregroundColor: string;
|
||||
x: number;
|
||||
y: number;
|
||||
}) {
|
||||
return (
|
||||
<g data-qr-finder-pattern="">
|
||||
<rect
|
||||
fill={foregroundColor}
|
||||
height={FINDER_PATTERN_SIZE}
|
||||
rx={2}
|
||||
width={FINDER_PATTERN_SIZE}
|
||||
x={x}
|
||||
y={y}
|
||||
/>
|
||||
<rect
|
||||
fill={backgroundColor}
|
||||
height={FINDER_PATTERN_SIZE - 2}
|
||||
rx={0.8}
|
||||
width={FINDER_PATTERN_SIZE - 2}
|
||||
x={x + 1}
|
||||
y={y + 1}
|
||||
/>
|
||||
<rect
|
||||
fill={foregroundColor}
|
||||
height={FINDER_PATTERN_SIZE - 4}
|
||||
rx={0.4}
|
||||
width={FINDER_PATTERN_SIZE - 4}
|
||||
x={x + 2}
|
||||
y={y + 2}
|
||||
/>
|
||||
</g>
|
||||
);
|
||||
}
|
||||
|
||||
export function StyledQrCode({
|
||||
backgroundColor = "#ffffff",
|
||||
centerImageSrc,
|
||||
foregroundColor = "#000000",
|
||||
size = 240,
|
||||
title = "QR code",
|
||||
value,
|
||||
...svgProps
|
||||
}: StyledQrCodeProps) {
|
||||
const clipId = `styled-qr-logo-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
||||
const matrix = useMemo(
|
||||
() => create(value, { errorCorrectionLevel: "M" }).modules,
|
||||
[value],
|
||||
);
|
||||
const viewBoxSize = matrix.size + QUIET_ZONE_SIZE * 2;
|
||||
const dataCellSize = 1 - CELL_SPACING_RATIO;
|
||||
const dataCellRadius = dataCellSize / 2;
|
||||
const centerAreaSize = centerImageSrc ? getCenterAreaSize(matrix.size) : 0;
|
||||
const centerAreaStart = (matrix.size - centerAreaSize) / 2;
|
||||
const centerAreaEnd = centerAreaStart + centerAreaSize;
|
||||
const centerImageSize = centerAreaSize * CENTER_ICON_SIZE_RATIO;
|
||||
const centerImageStart = (matrix.size - centerImageSize) / 2;
|
||||
const cells: ReactNode[] = [];
|
||||
|
||||
for (let row = 0; row < matrix.size; row += 1) {
|
||||
for (let column = 0; column < matrix.size; column += 1) {
|
||||
const isCenterCell =
|
||||
centerImageSrc &&
|
||||
row >= centerAreaStart &&
|
||||
row < centerAreaEnd &&
|
||||
column >= centerAreaStart &&
|
||||
column < centerAreaEnd;
|
||||
|
||||
if (
|
||||
!matrix.get(row, column) ||
|
||||
isFinderCell(row, column, matrix.size) ||
|
||||
isCenterCell
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cells.push(
|
||||
<circle
|
||||
cx={column + 0.5}
|
||||
cy={row + 0.5}
|
||||
fill={foregroundColor}
|
||||
key={`${row}-${column}`}
|
||||
r={dataCellRadius}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<svg
|
||||
{...svgProps}
|
||||
aria-label={title}
|
||||
data-qr-matrix-size={matrix.size}
|
||||
height={size}
|
||||
role="img"
|
||||
viewBox={`${-QUIET_ZONE_SIZE} ${-QUIET_ZONE_SIZE} ${viewBoxSize} ${viewBoxSize}`}
|
||||
width={size}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>{title}</title>
|
||||
<rect
|
||||
fill={backgroundColor}
|
||||
height={viewBoxSize}
|
||||
width={viewBoxSize}
|
||||
x={-QUIET_ZONE_SIZE}
|
||||
y={-QUIET_ZONE_SIZE}
|
||||
/>
|
||||
<g data-qr-data-cells="">{cells}</g>
|
||||
<FinderPattern
|
||||
backgroundColor={backgroundColor}
|
||||
foregroundColor={foregroundColor}
|
||||
x={0}
|
||||
y={0}
|
||||
/>
|
||||
<FinderPattern
|
||||
backgroundColor={backgroundColor}
|
||||
foregroundColor={foregroundColor}
|
||||
x={matrix.size - FINDER_PATTERN_SIZE}
|
||||
y={0}
|
||||
/>
|
||||
<FinderPattern
|
||||
backgroundColor={backgroundColor}
|
||||
foregroundColor={foregroundColor}
|
||||
x={0}
|
||||
y={matrix.size - FINDER_PATTERN_SIZE}
|
||||
/>
|
||||
{centerImageSrc ? (
|
||||
<>
|
||||
<defs>
|
||||
<clipPath id={clipId}>
|
||||
<rect
|
||||
height={centerImageSize}
|
||||
rx={2}
|
||||
width={centerImageSize}
|
||||
x={centerImageStart}
|
||||
y={centerImageStart}
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<rect
|
||||
fill={foregroundColor}
|
||||
height={centerImageSize}
|
||||
rx={2}
|
||||
width={centerImageSize}
|
||||
x={centerImageStart}
|
||||
y={centerImageStart}
|
||||
/>
|
||||
<image
|
||||
clipPath={`url(#${clipId})`}
|
||||
height={centerImageSize}
|
||||
href={centerImageSrc}
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
width={centerImageSize}
|
||||
x={centerImageStart}
|
||||
y={centerImageStart}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -10902,6 +10902,11 @@ export function maybeInstallE2eTauriMocks() {
|
||||
case "plugin:event|listen":
|
||||
// Tauri event system (pairing, huddle) — no-op in e2e, return unlisten fn ID
|
||||
return Math.floor(Math.random() * 1_000_000);
|
||||
case "start_pairing":
|
||||
return "nostrpair://8f4b8db31967ce14fef970a1ff1e8eecf19a430aa1c83875e2f5be68dcac0f1a?relay=wss%3A%2F%2Frelay.example.com&secret=87d5a8cfd5807a0cb44f728b67d88d6dcb8daf99be137c158f21a50c1e913c0a&v=1";
|
||||
case "cancel_pairing":
|
||||
case "confirm_pairing_sas":
|
||||
return null;
|
||||
// ── NIP-IA identity archival ────────────────────────────────────────
|
||||
// These mocks drive the archive-button gate matrix in
|
||||
// tests/e2e/identity-archive.spec.ts. Defaults keep the button hidden
|
||||
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
declare module "qrcode" {
|
||||
type ErrorCorrectionLevel = "L" | "M" | "Q" | "H";
|
||||
|
||||
type BitMatrix = {
|
||||
get(row: number, column: number): number;
|
||||
size: number;
|
||||
};
|
||||
|
||||
type QrCode = {
|
||||
modules: BitMatrix;
|
||||
};
|
||||
|
||||
export function create(
|
||||
value: string,
|
||||
options?: { errorCorrectionLevel?: ErrorCorrectionLevel },
|
||||
): QrCode;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { mkdirSync } from "node:fs";
|
||||
|
||||
import { installMockBridge } from "../helpers/bridge";
|
||||
import { waitForAnimations } from "../helpers/animations";
|
||||
|
||||
const SCREENSHOT_DIR = "test-results/mobile-pairing-qr";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await installMockBridge(page);
|
||||
});
|
||||
|
||||
test("mobile pairing uses the local Wallet-style QR renderer", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto("/");
|
||||
await page.getByTestId("open-settings").click();
|
||||
await page.getByTestId("profile-popover-settings").click();
|
||||
await page.getByTestId("settings-nav-mobile").click();
|
||||
await page.getByTestId("pair-mobile-button").click();
|
||||
|
||||
const dialog = page.getByTestId("mobile-pairing-dialog");
|
||||
const qrCode = page.getByTestId("mobile-pairing-qr");
|
||||
const qrContainer = page.getByTestId("mobile-pairing-qr-container");
|
||||
const copyButton = dialog.getByTestId("copy-pairing-code");
|
||||
await expect(dialog).toBeVisible();
|
||||
await expect(qrCode).toBeVisible();
|
||||
await expect(copyButton).toHaveText("Copy pairing code");
|
||||
await expect(dialog).toHaveCSS("border-radius", "16px");
|
||||
await expect(dialog).toHaveCSS("border-left-width", "0px");
|
||||
await expect(dialog).toHaveCSS("padding-left", "24px");
|
||||
await expect(dialog).toHaveCSS("padding-right", "24px");
|
||||
await expect(dialog).toHaveCSS("padding-top", "24px");
|
||||
await expect(dialog.getByTestId("mobile-pairing-done")).toHaveCount(0);
|
||||
await expect(
|
||||
dialog.getByRole("button", { name: "Close", exact: true }),
|
||||
).toHaveCount(1);
|
||||
await expect(
|
||||
dialog.getByText("Waiting for mobile device to scan..."),
|
||||
).toHaveCount(0);
|
||||
await expect(dialog.locator("code")).toHaveCount(0);
|
||||
await expect(qrCode).toHaveAttribute("data-qr-matrix-size", "57");
|
||||
await expect(qrCode.locator("[data-qr-finder-pattern]")).toHaveCount(3);
|
||||
expect(await qrCode.locator("circle").count()).toBeGreaterThan(100);
|
||||
await expect(qrCode.locator("image")).toHaveAttribute(
|
||||
"href",
|
||||
"/app-icon@2x.png",
|
||||
);
|
||||
await waitForAnimations(page);
|
||||
const qrContainerWidth = await qrContainer.evaluate(
|
||||
(element) => getComputedStyle(element).width,
|
||||
);
|
||||
await expect(copyButton).toHaveCSS("width", qrContainerWidth);
|
||||
|
||||
mkdirSync(SCREENSHOT_DIR, { recursive: true });
|
||||
await dialog.screenshot({ path: `${SCREENSHOT_DIR}/pairing-dialog.png` });
|
||||
await qrCode.screenshot({ path: `${SCREENSHOT_DIR}/pairing-qr.png` });
|
||||
});
|
||||
Generated
+210
@@ -191,6 +191,9 @@ importers:
|
||||
motion:
|
||||
specifier: ^12.38.0
|
||||
version: 12.40.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)
|
||||
qrcode:
|
||||
specifier: ^1.5.4
|
||||
version: 1.5.4
|
||||
qrcode.react:
|
||||
specifier: ^4.2.0
|
||||
version: 4.2.0(react@19.2.7)
|
||||
@@ -2120,6 +2123,10 @@ packages:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ansi-styles@5.2.0:
|
||||
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -2190,6 +2197,10 @@ packages:
|
||||
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
camelcase@5.3.1:
|
||||
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
caniuse-lite@1.0.30001793:
|
||||
resolution: {integrity: sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==}
|
||||
|
||||
@@ -2228,10 +2239,20 @@ packages:
|
||||
clean-git-ref@2.0.1:
|
||||
resolution: {integrity: sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==}
|
||||
|
||||
cliui@6.0.0:
|
||||
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
|
||||
|
||||
clsx@2.1.1:
|
||||
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
color-convert@2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
|
||||
color-name@1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
comma-separated-tokens@2.0.3:
|
||||
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
||||
|
||||
@@ -2278,6 +2299,10 @@ packages:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
decamelize@1.2.0:
|
||||
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
decimal.js@10.6.0:
|
||||
resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
|
||||
|
||||
@@ -2316,6 +2341,9 @@ packages:
|
||||
resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
||||
dijkstrajs@1.0.3:
|
||||
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
|
||||
|
||||
dom-accessibility-api@0.5.16:
|
||||
resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
|
||||
|
||||
@@ -2345,6 +2373,9 @@ packages:
|
||||
emoji-mart@5.6.0:
|
||||
resolution: {integrity: sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==}
|
||||
|
||||
emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
|
||||
enhanced-resolve@5.21.5:
|
||||
resolution: {integrity: sha512-mLCNbrQli11K1ySUmuNt4ZUB3OpGIDq4q2vTBTf5cL2lpsRjI9QKqSD0ndjW8FyvcW/Jj46gMe9syyHAsvMa/A==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
@@ -2417,6 +2448,10 @@ packages:
|
||||
picomatch:
|
||||
optional: true
|
||||
|
||||
find-up@4.1.0:
|
||||
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
for-each@0.3.5:
|
||||
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2452,6 +2487,10 @@ packages:
|
||||
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
get-caller-file@2.0.5:
|
||||
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||
engines: {node: 6.* || 8.* || >= 10.*}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -2546,6 +2585,10 @@ packages:
|
||||
is-decimal@2.0.1:
|
||||
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
|
||||
|
||||
is-fullwidth-code-point@3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-hexadecimal@2.0.1:
|
||||
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
|
||||
|
||||
@@ -2692,6 +2735,10 @@ packages:
|
||||
linkifyjs@4.3.2:
|
||||
resolution: {integrity: sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==}
|
||||
|
||||
locate-path@5.0.0:
|
||||
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
lodash@4.18.1:
|
||||
resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
|
||||
|
||||
@@ -2946,6 +2993,18 @@ packages:
|
||||
orderedmap@2.1.1:
|
||||
resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==}
|
||||
|
||||
p-limit@2.3.0:
|
||||
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
p-locate@4.1.0:
|
||||
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
p-try@2.2.0:
|
||||
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
pako@1.0.11:
|
||||
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
|
||||
|
||||
@@ -2955,6 +3014,10 @@ packages:
|
||||
parse5@8.0.1:
|
||||
resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==}
|
||||
|
||||
path-exists@4.0.0:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
pathe@2.0.3:
|
||||
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
|
||||
|
||||
@@ -2983,6 +3046,10 @@ packages:
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
pngjs@5.0.0:
|
||||
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
possible-typed-array-names@1.1.0:
|
||||
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3063,6 +3130,11 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
qrcode@1.5.4:
|
||||
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
|
||||
react-diff-view@3.3.3:
|
||||
resolution: {integrity: sha512-CPveApk6n7ZbkW7T6PoptR7LWAvD9hohTHZ7WnKnu3GZkTfUB5rvg486apPo94iYVi4fZd3Nt+rtBZ5877exoQ==}
|
||||
peerDependencies:
|
||||
@@ -3152,10 +3224,17 @@ packages:
|
||||
remark-stringify@11.0.0:
|
||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
||||
|
||||
require-directory@2.1.1:
|
||||
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
require-from-string@2.0.2:
|
||||
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
require-main-filename@2.0.0:
|
||||
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
|
||||
|
||||
rolldown@1.0.3:
|
||||
resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
@@ -3188,6 +3267,9 @@ packages:
|
||||
resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
set-blocking@2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
|
||||
set-function-length@1.2.2:
|
||||
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3232,12 +3314,20 @@ packages:
|
||||
std-env@4.2.0:
|
||||
resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
string_decoder@1.3.0:
|
||||
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
|
||||
|
||||
stringify-entities@4.0.4:
|
||||
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
strip-indent@3.0.0:
|
||||
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -3529,6 +3619,9 @@ packages:
|
||||
resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==}
|
||||
engines: {node: '>=20'}
|
||||
|
||||
which-module@2.0.1:
|
||||
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
|
||||
|
||||
which-typed-array@1.1.22:
|
||||
resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -3538,6 +3631,10 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
@@ -3560,6 +3657,9 @@ packages:
|
||||
xmlchars@2.2.0:
|
||||
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
|
||||
|
||||
y18n@4.0.3:
|
||||
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
|
||||
|
||||
yallist@3.1.1:
|
||||
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
|
||||
|
||||
@@ -3568,6 +3668,14 @@ packages:
|
||||
engines: {node: '>= 14.6'}
|
||||
hasBin: true
|
||||
|
||||
yargs-parser@18.1.3:
|
||||
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
yargs@15.4.1:
|
||||
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
zod@4.4.3:
|
||||
resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
|
||||
|
||||
@@ -5233,6 +5341,10 @@ snapshots:
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-styles@4.3.0:
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
ansi-styles@5.2.0: {}
|
||||
|
||||
ansis@4.3.0: {}
|
||||
@@ -5306,6 +5418,8 @@ snapshots:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
get-intrinsic: 1.3.0
|
||||
|
||||
camelcase@5.3.1: {}
|
||||
|
||||
caniuse-lite@1.0.30001793: {}
|
||||
|
||||
canvas-renderer@2.2.1:
|
||||
@@ -5336,8 +5450,20 @@ snapshots:
|
||||
|
||||
clean-git-ref@2.0.1: {}
|
||||
|
||||
cliui@6.0.0:
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wrap-ansi: 6.2.0
|
||||
|
||||
clsx@2.1.1: {}
|
||||
|
||||
color-convert@2.0.1:
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
|
||||
color-name@1.1.4: {}
|
||||
|
||||
comma-separated-tokens@2.0.3: {}
|
||||
|
||||
convert-source-map@2.0.0: {}
|
||||
@@ -5373,6 +5499,8 @@ snapshots:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
decamelize@1.2.0: {}
|
||||
|
||||
decimal.js@10.6.0: {}
|
||||
|
||||
decode-named-character-reference@1.3.0:
|
||||
@@ -5405,6 +5533,8 @@ snapshots:
|
||||
|
||||
diff@8.0.4: {}
|
||||
|
||||
dijkstrajs@1.0.3: {}
|
||||
|
||||
dom-accessibility-api@0.5.16: {}
|
||||
|
||||
dom-accessibility-api@0.6.3: {}
|
||||
@@ -5431,6 +5561,8 @@ snapshots:
|
||||
|
||||
emoji-mart@5.6.0: {}
|
||||
|
||||
emoji-regex@8.0.0: {}
|
||||
|
||||
enhanced-resolve@5.21.5:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
@@ -5480,6 +5612,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.5
|
||||
|
||||
find-up@4.1.0:
|
||||
dependencies:
|
||||
locate-path: 5.0.0
|
||||
path-exists: 4.0.0
|
||||
|
||||
for-each@0.3.5:
|
||||
dependencies:
|
||||
is-callable: 1.2.7
|
||||
@@ -5503,6 +5640,8 @@ snapshots:
|
||||
|
||||
gensync@1.0.0-beta.2: {}
|
||||
|
||||
get-caller-file@2.0.5: {}
|
||||
|
||||
get-intrinsic@1.3.0:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@@ -5626,6 +5765,8 @@ snapshots:
|
||||
|
||||
is-decimal@2.0.1: {}
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
is-hexadecimal@2.0.1: {}
|
||||
|
||||
is-plain-obj@4.1.0: {}
|
||||
@@ -5757,6 +5898,10 @@ snapshots:
|
||||
|
||||
linkifyjs@4.3.2: {}
|
||||
|
||||
locate-path@5.0.0:
|
||||
dependencies:
|
||||
p-locate: 4.1.0
|
||||
|
||||
lodash@4.18.1: {}
|
||||
|
||||
longest-streak@3.1.0: {}
|
||||
@@ -6209,6 +6354,16 @@ snapshots:
|
||||
|
||||
orderedmap@2.1.1: {}
|
||||
|
||||
p-limit@2.3.0:
|
||||
dependencies:
|
||||
p-try: 2.2.0
|
||||
|
||||
p-locate@4.1.0:
|
||||
dependencies:
|
||||
p-limit: 2.3.0
|
||||
|
||||
p-try@2.2.0: {}
|
||||
|
||||
pako@1.0.11: {}
|
||||
|
||||
parse-entities@4.0.2:
|
||||
@@ -6225,6 +6380,8 @@ snapshots:
|
||||
dependencies:
|
||||
entities: 8.0.0
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
|
||||
pathe@2.0.3: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
@@ -6243,6 +6400,8 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
pngjs@5.0.0: {}
|
||||
|
||||
possible-typed-array-names@1.1.0: {}
|
||||
|
||||
postcss-selector-parser@6.0.10:
|
||||
@@ -6351,6 +6510,12 @@ snapshots:
|
||||
dependencies:
|
||||
react: 19.2.7
|
||||
|
||||
qrcode@1.5.4:
|
||||
dependencies:
|
||||
dijkstrajs: 1.0.3
|
||||
pngjs: 5.0.0
|
||||
yargs: 15.4.1
|
||||
|
||||
react-diff-view@3.3.3(react@19.2.7):
|
||||
dependencies:
|
||||
classnames: 2.5.1
|
||||
@@ -6480,8 +6645,12 @@ snapshots:
|
||||
mdast-util-to-markdown: 2.1.2
|
||||
unified: 11.0.5
|
||||
|
||||
require-directory@2.1.1: {}
|
||||
|
||||
require-from-string@2.0.2: {}
|
||||
|
||||
require-main-filename@2.0.0: {}
|
||||
|
||||
rolldown@1.0.3:
|
||||
dependencies:
|
||||
'@oxc-project/types': 0.133.0
|
||||
@@ -6521,6 +6690,8 @@ snapshots:
|
||||
|
||||
seroval@1.5.4: {}
|
||||
|
||||
set-blocking@2.0.0: {}
|
||||
|
||||
set-function-length@1.2.2:
|
||||
dependencies:
|
||||
define-data-property: 1.1.4
|
||||
@@ -6572,6 +6743,12 @@ snapshots:
|
||||
|
||||
std-env@4.2.0: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
string_decoder@1.3.0:
|
||||
dependencies:
|
||||
safe-buffer: 5.2.1
|
||||
@@ -6581,6 +6758,10 @@ snapshots:
|
||||
character-entities-html4: 2.1.0
|
||||
character-entities-legacy: 3.0.0
|
||||
|
||||
strip-ansi@6.0.1:
|
||||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
strip-indent@3.0.0:
|
||||
dependencies:
|
||||
min-indent: 1.0.1
|
||||
@@ -6814,6 +6995,8 @@ snapshots:
|
||||
tr46: 6.0.0
|
||||
webidl-conversions: 8.0.1
|
||||
|
||||
which-module@2.0.1: {}
|
||||
|
||||
which-typed-array@1.1.22:
|
||||
dependencies:
|
||||
available-typed-arrays: 1.0.7
|
||||
@@ -6829,6 +7012,12 @@ snapshots:
|
||||
siginfo: 2.0.0
|
||||
stackback: 0.0.2
|
||||
|
||||
wrap-ansi@6.2.0:
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
ws@8.21.1: {}
|
||||
@@ -6837,10 +7026,31 @@ snapshots:
|
||||
|
||||
xmlchars@2.2.0: {}
|
||||
|
||||
y18n@4.0.3: {}
|
||||
|
||||
yallist@3.1.1: {}
|
||||
|
||||
yaml@2.9.0: {}
|
||||
|
||||
yargs-parser@18.1.3:
|
||||
dependencies:
|
||||
camelcase: 5.3.1
|
||||
decamelize: 1.2.0
|
||||
|
||||
yargs@15.4.1:
|
||||
dependencies:
|
||||
cliui: 6.0.0
|
||||
decamelize: 1.2.0
|
||||
find-up: 4.1.0
|
||||
get-caller-file: 2.0.5
|
||||
require-directory: 2.1.1
|
||||
require-main-filename: 2.0.0
|
||||
set-blocking: 2.0.0
|
||||
string-width: 4.2.3
|
||||
which-module: 2.0.1
|
||||
y18n: 4.0.3
|
||||
yargs-parser: 18.1.3
|
||||
|
||||
zod@4.4.3: {}
|
||||
|
||||
zwitch@2.0.4: {}
|
||||
|
||||
Reference in New Issue
Block a user