diff --git a/.changeset/happy-mountain-fly.md b/.changeset/happy-mountain-fly.md new file mode 100644 index 0000000..05237c1 --- /dev/null +++ b/.changeset/happy-mountain-fly.md @@ -0,0 +1,20 @@ +--- +"pine-ui-kit": minor +--- + +Component updates and improvements + +## New Components + +- **Tab**: Added tab interface component for organizing content + +## Component Improvements + +- **Base UI Migration**: Migrated all interactive components to Base UI for better accessibility and form handling + - Enhanced Button, Switch, Checkbox, Dialog, Dropdown, and TextField components + - Improved keyboard navigation and screen reader support + - Better form validation and state management + +## Browser Support + +- **iOS 26+ Safari**: Added backdrop support for overlay components like Dialog and Dropdown diff --git a/.github/workflows/changeset-check.yml b/.github/workflows/changeset-check.yml new file mode 100644 index 0000000..dbc54fd --- /dev/null +++ b/.github/workflows/changeset-check.yml @@ -0,0 +1,87 @@ +name: Changeset Check + +on: + pull_request: + branches: + - main + +jobs: + changeset-check: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Check if changeset is required + id: check-skip + run: | + # PR에 'skip-changeset' 라벨이 있는지 확인 + if [[ "${{ contains(github.event.pull_request.labels.*.name, 'skip-changeset') }}" == "true" ]]; then + echo "skip=true" >> $GITHUB_OUTPUT + echo "⏭️ Skipping changeset check due to 'skip-changeset' label" + exit 0 + fi + + # 변경된 파일 목록 가져오기 + git fetch origin ${{ github.base_ref }} + # main 브랜치를 로컬에 명시적으로 생성 (changeset status를 위해 필요) + git fetch origin ${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} + CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) + + # 문서, CI, 설정 파일만 변경된 경우 체크 + if echo "$CHANGED_FILES" | grep -qvE '^(\.github/|\.changeset/|\.vscode/|docs/|README\.md|LICENSE|\.gitignore|\.prettierrc|\.eslintrc|package\.json|tsconfig\.json|vite\.config\.ts)'; then + echo "skip=false" >> $GITHUB_OUTPUT + echo "📦 Source code changes detected - changeset required" + else + echo "skip=true" >> $GITHUB_OUTPUT + echo "⏭️ Only docs/config changes detected - skipping changeset check" + fi + + - name: Setup pnpm + if: steps.check-skip.outputs.skip != 'true' + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Setup Node.js + if: steps.check-skip.outputs.skip != 'true' + uses: actions/setup-node@v4 + with: + node-version: "20" + cache: "pnpm" + + - name: Install dependencies + if: steps.check-skip.outputs.skip != 'true' + run: pnpm install --frozen-lockfile + + - name: Check for changesets + if: steps.check-skip.outputs.skip != 'true' + run: | + # .changeset 디렉토리에 있는 .md 파일 개수 확인 (config.json, README.md 제외) + CHANGESET_COUNT=$(find .changeset -name "*.md" ! -name "README.md" | wc -l) + + echo "Found $CHANGESET_COUNT changeset(s)" + + if [ "$CHANGESET_COUNT" -eq 0 ]; then + echo "❌ Error: No changeset found!" + echo "" + echo "Please add a changeset to describe your changes:" + echo " pnpm changeset" + echo "" + echo "This helps us maintain a proper changelog and version history." + echo "" + echo "If you believe this PR doesn't need a changeset (docs/config only)," + echo "please add the 'skip-changeset' label to this PR." + exit 1 + else + echo "✅ Changeset found!" + echo "" + echo "Changeset files:" + find .changeset -name "*.md" ! -name "README.md" -exec echo " - {}" \; + fi + + - name: Validate changeset format + if: steps.check-skip.outputs.skip != 'true' + run: pnpm changeset status --since=origin/${{ github.base_ref }} --verbose diff --git a/.gitignore b/.gitignore index 56071eb..ce942ef 100644 --- a/.gitignore +++ b/.gitignore @@ -13,9 +13,13 @@ dist-ssr *.local storybook-static +# pnpm +.pnpm-store + # Editor directories and files .vscode/* !.vscode/extensions.json +!.vscode/settings.json .idea .DS_Store *.suo diff --git a/.storybook/ThemeWrapper.tsx b/.storybook/ThemeWrapper.tsx index 256c547..73650cb 100644 --- a/.storybook/ThemeWrapper.tsx +++ b/.storybook/ThemeWrapper.tsx @@ -1,10 +1,10 @@ import React from "react"; -import { ThemeProvider } from "../packages/providers"; +import { ThemeProvider } from "../src/providers"; import { appearanceTheme, applyAppearanceTheme, type AppearanceMode, -} from "../packages/tokens/appearanceTheme"; +} from "../src/tokens/appearanceTheme"; interface ThemeWrapperProps { mode: AppearanceMode; diff --git a/.storybook/main.ts b/.storybook/main.ts index 3e2119c..ab6c59e 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -3,8 +3,8 @@ import type { StorybookConfig } from "@storybook/react-vite"; const config: StorybookConfig = { stories: [ "../.storybook/**/*.mdx", - "../packages/**/*.mdx", - "../packages/**/*.stories.@(js|jsx|mjs|ts|tsx)", + "../src/**/*.mdx", + "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)", ], addons: [ "@storybook/addon-essentials", diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index b0d080c..4c3c375 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,11 +1,11 @@ import React from "react"; import type { Decorator, Preview } from "@storybook/react"; -import "../packages/tokens/theme.css"; +import "../src/tokens/theme.css"; import { ThemeWrapper } from "./ThemeWrapper"; import { appearanceTheme, type AppearanceMode, -} from "../packages/tokens/appearanceTheme"; +} from "../src/tokens/appearanceTheme"; const withTheme: Decorator = (Story, context) => { const theme = (context.globals?.theme || "light") as AppearanceMode; diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bb69106 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.expand": false, + "explorer.fileNesting.patterns": { + "*.tsx": "${capture}.css.ts, ${capture}.spec.tsx, ${capture}.stories.tsx, ${capture}.test.tsx", + "*.ts": "${capture}.spec.ts, ${capture}.test.ts", + "package.json": "package-lock.json, pnpm-lock.yaml, yarn.lock, .npmrc, .nvmrc, .node-version", + "tsconfig.json": "tsconfig.*.json", + "vite.config.*": "vitest.config.*, vitest.setup.*", + ".eslintrc.*": ".eslintignore, .prettierrc*, .prettierignore", + ".gitignore": ".gitattributes, .gitmodules", + "README.md": "CHANGELOG.md, LICENSE, CONTRIBUTING.md", + ".storybook": "storybook-static" + } +} diff --git a/package.json b/package.json index edbee9d..279b24c 100644 --- a/package.json +++ b/package.json @@ -42,15 +42,21 @@ "build": "vite build && tsc --project tsconfig.build.json", "build:lib": "pnpm run build", "lint": "eslint .", + "test": "vitest", + "test:ui": "vitest --ui", + "test:run": "vitest run", "storybook": "storybook dev -p 6006", "build-storybook": "pnpm run sync-readme && storybook build", "sync-readme": "node scripts/sync-readme.js", "prepublishOnly": "pnpm run build:lib", "changeset": "changeset", + "changeset:auto": "./scripts/auto-changeset.sh", "version": "changeset version", - "release": "pnpm run version && pnpm run build:lib && npm publish --access public" + "release": "pnpm run version && pnpm run build:lib && npm publish --access public", + "pr": "./scripts/create-pr.sh" }, "dependencies": { + "@base-ui/react": "^1.0.0", "clsx": "^2.1.1" }, "peerDependencies": { @@ -68,6 +74,9 @@ "@storybook/react": "^8", "@storybook/react-vite": "^8", "@storybook/test": "^8", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.1", + "@testing-library/user-event": "^14.6.1", "@types/node": "^24.10.1", "@types/react": "^19.0.0", "@types/react-dom": "^19.0.0", @@ -75,18 +84,21 @@ "@vanilla-extract/recipes": "^0.5.7", "@vanilla-extract/vite-plugin": "^5.1.1", "@vitejs/plugin-react": "^5.1.0", + "@vitest/ui": "^4.0.16", "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.24", "eslint-plugin-storybook": "^10.0.7", "globals": "^16.5.0", + "jsdom": "^27.4.0", "react": "^19.0.0", "react-dom": "^19.0.0", "storybook": "^8", "storybook-dark-mode": "^4.0.2", "typescript": "~5.9.3", "typescript-eslint": "^8.46.3", - "vite": "^5.4.11" + "vite": "^5.4.11", + "vitest": "^4.0.16" }, "eslintConfig": { "extends": [ diff --git a/packages/components/Button/Button.tsx b/packages/components/Button/Button.tsx deleted file mode 100644 index 58efcf3..0000000 --- a/packages/components/Button/Button.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import React from "react"; -import clsx from "clsx"; -import * as styles from "./Button.css"; -import { lightTheme, type ColorIntent } from "@/tokens"; -import { useTheme } from "@/providers"; - -export type ButtonVariant = "solid" | "outline" | "ghost" | "weak"; -export type ButtonSize = "small" | "medium" | "large" | "xlarge"; -export type ButtonIntent = ColorIntent; -export type ButtonRounded = "small" | "medium" | "large"; - -export interface ButtonProps - extends React.ButtonHTMLAttributes { - variant?: ButtonVariant; - size?: ButtonSize; - intent?: ButtonIntent; - rounded?: ButtonRounded; - fullWidth?: boolean; - disabled?: boolean; -} - -export const Button = ({ - variant = "solid", - size = "medium", - intent = "primary", - rounded = "medium", - fullWidth = false, - disabled = false, - children, - className, - ...props -}: ButtonProps) => { - const themeContext = useTheme(); - const themeClass = themeContext?.themeClass ?? lightTheme; - - return ( - - ); -}; diff --git a/packages/components/Checkbox/Checkbox.tsx b/packages/components/Checkbox/Checkbox.tsx deleted file mode 100644 index d465a89..0000000 --- a/packages/components/Checkbox/Checkbox.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import React from "react"; -import clsx from "clsx"; -import * as styles from "./Checkbox.css"; -import { lightTheme, type ColorIntent } from "@/tokens"; -import { useTheme } from "@/providers"; -import { Text } from "../Text/Text"; - -export type CheckboxSize = "small" | "medium" | "large" | "xlarge"; -export type CheckboxVariant = "circle" | "square"; -export type CheckboxIntent = ColorIntent; -export type CheckboxRounded = "small" | "medium" | "large"; - -export interface CheckboxProps - extends Omit, "size" | "type"> { - size?: CheckboxSize; - variant?: CheckboxVariant; - intent?: CheckboxIntent; - rounded?: CheckboxRounded; - label?: string; - checked?: boolean; - disabled?: boolean; -} - -export const Checkbox = ({ - size = "medium", - variant = "square", - intent = "primary", - rounded = "medium", - label, - checked: controlledChecked, - disabled = false, - className, - onChange, - ...props -}: CheckboxProps) => { - const themeContext = useTheme(); - const themeClass = themeContext?.themeClass ?? lightTheme; - - // Uncontrolled 모드 지원 - const [internalChecked, setInternalChecked] = React.useState(false); - const isControlled = controlledChecked !== undefined; - const checked = isControlled ? controlledChecked : internalChecked; - - const handleChange = (e: React.ChangeEvent) => { - if (!isControlled) { - setInternalChecked(e.target.checked); - } - onChange?.(e); - }; - - return ( - - ); -}; diff --git a/packages/components/Dialog/Dialog.tsx b/packages/components/Dialog/Dialog.tsx deleted file mode 100644 index 68ec01e..0000000 --- a/packages/components/Dialog/Dialog.tsx +++ /dev/null @@ -1,208 +0,0 @@ -import React, { - useEffect, - useRef, - useState, - useCallback, -} from "react"; -import { createPortal } from "react-dom"; -import clsx from "clsx"; -import * as styles from "./Dialog.css"; -import { lightTheme } from "@/tokens"; -import { useTheme } from "@/providers"; -import { Text } from "../Text"; -import { Button } from "../Button"; -import type { ButtonVariant, ButtonIntent } from "../Button"; - -export type DialogSize = "small" | "medium" | "large" | "xlarge" | "full"; -export type DialogRounded = "small" | "medium" | "large"; - -export interface DialogAction { - label: string; - onClick: () => void; - variant?: ButtonVariant; - intent?: ButtonIntent; - disabled?: boolean; -} - -export interface DialogProps { - open: boolean; - onClose: () => void; - size?: DialogSize; - rounded?: DialogRounded; - title?: string; - description?: string; - children: React.ReactNode; - actions?: DialogAction[]; - footer?: React.ReactNode; - showCloseButton?: boolean; - closeOnOverlayClick?: boolean; - closeOnEscape?: boolean; - className?: string; -} - -export const Dialog = ({ - open, - onClose, - size = "medium", - rounded = "medium", - title, - description, - children, - actions, - footer, - showCloseButton = true, - closeOnOverlayClick = true, - closeOnEscape = true, - className, -}: DialogProps) => { - const [isClosing, setIsClosing] = useState(false); - const [mounted, setMounted] = useState(false); - const dialogRef = useRef(null); - const themeContext = useTheme(); - const themeClass = themeContext?.themeClass ?? lightTheme; - - useEffect(() => { - setMounted(true); - return () => setMounted(false); - }, []); - - const handleClose = useCallback(() => { - setIsClosing(true); - setTimeout(() => { - setIsClosing(false); - onClose(); - }, 200); - }, [onClose]); - - useEffect(() => { - if (!open || !closeOnEscape) return; - - const handleEscape = (e: KeyboardEvent) => { - if (e.key === "Escape") { - handleClose(); - } - }; - - document.addEventListener("keydown", handleEscape); - return () => document.removeEventListener("keydown", handleEscape); - }, [open, closeOnEscape, handleClose]); - - useEffect(() => { - if (open) { - document.body.style.overflow = "hidden"; - } else { - document.body.style.overflow = ""; - } - - return () => { - document.body.style.overflow = ""; - }; - }, [open]); - - const handleOverlayClick = (e: React.MouseEvent) => { - if (closeOnOverlayClick && e.target === e.currentTarget) { - handleClose(); - } - }; - - if (!open && !isClosing) return null; - if (!mounted) return null; - - const dialogContent = ( -
-
- {(title || showCloseButton) && ( -
-
- {title && ( - - {title} - - )} - {description && ( - - {description} - - )} -
- {showCloseButton && ( - - )} -
- )} - -
{children}
- - {(actions || footer) && ( -
- {actions - ? actions.map((action, index) => ( - - )) - : footer} -
- )} -
-
- ); - - return createPortal(dialogContent, document.body); -}; diff --git a/packages/components/Dropdown/Dropdown.tsx b/packages/components/Dropdown/Dropdown.tsx deleted file mode 100644 index b186949..0000000 --- a/packages/components/Dropdown/Dropdown.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import { useEffect, useRef, useState, useCallback } from "react"; -import clsx from "clsx"; -import * as styles from "./Dropdown.css"; -import { lightTheme, type ColorIntent } from "@/tokens"; -import { useTheme } from "@/providers"; - -export type DropdownSize = "small" | "medium" | "large"; -export type DropdownRounded = "small" | "medium" | "large"; -export type DropdownIntent = ColorIntent; - -export interface DropdownOption { - value: string; - label: string; - disabled?: boolean; -} - -export interface DropdownProps { - options: DropdownOption[]; - value?: string; - onChange?: (value: string) => void; - placeholder?: string; - size?: DropdownSize; - rounded?: DropdownRounded; - intent?: DropdownIntent; - fullWidth?: boolean; - disabled?: boolean; - className?: string; -} - -export const Dropdown = ({ - options, - value, - onChange, - placeholder = "Select an option", - size = "medium", - rounded = "medium", - intent = "primary", - fullWidth = false, - disabled = false, - className, -}: DropdownProps) => { - const [isOpen, setIsOpen] = useState(false); - const [isClosing, setIsClosing] = useState(false); - const [focusedIndex, setFocusedIndex] = useState(-1); - const containerRef = useRef(null); - const menuRef = useRef(null); - const themeContext = useTheme(); - const themeClass = themeContext?.themeClass ?? lightTheme; - - const selectedOption = options.find((opt) => opt.value === value); - - const handleClose = useCallback(() => { - setIsClosing(true); - setTimeout(() => { - setIsClosing(false); - setIsOpen(false); - setFocusedIndex(-1); - }, 150); - }, []); - - const handleToggle = useCallback(() => { - if (disabled) return; - if (isOpen) { - handleClose(); - } else { - setIsOpen(true); - setFocusedIndex(-1); - } - }, [isOpen, disabled, handleClose]); - - const handleSelect = useCallback( - (optionValue: string) => { - onChange?.(optionValue); - handleClose(); - }, - [onChange, handleClose] - ); - - useEffect(() => { - if (!isOpen) return; - - const handleClickOutside = (event: MouseEvent) => { - if ( - containerRef.current && - !containerRef.current.contains(event.target as Node) - ) { - handleClose(); - } - }; - - document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, [isOpen, handleClose]); - - useEffect(() => { - if (!isOpen) return; - - const enabledOptions = options.filter((opt) => !opt.disabled); - - const handleKeyDown = (event: KeyboardEvent) => { - switch (event.key) { - case "Escape": - event.preventDefault(); - handleClose(); - break; - - case "ArrowDown": - event.preventDefault(); - setFocusedIndex((prev) => { - const nextIndex = prev + 1; - return nextIndex >= enabledOptions.length ? 0 : nextIndex; - }); - break; - - case "ArrowUp": - event.preventDefault(); - setFocusedIndex((prev) => { - const nextIndex = prev - 1; - return nextIndex < 0 ? enabledOptions.length - 1 : nextIndex; - }); - break; - - case "Enter": - event.preventDefault(); - if (focusedIndex >= 0 && focusedIndex < enabledOptions.length) { - handleSelect(enabledOptions[focusedIndex].value); - } - break; - - case "Home": - event.preventDefault(); - setFocusedIndex(0); - break; - - case "End": - event.preventDefault(); - setFocusedIndex(enabledOptions.length - 1); - break; - } - }; - - document.addEventListener("keydown", handleKeyDown); - return () => document.removeEventListener("keydown", handleKeyDown); - }, [isOpen, focusedIndex, options, handleSelect, handleClose]); - - useEffect(() => { - if (!isOpen || focusedIndex < 0 || !menuRef.current) return; - - const focusedElement = menuRef.current.children[ - focusedIndex - ] as HTMLElement | null; - if (focusedElement?.scrollIntoView) { - focusedElement.scrollIntoView({ - block: "nearest", - }); - } - }, [focusedIndex, isOpen]); - - return ( -
- - - {(isOpen || isClosing) && ( -
- {options.map((option, index) => ( - - ))} -
- )} -
- ); -}; diff --git a/packages/components/Switch/Switch.css.ts b/packages/components/Switch/Switch.css.ts deleted file mode 100644 index 384a8ca..0000000 --- a/packages/components/Switch/Switch.css.ts +++ /dev/null @@ -1,255 +0,0 @@ -import { style } from "@vanilla-extract/css"; -import { recipe } from "@vanilla-extract/recipes"; -import { themeContract } from "@/tokens"; - -export const container = style({ - display: "inline-flex", - alignItems: "center", - gap: themeContract.spacing.xs, - cursor: "pointer", - userSelect: "none", - selectors: { - "&:has(input:disabled)": { - cursor: "not-allowed", - opacity: 0.5, - }, - }, -}); - -export const hiddenInput = style({ - position: "absolute", - width: "1px", - height: "1px", - padding: 0, - margin: "-1px", - overflow: "hidden", - clip: "rect(0, 0, 0, 0)", - whiteSpace: "nowrap", - border: 0, -}); - -const trackBase = style({ - position: "relative", - display: "inline-flex", - alignItems: "center", - flexShrink: 0, - borderRadius: themeContract.radius.xlarge, - transition: "background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1)", - selectors: { - "input:focus-visible + &": { - outline: `2px solid ${themeContract.color.primary.surface}`, - outlineOffset: "2px", - }, - "input:disabled + &": { - cursor: "not-allowed", - }, - }, -}); - -export const track = recipe({ - base: trackBase, - - variants: { - size: { - small: { - width: "30px", - height: "18px", - padding: "2px 4px", - }, - medium: { - width: "43px", - height: "24px", - padding: "2px 3px", - }, - large: { - width: "54px", - height: "30px", - padding: "2px 4px", - }, - xlarge: { - width: "66px", - height: "36px", - padding: "2px 4px", - }, - }, - - intent: { - primary: {}, - secondary: {}, - success: {}, - warning: {}, - danger: {}, - neutral: {}, - }, - - checked: { - true: {}, - false: {}, - }, - }, - - compoundVariants: [ - // Primary - { - variants: { intent: "primary", checked: false }, - style: { - backgroundColor: themeContract.color.surface.outline, - }, - }, - { - variants: { intent: "primary", checked: true }, - style: { - backgroundColor: themeContract.color.primary.surface, - }, - }, - - // Secondary - { - variants: { intent: "secondary", checked: false }, - style: { - backgroundColor: themeContract.color.surface.outline, - }, - }, - { - variants: { intent: "secondary", checked: true }, - style: { - backgroundColor: themeContract.color.secondary.surface, - }, - }, - - // Success - { - variants: { intent: "success", checked: false }, - style: { - backgroundColor: themeContract.color.surface.outline, - }, - }, - { - variants: { intent: "success", checked: true }, - style: { - backgroundColor: themeContract.color.success.surface, - }, - }, - - // Warning - { - variants: { intent: "warning", checked: false }, - style: { - backgroundColor: themeContract.color.surface.outline, - }, - }, - { - variants: { intent: "warning", checked: true }, - style: { - backgroundColor: themeContract.color.warning.surface, - }, - }, - - // Danger - { - variants: { intent: "danger", checked: false }, - style: { - backgroundColor: themeContract.color.surface.outline, - }, - }, - { - variants: { intent: "danger", checked: true }, - style: { - backgroundColor: themeContract.color.danger.surface, - }, - }, - - // Neutral - { - variants: { intent: "neutral", checked: false }, - style: { - backgroundColor: themeContract.color.surface.outline, - }, - }, - { - variants: { intent: "neutral", checked: true }, - style: { - backgroundColor: themeContract.color.neutral.surface, - }, - }, - ], - - defaultVariants: { - size: "medium", - intent: "primary", - checked: false, - }, -}); - -// Switch thumb (sliding circle) -const thumbBase = style({ - backgroundColor: "white", - borderRadius: themeContract.radius.xlarge, - transition: "transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)", - boxShadow: themeContract.shadow.small, -}); - -export const thumb = recipe({ - base: thumbBase, - - variants: { - size: { - small: { - width: "14px", - height: "14px", - }, - medium: { - width: "20px", - height: "20px", - }, - large: { - width: "24px", - height: "24px", - }, - xlarge: { - width: "28px", - height: "28px", - }, - }, - - checked: { - true: {}, - false: { - transform: "translateX(0)", - }, - }, - }, - - compoundVariants: [ - // Checked state - move thumb to right based on size - { - variants: { size: "small", checked: true }, - style: { - transform: "translateX(16px)", - }, - }, - { - variants: { size: "medium", checked: true }, - style: { - transform: "translateX(22px)", - }, - }, - { - variants: { size: "large", checked: true }, - style: { - transform: "translateX(28px)", - }, - }, - { - variants: { size: "xlarge", checked: true }, - style: { - transform: "translateX(34px)", - }, - }, - ], - - defaultVariants: { - size: "medium", - checked: false, - }, -}); diff --git a/packages/components/Switch/Switch.tsx b/packages/components/Switch/Switch.tsx deleted file mode 100644 index 1f4f776..0000000 --- a/packages/components/Switch/Switch.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from "react"; -import clsx from "clsx"; -import * as styles from "./Switch.css"; -import { lightTheme, type ColorIntent } from "@/tokens"; -import { useTheme } from "@/providers"; -import { Text } from "../Text/Text"; - -export type SwitchSize = "small" | "medium" | "large" | "xlarge"; -export type SwitchIntent = ColorIntent; - -export interface SwitchProps - extends Omit, "size" | "type"> { - size?: SwitchSize; - intent?: SwitchIntent; - label?: string; - checked?: boolean; - disabled?: boolean; -} - -export const Switch = ({ - size = "medium", - intent = "primary", - label, - checked: controlledChecked, - disabled = false, - className, - onChange, - ...props -}: SwitchProps) => { - const themeContext = useTheme(); - const themeClass = themeContext?.themeClass ?? lightTheme; - - // Uncontrolled 모드 지원 - const [internalChecked, setInternalChecked] = React.useState(false); - const isControlled = controlledChecked !== undefined; - const checked = isControlled ? controlledChecked : internalChecked; - - const handleChange = (e: React.ChangeEvent) => { - if (!isControlled) { - setInternalChecked(e.target.checked); - } - onChange?.(e); - }; - - return ( - - ); -}; diff --git a/packages/components/TextField/TextField.tsx b/packages/components/TextField/TextField.tsx deleted file mode 100644 index 32c4ea0..0000000 --- a/packages/components/TextField/TextField.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import React from "react"; -import clsx from "clsx"; -import { container, containerVariants, input } from "./TextField.css"; -import { lightTheme } from "@/tokens"; -import { useTheme } from "@/providers"; -import { Text } from "../Text/Text"; - -export type TextFieldSize = "small" | "medium" | "large" | "xlarge"; -export type TextFieldRounded = "small" | "medium" | "large"; -export type TextFieldVariant = "outline" | "filled"; -export type TextFieldStatus = "default" | "error" | "success"; - -export interface TextFieldProps - extends Omit, "size"> { - size?: TextFieldSize; - rounded?: TextFieldRounded; - variant?: TextFieldVariant; - status?: TextFieldStatus; - label?: string; - helperText?: string; - fullWidth?: boolean; -} - -export const TextField = ({ - size = "medium", - rounded = "medium", - variant = "outline", - status = "default", - label, - helperText, - fullWidth = false, - disabled = false, - className, - ...props -}: TextFieldProps) => { - const themeContext = useTheme(); - const themeClass = themeContext?.themeClass ?? lightTheme; - - const getHelperTextIntent = (): "inherit" | "danger" | "success" => { - if (status === "error") return "danger"; - if (status === "success") return "success"; - return "inherit"; - }; - - const getLabelSize = (): "xsmall" | "small" | "medium" => { - if (size === "small") return "xsmall"; - if (size === "medium") return "small"; - return "medium"; - }; - - const getHelperTextSize = (): "xsmall" | "small" => { - if (size === "small" || size === "medium") return "xsmall"; - return "small"; - }; - - return ( -
- {label && ( - - {label} - - )} - - {helperText && ( - - {helperText} - - )} -
- ); -}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a11460e..8dacb7d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,103 +8,136 @@ importers: .: dependencies: + '@base-ui/react': + specifier: ^1.0.0 + version: 1.0.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) clsx: specifier: ^2.1.1 version: 2.1.1 devDependencies: '@changesets/cli': specifier: ^2.29.7 - version: 2.29.7(@types/node@24.10.1) + version: 2.29.8(@types/node@24.10.4) '@eslint/js': specifier: ^9.39.1 - version: 9.39.1 + version: 9.39.2 '@storybook/addon-a11y': specifier: ^8 - version: 8.6.14(storybook@8.6.14(prettier@3.6.2)) + version: 8.6.15(storybook@8.6.15(prettier@3.7.4)) '@storybook/addon-essentials': specifier: ^8 - version: 8.6.14(@types/react@19.2.6)(storybook@8.6.14(prettier@3.6.2)) + version: 8.6.14(@types/react@19.2.7)(storybook@8.6.15(prettier@3.7.4)) '@storybook/addon-interactions': specifier: ^8 - version: 8.6.14(storybook@8.6.14(prettier@3.6.2)) + version: 8.6.14(storybook@8.6.15(prettier@3.7.4)) '@storybook/addon-storysource': specifier: ^8.6.14 - version: 8.6.14(storybook@8.6.14(prettier@3.6.2)) + version: 8.6.14(storybook@8.6.15(prettier@3.7.4)) '@storybook/blocks': specifier: ^8 - version: 8.6.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2)) + version: 8.6.14(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4)) '@storybook/react': specifier: ^8 - version: 8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.6.2)))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2))(typescript@5.9.3) + version: 8.6.15(@storybook/test@8.6.15(storybook@8.6.15(prettier@3.7.4)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4))(typescript@5.9.3) '@storybook/react-vite': specifier: ^8 - version: 8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.6.2)))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.53.3)(storybook@8.6.14(prettier@3.6.2))(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.1)) + version: 8.6.15(@storybook/test@8.6.15(storybook@8.6.15(prettier@3.7.4)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rollup@4.55.1)(storybook@8.6.15(prettier@3.7.4))(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.4)) '@storybook/test': specifier: ^8 - version: 8.6.14(storybook@8.6.14(prettier@3.6.2)) + version: 8.6.15(storybook@8.6.15(prettier@3.7.4)) + '@testing-library/jest-dom': + specifier: ^6.9.1 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.3.1 + version: 16.3.1(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@testing-library/user-event': + specifier: ^14.6.1 + version: 14.6.1(@testing-library/dom@10.4.0) '@types/node': specifier: ^24.10.1 - version: 24.10.1 + version: 24.10.4 '@types/react': specifier: ^19.0.0 - version: 19.2.6 + version: 19.2.7 '@types/react-dom': specifier: ^19.0.0 - version: 19.2.3(@types/react@19.2.6) + version: 19.2.3(@types/react@19.2.7) '@vanilla-extract/css': specifier: ^1.17.4 - version: 1.17.4 + version: 1.18.0 '@vanilla-extract/recipes': specifier: ^0.5.7 - version: 0.5.7(@vanilla-extract/css@1.17.4) + version: 0.5.7(@vanilla-extract/css@1.18.0) '@vanilla-extract/vite-plugin': specifier: ^5.1.1 - version: 5.1.1(@types/node@24.10.1)(vite@5.4.21(@types/node@24.10.1)) + version: 5.1.4(@types/node@24.10.4)(vite@5.4.21(@types/node@24.10.4)) '@vitejs/plugin-react': specifier: ^5.1.0 - version: 5.1.1(vite@5.4.21(@types/node@24.10.1)) + version: 5.1.2(vite@5.4.21(@types/node@24.10.4)) + '@vitest/ui': + specifier: ^4.0.16 + version: 4.0.16(vitest@4.0.16) eslint: specifier: ^9.39.1 - version: 9.39.1 + version: 9.39.2 eslint-plugin-react-hooks: specifier: ^5.2.0 - version: 5.2.0(eslint@9.39.1) + version: 5.2.0(eslint@9.39.2) eslint-plugin-react-refresh: specifier: ^0.4.24 - version: 0.4.24(eslint@9.39.1) + version: 0.4.26(eslint@9.39.2) eslint-plugin-storybook: specifier: ^10.0.7 - version: 10.0.8(eslint@9.39.1)(storybook@8.6.14(prettier@3.6.2))(typescript@5.9.3) + version: 10.1.11(eslint@9.39.2)(storybook@8.6.15(prettier@3.7.4))(typescript@5.9.3) globals: specifier: ^16.5.0 version: 16.5.0 + jsdom: + specifier: ^27.4.0 + version: 27.4.0 react: specifier: ^19.0.0 - version: 19.2.0 + version: 19.2.3 react-dom: specifier: ^19.0.0 - version: 19.2.0(react@19.2.0) + version: 19.2.3(react@19.2.3) storybook: specifier: ^8 - version: 8.6.14(prettier@3.6.2) + version: 8.6.15(prettier@3.7.4) storybook-dark-mode: specifier: ^4.0.2 - version: 4.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2)) + version: 4.0.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4)) typescript: specifier: ~5.9.3 version: 5.9.3 typescript-eslint: specifier: ^8.46.3 - version: 8.47.0(eslint@9.39.1)(typescript@5.9.3) + version: 8.52.0(eslint@9.39.2)(typescript@5.9.3) vite: specifier: ^5.4.11 - version: 5.4.21(@types/node@24.10.1) + version: 5.4.21(@types/node@24.10.4) + vitest: + specifier: ^4.0.16 + version: 4.0.16(@types/node@24.10.4)(@vitest/ui@4.0.16)(jsdom@27.4.0) packages: + '@acemir/cssom@0.9.30': + resolution: {integrity: sha512-9CnlMCI0LmCIq0olalQqdWrJHPzm0/tw3gzOA9zJSgvFX7Xau3D24mAGa4BtwxwY69nsuJW6kQqqCzf/mEcQgg==} + '@adobe/css-tools@4.4.4': resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + '@asamuzakjp/css-color@4.1.1': + resolution: {integrity: sha512-B0Hv6G3gWGMn0xKJ0txEi/jM5iFpT3MfDxmhZFb4W047GvytCf1DHQ1D69W3zHI4yWe2aTZAA0JnbMZ7Xc8DuQ==} + + '@asamuzakjp/dom-selector@6.7.6': + resolution: {integrity: sha512-hBaJER6A9MpdG3WgdlOolHmbOYvSk46y7IQN/1+iqiCuUu6iWdQrs9DGKF8ocqsEqWujWf/V7b7vaDgiUmIvUg==} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -198,8 +231,29 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@changesets/apply-release-plan@7.0.13': - resolution: {integrity: sha512-BIW7bofD2yAWoE8H4V40FikC+1nNFEKBisMECccS16W1rt6qqhNTBDmIw5HaqmMgtLNz9e7oiALiEUuKrQ4oHg==} + '@base-ui/react@1.0.0': + resolution: {integrity: sha512-4USBWz++DUSLTuIYpbYkSgy1F9ZmNG9S/lXvlUN6qMK0P0RlW+6eQmDUB4DgZ7HVvtXl4pvi4z5J2fv6Z3+9hg==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17 || ^18 || ^19 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + + '@base-ui/utils@0.2.3': + resolution: {integrity: sha512-/CguQ2PDaOzeVOkllQR8nocJ0FFIDqsWIcURsVmm53QGo8NhFNpePjNlyPIB41luxfOqnG7PU0xicMEw3ls7XQ==} + peerDependencies: + '@types/react': ^17 || ^18 || ^19 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + + '@changesets/apply-release-plan@7.0.14': + resolution: {integrity: sha512-ddBvf9PHdy2YY0OUiEl3TV78mH9sckndJR14QAt87KLEbIov81XO0q0QAmvooBxXlqRRP8I9B7XOzZwQG7JkWA==} '@changesets/assemble-release-plan@6.0.9': resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} @@ -207,12 +261,12 @@ packages: '@changesets/changelog-git@0.2.1': resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} - '@changesets/cli@2.29.7': - resolution: {integrity: sha512-R7RqWoaksyyKXbKXBTbT4REdy22yH81mcFK6sWtqSanxUCbUi9Uf+6aqxZtDQouIqPdem2W56CdxXgsxdq7FLQ==} + '@changesets/cli@2.29.8': + resolution: {integrity: sha512-1weuGZpP63YWUYjay/E84qqwcnt5yJMM0tep10Up7Q5cS/DGe2IZ0Uj3HNMxGhCINZuR7aO9WBMdKnPit5ZDPA==} hasBin: true - '@changesets/config@3.1.1': - resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==} + '@changesets/config@3.1.2': + resolution: {integrity: sha512-CYiRhA4bWKemdYi/uwImjPxqWNpqGPNbEBdX1BdONALFIDK7MCUj6FPkzD+z9gJcvDFUQJn9aDVf4UG7OT6Kog==} '@changesets/errors@0.2.0': resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} @@ -220,8 +274,8 @@ packages: '@changesets/get-dependents-graph@2.1.3': resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} - '@changesets/get-release-plan@4.0.13': - resolution: {integrity: sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==} + '@changesets/get-release-plan@4.0.14': + resolution: {integrity: sha512-yjZMHpUHgl4Xl5gRlolVuxDkm4HgSJqT93Ri1Uz8kGrQb+5iJ8dkXJ20M2j/Y4iV5QzS2c5SeTxVSKX+2eMI0g==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} @@ -232,14 +286,14 @@ packages: '@changesets/logger@0.1.1': resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} - '@changesets/parse@0.4.1': - resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==} + '@changesets/parse@0.4.2': + resolution: {integrity: sha512-Uo5MC5mfg4OM0jU3up66fmSn6/NE9INK+8/Vn/7sMVcdWg46zfbvvUSjD9EMonVqPi9fbrJH9SXHn48Tr1f2yA==} '@changesets/pre@2.0.2': resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} - '@changesets/read@0.6.5': - resolution: {integrity: sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==} + '@changesets/read@0.6.6': + resolution: {integrity: sha512-P5QaN9hJSQQKJShzzpBT13FzOSPyHbqdoIBUd2DJdgvnECCyO6LmAOWSV+O8se2TaZJVwSXjL+v9yhb+a9JeJg==} '@changesets/should-skip-package@0.1.2': resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} @@ -253,6 +307,38 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.0.23': + resolution: {integrity: sha512-YEmgyklR6l/oKUltidNVYdjSmLSW88vMsKx0pmiS3r71s8ZZRpd8A0Yf0U+6p/RzElmMnPBv27hNWjDQMSZRtQ==} + engines: {node: '>=18'} + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@emotion/hash@0.9.2': resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} @@ -268,6 +354,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} @@ -280,6 +372,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} @@ -292,6 +390,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} @@ -304,6 +408,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} @@ -316,6 +426,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} @@ -328,6 +444,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} @@ -340,6 +462,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} @@ -352,6 +480,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} @@ -364,6 +498,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} @@ -376,6 +516,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} @@ -388,6 +534,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} @@ -400,6 +552,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} @@ -412,6 +570,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} @@ -424,6 +588,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} @@ -436,6 +606,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} @@ -448,6 +624,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} @@ -460,12 +642,24 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.12': resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} @@ -478,12 +672,24 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.12': resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} @@ -496,12 +702,24 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/openharmony-arm64@0.25.12': resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} @@ -514,6 +732,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} @@ -526,6 +750,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} @@ -538,6 +768,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} @@ -550,8 +786,14 @@ packages: cpu: [x64] os: [win32] - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -572,12 +814,12 @@ packages: resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.1': - resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': @@ -588,6 +830,30 @@ packages: resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@exodus/bytes@1.8.0': + resolution: {integrity: sha512-8JPn18Bcp8Uo1T82gR8lh2guEOa5KKU/IEKvvdp0sgmi7coPBWf1Doi1EXsGZb2ehc8ym/StJCjffYV+ne7sXQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@exodus/crypto': ^1.0.0-rc.4 + peerDependenciesMeta: + '@exodus/crypto': + optional: true + + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} + + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} + + '@floating-ui/react-dom@2.1.6': + resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -670,8 +936,11 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@rolldown/pluginutils@1.0.0-beta.47': - resolution: {integrity: sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@rolldown/pluginutils@1.0.0-beta.53': + resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} '@rollup/pluginutils@5.3.0': resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} @@ -682,120 +951,138 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.53.3': - resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} + '@rollup/rollup-android-arm-eabi@4.55.1': + resolution: {integrity: sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.3': - resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} + '@rollup/rollup-android-arm64@4.55.1': + resolution: {integrity: sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.3': - resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} + '@rollup/rollup-darwin-arm64@4.55.1': + resolution: {integrity: sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.3': - resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} + '@rollup/rollup-darwin-x64@4.55.1': + resolution: {integrity: sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.3': - resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} + '@rollup/rollup-freebsd-arm64@4.55.1': + resolution: {integrity: sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.3': - resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} + '@rollup/rollup-freebsd-x64@4.55.1': + resolution: {integrity: sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': - resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} + '@rollup/rollup-linux-arm-gnueabihf@4.55.1': + resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.3': - resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} + '@rollup/rollup-linux-arm-musleabihf@4.55.1': + resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.3': - resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} + '@rollup/rollup-linux-arm64-gnu@4.55.1': + resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.53.3': - resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} + '@rollup/rollup-linux-arm64-musl@4.55.1': + resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.3': - resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} + '@rollup/rollup-linux-loong64-gnu@4.55.1': + resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.3': - resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} + '@rollup/rollup-linux-loong64-musl@4.55.1': + resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.55.1': + resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.55.1': + resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.3': - resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} + '@rollup/rollup-linux-riscv64-gnu@4.55.1': + resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.3': - resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + '@rollup/rollup-linux-riscv64-musl@4.55.1': + resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.3': - resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} + '@rollup/rollup-linux-s390x-gnu@4.55.1': + resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.3': - resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + '@rollup/rollup-linux-x64-gnu@4.55.1': + resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.3': - resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} + '@rollup/rollup-linux-x64-musl@4.55.1': + resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.53.3': - resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + '@rollup/rollup-openbsd-x64@4.55.1': + resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.55.1': + resolution: {integrity: sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.3': - resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} + '@rollup/rollup-win32-arm64-msvc@4.55.1': + resolution: {integrity: sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.3': - resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} + '@rollup/rollup-win32-ia32-msvc@4.55.1': + resolution: {integrity: sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.3': - resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} + '@rollup/rollup-win32-x64-gnu@4.55.1': + resolution: {integrity: sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.3': - resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} + '@rollup/rollup-win32-x64-msvc@4.55.1': + resolution: {integrity: sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==} cpu: [x64] os: [win32] - '@storybook/addon-a11y@8.6.14': - resolution: {integrity: sha512-fozv6enO9IgpWq2U8qqS8MZ21Nt+MVHiRQe3CjnCpBOejTyo/ATm690PeYYRVHVG6M/15TVePb0h3ngKQbrrzQ==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@storybook/addon-a11y@8.6.15': + resolution: {integrity: sha512-hNSI28z1PCu7/mQ+skVHX+PvLwnLLiM4d+Ecr0hhZLJDwa5JoZrnszSrCoGadSzaRe270kwjYoEwgX9MGXaxrA==} peerDependencies: - storybook: ^8.6.14 + storybook: ^8.6.15 '@storybook/addon-actions@8.6.14': resolution: {integrity: sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ==} @@ -827,6 +1114,11 @@ packages: peerDependencies: storybook: ^8.6.14 + '@storybook/addon-highlight@8.6.15': + resolution: {integrity: sha512-lOu44QTVw5nR8kzag0ukxWnLq48oy2MqMUDuMVFQWPBKX8ayhmgl2OiEcvAOVNsieTHrr2W4CkP7FFvF4D0vlg==} + peerDependencies: + storybook: ^8.6.15 + '@storybook/addon-interactions@8.6.14': resolution: {integrity: sha512-8VmElhm2XOjh22l/dO4UmXxNOolGhNiSpBcls2pqWSraVh4a670EyYBZsHpkXqfNHo2YgKyZN3C91+9zfH79qQ==} peerDependencies: @@ -869,10 +1161,10 @@ packages: react-dom: optional: true - '@storybook/builder-vite@8.6.14': - resolution: {integrity: sha512-ajWYhy32ksBWxwWHrjwZzyC0Ii5ZTeu5lsqA95Q/EQBB0P5qWlHWGM3AVyv82Mz/ND03ebGy123uVwgf6olnYQ==} + '@storybook/builder-vite@8.6.15': + resolution: {integrity: sha512-9Y05/ndZE6/eI7ZIUCD/QtH2htRIUs9j1gxE6oW0zRo9TJO1iqxfLNwgzd59KEkId7gdZxPei0l+LGTUGXYKRg==} peerDependencies: - storybook: ^8.6.14 + storybook: ^8.6.15 vite: ^4.0.0 || ^5.0.0 || ^6.0.0 '@storybook/components@8.6.14': @@ -880,13 +1172,18 @@ packages: peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + '@storybook/components@8.6.15': + resolution: {integrity: sha512-+9GVKXPEW8Kl9zvNSTm9+VrJtx/puMZiO7gxCML63nK4aTWJXHQr4t9YUoGammSBM3AV1JglsKm6dBgJEeCoiA==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + '@storybook/core-events@8.6.14': resolution: {integrity: sha512-RrJ95u3HuIE4Nk8VmZP0tc/u0vYoE2v9fYlMw6K2GUSExzKDITs3voy6WMIY7Q3qbQun8XUXVlmqkuFzTEy/pA==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/core@8.6.14': - resolution: {integrity: sha512-1P/w4FSNRqP8j3JQBOi3yGt8PVOgSRbP66Ok520T78eJBeqx9ukCfl912PQZ7SPbW3TIunBwLXMZOjZwBB/JmA==} + '@storybook/core@8.6.15': + resolution: {integrity: sha512-VFpKcphNurJpSC4fpUfKL3GTXVoL53oytghGR30QIw5jKWwaT50HVbTyb41BLOUuZjmMhUQA8weiQEew6RX0gw==} peerDependencies: prettier: ^2 || ^3 peerDependenciesMeta: @@ -898,6 +1195,11 @@ packages: peerDependencies: storybook: ^8.6.14 + '@storybook/csf-plugin@8.6.15': + resolution: {integrity: sha512-ZLz/mtOoE1Jj2lE4pK3U7MmYrv5+lot3mGtwxGb832tcABMc97j9O+reCVxZYc7DeFbBuuEdMT9rBL/O3kXYmw==} + peerDependencies: + storybook: ^8.6.15 + '@storybook/global@5.0.0': resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} @@ -913,13 +1215,23 @@ packages: peerDependencies: storybook: ^8.6.14 + '@storybook/instrumenter@8.6.15': + resolution: {integrity: sha512-TvHR/+yyIAOp/1bLulFai2kkhIBtAlBw7J6Jd9DKyInoGhTWNE1G1Y61jD5GWXX29AlwaHfzGUaX5NL1K+FJpg==} + peerDependencies: + storybook: ^8.6.15 + '@storybook/manager-api@8.6.14': resolution: {integrity: sha512-ez0Zihuy17udLbfHZQXkGqwtep0mSGgHcNzGN7iZrMP1m+VmNo+7aGCJJdvXi7+iU3yq8weXSQFWg5DqWgLS7g==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/preview-api@8.6.14': - resolution: {integrity: sha512-2GhcCd4dNMrnD7eooEfvbfL4I83qAqEyO0CO7JQAmIO6Rxb9BsOLLI/GD5HkvQB73ArTJ+PT50rfaO820IExOQ==} + '@storybook/manager-api@8.6.15': + resolution: {integrity: sha512-ZOFtH821vFcwzECbFYFTKtSVO96Cvwwg45dMh3M/9bZIdN7klsloX7YNKw8OKvwE6XLFLsi2OvsNNcmTW6g88w==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/preview-api@8.6.15': + resolution: {integrity: sha512-oqsp8f7QekB9RzpDqOXZQcPPRXXd/mTsnZSdAAQB/pBVqUpC9h/y5hgovbYnJ6DWXcpODbMwH+wbJHZu5lvm+w==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 @@ -930,27 +1242,34 @@ packages: react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta storybook: ^8.6.14 - '@storybook/react-vite@8.6.14': - resolution: {integrity: sha512-FZU0xMPxa4/TO87FgcWwappOxLBHZV5HSRK5K+2bJD7rFJAoNorbHvB4Q1zvIAk7eCMjkr2GPCPHx9PRB9vJFg==} + '@storybook/react-dom-shim@8.6.15': + resolution: {integrity: sha512-m2trBmmd4iom1qwrp1F109zjRDc0cPaHYhDQxZR4Qqdz8pYevYJTlipDbH/K4NVB6Rn687RT29OoOPfJh6vkFA==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + storybook: ^8.6.15 + + '@storybook/react-vite@8.6.15': + resolution: {integrity: sha512-9st+2NCemzzBwmindpDrRLEqYJmwwd2RnXMoj+Wt4Y1r4MGoRe1l837ciT2tmstaqekY2mVUSYd6879NzeeMYw==} engines: {node: '>=18.0.0'} peerDependencies: - '@storybook/test': 8.6.14 + '@storybook/test': 8.6.15 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.6.14 + storybook: ^8.6.15 vite: ^4.0.0 || ^5.0.0 || ^6.0.0 peerDependenciesMeta: '@storybook/test': optional: true - '@storybook/react@8.6.14': - resolution: {integrity: sha512-BOepx5bBFwl/CPI+F+LnmMmsG1wQYmrX/UQXgUbHQUU9Tj7E2ndTnNbpIuSLc8IrM03ru+DfwSg1Co3cxWtT+g==} + '@storybook/react@8.6.15': + resolution: {integrity: sha512-hdnhlJg+YkpPMOw2hvK7+mhdxAbguA+TFTIAzVV9CeUYoHDIZAsgeKVhRmgZGN20NGjRN5ZcwkplAMJnF9v+6w==} engines: {node: '>=18.0.0'} peerDependencies: - '@storybook/test': 8.6.14 + '@storybook/test': 8.6.15 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.6.14 + storybook: ^8.6.15 typescript: '>= 4.2.x' peerDependenciesMeta: '@storybook/test': @@ -968,11 +1287,21 @@ packages: peerDependencies: storybook: ^8.6.14 + '@storybook/test@8.6.15': + resolution: {integrity: sha512-EwquDRUDVvWcZds3T2abmB5wSN/Vattal4YtZ6fpBlIUqONV4o/cOBX39cFfQSUCBrIXIjQ6RmapQCHK/PvBYw==} + peerDependencies: + storybook: ^8.6.15 + '@storybook/theming@8.6.14': resolution: {integrity: sha512-r4y+LsiB37V5hzpQo+BM10PaCsp7YlZ0YcZzQP1OCkPlYXmUAFy2VvDKaFRpD8IeNPKug2u4iFm/laDEbs03dg==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + '@storybook/theming@8.6.15': + resolution: {integrity: sha512-dAbL0XOekyT6XsF49R6Etj3WxQ/LpdJDIswUUeHgVJ6/yd2opZOGbPxnwA3zlmAh1c0tvpPyhSDXxSG79u8e4Q==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + '@testing-library/dom@10.4.0': resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} @@ -981,12 +1310,37 @@ packages: resolution: {integrity: sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.3.1': + resolution: {integrity: sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@testing-library/user-event@14.5.2': resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} engines: {node: '>=12', npm: '>=6'} peerDependencies: '@testing-library/dom': '>=7.21.4' + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -1002,6 +1356,12 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/doctrine@0.0.9': resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} @@ -1017,16 +1377,16 @@ packages: '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@24.10.1': - resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/node@24.10.4': + resolution: {integrity: sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==} '@types/react-dom@19.2.3': resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.6': - resolution: {integrity: sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==} + '@types/react@19.2.7': + resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} @@ -1034,76 +1394,76 @@ packages: '@types/uuid@9.0.8': resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} - '@typescript-eslint/eslint-plugin@8.47.0': - resolution: {integrity: sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==} + '@typescript-eslint/eslint-plugin@8.52.0': + resolution: {integrity: sha512-okqtOgqu2qmZJ5iN4TWlgfF171dZmx2FzdOv2K/ixL2LZWDStL8+JgQerI2sa8eAEfoydG9+0V96m7V+P8yE1Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.47.0 + '@typescript-eslint/parser': ^8.52.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.47.0': - resolution: {integrity: sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==} + '@typescript-eslint/parser@8.52.0': + resolution: {integrity: sha512-iIACsx8pxRnguSYhHiMn2PvhvfpopO9FXHyn1mG5txZIsAaB6F0KwbFnUQN3KCiG3Jcuad/Cao2FAs1Wp7vAyg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.47.0': - resolution: {integrity: sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==} + '@typescript-eslint/project-service@8.52.0': + resolution: {integrity: sha512-xD0MfdSdEmeFa3OmVqonHi+Cciab96ls1UhIF/qX/O/gPu5KXD0bY9lu33jj04fjzrXHcuvjBcBC+D3SNSadaw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.47.0': - resolution: {integrity: sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==} + '@typescript-eslint/scope-manager@8.52.0': + resolution: {integrity: sha512-ixxqmmCcc1Nf8S0mS0TkJ/3LKcC8mruYJPOU6Ia2F/zUUR4pApW7LzrpU3JmtePbRUTes9bEqRc1Gg4iyRnDzA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.47.0': - resolution: {integrity: sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==} + '@typescript-eslint/tsconfig-utils@8.52.0': + resolution: {integrity: sha512-jl+8fzr/SdzdxWJznq5nvoI7qn2tNYV/ZBAEcaFMVXf+K6jmXvAFrgo/+5rxgnL152f//pDEAYAhhBAZGrVfwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.47.0': - resolution: {integrity: sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==} + '@typescript-eslint/type-utils@8.52.0': + resolution: {integrity: sha512-JD3wKBRWglYRQkAtsyGz1AewDu3mTc7NtRjR/ceTyGoPqmdS5oCdx/oZMWD5Zuqmo6/MpsYs0wp6axNt88/2EQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.47.0': - resolution: {integrity: sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==} + '@typescript-eslint/types@8.52.0': + resolution: {integrity: sha512-LWQV1V4q9V4cT4H5JCIx3481iIFxH1UkVk+ZkGGAV1ZGcjGI9IoFOfg3O6ywz8QqCDEp7Inlg6kovMofsNRaGg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.47.0': - resolution: {integrity: sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==} + '@typescript-eslint/typescript-estree@8.52.0': + resolution: {integrity: sha512-XP3LClsCc0FsTK5/frGjolyADTh3QmsLp6nKd476xNI9CsSsLnmn4f0jrzNoAulmxlmNIpeXuHYeEQv61Q6qeQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.47.0': - resolution: {integrity: sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==} + '@typescript-eslint/utils@8.52.0': + resolution: {integrity: sha512-wYndVMWkweqHpEpwPhwqE2lnD2DxC6WVLupU/DOt/0/v+/+iQbbzO3jOHjmBMnhu0DgLULvOaU4h4pwHYi2oRQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.47.0': - resolution: {integrity: sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==} + '@typescript-eslint/visitor-keys@8.52.0': + resolution: {integrity: sha512-ink3/Zofus34nmBsPjow63FP5M7IGff0RKAgqR6+CFpdk22M7aLwC9gOcLGYqr7MczLPzZVERW9hRog3O4n1sQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@vanilla-extract/babel-plugin-debug-ids@1.2.2': resolution: {integrity: sha512-MeDWGICAF9zA/OZLOKwhoRlsUW+fiMwnfuOAqFVohL31Agj7Q/RBWAYweqjHLgFBCsdnr6XIfwjJnmb2znEWxw==} - '@vanilla-extract/compiler@0.3.1': - resolution: {integrity: sha512-KZ67DZQu58dMo7Jv4PNMPG5TbMOXB68xxVYV2cRJvUdPeiOmX0FOaPgEsYBAZUgd/oLEx4IyV0AvlvsxJ1akfQ==} + '@vanilla-extract/compiler@0.3.4': + resolution: {integrity: sha512-W9HXf9EAccpE1vEIATvSoBVj/bQnmHfYHfDJjUN8dcOHW6oMcnoGTqweDM9I66BHqlNH4d0IsaeZKSViOv7K4w==} - '@vanilla-extract/css@1.17.4': - resolution: {integrity: sha512-m3g9nQDWPtL+sTFdtCGRMI1Vrp86Ay4PBYq1Bo7Bnchj5ElNtAJpOqD+zg+apthVA4fB7oVpMWNjwpa6ElDWFQ==} + '@vanilla-extract/css@1.18.0': + resolution: {integrity: sha512-/p0dwOjr0o8gE5BRQ5O9P0u/2DjUd6Zfga2JGmE4KaY7ZITWMszTzk4x4CPlM5cKkRr2ZGzbE6XkuPNfp9shSQ==} - '@vanilla-extract/integration@8.0.4': - resolution: {integrity: sha512-cmOb7tR+g3ulKvFtSbmdw3YUyIS1d7MQqN+FcbwNhdieyno5xzUyfDCMjeWJhmCSMvZ6WlinkrOkgs6SHB+FRg==} + '@vanilla-extract/integration@8.0.7': + resolution: {integrity: sha512-ILob4F9cEHXpbWAVt3Y2iaQJpqYq/c/5TJC8Fz58C2XmX3QW2Y589krvViiyJhQfydCGK3EbwPQhVFjQaBeKfg==} '@vanilla-extract/private@1.0.9': resolution: {integrity: sha512-gT2jbfZuaaCLrAxwXbRgIhGhcXbRZCG3v4TTUnjw0EJ7ArdBRxkq4msNJkbuRkCgfIK5ATmprB5t9ljvLeFDEA==} @@ -1113,13 +1473,13 @@ packages: peerDependencies: '@vanilla-extract/css': ^1.0.0 - '@vanilla-extract/vite-plugin@5.1.1': - resolution: {integrity: sha512-Nd1worqkHrd8XED4ZAA7Wmkd3pCqCwpmzCBVF8v6T1BSLHGXQE5HYflVgygw0CsIAbFRMS6zQBIk4F4/r/YKIw==} + '@vanilla-extract/vite-plugin@5.1.4': + resolution: {integrity: sha512-fTYNKUK3n4ApkUf2FEcO7mpqNKEHf9kDGg8DXlkqHtPxgwPhjuaajmDfQCSBsNgnA2SLI+CB5EO6kLQuKsw2Rw==} peerDependencies: vite: ^5.0.0 || ^6.0.0 || ^7.0.0 - '@vitejs/plugin-react@5.1.1': - resolution: {integrity: sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA==} + '@vitejs/plugin-react@5.1.2': + resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -1127,21 +1487,55 @@ packages: '@vitest/expect@2.0.5': resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} + '@vitest/expect@4.0.16': + resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==} + + '@vitest/mocker@4.0.16': + resolution: {integrity: sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/pretty-format@2.0.5': resolution: {integrity: sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==} '@vitest/pretty-format@2.1.9': resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + '@vitest/pretty-format@4.0.16': + resolution: {integrity: sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA==} + + '@vitest/runner@4.0.16': + resolution: {integrity: sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q==} + + '@vitest/snapshot@4.0.16': + resolution: {integrity: sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA==} + '@vitest/spy@2.0.5': resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} + '@vitest/spy@4.0.16': + resolution: {integrity: sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw==} + + '@vitest/ui@4.0.16': + resolution: {integrity: sha512-rkoPH+RqWopVxDnCBE/ysIdfQ2A7j1eDmW8tCxxrR9nnFBa9jKf86VgsSAzxBd1x+ny0GC4JgiD3SNfRHv3pOg==} + peerDependencies: + vitest: 4.0.16 + '@vitest/utils@2.0.5': resolution: {integrity: sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==} '@vitest/utils@2.1.9': resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + '@vitest/utils@4.0.16': + resolution: {integrity: sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1152,6 +1546,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -1208,15 +1606,15 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} - axe-core@4.11.0: - resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} + axe-core@4.11.1: + resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==} engines: {node: '>=4'} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - baseline-browser-mapping@2.8.29: - resolution: {integrity: sha512-sXdt2elaVnhpDNRDz+1BDx1JQoJRuNk7oVlAlbGiFkLikHCAQiccexF/9e91zVi6RCgqspl04aP+6Cnl9zRLrA==} + baseline-browser-mapping@2.9.13: + resolution: {integrity: sha512-WhtvB2NG2wjr04+h77sg3klAIwrgOqnjS49GGudnUPGFFgg7G17y7Qecqp+2Dr5kUDxNRBca0SK7cG8JwzkWDQ==} hasBin: true better-opn@3.0.2: @@ -1227,6 +1625,9 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -1240,8 +1641,8 @@ packages: browser-assert@1.2.1: resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} - browserslist@4.28.0: - resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1265,13 +1666,17 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001756: - resolution: {integrity: sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==} + caniuse-lite@1.0.30001763: + resolution: {integrity: sha512-mh/dGtq56uN98LlNX9qdbKnzINhX0QzhiWBFEkFfsFO4QyCvL8YegrJAazCwXIeqkIob8BlZPGM3xdnY+sgmvQ==} chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + chalk@3.0.0: resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} engines: {node: '>=8'} @@ -1283,8 +1688,8 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - check-error@2.1.1: - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} ci-info@3.9.0: @@ -1315,6 +1720,10 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.2.2: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} @@ -1327,9 +1736,17 @@ packages: engines: {node: '>=4'} hasBin: true + cssstyle@5.3.7: + resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==} + engines: {node: '>=20'} + csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + data-urls@6.0.0: + resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} + engines: {node: '>=20'} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -1339,8 +1756,11 @@ packages: supports-color: optional: true - dedent@1.7.0: - resolution: {integrity: sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + dedent@1.7.1: + resolution: {integrity: sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==} peerDependencies: babel-plugin-macros: ^3.1.0 peerDependenciesMeta: @@ -1398,8 +1818,8 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.256: - resolution: {integrity: sha512-uqYq1IQhpXXLX+HgiXdyOZml7spy4xfy42yPxcCCRjswp0fYM2X+JwCON07lqnpLEGVCj739B7Yr+FngmHBMEQ==} + electron-to-chromium@1.5.267: + resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1411,6 +1831,10 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1426,8 +1850,8 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} - es-toolkit@1.42.0: - resolution: {integrity: sha512-SLHIyY7VfDJBM8clz4+T2oquwTQxEzu263AyhVK4jREOAwJ+8eebaa4wM3nlvnAqhDrMm2EsA6hWHaQsMPQ1nA==} + es-toolkit@1.43.0: + resolution: {integrity: sha512-SKCT8AsWvYzBBuUqMk4NPwFlSdqLpJwmy6AP322ERn8W2YLIB6JBXnwMI2Qsh2gfphT3q7EKAxKb23cvFHFwKA==} esbuild-register@3.6.0: resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} @@ -1444,6 +1868,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1458,16 +1887,16 @@ packages: peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - eslint-plugin-react-refresh@0.4.24: - resolution: {integrity: sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==} + eslint-plugin-react-refresh@0.4.26: + resolution: {integrity: sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==} peerDependencies: eslint: '>=8.40' - eslint-plugin-storybook@10.0.8: - resolution: {integrity: sha512-ZKEMFhF/z/HRVvIgnEIYG2uAqmuLbkebUdHH3DpGHE64GPgk+KozcpqnD6zNk5vJ407bFmcWsGinBc2zi74f0g==} + eslint-plugin-storybook@10.1.11: + resolution: {integrity: sha512-mbq2r2kK5+AcLl0XDJ3to91JOgzCbHOqj+J3n+FRw6drk+M1boRqMShSoMMm0HdzXPLmlr7iur+qJ5ZuhH6ayQ==} peerDependencies: eslint: '>=8' - storybook: ^10.0.8 + storybook: ^10.1.11 eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} @@ -1481,8 +1910,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.39.1: - resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} + eslint@9.39.2: + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1500,8 +1929,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -1526,6 +1955,10 @@ packages: resolution: {integrity: sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==} engines: {node: '>= 0.8'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} @@ -1542,8 +1975,20 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} @@ -1639,9 +2084,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -1661,12 +2103,24 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - human-id@4.1.2: - resolution: {integrity: sha512-v/J+4Z/1eIJovEBdlV5TYj1IR+ZiohcYGRY+qN/oC9dAfKzVT023N/Bgw37hrKCoVRBvk3bqyzpr2PP5YeTMSg==} + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-id@4.1.3: + resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} hasBin: true - iconv-lite@0.7.0: - resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + iconv-lite@0.7.1: + resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} engines: {node: '>=0.10.0'} ignore@5.3.2: @@ -1729,6 +2183,9 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -1773,6 +2230,15 @@ packages: resolution: {integrity: sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==} engines: {node: '>=12.0.0'} + jsdom@27.4.0: + resolution: {integrity: sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -1825,6 +2291,10 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.4: + resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -1846,6 +2316,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + media-query-parser@2.0.2: resolution: {integrity: sha512-1N4qp+jE0pL5Xv4uEcwVUhIkwdUO3S/9gML90nqKA7v7FcOS5vUtatfzok9S9U1EJU8dHWlcv95WLnKmmxZI9w==} @@ -1888,6 +2361,10 @@ packages: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1902,6 +2379,9 @@ packages: node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -1951,6 +2431,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse5@8.0.0: + resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -2016,8 +2499,8 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.6.2: - resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + prettier@3.7.4: + resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} engines: {node: '>=14'} hasBin: true @@ -2048,10 +2531,10 @@ packages: resolution: {integrity: sha512-hlSJDQ2synMPKFZOsKo9Hi8WWZTC7POR8EmWvTSjow+VDgKzkmjQvFm2fk0tmRw+f0vTOIYKlarR0iL4996pdg==} engines: {node: '>=16.14.0'} - react-dom@19.2.0: - resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} + react-dom@19.2.3: + resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: - react: ^19.2.0 + react: ^19.2.3 react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} @@ -2060,8 +2543,8 @@ packages: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} - react@19.2.0: - resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} + react@19.2.3: + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} read-yaml-file@1.1.0: @@ -2076,9 +2559,16 @@ packages: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + require-like@0.1.2: resolution: {integrity: sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==} + reselect@5.1.1: + resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2096,8 +2586,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rollup@4.53.3: - resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} + rollup@4.55.1: + resolution: {integrity: sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2111,6 +2601,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.27.0: resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} @@ -2135,10 +2629,17 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -2157,11 +2658,17 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + storybook-dark-mode@4.0.2: resolution: {integrity: sha512-zjcwwQ01R5t1VsakA6alc2JDIRVtavryW8J3E3eKLDIlAMcvsgtpxlelWkZs2cuNspk6Z10XzhQVrUWtYc3F0w==} - storybook@8.6.14: - resolution: {integrity: sha512-sVKbCj/OTx67jhmauhxc2dcr1P+yOgz/x3h0krwjyMgdc5Oubvxyg4NYDZmzAw+ym36g/lzH8N0Ccp4dwtdfxw==} + storybook@8.6.15: + resolution: {integrity: sha512-Ob7DMlwWx8s7dMvcQ3xPc02TvUeralb+xX3oaPRk9wY9Hc6M1IBC/7cEoITkSmRS2v38DHubC+mtEKNc1u2gQg==} hasBin: true peerDependencies: prettier: ^2 || ^3 @@ -2209,6 +2716,12 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tabbable@6.4.0: + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -2216,20 +2729,54 @@ packages: tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - tinyrainbow@1.2.0: + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tinyrainbow@1.2.0: resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} engines: {node: '>=14.0.0'} + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + tinyspy@3.0.2: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tldts-core@7.0.19: + resolution: {integrity: sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==} + + tldts@7.0.19: + resolution: {integrity: sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tough-cookie@6.0.0: + resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} + engines: {node: '>=16'} + + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + + ts-api-utils@2.4.0: + resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -2249,8 +2796,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.47.0: - resolution: {integrity: sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==} + typescript-eslint@8.52.0: + resolution: {integrity: sha512-atlQQJ2YkO4pfTVQmQ+wvYQwexPDOIgo+RaVcD7gHgzy/IQA+XTyuxNM9M9TVXvttkF7koBHmcwisKdOAf2EcA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2261,8 +2808,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - ufo@1.6.1: - resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + ufo@1.6.2: + resolution: {integrity: sha512-heMioaxBcG9+Znsda5Q8sQbWnLJSl98AFDXTO80wELWEzX3hordXsTdxrIfMQoO9IY1MEnoGoPjpoKpMj+Yx0Q==} undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -2275,8 +2822,8 @@ packages: resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} engines: {node: '>=14.0.0'} - update-browserslist-db@1.1.4: - resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -2284,6 +2831,11 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} @@ -2327,9 +2879,99 @@ packages: terser: optional: true + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.0.16: + resolution: {integrity: sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.16 + '@vitest/browser-preview': 4.0.16 + '@vitest/browser-webdriverio': 4.0.16 + '@vitest/ui': 4.0.16 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@15.1.0: + resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} + engines: {node: '>=20'} + which-typed-array@1.1.19: resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} @@ -2339,6 +2981,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -2351,8 +2998,8 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -2363,6 +3010,13 @@ packages: utf-8-validate: optional: true + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -2372,8 +3026,28 @@ packages: snapshots: + '@acemir/cssom@0.9.30': {} + '@adobe/css-tools@4.4.4': {} + '@asamuzakjp/css-color@4.1.1': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 11.2.4 + + '@asamuzakjp/dom-selector@6.7.6': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.1.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.4 + + '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -2414,7 +3088,7 @@ snapshots: dependencies: '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.0 + browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 @@ -2493,9 +3167,34 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@changesets/apply-release-plan@7.0.13': + '@base-ui/react@1.0.0(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@babel/runtime': 7.28.4 + '@base-ui/utils': 0.2.3(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@floating-ui/utils': 0.2.10 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + reselect: 5.1.1 + tabbable: 6.4.0 + use-sync-external-store: 1.6.0(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.7 + + '@base-ui/utils@0.2.3(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: - '@changesets/config': 3.1.1 + '@babel/runtime': 7.28.4 + '@floating-ui/utils': 0.2.10 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + reselect: 5.1.1 + use-sync-external-store: 1.6.0(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.7 + + '@changesets/apply-release-plan@7.0.14': + dependencies: + '@changesets/config': 3.1.2 '@changesets/get-version-range-type': 0.4.0 '@changesets/git': 3.0.4 '@changesets/should-skip-package': 0.1.2 @@ -2522,23 +3221,23 @@ snapshots: dependencies: '@changesets/types': 6.1.0 - '@changesets/cli@2.29.7(@types/node@24.10.1)': + '@changesets/cli@2.29.8(@types/node@24.10.4)': dependencies: - '@changesets/apply-release-plan': 7.0.13 + '@changesets/apply-release-plan': 7.0.14 '@changesets/assemble-release-plan': 6.0.9 '@changesets/changelog-git': 0.2.1 - '@changesets/config': 3.1.1 + '@changesets/config': 3.1.2 '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 - '@changesets/get-release-plan': 4.0.13 + '@changesets/get-release-plan': 4.0.14 '@changesets/git': 3.0.4 '@changesets/logger': 0.1.1 '@changesets/pre': 2.0.2 - '@changesets/read': 0.6.5 + '@changesets/read': 0.6.6 '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@24.10.1) + '@inquirer/external-editor': 1.0.3(@types/node@24.10.4) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 ci-info: 3.9.0 @@ -2555,7 +3254,7 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@changesets/config@3.1.1': + '@changesets/config@3.1.2': dependencies: '@changesets/errors': 0.2.0 '@changesets/get-dependents-graph': 2.1.3 @@ -2576,12 +3275,12 @@ snapshots: picocolors: 1.1.1 semver: 7.7.3 - '@changesets/get-release-plan@4.0.13': + '@changesets/get-release-plan@4.0.14': dependencies: '@changesets/assemble-release-plan': 6.0.9 - '@changesets/config': 3.1.1 + '@changesets/config': 3.1.2 '@changesets/pre': 2.0.2 - '@changesets/read': 0.6.5 + '@changesets/read': 0.6.6 '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 @@ -2599,10 +3298,10 @@ snapshots: dependencies: picocolors: 1.1.1 - '@changesets/parse@0.4.1': + '@changesets/parse@0.4.2': dependencies: '@changesets/types': 6.1.0 - js-yaml: 3.14.2 + js-yaml: 4.1.1 '@changesets/pre@2.0.2': dependencies: @@ -2611,11 +3310,11 @@ snapshots: '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - '@changesets/read@0.6.5': + '@changesets/read@0.6.6': dependencies: '@changesets/git': 3.0.4 '@changesets/logger': 0.1.1 - '@changesets/parse': 0.4.1 + '@changesets/parse': 0.4.2 '@changesets/types': 6.1.0 fs-extra: 7.0.1 p-filter: 2.1.0 @@ -2634,9 +3333,31 @@ snapshots: dependencies: '@changesets/types': 6.1.0 fs-extra: 7.0.1 - human-id: 4.1.2 + human-id: 4.1.3 prettier: 2.8.8 + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-syntax-patches-for-csstree@1.0.23': {} + + '@csstools/css-tokenizer@3.0.4': {} + '@emotion/hash@0.9.2': {} '@esbuild/aix-ppc64@0.21.5': @@ -2645,150 +3366,228 @@ snapshots: '@esbuild/aix-ppc64@0.25.12': optional: true + '@esbuild/aix-ppc64@0.27.2': + optional: true + '@esbuild/android-arm64@0.21.5': optional: true '@esbuild/android-arm64@0.25.12': optional: true + '@esbuild/android-arm64@0.27.2': + optional: true + '@esbuild/android-arm@0.21.5': optional: true '@esbuild/android-arm@0.25.12': optional: true + '@esbuild/android-arm@0.27.2': + optional: true + '@esbuild/android-x64@0.21.5': optional: true '@esbuild/android-x64@0.25.12': optional: true + '@esbuild/android-x64@0.27.2': + optional: true + '@esbuild/darwin-arm64@0.21.5': optional: true '@esbuild/darwin-arm64@0.25.12': optional: true + '@esbuild/darwin-arm64@0.27.2': + optional: true + '@esbuild/darwin-x64@0.21.5': optional: true '@esbuild/darwin-x64@0.25.12': optional: true + '@esbuild/darwin-x64@0.27.2': + optional: true + '@esbuild/freebsd-arm64@0.21.5': optional: true '@esbuild/freebsd-arm64@0.25.12': optional: true + '@esbuild/freebsd-arm64@0.27.2': + optional: true + '@esbuild/freebsd-x64@0.21.5': optional: true '@esbuild/freebsd-x64@0.25.12': optional: true + '@esbuild/freebsd-x64@0.27.2': + optional: true + '@esbuild/linux-arm64@0.21.5': optional: true '@esbuild/linux-arm64@0.25.12': optional: true + '@esbuild/linux-arm64@0.27.2': + optional: true + '@esbuild/linux-arm@0.21.5': optional: true '@esbuild/linux-arm@0.25.12': optional: true + '@esbuild/linux-arm@0.27.2': + optional: true + '@esbuild/linux-ia32@0.21.5': optional: true '@esbuild/linux-ia32@0.25.12': optional: true + '@esbuild/linux-ia32@0.27.2': + optional: true + '@esbuild/linux-loong64@0.21.5': optional: true '@esbuild/linux-loong64@0.25.12': optional: true + '@esbuild/linux-loong64@0.27.2': + optional: true + '@esbuild/linux-mips64el@0.21.5': optional: true '@esbuild/linux-mips64el@0.25.12': optional: true + '@esbuild/linux-mips64el@0.27.2': + optional: true + '@esbuild/linux-ppc64@0.21.5': optional: true '@esbuild/linux-ppc64@0.25.12': optional: true + '@esbuild/linux-ppc64@0.27.2': + optional: true + '@esbuild/linux-riscv64@0.21.5': optional: true '@esbuild/linux-riscv64@0.25.12': optional: true + '@esbuild/linux-riscv64@0.27.2': + optional: true + '@esbuild/linux-s390x@0.21.5': optional: true '@esbuild/linux-s390x@0.25.12': optional: true + '@esbuild/linux-s390x@0.27.2': + optional: true + '@esbuild/linux-x64@0.21.5': optional: true '@esbuild/linux-x64@0.25.12': optional: true + '@esbuild/linux-x64@0.27.2': + optional: true + '@esbuild/netbsd-arm64@0.25.12': optional: true + '@esbuild/netbsd-arm64@0.27.2': + optional: true + '@esbuild/netbsd-x64@0.21.5': optional: true '@esbuild/netbsd-x64@0.25.12': optional: true + '@esbuild/netbsd-x64@0.27.2': + optional: true + '@esbuild/openbsd-arm64@0.25.12': optional: true + '@esbuild/openbsd-arm64@0.27.2': + optional: true + '@esbuild/openbsd-x64@0.21.5': optional: true '@esbuild/openbsd-x64@0.25.12': optional: true + '@esbuild/openbsd-x64@0.27.2': + optional: true + '@esbuild/openharmony-arm64@0.25.12': optional: true + '@esbuild/openharmony-arm64@0.27.2': + optional: true + '@esbuild/sunos-x64@0.21.5': optional: true '@esbuild/sunos-x64@0.25.12': optional: true + '@esbuild/sunos-x64@0.27.2': + optional: true + '@esbuild/win32-arm64@0.21.5': optional: true '@esbuild/win32-arm64@0.25.12': optional: true + '@esbuild/win32-arm64@0.27.2': + optional: true + '@esbuild/win32-ia32@0.21.5': optional: true '@esbuild/win32-ia32@0.25.12': optional: true + '@esbuild/win32-ia32@0.27.2': + optional: true + '@esbuild/win32-x64@0.21.5': optional: true '@esbuild/win32-x64@0.25.12': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1)': + '@esbuild/win32-x64@0.27.2': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2)': dependencies: - eslint: 9.39.1 + eslint: 9.39.2 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -2809,7 +3608,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.1': + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 debug: 4.4.3 @@ -2823,7 +3622,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.39.1': {} + '@eslint/js@9.39.2': {} '@eslint/object-schema@2.1.7': {} @@ -2832,6 +3631,25 @@ snapshots: '@eslint/core': 0.17.0 levn: 0.4.1 + '@exodus/bytes@1.8.0': {} + + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/react-dom@2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@floating-ui/dom': 1.7.4 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + + '@floating-ui/utils@0.2.10': {} + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': @@ -2843,12 +3661,12 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} - '@inquirer/external-editor@1.0.3(@types/node@24.10.1)': + '@inquirer/external-editor@1.0.3(@types/node@24.10.4)': dependencies: chardet: 2.1.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.1 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@isaacs/cliui@8.0.2': dependencies: @@ -2859,12 +3677,12 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.1))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.4))': dependencies: glob: 10.5.0 magic-string: 0.27.0 react-docgen-typescript: 2.4.0(typescript@5.9.3) - vite: 5.4.21(@types/node@24.10.1) + vite: 5.4.21(@types/node@24.10.4) optionalDependencies: typescript: 5.9.3 @@ -2903,11 +3721,11 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 - '@mdx-js/react@3.1.1(@types/react@19.2.6)(react@19.2.0)': + '@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3)': dependencies: '@types/mdx': 2.0.13 - '@types/react': 19.2.6 - react: 19.2.0 + '@types/react': 19.2.7 + react: 19.2.3 '@nodelib/fs.scandir@2.1.5': dependencies: @@ -2919,217 +3737,239 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 + fastq: 1.20.1 '@pkgjs/parseargs@0.11.0': optional: true - '@rolldown/pluginutils@1.0.0-beta.47': {} + '@polka/url@1.0.0-next.29': {} - '@rollup/pluginutils@5.3.0(rollup@4.53.3)': + '@rolldown/pluginutils@1.0.0-beta.53': {} + + '@rollup/pluginutils@5.3.0(rollup@4.55.1)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.53.3 + rollup: 4.55.1 + + '@rollup/rollup-android-arm-eabi@4.55.1': + optional: true + + '@rollup/rollup-android-arm64@4.55.1': + optional: true - '@rollup/rollup-android-arm-eabi@4.53.3': + '@rollup/rollup-darwin-arm64@4.55.1': optional: true - '@rollup/rollup-android-arm64@4.53.3': + '@rollup/rollup-darwin-x64@4.55.1': optional: true - '@rollup/rollup-darwin-arm64@4.53.3': + '@rollup/rollup-freebsd-arm64@4.55.1': optional: true - '@rollup/rollup-darwin-x64@4.53.3': + '@rollup/rollup-freebsd-x64@4.55.1': optional: true - '@rollup/rollup-freebsd-arm64@4.53.3': + '@rollup/rollup-linux-arm-gnueabihf@4.55.1': optional: true - '@rollup/rollup-freebsd-x64@4.53.3': + '@rollup/rollup-linux-arm-musleabihf@4.55.1': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + '@rollup/rollup-linux-arm64-gnu@4.55.1': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.3': + '@rollup/rollup-linux-arm64-musl@4.55.1': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.3': + '@rollup/rollup-linux-loong64-gnu@4.55.1': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.3': + '@rollup/rollup-linux-loong64-musl@4.55.1': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.3': + '@rollup/rollup-linux-ppc64-gnu@4.55.1': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.3': + '@rollup/rollup-linux-ppc64-musl@4.55.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.3': + '@rollup/rollup-linux-riscv64-gnu@4.55.1': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.3': + '@rollup/rollup-linux-riscv64-musl@4.55.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.3': + '@rollup/rollup-linux-s390x-gnu@4.55.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.3': + '@rollup/rollup-linux-x64-gnu@4.55.1': optional: true - '@rollup/rollup-linux-x64-musl@4.53.3': + '@rollup/rollup-linux-x64-musl@4.55.1': optional: true - '@rollup/rollup-openharmony-arm64@4.53.3': + '@rollup/rollup-openbsd-x64@4.55.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.3': + '@rollup/rollup-openharmony-arm64@4.55.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.3': + '@rollup/rollup-win32-arm64-msvc@4.55.1': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.3': + '@rollup/rollup-win32-ia32-msvc@4.55.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.3': + '@rollup/rollup-win32-x64-gnu@4.55.1': optional: true - '@storybook/addon-a11y@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@rollup/rollup-win32-x64-msvc@4.55.1': + optional: true + + '@standard-schema/spec@1.1.0': {} + + '@storybook/addon-a11y@8.6.15(storybook@8.6.15(prettier@3.7.4))': dependencies: - '@storybook/addon-highlight': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/addon-highlight': 8.6.15(storybook@8.6.15(prettier@3.7.4)) '@storybook/global': 5.0.0 - '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - axe-core: 4.11.0 - storybook: 8.6.14(prettier@3.6.2) + '@storybook/test': 8.6.15(storybook@8.6.15(prettier@3.7.4)) + axe-core: 4.11.1 + storybook: 8.6.15(prettier@3.7.4) - '@storybook/addon-actions@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-actions@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 '@types/uuid': 9.0.8 dequal: 2.0.3 polished: 4.3.1 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) uuid: 9.0.1 - '@storybook/addon-backgrounds@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-backgrounds@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 memoizerific: 1.11.3 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 - '@storybook/addon-controls@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-controls@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 dequal: 2.0.3 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 - '@storybook/addon-docs@8.6.14(@types/react@19.2.6)(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-docs@8.6.14(@types/react@19.2.7)(storybook@8.6.15(prettier@3.7.4))': dependencies: - '@mdx-js/react': 3.1.1(@types/react@19.2.6)(react@19.2.0) - '@storybook/blocks': 8.6.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2)) - '@storybook/csf-plugin': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/react-dom-shim': 8.6.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2)) - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 8.6.14(prettier@3.6.2) + '@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.3) + '@storybook/blocks': 8.6.14(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4)) + '@storybook/csf-plugin': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/react-dom-shim': 8.6.14(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4)) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' - '@storybook/addon-essentials@8.6.14(@types/react@19.2.6)(storybook@8.6.14(prettier@3.6.2))': - dependencies: - '@storybook/addon-actions': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-backgrounds': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-controls': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-docs': 8.6.14(@types/react@19.2.6)(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-highlight': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-measure': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-outline': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-toolbars': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/addon-viewport': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - storybook: 8.6.14(prettier@3.6.2) + '@storybook/addon-essentials@8.6.14(@types/react@19.2.7)(storybook@8.6.15(prettier@3.7.4))': + dependencies: + '@storybook/addon-actions': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-backgrounds': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-controls': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-docs': 8.6.14(@types/react@19.2.7)(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-highlight': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-measure': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-outline': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-toolbars': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/addon-viewport': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' - '@storybook/addon-highlight@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-highlight@8.6.14(storybook@8.6.15(prettier@3.7.4))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.15(prettier@3.7.4) + + '@storybook/addon-highlight@8.6.15(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/addon-interactions@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-interactions@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 - '@storybook/instrumenter': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/instrumenter': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/test': 8.6.14(storybook@8.6.15(prettier@3.7.4)) polished: 4.3.1 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 - '@storybook/addon-measure@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-measure@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) tiny-invariant: 1.3.3 - '@storybook/addon-outline@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-outline@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 - '@storybook/addon-storysource@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-storysource@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - '@storybook/source-loader': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/source-loader': 8.6.14(storybook@8.6.15(prettier@3.7.4)) estraverse: 5.3.0 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) tiny-invariant: 1.3.3 - '@storybook/addon-toolbars@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-toolbars@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/addon-viewport@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/addon-viewport@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: memoizerific: 1.11.3 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/blocks@8.6.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2))': + '@storybook/blocks@8.6.14(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4))': dependencies: - '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - storybook: 8.6.14(prettier@3.6.2) + '@storybook/icons': 1.6.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 optionalDependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) - '@storybook/builder-vite@8.6.14(storybook@8.6.14(prettier@3.6.2))(vite@5.4.21(@types/node@24.10.1))': + '@storybook/builder-vite@8.6.15(storybook@8.6.15(prettier@3.7.4))(vite@5.4.21(@types/node@24.10.4))': dependencies: - '@storybook/csf-plugin': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/csf-plugin': 8.6.15(storybook@8.6.15(prettier@3.7.4)) browser-assert: 1.2.1 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) ts-dedent: 2.2.0 - vite: 5.4.21(@types/node@24.10.1) + vite: 5.4.21(@types/node@24.10.4) + + '@storybook/components@8.6.14(storybook@8.6.15(prettier@3.7.4))': + dependencies: + storybook: 8.6.15(prettier@3.7.4) - '@storybook/components@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/components@8.6.15(storybook@8.6.15(prettier@3.7.4))': dependencies: - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/core-events@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/core-events@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/core@8.6.14(prettier@3.6.2)(storybook@8.6.14(prettier@3.6.2))': + '@storybook/core@8.6.15(prettier@3.7.4)(storybook@8.6.15(prettier@3.7.4))': dependencies: - '@storybook/theming': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/theming': 8.6.15(storybook@8.6.15(prettier@3.7.4)) better-opn: 3.0.2 browser-assert: 1.2.1 esbuild: 0.25.12 @@ -3139,105 +3979,141 @@ snapshots: recast: 0.23.11 semver: 7.7.3 util: 0.12.5 - ws: 8.18.3 + ws: 8.19.0 optionalDependencies: - prettier: 3.6.2 + prettier: 3.7.4 transitivePeerDependencies: - bufferutil - storybook - supports-color - utf-8-validate - '@storybook/csf-plugin@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/csf-plugin@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) + unplugin: 1.16.1 + + '@storybook/csf-plugin@8.6.15(storybook@8.6.15(prettier@3.7.4))': + dependencies: + storybook: 8.6.15(prettier@3.7.4) unplugin: 1.16.1 '@storybook/global@5.0.0': {} - '@storybook/icons@1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@storybook/icons@1.6.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + + '@storybook/instrumenter@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) + '@storybook/global': 5.0.0 + '@vitest/utils': 2.1.9 + storybook: 8.6.15(prettier@3.7.4) - '@storybook/instrumenter@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/instrumenter@8.6.15(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 '@vitest/utils': 2.1.9 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/manager-api@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/manager-api@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/preview-api@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/manager-api@8.6.15(storybook@8.6.15(prettier@3.7.4))': dependencies: - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/react-dom-shim@8.6.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2))': + '@storybook/preview-api@8.6.15(storybook@8.6.15(prettier@3.7.4))': dependencies: - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/react-vite@8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.6.2)))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(rollup@4.53.3)(storybook@8.6.14(prettier@3.6.2))(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.1))': + '@storybook/react-dom-shim@8.6.14(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.1)) - '@rollup/pluginutils': 5.3.0(rollup@4.53.3) - '@storybook/builder-vite': 8.6.14(storybook@8.6.14(prettier@3.6.2))(vite@5.4.21(@types/node@24.10.1)) - '@storybook/react': 8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.6.2)))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2))(typescript@5.9.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + storybook: 8.6.15(prettier@3.7.4) + + '@storybook/react-dom-shim@8.6.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4))': + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + storybook: 8.6.15(prettier@3.7.4) + + '@storybook/react-vite@8.6.15(@storybook/test@8.6.15(storybook@8.6.15(prettier@3.7.4)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rollup@4.55.1)(storybook@8.6.15(prettier@3.7.4))(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.4))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.9.3)(vite@5.4.21(@types/node@24.10.4)) + '@rollup/pluginutils': 5.3.0(rollup@4.55.1) + '@storybook/builder-vite': 8.6.15(storybook@8.6.15(prettier@3.7.4))(vite@5.4.21(@types/node@24.10.4)) + '@storybook/react': 8.6.15(@storybook/test@8.6.15(storybook@8.6.15(prettier@3.7.4)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4))(typescript@5.9.3) find-up: 5.0.0 magic-string: 0.30.21 - react: 19.2.0 + react: 19.2.3 react-docgen: 7.1.1 - react-dom: 19.2.0(react@19.2.0) + react-dom: 19.2.3(react@19.2.3) resolve: 1.22.11 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) tsconfig-paths: 4.2.0 - vite: 5.4.21(@types/node@24.10.1) + vite: 5.4.21(@types/node@24.10.4) optionalDependencies: - '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/test': 8.6.15(storybook@8.6.15(prettier@3.7.4)) transitivePeerDependencies: - rollup - supports-color - typescript - '@storybook/react@8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.6.2)))(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2))(typescript@5.9.3)': + '@storybook/react@8.6.15(@storybook/test@8.6.15(storybook@8.6.15(prettier@3.7.4)))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4))(typescript@5.9.3)': dependencies: - '@storybook/components': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/components': 8.6.15(storybook@8.6.15(prettier@3.7.4)) '@storybook/global': 5.0.0 - '@storybook/manager-api': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/preview-api': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/react-dom-shim': 8.6.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2)) - '@storybook/theming': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) - storybook: 8.6.14(prettier@3.6.2) + '@storybook/manager-api': 8.6.15(storybook@8.6.15(prettier@3.7.4)) + '@storybook/preview-api': 8.6.15(storybook@8.6.15(prettier@3.7.4)) + '@storybook/react-dom-shim': 8.6.15(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4)) + '@storybook/theming': 8.6.15(storybook@8.6.15(prettier@3.7.4)) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + storybook: 8.6.15(prettier@3.7.4) optionalDependencies: - '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/test': 8.6.15(storybook@8.6.15(prettier@3.7.4)) typescript: 5.9.3 - '@storybook/source-loader@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/source-loader@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - es-toolkit: 1.42.0 + es-toolkit: 1.43.0 estraverse: 5.3.0 - prettier: 3.6.2 - storybook: 8.6.14(prettier@3.6.2) + prettier: 3.7.4 + storybook: 8.6.15(prettier@3.7.4) + + '@storybook/test@8.6.14(storybook@8.6.15(prettier@3.7.4))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@testing-library/dom': 10.4.0 + '@testing-library/jest-dom': 6.5.0 + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) + '@vitest/expect': 2.0.5 + '@vitest/spy': 2.0.5 + storybook: 8.6.15(prettier@3.7.4) - '@storybook/test@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/test@8.6.15(storybook@8.6.15(prettier@3.7.4))': dependencies: '@storybook/global': 5.0.0 - '@storybook/instrumenter': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/instrumenter': 8.6.15(storybook@8.6.15(prettier@3.7.4)) '@testing-library/dom': 10.4.0 '@testing-library/jest-dom': 6.5.0 '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) '@vitest/expect': 2.0.5 '@vitest/spy': 2.0.5 - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) - '@storybook/theming@8.6.14(storybook@8.6.14(prettier@3.6.2))': + '@storybook/theming@8.6.14(storybook@8.6.15(prettier@3.7.4))': dependencies: - storybook: 8.6.14(prettier@3.6.2) + storybook: 8.6.15(prettier@3.7.4) + + '@storybook/theming@8.6.15(storybook@8.6.15(prettier@3.7.4))': + dependencies: + storybook: 8.6.15(prettier@3.7.4) '@testing-library/dom@10.4.0': dependencies: @@ -3260,10 +4136,33 @@ snapshots: lodash: 4.17.21 redent: 3.0.0 + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.4.4 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.1(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@babel/runtime': 7.28.4 + '@testing-library/dom': 10.4.0 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.7 + '@types/react-dom': 19.2.3(@types/react@19.2.7) + '@testing-library/user-event@14.5.2(@testing-library/dom@10.4.0)': dependencies: '@testing-library/dom': 10.4.0 + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.0)': + dependencies: + '@testing-library/dom': 10.4.0 + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -3287,6 +4186,13 @@ snapshots: dependencies: '@babel/types': 7.28.5 + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + '@types/doctrine@0.0.9': {} '@types/estree@1.0.8': {} @@ -3297,15 +4203,15 @@ snapshots: '@types/node@12.20.55': {} - '@types/node@24.10.1': + '@types/node@24.10.4': dependencies: undici-types: 7.16.0 - '@types/react-dom@19.2.3(@types/react@19.2.6)': + '@types/react-dom@19.2.3(@types/react@19.2.7)': dependencies: - '@types/react': 19.2.6 + '@types/react': 19.2.7 - '@types/react@19.2.6': + '@types/react@19.2.7': dependencies: csstype: 3.2.3 @@ -3313,97 +4219,95 @@ snapshots: '@types/uuid@9.0.8': {} - '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.47.0 - eslint: 9.39.1 - graphemer: 1.4.0 + '@typescript-eslint/parser': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.52.0 + '@typescript-eslint/type-utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.52.0 + eslint: 9.39.2 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.9.3) + ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/scope-manager': 8.52.0 + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.52.0 debug: 4.4.3 - eslint: 9.39.1 + eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.47.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.52.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) - '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3) + '@typescript-eslint/types': 8.52.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.47.0': + '@typescript-eslint/scope-manager@8.52.0': dependencies: - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/visitor-keys': 8.52.0 - '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.52.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.52.0(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.1 - ts-api-utils: 2.1.0(typescript@5.9.3) + eslint: 9.39.2 + ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.47.0': {} + '@typescript-eslint/types@8.52.0': {} - '@typescript-eslint/typescript-estree@8.47.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.52.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.47.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/visitor-keys': 8.47.0 + '@typescript-eslint/project-service': 8.52.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.52.0(typescript@5.9.3) + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/visitor-keys': 8.52.0 debug: 4.4.3 - fast-glob: 3.3.3 - is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.3 - ts-api-utils: 2.1.0(typescript@5.9.3) + tinyglobby: 0.2.15 + ts-api-utils: 2.4.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.52.0(eslint@9.39.2)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@typescript-eslint/scope-manager': 8.47.0 - '@typescript-eslint/types': 8.47.0 - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - eslint: 9.39.1 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) + '@typescript-eslint/scope-manager': 8.52.0 + '@typescript-eslint/types': 8.52.0 + '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3) + eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.47.0': + '@typescript-eslint/visitor-keys@8.52.0': dependencies: - '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/types': 8.52.0 eslint-visitor-keys: 4.2.1 '@vanilla-extract/babel-plugin-debug-ids@1.2.2': @@ -3412,12 +4316,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@vanilla-extract/compiler@0.3.1(@types/node@24.10.1)': + '@vanilla-extract/compiler@0.3.4(@types/node@24.10.4)': dependencies: - '@vanilla-extract/css': 1.17.4 - '@vanilla-extract/integration': 8.0.4 - vite: 5.4.21(@types/node@24.10.1) - vite-node: 3.2.4(@types/node@24.10.1) + '@vanilla-extract/css': 1.18.0 + '@vanilla-extract/integration': 8.0.7 + vite: 5.4.21(@types/node@24.10.4) + vite-node: 3.2.4(@types/node@24.10.4) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -3430,14 +4334,14 @@ snapshots: - supports-color - terser - '@vanilla-extract/css@1.17.4': + '@vanilla-extract/css@1.18.0': dependencies: '@emotion/hash': 0.9.2 '@vanilla-extract/private': 1.0.9 css-what: 6.2.2 cssesc: 3.0.0 csstype: 3.2.3 - dedent: 1.7.0 + dedent: 1.7.1 deep-object-diff: 1.1.9 deepmerge: 4.3.1 lru-cache: 10.4.3 @@ -3447,14 +4351,14 @@ snapshots: transitivePeerDependencies: - babel-plugin-macros - '@vanilla-extract/integration@8.0.4': + '@vanilla-extract/integration@8.0.7': dependencies: '@babel/core': 7.28.5 '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.5) '@vanilla-extract/babel-plugin-debug-ids': 1.2.2 - '@vanilla-extract/css': 1.17.4 - dedent: 1.7.0 - esbuild: 0.25.12 + '@vanilla-extract/css': 1.18.0 + dedent: 1.7.1 + esbuild: 0.27.2 eval: 0.1.8 find-up: 5.0.0 javascript-stringify: 2.1.0 @@ -3465,15 +4369,15 @@ snapshots: '@vanilla-extract/private@1.0.9': {} - '@vanilla-extract/recipes@0.5.7(@vanilla-extract/css@1.17.4)': + '@vanilla-extract/recipes@0.5.7(@vanilla-extract/css@1.18.0)': dependencies: - '@vanilla-extract/css': 1.17.4 + '@vanilla-extract/css': 1.18.0 - '@vanilla-extract/vite-plugin@5.1.1(@types/node@24.10.1)(vite@5.4.21(@types/node@24.10.1))': + '@vanilla-extract/vite-plugin@5.1.4(@types/node@24.10.4)(vite@5.4.21(@types/node@24.10.4))': dependencies: - '@vanilla-extract/compiler': 0.3.1(@types/node@24.10.1) - '@vanilla-extract/integration': 8.0.4 - vite: 5.4.21(@types/node@24.10.1) + '@vanilla-extract/compiler': 0.3.4(@types/node@24.10.4) + '@vanilla-extract/integration': 8.0.7 + vite: 5.4.21(@types/node@24.10.4) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -3486,15 +4390,15 @@ snapshots: - supports-color - terser - '@vitejs/plugin-react@5.1.1(vite@5.4.21(@types/node@24.10.1))': + '@vitejs/plugin-react@5.1.2(vite@5.4.21(@types/node@24.10.4))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5) - '@rolldown/pluginutils': 1.0.0-beta.47 + '@rolldown/pluginutils': 1.0.0-beta.53 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 5.4.21(@types/node@24.10.1) + vite: 5.4.21(@types/node@24.10.4) transitivePeerDependencies: - supports-color @@ -3505,6 +4409,23 @@ snapshots: chai: 5.3.3 tinyrainbow: 1.2.0 + '@vitest/expect@4.0.16': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + chai: 6.2.2 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.16(vite@7.3.1(@types/node@24.10.4))': + dependencies: + '@vitest/spy': 4.0.16 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.1(@types/node@24.10.4) + '@vitest/pretty-format@2.0.5': dependencies: tinyrainbow: 1.2.0 @@ -3513,10 +4434,38 @@ snapshots: dependencies: tinyrainbow: 1.2.0 + '@vitest/pretty-format@4.0.16': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.16': + dependencies: + '@vitest/utils': 4.0.16 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + magic-string: 0.30.21 + pathe: 2.0.3 + '@vitest/spy@2.0.5': dependencies: tinyspy: 3.0.2 + '@vitest/spy@4.0.16': {} + + '@vitest/ui@4.0.16(vitest@4.0.16)': + dependencies: + '@vitest/utils': 4.0.16 + fflate: 0.8.2 + flatted: 3.3.3 + pathe: 2.0.3 + sirv: 3.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vitest: 4.0.16(@types/node@24.10.4)(@vitest/ui@4.0.16)(jsdom@27.4.0) + '@vitest/utils@2.0.5': dependencies: '@vitest/pretty-format': 2.0.5 @@ -3530,12 +4479,19 @@ snapshots: loupe: 3.2.1 tinyrainbow: 1.2.0 + '@vitest/utils@4.0.16': + dependencies: + '@vitest/pretty-format': 4.0.16 + tinyrainbow: 3.0.3 + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 acorn@8.15.0: {} + agent-base@7.1.4: {} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -3581,11 +4537,11 @@ snapshots: dependencies: possible-typed-array-names: 1.1.0 - axe-core@4.11.0: {} + axe-core@4.11.1: {} balanced-match@1.0.2: {} - baseline-browser-mapping@2.8.29: {} + baseline-browser-mapping@2.9.13: {} better-opn@3.0.2: dependencies: @@ -3595,6 +4551,10 @@ snapshots: dependencies: is-windows: 1.0.2 + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -3610,13 +4570,13 @@ snapshots: browser-assert@1.2.1: {} - browserslist@4.28.0: + browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.8.29 - caniuse-lite: 1.0.30001756 - electron-to-chromium: 1.5.256 + baseline-browser-mapping: 2.9.13 + caniuse-lite: 1.0.30001763 + electron-to-chromium: 1.5.267 node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.28.0) + update-browserslist-db: 1.2.3(browserslist@4.28.1) cac@6.7.14: {} @@ -3639,16 +4599,18 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001756: {} + caniuse-lite@1.0.30001763: {} chai@5.3.3: dependencies: assertion-error: 2.0.1 - check-error: 2.1.1 + check-error: 2.1.3 deep-eql: 5.0.2 loupe: 3.2.1 pathval: 2.0.1 + chai@6.2.2: {} + chalk@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -3661,7 +4623,7 @@ snapshots: chardet@2.1.1: {} - check-error@2.1.1: {} + check-error@2.1.3: {} ci-info@3.9.0: {} @@ -3685,19 +4647,38 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + css-what@6.2.2: {} css.escape@1.5.1: {} cssesc@3.0.0: {} + cssstyle@5.3.7: + dependencies: + '@asamuzakjp/css-color': 4.1.1 + '@csstools/css-syntax-patches-for-csstree': 1.0.23 + css-tree: 3.1.0 + lru-cache: 11.2.4 + csstype@3.2.3: {} + data-urls@6.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + debug@4.4.3: dependencies: ms: 2.1.3 - dedent@1.7.0: {} + decimal.js@10.6.0: {} + + dedent@1.7.1: {} deep-eql@5.0.2: {} @@ -3739,7 +4720,7 @@ snapshots: eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.256: {} + electron-to-chromium@1.5.267: {} emoji-regex@8.0.0: {} @@ -3750,6 +4731,8 @@ snapshots: ansi-colors: 4.1.3 strip-ansi: 6.0.1 + entities@6.0.1: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -3760,7 +4743,7 @@ snapshots: dependencies: es-errors: 1.3.0 - es-toolkit@1.42.0: {} + es-toolkit@1.43.0: {} esbuild-register@3.6.0(esbuild@0.25.12): dependencies: @@ -3824,23 +4807,52 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + escalade@3.2.0: {} escape-string-regexp@4.0.0: {} - eslint-plugin-react-hooks@5.2.0(eslint@9.39.1): + eslint-plugin-react-hooks@5.2.0(eslint@9.39.2): dependencies: - eslint: 9.39.1 + eslint: 9.39.2 - eslint-plugin-react-refresh@0.4.24(eslint@9.39.1): + eslint-plugin-react-refresh@0.4.26(eslint@9.39.2): dependencies: - eslint: 9.39.1 + eslint: 9.39.2 - eslint-plugin-storybook@10.0.8(eslint@9.39.1)(storybook@8.6.14(prettier@3.6.2))(typescript@5.9.3): + eslint-plugin-storybook@10.1.11(eslint@9.39.2)(storybook@8.6.15(prettier@3.7.4))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 - storybook: 8.6.14(prettier@3.6.2) + '@typescript-eslint/utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + eslint: 9.39.2 + storybook: 8.6.15(prettier@3.7.4) transitivePeerDependencies: - supports-color - typescript @@ -3854,15 +4866,15 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1: + eslint@9.39.2: dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.39.1 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 @@ -3876,7 +4888,7 @@ snapshots: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 - esquery: 1.6.0 + esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -3901,7 +4913,7 @@ snapshots: esprima@4.0.1: {} - esquery@1.6.0: + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -3921,9 +4933,11 @@ snapshots: eval@0.1.8: dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 require-like: 0.1.2 + expect-type@1.3.0: {} + extendable-error@0.1.7: {} fast-deep-equal@3.1.3: {} @@ -3940,10 +4954,16 @@ snapshots: fast-levenshtein@2.0.6: {} - fastq@1.19.1: + fastq@1.20.1: dependencies: reusify: 1.1.0 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fflate@0.8.2: {} + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -4051,8 +5071,6 @@ snapshots: graceful-fs@4.2.11: {} - graphemer@1.4.0: {} - has-flag@4.0.0: {} has-property-descriptors@1.0.2: @@ -4069,9 +5087,29 @@ snapshots: dependencies: function-bind: 1.1.2 - human-id@4.1.2: {} + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.8.0 + transitivePeerDependencies: + - '@exodus/crypto' + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + human-id@4.1.3: {} - iconv-lite@0.7.0: + iconv-lite@0.7.1: dependencies: safer-buffer: 2.1.2 @@ -4121,6 +5159,8 @@ snapshots: is-number@7.0.0: {} + is-potential-custom-element-name@1.0.1: {} + is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -4165,6 +5205,34 @@ snapshots: jsdoc-type-pratt-parser@4.8.0: {} + jsdom@27.4.0: + dependencies: + '@acemir/cssom': 0.9.30 + '@asamuzakjp/dom-selector': 6.7.6 + '@exodus/bytes': 1.8.0 + cssstyle: 5.3.7 + data-urls: 6.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 8.0.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + ws: 8.19.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@exodus/crypto' + - bufferutil + - supports-color + - utf-8-validate + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -4206,6 +5274,8 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@11.2.4: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -4224,6 +5294,8 @@ snapshots: math-intrinsics@1.1.0: {} + mdn-data@2.12.2: {} + media-query-parser@2.0.2: dependencies: '@babel/runtime': 7.28.4 @@ -4258,12 +5330,14 @@ snapshots: acorn: 8.15.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.1 + ufo: 1.6.2 modern-ahocorasick@1.1.0: {} mri@1.2.0: {} + mrmime@2.0.1: {} + ms@2.1.3: {} nanoid@3.3.11: {} @@ -4272,6 +5346,8 @@ snapshots: node-releases@2.0.27: {} + obug@2.1.1: {} + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -4323,6 +5399,10 @@ snapshots: dependencies: callsites: 3.1.0 + parse5@8.0.0: + dependencies: + entities: 6.0.1 + path-exists@4.0.0: {} path-key@3.1.1: {} @@ -4370,7 +5450,7 @@ snapshots: prettier@2.8.8: {} - prettier@3.6.2: {} + prettier@3.7.4: {} pretty-format@27.5.1: dependencies: @@ -4405,16 +5485,16 @@ snapshots: transitivePeerDependencies: - supports-color - react-dom@19.2.0(react@19.2.0): + react-dom@19.2.3(react@19.2.3): dependencies: - react: 19.2.0 + react: 19.2.3 scheduler: 0.27.0 react-is@17.0.2: {} react-refresh@0.18.0: {} - react@19.2.0: {} + react@19.2.3: {} read-yaml-file@1.1.0: dependencies: @@ -4436,8 +5516,12 @@ snapshots: indent-string: 4.0.0 strip-indent: 3.0.0 + require-from-string@2.0.2: {} + require-like@0.1.2: {} + reselect@5.1.1: {} + resolve-from@4.0.0: {} resolve-from@5.0.0: {} @@ -4450,32 +5534,35 @@ snapshots: reusify@1.1.0: {} - rollup@4.53.3: + rollup@4.55.1: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.3 - '@rollup/rollup-android-arm64': 4.53.3 - '@rollup/rollup-darwin-arm64': 4.53.3 - '@rollup/rollup-darwin-x64': 4.53.3 - '@rollup/rollup-freebsd-arm64': 4.53.3 - '@rollup/rollup-freebsd-x64': 4.53.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 - '@rollup/rollup-linux-arm-musleabihf': 4.53.3 - '@rollup/rollup-linux-arm64-gnu': 4.53.3 - '@rollup/rollup-linux-arm64-musl': 4.53.3 - '@rollup/rollup-linux-loong64-gnu': 4.53.3 - '@rollup/rollup-linux-ppc64-gnu': 4.53.3 - '@rollup/rollup-linux-riscv64-gnu': 4.53.3 - '@rollup/rollup-linux-riscv64-musl': 4.53.3 - '@rollup/rollup-linux-s390x-gnu': 4.53.3 - '@rollup/rollup-linux-x64-gnu': 4.53.3 - '@rollup/rollup-linux-x64-musl': 4.53.3 - '@rollup/rollup-openharmony-arm64': 4.53.3 - '@rollup/rollup-win32-arm64-msvc': 4.53.3 - '@rollup/rollup-win32-ia32-msvc': 4.53.3 - '@rollup/rollup-win32-x64-gnu': 4.53.3 - '@rollup/rollup-win32-x64-msvc': 4.53.3 + '@rollup/rollup-android-arm-eabi': 4.55.1 + '@rollup/rollup-android-arm64': 4.55.1 + '@rollup/rollup-darwin-arm64': 4.55.1 + '@rollup/rollup-darwin-x64': 4.55.1 + '@rollup/rollup-freebsd-arm64': 4.55.1 + '@rollup/rollup-freebsd-x64': 4.55.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.55.1 + '@rollup/rollup-linux-arm-musleabihf': 4.55.1 + '@rollup/rollup-linux-arm64-gnu': 4.55.1 + '@rollup/rollup-linux-arm64-musl': 4.55.1 + '@rollup/rollup-linux-loong64-gnu': 4.55.1 + '@rollup/rollup-linux-loong64-musl': 4.55.1 + '@rollup/rollup-linux-ppc64-gnu': 4.55.1 + '@rollup/rollup-linux-ppc64-musl': 4.55.1 + '@rollup/rollup-linux-riscv64-gnu': 4.55.1 + '@rollup/rollup-linux-riscv64-musl': 4.55.1 + '@rollup/rollup-linux-s390x-gnu': 4.55.1 + '@rollup/rollup-linux-x64-gnu': 4.55.1 + '@rollup/rollup-linux-x64-musl': 4.55.1 + '@rollup/rollup-openbsd-x64': 4.55.1 + '@rollup/rollup-openharmony-arm64': 4.55.1 + '@rollup/rollup-win32-arm64-msvc': 4.55.1 + '@rollup/rollup-win32-ia32-msvc': 4.55.1 + '@rollup/rollup-win32-x64-gnu': 4.55.1 + '@rollup/rollup-win32-x64-msvc': 4.55.1 fsevents: 2.3.3 run-parallel@1.2.0: @@ -4490,6 +5577,10 @@ snapshots: safer-buffer@2.1.2: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.27.0: {} semver@6.3.1: {} @@ -4511,8 +5602,16 @@ snapshots: shebang-regex@3.0.0: {} + siginfo@2.0.0: {} + signal-exit@4.1.0: {} + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + slash@3.0.0: {} source-map-js@1.2.1: {} @@ -4526,14 +5625,18 @@ snapshots: sprintf-js@1.0.3: {} - storybook-dark-mode@4.0.2(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(storybook@8.6.14(prettier@3.6.2)): + stackback@0.0.2: {} + + std-env@3.10.0: {} + + storybook-dark-mode@4.0.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@8.6.15(prettier@3.7.4)): dependencies: - '@storybook/components': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/core-events': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/components': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/core-events': 8.6.14(storybook@8.6.15(prettier@3.7.4)) '@storybook/global': 5.0.0 - '@storybook/icons': 1.6.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@storybook/manager-api': 8.6.14(storybook@8.6.14(prettier@3.6.2)) - '@storybook/theming': 8.6.14(storybook@8.6.14(prettier@3.6.2)) + '@storybook/icons': 1.6.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@storybook/manager-api': 8.6.14(storybook@8.6.15(prettier@3.7.4)) + '@storybook/theming': 8.6.14(storybook@8.6.15(prettier@3.7.4)) fast-deep-equal: 3.1.3 memoizerific: 1.11.3 transitivePeerDependencies: @@ -4541,11 +5644,11 @@ snapshots: - react-dom - storybook - storybook@8.6.14(prettier@3.6.2): + storybook@8.6.15(prettier@3.7.4): dependencies: - '@storybook/core': 8.6.14(prettier@3.6.2)(storybook@8.6.14(prettier@3.6.2)) + '@storybook/core': 8.6.15(prettier@3.7.4)(storybook@8.6.15(prettier@3.7.4)) optionalDependencies: - prettier: 3.6.2 + prettier: 3.7.4 transitivePeerDependencies: - bufferutil - supports-color @@ -4587,19 +5690,50 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + symbol-tree@3.2.4: {} + + tabbable@6.4.0: {} + term-size@2.2.1: {} tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} + + tinyexec@1.0.2: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tinyrainbow@1.2.0: {} + tinyrainbow@3.0.3: {} + tinyspy@3.0.2: {} + tldts-core@7.0.19: {} + + tldts@7.0.19: + dependencies: + tldts-core: 7.0.19 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - ts-api-utils@2.1.0(typescript@5.9.3): + totalist@3.0.1: {} + + tough-cookie@6.0.0: + dependencies: + tldts: 7.0.19 + + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -4617,20 +5751,20 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.47.0(eslint@9.39.1)(typescript@5.9.3): + typescript-eslint@8.52.0(eslint@9.39.2)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) - eslint: 9.39.1 + '@typescript-eslint/eslint-plugin': 8.52.0(@typescript-eslint/parser@8.52.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/parser': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.52.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.52.0(eslint@9.39.2)(typescript@5.9.3) + eslint: 9.39.2 typescript: 5.9.3 transitivePeerDependencies: - supports-color typescript@5.9.3: {} - ufo@1.6.1: {} + ufo@1.6.2: {} undici-types@7.16.0: {} @@ -4641,9 +5775,9 @@ snapshots: acorn: 8.15.0 webpack-virtual-modules: 0.6.2 - update-browserslist-db@1.1.4(browserslist@4.28.0): + update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 escalade: 3.2.0 picocolors: 1.1.1 @@ -4651,6 +5785,10 @@ snapshots: dependencies: punycode: 2.3.1 + use-sync-external-store@1.6.0(react@19.2.3): + dependencies: + react: 19.2.3 + util@0.12.5: dependencies: inherits: 2.0.4 @@ -4661,13 +5799,13 @@ snapshots: uuid@9.0.1: {} - vite-node@3.2.4(@types/node@24.10.1): + vite-node@3.2.4(@types/node@24.10.4): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 5.4.21(@types/node@24.10.1) + vite: 5.4.21(@types/node@24.10.4) transitivePeerDependencies: - '@types/node' - less @@ -4679,17 +5817,81 @@ snapshots: - supports-color - terser - vite@5.4.21(@types/node@24.10.1): + vite@5.4.21(@types/node@24.10.4): dependencies: esbuild: 0.21.5 postcss: 8.5.6 - rollup: 4.53.3 + rollup: 4.55.1 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 fsevents: 2.3.3 + vite@7.3.1(@types/node@24.10.4): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.55.1 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.4 + fsevents: 2.3.3 + + vitest@4.0.16(@types/node@24.10.4)(@vitest/ui@4.0.16)(jsdom@27.4.0): + dependencies: + '@vitest/expect': 4.0.16 + '@vitest/mocker': 4.0.16(vite@7.3.1(@types/node@24.10.4)) + '@vitest/pretty-format': 4.0.16 + '@vitest/runner': 4.0.16 + '@vitest/snapshot': 4.0.16 + '@vitest/spy': 4.0.16 + '@vitest/utils': 4.0.16 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.3.1(@types/node@24.10.4) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.10.4 + '@vitest/ui': 4.0.16(vitest@4.0.16) + jsdom: 27.4.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + webidl-conversions@8.0.1: {} + webpack-virtual-modules@0.6.2: {} + whatwg-mimetype@4.0.0: {} + + whatwg-url@15.1.0: + dependencies: + tr46: 6.0.0 + webidl-conversions: 8.0.1 + which-typed-array@1.1.19: dependencies: available-typed-arrays: 1.0.7 @@ -4704,6 +5906,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} wrap-ansi@7.0.0: @@ -4718,7 +5925,11 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.2 - ws@8.18.3: {} + ws@8.19.0: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} yallist@3.1.1: {} diff --git a/scripts/auto-changeset.sh b/scripts/auto-changeset.sh new file mode 100755 index 0000000..8778849 --- /dev/null +++ b/scripts/auto-changeset.sh @@ -0,0 +1,231 @@ +#!/bin/bash + +# Automatic changeset generation from commit history +# Usage: pnpm changeset:auto + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +PURPLE='\033[0;35m' +NC='\033[0m' + +echo -e "${PURPLE}🤖 Auto-generating changeset from commits...${NC}\n" + +# 1. Check if on main branch +CURRENT_BRANCH=$(git branch --show-current) +if [[ "$CURRENT_BRANCH" == "main" ]]; then + echo -e "${RED}❌ Cannot create changeset on main branch.${NC}" + exit 1 +fi + +echo -e "${GREEN}✓${NC} Current branch: ${BLUE}$CURRENT_BRANCH${NC}" + +# 2. Check for existing changesets +EXISTING_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" 2>/dev/null || echo "") +if [[ -n "$EXISTING_CHANGESETS" ]]; then + echo -e "${YELLOW}⚠️ Changeset already exists:${NC}" + echo "$EXISTING_CHANGESETS" | while read -r file; do + echo " - $(basename "$file")" + done + echo "" + echo -e "${YELLOW}Do you want to create another one? (y/n)${NC}" + read -r CONTINUE + if [[ "$CONTINUE" != "y" ]]; then + echo -e "${BLUE}ℹ️ Changeset creation cancelled${NC}" + exit 0 + fi +fi + +# 3. Get commits since main +COMMITS=$(git log main..HEAD --pretty=format:"%s" --no-merges) +COMMIT_COUNT=$(echo "$COMMITS" | grep -c . || echo "0") + +if [[ "$COMMIT_COUNT" -eq 0 ]]; then + echo -e "${RED}❌ No commits found since main branch.${NC}" + echo "Make some commits first!" + exit 1 +fi + +echo -e "${GREEN}✓${NC} Found ${BLUE}$COMMIT_COUNT${NC} commit(s)" +echo "" +echo -e "${BLUE}Commits:${NC}" +echo "$COMMITS" | nl -w2 -s'. ' +echo "" + +# 4. Analyze commit types to determine version bump +HAS_BREAKING=false +HAS_FEAT=false +HAS_FIX=false + +while IFS= read -r commit; do + # Check for breaking changes (BSD grep compatible) + if echo "$commit" | grep -q "!" || echo "$commit" | grep -q "BREAKING CHANGE:"; then + HAS_BREAKING=true + fi + + # Check for features + if echo "$commit" | grep -q "^feat"; then + HAS_FEAT=true + fi + + # Check for fixes and other changes + if echo "$commit" | grep -qE "^(fix|docs|style|refactor|perf|test|chore)"; then + HAS_FIX=true + fi +done <<< "$COMMITS" + +# Determine version type +if [[ "$HAS_BREAKING" == true ]]; then + VERSION_TYPE="major" + VERSION_EMOJI="💥" + VERSION_DESC="Breaking Change" +elif [[ "$HAS_FEAT" == true ]]; then + VERSION_TYPE="minor" + VERSION_EMOJI="✨" + VERSION_DESC="New Feature" +else + VERSION_TYPE="patch" + VERSION_EMOJI="🐛" + VERSION_DESC="Bug Fix / Improvement" +fi + +echo -e "${GREEN}✓${NC} Detected version type: ${PURPLE}$VERSION_TYPE${NC} ($VERSION_EMOJI $VERSION_DESC)" + +# 5. Generate changeset summary +echo -e "\n${BLUE}📝 Generating changeset summary...${NC}" + +# Extract meaningful parts from commits +SUMMARY="" +DETAILS="" + +# Group commits by type (BSD grep compatible) +FEAT_COMMITS=$(echo "$COMMITS" | grep "^feat" || echo "") +FIX_COMMITS=$(echo "$COMMITS" | grep "^fix" || echo "") +OTHER_COMMITS=$(echo "$COMMITS" | grep -vE "^(feat|fix)" || echo "") + +# Create summary from first significant commit +FIRST_COMMIT=$(echo "$COMMITS" | head -1) +SUMMARY=$(echo "$FIRST_COMMIT" | sed -E 's/^[a-z]+(\(.+\))?!?: //' | sed 's/^./\u&/') + +# Create detailed description (BSD sed compatible) +if [[ -n "$FEAT_COMMITS" ]]; then + DETAILS="${DETAILS}**New Features:**\n" + while IFS= read -r commit; do + DESC=$(echo "$commit" | sed 's/^feat[^:]*: //') + DETAILS="${DETAILS}- ${DESC}\n" + done <<< "$FEAT_COMMITS" + DETAILS="${DETAILS}\n" +fi + +if [[ -n "$FIX_COMMITS" ]]; then + DETAILS="${DETAILS}**Bug Fixes:**\n" + while IFS= read -r commit; do + DESC=$(echo "$commit" | sed 's/^fix[^:]*: //') + DETAILS="${DETAILS}- ${DESC}\n" + done <<< "$FIX_COMMITS" + DETAILS="${DETAILS}\n" +fi + +if [[ -n "$OTHER_COMMITS" ]]; then + DETAILS="${DETAILS}**Other Changes:**\n" + while IFS= read -r commit; do + DESC=$(echo "$commit" | sed 's/^[a-z]*[^:]*: //') + DETAILS="${DETAILS}- ${DESC}\n" + done <<< "$OTHER_COMMITS" +fi + +# 6. Preview changeset +echo "" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${BLUE}📋 Changeset Preview${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${GREEN}Version Type:${NC} ${PURPLE}$VERSION_TYPE${NC} $VERSION_EMOJI" +echo -e "${GREEN}Summary:${NC} $SUMMARY" +echo "" +echo -e "${GREEN}Details:${NC}" +echo -e "$DETAILS" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n" + +# 7. Allow customization +echo -e "${YELLOW}Would you like to customize? (y/n)${NC}" +read -r CUSTOMIZE + +if [[ "$CUSTOMIZE" == "y" ]]; then + echo "" + echo -e "${BLUE}Select version type:${NC}" + echo "1) patch (bug fixes, small improvements)" + echo "2) minor (new features, backwards compatible)" + echo "3) major (breaking changes)" + echo "" + echo -e "${YELLOW}Enter number [current: $VERSION_TYPE]:${NC}" + read -r VERSION_CHOICE + + case $VERSION_CHOICE in + 1) VERSION_TYPE="patch" ;; + 2) VERSION_TYPE="minor" ;; + 3) VERSION_TYPE="major" ;; + *) echo -e "${BLUE}ℹ️ Keeping: $VERSION_TYPE${NC}" ;; + esac + + echo "" + echo -e "${BLUE}Enter summary [press Enter to keep current]:${NC}" + read -r CUSTOM_SUMMARY + if [[ -n "$CUSTOM_SUMMARY" ]]; then + SUMMARY="$CUSTOM_SUMMARY" + fi +fi + +# 8. Create changeset file +echo "" +echo -e "${BLUE}📝 Creating changeset...${NC}" + +# Generate random changeset filename (similar to changeset CLI) +ADJECTIVES=("happy" "sad" "quick" "slow" "bright" "dark" "hot" "cold" "big" "small") +NOUNS=("dog" "cat" "bird" "fish" "tree" "flower" "mountain" "river" "cloud" "star") +VERBS=("run" "jump" "swim" "fly" "dance" "sing" "sleep" "wake" "laugh" "smile") + +RANDOM_ADJ=${ADJECTIVES[$RANDOM % ${#ADJECTIVES[@]}]} +RANDOM_NOUN=${NOUNS[$RANDOM % ${#NOUNS[@]}]} +RANDOM_VERB=${VERBS[$RANDOM % ${#VERBS[@]}]} +CHANGESET_FILENAME="$RANDOM_ADJ-$RANDOM_NOUN-$RANDOM_VERB.md" + +# Create changeset content +CHANGESET_CONTENT="--- +\"pine-ui-kit\": $VERSION_TYPE +--- + +$SUMMARY + +$(echo -e "$DETAILS" | sed 's/\\n/\n/g') +" + +# Write changeset file +echo "$CHANGESET_CONTENT" > ".changeset/$CHANGESET_FILENAME" + +echo -e "${GREEN}✓${NC} Changeset created: ${BLUE}.changeset/$CHANGESET_FILENAME${NC}" + +# 9. Show the file +echo "" +echo -e "${BLUE}📄 Generated changeset:${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +cat ".changeset/$CHANGESET_FILENAME" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n" + +# 10. Offer to commit +echo -e "${YELLOW}Commit this changeset? (y/n)${NC}" +read -r COMMIT_CHANGESET + +if [[ "$COMMIT_CHANGESET" == "y" ]]; then + git add ".changeset/$CHANGESET_FILENAME" + git commit -m "docs: add changeset for $VERSION_TYPE release" + echo -e "${GREEN}✓${NC} Changeset committed" +fi + +echo "" +echo -e "${GREEN}✅ Done!${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + diff --git a/scripts/create-pr.sh b/scripts/create-pr.sh new file mode 100755 index 0000000..7a4188a --- /dev/null +++ b/scripts/create-pr.sh @@ -0,0 +1,193 @@ +#!/bin/bash + +# Automatic PR creation script +# Usage: pnpm pr + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}🚀 Creating Pull Request...${NC}\n" + +# 1. Check Git status +if [[ -n $(git status -s) ]]; then + echo -e "${YELLOW}⚠️ You have uncommitted changes.${NC}" + echo "Please commit your changes first." + exit 1 +fi + +# 2. Check current branch +CURRENT_BRANCH=$(git branch --show-current) +if [[ "$CURRENT_BRANCH" == "main" ]]; then + echo -e "${RED}❌ Cannot create PR from main branch.${NC}" + exit 1 +fi + +echo -e "${GREEN}✓${NC} Current branch: ${BLUE}$CURRENT_BRANCH${NC}" + +# 3. Check for changeset +CHANGESET_FILES=$(find .changeset -name "*.md" ! -name "README.md" 2>/dev/null || echo "") +CHANGESET_COUNT=$(echo "$CHANGESET_FILES" | grep -c . || echo "0") + +if [[ "$CHANGESET_COUNT" -eq 0 ]]; then + echo -e "${YELLOW}⚠️ No changeset found. Would you like to create one? (y/n)${NC}" + read -r CREATE_CHANGESET + + if [[ "$CREATE_CHANGESET" == "y" ]]; then + pnpm changeset + echo -e "${GREEN}✓${NC} Changeset created" + + # Commit changeset + git add .changeset/ + git commit -m "docs: add changeset" + echo -e "${GREEN}✓${NC} Changeset committed" + fi +fi + +# 4. Analyze changes +echo -e "\n${BLUE}📊 Analyzing changes...${NC}" +CHANGED_FILES=$(git diff --name-only main...HEAD) +FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l | tr -d ' ') +COMMIT_MESSAGES=$(git log main..HEAD --pretty=format:"%s" | head -5) + +# 5. Extract changeset information +if [[ -n "$CHANGESET_FILES" ]]; then + CHANGESET_CONTENT=$(cat $(echo "$CHANGESET_FILES" | head -1)) + # BSD grep compatible (macOS) + CHANGESET_TYPE=$(echo "$CHANGESET_CONTENT" | grep -o '"[^"]*"' | head -1 | tr -d '"' || echo "pine-ui-kit") + CHANGESET_VERSION=$(echo "$CHANGESET_CONTENT" | grep -o ': [a-z]*' | head -1 | sed 's/: //' || echo "patch") + CHANGESET_DESC=$(echo "$CHANGESET_CONTENT" | tail -n +4) +else + CHANGESET_TYPE="pine-ui-kit" + CHANGESET_VERSION="patch" + CHANGESET_DESC="" +fi + +# 6. Generate PR title +echo -e "\n${BLUE}📝 Enter PR title (press Enter for auto-generated):${NC}" +read -r PR_TITLE_INPUT + +if [[ -z "$PR_TITLE_INPUT" ]]; then + # Use first commit message as title + PR_TITLE=$(echo "$COMMIT_MESSAGES" | head -1) + + # Use changeset description if available + if [[ -n "$CHANGESET_DESC" ]]; then + PR_TITLE=$(echo "$CHANGESET_DESC" | head -1) + fi +else + PR_TITLE="$PR_TITLE_INPUT" +fi + +echo -e "${GREEN}✓${NC} PR title: ${BLUE}$PR_TITLE${NC}" + +# 7. Generate PR body +PR_BODY="## 📝 Changes + +$CHANGESET_DESC + +## 🔄 Changeset Info + +- **Package**: \`$CHANGESET_TYPE\` +- **Version**: \`$CHANGESET_VERSION\` + +## 📊 Commit History + +\`\`\` +$COMMIT_MESSAGES +\`\`\` + +## 📁 Changed Files ($FILE_COUNT) + +\`\`\` +$(echo "$CHANGED_FILES" | head -20) +$(if [[ $(echo "$CHANGED_FILES" | wc -l) -gt 20 ]]; then echo "... and more"; fi) +\`\`\` + +## ✅ Checklist + +- [x] Changeset added +- [x] Code review ready +- [ ] Tests passing +- [ ] Documentation updated (if needed) + +--- + +
+🤖 Auto-generated PR + +This PR was automatically generated using \`pnpm pr\` command. +
+" + +# 8. PR Preview +echo -e "\n${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${BLUE}📋 PR Preview${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +echo -e "${GREEN}Title:${NC} $PR_TITLE" +echo "" +echo -e "${GREEN}Body:${NC}" +echo "$PR_BODY" | head -20 +echo -e "${YELLOW}...${NC}" +echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n" + +# 9. Confirm +echo -e "${YELLOW}Create this PR? (y/n)${NC}" +read -r CONFIRM + +if [[ "$CONFIRM" != "y" ]]; then + echo -e "${RED}❌ PR creation cancelled${NC}" + exit 0 +fi + +# 10. Push +echo -e "\n${BLUE}📤 Pushing branch...${NC}" +git push -u origin "$CURRENT_BRANCH" +echo -e "${GREEN}✓${NC} Push complete" + +# 11. Create PR +echo -e "\n${BLUE}🎉 Creating PR...${NC}" + +# Use Homebrew's gh explicitly (avoid npm package conflict) +GH_CMD="/opt/homebrew/bin/gh" + +# Fallback to system gh if Homebrew version not found +if [[ ! -f "$GH_CMD" ]]; then + if command -v gh &> /dev/null; then + GH_CMD="gh" + else + echo -e "${RED}❌ GitHub CLI (gh) is not installed.${NC}" + echo "Install: brew install gh" + echo "Then authenticate: gh auth login" + echo "" + echo "Or create PR manually:" + echo "https://github.com/$(git remote get-url origin | sed 's/.*github.com[:/]\(.*\)\.git/\1/')/compare/main...$CURRENT_BRANCH" + exit 1 + fi +fi + +# Check authentication +if ! "$GH_CMD" auth status &> /dev/null; then + echo -e "${RED}❌ Not authenticated with GitHub.${NC}" + echo "Please run: gh auth login" + exit 1 +fi + +# Create PR +if "$GH_CMD" pr create \ + --title "$PR_TITLE" \ + --body "$PR_BODY" \ + --base main \ + --head "$CURRENT_BRANCH"; then + echo -e "\n${GREEN}✅ PR created successfully!${NC}" + echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +else + echo -e "\n${RED}❌ Failed to create PR.${NC}" + echo "Please check the error message above." + exit 1 +fi diff --git a/packages/components/Badge/Badge.css.ts b/src/components/Badge/Badge.css.ts similarity index 95% rename from packages/components/Badge/Badge.css.ts rename to src/components/Badge/Badge.css.ts index 8af1e8e..5e5d3f8 100644 --- a/packages/components/Badge/Badge.css.ts +++ b/src/components/Badge/Badge.css.ts @@ -49,19 +49,15 @@ export const badge = recipe({ }, variant: { - // 스타일은 compoundVariants에서 variant + intent 조합으로 정의됨 solid: {}, outline: { - // outline variant는 투명 배경이 항상 필요 backgroundColor: "transparent", }, - subtle: {}, // compoundVariants에서 정의됨 - weak: {}, // compoundVariants에서 정의됨 + subtle: {}, + weak: {}, }, intent: { - // intent만으로는 색상이 결정되지 않음 - // 실제 색상은 compoundVariants에서 variant + intent 조합으로 정의됨 primary: {}, secondary: {}, success: {}, diff --git a/src/components/Badge/Badge.spec.tsx b/src/components/Badge/Badge.spec.tsx new file mode 100644 index 0000000..cc09fdd --- /dev/null +++ b/src/components/Badge/Badge.spec.tsx @@ -0,0 +1,165 @@ +import { describe, it, expect, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { Badge } from "./Badge"; + +describe("Badge", () => { + describe("Rendering", () => { + it("renders with children", () => { + render(Test Badge); + expect(screen.getByText("Test Badge")).toBeInTheDocument(); + }); + + it("renders as span element", () => { + render(Badge); + const element = screen.getByText("Badge"); + expect(element.tagName).toBe("SPAN"); + }); + + it("renders with custom className", () => { + render(Test); + const element = screen.getByText("Test"); + expect(element).toHaveClass("custom-class"); + }); + }); + + describe("Dot Indicator", () => { + it("does not render dot by default", () => { + render(No Dot); + const badge = screen.getByText("No Dot"); + const dot = badge.querySelector("span"); + expect(dot).not.toBeInTheDocument(); + }); + + it("renders dot when showDot is true", () => { + render(With Dot); + const badge = screen.getByText("With Dot"); + const dot = badge.querySelector("span"); + expect(dot).toBeInTheDocument(); + }); + }); + + describe("HTML Attributes", () => { + it("accepts id attribute", () => { + render(Test); + const element = screen.getByText("Test"); + expect(element).toHaveAttribute("id", "custom-id"); + }); + + it("accepts data attributes", () => { + render(Test); + const element = screen.getByTestId("custom-test-id"); + expect(element).toBeInTheDocument(); + }); + + it("accepts aria attributes", () => { + render(Test); + const element = screen.getByText("Test"); + expect(element).toHaveAttribute("aria-label", "Custom label"); + }); + + it("accepts style attribute", () => { + render(Test); + const element = screen.getByText("Test"); + expect(element).toHaveStyle({ marginLeft: "10px" }); + }); + + it("accepts title attribute", () => { + render(Test); + const element = screen.getByText("Test"); + expect(element).toHaveAttribute("title", "Tooltip text"); + }); + + it("accepts onClick handler", () => { + const handleClick = vi.fn(); + render(Clickable); + const element = screen.getByText("Clickable"); + element.click(); + expect(handleClick).toHaveBeenCalledTimes(1); + }); + }); + + describe("Content Types", () => { + it("renders text content", () => { + render(Text Badge); + expect(screen.getByText("Text Badge")).toBeInTheDocument(); + }); + + it("renders number content", () => { + render(42); + expect(screen.getByText("42")).toBeInTheDocument(); + }); + + it("renders with zero", () => { + render({0}); + expect(screen.getByText("0")).toBeInTheDocument(); + }); + + it("renders nested elements", () => { + render( + + Bold Text + + ); + expect(screen.getByText("Bold")).toBeInTheDocument(); + expect(screen.getByText(/Text/)).toBeInTheDocument(); + }); + + it("renders with icon", () => { + render( + + Success + + ); + expect(screen.getByText("✓")).toBeInTheDocument(); + expect(screen.getByText(/Success/)).toBeInTheDocument(); + }); + }); + + describe("Accessibility", () => { + it("has proper role when used as status indicator", () => { + render(Active); + const element = screen.getByText("Active"); + expect(element).toHaveAttribute("role", "status"); + }); + + it("supports aria-label for screen readers", () => { + render(3); + const element = screen.getByLabelText("3 unread messages"); + expect(element).toBeInTheDocument(); + }); + + it("supports aria-describedby", () => { + render( + <> + New + This item is new + + ); + const badge = screen.getByText("New"); + expect(badge).toHaveAttribute("aria-describedby", "badge-desc"); + }); + }); + + describe("Edge Cases", () => { + it("renders with very long text", () => { + const longText = "This is a very long badge text that might overflow"; + render({longText}); + expect(screen.getByText(longText)).toBeInTheDocument(); + }); + + it("renders with single character", () => { + render(A); + expect(screen.getByText("A")).toBeInTheDocument(); + }); + + it("renders with special characters", () => { + render(★ Special ★); + expect(screen.getByText("★ Special ★")).toBeInTheDocument(); + }); + + it("renders with emoji", () => { + render(🎉 Party); + expect(screen.getByText("🎉 Party")).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/components/Badge/Badge.stories.tsx b/src/components/Badge/Badge.stories.tsx similarity index 100% rename from packages/components/Badge/Badge.stories.tsx rename to src/components/Badge/Badge.stories.tsx diff --git a/packages/components/Badge/Badge.tsx b/src/components/Badge/Badge.tsx similarity index 70% rename from packages/components/Badge/Badge.tsx rename to src/components/Badge/Badge.tsx index 2f67e8a..187531e 100644 --- a/packages/components/Badge/Badge.tsx +++ b/src/components/Badge/Badge.tsx @@ -18,6 +18,17 @@ export interface BadgeProps extends React.HTMLAttributes { children: React.ReactNode; } +/** + * Badge component for displaying labels, tags, or status indicators. + * + * @param BadgeProps + * @param variant - Visual style variant (solid, outline, subtle, weak) + * @param size - Size of the badge (small, medium, large, xlarge) + * @param intent - Color intent (primary, secondary, success, warning, danger, neutral) + * @param rounded - Border radius size (small, medium, large) + * @param showDot - Whether to show a dot indicator + * @param children - Badge content + */ export const Badge = ({ size = "medium", variant = "solid", diff --git a/packages/components/Badge/index.ts b/src/components/Badge/index.ts similarity index 100% rename from packages/components/Badge/index.ts rename to src/components/Badge/index.ts diff --git a/packages/components/Button/Button.css.ts b/src/components/Button/Button.css.ts similarity index 100% rename from packages/components/Button/Button.css.ts rename to src/components/Button/Button.css.ts diff --git a/src/components/Button/Button.spec.tsx b/src/components/Button/Button.spec.tsx new file mode 100644 index 0000000..a8f1b78 --- /dev/null +++ b/src/components/Button/Button.spec.tsx @@ -0,0 +1,115 @@ +import { describe, it, expect, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { Button } from "./Button"; + +describe("Button", () => { + describe("Rendering", () => { + it("renders children correctly", () => { + render(); + expect(screen.getByRole("button")).toHaveTextContent("Click me"); + }); + + it("applies custom className", () => { + render(); + const button = screen.getByRole("button"); + expect(button).toHaveClass("custom-class"); + }); + }); + + describe("States", () => { + it("renders disabled button", () => { + render(); + const button = screen.getByRole("button"); + expect(button).toBeDisabled(); + }); + + it("applies fullWidth class when fullWidth prop is true", () => { + render(); + const button = screen.getByRole("button"); + expect(button).toBeInTheDocument(); + }); + }); + + describe("Interactions", () => { + it("calls onClick handler when clicked", async () => { + const handleClick = vi.fn(); + const user = userEvent.setup(); + + render(); + const button = screen.getByRole("button"); + + await user.click(button); + expect(handleClick).toHaveBeenCalledTimes(1); + }); + + it("does not call onClick when disabled", async () => { + const handleClick = vi.fn(); + const user = userEvent.setup(); + + render( + + ); + const button = screen.getByRole("button"); + + await user.click(button); + expect(handleClick).not.toHaveBeenCalled(); + }); + + it("handles multiple clicks", async () => { + const handleClick = vi.fn(); + const user = userEvent.setup(); + + render(); + const button = screen.getByRole("button"); + + await user.tripleClick(button); + expect(handleClick).toHaveBeenCalledTimes(3); + }); + }); + + describe("Accessibility", () => { + it("has button role", () => { + render(); + expect(screen.getByRole("button")).toBeInTheDocument(); + }); + + it("accepts aria-label", () => { + render(); + expect(screen.getByLabelText("Custom label")).toBeInTheDocument(); + }); + + it("accepts aria-disabled", () => { + render(); + const button = screen.getByRole("button"); + expect(button).toHaveAttribute("aria-disabled", "true"); + }); + + it("can be focused with keyboard", () => { + render(); + const button = screen.getByRole("button"); + button.focus(); + expect(button).toHaveFocus(); + }); + }); + + describe("HTML Attributes", () => { + it("accepts type attribute", () => { + render(); + expect(screen.getByRole("button")).toHaveAttribute("type", "submit"); + }); + + it("accepts data attributes", () => { + render(); + expect(screen.getByTestId("custom-button")).toBeInTheDocument(); + }); + + it("forwards ref", () => { + const ref = vi.fn(); + render(); + expect(ref).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/components/Button/Button.stories.tsx b/src/components/Button/Button.stories.tsx similarity index 100% rename from packages/components/Button/Button.stories.tsx rename to src/components/Button/Button.stories.tsx diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx new file mode 100644 index 0000000..d1ac4e7 --- /dev/null +++ b/src/components/Button/Button.tsx @@ -0,0 +1,77 @@ +import React from "react"; +import { Button as BaseButton } from "@base-ui/react/button"; +import clsx from "clsx"; +import * as styles from "./Button.css"; +import { lightTheme, type ColorIntent } from "@/tokens"; +import { useTheme } from "@/providers"; + +export type ButtonVariant = "solid" | "outline" | "ghost" | "weak"; +export type ButtonSize = "small" | "medium" | "large" | "xlarge"; +export type ButtonIntent = ColorIntent; +export type ButtonRounded = "small" | "medium" | "large"; + +export interface ButtonProps extends Omit< + React.ButtonHTMLAttributes, + "color" +> { + variant?: ButtonVariant; + size?: ButtonSize; + intent?: ButtonIntent; + rounded?: ButtonRounded; + fullWidth?: boolean; + disabled?: boolean; +} + +/** + * Button component for user interactions. + * + * @param ButtonProps + * @param variant - Visual style variant (solid, outline, ghost, weak) + * @param size - Size of the button (small, medium, large, xlarge) + * @param intent - Color intent (primary, secondary, success, warning, danger, neutral) + * @param rounded - Border radius size (small, medium, large) + * @param disabled - Whether the button is disabled + * @param fullWidth - Whether the button should take full width + */ +export const Button = React.forwardRef( + ( + { + variant = "solid", + size = "medium", + intent = "primary", + rounded = "medium", + fullWidth = false, + disabled = false, + children, + className, + ...props + }, + ref + ) => { + const themeContext = useTheme(); + const themeClass = themeContext?.themeClass ?? lightTheme; + + return ( + + {children} + + ); + } +); + +Button.displayName = "Button"; diff --git a/packages/components/Button/index.ts b/src/components/Button/index.ts similarity index 100% rename from packages/components/Button/index.ts rename to src/components/Button/index.ts diff --git a/packages/components/Checkbox/Checkbox.css.ts b/src/components/Checkbox/Checkbox.css.ts similarity index 87% rename from packages/components/Checkbox/Checkbox.css.ts rename to src/components/Checkbox/Checkbox.css.ts index dff6ce4..f894ddb 100644 --- a/packages/components/Checkbox/Checkbox.css.ts +++ b/src/components/Checkbox/Checkbox.css.ts @@ -27,17 +27,10 @@ export const container = style({ }, }); -// Hidden native checkbox -export const hiddenInput = style({ - position: "absolute", - width: "1px", - height: "1px", - padding: 0, - margin: "-1px", - overflow: "hidden", - clip: "rect(0, 0, 0, 0)", - whiteSpace: "nowrap", - border: 0, +// Checkbox root (Base UI) +export const checkboxRoot = style({ + all: "unset", + display: "inline-block", }); // Custom checkbox box base @@ -51,11 +44,11 @@ const checkboxBase = style({ transition: "all 0.2s ease-in-out", backgroundColor: "transparent", selectors: { - "input:focus-visible + &": { + "button:focus-visible &": { outline: `2px solid ${themeContract.color.primary.surface}`, outlineOffset: "2px", }, - "input:disabled + &": { + "button:disabled &": { cursor: "not-allowed", }, }, @@ -128,7 +121,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.surface.outline, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.primary.surface, }, }, @@ -139,6 +132,12 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.primary.surface, backgroundColor: themeContract.color.primary.surface, + selectors: { + "&[data-state='checked']": { + borderColor: themeContract.color.primary.surface, + backgroundColor: themeContract.color.primary.surface, + }, + }, }, }, @@ -148,7 +147,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.surface.outline, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.secondary.surface, }, }, @@ -168,7 +167,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.surface.outline, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.success.surface, }, }, @@ -188,7 +187,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.surface.outline, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.warning.surface, }, }, @@ -208,7 +207,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.surface.outline, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.danger.surface, }, }, @@ -228,7 +227,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.surface.outline, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.neutral.surface, }, }, @@ -248,7 +247,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.primary.weak, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.primary.surface, }, }, @@ -269,7 +268,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.secondary.weak, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.secondary.surface, }, }, @@ -290,7 +289,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.success.weak, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.success.surface, }, }, @@ -311,7 +310,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.warning.weak, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.warning.surface, }, }, @@ -332,7 +331,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.danger.weak, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.danger.surface, }, }, @@ -353,7 +352,7 @@ export const checkbox = recipe({ style: { borderColor: themeContract.color.neutral.weak, selectors: { - "input:hover:not(:disabled) + &": { + "button:hover:not(:disabled) &": { borderColor: themeContract.color.neutral.surface, }, }, @@ -378,16 +377,24 @@ export const checkbox = recipe({ }, }); -// Checkmark icon (SVG) -export const checkmarkIcon = style({ +// Indicator container +export const indicatorContainer = style({ display: "none", width: "100%", height: "100%", - color: "white", + alignItems: "center", + justifyContent: "center", selectors: { - "input:checked + * > &": { - display: "block", - animation: `${checkmark} 0.2s ease-in-out`, + "&[data-state='checked']": { + display: "flex", }, }, }); + +// Checkmark icon (SVG) +export const checkmarkIcon = style({ + width: "100%", + height: "100%", + color: "white", + animation: `${checkmark} 0.2s ease-in-out`, +}); diff --git a/src/components/Checkbox/Checkbox.spec.tsx b/src/components/Checkbox/Checkbox.spec.tsx new file mode 100644 index 0000000..db96c16 --- /dev/null +++ b/src/components/Checkbox/Checkbox.spec.tsx @@ -0,0 +1,216 @@ +import { describe, it, expect, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { Checkbox } from "./Checkbox"; +import React from "react"; + +describe("Checkbox", () => { + describe("Rendering", () => { + it("renders without label", () => { + render(); + expect(screen.getByRole("checkbox")).toBeInTheDocument(); + }); + + it("renders with label", () => { + render(); + expect(screen.getByRole("checkbox")).toBeInTheDocument(); + expect(screen.getByText("Accept terms")).toBeInTheDocument(); + }); + + it("applies custom className", () => { + const { container } = render(); + expect(container.querySelector(".custom-class")).toBeInTheDocument(); + }); + }); + + describe("States", () => { + it("renders unchecked by default", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("aria-checked", "false"); + expect(checkboxElement).toHaveAttribute("data-unchecked"); + }); + + it("renders checked when checked prop is true", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("aria-checked", "true"); + expect(checkboxElement).toHaveAttribute("data-checked"); + }); + + it("renders disabled checkbox", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("aria-disabled", "true"); + expect(checkboxElement).toHaveAttribute("data-disabled"); + }); + + it("supports defaultChecked for uncontrolled mode", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("aria-checked", "true"); + expect(checkboxElement).toHaveAttribute("data-checked"); + }); + + it("renders readOnly checkbox", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("data-readonly"); + }); + }); + + describe("Interactions", () => { + it("toggles when clicked (uncontrolled)", async () => { + const user = userEvent.setup(); + render(); + const checkboxElement = screen.getByRole("checkbox"); + + expect(checkboxElement).toHaveAttribute("aria-checked", "false"); + + await user.click(checkboxElement); + expect(checkboxElement).toHaveAttribute("aria-checked", "true"); + + await user.click(checkboxElement); + expect(checkboxElement).toHaveAttribute("aria-checked", "false"); + }); + + it("calls onCheckedChange when toggled", async () => { + const handleChange = vi.fn(); + const user = userEvent.setup(); + + render(); + const checkboxElement = screen.getByRole("checkbox"); + + await user.click(checkboxElement); + expect(handleChange).toHaveBeenCalled(); + expect(handleChange.mock.calls[0][0]).toBe(true); + + await user.click(checkboxElement); + expect(handleChange).toHaveBeenCalledTimes(2); + expect(handleChange.mock.calls[1][0]).toBe(false); + }); + + it("does not toggle when disabled", async () => { + const handleChange = vi.fn(); + const user = userEvent.setup(); + + render(); + const checkboxElement = screen.getByRole("checkbox"); + + await user.click(checkboxElement); + expect(handleChange).not.toHaveBeenCalled(); + }); + + it("works in controlled mode", async () => { + const TestComponent = () => { + const [checked, setChecked] = React.useState(false); + return ( + + ); + }; + + const user = userEvent.setup(); + + render(); + const checkboxElement = screen.getByRole("checkbox"); + + expect(checkboxElement).toHaveAttribute("aria-checked", "false"); + + await user.click(checkboxElement); + expect(checkboxElement).toHaveAttribute("aria-checked", "true"); + }); + }); + + describe("Keyboard Navigation", () => { + it("can be focused with keyboard", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + checkboxElement.focus(); + expect(checkboxElement).toHaveFocus(); + }); + + it("toggles with Space key", async () => { + const user = userEvent.setup(); + render(); + const checkboxElement = screen.getByRole("checkbox"); + + checkboxElement.focus(); + await user.keyboard(" "); + + expect(checkboxElement).toHaveAttribute("aria-checked", "true"); + }); + + it("toggles with Enter key", async () => { + const user = userEvent.setup(); + render(); + const checkboxElement = screen.getByRole("checkbox"); + + checkboxElement.focus(); + await user.keyboard("{Enter}"); + + expect(checkboxElement).toHaveAttribute("aria-checked", "true"); + }); + }); + + describe("Accessibility", () => { + it("has checkbox role", () => { + render(); + expect(screen.getByRole("checkbox")).toBeInTheDocument(); + }); + + it("has correct aria-checked attribute when unchecked", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("aria-checked", "false"); + }); + + it("has correct aria-checked attribute when checked", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("aria-checked", "true"); + }); + + it("has correct aria-disabled attribute when disabled", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("aria-disabled", "true"); + }); + + it("associates label with checkbox", () => { + render(); + const label = screen.getByText("Test label"); + expect(label).toBeInTheDocument(); + }); + }); + + describe("Form Integration", () => { + it("accepts name attribute", () => { + const { container } = render(); + const hiddenInput = container.querySelector('input[type="checkbox"]'); + expect(hiddenInput).toHaveAttribute("name", "terms"); + }); + + it("accepts required attribute", () => { + render(); + const checkboxElement = screen.getByRole("checkbox"); + expect(checkboxElement).toHaveAttribute("data-required"); + }); + + it("updates hidden input value when toggled", async () => { + const user = userEvent.setup(); + const { container } = render(); + const hiddenInput = container.querySelector('input[type="checkbox"]') as HTMLInputElement; + + expect(hiddenInput?.checked).toBe(false); + + const checkboxElement = screen.getByRole("checkbox"); + await user.click(checkboxElement); + + expect(hiddenInput?.checked).toBe(true); + }); + }); +}); diff --git a/packages/components/Checkbox/Checkbox.stories.tsx b/src/components/Checkbox/Checkbox.stories.tsx similarity index 99% rename from packages/components/Checkbox/Checkbox.stories.tsx rename to src/components/Checkbox/Checkbox.stories.tsx index 04372be..cfd2e04 100644 --- a/packages/components/Checkbox/Checkbox.stories.tsx +++ b/src/components/Checkbox/Checkbox.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react"; +import React from "react"; import { Checkbox } from "./Checkbox"; const meta = { @@ -347,7 +348,7 @@ export const ControlledExample: Story = { setChecked(e.target.checked)} + onCheckedChange={(checked) => setChecked(checked)} />

Current state: {checked ? "✅ Checked" : "⬜ Unchecked"}

+ +

Dialog content

+
+ + ); + }; + + const user = userEvent.setup(); + render(); + + expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); + + await user.click(screen.getByText("Open Dialog")); + + await waitFor(() => { + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + }); + }); + + describe("Accessibility", () => { + it("has dialog role", () => { + render( + {}}> +

Content

+
+ ); + expect(screen.getByRole("dialog")).toBeInTheDocument(); + }); + + it("has aria-labelledby when title is provided", () => { + render( + {}} title="Dialog Title"> +

Content

+
+ ); + const dialog = screen.getByRole("dialog"); + expect(dialog).toHaveAttribute("aria-labelledby"); + }); + + it("has aria-describedby when description is provided", () => { + render( + {}} + title="Title" + description="Description" + > +

Content

+
+ ); + const dialog = screen.getByRole("dialog"); + expect(dialog).toHaveAttribute("aria-describedby"); + }); + + it("supports dialog interactions", () => { + render( + {}}> +

Content

+
+ ); + const dialog = screen.getByRole("dialog"); + expect(dialog).toBeInTheDocument(); + expect(dialog).toBeVisible(); + }); + + it("traps focus within dialog when open", async () => { + const user = userEvent.setup(); + + render( + {}} + title="Dialog" + actions={[ + { label: "Cancel", onClick: () => {} }, + { label: "Confirm", onClick: () => {} }, + ]} + > +

Content

+
+ ); + + const cancelButton = screen.getByText("Cancel"); + const confirmButton = screen.getByText("Confirm"); + + // Tab through dialog elements + await user.tab(); + // One of the buttons should have focus + const hasButtonFocus = cancelButton.matches(':focus') || confirmButton.matches(':focus'); + expect(hasButtonFocus || document.activeElement === cancelButton || document.activeElement === confirmButton).toBe(true); + }); + }); + + describe("Portal", () => { + it("renders dialog outside of parent DOM hierarchy", () => { + const { container } = render( +
+ {}}> +

Content

+
+
+ ); + + const dialog = screen.getByRole("dialog"); + const parent = container.querySelector('[data-testid="parent"]'); + + // Dialog should not be a descendant of parent + expect(parent).not.toContainElement(dialog); + }); + }); + + describe("Multiple Actions", () => { + it("renders multiple actions with different variants and intents", () => { + render( + {}} + actions={[ + { + label: "Delete", + onClick: () => {}, + variant: "solid", + intent: "danger", + }, + { + label: "Cancel", + onClick: () => {}, + variant: "outline", + intent: "neutral", + }, + { + label: "Save", + onClick: () => {}, + variant: "solid", + intent: "primary", + }, + ]} + > +

Content

+
+ ); + + expect(screen.getByText("Delete")).toBeInTheDocument(); + expect(screen.getByText("Cancel")).toBeInTheDocument(); + expect(screen.getByText("Save")).toBeInTheDocument(); + }); + }); +}); + diff --git a/packages/components/Dialog/Dialog.stories.tsx b/src/components/Dialog/Dialog.stories.tsx similarity index 100% rename from packages/components/Dialog/Dialog.stories.tsx rename to src/components/Dialog/Dialog.stories.tsx diff --git a/src/components/Dialog/Dialog.tsx b/src/components/Dialog/Dialog.tsx new file mode 100644 index 0000000..847837d --- /dev/null +++ b/src/components/Dialog/Dialog.tsx @@ -0,0 +1,153 @@ +import { Dialog as BaseDialog } from "@base-ui/react/dialog"; +import clsx from "clsx"; +import * as styles from "./Dialog.css"; +import { lightTheme } from "@/tokens"; +import { useTheme } from "@/providers"; +import { Button } from "../Button"; +import type { ButtonVariant, ButtonIntent } from "../Button"; + +export type DialogSize = "small" | "medium" | "large" | "xlarge" | "full"; +export type DialogRounded = "small" | "medium" | "large"; + +export interface DialogAction { + label: string; + onClick: () => void; + variant?: ButtonVariant; + intent?: ButtonIntent; + disabled?: boolean; +} + +export interface DialogProps extends Omit, "title"> { + open: boolean; + onOpenChange?: (open: boolean) => void; + onClose?: () => void; + size?: DialogSize; + rounded?: DialogRounded; + title?: string; + description?: string; + children: React.ReactNode; + actions?: DialogAction[]; + footer?: React.ReactNode; + showCloseButton?: boolean; + closeOnOverlayClick?: boolean; + closeOnEscape?: boolean; +} + +/** + * Dialog component for modal interactions. + * + * @param DialogProps + * @param open - Whether the dialog is open + * @param onOpenChange - Callback when open state changes + * @param title - Dialog title + * @param description - Dialog description text + * @param size - Size of the dialog (small, medium, large, xlarge, full) + * @param rounded - Border radius size (small, medium, large) + * @param actions - Array of action buttons to display + * @param closeOnEscape - Whether to close on Escape key press + */ +export const Dialog = ({ + open, + onOpenChange, + onClose, + size = "medium", + rounded = "medium", + title, + description, + children, + actions, + footer, + showCloseButton = true, + closeOnOverlayClick = true, + closeOnEscape = true, + className, +}: DialogProps) => { + const themeContext = useTheme(); + const themeClass = themeContext?.themeClass ?? lightTheme; + + const handleOpenChange = (newOpen: boolean) => { + onOpenChange?.(newOpen); + if (!newOpen) { + onClose?.(); + } + }; + + return ( + + + + + {(title || showCloseButton) && ( +
+
+ {title && ( + + {title} + + )} + {description && ( + + {description} + + )} +
+ {showCloseButton && ( + + + + )} +
+ )} + +
{children}
+ + {(actions || footer) && ( +
+ {actions + ? actions.map((action, index) => ( + + )) + : footer} +
+ )} +
+
+
+ ); +}; diff --git a/packages/components/Dialog/index.ts b/src/components/Dialog/index.ts similarity index 100% rename from packages/components/Dialog/index.ts rename to src/components/Dialog/index.ts diff --git a/packages/components/Dropdown/Dropdown.css.ts b/src/components/Dropdown/Dropdown.css.ts similarity index 100% rename from packages/components/Dropdown/Dropdown.css.ts rename to src/components/Dropdown/Dropdown.css.ts diff --git a/src/components/Dropdown/Dropdown.spec.tsx b/src/components/Dropdown/Dropdown.spec.tsx new file mode 100644 index 0000000..7be3793 --- /dev/null +++ b/src/components/Dropdown/Dropdown.spec.tsx @@ -0,0 +1,334 @@ +import { describe, it, expect, vi } from "vitest"; +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { Dropdown, type DropdownOption } from "./Dropdown"; +import React from "react"; + +const mockOptions: DropdownOption[] = [ + { value: "1", label: "Option 1" }, + { value: "2", label: "Option 2" }, + { value: "3", label: "Option 3" }, + { value: "4", label: "Option 4", disabled: true }, +]; + +describe("Dropdown", () => { + describe("Rendering", () => { + it("renders with placeholder", () => { + render( + + ); + expect(screen.getByRole("combobox")).toBeInTheDocument(); + expect(screen.getByText("Select an option")).toBeInTheDocument(); + }); + + it("renders with selected value", () => { + render( + + ); + expect(screen.getByText("Option 2")).toBeInTheDocument(); + }); + + it("applies custom className", () => { + const { container } = render( + + ); + expect(container.querySelector(".custom-class")).toBeInTheDocument(); + }); + + it("renders disabled dropdown", () => { + render(); + const trigger = screen.getByRole("combobox"); + expect(trigger).toHaveAttribute("data-disabled"); + }); + }); + + describe("Interactions", () => { + it("opens dropdown when clicked", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + await user.click(trigger); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + }); + + it("selects option when clicked", async () => { + const handleChange = vi.fn(); + const user = userEvent.setup(); + + render( + + ); + + const trigger = screen.getByRole("combobox"); + await user.click(trigger); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + + const option2 = await screen.findByRole("option", { name: "Option 2" }); + await user.click(option2); + + await waitFor(() => { + expect(handleChange).toHaveBeenCalledWith("2"); + }); + }); + + it("does not open when disabled", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + await user.click(trigger); + + // Should not open + expect(trigger).toHaveAttribute("aria-expanded", "false"); + }); + + it("does not select disabled option", async () => { + const handleChange = vi.fn(); + const user = userEvent.setup(); + + render( + + ); + + const trigger = screen.getByRole("combobox"); + await user.click(trigger); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + + const option4 = await screen.findByRole("option", { name: "Option 4" }); + expect(option4).toHaveAttribute("data-disabled"); + }); + }); + + describe("Keyboard Navigation", () => { + it("opens dropdown with Enter key", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + trigger.focus(); + await user.keyboard("{Enter}"); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + }); + + it("opens dropdown with Space key", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + trigger.focus(); + await user.keyboard(" "); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + }); + + it("closes dropdown with Escape key", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + await user.click(trigger); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + + await user.keyboard("{Escape}"); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "false"); + }); + }); + }); + + describe("Controlled Mode", () => { + it("works in controlled mode", async () => { + const TestComponent = () => { + const [value, setValue] = React.useState(null); + return ( + + ); + }; + + const user = userEvent.setup(); + render(); + + const trigger = screen.getByRole("combobox"); + expect(trigger).toBeInTheDocument(); + + // Trigger should initially show placeholder + await user.click(trigger); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + + const option1 = await screen.findByRole("option", { name: "Option 1" }); + await user.click(option1); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "false"); + }); + }); + + it("supports defaultValue for uncontrolled mode", () => { + render( + + ); + expect(screen.getByText("Option 2")).toBeInTheDocument(); + }); + }); + + describe("Accessibility", () => { + it("has combobox role", () => { + render(); + expect(screen.getByRole("combobox")).toBeInTheDocument(); + }); + + it("has correct aria-expanded attribute", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + expect(trigger).toHaveAttribute("aria-expanded", "false"); + + await user.click(trigger); + + await waitFor(() => { + expect(trigger).toHaveAttribute("aria-expanded", "true"); + }); + }); + + it("has correct aria-disabled attribute when disabled", () => { + render(); + const trigger = screen.getByRole("combobox"); + expect(trigger).toHaveAttribute("data-disabled"); + }); + + it("options have option role", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + await user.click(trigger); + + await waitFor(async () => { + const options = await screen.findAllByRole("option"); + expect(options).toHaveLength(4); + }); + }); + + it("selected option has correct aria-selected attribute", async () => { + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + await user.click(trigger); + + await waitFor(async () => { + const option2 = await screen.findByRole("option", { name: "Option 2" }); + expect(option2).toHaveAttribute("data-selected"); + }); + }); + }); + + describe("Form Integration", () => { + it("accepts name attribute", () => { + const { container } = render( + + ); + const hiddenInput = container.querySelector( + 'input[name="dropdown-field"]' + ); + expect(hiddenInput).toBeInTheDocument(); + }); + + it("accepts required attribute", () => { + render(); + const trigger = screen.getByRole("combobox"); + // Required attribute is passed to the component + expect(trigger).toBeInTheDocument(); + }); + }); + + describe("Width", () => { + it("renders with fullWidth", () => { + render(); + const trigger = screen.getByRole("combobox"); + expect(trigger).toBeInTheDocument(); + }); + + it("renders with default width", () => { + render(); + const trigger = screen.getByRole("combobox"); + expect(trigger).toBeInTheDocument(); + }); + }); + + describe("Empty Options", () => { + it("renders with empty options array", () => { + render(); + expect(screen.getByText("No options")).toBeInTheDocument(); + }); + }); + + describe("Multiple Options", () => { + it("renders many options", async () => { + const manyOptions: DropdownOption[] = Array.from({ length: 20 }, (_, i) => ({ + value: `${i + 1}`, + label: `Option ${i + 1}`, + })); + + const user = userEvent.setup(); + + render(); + const trigger = screen.getByRole("combobox"); + + await user.click(trigger); + + await waitFor(async () => { + const options = await screen.findAllByRole("option"); + expect(options.length).toBe(20); + }); + }); + }); +}); + diff --git a/packages/components/Dropdown/Dropdown.stories.tsx b/src/components/Dropdown/Dropdown.stories.tsx similarity index 92% rename from packages/components/Dropdown/Dropdown.stories.tsx rename to src/components/Dropdown/Dropdown.stories.tsx index edba319..250c004 100644 --- a/packages/components/Dropdown/Dropdown.stories.tsx +++ b/src/components/Dropdown/Dropdown.stories.tsx @@ -120,9 +120,9 @@ export const Basic: Story = { { + onValueChange={(newValue) => { setValue(newValue); - args.onChange?.(newValue); + args.onValueChange?.(newValue); }} placeholder={args.placeholder ?? "Select a fruit"} /> @@ -148,9 +148,9 @@ export const WithDefaultValue: Story = { { + onValueChange={(newValue) => { setValue(newValue); - args.onChange?.(newValue); + args.onValueChange?.(newValue); }} /> @@ -177,21 +177,21 @@ export const Sizes: Story = { @@ -222,42 +222,42 @@ export const Intents: Story = { @@ -285,21 +285,21 @@ export const Rounded: Story = { @@ -325,9 +325,9 @@ export const FullWidth: Story = { { + onValueChange={(newValue) => { setValue(newValue); - args.onChange?.(newValue); + args.onValueChange?.(newValue); }} placeholder={args.placeholder ?? "Full width dropdown"} /> @@ -374,9 +374,9 @@ export const WithDisabledOptions: Story = { {...args} options={optionsWithDisabled} value={value} - onChange={(newValue) => { + onValueChange={(newValue) => { setValue(newValue); - args.onChange?.(newValue); + args.onValueChange?.(newValue); }} placeholder={args.placeholder ?? "Select a fruit"} /> @@ -405,9 +405,9 @@ export const ManyOptions: Story = { {...args} options={manyOptions} value={value} - onChange={(newValue) => { + onValueChange={(newValue) => { setValue(newValue); - args.onChange?.(newValue); + args.onValueChange?.(newValue); }} placeholder={args.placeholder ?? "Select an option"} /> @@ -469,7 +469,7 @@ export const FormExample: Story = { @@ -489,7 +489,7 @@ export const FormExample: Story = { @@ -509,7 +509,7 @@ export const FormExample: Story = { @@ -561,9 +561,9 @@ export const ControlledExample: Story = { { + onValueChange={(newValue) => { setValue(newValue); - args.onChange?.(newValue); + args.onValueChange?.(newValue); }} />

@@ -614,9 +614,9 @@ export const Playground: Story = { { + onValueChange={(newValue) => { setValue(newValue); - args.onChange?.(newValue); + args.onValueChange?.(newValue); }} /> diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx new file mode 100644 index 0000000..c6a1359 --- /dev/null +++ b/src/components/Dropdown/Dropdown.tsx @@ -0,0 +1,139 @@ +import { Select as BaseSelect } from "@base-ui/react/select"; +import clsx from "clsx"; +import * as styles from "./Dropdown.css"; +import { lightTheme, type ColorIntent } from "@/tokens"; +import { useTheme } from "@/providers"; + +export type DropdownSize = "small" | "medium" | "large"; +export type DropdownRounded = "small" | "medium" | "large"; +export type DropdownIntent = ColorIntent; + +export interface DropdownOption { + value: string; + label: string; + disabled?: boolean; +} + +export interface DropdownProps + extends Omit, "onChange" | "defaultValue"> { + options: DropdownOption[]; + value?: string; + defaultValue?: string; + onValueChange?: (value: string | null) => void; + placeholder?: string; + size?: DropdownSize; + rounded?: DropdownRounded; + intent?: DropdownIntent; + fullWidth?: boolean; + disabled?: boolean; + name?: string; + required?: boolean; +} + +/** + * Dropdown component for option selection. + * + * @param DropdownProps + * @param options - Array of selectable options + * @param value - Currently selected value (controlled) + * @param placeholder - Placeholder text when no option is selected + * @param size - Size of the dropdown (small, medium, large) + * @param rounded - Border radius size (small, medium, large) + * @param intent - Color intent (primary, secondary, success, warning, danger, neutral) + * @param disabled - Whether the dropdown is disabled + * @param onValueChange - Callback when selected value changes + */ +export const Dropdown = ({ + options, + value, + defaultValue, + onValueChange, + placeholder = "Select an option", + size = "medium", + rounded = "medium", + intent = "primary", + fullWidth = false, + disabled = false, + className, + name, + required, +}: DropdownProps) => { + const themeContext = useTheme(); + const themeClass = themeContext?.themeClass ?? lightTheme; + + return ( + onValueChange?.(newValue)} + disabled={disabled} + name={name} + required={required} + > +

+ + + {(selectedValue: string | null) => { + const selected = options.find( + (opt) => opt.value === selectedValue + ); + return selected?.label || placeholder; + }} + + + + + + + + + + + + + {options.map((option) => ( + + {option.label} + + ))} + + + + +
+ + ); +}; diff --git a/packages/components/Dropdown/index.ts b/src/components/Dropdown/index.ts similarity index 100% rename from packages/components/Dropdown/index.ts rename to src/components/Dropdown/index.ts diff --git a/src/components/Switch/Switch.css.ts b/src/components/Switch/Switch.css.ts new file mode 100644 index 0000000..5083075 --- /dev/null +++ b/src/components/Switch/Switch.css.ts @@ -0,0 +1,206 @@ +import { style } from "@vanilla-extract/css"; +import { recipe } from "@vanilla-extract/recipes"; +import { themeContract } from "@/tokens"; + +export const container = style({ + display: "inline-flex", + alignItems: "center", + gap: themeContract.spacing.xs, + cursor: "pointer", + userSelect: "none", + selectors: { + "&:has(input:disabled)": { + cursor: "not-allowed", + opacity: 0.5, + }, + }, +}); + +export const switchRoot = style({ + all: "unset", + display: "inline-block", +}); + +const trackBase = style({ + position: "relative", + display: "inline-flex", + alignItems: "center", + flexShrink: 0, + borderRadius: themeContract.radius.xlarge, + transition: "background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1)", + selectors: { + "button:focus-visible &": { + outline: `2px solid ${themeContract.color.primary.surface}`, + outlineOffset: "2px", + }, + "button:disabled &": { + cursor: "not-allowed", + }, + }, +}); + +export const track = recipe({ + base: trackBase, + + variants: { + size: { + small: { + width: "30px", + height: "18px", + padding: "2px 4px", + }, + medium: { + width: "43px", + height: "24px", + padding: "2px 3px", + }, + large: { + width: "54px", + height: "30px", + padding: "2px 4px", + }, + xlarge: { + width: "66px", + height: "36px", + padding: "2px 4px", + }, + }, + + intent: { + primary: { + selectors: { + "&[data-state='unchecked']": { + backgroundColor: themeContract.color.surface.outline, + }, + "&[data-state='checked']": { + backgroundColor: themeContract.color.primary.surface, + }, + }, + }, + secondary: { + selectors: { + "&[data-state='unchecked']": { + backgroundColor: themeContract.color.surface.outline, + }, + "&[data-state='checked']": { + backgroundColor: themeContract.color.secondary.surface, + }, + }, + }, + success: { + selectors: { + "&[data-state='unchecked']": { + backgroundColor: themeContract.color.surface.outline, + }, + "&[data-state='checked']": { + backgroundColor: themeContract.color.success.surface, + }, + }, + }, + warning: { + selectors: { + "&[data-state='unchecked']": { + backgroundColor: themeContract.color.surface.outline, + }, + "&[data-state='checked']": { + backgroundColor: themeContract.color.warning.surface, + }, + }, + }, + danger: { + selectors: { + "&[data-state='unchecked']": { + backgroundColor: themeContract.color.surface.outline, + }, + "&[data-state='checked']": { + backgroundColor: themeContract.color.danger.surface, + }, + }, + }, + neutral: { + selectors: { + "&[data-state='unchecked']": { + backgroundColor: themeContract.color.surface.outline, + }, + "&[data-state='checked']": { + backgroundColor: themeContract.color.neutral.surface, + }, + }, + }, + }, + }, + + defaultVariants: { + size: "medium", + intent: "primary", + }, +}); + +// Switch thumb (sliding circle) +const thumbBase = style({ + backgroundColor: "white", + borderRadius: themeContract.radius.xlarge, + transition: "transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1)", + boxShadow: themeContract.shadow.small, +}); + +export const thumb = recipe({ + base: thumbBase, + + variants: { + size: { + small: { + width: "14px", + height: "14px", + selectors: { + "&[data-state='unchecked']": { + transform: "translateX(0)", + }, + "&[data-state='checked']": { + transform: "translateX(16px)", + }, + }, + }, + medium: { + width: "20px", + height: "20px", + selectors: { + "&[data-state='unchecked']": { + transform: "translateX(0)", + }, + "&[data-state='checked']": { + transform: "translateX(22px)", + }, + }, + }, + large: { + width: "24px", + height: "24px", + selectors: { + "&[data-state='unchecked']": { + transform: "translateX(0)", + }, + "&[data-state='checked']": { + transform: "translateX(28px)", + }, + }, + }, + xlarge: { + width: "28px", + height: "28px", + selectors: { + "&[data-state='unchecked']": { + transform: "translateX(0)", + }, + "&[data-state='checked']": { + transform: "translateX(34px)", + }, + }, + }, + }, + }, + + defaultVariants: { + size: "medium", + }, +}); diff --git a/src/components/Switch/Switch.spec.tsx b/src/components/Switch/Switch.spec.tsx new file mode 100644 index 0000000..dd7c4ce --- /dev/null +++ b/src/components/Switch/Switch.spec.tsx @@ -0,0 +1,216 @@ +import { describe, it, expect, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { Switch } from "./Switch"; +import React from "react"; + +describe("Switch", () => { + describe("Rendering", () => { + it("renders without label", () => { + render(); + expect(screen.getByRole("switch")).toBeInTheDocument(); + }); + + it("renders with label", () => { + render(); + expect(screen.getByRole("switch")).toBeInTheDocument(); + expect(screen.getByText("Enable notifications")).toBeInTheDocument(); + }); + + it("applies custom className", () => { + const { container } = render(); + expect(container.querySelector(".custom-class")).toBeInTheDocument(); + }); + }); + + describe("States", () => { + it("renders unchecked by default", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("aria-checked", "false"); + expect(switchElement).toHaveAttribute("data-unchecked"); + }); + + it("renders checked when checked prop is true", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("aria-checked", "true"); + expect(switchElement).toHaveAttribute("data-checked"); + }); + + it("renders disabled switch", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("aria-disabled", "true"); + expect(switchElement).toHaveAttribute("data-disabled"); + }); + + it("supports defaultChecked for uncontrolled mode", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("aria-checked", "true"); + expect(switchElement).toHaveAttribute("data-checked"); + }); + + it("renders readOnly switch", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("data-readonly"); + }); + }); + + describe("Interactions", () => { + it("toggles when clicked (uncontrolled)", async () => { + const user = userEvent.setup(); + render(); + const switchElement = screen.getByRole("switch"); + + expect(switchElement).toHaveAttribute("aria-checked", "false"); + + await user.click(switchElement); + expect(switchElement).toHaveAttribute("aria-checked", "true"); + + await user.click(switchElement); + expect(switchElement).toHaveAttribute("aria-checked", "false"); + }); + + it("calls onCheckedChange when toggled", async () => { + const handleChange = vi.fn(); + const user = userEvent.setup(); + + render(); + const switchElement = screen.getByRole("switch"); + + await user.click(switchElement); + expect(handleChange).toHaveBeenCalled(); + expect(handleChange.mock.calls[0][0]).toBe(true); + + await user.click(switchElement); + expect(handleChange).toHaveBeenCalledTimes(2); + expect(handleChange.mock.calls[1][0]).toBe(false); + }); + + it("does not toggle when disabled", async () => { + const handleChange = vi.fn(); + const user = userEvent.setup(); + + render(); + const switchElement = screen.getByRole("switch"); + + await user.click(switchElement); + expect(handleChange).not.toHaveBeenCalled(); + }); + + it("works in controlled mode", async () => { + const TestComponent = () => { + const [checked, setChecked] = React.useState(false); + return ( + + ); + }; + + const user = userEvent.setup(); + + render(); + const switchElement = screen.getByRole("switch"); + + expect(switchElement).toHaveAttribute("aria-checked", "false"); + + await user.click(switchElement); + expect(switchElement).toHaveAttribute("aria-checked", "true"); + }); + }); + + describe("Keyboard Navigation", () => { + it("can be focused with keyboard", () => { + render(); + const switchElement = screen.getByRole("switch"); + switchElement.focus(); + expect(switchElement).toHaveFocus(); + }); + + it("toggles with Space key", async () => { + const user = userEvent.setup(); + render(); + const switchElement = screen.getByRole("switch"); + + switchElement.focus(); + await user.keyboard(" "); + + expect(switchElement).toHaveAttribute("aria-checked", "true"); + }); + + it("toggles with Enter key", async () => { + const user = userEvent.setup(); + render(); + const switchElement = screen.getByRole("switch"); + + switchElement.focus(); + await user.keyboard("{Enter}"); + + expect(switchElement).toHaveAttribute("aria-checked", "true"); + }); + }); + + describe("Accessibility", () => { + it("has switch role", () => { + render(); + expect(screen.getByRole("switch")).toBeInTheDocument(); + }); + + it("has correct aria-checked attribute when unchecked", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("aria-checked", "false"); + }); + + it("has correct aria-checked attribute when checked", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("aria-checked", "true"); + }); + + it("has correct aria-disabled attribute when disabled", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("aria-disabled", "true"); + }); + + it("associates label with switch", () => { + render(); + const label = screen.getByText("Test label"); + expect(label).toBeInTheDocument(); + }); + }); + + describe("Form Integration", () => { + it("accepts name attribute", () => { + const { container } = render(); + const hiddenInput = container.querySelector('input[type="checkbox"]'); + expect(hiddenInput).toHaveAttribute("name", "notifications"); + }); + + it("accepts required attribute", () => { + render(); + const switchElement = screen.getByRole("switch"); + expect(switchElement).toHaveAttribute("data-required"); + }); + + it("updates hidden input value when toggled", async () => { + const user = userEvent.setup(); + const { container } = render(); + const hiddenInput = container.querySelector('input[type="checkbox"]') as HTMLInputElement; + + expect(hiddenInput?.checked).toBe(false); + + const switchElement = screen.getByRole("switch"); + await user.click(switchElement); + + expect(hiddenInput?.checked).toBe(true); + }); + }); +}); diff --git a/packages/components/Switch/Switch.stories.tsx b/src/components/Switch/Switch.stories.tsx similarity index 98% rename from packages/components/Switch/Switch.stories.tsx rename to src/components/Switch/Switch.stories.tsx index 3351664..d8d0323 100644 --- a/packages/components/Switch/Switch.stories.tsx +++ b/src/components/Switch/Switch.stories.tsx @@ -92,7 +92,7 @@ export const Checked: Story = { setChecked(e.target.checked)} + onCheckedChange={(checked) => setChecked(checked)} /> ); }, @@ -320,7 +320,7 @@ export const ControlledExample: Story = { setChecked(e.target.checked)} + onCheckedChange={(checked) => setChecked(checked)} />

Current state: {checked ? "🟢 ON" : "⚪ OFF"}

+ + ); + + const input = screen.getByPlaceholderText("Username"); + await user.type(input, "testuser"); + + const submitButton = screen.getByRole("button", { name: /submit/i }); + await user.click(submitButton); + + expect(handleSubmit).toHaveBeenCalledTimes(1); + }); + }); + + describe("Validation", () => { + it("accepts validate prop", () => { + const validate = (value: unknown) => { + if (typeof value === "string" && value.length < 3) { + return "Must be at least 3 characters"; + } + return null; + }; + + render( + + ); + + const input = screen.getByPlaceholderText("test"); + expect(input).toBeInTheDocument(); + }); + }); +}); diff --git a/packages/components/TextField/TextField.stories.tsx b/src/components/TextField/TextField.stories.tsx similarity index 100% rename from packages/components/TextField/TextField.stories.tsx rename to src/components/TextField/TextField.stories.tsx diff --git a/src/components/TextField/TextField.tsx b/src/components/TextField/TextField.tsx new file mode 100644 index 0000000..175e328 --- /dev/null +++ b/src/components/TextField/TextField.tsx @@ -0,0 +1,107 @@ +import { Field } from "@base-ui/react/field"; +import { Input } from "@base-ui/react/input"; +import clsx from "clsx"; +import { + container, + containerVariants, + input, + label, + helperText, +} from "./TextField.css"; +import { lightTheme } from "@/tokens"; +import { useTheme } from "@/providers"; + +export type TextFieldSize = "small" | "medium" | "large" | "xlarge"; +export type TextFieldRounded = "small" | "medium" | "large"; +export type TextFieldVariant = "outline" | "filled"; +export type TextFieldStatus = "default" | "error" | "success"; + +export interface TextFieldProps extends Omit< + React.InputHTMLAttributes, + "size" +> { + size?: TextFieldSize; + rounded?: TextFieldRounded; + variant?: TextFieldVariant; + status?: TextFieldStatus; + label?: string; + helperText?: string; + fullWidth?: boolean; + name?: string; + required?: boolean; + validate?: ( + value: unknown, + formValues: Record + ) => string | string[] | Promise | null; +} + +/** + * TextField component for text input. + * + * @param TextFieldProps + * @param label - Label text for the input field + * @param placeholder - Placeholder text + * @param value - Current input value (controlled) + * @param type - Input type (text, email, password, etc.) + * @param size - Size of the input (small, medium, large, xlarge) + * @param rounded - Border radius size (small, medium, large) + * @param variant - Visual style variant (outline, filled) + * @param status - Validation status (default, error, success) + * @param disabled - Whether the input is disabled + * @param helperText - Helper text displayed below the input + */ +export const TextField = ({ + size = "medium", + rounded = "medium", + variant = "outline", + status = "default", + label: labelText, + helperText: helperTextContent, + fullWidth = false, + disabled = false, + className, + name, + required, + validate, + ...props +}: TextFieldProps) => { + const themeContext = useTheme(); + const themeClass = themeContext?.themeClass ?? lightTheme; + + return ( + + {labelText && ( + + {labelText} + {required && " *"} + + )} + + {helperTextContent && status !== "error" && ( + + {helperTextContent} + + )} + + + ); +}; diff --git a/packages/components/TextField/index.ts b/src/components/TextField/index.ts similarity index 100% rename from packages/components/TextField/index.ts rename to src/components/TextField/index.ts diff --git a/packages/components/index.ts b/src/components/index.ts similarity index 91% rename from packages/components/index.ts rename to src/components/index.ts index 1e9dbf4..7352c40 100644 --- a/packages/components/index.ts +++ b/src/components/index.ts @@ -4,6 +4,7 @@ export * from "./Checkbox"; export * from "./Dialog"; export * from "./Dropdown"; export * from "./Switch"; +export * from "./Tab"; export * from "./Text"; export * from "./TextField"; diff --git a/packages/providers/ThemeContext.tsx b/src/providers/ThemeContext.tsx similarity index 100% rename from packages/providers/ThemeContext.tsx rename to src/providers/ThemeContext.tsx diff --git a/packages/providers/ThemeProvider.tsx b/src/providers/ThemeProvider.tsx similarity index 100% rename from packages/providers/ThemeProvider.tsx rename to src/providers/ThemeProvider.tsx diff --git a/packages/providers/index.ts b/src/providers/index.ts similarity index 100% rename from packages/providers/index.ts rename to src/providers/index.ts diff --git a/packages/providers/useTheme.ts b/src/providers/useTheme.ts similarity index 100% rename from packages/providers/useTheme.ts rename to src/providers/useTheme.ts diff --git a/packages/tokens/appearanceTheme.ts b/src/tokens/appearanceTheme.ts similarity index 100% rename from packages/tokens/appearanceTheme.ts rename to src/tokens/appearanceTheme.ts diff --git a/packages/tokens/colors.ts b/src/tokens/colors.ts similarity index 100% rename from packages/tokens/colors.ts rename to src/tokens/colors.ts diff --git a/src/tokens/global.css.ts b/src/tokens/global.css.ts new file mode 100644 index 0000000..181a908 --- /dev/null +++ b/src/tokens/global.css.ts @@ -0,0 +1,15 @@ +import { globalStyle } from "@vanilla-extract/css"; + +globalStyle("#root", { + isolation: "isolate", +}); + +globalStyle("body", { + isolation: "isolate", + position: "relative", + margin: 0, +}); + +globalStyle("*, *::before, *::after", { + boxSizing: "border-box", +}); diff --git a/packages/tokens/index.ts b/src/tokens/index.ts similarity index 89% rename from packages/tokens/index.ts rename to src/tokens/index.ts index b107739..62898a1 100644 --- a/packages/tokens/index.ts +++ b/src/tokens/index.ts @@ -5,3 +5,5 @@ export * from "./radius"; export * from "./shadow"; export * from "./appearanceTheme"; export * from "./theme.css"; + +import "./global.css"; diff --git a/packages/tokens/radius.ts b/src/tokens/radius.ts similarity index 100% rename from packages/tokens/radius.ts rename to src/tokens/radius.ts diff --git a/packages/tokens/shadow.ts b/src/tokens/shadow.ts similarity index 100% rename from packages/tokens/shadow.ts rename to src/tokens/shadow.ts diff --git a/packages/tokens/spacing.ts b/src/tokens/spacing.ts similarity index 100% rename from packages/tokens/spacing.ts rename to src/tokens/spacing.ts diff --git a/packages/tokens/theme.css.ts b/src/tokens/theme.css.ts similarity index 100% rename from packages/tokens/theme.css.ts rename to src/tokens/theme.css.ts diff --git a/packages/tokens/typography.ts b/src/tokens/typography.ts similarity index 100% rename from packages/tokens/typography.ts rename to src/tokens/typography.ts diff --git a/packages/tokens/utils/applyPrimaryColor.ts b/src/tokens/utils/applyPrimaryColor.ts similarity index 100% rename from packages/tokens/utils/applyPrimaryColor.ts rename to src/tokens/utils/applyPrimaryColor.ts diff --git a/packages/tokens/utils/constants.ts b/src/tokens/utils/constants.ts similarity index 100% rename from packages/tokens/utils/constants.ts rename to src/tokens/utils/constants.ts diff --git a/packages/tokens/utils/generateColorScale.ts b/src/tokens/utils/generateColorScale.ts similarity index 100% rename from packages/tokens/utils/generateColorScale.ts rename to src/tokens/utils/generateColorScale.ts diff --git a/packages/tokens/utils/getWeakColor.ts b/src/tokens/utils/getWeakColor.ts similarity index 100% rename from packages/tokens/utils/getWeakColor.ts rename to src/tokens/utils/getWeakColor.ts diff --git a/packages/tokens/utils/index.ts b/src/tokens/utils/index.ts similarity index 100% rename from packages/tokens/utils/index.ts rename to src/tokens/utils/index.ts diff --git a/tsconfig.app.json b/tsconfig.app.json index 54f5ade..caee707 100644 --- a/tsconfig.app.json +++ b/tsconfig.app.json @@ -5,7 +5,7 @@ "useDefineForClassFields": true, "lib": ["ES2022", "DOM", "DOM.Iterable"], "module": "ESNext", - "types": ["vite/client"], + "types": ["vite/client", "vitest/globals", "@testing-library/jest-dom"], "skipLibCheck": true, /* Bundler mode */ @@ -27,8 +27,8 @@ /* Path Aliases */ "baseUrl": ".", "paths": { - "@/*": ["./packages/*"] + "@/*": ["./src/*"] } }, - "include": ["packages"] + "include": ["src"] } diff --git a/tsconfig.build.json b/tsconfig.build.json index 0587e93..e104e57 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -6,7 +6,7 @@ "outDir": "./dist", "noEmit": false }, - "include": ["packages/**/*"], - "exclude": ["node_modules", "dist", "**/*.stories.tsx", "**/*.test.tsx", "src"] + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "**/*.stories.tsx", "**/*.test.tsx", "**/*.spec.tsx"] } diff --git a/vite.config.ts b/vite.config.ts index eb3d874..57c3bbc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -8,12 +8,12 @@ export default defineConfig({ plugins: [react(), vanillaExtractPlugin()], resolve: { alias: { - "@": resolve(__dirname, "./packages"), + "@": resolve(__dirname, "./src"), }, }, build: { lib: { - entry: resolve(__dirname, "packages/components/index.ts"), + entry: resolve(__dirname, "src/components/index.ts"), name: "PineUI", fileName: (format) => `pine-ui.${format}.js`, formats: ["es", "cjs"], diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..55652d5 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,20 @@ +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; +import { vanillaExtractPlugin } from "@vanilla-extract/vite-plugin"; +import { resolve } from "path"; + +export default defineConfig({ + plugins: [react(), vanillaExtractPlugin()], + test: { + globals: true, + environment: "jsdom", + setupFiles: ["./vitest.setup.ts"], + css: true, + }, + resolve: { + alias: { + "@": resolve(__dirname, "./src"), + }, + }, +}); + diff --git a/vitest.setup.ts b/vitest.setup.ts new file mode 100644 index 0000000..a86a67e --- /dev/null +++ b/vitest.setup.ts @@ -0,0 +1,2 @@ +import "@testing-library/jest-dom/vitest"; +