diff --git a/README.md b/README.md index 2164a88b..b1c6a8ce 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,353 @@ # @devmehq/react-qr-code -Simple & Advanced React component to generate [QR codes](http://en.wikipedia.org/wiki/QR_code) - +๐ŸŽฏ Simple & Advanced React component to generate [QR codes](http://en.wikipedia.org/wiki/QR_code) with custom styling, multiple render formats, and image embedding support. [![NPM version](https://badgen.net/npm/v/@devmehq/react-qr-code)](https://npm.im/@devmehq/react-qr-code) [![Build Status](https://github.com/devmehq/react-qr-code/workflows/CI/badge.svg)](https://github.com/devmehq/react-qr-code/actions) [![Downloads](https://img.shields.io/npm/dm/@devmehq/react-qr-code.svg)](https://www.npmjs.com/package/@devmehq/react-qr-code) +[![Bundle Size](https://badgen.net/bundlephobia/minzip/@devmehq/react-qr-code)](https://bundlephobia.com/package/@devmehq/react-qr-code) +[![License](https://badgen.net/npm/license/@devmehq/react-qr-code)](https://github.com/devmehq/react-qr-code/blob/master/LICENSE.md) [![UNPKG](https://img.shields.io/badge/UNPKG-OK-179BD7.svg)](https://unpkg.com/browse/@devmehq/react-qr-code@latest/) [![Edit react-qr-code-demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/react-qr-code-demo-ccho5l?fontsize=14&hidenavigation=1&theme=dark) -## Installation -```npm +## โœจ Features + +- ๐ŸŽจ **Customizable**: Colors, sizes, margins, and styles +- ๐Ÿ–ผ๏ธ **Multiple Formats**: Render as SVG or Canvas +- ๐Ÿ“ฑ **Responsive**: Scales perfectly on all devices +- ๐Ÿž๏ธ **Image Embedding**: Add logos or images to QR codes +- ๐Ÿ›ก๏ธ **Error Correction**: Four levels (L, M, Q, H) +- ๐Ÿ“ฆ **Lightweight**: Zero dependencies, small bundle size +- ๐Ÿ”ง **TypeScript**: Full TypeScript support +- โšก **Performance**: Optimized rendering with React hooks + +## ๐Ÿ“ฆ Installation + +```bash +# Using npm npm install @devmehq/react-qr-code + +# Using yarn +yarn add @devmehq/react-qr-code + +# Using pnpm +pnpm add @devmehq/react-qr-code +``` + +## ๐Ÿš€ Quick Start + +### Basic Usage + +```tsx +import React from 'react' +import { ReactQrCode } from '@devmehq/react-qr-code' + +function App() { + return +} +``` + +### With Custom Styling + +```tsx +import React from 'react' +import { ReactQrCode } from '@devmehq/react-qr-code' + +function StyledQRCode() { + return ( + + ) +} +``` + +### Canvas Rendering + +```tsx +import React from 'react' +import { ReactQrCode } from '@devmehq/react-qr-code' + +function CanvasQRCode() { + return ( + + ) +} +``` + +### With Logo/Image + +```tsx +import React from 'react' +import { ReactQrCode } from '@devmehq/react-qr-code' + +function QRCodeWithLogo() { + return ( + + ) +} +``` + +## ๐Ÿ“– API Reference + +### ReactQrCode Props + +| Prop | Type | Default | Description | +| ------------ | -------------------------- | ------------ | --------------------------------------- | +| `value` | `string` | **Required** | The value to encode in the QR code | +| `renderAs` | `'svg' \| 'canvas'` | `'svg'` | Render format (SVG or Canvas) | +| `size` | `number` | `256` | Size of the QR code in pixels | +| `bgColor` | `string` | `'#ffffff'` | Background color (CSS color value) | +| `fgColor` | `string` | `'#000000'` | Foreground color (CSS color value) | +| `level` | `'L' \| 'M' \| 'Q' \| 'H'` | `'L'` | Error correction level | +| `marginSize` | `number` | `0` | Margin around the QR code in pixels | +| `style` | `CSSProperties` | `undefined` | React style object | +| `className` | `string` | `undefined` | CSS class name | +| `title` | `string` | `undefined` | Title for SVG accessibility | +| `id` | `string` | `undefined` | HTML id attribute | +| `images` | `ReactQrCodeImageProps[]` | `undefined` | Array of images to embed in the QR code | + +### ReactQrCodeImageProps + +| Property | Type | Default | Description | +| ---------- | --------- | -------------- | -------------------------------------------- | +| `src` | `string` | **Required** | Image source URL | +| `x` | `number` | Auto-centered | X position of the image | +| `y` | `number` | Auto-centered | Y position of the image | +| `height` | `number` | 10% of QR size | Height of the image | +| `width` | `number` | 10% of QR size | Width of the image | +| `excavate` | `boolean` | `false` | Whether to clear QR modules behind the image | + +### Error Correction Levels + +| Level | Error Correction | Data Capacity | +| ----- | ---------------- | ------------- | +| `L` | ~7% | High | +| `M` | ~15% | Medium | +| `Q` | ~25% | Medium-Low | +| `H` | ~30% | Low | + +## ๐ŸŽจ Styling & Customization + +### Responsive Design + +```tsx +import React from 'react' +import { ReactQrCode } from '@devmehq/react-qr-code' + +function ResponsiveQRCode() { + return ( +
+ +
+ ) +} ``` -```yarn -yarn install @devmehq/react-qr-code +### Dark Mode Support + +```tsx +import React from 'react' +import { ReactQrCode } from '@devmehq/react-qr-code' + +function DarkModeQRCode({ isDarkMode }) { + return ( + + ) +} ``` -## Usage +### Custom CSS Classes -```typescript -import React from 'react'; -import { ReactQrCode } from '@devmehq/react-qr-code'; +```tsx +import React from 'react' +import { ReactQrCode } from '@devmehq/react-qr-code' +import './styles.css' + +function CustomStyledQRCode() { + return ( + + ) +} +``` - +```css +/* styles.css */ +.qr-code-custom { + border-radius: 16px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + padding: 16px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); +} ``` -```js -var React = require('react'); -var { ReactQrCode } = require('@devmehq/react-qr-code'); +**Note:** When using `renderAs="canvas"` on high-density displays, the canvas is scaled for pixel-perfect rendering. Custom styles are merged with internal scaling styles. - +## ๐Ÿ’ก Use Cases + +### WiFi Password Sharing + +```tsx +function WiFiQRCode({ ssid, password, security = 'WPA' }) { + const wifiString = `WIFI:T:${security};S:${ssid};P:${password};;` + + return +} ``` -## Available Props +### Contact Information (vCard) -| prop | type | default value | -|--------------|------------------------------|---------------| -| `value` | `string` | | -| `renderAs` | `string` (`'canvas' 'svg'`) | `'canvas'` | -| `size` | `number` | `128` | -| `bgColor` | `string` (CSS color) | `"#FFFFFF"` | -| `fgColor` | `string` (CSS color) | `"#000000"` | -| `level` | `string` (`'L' 'M' 'Q' 'H'`) | `'L'` | -| `marginSize` | `number` | `false` | -| `images` | `array` (see below) | | +```tsx +function ContactQRCode({ name, phone, email }) { + const vCard = `BEGIN:VCARD +VERSION:3.0 +FN:${name} +TEL:${phone} +EMAIL:${email} +END:VCARD` -### `imageSettings` + return +} +``` -| field | type | default value | -|------------|-----------|-------------------| -| `src` | `string` | | -| `x` | `number` | none, will center | -| `y` | `number` | none, will center | -| `height` | `number` | 10% of `size` | -| `width` | `number` | 10% of `size` | -| `excavate` | `boolean` | `false` | +### Two-Factor Authentication -## Custom Styles +```tsx +function TwoFactorQRCode({ secret, issuer, accountName }) { + const otpauth = `otpauth://totp/${issuer}:${accountName}?secret=${secret}&issuer=${issuer}` -`@devmehq/react-qr-code` will pass through any additional props to the underlying DOM node (`` or ``). This allows the use of inline `style` or custom `className` to customize the rendering. One common use would be to support a responsive layout. + return ( + + ) +} +``` + +### Payment Links -**Note:** In order to render QR Codes in `` on high density displays, we scale the canvas element to contain an appropriate number of pixels and then use inline styles to scale back down. We will merge any additional styles, with custom `height` and `width` overriding our own values. This allows scaling to percentages *but* if scaling beyond the `size`, you will encounter blurry images. I recommend detecting resizes with something like [react-measure](https://github.com/souporserious/react-measure) to detect and pass the appropriate size when rendering to ``. +```tsx +function PaymentQRCode({ amount, recipient, currency = 'USD' }) { + const paymentLink = `https://pay.example.com/?to=${recipient}&amount=${amount}¤cy=${currency}` + + return +} +``` qrcode-demo +## ๐Ÿงช Testing + +```bash +# Run tests +yarn test + +# Run tests in watch mode +yarn test:watch + +# Generate coverage report +yarn test:coverage +``` + +## ๐Ÿ”ง Development + +```bash +# Install dependencies +yarn install + +# Build the library +yarn build + +# Run linting +yarn lint-js + +# Format code +yarn prettier +``` + +## ๐Ÿค Contributing + +Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests. + +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/amazing-feature`) +3. Commit your changes (`git commit -m 'Add some amazing feature'`) +4. Push to the branch (`git push origin feature/amazing-feature`) +5. Open a Pull Request + +## ๐Ÿ“ Roadmap + +- [ ] Download QR code as image (PNG/JPEG/SVG) +- [ ] Share QR code functionality +- [ ] Server-side rendering (SSR) support +- [ ] Corner dot customization +- [ ] Gradient color support +- [ ] Custom shape modules (dots, rounded, etc.) +- [ ] Animation support +- [ ] Batch QR code generation +- [ ] QR code scanner component + +## ๐Ÿ“„ License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE.md) file for details. + +## ๐Ÿ™ Acknowledgments + +- QR Code is a registered trademark of DENSO WAVE INCORPORATED +- Built with โค๏ธ by the [DEV.ME](https://dev.me) team +- Inspired by the QR code specification and community feedback + +## ๐Ÿ“ง Support + +For support, email support@dev.me or open an issue on [GitHub](https://github.com/devmehq/react-qr-code/issues). -## TODO -- Add Image Ref -- Add Corner Images and Center Image -- Add Examples to wifi password, 2fa, and other QR codes -- ADD SSR Rendering Support -- Add Download / Share QR Code -- Add Test +--- -## LICENSE [MIT](LICENSE.md) +
+ Made with โค๏ธ by DEV.ME +
diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..90c2946d --- /dev/null +++ b/jest.config.js @@ -0,0 +1,31 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'jsdom', + roots: ['/src'], + testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'], + transform: { + '^.+\\.(ts|tsx)$': [ + 'ts-jest', + { + tsconfig: { + jsx: 'react', + esModuleInterop: true, + allowSyntheticDefaultImports: true, + }, + }, + ], + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], + collectCoverageFrom: [ + 'src/**/*.{ts,tsx}', + '!src/**/*.d.ts', + '!src/**/index.ts', + '!src/**/*.test.{ts,tsx}', + ], + coverageDirectory: 'coverage', + coverageReporters: ['text', 'lcov', 'html'], + setupFilesAfterEnv: ['/jest.setup.js'], + moduleNameMapper: { + '\\.(css|less|scss|sass)$': 'identity-obj-proxy', + }, +} diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 00000000..e3cab99b --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,41 @@ +require('@testing-library/jest-dom') + +// Mock canvas for testing +HTMLCanvasElement.prototype.getContext = jest.fn(() => ({ + fillStyle: '', + fillRect: jest.fn(), + clearRect: jest.fn(), + getImageData: jest.fn(() => ({ + data: new Array(4), + })), + putImageData: jest.fn(), + createImageData: jest.fn(() => []), + setTransform: jest.fn(), + drawImage: jest.fn(), + save: jest.fn(), + restore: jest.fn(), + scale: jest.fn(), + rotate: jest.fn(), + translate: jest.fn(), + transform: jest.fn(), + beginPath: jest.fn(), + closePath: jest.fn(), + moveTo: jest.fn(), + lineTo: jest.fn(), + clip: jest.fn(), + quadraticCurveTo: jest.fn(), + bezierCurveTo: jest.fn(), + arc: jest.fn(), + arcTo: jest.fn(), + isPointInPath: jest.fn(), + stroke: jest.fn(), + fill: jest.fn(), +})) + +// Mock Image constructor +global.Image = class { + constructor() { + this.onload = null + this.src = '' + } +} diff --git a/package.json b/package.json index c6eab584..823ccc06 100644 --- a/package.json +++ b/package.json @@ -45,8 +45,9 @@ "prepare": "husky", "prepublishOnly": "rm -rf dist/* && NODE_ENV=production rollup -c rollup.config.mjs", "prettier": "prettier --write '**/*.{ts,tsx,css,scss}'", - "test": "echo \"Error: no test specified\"", - "test-watch": "jest --watch" + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage" }, "lint-staged": { "src/*.{ts,tsx,js,jsx}": "prettier --write", @@ -58,6 +59,10 @@ "@rollup/plugin-node-resolve": "16.0.1", "@rollup/plugin-replace": "6.0.2", "@rollup/plugin-typescript": "12.1.4", + "@testing-library/dom": "10.4.1", + "@testing-library/jest-dom": "6.8.0", + "@testing-library/react": "16.3.0", + "@testing-library/user-event": "14.6.1", "@types/jasmine": "5.1.9", "@types/jest": "30.0.0", "@types/react": "19.1.12", @@ -67,10 +72,14 @@ "eslint": "9.35.0", "eslint-config-prettier": "10.1.8", "husky": "9.1.7", + "identity-obj-proxy": "3.0.0", "jest": "30.1.3", + "jest-environment-jsdom": "30.1.2", "lint-staged": "16.1.6", "prettier": "3.6.2", "pretty-quick": "4.2.2", + "react": "19.1.1", + "react-dom": "19.1.1", "rollup": "4.50.0", "rollup-plugin-uglify": "6.0.4", "ts-jest": "29.4.1", diff --git a/src/index.test.tsx b/src/index.test.tsx new file mode 100644 index 00000000..a40ba599 --- /dev/null +++ b/src/index.test.tsx @@ -0,0 +1,238 @@ +import React from 'react' +import { render, screen } from '@testing-library/react' +import { ReactQrCode } from './index' + +describe('ReactQrCode', () => { + describe('SVG rendering', () => { + it('should render SVG QR code by default', () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + expect(svg).toHaveAttribute('width', '256') + expect(svg).toHaveAttribute('height', '256') + }) + + it('should render with custom size', () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toHaveAttribute('width', '512') + expect(svg).toHaveAttribute('height', '512') + }) + + it('should apply custom colors', () => { + const { container } = render( + + ) + const paths = container.querySelectorAll('path') + const hasRedPath = Array.from(paths).some( + (path) => path.getAttribute('fill') === '#FF0000' + ) + expect(hasRedPath).toBe(true) + }) + + it('should apply margin size', () => { + const { container } = render() + const rect = container.querySelector('rect') + expect(rect).toBeInTheDocument() + }) + + it('should render with title', () => { + const { container } = render( + + ) + const title = container.querySelector('title') + expect(title).toBeInTheDocument() + expect(title?.textContent).toBe('QR Code Title') + }) + + it('should apply custom className', () => { + const { container } = render( + + ) + const svg = container.querySelector('svg') + expect(svg).toHaveClass('custom-qr') + }) + + it('should apply custom styles', () => { + const { container } = render( + + ) + const svg = container.querySelector('svg') + expect(svg).toHaveStyle('border: 1px solid red') + }) + + it('should render images in SVG', () => { + const { container } = render( + + ) + const image = container.querySelector('image') + expect(image).toBeInTheDocument() + expect(image).toHaveAttribute('href', 'https://example.com/logo.png') + expect(image).toHaveAttribute('width', '24') + expect(image).toHaveAttribute('height', '24') + }) + + it('should render images with excavate', () => { + const { container } = render( + + ) + const g = container.querySelector('g') + const rect = g?.querySelector('rect') + expect(rect).toBeInTheDocument() + }) + + it('should position images with custom x and y', () => { + const { container } = render( + + ) + const image = container.querySelector('image') + expect(image).toHaveAttribute('x', '50') + expect(image).toHaveAttribute('y', '50') + }) + }) + + describe('Canvas rendering', () => { + it('should render canvas when renderAs is canvas', () => { + const { container } = render( + + ) + const canvas = container.querySelector('canvas') + expect(canvas).toBeInTheDocument() + expect(canvas).toHaveStyle('width: 256px') + expect(canvas).toHaveStyle('height: 256px') + }) + + it('should apply custom size to canvas', () => { + const { container } = render( + + ) + const canvas = container.querySelector('canvas') + expect(canvas).toHaveStyle('width: 512px') + expect(canvas).toHaveStyle('height: 512px') + }) + + it('should apply custom className to canvas', () => { + const { container } = render( + + ) + const canvas = container.querySelector('canvas') + expect(canvas).toHaveClass('canvas-qr') + }) + + it('should apply custom id to canvas', () => { + const { container } = render( + + ) + const canvas = container.querySelector('canvas') + expect(canvas).toHaveAttribute('id', 'qr-canvas') + }) + }) + + describe('Error correction levels', () => { + const levels: Array<'L' | 'M' | 'Q' | 'H'> = ['L', 'M', 'Q', 'H'] + + levels.forEach((level) => { + it(`should render with error correction level ${level}`, () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + }) + }) + + describe('Value encoding', () => { + it('should encode URLs', () => { + const { container } = render( + + ) + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + + it('should encode plain text', () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + + it('should encode numbers', () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + + it('should encode special characters', () => { + const { container } = render( + + ) + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + + it('should encode long text', () => { + const longText = 'A'.repeat(1000) + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + }) + + describe('Default props', () => { + it('should use default value when no value provided', () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + + it('should use default colors', () => { + const { container } = render() + const paths = container.querySelectorAll('path') + const hasBlackPath = Array.from(paths).some( + (path) => path.getAttribute('fill') === '#000000' + ) + expect(hasBlackPath).toBe(true) + }) + + it('should use default size', () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toHaveAttribute('width', '256') + }) + + it('should use default error correction level', () => { + const { container } = render() + const svg = container.querySelector('svg') + expect(svg).toBeInTheDocument() + }) + }) +}) diff --git a/src/index.tsx b/src/index.tsx index 8f811cfe..09234820 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,18 +1,20 @@ -import React from 'react' +import React, { useEffect, useRef, CSSProperties } from 'react' import { JsQrCode } from './qr-js/js-qr-code' import { qrErrorCorrectLevel } from './qr-js/qr-error-correct-level' +interface QRCodePathProps { + d: string + fill: string + transformX: number + transformY: number +} + function QRCodePath({ d, fill, transformX, transformY, -}: { - d: string - fill: string - transformX: number - transformY: number -}) { +}: QRCodePathProps): React.ReactElement { return ( {title ? {title} : null} @@ -42,29 +48,93 @@ function QRCodeSvg({ ) } -export type ReactQrCodeImageProps = { - // todo implement +export interface ReactQrCodeImageProps { src: string - height: number - width: number + height?: number + width?: number excavate?: boolean x?: number y?: number } -export type ReactQrCodeProps = { +export interface ReactQrCodeProps { value: string size?: number level?: 'L' | 'M' | 'Q' | 'H' bgColor?: string fgColor?: string - marginSize?: number // todo implement - style?: Record // todo implement - renderAs?: 'svg' | 'canvas' // todo implement + marginSize?: number + style?: CSSProperties + renderAs?: 'svg' | 'canvas' + images?: ReactQrCodeImageProps[] + title?: string + className?: string + id?: string +} + +function drawQRCodeCanvas( + canvas: HTMLCanvasElement, + cells: boolean[][], + size: number, + marginSize: number, + bgColor: string, + fgColor: string, images?: ReactQrCodeImageProps[] +): void { + const ctx = canvas.getContext('2d') + if (!ctx) return + + const scale = window.devicePixelRatio || 1 + canvas.width = size * scale + canvas.height = size * scale + ctx.scale(scale, scale) + + const actualSize = size - marginSize * 2 + const tileSize = actualSize / cells.length + + ctx.fillStyle = bgColor + ctx.fillRect(0, 0, size, size) + + cells.forEach((row, rowIndex) => { + row.forEach((cell, cellIndex) => { + if (cell) { + ctx.fillStyle = fgColor + const x = marginSize + cellIndex * tileSize + const y = marginSize + rowIndex * tileSize + ctx.fillRect( + Math.round(x), + Math.round(y), + Math.ceil(tileSize), + Math.ceil(tileSize) + ) + } + }) + }) + + if (images && images.length > 0) { + images.forEach((imageProps) => { + const img = new Image() + img.onload = () => { + const imgWidth = imageProps.width || size * 0.1 + const imgHeight = imageProps.height || size * 0.1 + const imgX = + imageProps.x !== undefined ? imageProps.x : (size - imgWidth) / 2 + const imgY = + imageProps.y !== undefined ? imageProps.y : (size - imgHeight) / 2 + + if (imageProps.excavate) { + ctx.fillStyle = bgColor + ctx.fillRect(imgX - 5, imgY - 5, imgWidth + 10, imgHeight + 10) + } + + ctx.drawImage(img, imgX, imgY, imgWidth, imgHeight) + } + img.src = imageProps.src + }) + } } -export function ReactQrCode(props: ReactQrCodeProps) { +export function ReactQrCode(props: ReactQrCodeProps): React.ReactElement { const { bgColor = '#ffffff', fgColor = '#000000', @@ -73,27 +143,78 @@ export function ReactQrCode(props: ReactQrCodeProps) { value = 'https://github.com/devmehq/react-qr-code', marginSize = 0, renderAs = 'svg', + images, + title, + style, + className, + id, ...rest } = props - // We'll use type === -1 to force JsQrCode to automatically pick the best type. + + const canvasRef = useRef(null) + const qrcode = new JsQrCode(-1, qrErrorCorrectLevel[level]) qrcode.addData(value) qrcode.make() const cells = qrcode.modules - const tileSize = size / cells.length + + useEffect(() => { + if (renderAs === 'canvas' && canvasRef.current) { + drawQRCodeCanvas( + canvasRef.current, + cells, + size, + marginSize, + bgColor, + fgColor, + images + ) + } + }, [renderAs, cells, size, marginSize, bgColor, fgColor, images]) + + if (renderAs === 'canvas') { + return ( + + ) + } + + const actualSize = size - marginSize * 2 + const tileSize = actualSize / cells.length + return ( - - {cells.map((row: any[], rowIndex: number) => + + {marginSize > 0 && ( + + )} + {cells.map((row: boolean[], rowIndex: number) => row.map((cell, cellIndex) => { const fill = cell ? fgColor : bgColor - const transformX = Math.round(cellIndex * tileSize) - const transformY = Math.round(rowIndex * tileSize) + const transformX = marginSize + Math.round(cellIndex * tileSize) + const transformY = marginSize + Math.round(rowIndex * tileSize) const qrItemWidth = - Math.round((cellIndex + 1) * tileSize) - transformX + Math.round((cellIndex + 1) * tileSize) - + Math.round(cellIndex * tileSize) const qrItemHeight = - Math.round((rowIndex + 1) * tileSize) - transformY + Math.round((rowIndex + 1) * tileSize) - + Math.round(rowIndex * tileSize) const d = `M 0 0 L ${qrItemWidth} 0 L ${qrItemWidth} ${qrItemHeight} L 0 ${qrItemHeight} Z` - return ( + return cell ? ( - ) + ) : null }) )} + {images?.map((imageProps, index) => { + const imgWidth = imageProps.width || size * 0.1 + const imgHeight = imageProps.height || size * 0.1 + const imgX = + imageProps.x !== undefined ? imageProps.x : (size - imgWidth) / 2 + const imgY = + imageProps.y !== undefined ? imageProps.y : (size - imgHeight) / 2 + + return ( + + {imageProps.excavate && ( + + )} + + + ) + })} ) } diff --git a/src/jest-dom.d.ts b/src/jest-dom.d.ts new file mode 100644 index 00000000..c44951a6 --- /dev/null +++ b/src/jest-dom.d.ts @@ -0,0 +1 @@ +import '@testing-library/jest-dom' diff --git a/yarn.lock b/yarn.lock index 8ad7e88e..8a6548dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,23 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.27.1": +"@adobe/css-tools@^4.4.0": + version "4.4.4" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.4.tgz#2856c55443d3d461693f32d2b96fb6ea92e1ffa9" + integrity sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg== + +"@asamuzakjp/css-color@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@asamuzakjp/css-color/-/css-color-3.2.0.tgz#cc42f5b85c593f79f1fa4f25d2b9b321e61d1794" + integrity sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw== + dependencies: + "@csstools/css-calc" "^2.1.3" + "@csstools/css-color-parser" "^3.0.9" + "@csstools/css-parser-algorithms" "^3.0.4" + "@csstools/css-tokenizer" "^3.0.3" + lru-cache "^10.4.3" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== @@ -235,6 +251,11 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" +"@babel/runtime@^7.12.5": + version "7.28.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" + integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + "@babel/template@^7.27.2": version "7.27.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" @@ -270,6 +291,34 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@csstools/color-helpers@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-5.1.0.tgz#106c54c808cabfd1ab4c602d8505ee584c2996ef" + integrity sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA== + +"@csstools/css-calc@^2.1.3", "@csstools/css-calc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.4.tgz#8473f63e2fcd6e459838dd412401d5948f224c65" + integrity sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ== + +"@csstools/css-color-parser@^3.0.9": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz#4e386af3a99dd36c46fef013cfe4c1c341eed6f0" + integrity sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA== + dependencies: + "@csstools/color-helpers" "^5.1.0" + "@csstools/css-calc" "^2.1.4" + +"@csstools/css-parser-algorithms@^3.0.4": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz#5755370a9a29abaec5515b43c8b3f2cf9c2e3076" + integrity sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ== + +"@csstools/css-tokenizer@^3.0.3": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz#333fedabc3fd1a8e5d0100013731cf19e6a8c5d3" + integrity sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw== + "@emnapi/core@^1.4.3": version "1.5.0" resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.5.0.tgz#85cd84537ec989cebb2343606a1ee663ce4edaf0" @@ -478,6 +527,19 @@ resolved "https://registry.yarnpkg.com/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz#0ededeae4d071f5c8ffe3678d15f3a1be09156be" integrity sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw== +"@jest/environment-jsdom-abstract@30.1.2": + version "30.1.2" + resolved "https://registry.yarnpkg.com/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.1.2.tgz#4ede626bf27a52c21f11917608f4ab539363b16f" + integrity sha512-u8kTh/ZBl97GOmnGJLYK/1GuwAruMC4hoP6xuk/kwltmVWsA9u/6fH1/CsPVGt2O+Wn2yEjs8n1B1zZJ62Cx0w== + dependencies: + "@jest/environment" "30.1.2" + "@jest/fake-timers" "30.1.2" + "@jest/types" "30.0.5" + "@types/jsdom" "^21.1.7" + "@types/node" "*" + jest-mock "30.0.5" + jest-util "30.0.5" + "@jest/environment@30.1.2": version "30.1.2" resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-30.1.2.tgz#f1bd73a7571f96104a3ff2007747c2ce12b5c038" @@ -894,6 +956,44 @@ dependencies: "@sinonjs/commons" "^3.0.1" +"@testing-library/dom@10.4.1": + version "10.4.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.1.tgz#d444f8a889e9a46e9a3b4f3b88e0fcb3efb6cf95" + integrity sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^5.0.1" + aria-query "5.3.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.5.0" + picocolors "1.1.1" + pretty-format "^27.0.2" + +"@testing-library/jest-dom@6.8.0": + version "6.8.0" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.8.0.tgz#697db9424f0d21d8216f1958fa0b1b69b5f43923" + integrity sha512-WgXcWzVM6idy5JaftTVC8Vs83NKRmGJz4Hqs4oyOuO2J4r/y79vvKZsb+CaGyCSEbUPI6OsewfPd0G1A0/TUZQ== + dependencies: + "@adobe/css-tools" "^4.4.0" + aria-query "^5.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + picocolors "^1.1.1" + redent "^3.0.0" + +"@testing-library/react@16.3.0": + version "16.3.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.3.0.tgz#3a85bb9bdebf180cd76dba16454e242564d598a6" + integrity sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw== + dependencies: + "@babel/runtime" "^7.12.5" + +"@testing-library/user-event@14.6.1": + version "14.6.1" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.6.1.tgz#13e09a32d7a8b7060fe38304788ebf4197cd2149" + integrity sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw== + "@tybys/wasm-util@^0.10.0": version "0.10.0" resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.0.tgz#2fd3cd754b94b378734ce17058d0507c45c88369" @@ -901,6 +1001,11 @@ dependencies: tslib "^2.4.0" +"@types/aria-query@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== + "@types/babel__core@^7.20.5": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -971,6 +1076,15 @@ expect "^30.0.0" pretty-format "^30.0.0" +"@types/jsdom@^21.1.7": + version "21.1.7" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-21.1.7.tgz#9edcb09e0b07ce876e7833922d3274149c898cfa" + integrity sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" + "@types/json-schema@^7.0.15": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -1005,6 +1119,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -1227,6 +1346,11 @@ acorn@^8.15.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== +agent-base@^7.1.0, agent-base@^7.1.2: + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1268,7 +1392,7 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" -ansi-styles@^5.2.0: +ansi-styles@^5.0.0, ansi-styles@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== @@ -1298,6 +1422,18 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-query@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + +aria-query@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + babel-jest@30.1.2: version "30.1.2" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-30.1.2.tgz#decd53b3a0cafca49443f93fb7a2c0fba55510da" @@ -1544,18 +1680,44 @@ cross-spawn@^7.0.3, cross-spawn@^7.0.6: shebang-command "^2.0.0" which "^2.0.1" +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + +cssstyle@^4.2.1: + version "4.6.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.6.0.tgz#ea18007024e3167f4f105315f3ec2d982bf48ed9" + integrity sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg== + dependencies: + "@asamuzakjp/css-color" "^3.2.0" + rrweb-cssom "^0.8.0" + csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1: +data-urls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" + integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== + dependencies: + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== dependencies: ms "^2.1.3" +decimal.js@^10.5.0: + version "10.6.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.6.0.tgz#e649a43e3ab953a72192ff5983865e509f37ed9a" + integrity sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg== + dedent@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.7.0.tgz#c1f9445335f0175a96587be245a282ff451446ca" @@ -1571,11 +1733,26 @@ deepmerge@^4.2.2, deepmerge@^4.3.1: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + detect-newline@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +dom-accessibility-api@^0.5.9: + version "0.5.16" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== + +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -1606,6 +1783,11 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +entities@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694" + integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g== + environment@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" @@ -1978,6 +2160,11 @@ handlebars@^4.7.8: optionalDependencies: uglify-js "^3.1.4" +harmony-reflect@^1.4.6: + version "1.6.2" + resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" + integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1995,11 +2182,34 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +html-encoding-sniffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" + integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== + dependencies: + whatwg-encoding "^3.1.1" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + +https-proxy-agent@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz#da8dfeac7da130b05c2ba4b59c9b6cd66611a6b9" + integrity sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw== + dependencies: + agent-base "^7.1.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -2010,6 +2220,20 @@ husky@9.1.7: resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +identity-obj-proxy@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" + integrity sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA== + dependencies: + harmony-reflect "^1.4.6" + ignore@^5.2.0: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" @@ -2041,6 +2265,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -2110,6 +2339,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-reference@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" @@ -2287,6 +2521,17 @@ jest-each@30.1.0: jest-util "30.0.5" pretty-format "30.0.5" +jest-environment-jsdom@30.1.2: + version "30.1.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-30.1.2.tgz#30756e73b9b7c10ebbe9c066f30dd1af670eb9c1" + integrity sha512-LXsfAh5+mDTuXDONGl1ZLYxtJEaS06GOoxJb2arcJTjIfh1adYg8zLD8f6P0df8VmjvCaMrLmc1PgHUI/YUTbg== + dependencies: + "@jest/environment" "30.1.2" + "@jest/environment-jsdom-abstract" "30.1.2" + "@types/jsdom" "^21.1.7" + "@types/node" "*" + jsdom "^26.1.0" + jest-environment-node@30.1.2: version "30.1.2" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-30.1.2.tgz#ae2f20442f8abc3c6b20120dc789fa38faff568f" @@ -2562,6 +2807,32 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +jsdom@^26.1.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-26.1.0.tgz#ab5f1c1cafc04bd878725490974ea5e8bf0c72b3" + integrity sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg== + dependencies: + cssstyle "^4.2.1" + data-urls "^5.0.0" + decimal.js "^10.5.0" + html-encoding-sniffer "^4.0.0" + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.6" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.16" + parse5 "^7.2.1" + rrweb-cssom "^0.8.0" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^5.1.1" + w3c-xmlserializer "^5.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^3.1.1" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.1.1" + ws "^8.18.0" + xml-name-validator "^5.0.0" + jsesc@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" @@ -2685,7 +2956,7 @@ log-update@^6.1.0: strip-ansi "^7.1.0" wrap-ansi "^9.0.0" -lru-cache@^10.2.0: +lru-cache@^10.2.0, lru-cache@^10.4.3: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== @@ -2697,6 +2968,11 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lz-string@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + magic-string@^0.30.3: version "0.30.18" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.18.tgz#905bfbbc6aa5692703a93db26a9edcaa0007d2bb" @@ -2751,6 +3027,11 @@ mimic-function@^5.0.0: resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -2827,6 +3108,11 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" +nwsapi@^2.2.16: + version "2.2.22" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.22.tgz#109f9530cda6c156d6a713cdf5939e9f0de98b9d" + integrity sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ== + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -2915,6 +3201,13 @@ parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse5@^7.0.0, parse5@^7.2.1: + version "7.3.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05" + integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw== + dependencies: + entities "^6.0.0" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2943,7 +3236,7 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -picocolors@^1.1.1: +picocolors@1.1.1, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== @@ -2994,6 +3287,15 @@ pretty-format@30.0.5, pretty-format@^30.0.0: ansi-styles "^5.2.0" react-is "^18.3.1" +pretty-format@^27.0.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + pretty-quick@4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/pretty-quick/-/pretty-quick-4.2.2.tgz#0fc31da666f182fe14e119905fc9829b5b85a234" @@ -3007,7 +3309,7 @@ pretty-quick@4.2.2: tinyexec "^0.3.2" tslib "^2.8.1" -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -3022,11 +3324,36 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +react-dom@19.1.1: + version "19.1.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.1.tgz#2daa9ff7f3ae384aeb30e76d5ee38c046dc89893" + integrity sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw== + dependencies: + scheduler "^0.26.0" + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-is@^18.3.1: version "18.3.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== +react@19.1.1: + version "19.1.1" + resolved "https://registry.yarnpkg.com/react/-/react-19.1.1.tgz#06d9149ec5e083a67f9a1e39ce97b06a03b644af" + integrity sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ== + +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -3116,6 +3443,11 @@ rollup@4.50.0: "@rollup/rollup-win32-x64-msvc" "4.50.0" fsevents "~2.3.2" +rrweb-cssom@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz#3021d1b4352fbf3b614aaeed0bc0d5739abe0bc2" + integrity sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -3123,6 +3455,23 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + +scheduler@^0.26.0: + version "0.26.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337" + integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA== + semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -3286,6 +3635,13 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -3317,6 +3673,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + synckit@^0.11.8: version "0.11.11" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0" @@ -3338,6 +3699,18 @@ tinyexec@^0.3.2: resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== +tldts-core@^6.1.86: + version "6.1.86" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-6.1.86.tgz#a93e6ed9d505cb54c542ce43feb14c73913265d8" + integrity sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA== + +tldts@^6.1.32: + version "6.1.86" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-6.1.86.tgz#087e0555b31b9725ee48ca7e77edc56115cd82f7" + integrity sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ== + dependencies: + tldts-core "^6.1.86" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" @@ -3350,6 +3723,20 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tough-cookie@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-5.1.2.tgz#66d774b4a1d9e12dc75089725af3ac75ec31bed7" + integrity sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A== + dependencies: + tldts "^6.1.32" + +tr46@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" + integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== + dependencies: + punycode "^2.3.1" + ts-api-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" @@ -3463,6 +3850,13 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== + dependencies: + xml-name-validator "^5.0.0" + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -3470,6 +3864,31 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== + dependencies: + iconv-lite "0.6.3" + +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== + +whatwg-url@^14.0.0, whatwg-url@^14.1.1: + version "14.2.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" + integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== + dependencies: + tr46 "^5.1.0" + webidl-conversions "^7.0.0" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -3536,6 +3955,21 @@ write-file-atomic@^5.0.1: imurmurhash "^0.1.4" signal-exit "^4.0.1" +ws@^8.18.0: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"