diff --git a/.changeset/0001-architectural-rewrite.md b/.changeset/0001-architectural-rewrite.md new file mode 100644 index 0000000..fa811a7 --- /dev/null +++ b/.changeset/0001-architectural-rewrite.md @@ -0,0 +1,37 @@ +--- +"@managemate/css": major +"@managemate/react": major +"@managemate/icons": major +--- + +# DSMMG 0.2 — refonte architecturale + +**Breaking changes :** + +- **Tokens couleur** : tous les tokens couleur passent sous le préfixe `--mmg-color-*`. + - `--mmg-bg-*` → `--mmg-color-bg-*` + - `--mmg-text-1/2/3/4` → `--mmg-color-text-{primary,secondary,tertiary,quaternary}` + - `--mmg-border-*` → `--mmg-color-border-*` + - `--mmg-brand-*` → `--mmg-color-accent-*` + - `--mmg-success/warning/danger/info-*` → `--mmg-color-*` + - `--mmg-art-*` → `--mmg-color-art-*` + - `--mmg-state-*` → `--mmg-color-state-*` +- **Tokens typographie** : `--mmg-text-{xs..5xl}` → `--mmg-font-size-*`, `--mmg-leading-*` → `--mmg-line-height-*`, `--mmg-weight-*` → `--mmg-font-weight-*`. +- **Suppression `[data-mmg-product]`** : remplacé par presets utilisateur via `[data-mmg-accent]`. +- **Composants splittés** : `Advanced.tsx`, `Chrome.tsx`, `Article.tsx` éclatés en un fichier par composant. Imports inchangés via le barrel `index.tsx`. +- **Build** : packages désormais distribués via `dist/` (ESM + CJS + types). Les imports depuis `src/` ne sont plus supportés. + +**Nouveautés :** + +- **9 presets accent** utilisateur (`synapse`, `rose`, `blue`, `violet`, `green`, `amber`, `red`, `cyan`, `slate`) avec rampes complètes et variantes dark. +- Composant `ThemePicker` + hooks `useAccent`, `useTheme`. +- Cascade `@layer reset, tokens, base, components, utilities` pour permettre les surcharges sans `!important`. +- Utilitaires CSS `mmg-u-*` (stack, flex, grid, text, bg, padding, margin…). + +**Migration :** + +Lancer le codemod fourni pour migrer ton codebase consommateur : + +```sh +node scripts/migrate-tokens.mjs +``` diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..26047db --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,30 @@ +# Changesets + +Ce dossier contient les "changesets" — des fichiers Markdown qui décrivent les changements à publier. + +## Workflow + +1. Pour chaque PR qui modifie un package versionné, ajouter un changeset : + ```sh + pnpm changeset + ``` +2. Sélectionner les packages impactés et le bump (patch / minor / major). +3. Décrire le changement (1-2 phrases, orienté consommateur). +4. Commit le `.changeset/*.md` généré avec ta PR. + +## Release + +Sur `main` : +```sh +pnpm version-packages # consume les changesets, bump les versions, met à jour CHANGELOG +pnpm release # build + publish (registre privé) +``` + +## Politique de versioning (SemVer strict) + +- **major** : breaking change API publique (rename/suppression d'export, signature de prop modifiée, token renommé). +- **minor** : nouveau composant, nouvelle prop, nouveau token, nouvelle variante. +- **patch** : bugfix, doc, perf interne sans surface publique. + +Les 4 packages versionnés sont **fixed** (même version) pour éviter les +incompatibilités de tokens entre `@managemate/css` et `@managemate/react`. diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..212d667 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [["@managemate/css", "@managemate/react", "@managemate/icons", "@managemate/tokens"]], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": ["demo", "storybook", "docs"] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..66a461d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,71 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + CI: true + HUSKY: 0 + +jobs: + build: + name: Build, typecheck, test, a11y + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + + - name: Install + run: pnpm install --frozen-lockfile + + - name: Build tokens (Style Dictionary) + run: pnpm --filter @managemate/tokens build + + - name: Build icons + run: pnpm --filter @managemate/icons build + + - name: Build CSS + run: pnpm --filter @managemate/css build + + - name: Build React + run: pnpm --filter @managemate/react build + + - name: Typecheck + run: pnpm --filter @managemate/react typecheck + + - name: Test (Vitest + axe-core) + run: pnpm --filter @managemate/react test + + - name: Lint contraste WCAG AA + run: pnpm lint:contrast + + - name: Build Storybook + run: pnpm --filter storybook build + + - name: Bundle size budget + run: pnpm size + + - name: Upload Storybook artifact + if: github.event_name == 'pull_request' + uses: actions/upload-artifact@v4 + with: + name: storybook-static + path: storybook/storybook-static + retention-days: 7 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..edfc6c6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,49 @@ +name: Release + +on: + push: + branches: [main] + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +permissions: + contents: write + pull-requests: write + packages: write + +jobs: + release: + name: Release / open changeset PR + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: pnpm/action-setup@v4 + with: + version: 10 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + registry-url: https://npm.pkg.github.com + + - run: pnpm install --frozen-lockfile + + - run: pnpm build + + - name: Create release PR or publish + uses: changesets/action@v1 + with: + publish: pnpm release + version: pnpm version-packages + commit: "chore(release): version packages" + title: "chore(release): version packages" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e1f4d85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Dependencies +node_modules +.pnpm-store + +# Build outputs +dist +build +*.tsbuildinfo +.turbo + +# Environment +.env +.env.local +.env.*.local + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# IDE +.vscode +.idea +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Storybook +storybook-static +.storybook/dist + +# Test artifacts +coverage +.nyc_output + +# Demo specifics +demo/_dev.log + +# Misc +.cache +.pnpm-debug.log diff --git a/.size-limit.json b/.size-limit.json new file mode 100644 index 0000000..50a318a --- /dev/null +++ b/.size-limit.json @@ -0,0 +1,32 @@ +[ + { + "name": "@managemate/react — full barrel (ESM)", + "path": "packages/react/dist/index.js", + "limit": "60 KB", + "ignore": ["react", "react-dom", "react/jsx-runtime"] + }, + { + "name": "@managemate/react — single Button (tree-shake)", + "path": "packages/react/dist/index.js", + "import": "{ Button }", + "limit": "5 KB", + "ignore": ["react", "react-dom", "react/jsx-runtime"] + }, + { + "name": "@managemate/react — Dialog + ConfirmDialog (Radix)", + "path": "packages/react/dist/index.js", + "import": "{ Dialog, ConfirmDialog }", + "limit": "30 KB", + "ignore": ["react", "react-dom", "react/jsx-runtime"] + }, + { + "name": "@managemate/css — full bundle", + "path": "packages/css/dist/index.css", + "limit": "40 KB" + }, + { + "name": "@managemate/icons — full bundle (192 classes)", + "path": "packages/icons/dist/icons.css", + "limit": "120 KB" + } +] diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..7f6dafb --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,468 @@ +--- +version: "0.2" +name: DSMMG +description: > + Design System ManageMate Group — référence pour Synapse, HRTime, Forge, + Orbit, MSLM, Espace-Client et sites publics. Headless-first sur Radix UI, + RGAA 4.1 / WCAG 2.2 AA, theming utilisateur via 9 presets accent. + +# ═══════════════════════════════════════════════════════════════════ +# COULEURS — primitives → semantic → accent (user-themable) +# ═══════════════════════════════════════════════════════════════════ +colors: + # — Neutrals (warm-cool mix : frais en light, neutre en dark) —————— + neutral-0: "#FFFFFF" + neutral-50: "#F7F6FB" + neutral-100: "#F0EFF9" + neutral-150: "#EDEDFA" + neutral-200: "#E4E3F4" + neutral-300: "#C9C7E0" + neutral-400: "#AAA8C9" + neutral-500: "#7875A1" + neutral-600: "#56557A" + neutral-700: "#3B3A56" + neutral-800: "#1F1E32" + neutral-900: "#111120" + + # — Synapse (rose corporate ManageMate, défaut accent) —————— + synapse-50: "#FEF0F4" + synapse-100: "#FCE0EA" + synapse-200: "#FAD0DF" + synapse-300: "#F4A0BD" + synapse-400: "#ED608E" + synapse-500: "#D12B6A" # ★ marque ManageMate + synapse-600: "#BA245F" + synapse-700: "#A82257" + synapse-800: "#831B45" + synapse-900: "#5A132F" + + # — Presets accent user (8 alternatives au synapse) —————— + rose-500: "#E11D48" + blue-500: "#2563EB" + violet-500: "#7C3AED" + green-500: "#0E9F6E" + amber-500: "#D97706" + red-500: "#DC2626" + cyan-500: "#0891B2" + slate-500: "#475569" + + # — Sémantique fixe (NE CHANGE JAMAIS avec l'accent user) —————— + success: "#059669" + warning: "#D97706" + danger: "#DC2626" + info: "#2563EB" + + # — Active accent (alias dynamique, par défaut synapse) —————— + primary: "{colors.synapse-500}" + secondary: "{colors.neutral-600}" + tertiary: "{colors.neutral-300}" + +# ═══════════════════════════════════════════════════════════════════ +# TYPOGRAPHIE — Figtree partout, 3 échelles selon contexte +# ═══════════════════════════════════════════════════════════════════ +typography: + # — Display (landings produits — HRTime, Synapse, Forge, Orbit) —— + display-2xl: + fontFamily: Figtree + fontSize: 72px + fontWeight: 800 + letterSpacing: "-0.035em" + lineHeight: 1.0 + display-xl: + fontFamily: Figtree + fontSize: 60px + fontWeight: 800 + letterSpacing: "-0.03em" + lineHeight: 1.05 + display-lg: + fontFamily: Figtree + fontSize: 48px + fontWeight: 700 + letterSpacing: "-0.025em" + lineHeight: 1.1 + display-md: + fontFamily: Figtree + fontSize: 36px + fontWeight: 700 + letterSpacing: "-0.02em" + lineHeight: 1.15 + + # — Headlines (apps métier — h1 → h6 sémantiques) ———————— + h1: + fontFamily: Figtree + fontSize: 36px + fontWeight: 700 + letterSpacing: "-0.02em" + lineHeight: 1.2 + h2: + fontFamily: Figtree + fontSize: 30px + fontWeight: 700 + letterSpacing: "-0.015em" + lineHeight: 1.25 + h3: + fontFamily: Figtree + fontSize: 24px + fontWeight: 700 + letterSpacing: "-0.01em" + lineHeight: 1.3 + h4: + fontFamily: Figtree + fontSize: 20px + fontWeight: 600 + letterSpacing: "-0.005em" + lineHeight: 1.35 + h5: + fontFamily: Figtree + fontSize: 17px + fontWeight: 600 + lineHeight: 1.4 + h6: + fontFamily: Figtree + fontSize: 15px + fontWeight: 600 + lineHeight: 1.45 + + # — Body ———————————————————————————————————————— + body-lg: + fontFamily: Figtree + fontSize: 17px + lineHeight: 1.6 + body: + fontFamily: Figtree + fontSize: 15px + lineHeight: 1.55 + body-sm: + fontFamily: Figtree + fontSize: 13px + lineHeight: 1.5 + body-xs: + fontFamily: Figtree + fontSize: 11px + lineHeight: 1.45 + + # — Auxiliaires ———————————————————————————————— + eyebrow: + fontFamily: Figtree + fontSize: 13px + fontWeight: 600 + letterSpacing: "0.06em" + textTransform: uppercase + lead: + fontFamily: Figtree + fontSize: 20px + fontWeight: 400 + letterSpacing: "-0.005em" + lineHeight: 1.5 + overline: + fontFamily: Figtree + fontSize: 11px + fontWeight: 600 + letterSpacing: "0.08em" + textTransform: uppercase + caption: + fontFamily: Figtree + fontSize: 11px + lineHeight: 1.4 + code: + fontFamily: "JetBrains Mono" + fontSize: 13px + +# ═══════════════════════════════════════════════════════════════════ +# RAYONS — pill par défaut sur interactifs et conteneurs +# ═══════════════════════════════════════════════════════════════════ +rounded: + none: 0 + sm: 8px + md: 12px + card: 20px + panel: 24px + icon: 12px + pill: 9999px + +# ═══════════════════════════════════════════════════════════════════ +# ESPACEMENT — grille 4pt (multiples de 4 ou 8 exclusivement) +# ═══════════════════════════════════════════════════════════════════ +spacing: + "0": 0 + "1": 4px + "2": 8px + "3": 12px + "4": 16px + "5": 20px + "6": 24px + "7": 32px + "8": 40px + "9": 48px + "10": 64px + "11": 80px + "12": 120px + +# ═══════════════════════════════════════════════════════════════════ +# MOTION — animation = feedback fonctionnel, jamais décoratif +# ═══════════════════════════════════════════════════════════════════ +motion: + duration: + fast: 120ms # micro-interactions (hover, focus) + base: 200ms # transitions UI standard + slow: 320ms # navigation (modals, drawers) + easing: + default: "cubic-bezier(0.4, 0, 0.2, 1)" # matériel, doux + emphasis: "cubic-bezier(0.2, 0.8, 0.2, 1)" # rebond léger + +# ═══════════════════════════════════════════════════════════════════ +# DENSITÉ — 3 modes adaptables par préférence user +# ═══════════════════════════════════════════════════════════════════ +density: + comfortable: + rowHeight: 44px + inputHeight: 40px + paddingX: 16px + paddingY: 12px + cozy: + rowHeight: 36px + inputHeight: 36px + paddingX: 12px + paddingY: 8px + compact: + rowHeight: 28px + inputHeight: 30px + paddingX: 8px + paddingY: 4px + +# ═══════════════════════════════════════════════════════════════════ +# COMPOSANTS — extraits clé. Liste exhaustive : @managemate/react +# ═══════════════════════════════════════════════════════════════════ +components: + button-primary: + backgroundColor: "{colors.primary}" + textColor: "{colors.neutral-0}" + typography: "{typography.body-sm}" + fontWeight: 600 + rounded: "{rounded.pill}" + padding: "10px 22px" + minHeight: 40px + + button-tonal: + backgroundColor: "{colors.synapse-50}" + textColor: "{colors.synapse-800}" + typography: "{typography.body-sm}" + fontWeight: 600 + rounded: "{rounded.pill}" + padding: "10px 22px" + + button-ghost: + backgroundColor: transparent + textColor: "{colors.neutral-700}" + typography: "{typography.body-sm}" + fontWeight: 600 + + card: + backgroundColor: "{colors.neutral-0}" + rounded: "{rounded.card}" + padding: "{spacing.6}" + borderColor: "{colors.neutral-200}" + + input: + backgroundColor: "{colors.neutral-0}" + textColor: "{colors.neutral-900}" + borderColor: "{colors.neutral-200}" + rounded: "{rounded.md}" + padding: "10px 14px" + minHeight: 40px + + badge: + backgroundColor: "{colors.neutral-150}" + textColor: "{colors.neutral-700}" + typography: "{typography.body-xs}" + fontWeight: 600 + rounded: 6px + padding: "2px 8px" + + toast: + backgroundColor: "{colors.neutral-0}" + borderColor: "{colors.neutral-200}" + rounded: 14px + padding: "14px 14px 14px 16px" + + tile: + backgroundColor: "{colors.neutral-0}" + borderColor: "{colors.neutral-200}" + rounded: "{rounded.card}" + padding: "{spacing.6}" +--- + +# DSMMG — Design System ManageMate Group + +> **Version 0.2** · La source de vérité visuelle, comportementale et accessible pour les produits ManageMate (Synapse, HRTime, Forge, Orbit, MSLM, Espace-Client, sites publics). + +## Overview + +Le DSMMG est un design system **headless-first** construit sur Radix UI. Trois mots : + +- **Cohérence** — un bouton dans n'importe quel produit ManageMate a la même structure et la même couleur de base. La différenciation se fait par contenu, pas par couleur. +- **Accessibilité** — RGAA 4.1 / WCAG 2.2 AA non-négociable. Validé `axe-core` en CI. Plusieurs clients (collectivités, opérateurs publics) sont soumis au RGAA par la loi. +- **Theming utilisateur** — 9 presets accent (rose Synapse par défaut), chaque utilisateur choisit dans ses préférences. La sémantique (success/danger/warning/info) reste fixe. + +## Colors + +Trois couches verticales : + +``` +primitives → semantic → accent (user-themable) +``` + +1. **Primitives** — rampes brutes (`neutral-0..900`, `synapse-50..900`, et 8 presets). Ne JAMAIS référencer directement dans les composants. +2. **Sémantiques** — `bg-page`, `text-primary`, `border`, `success/warning/danger/info`. **Stables, ne changent pas avec l'accent user.** +3. **Accent** — `--mmg-color-accent-*`. Posé par `[data-mmg-accent=""]` sur ``. SEUL token couleur user-themable. + +### Presets accent disponibles + +`synapse` (défaut), `rose`, `blue`, `violet`, `green`, `amber`, `red`, `cyan`, `slate`. + +Chaque preset a sa version dark adaptée (saturation -2pts, luminosité +3pts) pour confort visuel. + +### Règle absolue + +- ❌ **Aucun hex en dur dans les composants.** +- ❌ **Jamais de `--mmg-color-synapse-*` direct** dans un composant — toujours via `--mmg-color-accent-*`. + +## Typography + +**Figtree** partout (Google Fonts, sans-serif géométrique). 3 échelles selon contexte : + +| Famille | Cas d'usage | Tailles | +|---|---|---| +| **Display** | Hero des landings produits (HRTime, Synapse…) | 36px → 72px | +| **Headlines** | Apps métier (h1-h6 sémantiques) | 15px → 36px | +| **Body** | Texte courant et UI | 11px → 17px | +| **Auxiliaires** | eyebrow, lead, overline, caption | 11px → 20px | + +**Modificateurs** : `mono`, `tabular`, `balance` (titres), `pretty` (body), `italic`, `emphasis` (italique + accent), `highlight`, `underline`, `strike`, `gradient`, `rainbow`. + +> **Choisir le tag (`as`) selon la SÉMANTIQUE, pas selon la taille.** Un titre de page reste `

` même si visuellement il s'affiche en `display-xl`. + +## Layout & Spacing + +Grille **4 points** stricte. Multiples de 4 ou 8 uniquement. Aucune valeur intermédiaire (10, 14, 22) qui casse l'alignement vertical. + +12 niveaux : `0` (0) → `12` (120px). + +**Densité** adaptable par utilisateur via `[data-mmg-density="comfortable|cozy|compact"]`. Touch target minimum **44×44** quel que soit le mode (WCAG SC 2.5.5). + +## Elevation & Depth + +Light mode : +- `shadow-1` — 0 1px 4px ink + 1px ring +- `shadow-2` — 0 4px 16px ink + 1px ring +- `shadow-3` — 0 12px 32px ink (modals, dropdowns) +- `shadow-elevated` — neutre, pour boutons elevated + +Dark mode : +- Ombres = noir + halo blanc subtil 4-6 % (jamais "noir s'évapore") +- backdrop-filter blur 12-14px sur overlays/popovers/toasts pour effet verre dépoli + +Ombres teintées accent via `color-mix(in srgb, var(--mmg-color-accent) X%, transparent)` — s'adaptent automatiquement au preset user. + +## Shapes + +Pill par défaut sur **interactifs** (buttons, inputs, badges-pills) et **conteneurs principaux** (Tile, Card, Hero). + +| Token | Valeur | Usage | +|---|---|---| +| `rounded-sm` | 8px | inputs, badges-discrets | +| `rounded-md` | 12px | cards compact, popover, menu | +| `rounded-card` | 20px | cards principales, tiles | +| `rounded-panel` | 24px | modals, sheets | +| `rounded-pill` | 9999px | boutons, badges-pills | + +## Motion + +Animation = **feedback fonctionnel**, jamais décoratif. Trois durées : + +- 120ms — micro-interactions (hover, focus, ripple) +- 200ms — transitions UI standard +- 320ms — navigation (modals, drawers, sheets) + +`prefers-reduced-motion: reduce` désactive tout (durée 0.001ms). WCAG SC 2.3.3 AAA. + +## Components + +Catalogue complet (~62 composants) dans `@managemate/react`. Les principaux : + +**Forms** : Button, Input, Textarea, Select, Combobox, Checkbox, Radio, Switch, Slider, ToggleGroup, FileUpload. + +**Layout** : Container, Section, Stack, Inline, Card, Tile, Hero. + +**Feedback** : Alert, Notice, Banner, Badge (avec dot indicator + pulse), Spinner, Skeleton, Toast (pile Sonner-style empilable). + +**Overlays** : Tooltip, Popover, Menu, Dialog, ConfirmDialog, Sheet (4 sides × 5 sizes), Drawer, HoverCard, ContextMenu — **tous Radix-backed**. + +**Navigation** : Header (mega-menu DSFR-style), Footer, Breadcrumb, Tabs, Pagination, AppShell, Sidebar, Topbar, SkipLink. + +**Profile & Cards** : Avatar (status indicator + auto-color), AvatarGroup, UserCard, ProfileHeader (cover + débord), MetricCard (KPI avec trend), PricingCard, FeatureCard, Stat. + +**Article** : ArticlePage, ArticleHeader, ArticleAside, ArticleFooter, ArticleCallout, ArticleTOC. + +**Theming** : ThemePicker (radiogroup avec navigation flèches/Home/End). + +## Do's and Don'ts + +### ✅ Do + +- Utiliser les **tokens sémantiques** (`--mmg-color-text-primary`, `--mmg-color-bg-surface`). +- Choisir le tag HTML selon **la sémantique**, pas selon la taille visuelle. +- Tester en clavier : Tab, Shift+Tab, Esc, flèches, Enter, Espace. +- Tester en zoom 200 % et reflow 320px. +- Tester avec `prefers-reduced-motion: reduce` activé. +- Préférer les composants Radix-backed (Tooltip, Menu, Dialog…) aux implémentations custom. +- Documenter le composant dans Storybook + MDX avant de le livrer. + +### ❌ Don't + +- **Aucun hex en dur** dans les composants. +- **Aucune référence directe** à `--mmg-color-synapse-*` — toujours via `--mmg-color-accent-*`. +- **Pas de couleur seule** porteuse d'info (RGAA 9). Toujours redonder avec icône, texte ou pattern. +- **Pas de placeholder** en remplacement de label (RGAA 11.1). +- **Pas de focus invisible** ni `outline: none` sans alternative. +- **Pas de `
`** au lieu de ` +``` + +### React (recommandé) + +```tsx +import "@managemate/css"; +import "@managemate/icons"; +import { Button, Hero, Header, Footer } from "@managemate/react"; + + +``` + +## Composants v0.1 + +| Catégorie | Composants | +|---|---| +| **Layout** | Container, Section, Stack, Inline, Card, Tile, Hero, Grid (`.mmg-col-*`) | +| **Boutons** | Button (6 variants × 5 sizes, icon, loading, block) | +| **Forms** | Field, Input, Textarea, Select, Checkbox, Radio, Switch | +| **Feedback** | Alert, Notice, Badge, Modal, ToastRegion, Spinner, Skeleton | +| **Chrome** | Header, Footer, Breadcrumb, Sidebar, Topbar, Tabs, Pagination, AppShell, Avatar, Stat, SkipLink | +| **Icônes** | 49 icônes via `mmg-icon-` | + +## Tokens + +Tous les tokens sont des CSS custom properties préfixées `--mmg-*`. Light + dark mode via `[data-mmg-theme]`. + +**Couleur de marque** : rose `#D12B6A` corporate, partagée par tous les produits. + +## TODO v0.2 + +- [ ] Tooltip +- [ ] Stepper +- [ ] DatePicker +- [ ] DataTable avancée (tri, filtres, pagination intégrée) +- [ ] Combobox / Autocomplete +- [ ] FileUpload +- [ ] CommandMenu (cmd+k) +- [ ] Storybook +- [ ] Tests visuels +- [ ] Variants line/fill pour toutes les icônes (Remix Icon) +- [ ] Détection Wappalyzer (PR sur webappanalyzer) + +## Wappalyzer + +Pour la détection automatique : +1. Ajouter `` dans le `` des sites. +2. Ouvrir une PR sur https://github.com/enthec/webappanalyzer avec un fichier qui matche `class*="mmg-"` + le meta tag. + +## Licence + +Privée — usage interne ManageMate Group uniquement. diff --git a/demo/index.html b/demo/index.html new file mode 100644 index 0000000..82c8df1 --- /dev/null +++ b/demo/index.html @@ -0,0 +1,13 @@ + + + + + + DSMMG — ManageMate Design System + + + +
+ + + diff --git a/demo/package.json b/demo/package.json new file mode 100644 index 0000000..765ca7f --- /dev/null +++ b/demo/package.json @@ -0,0 +1,25 @@ +{ + "name": "demo", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@managemate/css": "workspace:*", + "@managemate/icons": "workspace:*", + "@managemate/react": "workspace:*", + "react": "^19.2.5", + "react-dom": "^19.2.5" + }, + "devDependencies": { + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^6.0.1", + "typescript": "~6.0.2", + "vite": "^8.0.10" + } +} diff --git a/demo/src/App.tsx b/demo/src/App.tsx new file mode 100644 index 0000000..0e02a9e --- /dev/null +++ b/demo/src/App.tsx @@ -0,0 +1,1853 @@ +import { useMemo, useState } from "react"; +import { + Header, Footer, Hero, Container, Section, Stack, Inline, + Card, Tile, Button, Notice, Alert, Badge, Modal, Input, Select, + Checkbox, Switch, Tabs, Stat, Avatar, + Icon, Spinner, IconBlock, + Stepper, Accordion, Tooltip, Tag, Progress, + Highlight, Quote, Callout, Banner, FileUpload, SearchBar, + DataTable, type DataTableColumn, + CommandMenu, useCommandMenu, type Command, + DatePicker, DateRangePicker, type DateRange, + ToastProvider, useToast, + EmptyState, + SegmentedControl, DescriptionList, Sparkline, Kbd, + Pictogram, + ArticlePage, ArticleHeader, ArticleAside, ArticleFooter, ArticleCallout, ArticleTOC, + ThemePicker, TooltipProvider, Popover, Dialog, ConfirmDialog, + Sheet, HoverCard, ContextMenu, Slider, ToggleGroup, + AvatarGroup, UserCard, ProfileHeader, MetricCard, PricingCard, FeatureCard, + Text, Display, Eyebrow, Lead, + type HeaderNavItem, +} from "@managemate/react"; +import iconsData from "../../packages/icons/dist/icons.json"; +const iconNames = iconsData as string[]; + +type Employee = { + id: number; + nom: string; + poste: string; + contrat: "CDI" | "CDD" | "Stage"; + entreeLe: string; + statut: "actif" | "absent" | "conge"; + salaire: number; +}; + +const EMPLOYEES: Employee[] = [ + { id: 1, nom: "Lohann Bouveresse", poste: "CEO", contrat: "CDI", entreeLe: "2018-04-01", statut: "actif", salaire: 95000 }, + { id: 2, nom: "Marie Dupont", poste: "Lead Developer", contrat: "CDI", entreeLe: "2020-09-14", statut: "actif", salaire: 72000 }, + { id: 3, nom: "Jean Martin", poste: "Designer", contrat: "CDI", entreeLe: "2021-02-22", statut: "absent", salaire: 54000 }, + { id: 4, nom: "Sophie Bernard", poste: "Product Manager", contrat: "CDI", entreeLe: "2022-06-01", statut: "actif", salaire: 68000 }, + { id: 5, nom: "Thomas Legrand", poste: "DevOps", contrat: "CDI", entreeLe: "2023-01-10", statut: "actif", salaire: 64000 }, + { id: 6, nom: "Emma Rousseau", poste: "QA Engineer", contrat: "CDD", entreeLe: "2024-09-01", statut: "conge", salaire: 48000 }, + { id: 7, nom: "Lucas Martin", poste: "Junior Dev", contrat: "Stage", entreeLe: "2025-09-01", statut: "actif", salaire: 13000 }, + { id: 8, nom: "Camille Moreau", poste: "Sales", contrat: "CDI", entreeLe: "2019-11-03", statut: "actif", salaire: 58000 }, +]; + +function AppInner() { + const [open, setOpen] = useState(false); + const [tab, setTab] = useState("apercu"); + const [theme, setTheme] = useState<"light" | "dark">("light"); + const [showAccentPanel, setShowAccentPanel] = useState(false); + const [confirmOpen, setConfirmOpen] = useState(false); + const [sheetOpen, setSheetOpen] = useState(false); + const [sheetSide, setSheetSide] = useState<"right" | "left" | "top" | "bottom">("right"); + const [volume, setVolume] = useState([62]); + const [priceRange, setPriceRange] = useState([800, 2400]); + const [viewMode, setViewMode] = useState("list"); + const [filters, setFilters] = useState(["actif"]); + const [iconFilter, setIconFilter] = useState(""); + const [stepperStep, setStepperStep] = useState(2); + const [selectedRows, setSelectedRows] = useState<(string | number)[]>([]); + const [date, setDate] = useState(null); + const [range, setRange] = useState({ start: null, end: null }); + const [period, setPeriod] = useState<"day" | "week" | "month" | "year">("month"); + const [view, setView] = useState<"grid" | "list">("grid"); + const cmd = useCommandMenu(); + const { toast } = useToast(); + + const toggleTheme = () => { + const next = theme === "light" ? "dark" : "light"; + setTheme(next); + document.documentElement.dataset.mmgTheme = next; + }; + + const filteredIcons = iconNames.filter((n) => + n.includes(iconFilter.toLowerCase()), + ); + + const columns: DataTableColumn[] = useMemo(() => [ + { + key: "nom", + header: "Collaborateur", + sortable: true, + cell: (r) => ( + + s[0]).join("")} size="sm" /> + {r.nom} + + ), + }, + { key: "poste", header: "Poste", sortable: true }, + { + key: "contrat", + header: "Contrat", + sortable: true, + cell: (r) => {r.contrat}, + }, + { + key: "entreeLe", + header: "Entrée", + sortable: true, + cell: (r) => new Date(r.entreeLe).toLocaleDateString("fr-FR"), + }, + { + key: "statut", + header: "Statut", + sortable: true, + cell: (r) => { + const map = { actif: "success", absent: "danger", conge: "warning" } as const; + const label = { actif: "Actif", absent: "Absent", conge: "En congé" } as const; + return {label[r.statut]}; + }, + }, + { + key: "salaire", + header: "Salaire annuel", + sortable: true, + align: "right", + cell: (r) => r.salaire.toLocaleString("fr-FR") + " €", + }, + ], []); + + const commands: Command[] = useMemo(() => [ + { id: "home", label: "Aller à l'accueil", icon: "home-4-line", group: "Navigation", shortcut: ["G", "H"], onSelect: () => setTab("apercu") }, + { id: "tab-buttons", label: "Voir les boutons", icon: "checkbox-circle-line", group: "Navigation", onSelect: () => setTab("boutons") }, + { id: "tab-forms", label: "Voir les formulaires", icon: "edit-line", group: "Navigation", onSelect: () => setTab("forms") }, + { id: "tab-data", label: "Voir le tableau de données", icon: "dashboard-line", group: "Navigation", onSelect: () => setTab("data") }, + { id: "tab-icons", label: "Voir les icônes", icon: "magic-line", group: "Navigation", onSelect: () => setTab("icons") }, + { id: "tab-iconblocks", label: "Voir les IconBlocks", icon: "palette-line", group: "Navigation", onSelect: () => setTab("iconblocks") }, + { id: "theme-toggle", label: "Basculer le thème clair / sombre", icon: theme === "light" ? "moon-line" : "sun-line", group: "Préférences", shortcut: ["⌘", "T"], onSelect: toggleTheme }, + { id: "modal", label: "Ouvrir une modale d'exemple", icon: "error-warning-line", group: "Démo", onSelect: () => setOpen(true) }, + { id: "toast-success", label: "Toast — succès", icon: "checkbox-circle-line", group: "Démo", onSelect: () => toast({ title: "Modifications sauvegardées", description: "Les 3 collaborateurs sélectionnés ont été mis à jour.", severity: "success" }) }, + { id: "toast-info", label: "Toast — info", icon: "information-line", group: "Démo", onSelect: () => toast({ title: "Maintenance prévue dimanche", severity: "info", action: { label: "En savoir plus", onClick: () => alert("doc") } }) }, + { id: "toast-error", label: "Toast — erreur", icon: "error-warning-line", group: "Démo", onSelect: () => toast({ title: "Échec de la synchronisation", description: "Vérifiez votre connexion réseau.", severity: "danger", duration: 0 }) }, + ], [theme, toast]); + + return ( + <> + + DSMMG v0.2 — Refonte tokens (--mmg-color-*), 9 presets accent user-themable, overlays Radix, Storybook, Style Dictionary, doc Starlight. ⌘ K pour la palette. + + +
+ + + + + } + /> + + + + + + } + /> + +
+ + 0 ? `(${selectedRows.length})` : ""}` }, + { id: "dates", label: "Dates" }, + { id: "icons", label: `Icônes (${iconNames.length / 2})` }, + { id: "iconblocks", label: "IconBlocks" }, + { id: "extras", label: "Extras" }, + { id: "article", label: "Article" }, + { id: "modern", label: "Sheet · HoverCard · Slider" }, + { id: "cards", label: "Cards & Profile" }, + { id: "typo", label: "Typographie" }, + ]} + /> + + {tab === "apercu" && ( + +
+

Que souhaitez-vous faire aujourd'hui ?

+

+ Les actions les plus fréquentes sur votre espace ManageMate. +

+
+
+
+
+
+
+ +

Tuiles cliquables — 3 tailles

+

+ La même <Tile> en taille sm (au-dessus, dense), md (défaut) et lg (CTA pleine largeur, marketing). +

+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+ +
+ +

Activité — vue {period === "day" ? "quotidienne" : period === "week" ? "hebdomadaire" : period === "month" ? "mensuelle" : "annuelle"}

+ +
+
+
+ + +
+
Collaborateurs
+
1 247
+ +12 ce mois +
+ +
+ +
+
+
+ + +
+
SLA respecté
+
98%
+ +2 pts +
+ +
+ +
+
+
+ + +
+
MRR
+
32 K€
+ +8.2% +
+ +
+ +
+
+
+ + +
+
Alertes ouvertes
+
3
+ 2 critiques +
+ +
+ +
+
+
+
+ +
+

Suite ManageMate

+

+ Quatre produits, un seul écosystème. Pictogrammes 80×80 dédiés. +

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+

Capacités transverses

+

+ Ce qui distingue chaque produit ManageMate. +

+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + + Voir le changelog + + } + /> +
+ )} + + {tab === "boutons" && ( + + +
VariantesInspiré Material 3 (tonal, elevated) + Fluent 2 (subtle).
+ + + + + + + + + + +
+ +
Tailles & formesPill par défaut · `square` pour radius modéré (DSFR/Fluent).
+ + + + + + + + + + + + +
+ + Avec icône / loading + + + + + + +
+ )} + + {tab === "forms" && ( + +
+
+ + Connexion + + + + + + + +
+
+ + Profil + + + + + +
+
+ + Recherche & upload + + + + + +
+ )} + + {tab === "feedback" && ( + + Maintenance prévue dimanche 7 mai de 2h à 4h. + Vos modifications ont bien été enregistrées. + Votre quota approche des 90%. + Impossible de joindre le serveur. + + + Cohérence d'écosystème. Le DSMMG garantit que vos collaborateurs retrouvent les mêmes patterns sur tous les produits ManageMate. + + + Les utilisateurs passent la majorité de leur temps sur d'autres sites. Ils s'attendent à ce que le vôtre fonctionne comme ceux-là. + + + + EmptyState (état vide) + Ajouter un collaborateur} + secondaryAction={} + /> + + + + + ToastProvider — pile empilable façon Sonner + Survolez la pile pour la déployer. Pause des timers au hover/focus, reprise à la sortie. + + + + + + + + + + + + + Tooltip — auto-positionnement + + + + + + + + + + + + + + + + + + Nouveau + En ligne + En attente + Échec + Beta + Pro + + + Sans action + {}} icon="filter-3-line">Filtre + {}} selected icon="check-line">Sélectionné + + + + + + + + + + + + + )} + + {tab === "navigation" && ( + + + Stepper + + + + + + + +
Foire aux questionsLe DSMMG en quelques questions essentielles.
+ +

Le Design System ManageMate Group fournit une bibliothèque de composants visuels et d'interactions partagés par tous nos produits. Objectif : qu'un utilisateur de ManageMate Paie retrouve les mêmes patterns dans ManageMate SIRH ou Plannings — moins d'apprentissage, plus de confiance.

+
+ +

Importez @managemate/css et @managemate/icons, puis utilisez les composants @managemate/react. Toutes les classes sont préfixées mmg- pour éviter les conflits avec d'autres bibliothèques (Tailwind, Bootstrap…).

+
+ +

Oui. Tous les composants sont conçus pour respecter WCAG 2.1 AA : contraste minimum 4.5:1, focus visible (anneau rose 2px), navigation clavier complète, attributs ARIA appropriés, support des lecteurs d'écran.

+
+ +

Les tokens CSS sont surchargeables : redéfinissez --mmg-color-accent et ses variantes (--mmg-color-accent-soft, --mmg-color-accent-strong) dans un sélecteur racine de votre app. Mais nous recommandons de garder le rose corporate pour préserver l'identité d'écosystème.

+
+ +

Via l'attribut data-mmg-theme="light|dark" sur l'élément <html>. Sans attribut, le DS suit la préférence système de l'utilisateur. Tous les tokens couleurs ont une variante dark validée WCAG AA.

+
+ +

Ouvrez une issue sur le repo interne managemate-ds avec un cas d'usage concret. Si plusieurs produits expriment le besoin, le composant rejoint la roadmap. Évitez les composants ad-hoc dans vos apps : préférez une PR sur le DS.

+
+
+
+ )} + + {tab === "data" && ( + + + {selectedRows.length > 0 ? ( + <> + + + + ) : ( + <> + + + + + )} + + } + /> + + )} + + {tab === "dates" && ( +
+
+ + DatePicker + + + d < new Date()} + /> + + +
+
+ + DateRangePicker + + + {range.start && range.end && ( + {Math.ceil((range.end.getTime() - range.start.getTime()) / (1000 * 60 * 60 * 24)) + 1} jour(s) sélectionné(s) + )} + + +
+
+ )} + + {tab === "icons" && ( + + +
+ Icônes Remix ({iconNames.length / 2} × 2 variants) + Classes mmg-icon-<name>-line et -fill +
+ setIconFilter(e.target.value)} + prefixIcon="search-2-line" + style={{ minWidth: 280 }} + /> +
+ {filteredIcons.length === 0 ? ( + setIconFilter("")}>Réinitialiser} + /> + ) : ( +
+ {filteredIcons.map((n) => ( +
+ +
{n}
+
+ ))} +
+ )} +
+ )} + + {tab === "article" && ( + + + Lecture 6 min + Par Marie Dupont, Lead Platform + 28 avril 2026 + + } + /> + } + aside={ + + + + + + + + + + } + footer={ + + } + > +

+ Quand j'ai rejoint l'équipe en septembre 2024, la CI mettait 14 minutes entre le moment où une PR était poussée et celui où elle était mergeable. Sur une équipe de 18 développeurs qui pousse en moyenne 30 PR par jour, ça représente 7 heures de temps machine quotidien et un coût d'attente humain difficile à chiffrer mais réel : context-switching, perte de flow, frustration. +

+ + + En 18 mois on est passé de 14 min à 3 min 20. Les gains : Turborepo (-40%), tests parallélisés sur 8 workers (-25%), suppression du linter en CI au profit du pre-commit hook (-15%). Ce qui n'a rien changé : migration vers Bun (gain marginal), Docker layer caching (cassé en pratique). + + +

Le contexte : pourquoi c'était bloquant

+

+ Notre produit est un monorepo de 84 packages, environ 320 000 lignes de TypeScript. Tout le monde dépend de tout le monde — bibliothèque UI, hooks partagés, types métier. La moindre PR déclenchait : +

+
    +
  • Install des dépendances (3 min)
  • +
  • Build complet du monorepo (5 min)
  • +
  • Tests unitaires (4 min)
  • +
  • Linter + type-check (1 min)
  • +
  • Déploiement preview (1 min)
  • +
+

+ Chaque étape était séquentielle. La plupart du travail effectué était inutile : on rebuildait des packages qui n'avaient pas changé depuis trois mois. +

+ +

Diagnostic : où passait le temps

+

+ Premier réflexe : mesurer. On a instrumenté la CI avec des spans OpenTelemetry sur chaque étape. La répartition réelle du temps était surprenante. +

+ + L'équipe pensait que l'install était le bottleneck. En réalité c'était le build, qui prenait 38% du temps total. Sans mesure, on aurait optimisé la mauvaise chose pendant 3 mois. + + +

Les six décisions qui ont fait la différence

+

1. Migration vers Turborepo (gain : -5 min 40)

+

+ Turborepo invalide intelligemment le cache au niveau du package. Une PR qui ne touche que le package @app/billing ne déclenche que son build et celui des packages qui en dépendent. Sur 84 packages, on rebuildait en moyenne 6 packages par PR, contre 84 avant. +

+ +

3. Tests parallélisés sur 8 workers (gain : -3 min 30)

+

+ Vitest peut paralléliser sur N workers via --reporter=verbose --pool=threads. Le sweet spot pour notre runner GitHub Actions ubuntu-latest-4core est 6 workers — au-delà, l'overhead d'orchestration grignote les gains. +

+ +

5. Suppression du linter en CI

+

+ Décision controversée. On a déplacé ESLint en pre-commit hook côté local (via husky + lint-staged). La CI ne fait plus que le type-check (qui est strictement nécessaire et ne peut pas tourner localement sans contexte). +

+
+ Si un dev pousse du code non-linté, c'est un problème de discipline d'équipe, pas un problème à 1 minute par PR pour les 17 autres. +
+ +

Ce qui n'a rien changé (et qu'on pensait magique)

+
    +
  • Migration vers Bun : -3 secondes sur l'install. Pas significatif vu le risque.
  • +
  • Docker layer caching : marche en théorie, cassé en pratique sur GitHub Actions à cause du cache éphémère entre runners.
  • +
  • Self-hosted runners : 2× plus rapides mais 5× plus chers en ops. ROI négatif pour notre taille.
  • +
+ + + Sur les 6 décisions appliquées, 3 ont eu un impact significatif (>3 min de gain) et 3 ont été des déceptions (<30 sec). Sans mesure préalable et postérieure systématique, on aurait perdu des semaines d'ingénierie. + + +

Résultats mesurés

+

Trois métriques suivies en continu depuis le début du chantier :

+
    +
  • P50 du temps de CI : 14:023:20 (-76%)
  • +
  • P95 (cas pathologiques) : 22:185:45
  • +
  • Taux de re-runs flaky : 11% → 1.2% (gros effet de bord positif)
  • +
+

+ Au-delà de la performance pure, la satisfaction de l'équipe s'est nettement améliorée : enquête interne trimestrielle, item "satisfaction CI" passée de 4.2/10 à 8.7/10. +

+ +

Et maintenant ?

+

+ On continue à mesurer. Les prochaines pistes : tests d'intégration sur Playwright qui prennent encore 1 min 40 — possiblement parallélisables sur des shards. Et un système de preview deploys partagés pour éviter de redéployer une preview pour chaque commit quand l'UI n'a pas bougé. +

+

+ Si vous travaillez sur un monorepo et que votre CI prend plus de 10 minutes, c'est probablement votre plus grand levier de productivité d'équipe. Mesurez avant d'optimiser. Investissez sur les bons gains. +

+
+
+ )} + + {tab === "extras" && ( + + + +
+ SegmentedControl + Choix exclusif court — Apple HIG. Préférable au Radio quand 3-5 options et espace horizontal disponible. +
+
+ + + + {}} + /> + +
+ + + +
+ DescriptionList + Pattern clé-valeur structuré. Sémantique <dl>/<dt>/<dd> — natif a11y. +
+
+ + VF33CNFUC84063345 }, + { label: "Date de 1ère immatriculation", value: "19/04/2005" }, + { label: "Date de l'immatriculation", value: "14/06/2025" }, + { label: "Statut", value: Actif sans gage }, + ]} + /> + +
+ + + +
+ Sparkline + Micro-graphe inline pour stat cards. SVG pur, accessible (rôle img + aria-label). +
+
+ + + Effectifs : 1 247 + + + + SLA : 98% + + + + Tickets : 14 + + + +
+ + + +
+ Kbd + Raccourcis clavier inline. Sémantique <kbd>. +
+
+

+ Appuyez sur + K pour ouvrir la palette de commandes. + Sauvegardez avec Ctrl + S. Naviguez avec et validez avec ↵ Entrée. +

+
+ + + +
+ Modal — focus trap actif + Ouvrez la modale et tabuler : le focus reste piégé à l'intérieur, retourne au bouton à la fermeture. +
+
+ + + +
+
+ )} + + {tab === "iconblocks" && ( + + +
IconBlock — variantes & couleursPattern Linear/Vercel : icône Remix sur fond coloré. Remplace les pictogrammes hand-codés.
+ +
+

Soft (défaut)

+ + + + + + + + +
+
+

Filled (CTA)

+ + + + + + + +
+
+

Gradient (premium)

+ + + + + + +
+
+

Tailles

+ + + + + + + +
+
+
+
+ )} + + {tab === "modern" && ( + + + +
+ Sheet — panneau latéral (Radix Dialog) + Glisse depuis un bord. Focus trap, scroll lock, restitution focus, Esc — tout natif. 4 côtés × 5 tailles. +
+
+ + v && setSheetSide(v as typeof sheetSide)} + items={[ + { value: "right", label: "Droite", icon: "arrow-right-line" }, + { value: "left", label: "Gauche", icon: "arrow-left-line" }, + { value: "top", label: "Haut", icon: "arrow-up-line" }, + { value: "bottom", label: "Bas", icon: "arrow-down-line" }, + ]} + /> + + + + +
+ + + +
+ HoverCard — preview riche au survol + Pour les fiches utilisateur, aperçus produit, métadonnées de lien. Hover-bridge gérée par Radix. +
+
+ + + @marie.dupont + + } + > + + +
+
Marie Dupont
+
Lead Developer · Synapse
+
+ Rejointe en sept. 2020. Lead frontend, mainteneuse du DSMMG. +
+
+ 184 commits + 23 reviews + 5 ans +
+
+
+
+ + Synapse v4.2.1 + } + > +
Synapse v4.2.1
+
Sortie le 24 avril 2026
+
    +
  • Fix : duplication de tickets sur conflit réseau
  • +
  • UX : raccourci Cmd+Shift+L pour archiver
  • +
  • Perf : DataTable +40% sur 10k rows
  • +
+
+
+
+ + + +
+ ContextMenu — clic droit + Menu contextuel. Clic droit sur la zone ci-dessous (ou long-press tactile). +
+
+ toast({ title: "Voir détail" }) }, + { label: "Modifier", icon: "edit-line", shortcut: "E", onSelect: () => toast({ title: "Modifier" }) }, + { label: "Dupliquer", icon: "file-copy-line", shortcut: "⌘D", onSelect: () => toast({ title: "Dupliqué" }) }, + { type: "divider" }, + { type: "label", label: "Visibilité" }, + { label: "Partager", icon: "share-line", onSelect: () => toast({ title: "Partagé" }) }, + { label: "Archiver", icon: "inbox-line", onSelect: () => toast({ title: "Archivé", severity: "info" }) }, + { type: "divider" }, + { label: "Supprimer", icon: "delete-bin-line", danger: true, shortcut: "⌫", onSelect: () => toast({ title: "Supprimé", severity: "danger" }) }, + ]} + > +
+ Clic droit ici +
+
+
+ + + +
+ Slider — sélecteur de valeur + Single (volume) ou range (fourchette de prix). Clavier : flèches, Page Up/Down, Home/End. +
+
+ +
+ + +
+
+ + +
+
+
+ + + +
+ ToggleGroup — single & multiple + Single = SegmentedControl. Multiple = filtres composables. Roving tabindex géré par Radix. +
+
+ +
+
Vue
+ v && setViewMode(v)} + items={[ + { value: "list", label: "Liste", icon: "menu-line" }, + { value: "grid", label: "Grille", icon: "apps-2-line" }, + { value: "kanban", label: "Kanban", icon: "stack-line" }, + { value: "calendar", label: "Calendrier", icon: "calendar-line" }, + ]} + /> +
+
+
Filtres (multiple)
+ +
+ Sélection : {filters.length === 0 ? "aucune" : filters.join(", ")} +
+
+
+
+
+ )} + + {tab === "cards" && ( + + + +
+ ProfileHeader + Cover image + avatar en débord. LinkedIn / GitHub pattern. +
+
+ + + + Disponible + + + + Owner DSMMG + + Frontend · React + Paris + + } + actions={ + <> + + + + } + stats={[ + { label: "Commits", value: "184" }, + { label: "Reviews", value: "23" }, + { label: "Tickets résolus", value: "412" }, + { label: "Ancienneté", value: "5 ans" }, + ]} + /> +
+ + + +
+ UserCard — différentes tailles + Card cliquable compacte. Avec status indicator + actions. +
+
+ + + + } + /> + + + + + } + /> + +
+ + + +
+ AvatarGroup — empilement avec overflow + Pattern Slack / Linear / GitHub. Hover pour identifier qui est qui. +
+
+ + + + 5 participants + + + + 12 reviewers + + + + + + + + + + + +
+ + + +
+ MetricCard — KPI dashboard + Valeur + delta coloré + tendance + sparkline. Pattern Linear / Vercel / Stripe Dashboard. +
+
+
+
+ } + /> +
+
+ +
+
+ +
+
+ +
+
+
+ + + +
+ FeatureCard — landing produit + Icône colorée + titre + description + lien. Variante "glow" pour bordures animées au hover (Vercel-style). +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ + + +
+ PricingCard — landing tarifs + 3 plans avec mise en avant du tier "Pro". Features avec check / cross. +
+
+
+
+ Démarrer l'essai} + /> +
+
+ Choisir Pro} + /> +
+
+ Contacter les sales} + /> +
+
+
+
+ )} + + {tab === "typo" && ( + + + +
+ Display — pages marketing / landing produits + 72px → 36px, extra-bold, letter-spacing serré. Pour les hero de HRTime / Synapse / Forge / Orbit. +
+
+ +
+ Display 2XL · 72px + Le SIRH simple, vraiment. +
+
+ Display XL · 60px + + Le temps de vos équipes, au cordeau. + +
+
+ Display LG · 48px + + Construit pour les équipes qui livrent. + +
+
+ Display MD · 36px + Sous-section marketing +
+
+
+ + + +
+ Headlines — apps métier + Hiérarchie h1 → h6 sémantique. Pour Synapse, HRTime app, Forge, Orbit, Espace-Client. +
+
+ + H1 — titre de page (36px) + H2 — section (30px) + H3 — sous-section (24px) + H4 — groupe / card title (20px) + H5 — sub-card (17px) + H6 — label fort (15px) + +
+ + + +
+ Body & auxiliaires + Tailles courantes pour le texte courant et les annotations. +
+
+ + + Body LG (17px) — pour les paragraphes de pages marketing aérées, + où l'utilisateur lit le texte sans contrainte de densité. + + + Body (15px, défaut) — texte courant, doc, articles. C'est la taille + qu'on devrait utiliser dans 80 % des cas dans une app. + + + Body SM (13px) — UI dense, hint sous un input, légende secondaire. + + + Body XS (11px) — métadonnées, footnotes, timestamps. À éviter pour le texte courant. + +
+ + Lead (20px) — chapô sous un Hero. Plus long que le titre, moins + long que le body principal. Souvent en text-secondary pour + laisser le titre dominer. + + + SIRH + Section overline + + + Caption (11px) — légende d'image, timestamp d'un message, "il y a 3 minutes". + +
+
+ + + +
+ Italique, emphase, surligneur + Pour mots étrangers, citations, mots-clefs sémantiquement à part. Sémantique : <em> sort italique automatiquement. +
+
+ + + Italique sobre : il faut savoir choisir ses combats. Le tag <em> natif sort en italique sans décoration supplémentaire. + + + Italique via prop : terme étranger, nom d'une œuvre, ou citation courte. + + + Emphase éditoriale (italique + accent) : vraiment nouveau, simple, cohérent. + + + Surligneur subtil : le mot-clef qui compte dans un paragraphe long. + + + Souligné fort : fonctionnalité critique pour focus l'œil. + + + Barré (prix, élément déprécié) : 49 € / mois 29 € / mois. + + +
+ + + +
+ Modificateurs décoratifs (à dose homéopathique) + Gradient et rainbow disponibles mais à utiliser parcimonieusement — un seul gradient par page, jamais de rainbow sur du texte courant. +
+
+ +
+ Gradient (accent → accent-strong) + Texte avec gradient +
+
+ Rainbow animé — un par page max + Réservé au hero principal +
+
+
+ + + +
+ Cas d'usage type — landing HRTime + Comment composer ces variantes pour une page produit. +
+
+
+ SIRH simple + + Le temps de vos équipes, au cordeau. + + + Plannings, congés, paie. Une seule plateforme, sans surprise. Connectez votre paie en 7 jours, sans data engineer. + + + + + +
+
+ + + +
+ Helpers raccourcis + Composants Display, Eyebrow, Lead = wrappers de Text avec defaults. +
+
+ + +{`SIRH simple +Le temps de vos équipes +Plannings, congés, paie. Une seule plateforme.`} + + +
+
+ )} +
+
+ + + + + + } + > + + + + = 0 && filtered[activeIndex] + ? `${id}-opt-${filtered[activeIndex].value}` + : undefined + } + value={query} + placeholder={placeholder} + onChange={(e) => { + setQuery(e.target.value); + setOpen(true); + setActiveIndex(-1); + }} + onFocus={() => setOpen(true)} + onBlur={() => setTimeout(() => setOpen(false), 100)} + onKeyDown={onKey} + /> + {open && ( +
{ + refs.setFloating(el); + listRef.current = el; + }} + id={`${id}-list`} + role="listbox" + className="mmg-menu mmg-combobox__list" + style={floatingStyles} + > + {filtered.length === 0 ? ( +
{emptyMessage}
+ ) : ( + filtered.map((o, i) => ( + + )) + )} +
+ )} +
+ ); +} diff --git a/packages/react/src/CommandMenu.tsx b/packages/react/src/CommandMenu.tsx new file mode 100644 index 0000000..13baca3 --- /dev/null +++ b/packages/react/src/CommandMenu.tsx @@ -0,0 +1,223 @@ +import { useEffect, useMemo, useRef, useState, type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type Command = { + id: string; + label: ReactNode; + /** Texte indexable pour la recherche (par défaut = label si string). */ + keywords?: string; + icon?: IconName; + group?: string; + shortcut?: string[]; // ex. ["⌘", "K"] + onSelect: () => void; +}; + +export function CommandMenu({ + open, + onClose, + commands, + placeholder = "Tapez une commande ou un mot-clé…", + emptyMessage = "Aucun résultat. Essayez un autre mot.", +}: { + open: boolean; + onClose: () => void; + commands: Command[]; + placeholder?: string; + emptyMessage?: string; +}) { + const [query, setQuery] = useState(""); + const [activeIdx, setActiveIdx] = useState(0); + const inputRef = useRef(null); + const listRef = useRef(null); + + // Reset à l'ouverture + useEffect(() => { + if (open) { + setQuery(""); + setActiveIdx(0); + setTimeout(() => inputRef.current?.focus(), 50); + } + }, [open]); + + // ESC pour fermer + useEffect(() => { + if (!open) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape") onClose(); + }; + document.addEventListener("keydown", onKey); + return () => document.removeEventListener("keydown", onKey); + }, [open, onClose]); + + // Block scroll + useEffect(() => { + if (!open) return; + const prev = document.body.style.overflow; + document.body.style.overflow = "hidden"; + return () => { + document.body.style.overflow = prev; + }; + }, [open]); + + const filtered = useMemo(() => { + const q = query.trim().toLowerCase(); + if (!q) return commands; + return commands.filter((c) => { + const txt = ( + (typeof c.label === "string" ? c.label : "") + + " " + + (c.keywords ?? "") + + " " + + (c.group ?? "") + ).toLowerCase(); + // Matching simple : tous les mots de q doivent être présents + return q.split(/\s+/).every((w) => txt.includes(w)); + }); + }, [commands, query]); + + // Groupes + const groups = useMemo(() => { + const map = new Map(); + for (const c of filtered) { + const g = c.group ?? "Commandes"; + if (!map.has(g)) map.set(g, []); + map.get(g)!.push(c); + } + return [...map.entries()]; + }, [filtered]); + + // Navigation clavier + useEffect(() => { + if (!open) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === "ArrowDown") { + e.preventDefault(); + setActiveIdx((i) => Math.min(filtered.length - 1, i + 1)); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + setActiveIdx((i) => Math.max(0, i - 1)); + } else if (e.key === "Enter") { + e.preventDefault(); + const cmd = filtered[activeIdx]; + if (cmd) { + cmd.onSelect(); + onClose(); + } + } + }; + document.addEventListener("keydown", onKey); + return () => document.removeEventListener("keydown", onKey); + }, [open, filtered, activeIdx, onClose]); + + // Scroll into view + useEffect(() => { + const el = listRef.current?.querySelector('[aria-selected="true"]'); + el?.scrollIntoView({ block: "nearest" }); + }, [activeIdx]); + + if (!open) return null; + + let runningIdx = 0; + + return ( +
{ + if (e.target === e.currentTarget) onClose(); + }} + > +
+
+ + { + setQuery(e.target.value); + setActiveIdx(0); + }} + placeholder={placeholder} + aria-label="Recherche" + /> + esc +
+ +
+ {filtered.length === 0 ? ( +
{emptyMessage}
+ ) : ( + groups.map(([group, items]) => ( +
+
{group}
+ {items.map((c) => { + const isActive = filtered[activeIdx]?.id === c.id; + const idx = runningIdx++; + return ( +
{ + c.onSelect(); + onClose(); + }} + onMouseEnter={() => setActiveIdx(filtered.indexOf(c))} + > + {c.icon && } + {c.label} + {c.shortcut && ( + + {c.shortcut.map((k, i) => ( + {k} + ))} + + )} +
+ ); + })} +
+ )) + )} +
+ +
+ + + naviguer + + + sélectionner + + + esc fermer + +
+
+
+ ); +} + +/** Hook pour ouvrir la palette via Cmd/Ctrl+K. */ +export function useCommandMenu() { + const [open, setOpen] = useState(false); + useEffect(() => { + const onKey = (e: KeyboardEvent) => { + if (e.key === "k" && (e.metaKey || e.ctrlKey)) { + e.preventDefault(); + setOpen((v) => !v); + } + }; + document.addEventListener("keydown", onKey); + return () => document.removeEventListener("keydown", onKey); + }, []); + return { open, setOpen, close: () => setOpen(false), toggle: () => setOpen((v) => !v) }; +} diff --git a/packages/react/src/ConfirmDialog.tsx b/packages/react/src/ConfirmDialog.tsx new file mode 100644 index 0000000..2fcdb59 --- /dev/null +++ b/packages/react/src/ConfirmDialog.tsx @@ -0,0 +1,65 @@ +import type { ReactNode } from "react"; +import { Dialog } from "./Dialog"; +import { Button } from "./Button"; + +export type ConfirmDialogProps = { + open: boolean; + onOpenChange: (open: boolean) => void; + title: ReactNode; + description?: ReactNode; + confirmLabel?: ReactNode; + cancelLabel?: ReactNode; + /** Variante destructive : bouton rouge. */ + destructive?: boolean; + onConfirm: () => void | Promise; + /** Affiche un loader pendant onConfirm. */ + loading?: boolean; +}; + +/** + * Boîte de dialogue de confirmation. Pattern destructive : confirm rouge, + * focus initial sur le bouton d'annulation (sécurité). Cf. heuristique + * Nielsen #5 : prevention of errors. + */ +export function ConfirmDialog({ + open, + onOpenChange, + title, + description, + confirmLabel = "Confirmer", + cancelLabel = "Annuler", + destructive, + onConfirm, + loading, +}: ConfirmDialogProps) { + return ( + + + + + } + > + {null} + + ); +} diff --git a/packages/react/src/ContextMenu.tsx b/packages/react/src/ContextMenu.tsx new file mode 100644 index 0000000..55cb438 --- /dev/null +++ b/packages/react/src/ContextMenu.tsx @@ -0,0 +1,68 @@ +import { type ReactNode } from "react"; +import * as RadixContextMenu from "@radix-ui/react-context-menu"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type ContextMenuItem = + | { + type?: "item"; + label: ReactNode; + icon?: IconName; + onSelect?: () => void; + danger?: boolean; + disabled?: boolean; + shortcut?: string; + } + | { type: "divider" } + | { type: "label"; label: ReactNode }; + +export type ContextMenuProps = { + /** Zone qui déclenche le menu au clic-droit / long-press. */ + children: ReactNode; + items: ContextMenuItem[]; +}; + +/** + * ContextMenu — menu contextuel au clic-droit (ou long-press tactile). + * + * Wrapper Radix : ouvre sur clic-droit, navigation flèches, type-ahead, + * Escape, focus management. Aucun appel a11y custom. + */ +export function ContextMenu({ children, items }: ContextMenuProps) { + return ( + + {children} + + + {items.map((item, i) => { + if (item.type === "divider") { + return ; + } + if (item.type === "label") { + return ( + + {item.label} + + ); + } + const { label, icon, onSelect, danger, disabled, shortcut } = item; + return ( + + {icon && } + {label} + {shortcut && {shortcut}} + + ); + })} + + + + ); +} + +export { RadixContextMenu as ContextMenuPrimitive }; diff --git a/packages/react/src/DataTable.tsx b/packages/react/src/DataTable.tsx new file mode 100644 index 0000000..8eba298 --- /dev/null +++ b/packages/react/src/DataTable.tsx @@ -0,0 +1,315 @@ +import { useMemo, useState, type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; +import { Pictogram, type PictogramName } from "./Pictogram"; +import { Button } from "./Button"; + +export type DataTableColumn = { + key: string; + header: ReactNode; + /** Accesseur ; par défaut row[key] */ + accessor?: (row: T) => unknown; + /** Render personnalisé ; par défaut texte */ + cell?: (row: T) => ReactNode; + /** Trie cliquable sur la colonne */ + sortable?: boolean; + /** Largeur CSS (ex. "120px", "1fr") */ + width?: string | number; + /** Alignement du contenu */ + align?: "left" | "right" | "center"; +}; + +type SortState = { key: string; dir: "asc" | "desc" } | null; + +export type DataTableProps = { + data: T[]; + columns: DataTableColumn[]; + /** Colonne identifiante (par défaut "id") */ + rowKey?: keyof T | ((row: T) => string | number); + /** Active la sélection multiple */ + selectable?: boolean; + selectedKeys?: (string | number)[]; + onSelectionChange?: (keys: (string | number)[]) => void; + /** Recherche dans toutes les colonnes */ + searchable?: boolean; + searchPlaceholder?: string; + /** Pagination cliente */ + pageSize?: number; + /** Densité des lignes */ + dense?: boolean; + /** État vide personnalisable */ + emptyTitle?: ReactNode; + emptyDescription?: ReactNode; + emptyPictogram?: PictogramName; + emptyAction?: ReactNode; + /** Loading */ + loading?: boolean; + /** Actions de la barre d'outils */ + toolbarActions?: ReactNode; + className?: string; + onRowClick?: (row: T) => void; +}; + +export function DataTable>({ + data, + columns, + rowKey = "id", + selectable, + selectedKeys, + onSelectionChange, + searchable, + searchPlaceholder = "Rechercher…", + pageSize, + dense, + emptyTitle = "Aucun résultat", + emptyDescription = "Aucun élément ne correspond à votre recherche.", + emptyPictogram = "search", + emptyAction, + loading, + toolbarActions, + className, + onRowClick, +}: DataTableProps) { + const [sort, setSort] = useState(null); + const [search, setSearch] = useState(""); + const [page, setPage] = useState(1); + + const getKey = (row: T): string | number => + typeof rowKey === "function" ? rowKey(row) : (row[rowKey as string] ?? ""); + + const accessor = (col: DataTableColumn, row: T) => + col.accessor ? col.accessor(row) : row[col.key]; + + const filtered = useMemo(() => { + if (!searchable || !search.trim()) return data; + const q = search.toLowerCase(); + return data.filter((row) => + columns.some((c) => { + const v = accessor(c, row); + return v != null && String(v).toLowerCase().includes(q); + }), + ); + }, [data, search, searchable, columns]); + + const sorted = useMemo(() => { + if (!sort) return filtered; + const col = columns.find((c) => c.key === sort.key); + if (!col) return filtered; + const sign = sort.dir === "asc" ? 1 : -1; + return [...filtered].sort((a, b) => { + const va = accessor(col, a); + const vb = accessor(col, b); + if (va == null) return 1; + if (vb == null) return -1; + if (typeof va === "number" && typeof vb === "number") return sign * (va - vb); + return sign * String(va).localeCompare(String(vb)); + }); + }, [filtered, sort, columns]); + + const pageCount = pageSize ? Math.max(1, Math.ceil(sorted.length / pageSize)) : 1; + const paged = pageSize + ? sorted.slice((page - 1) * pageSize, page * pageSize) + : sorted; + + const allKeys = paged.map(getKey); + const allSelected = allKeys.length > 0 && allKeys.every((k) => selectedKeys?.includes(k)); + const someSelected = !allSelected && allKeys.some((k) => selectedKeys?.includes(k)); + + const toggleAll = () => { + if (!onSelectionChange) return; + if (allSelected) { + onSelectionChange(selectedKeys?.filter((k) => !allKeys.includes(k)) ?? []); + } else { + onSelectionChange([...new Set([...(selectedKeys ?? []), ...allKeys])]); + } + }; + + const toggleOne = (k: string | number) => { + if (!onSelectionChange) return; + const set = new Set(selectedKeys ?? []); + set.has(k) ? set.delete(k) : set.add(k); + onSelectionChange([...set]); + }; + + const onSort = (col: DataTableColumn) => { + if (!col.sortable) return; + setSort((cur) => + cur?.key === col.key + ? cur.dir === "asc" + ? { key: col.key, dir: "desc" } + : null + : { key: col.key, dir: "asc" }, + ); + }; + + const showToolbar = searchable || toolbarActions || (selectable && (selectedKeys?.length ?? 0) > 0); + + return ( +
+ {showToolbar && ( +
+ {selectable && (selectedKeys?.length ?? 0) > 0 ? ( + + {selectedKeys?.length} sélectionné{(selectedKeys?.length ?? 0) > 1 ? "s" : ""} + + ) : searchable ? ( +
+ + { + setSearch(e.target.value); + setPage(1); + }} + /> +
+ ) : ( + + )} + {toolbarActions &&
{toolbarActions}
} +
+ )} + +
+ + + + {selectable && ( + + )} + {columns.map((col) => { + const isSorted = sort?.key === col.key; + return ( + + ); + })} + + + + {!loading && paged.length > 0 && ( + + {paged.map((row) => { + const k = getKey(row); + const selected = selectedKeys?.includes(k); + return ( + onRowClick(row) : undefined} + style={onRowClick ? { cursor: "pointer" } : undefined} + > + {selectable && ( + + )} + {columns.map((col) => ( + + ))} + + ); + })} + + )} +
+ { + if (el) el.indeterminate = someSelected; + }} + onChange={toggleAll} + aria-label="Tout sélectionner" + /> + onSort(col)} + style={{ + width: col.width, + textAlign: col.align, + }} + > + {col.header} + {col.sortable && ( + + + + )} +
e.stopPropagation()}> + toggleOne(k)} + aria-label={`Sélectionner ${k}`} + /> + + {col.cell ? col.cell(row) : String(accessor(col, row) ?? "—")} +
+ + {loading && ( +
+ + Chargement… +
+ )} + + {!loading && paged.length === 0 && ( +
+ +

{emptyTitle}

+

{emptyDescription}

+ {emptyAction} +
+ )} +
+ + {pageSize && pageCount > 1 && ( +
+ + Page {page} / {pageCount} — {sorted.length} résultat + {sorted.length > 1 ? "s" : ""} + +
+
+
+ )} +
+ ); +} diff --git a/packages/react/src/DatePicker.tsx b/packages/react/src/DatePicker.tsx new file mode 100644 index 0000000..7b18bd2 --- /dev/null +++ b/packages/react/src/DatePicker.tsx @@ -0,0 +1,241 @@ +import { + useEffect, + useId, + useMemo, + useRef, + useState, + type ReactNode, +} from "react"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; +import { Button } from "./Button"; + +const MONTHS = [ + "janvier", "février", "mars", "avril", "mai", "juin", + "juillet", "août", "septembre", "octobre", "novembre", "décembre", +]; +const WEEKDAYS = ["lun", "mar", "mer", "jeu", "ven", "sam", "dim"]; + +const fmt = (d: Date | null) => + d + ? d.toLocaleDateString("fr-FR", { + day: "2-digit", + month: "2-digit", + year: "numeric", + }) + : ""; + +const sameDay = (a: Date, b: Date) => + a.getFullYear() === b.getFullYear() && + a.getMonth() === b.getMonth() && + a.getDate() === b.getDate(); + +function buildMonthGrid(year: number, month: number) { + const first = new Date(year, month, 1); + // En France lundi = jour 0 + const startDay = (first.getDay() + 6) % 7; + const daysInMonth = new Date(year, month + 1, 0).getDate(); + const daysInPrev = new Date(year, month, 0).getDate(); + const cells: { date: Date; outside: boolean }[] = []; + + // Préfixe (mois précédent) + for (let i = startDay - 1; i >= 0; i--) { + cells.push({ date: new Date(year, month - 1, daysInPrev - i), outside: true }); + } + for (let d = 1; d <= daysInMonth; d++) { + cells.push({ date: new Date(year, month, d), outside: false }); + } + // Suffixe (mois suivant) + while (cells.length < 42) { + const idx = cells.length - (startDay + daysInMonth); + cells.push({ date: new Date(year, month + 1, idx + 1), outside: true }); + } + return cells; +} + +export type DatePickerProps = { + label?: ReactNode; + hint?: ReactNode; + error?: ReactNode; + value?: Date | null; + onChange?: (date: Date | null) => void; + required?: boolean; + disabled?: boolean; + /** Désactive certaines dates */ + isDisabled?: (date: Date) => boolean; + placeholder?: string; + className?: string; +}; + +export function DatePicker({ + label, + hint, + error, + value, + onChange, + required, + disabled, + isDisabled, + placeholder = "JJ/MM/AAAA", + className, +}: DatePickerProps) { + const id = useId(); + const [open, setOpen] = useState(false); + const [view, setView] = useState(() => value ?? new Date()); + const ref = useRef(null); + + useEffect(() => { + if (value) setView(value); + }, [value]); + + useEffect(() => { + if (!open) return; + const onClick = (e: MouseEvent) => { + if (!ref.current?.contains(e.target as Node)) setOpen(false); + }; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape") setOpen(false); + }; + document.addEventListener("mousedown", onClick); + document.addEventListener("keydown", onKey); + return () => { + document.removeEventListener("mousedown", onClick); + document.removeEventListener("keydown", onKey); + }; + }, [open]); + + const cells = useMemo( + () => buildMonthGrid(view.getFullYear(), view.getMonth()), + [view], + ); + const today = new Date(); + + return ( +
+ {label && ( + + )} +
+ !disabled && setOpen((v) => !v)} + onFocus={() => !disabled && setOpen(true)} + aria-haspopup="dialog" + aria-expanded={open} + /> + + + +
+ {error ? ( + {error} + ) : hint ? ( + {hint} + ) : null} + + {open && ( +
+
+ + + {MONTHS[view.getMonth()]} {view.getFullYear()} + + +
+ +
+ {WEEKDAYS.map((w) => ( +
{w}
+ ))} +
+ +
+ {cells.map(({ date, outside }, i) => { + const selected = value && sameDay(date, value); + const todayMatch = sameDay(date, today); + const dis = isDisabled?.(date) ?? false; + return ( + + ); + })} +
+ +
+ + +
+
+ )} +
+ ); +} diff --git a/packages/react/src/DateRangePicker.tsx b/packages/react/src/DateRangePicker.tsx new file mode 100644 index 0000000..602ba0d --- /dev/null +++ b/packages/react/src/DateRangePicker.tsx @@ -0,0 +1,248 @@ +import { useEffect, useId, useMemo, useRef, useState, type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; +import { Button } from "./Button"; + +const MONTHS = [ + "janvier", "février", "mars", "avril", "mai", "juin", + "juillet", "août", "septembre", "octobre", "novembre", "décembre", +]; +const WEEKDAYS = ["lun", "mar", "mer", "jeu", "ven", "sam", "dim"]; + +const fmt = (d: Date | null) => + d ? d.toLocaleDateString("fr-FR", { day: "2-digit", month: "2-digit", year: "numeric" }) : ""; +const sameDay = (a: Date, b: Date) => + a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate(); +const isBefore = (a: Date, b: Date) => a.getTime() < b.getTime(); +const isBetween = (d: Date, start: Date, end: Date) => + d.getTime() > start.getTime() && d.getTime() < end.getTime(); + +function buildMonthGrid(year: number, month: number) { + const first = new Date(year, month, 1); + const startDay = (first.getDay() + 6) % 7; + const daysInMonth = new Date(year, month + 1, 0).getDate(); + const daysInPrev = new Date(year, month, 0).getDate(); + const cells: { date: Date; outside: boolean }[] = []; + for (let i = startDay - 1; i >= 0; i--) { + cells.push({ date: new Date(year, month - 1, daysInPrev - i), outside: true }); + } + for (let d = 1; d <= daysInMonth; d++) { + cells.push({ date: new Date(year, month, d), outside: false }); + } + while (cells.length < 42) { + const idx = cells.length - (startDay + daysInMonth); + cells.push({ date: new Date(year, month + 1, idx + 1), outside: true }); + } + return cells; +} + +export type DateRange = { start: Date | null; end: Date | null }; + +export type DateRangePickerProps = { + label?: ReactNode; + hint?: ReactNode; + error?: ReactNode; + value?: DateRange; + onChange?: (range: DateRange) => void; + required?: boolean; + disabled?: boolean; + /** Désactive certaines dates (ex. dates passées). */ + isDisabled?: (date: Date) => boolean; + className?: string; +}; + +export function DateRangePicker({ + label, + hint, + error, + value = { start: null, end: null }, + onChange, + required, + disabled, + isDisabled, + className, +}: DateRangePickerProps) { + const id = useId(); + const [open, setOpen] = useState(false); + const [view, setView] = useState(() => value.start ?? new Date()); + const [hover, setHover] = useState(null); + const ref = useRef(null); + + useEffect(() => { + if (!open) return; + const onClick = (e: MouseEvent) => { + if (!ref.current?.contains(e.target as Node)) setOpen(false); + }; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape") setOpen(false); + }; + document.addEventListener("mousedown", onClick); + document.addEventListener("keydown", onKey); + return () => { + document.removeEventListener("mousedown", onClick); + document.removeEventListener("keydown", onKey); + }; + }, [open]); + + const cells = useMemo( + () => buildMonthGrid(view.getFullYear(), view.getMonth()), + [view], + ); + const today = new Date(); + + const handleClick = (date: Date) => { + if (!value.start || (value.start && value.end)) { + onChange?.({ start: date, end: null }); + } else if (isBefore(date, value.start)) { + onChange?.({ start: date, end: value.start }); + setOpen(false); + } else { + onChange?.({ start: value.start, end: date }); + setOpen(false); + } + }; + + const inRange = (d: Date) => { + if (!value.start) return false; + const end = value.end ?? hover; + if (!end) return false; + if (isBefore(end, value.start)) return isBetween(d, end, value.start); + return isBetween(d, value.start, end); + }; + + const display = value.start + ? value.end + ? `${fmt(value.start)} → ${fmt(value.end)}` + : `${fmt(value.start)} → …` + : ""; + + return ( +
+ {label && ( + + )} +
+ !disabled && setOpen((v) => !v)} + onFocus={() => !disabled && setOpen(true)} + aria-haspopup="dialog" + aria-expanded={open} + /> + + + +
+ {error ? ( + {error} + ) : hint ? ( + {hint} + ) : null} + + {open && ( +
+
+ + + {MONTHS[view.getMonth()]} {view.getFullYear()} + + +
+ +
+ {WEEKDAYS.map((w) => ( +
{w}
+ ))} +
+ +
+ {cells.map(({ date, outside }, i) => { + const isStart = value.start && sameDay(date, value.start); + const isEnd = value.end && sameDay(date, value.end); + const between = inRange(date); + const todayMatch = sameDay(date, today); + const dis = isDisabled?.(date) ?? false; + return ( + + ); + })} +
+ +
+ + +
+
+ )} +
+ ); +} diff --git a/packages/react/src/Dialog.test.tsx b/packages/react/src/Dialog.test.tsx new file mode 100644 index 0000000..2f3f95b --- /dev/null +++ b/packages/react/src/Dialog.test.tsx @@ -0,0 +1,64 @@ +import { describe, expect, it } from "vitest"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { axe } from "vitest-axe"; +import { useState } from "react"; +import { Dialog } from "./Dialog"; + +function Wrapped() { + const [open, setOpen] = useState(false); + return ( + <> + + +

Contenu

+
+ + ); +} + +describe("Dialog", () => { + it("est fermé par défaut", () => { + render(); + expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); + }); + + it("s'ouvre via setState", async () => { + const user = userEvent.setup(); + render(); + await user.click(screen.getByText("Ouvrir")); + expect(await screen.findByRole("dialog")).toBeInTheDocument(); + }); + + it("a un titre lié via aria-labelledby (Radix)", async () => { + const user = userEvent.setup(); + render(); + await user.click(screen.getByText("Ouvrir")); + const dialog = await screen.findByRole("dialog"); + expect(dialog).toHaveAccessibleName("Modifier l'utilisateur"); + }); + + it("se ferme avec Escape", async () => { + const user = userEvent.setup(); + render(); + await user.click(screen.getByText("Ouvrir")); + await screen.findByRole("dialog"); + await user.keyboard("{Escape}"); + // Radix retire le dialog après animation — on attend la disparition + await new Promise((r) => setTimeout(r, 0)); + expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); + }); + + it("a11y axe-core (ouvert)", async () => { + const user = userEvent.setup(); + const { container } = render(); + await user.click(screen.getByText("Ouvrir")); + await screen.findByRole("dialog"); + expect(await axe(container)).toHaveNoViolations(); + }); +}); diff --git a/packages/react/src/Dialog.tsx b/packages/react/src/Dialog.tsx new file mode 100644 index 0000000..b1ab106 --- /dev/null +++ b/packages/react/src/Dialog.tsx @@ -0,0 +1,72 @@ +import { type ReactNode } from "react"; +import * as RadixDialog from "@radix-ui/react-dialog"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; + +export type DialogProps = { + open: boolean; + onOpenChange: (open: boolean) => void; + title?: ReactNode; + description?: ReactNode; + children: ReactNode; + footer?: ReactNode; + /** Largeur max du contenu. */ + size?: "sm" | "md" | "lg" | "xl" | "full"; + /** Cache le bouton de fermeture en haut à droite. */ + hideClose?: boolean; + className?: string; +}; + +/** + * Dialog (modal) — wrapper Radix Dialog. + * + * Focus trap, Escape, scroll lock, restitution du focus à la fermeture, + * tout est géré par Radix. La sémantique est correcte (role="dialog", + * aria-modal, aria-labelledby/-describedby auto via Title/Description). + * + * Pour confirm/destructive, voir ConfirmDialog. + */ +export function Dialog({ + open, + onOpenChange, + title, + description, + children, + footer, + size = "md", + hideClose, + className, +}: DialogProps) { + return ( + + + + + {(title || !hideClose) && ( +
+ {title && {title}} + {!hideClose && ( + + + + )} +
+ )} + {description && ( + + {description} + + )} +
{children}
+ {footer &&
{footer}
} +
+
+
+ ); +} + +export { RadixDialog as DialogPrimitive }; diff --git a/packages/react/src/Drawer.tsx b/packages/react/src/Drawer.tsx new file mode 100644 index 0000000..5fe3dc5 --- /dev/null +++ b/packages/react/src/Drawer.tsx @@ -0,0 +1,71 @@ +import { type ReactNode } from "react"; +import * as RadixDialog from "@radix-ui/react-dialog"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; + +export type DrawerProps = { + open: boolean; + /** Callback de fermeture — déclenché par Esc, click backdrop, click close. */ + onClose: () => void; + /** Côté d'apparition. Défaut "right". */ + side?: "left" | "right"; + /** Largeur. Défaut "md" (480px). */ + size?: "sm" | "md" | "lg" | "xl"; + title?: ReactNode; + children: ReactNode; + footer?: ReactNode; + className?: string; +}; + +/** + * Drawer — panneau latéral (Radix Dialog). + * + * API simplifiée par rapport à Sheet : uniquement left/right, callback + * `onClose` (au lieu de `onOpenChange`). Pour bottom/top sheet ou plus + * de contrôle, utiliser directement Sheet. + * + * Backing Radix : focus trap, scroll lock, restitution focus, Esc — tout + * natif. Anciennement custom (useFocusTrap), maintenant aligné avec Sheet. + */ +export function Drawer({ + open, + onClose, + side = "right", + size = "md", + title, + children, + footer, + className, +}: DrawerProps) { + return ( + !o && onClose()}> + + + + {title && ( +
+
+ {title} +
+ + + +
+ )} +
{children}
+ {footer &&
{footer}
} +
+
+
+ ); +} diff --git a/packages/react/src/EmptyState.tsx b/packages/react/src/EmptyState.tsx new file mode 100644 index 0000000..2e62f26 --- /dev/null +++ b/packages/react/src/EmptyState.tsx @@ -0,0 +1,61 @@ +import type { HTMLAttributes, ReactNode } from "react"; +import { cx } from "./utils"; +import { IconBlock, type IconBlockProps } from "./IconBlock"; +import type { IconName } from "./Icon"; + +export type EmptyStateProps = HTMLAttributes & { + /** Icône Remix à afficher dans un IconBlock. */ + icon?: IconName; + /** Couleur de l'IconBlock. */ + iconColor?: IconBlockProps["color"]; + title: ReactNode; + description?: ReactNode; + /** Action principale (bouton, lien, etc.) */ + action?: ReactNode; + /** Actions secondaires (lien doc, contact support…) */ + secondaryAction?: ReactNode; + /** Variant compacte pour intégration dans un Card */ + compact?: boolean; +}; + +/** + * EmptyState — état vide standardisé. + * + * Cas d'usage : table vide, recherche sans résultat, espace + * non encore configuré, fonctionnalité en cours d'arrivée. + * + * UX : toujours un *next step* clair (action) — jamais juste "rien". + */ +export function EmptyState({ + icon = "search-2-line", + iconColor = "neutral", + title, + description, + action, + secondaryAction, + compact, + className, + ...rest +}: EmptyStateProps) { + return ( +
+ +

{title}

+ {description &&

{description}

} + {(action || secondaryAction) && ( +
+ {action} + {secondaryAction} +
+ )} +
+ ); +} diff --git a/packages/react/src/Extras.tsx b/packages/react/src/Extras.tsx new file mode 100644 index 0000000..19bdd53 --- /dev/null +++ b/packages/react/src/Extras.tsx @@ -0,0 +1,166 @@ +import { useId, type HTMLAttributes, type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +/* ──────────────────────────────────────────────────────── + SegmentedControl (Apple HIG) + - Choix exclusif court (2-5 options) + - Mieux qu'un Radio quand l'espace horizontal est dispo + - Évite l'overhead cognitif d'un Select pour peu d'options +──────────────────────────────────────────────────────── */ +export type SegmentedItem = { + value: V; + label: ReactNode; + icon?: IconName; + disabled?: boolean; +}; + +export function SegmentedControl({ + items, + value, + onChange, + size = "md", + fullWidth, + ariaLabel, + className, +}: { + items: SegmentedItem[]; + value: V; + onChange: (v: V) => void; + size?: "sm" | "md" | "lg"; + fullWidth?: boolean; + ariaLabel?: string; + className?: string; +}) { + return ( +
+ {items.map((item) => { + const checked = item.value === value; + return ( + + ); + })} +
+ ); +} + +/* ──────────────────────────────────────────────────────── + DescriptionList — pattern clé/valeur structuré (DSFR-like) + Sémantique HTML correcte (
) — meilleur que table + pour des paires non-tabulaires. Lecteurs d'écran nativement + supportés. +──────────────────────────────────────────────────────── */ +export type DListItem = { label: ReactNode; value: ReactNode }; + +export function DescriptionList({ + items, + layout = "horizontal", + className, +}: { + items: DListItem[]; + /** "horizontal" : label à gauche · "vertical" : label au-dessus */ + layout?: "horizontal" | "vertical"; + className?: string; +}) { + return ( +
+ {items.map((item, i) => ( +
+
{item.label}
+
{item.value}
+
+ ))} +
+ ); +} + +/* ──────────────────────────────────────────────────────── + Sparkline — micro graphe pour stat cards / dashboards + Inline SVG, sans dépendance, accessible (table de données + en + role img). +──────────────────────────────────────────────────────── */ +export function Sparkline({ + data, + width = 100, + height = 32, + color = "var(--mmg-color-accent)", + fill = "var(--mmg-color-accent-soft)", + ariaLabel, + className, +}: { + data: number[]; + width?: number; + height?: number; + color?: string; + fill?: string; + ariaLabel?: string; + className?: string; +}) { + if (data.length < 2) return null; + const min = Math.min(...data); + const max = Math.max(...data); + const range = max - min || 1; + const stepX = width / (data.length - 1); + + const points = data.map((v, i) => { + const x = i * stepX; + const y = height - ((v - min) / range) * height; + return `${x.toFixed(1)},${y.toFixed(1)}`; + }); + const linePath = `M ${points.join(" L ")}`; + const areaPath = `${linePath} L ${width},${height} L 0,${height} Z`; + + return ( + <svg + role="img" + aria-label={ariaLabel ?? `Évolution sur ${data.length} points : min ${min}, max ${max}`} + className={cx("mmg-sparkline", className)} + viewBox={`0 0 ${width} ${height}`} + width={width} + height={height} + preserveAspectRatio="none" + > + <path d={areaPath} fill={fill} /> + <path d={linePath} fill="none" stroke={color} strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" /> + </svg> + ); +} + +/* ──────────────────────────────────────────────────────── + Kbd — wrapping <kbd> stylisé + Pour shortcuts inline ("Appuyez sur ⌘K"). +──────────────────────────────────────────────────────── */ +export function Kbd({ + children, + className, + ...rest +}: HTMLAttributes<HTMLElement>) { + return ( + <kbd className={cx("mmg-kbd", className)} {...rest}> + {children} + </kbd> + ); +} diff --git a/packages/react/src/Fab.tsx b/packages/react/src/Fab.tsx new file mode 100644 index 0000000..9b4efc2 --- /dev/null +++ b/packages/react/src/Fab.tsx @@ -0,0 +1,22 @@ +import type { ButtonHTMLAttributes } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type FabProps = ButtonHTMLAttributes<HTMLButtonElement> & { + icon: IconName; + label: string; +}; + +export function Fab({ icon, label, className, ...rest }: FabProps) { + return ( + <button + type="button" + className={cx("mmg-fab", className)} + aria-label={label} + title={label} + {...rest} + > + <Icon name={icon} size="lg" /> + </button> + ); +} diff --git a/packages/react/src/FeatureCard.tsx b/packages/react/src/FeatureCard.tsx new file mode 100644 index 0000000..701142c --- /dev/null +++ b/packages/react/src/FeatureCard.tsx @@ -0,0 +1,61 @@ +import { type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type FeatureCardProps = { + /** Icône principale (Remix). */ + icon?: IconName; + /** Couleur de l'icône (et du glow associé en hover). */ + iconColor?: "brand" | "blue" | "green" | "amber" | "violet" | "neutral"; + title: ReactNode; + description?: ReactNode; + /** Slot pour un lien "En savoir plus". Rendu en bas de la carte. */ + link?: { label: ReactNode; href: string }; + /** Si true, ajoute un effet gradient borde au hover (Vercel-style). */ + glowOnHover?: boolean; + className?: string; +}; + +/** + * FeatureCard — carte de mise en avant (icône + titre + description + lien). + * + * Pattern landing pages Vercel / Linear / Stripe : grille 3 colonnes avec + * un IconBlock coloré, un titre fort, une description et un lien optionnel. + * + * Variante `glowOnHover` : ajoute un effet "border qui s'illumine" au + * hover via un dégradé conique (Vercel signature). Performant (un seul + * background-image animé via mask). + */ +export function FeatureCard({ + icon, + iconColor = "brand", + title, + description, + link, + glowOnHover, + className, +}: FeatureCardProps) { + return ( + <div + className={cx( + "mmg-feature-card", + glowOnHover && "mmg-feature-card--glow", + className, + )} + > + {icon && ( + <span className={cx("mmg-feature-card__icon", `mmg-feature-card__icon--${iconColor}`)} aria-hidden> + <Icon name={icon} size="lg" /> + </span> + )} + <h3 className="mmg-feature-card__title">{title}</h3> + {description && <p className="mmg-feature-card__desc">{description}</p>} + {link && ( + <a className="mmg-feature-card__link" href={link.href}> + {link.label} + <Icon name="arrow-right-line" size="sm" /> + </a> + )} + </div> + ); +} diff --git a/packages/react/src/Feedback.tsx b/packages/react/src/Feedback.tsx new file mode 100644 index 0000000..7add210 --- /dev/null +++ b/packages/react/src/Feedback.tsx @@ -0,0 +1,253 @@ +import { + useEffect, + useRef, + type HTMLAttributes, + type ReactNode, +} from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; +import { useFocusTrap } from "./useFocusTrap"; + +type Severity = "info" | "success" | "warning" | "danger"; + +const SEV_ICON: Record<Severity, IconName> = { + info: "information-fill", + success: "checkbox-circle-fill", + warning: "alert-fill", + danger: "error-warning-fill", +}; + +/* — Alert ————————————————————————————— */ +export function Alert({ + severity = "info", + title, + children, + closable, + onClose, + className, + ...rest +}: HTMLAttributes<HTMLDivElement> & { + severity?: Severity; + title?: ReactNode; + closable?: boolean; + onClose?: () => void; +}) { + return ( + <div + role={severity === "danger" ? "alert" : "status"} + className={cx( + "mmg-alert", + severity !== "info" && `mmg-alert--${severity}`, + className, + )} + {...rest} + > + <Icon name={SEV_ICON[severity]} className="mmg-alert__icon" size="md" /> + <div className="mmg-alert__body"> + {title && <div className="mmg-alert__title">{title}</div>} + {children && <div className="mmg-alert__desc">{children}</div>} + </div> + {closable && ( + <button + type="button" + className="mmg-alert__close" + aria-label="Fermer" + onClick={onClose} + > + <Icon name="close-line" /> + </button> + )} + </div> + ); +} + +/* — Notice ————————————————————————————— */ +export function Notice({ + variant = "brand", + className, + children, + ...rest +}: HTMLAttributes<HTMLDivElement> & { + variant?: "brand" | "info" | "warning" | "danger"; +}) { + return ( + <div + role="status" + className={cx( + "mmg-notice", + variant !== "brand" && `mmg-notice--${variant}`, + className, + )} + {...rest} + > + {children} + </div> + ); +} + +/* — Badge ————————————————————————————— */ +export function Badge({ + variant, + solid, + className, + children, + ...rest +}: HTMLAttributes<HTMLSpanElement> & { + variant?: "brand" | "success" | "warning" | "danger" | "info"; + solid?: boolean; +}) { + return ( + <span + className={cx( + "mmg-badge", + variant && `mmg-badge--${variant}`, + solid && "mmg-badge--solid", + className, + )} + {...rest} + > + {children} + </span> + ); +} + +/* — Modal ————————————————————————————— */ +let modalIdCounter = 0; +export function Modal({ + open, + onClose, + title, + description, + size, + children, + footer, + closable = true, +}: { + open: boolean; + onClose: () => void; + title?: ReactNode; + /** Optionnel — relié via aria-describedby aux lecteurs d'écran. */ + description?: ReactNode; + size?: "sm" | "lg"; + children: ReactNode; + footer?: ReactNode; + closable?: boolean; +}) { + const ref = useFocusTrap<HTMLDivElement>(open); + const titleIdRef = useRef<string>("mmg-modal-title-" + ++modalIdCounter); + const descIdRef = useRef<string>("mmg-modal-desc-" + modalIdCounter); + + useEffect(() => { + if (!open) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape" && closable) onClose(); + }; + document.addEventListener("keydown", onKey); + const prev = document.body.style.overflow; + document.body.style.overflow = "hidden"; + return () => { + document.removeEventListener("keydown", onKey); + document.body.style.overflow = prev; + }; + }, [open, closable, onClose]); + + if (!open) return null; + return ( + <div + className="mmg-modal-backdrop" + onClick={(e) => { + if (e.target === e.currentTarget && closable) onClose(); + }} + > + <div + ref={ref} + role="dialog" + aria-modal="true" + aria-labelledby={title ? titleIdRef.current : undefined} + aria-describedby={description ? descIdRef.current : undefined} + className={cx("mmg-modal", size && `mmg-modal--${size}`)} + > + {title && ( + <div className="mmg-modal__header"> + <h3 id={titleIdRef.current} className="mmg-modal__title"> + {title} + </h3> + {closable && ( + <button + type="button" + className="mmg-modal__close" + aria-label="Fermer" + onClick={onClose} + > + <Icon name="close-line" size="md" /> + </button> + )} + </div> + )} + <div className="mmg-modal__body"> + {description && ( + <p + id={descIdRef.current} + style={{ marginBottom: "var(--mmg-space-3)", color: "var(--mmg-color-text-tertiary)", fontSize: "var(--mmg-font-size-sm)" }} + > + {description} + </p> + )} + {children} + </div> + {footer && <div className="mmg-modal__footer">{footer}</div>} + </div> + </div> + ); +} + +/* — Toast (basique, contrôlé par parent) ————————————————————————————— */ +export type ToastItem = { + id: string; + severity?: Severity; + title: ReactNode; + desc?: ReactNode; +}; +export function ToastRegion({ + toasts, + onDismiss, +}: { + toasts: ToastItem[]; + onDismiss?: (id: string) => void; +}) { + return ( + <div className="mmg-toast-region" aria-live="polite"> + {toasts.map((t) => ( + <div + key={t.id} + className={cx( + "mmg-toast", + t.severity && t.severity !== "info" && `mmg-toast--${t.severity}`, + )} + onClick={() => onDismiss?.(t.id)} + > + <div> + <div className="mmg-toast__title">{t.title}</div> + {t.desc && <div className="mmg-toast__desc">{t.desc}</div>} + </div> + </div> + ))} + </div> + ); +} + +/* — Spinner ————————————————————————————— */ +export function Spinner({ + size = "md", + className, + ...rest +}: HTMLAttributes<HTMLSpanElement> & { size?: "sm" | "md" | "lg" }) { + return ( + <span + role="status" + aria-label="Chargement" + className={cx("mmg-spinner", size !== "md" && `mmg-spinner--${size}`, className)} + {...rest} + /> + ); +} diff --git a/packages/react/src/FileUpload.tsx b/packages/react/src/FileUpload.tsx new file mode 100644 index 0000000..3ab4030 --- /dev/null +++ b/packages/react/src/FileUpload.tsx @@ -0,0 +1,53 @@ +import { useState, type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; + +export type FileUploadProps = { + label?: ReactNode; + hint?: ReactNode; + multiple?: boolean; + accept?: string; + onFiles?: (files: FileList) => void; + className?: string; +}; + +export function FileUpload({ + label = "Glissez-déposez vos fichiers ici", + hint = "ou cliquez pour parcourir", + multiple, + accept, + onFiles, + className, +}: FileUploadProps) { + const [dragging, setDragging] = useState(false); + return ( + <label + className={cx("mmg-upload", className)} + data-dragging={dragging || undefined} + onDragEnter={(e) => { + e.preventDefault(); + setDragging(true); + }} + onDragOver={(e) => { + e.preventDefault(); + setDragging(true); + }} + onDragLeave={() => setDragging(false)} + onDrop={(e) => { + e.preventDefault(); + setDragging(false); + if (e.dataTransfer.files.length > 0) onFiles?.(e.dataTransfer.files); + }} + > + <Icon name="upload-line" className="mmg-upload__icon" size="xl" /> + <div className="mmg-upload__text">{label}</div> + <div className="mmg-upload__hint">{hint}</div> + <input + type="file" + multiple={multiple} + accept={accept} + onChange={(e) => e.target.files && onFiles?.(e.target.files)} + /> + </label> + ); +} diff --git a/packages/react/src/Footer.tsx b/packages/react/src/Footer.tsx new file mode 100644 index 0000000..d2cd054 --- /dev/null +++ b/packages/react/src/Footer.tsx @@ -0,0 +1,76 @@ +import type { ReactNode } from "react"; +import { cx } from "./utils"; + +export type FooterColumn = { + title: ReactNode; + links: { label: ReactNode; href: string }[]; +}; + +export type FooterProps = { + brand?: ReactNode; + description?: ReactNode; + columns?: FooterColumn[]; + bottomLinks?: { label: ReactNode; href: string }[]; + copyright?: ReactNode; + className?: string; +}; + +export function Footer({ + brand, + description, + columns, + bottomLinks, + copyright, + className, +}: FooterProps) { + return ( + <footer className={cx("mmg-footer", className)}> + <div className="mmg-container"> + <div className="mmg-footer__top"> + <div> + {brand && <div className="mmg-footer__col-title">{brand}</div>} + {description && ( + <p + style={{ + fontSize: "var(--mmg-font-size-sm)", + color: "var(--mmg-color-text-tertiary)", + marginTop: 8, + }} + > + {description} + </p> + )} + </div> + {columns?.map((col, i) => ( + <div key={i}> + <div className="mmg-footer__col-title">{col.title}</div> + <ul className="mmg-footer__col-list"> + {col.links.map((l, j) => ( + <li key={j}> + <a href={l.href}>{l.label}</a> + </li> + ))} + </ul> + </div> + ))} + </div> + <div className="mmg-footer__bottom"> + <div>{copyright ?? `© ${new Date().getFullYear()} ManageMate Group`}</div> + {bottomLinks && ( + <div className="mmg-inline"> + {bottomLinks.map((l, i) => ( + <a + key={i} + href={l.href} + style={{ fontSize: "var(--mmg-font-size-xs)", color: "var(--mmg-color-text-quaternary)" }} + > + {l.label} + </a> + ))} + </div> + )} + </div> + </div> + </footer> + ); +} diff --git a/packages/react/src/Form.tsx b/packages/react/src/Form.tsx new file mode 100644 index 0000000..b09d65c --- /dev/null +++ b/packages/react/src/Form.tsx @@ -0,0 +1,252 @@ +import { + forwardRef, + useId, + type InputHTMLAttributes, + type SelectHTMLAttributes, + type TextareaHTMLAttributes, + type ReactNode, +} from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +type FieldRenderArg = { + /** id du contrôle (à passer à <input>/<textarea>/<select>) */ + id: string; + /** id du message à passer en aria-describedby (peut être undefined) */ + describedBy: string | undefined; + /** L'état d'invalidité, à passer en aria-invalid */ + invalid: boolean | undefined; +}; + +type FieldProps = { + label?: ReactNode; + hint?: ReactNode; + error?: ReactNode; + success?: ReactNode; + required?: boolean; + className?: string; + id?: string; + children: (arg: FieldRenderArg) => ReactNode; +}; + +export function Field({ + label, + hint, + error, + success, + required, + className, + id: idProp, + children, +}: FieldProps) { + const auto = useId(); + const id = idProp ?? auto; + const messageId = `${id}-message`; + const hasMessage = Boolean(error || success || hint); + const describedBy = hasMessage ? messageId : undefined; + const state = error ? "error" : success ? "success" : undefined; + return ( + <div className={cx("mmg-field", state && `mmg-field--${state}`, className)}> + {label && ( + <label + className={cx( + "mmg-field__label", + required && "mmg-field__label--required", + )} + htmlFor={id} + > + {label} + </label> + )} + {children({ id, describedBy, invalid: error ? true : undefined })} + {error ? ( + <span id={messageId} className="mmg-field__error" role="alert"> + {error} + </span> + ) : success ? ( + <span id={messageId} className="mmg-field__success"> + {success} + </span> + ) : hint ? ( + <span id={messageId} className="mmg-field__hint"> + {hint} + </span> + ) : null} + </div> + ); +} + +/* — Input ————————————————————————————— */ +export type InputProps = Omit<InputHTMLAttributes<HTMLInputElement>, "size"> & { + label?: ReactNode; + hint?: ReactNode; + error?: ReactNode; + success?: ReactNode; + size?: "sm" | "md" | "lg"; + prefixIcon?: IconName; + suffixIcon?: IconName; +}; + +export const Input = forwardRef<HTMLInputElement, InputProps>(function Input( + { label, hint, error, success, size = "md", prefixIcon, suffixIcon, required, className, ...rest }, + ref, +) { + const cls = cx( + "mmg-input", + size !== "md" && `mmg-input--${size}`, + className, + ); + return ( + <Field label={label} hint={hint} error={error} success={success} required={required}> + {({ id, describedBy, invalid }) => + prefixIcon || suffixIcon ? ( + <span className={cx("mmg-input-wrap", suffixIcon && "mmg-input-wrap--with-suffix")}> + {prefixIcon && ( + <span className="mmg-input-wrap__icon"><Icon name={prefixIcon} /></span> + )} + <input + ref={ref} + id={id} + className={cls} + required={required} + aria-describedby={describedBy} + aria-invalid={invalid} + {...rest} + /> + {suffixIcon && ( + <span className="mmg-input-wrap__icon mmg-input-wrap__icon--suffix"> + <Icon name={suffixIcon} /> + </span> + )} + </span> + ) : ( + <input + ref={ref} + id={id} + className={cls} + required={required} + aria-describedby={describedBy} + aria-invalid={invalid} + {...rest} + /> + ) + } + </Field> + ); +}); + +/* — Textarea ————————————————————————————— */ +export type TextareaProps = TextareaHTMLAttributes<HTMLTextAreaElement> & { + label?: ReactNode; + hint?: ReactNode; + error?: ReactNode; + success?: ReactNode; + fieldSize?: "sm" | "md" | "lg"; +}; +export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>( + function Textarea( + { label, hint, error, success, fieldSize = "md", required, className, ...rest }, + ref, + ) { + const cls = cx( + "mmg-textarea", + fieldSize !== "md" && `mmg-textarea--${fieldSize}`, + className, + ); + return ( + <Field label={label} hint={hint} error={error} success={success} required={required}> + {({ id, describedBy, invalid }) => ( + <textarea + ref={ref} + id={id} + className={cls} + required={required} + aria-describedby={describedBy} + aria-invalid={invalid} + {...rest} + /> + )} + </Field> + ); + }, +); + +/* — Select ————————————————————————————— */ +export type SelectOption = { value: string; label: string; disabled?: boolean }; +export type SelectProps = Omit<SelectHTMLAttributes<HTMLSelectElement>, "size"> & { + label?: ReactNode; + hint?: ReactNode; + error?: ReactNode; + success?: ReactNode; + size?: "sm" | "md" | "lg"; + options: SelectOption[]; + placeholder?: string; +}; +export const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select( + { label, hint, error, success, size = "md", options, placeholder, required, className, ...rest }, + ref, +) { + const cls = cx("mmg-select", size !== "md" && `mmg-select--${size}`, className); + return ( + <Field label={label} hint={hint} error={error} success={success} required={required}> + {({ id, describedBy, invalid }) => ( + <select + ref={ref} + id={id} + className={cls} + required={required} + aria-describedby={describedBy} + aria-invalid={invalid} + {...rest} + > + {placeholder && <option value="">{placeholder}</option>} + {options.map((o) => ( + <option key={o.value} value={o.value} disabled={o.disabled}> + {o.label} + </option> + ))} + </select> + )} + </Field> + ); +}); + +/* — Checkbox / Radio ————————————————————————————— */ +type CheckProps = InputHTMLAttributes<HTMLInputElement> & { + label: ReactNode; +}; +export const Checkbox = forwardRef<HTMLInputElement, CheckProps>(function Checkbox( + { label, className, ...rest }, + ref, +) { + return ( + <label className={cx("mmg-check", className)}> + <input ref={ref} type="checkbox" className="mmg-check__input" {...rest} /> + <span className="mmg-check__label">{label}</span> + </label> + ); +}); +export const Radio = forwardRef<HTMLInputElement, CheckProps>(function Radio( + { label, className, ...rest }, + ref, +) { + return ( + <label className={cx("mmg-check", className)}> + <input ref={ref} type="radio" className="mmg-check__input" {...rest} /> + <span className="mmg-check__label">{label}</span> + </label> + ); +}); + +/* — Switch ————————————————————————————— */ +export const Switch = forwardRef<HTMLInputElement, CheckProps>(function Switch( + { label, className, ...rest }, + ref, +) { + return ( + <label className={cx("mmg-switch", className)}> + <input ref={ref} type="checkbox" role="switch" className="mmg-switch__input" {...rest} /> + <span className="mmg-check__label">{label}</span> + </label> + ); +}); diff --git a/packages/react/src/Header.tsx b/packages/react/src/Header.tsx new file mode 100644 index 0000000..96801a2 --- /dev/null +++ b/packages/react/src/Header.tsx @@ -0,0 +1,247 @@ +import { + useEffect, + useRef, + useState, + type ReactNode, +} from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type NavItemSimple = { + label: ReactNode; + href: string; + current?: boolean; +}; + +export type MegaMenuLink = { + label: ReactNode; + href: string; + description?: ReactNode; + icon?: IconName; +}; + +export type MegaMenuColumn = { + title?: ReactNode; + links: MegaMenuLink[]; +}; + +export type MegaMenuFeatured = { + title: ReactNode; + description: ReactNode; + href: string; + cta?: ReactNode; +}; + +export type NavItemMega = { + label: ReactNode; + current?: boolean; + columns: MegaMenuColumn[]; + featured?: MegaMenuFeatured; +}; + +export type HeaderNavItem = NavItemSimple | NavItemMega; + +const isMega = (item: HeaderNavItem): item is NavItemMega => "columns" in item; + +function MegaMenuTrigger({ item, index }: { item: NavItemMega; index: number }) { + const [open, setOpen] = useState(false); + const ref = useRef<HTMLLIElement>(null); + const closeTimer = useRef<number | null>(null); + + useEffect(() => { + if (!open) return; + const onClick = (e: MouseEvent) => { + if (!ref.current?.contains(e.target as Node)) setOpen(false); + }; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape") setOpen(false); + }; + document.addEventListener("mousedown", onClick); + document.addEventListener("keydown", onKey); + return () => { + document.removeEventListener("mousedown", onClick); + document.removeEventListener("keydown", onKey); + }; + }, [open]); + + const cancelClose = () => { + if (closeTimer.current) { + window.clearTimeout(closeTimer.current); + closeTimer.current = null; + } + }; + const scheduleClose = () => { + cancelClose(); + closeTimer.current = window.setTimeout(() => setOpen(false), 180); + }; + + return ( + <li + ref={ref} + className="mmg-header__nav-item" + onMouseEnter={() => { + cancelClose(); + setOpen(true); + }} + onMouseLeave={scheduleClose} + > + <button + type="button" + className="mmg-header__nav-trigger" + aria-expanded={open} + aria-haspopup="true" + aria-controls={`mmg-megamenu-${index}`} + onClick={() => setOpen((v) => !v)} + > + {item.label} + <Icon name="arrow-down-line" className="mmg-header__nav-chevron" size="sm" /> + </button> + {open && ( + <div + id={`mmg-megamenu-${index}`} + className="mmg-megamenu" + role="region" + aria-label={typeof item.label === "string" ? item.label : undefined} + > + <div + className="mmg-megamenu__grid" + style={{ + gridTemplateColumns: item.featured + ? `repeat(${item.columns.length}, minmax(180px, 1fr)) 240px` + : `repeat(${item.columns.length}, minmax(180px, 1fr))`, + }} + > + {item.columns.map((col, ci) => ( + <div key={ci}> + {col.title && <div className="mmg-megamenu__col-title">{col.title}</div>} + <ul className="mmg-megamenu__list"> + {col.links.map((l, li) => ( + <li key={li}> + <a href={l.href} className="mmg-megamenu__link"> + {l.icon && ( + <span className="mmg-megamenu__link-icon"> + <Icon name={l.icon} size="md" /> + </span> + )} + <span className="mmg-megamenu__link-content"> + <span className="mmg-megamenu__link-label">{l.label}</span> + {l.description && ( + <span className="mmg-megamenu__link-desc">{l.description}</span> + )} + </span> + </a> + </li> + ))} + </ul> + </div> + ))} + {item.featured && ( + <a + href={item.featured.href} + className="mmg-megamenu__featured" + style={{ textDecoration: "none" }} + > + <div className="mmg-megamenu__featured-title">{item.featured.title}</div> + <div className="mmg-megamenu__featured-desc">{item.featured.description}</div> + {item.featured.cta && ( + <span style={{ color: "var(--mmg-color-accent)", fontWeight: 600, fontSize: "var(--mmg-font-size-sm)" }}> + {item.featured.cta} → + </span> + )} + </a> + )} + </div> + </div> + )} + </li> + ); +} + +export type HeaderProps = { + brand: ReactNode; + brandHref?: string; + /** Si fourni avec serviceTitle, active le mode "institutional". */ + brandTop?: ReactNode; + serviceTitle?: ReactNode; + serviceTagline?: ReactNode; + logoMark?: ReactNode; + nav?: HeaderNavItem[]; + actions?: ReactNode; + className?: string; +}; + +export function Header({ + brand, + brandHref = "/", + brandTop, + serviceTitle, + serviceTagline, + logoMark, + nav, + actions, + className, +}: HeaderProps) { + const initials = typeof brand === "string" ? brand.slice(0, 2).toUpperCase() : null; + const isInstitutional = Boolean(brandTop || serviceTitle); + + return ( + <header + className={cx( + "mmg-header", + isInstitutional && "mmg-header--institutional", + className, + )} + > + <div className="mmg-container"> + <div className="mmg-header__inner"> + <a href={brandHref} className="mmg-header__brand"> + <span className="mmg-header__logo">{logoMark ?? initials}</span> + {isInstitutional ? ( + <span className="mmg-header__brand-text"> + {brandTop && <span className="mmg-header__brand-top">{brandTop}</span>} + {serviceTitle && <span className="mmg-header__service">{serviceTitle}</span>} + {serviceTagline && ( + <span className="mmg-header__service-tagline">{serviceTagline}</span> + )} + </span> + ) : ( + <span className="mmg-header__name">{brand}</span> + )} + </a> + {nav && ( + <nav className="mmg-header__nav" aria-label="Navigation principale"> + <ul + style={{ + display: "flex", + alignItems: "center", + listStyle: "none", + padding: 0, + margin: 0, + gap: "var(--mmg-space-1)", + height: "100%", + }} + > + {nav.map((item, i) => + isMega(item) ? ( + <MegaMenuTrigger key={i} item={item} index={i} /> + ) : ( + <li + key={i} + className="mmg-header__nav-item" + style={{ display: "flex", alignItems: "center" }} + > + <a href={item.href} aria-current={item.current ? "page" : undefined}> + {item.label} + </a> + </li> + ), + )} + </ul> + </nav> + )} + {actions && <div className="mmg-header__actions">{actions}</div>} + </div> + </div> + </header> + ); +} diff --git a/packages/react/src/Highlight.tsx b/packages/react/src/Highlight.tsx new file mode 100644 index 0000000..615363e --- /dev/null +++ b/packages/react/src/Highlight.tsx @@ -0,0 +1,12 @@ +import type { HTMLAttributes } from "react"; +import { cx } from "./utils"; + +export type HighlightProps = HTMLAttributes<HTMLDivElement>; + +export function Highlight({ children, className, ...rest }: HighlightProps) { + return ( + <div className={cx("mmg-highlight", className)} {...rest}> + {children} + </div> + ); +} diff --git a/packages/react/src/HoverCard.tsx b/packages/react/src/HoverCard.tsx new file mode 100644 index 0000000..ed50aca --- /dev/null +++ b/packages/react/src/HoverCard.tsx @@ -0,0 +1,57 @@ +import { type ReactNode } from "react"; +import * as RadixHoverCard from "@radix-ui/react-hover-card"; +import { cx } from "./utils"; + +export type HoverCardProps = { + trigger: ReactNode; + children: ReactNode; + /** Délai d'apparition (ms). Défaut 700. */ + openDelay?: number; + /** Délai avant fermeture (ms). Défaut 300. */ + closeDelay?: number; + side?: "top" | "right" | "bottom" | "left"; + align?: "start" | "center" | "end"; + sideOffset?: number; + className?: string; +}; + +/** + * HoverCard — preview riche au survol (Radix UI HoverCard). + * + * Pour : aperçus de profil utilisateur, métadonnées de lien, fiche produit + * en survol, etc. Pas pour les tooltips courts (utiliser Tooltip). + * + * A11y : Radix gère le hover-bridge (la fenêtre reste ouverte pendant la + * traversée de l'utilisateur entre trigger et content), le focus management + * et l'invocation par focus clavier (le HoverCard ouvre aussi sur :focus). + */ +export function HoverCard({ + trigger, + children, + openDelay = 700, + closeDelay = 300, + side = "bottom", + align = "start", + sideOffset = 8, + className, +}: HoverCardProps) { + return ( + <RadixHoverCard.Root openDelay={openDelay} closeDelay={closeDelay}> + <RadixHoverCard.Trigger asChild>{trigger}</RadixHoverCard.Trigger> + <RadixHoverCard.Portal> + <RadixHoverCard.Content + side={side} + align={align} + sideOffset={sideOffset} + collisionPadding={8} + className={cx("mmg-hover-card", className)} + > + {children} + <RadixHoverCard.Arrow className="mmg-hover-card__arrow" /> + </RadixHoverCard.Content> + </RadixHoverCard.Portal> + </RadixHoverCard.Root> + ); +} + +export { RadixHoverCard as HoverCardPrimitive }; diff --git a/packages/react/src/Icon.tsx b/packages/react/src/Icon.tsx new file mode 100644 index 0000000..0a8cd54 --- /dev/null +++ b/packages/react/src/Icon.tsx @@ -0,0 +1,40 @@ +import type { CSSProperties, HTMLAttributes } from "react"; +import { cx } from "./utils"; + +/** Nom d'une icône DSMMG (préfixe `mmg-icon-`). */ +export type IconName = string; + +export type IconProps = HTMLAttributes<HTMLSpanElement> & { + /** Nom de l'icône (ex. "arrow-right"). Voir packages/icons/dist/icons.json */ + name: IconName; + /** Taille — xs: 12px, sm: 14px, md: 18px, lg: 24px, xl: 32px, 2xl: 48px. + Par défaut hérite de font-size. */ + size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"; + /** Texte alternatif. Si absent, l'icône est purement décorative (aria-hidden). */ + label?: string; +}; + +export function Icon({ + name, + size, + label, + className, + style, + ...rest +}: IconProps) { + return ( + <span + role={label ? "img" : undefined} + aria-label={label} + aria-hidden={label ? undefined : true} + className={cx( + "mmg-icon", + `mmg-icon-${name}`, + size && `mmg-icon--${size}`, + className, + )} + style={style as CSSProperties} + {...rest} + /> + ); +} diff --git a/packages/react/src/IconBlock.tsx b/packages/react/src/IconBlock.tsx new file mode 100644 index 0000000..4ab4642 --- /dev/null +++ b/packages/react/src/IconBlock.tsx @@ -0,0 +1,54 @@ +import type { HTMLAttributes } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type IconBlockProps = HTMLAttributes<HTMLSpanElement> & { + /** Icône Remix (préfère les variants -fill pour visibilité). */ + icon: IconName; + /** Taille — xs:32 sm:40 md:56 lg:72 xl:96 px. */ + size?: "xs" | "sm" | "md" | "lg" | "xl"; + /** Variante de couleur sémantique. */ + color?: "brand" | "success" | "warning" | "danger" | "info" | "neutral"; + /** Style visuel — soft (par défaut), filled, outline, gradient. */ + variant?: "soft" | "filled" | "outline" | "gradient"; + /** Texte alternatif. Si absent, IconBlock est décoratif. */ + label?: string; +}; + +/** + * IconBlock — carré coloré avec icône centrée. + * + * Pattern utilisé chez Linear, Vercel, Notion. Plus polyvalent que les + * pictogrammes hand-codés : se compose à partir de n'importe quelle icône + * Remix, scale automatiquement avec les tokens couleur sémantique, et reste + * cohérent en dark mode. + * + * Préférer en Tile pour les pages d'index produits/fonctionnalités. + */ +export function IconBlock({ + icon, + size = "md", + color = "brand", + variant = "soft", + label, + className, + ...rest +}: IconBlockProps) { + return ( + <span + role={label ? "img" : undefined} + aria-label={label} + aria-hidden={label ? undefined : true} + className={cx( + "mmg-iconblock", + `mmg-iconblock--${size}`, + `mmg-iconblock--${color}`, + variant !== "soft" && `mmg-iconblock--${variant}`, + className, + )} + {...rest} + > + <Icon name={icon} /> + </span> + ); +} diff --git a/packages/react/src/Layout.tsx b/packages/react/src/Layout.tsx new file mode 100644 index 0000000..e86c7c8 --- /dev/null +++ b/packages/react/src/Layout.tsx @@ -0,0 +1,225 @@ +import type { HTMLAttributes, ReactNode, AnchorHTMLAttributes, ElementType } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; +import { IconBlock, type IconBlockProps } from "./IconBlock"; +import { Pictogram, type PictogramName } from "./Pictogram"; + +/* — Container ————————————————————————————— */ +export type ContainerProps = HTMLAttributes<HTMLDivElement> & { + variant?: "default" | "narrow" | "wide" | "fluid"; + as?: ElementType; +}; +export function Container({ + variant = "default", + as: As = "div", + className, + children, + ...rest +}: ContainerProps) { + const Tag = As as ElementType; + return ( + <Tag + className={cx( + "mmg-container", + variant !== "default" && `mmg-container--${variant}`, + className, + )} + {...rest} + > + {children} + </Tag> + ); +} + +/* — Section ————————————————————————————— */ +export type SectionProps = HTMLAttributes<HTMLElement> & { + size?: "sm" | "md" | "lg"; + variant?: "default" | "surface" | "muted" | "brand-soft"; +}; +export function Section({ + size = "md", + variant = "default", + className, + children, + ...rest +}: SectionProps) { + return ( + <section + className={cx( + "mmg-section", + size !== "md" && `mmg-section--${size}`, + variant !== "default" && `mmg-section--${variant}`, + className, + )} + {...rest} + > + {children} + </section> + ); +} + +/* — Stack & Inline ————————————————————————————— */ +export function Stack({ + gap = "md", + className, + children, + ...rest +}: HTMLAttributes<HTMLDivElement> & { gap?: "xs" | "sm" | "md" | "lg" | "xl" }) { + return ( + <div className={cx("mmg-stack", `mmg-stack--${gap}`, className)} {...rest}> + {children} + </div> + ); +} +export function Inline({ + align, + className, + children, + ...rest +}: HTMLAttributes<HTMLDivElement> & { align?: "end" | "between" | "center" }) { + return ( + <div + className={cx("mmg-inline", align && `mmg-inline--${align}`, className)} + {...rest} + > + {children} + </div> + ); +} + +/* — Card ————————————————————————————— */ +export function Card({ + raised, + flat, + noPadding, + className, + children, + ...rest +}: HTMLAttributes<HTMLDivElement> & { + raised?: boolean; + flat?: boolean; + noPadding?: boolean; +}) { + return ( + <div + className={cx( + "mmg-card", + raised && "mmg-card--raised", + flat && "mmg-card--flat", + noPadding && "mmg-card--no-padding", + className, + )} + {...rest} + > + {children} + </div> + ); +} +Card.Header = function CardHeader({ children, className, ...rest }: HTMLAttributes<HTMLDivElement>) { + return <div className={cx("mmg-card__header", className)} {...rest}>{children}</div>; +}; +Card.Title = function CardTitle({ children, className, ...rest }: HTMLAttributes<HTMLHeadingElement>) { + return <h3 className={cx("mmg-card__title", className)} {...rest}>{children}</h3>; +}; +Card.Desc = function CardDesc({ children, className, ...rest }: HTMLAttributes<HTMLParagraphElement>) { + return <p className={cx("mmg-card__desc", className)} {...rest}>{children}</p>; +}; +Card.Footer = function CardFooter({ children, className, ...rest }: HTMLAttributes<HTMLDivElement>) { + return <div className={cx("mmg-card__footer", className)} {...rest}>{children}</div>; +}; + +/* — Tile ————————————————————————————— */ +export type TileProps = AnchorHTMLAttributes<HTMLAnchorElement> & { + title: ReactNode; + desc?: ReactNode; + /** Petite icône carrée (style basique, 48×48). */ + icon?: IconName; + /** IconBlock — pattern recommandé : icône fill colorée sur fond rond. */ + iconBlock?: IconName; + /** Couleur sémantique de l'IconBlock. */ + iconColor?: IconBlockProps["color"]; + /** Variante visuelle de l'IconBlock. */ + iconVariant?: IconBlockProps["variant"]; + /** Pictogramme illustré (legacy v0.2). */ + pictogram?: PictogramName; + /** Disposition horizontale (icône à gauche). */ + horizontal?: boolean; + /** Cache la flèche d'invitation. */ + noArrow?: boolean; + /** Taille — sm (compact), md (défaut), lg (hero). */ + size?: "sm" | "md" | "lg"; +}; + +export function Tile({ + title, + desc, + icon, + iconBlock, + iconColor = "brand", + iconVariant = "soft", + pictogram, + horizontal, + noArrow, + size = "md", + className, + children, + ...rest +}: TileProps) { + const blockSize = size === "sm" ? "sm" : size === "lg" ? "lg" : "md"; + return ( + <a + className={cx( + "mmg-tile", + size !== "md" && `mmg-tile--${size}`, + horizontal && "mmg-tile--horizontal", + className, + )} + {...rest} + > + {iconBlock ? ( + <IconBlock icon={iconBlock} color={iconColor} variant={iconVariant} size={blockSize} /> + ) : pictogram ? ( + <Pictogram name={pictogram} className="mmg-tile__pictogram" /> + ) : icon ? ( + <span className="mmg-tile__icon"> + <Icon name={icon} /> + </span> + ) : null} + <div className="mmg-stack mmg-stack--xs" style={{ flex: 1 }}> + <span className="mmg-tile__title"> + {title} + {!noArrow && ( + <span className="mmg-tile__arrow" aria-hidden> + <Icon name="arrow-right-line" size="md" /> + </span> + )} + </span> + {desc && <span className="mmg-tile__desc">{desc}</span>} + {children} + </div> + </a> + ); +} + +/* — Hero ————————————————————————————— */ +export function Hero({ + title, + lead, + actions, + className, + ...rest +}: HTMLAttributes<HTMLElement> & { + title: ReactNode; + lead?: ReactNode; + actions?: ReactNode; +}) { + return ( + <section className={cx("mmg-hero", className)} {...rest}> + <div className="mmg-container"> + <h1 className="mmg-hero__title">{title}</h1> + {lead && <p className="mmg-hero__lead">{lead}</p>} + {actions && <div className="mmg-inline">{actions}</div>} + </div> + </section> + ); +} diff --git a/packages/react/src/Menu.tsx b/packages/react/src/Menu.tsx new file mode 100644 index 0000000..899650d --- /dev/null +++ b/packages/react/src/Menu.tsx @@ -0,0 +1,99 @@ +import { type ReactNode } from "react"; +import * as RadixMenu from "@radix-ui/react-dropdown-menu"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type MenuItem = + | { + type?: "item"; + label: ReactNode; + icon?: IconName; + onSelect?: () => void; + danger?: boolean; + href?: string; + disabled?: boolean; + shortcut?: string; + } + | { type: "divider" } + | { type: "label"; label: ReactNode }; + +export type MenuProps = { + trigger: ReactNode; + items: MenuItem[]; + align?: "start" | "center" | "end"; + side?: "top" | "right" | "bottom" | "left"; + sideOffset?: number; +}; + +/** + * Menu (dropdown) — wrapper Radix DropdownMenu. + * + * Accessibilité gérée par Radix : navigation flèches, type-ahead, Escape, + * focus management, ARIA roles. Aucun appel a11y custom. + * + * Pour les sous-menus, items radio/checkbox, ouvrir + * MenuPrimitive et composer manuellement. + */ +export function Menu({ + trigger, + items, + align = "start", + side = "bottom", + sideOffset = 6, +}: MenuProps) { + return ( + <RadixMenu.Root> + <RadixMenu.Trigger asChild>{trigger}</RadixMenu.Trigger> + <RadixMenu.Portal> + <RadixMenu.Content + align={align} + side={side} + sideOffset={sideOffset} + collisionPadding={8} + className="mmg-menu" + > + {items.map((item, i) => { + if (item.type === "divider") { + return <RadixMenu.Separator key={i} className="mmg-menu__divider" />; + } + if (item.type === "label") { + return ( + <RadixMenu.Label key={i} className="mmg-menu__label"> + {item.label} + </RadixMenu.Label> + ); + } + const { label, icon, onSelect, danger, href, disabled, shortcut } = item; + const cn = cx("mmg-menu__item", danger && "mmg-menu__item--danger"); + const inner = ( + <> + {icon && <Icon name={icon} />} + <span style={{ flex: 1 }}>{label}</span> + {shortcut && <span className="mmg-menu__shortcut">{shortcut}</span>} + </> + ); + if (href) { + return ( + <RadixMenu.Item key={i} className={cn} disabled={disabled} asChild> + <a href={href}>{inner}</a> + </RadixMenu.Item> + ); + } + return ( + <RadixMenu.Item + key={i} + className={cn} + disabled={disabled} + onSelect={onSelect} + > + {inner} + </RadixMenu.Item> + ); + })} + </RadixMenu.Content> + </RadixMenu.Portal> + </RadixMenu.Root> + ); +} + +export { RadixMenu as MenuPrimitive }; diff --git a/packages/react/src/MetricCard.tsx b/packages/react/src/MetricCard.tsx new file mode 100644 index 0000000..9d8977b --- /dev/null +++ b/packages/react/src/MetricCard.tsx @@ -0,0 +1,114 @@ +import { type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type MetricTrend = "up" | "down" | "flat"; + +export type MetricCardProps = { + /** Label de la métrique (ex: "MRR", "NPS", "Tickets ouverts"). */ + label: ReactNode; + /** Valeur principale (ex: "12 480 €", "8.2"). */ + value: ReactNode; + /** Variation chiffrée (ex: "+12.4%", "-3"). Affichée sous la valeur. */ + delta?: ReactNode; + /** Sens de la tendance — détermine la couleur (success/danger/neutre). */ + trend?: MetricTrend; + /** Si true, inverse la sémantique : down=success (ex: "tickets en attente"). */ + invertTrend?: boolean; + /** Période / sous-titre (ex: "vs mois dernier"). */ + period?: ReactNode; + /** Icône optionnelle à gauche du label. */ + icon?: IconName; + /** Slot pour un Sparkline ou autre graphique inline. */ + sparkline?: ReactNode; + /** Si fourni, rend la carte cliquable (drill-down). */ + href?: string; + onClick?: () => void; + className?: string; +}; + +const TREND_ICON: Record<MetricTrend, IconName> = { + up: "arrow-right-up-line", + down: "arrow-right-up-line", // rotated via CSS + flat: "subtract-line", +}; + +/** + * MetricCard — carte KPI avec valeur + delta + tendance + sparkline. + * + * Pattern Linear / Vercel / Stripe Dashboard : une grosse valeur, une + * variation colorée (vert si positif, rouge si négatif), période, et + * éventuellement un sparkline en arrière-plan ou inline. + * + * Sémantique : + * - trend "up" : vert par défaut (croissance = bien) + * - trend "down" : rouge par défaut (décroissance = mal) + * - trend "flat" : neutre + * - `invertTrend` inverse pour les KPI où "moins, c'est mieux" + * (tickets ouverts, latence, churn). + */ +export function MetricCard({ + label, + value, + delta, + trend = "flat", + invertTrend, + period, + icon, + sparkline, + href, + onClick, + className, +}: MetricCardProps) { + const Comp: "a" | "button" | "div" = href ? "a" : onClick ? "button" : "div"; + const semantic = + trend === "flat" + ? "neutral" + : (trend === "up" && !invertTrend) || (trend === "down" && invertTrend) + ? "success" + : "danger"; + + return ( + <Comp + className={cx( + "mmg-metric-card", + (href || onClick) && "mmg-metric-card--interactive", + className, + )} + href={href} + type={Comp === "button" ? "button" : undefined} + onClick={onClick} + > + <div className="mmg-metric-card__head"> + {icon && ( + <span className="mmg-metric-card__icon" aria-hidden> + <Icon name={icon} size="sm" /> + </span> + )} + <span className="mmg-metric-card__label">{label}</span> + </div> + + <div className="mmg-metric-card__value">{value}</div> + + {(delta || period) && ( + <div className="mmg-metric-card__footer"> + {delta && ( + <span + className={cx( + "mmg-metric-card__delta", + `mmg-metric-card__delta--${semantic}`, + trend === "down" && "mmg-metric-card__delta--rotated", + )} + > + <Icon name={TREND_ICON[trend]} size="xs" /> + {delta} + </span> + )} + {period && <span className="mmg-metric-card__period">{period}</span>} + </div> + )} + + {sparkline && <div className="mmg-metric-card__sparkline">{sparkline}</div>} + </Comp> + ); +} diff --git a/packages/react/src/Pagination.tsx b/packages/react/src/Pagination.tsx new file mode 100644 index 0000000..9c8f81e --- /dev/null +++ b/packages/react/src/Pagination.tsx @@ -0,0 +1,50 @@ +import { cx } from "./utils"; +import { Icon } from "./Icon"; + +export type PaginationProps = { + page: number; + pageCount: number; + onChange: (p: number) => void; + className?: string; +}; + +export function Pagination({ page, pageCount, onChange, className }: PaginationProps) { + const pages = Array.from({ length: pageCount }, (_, i) => i + 1); + return ( + <nav aria-label="Pagination"> + <ul className={cx("mmg-pagination", className)}> + <li> + <button + type="button" + onClick={() => onChange(Math.max(1, page - 1))} + disabled={page === 1} + aria-label="Page précédente" + > + <Icon name="arrow-left-line" /> + </button> + </li> + {pages.map((p) => ( + <li key={p}> + <button + type="button" + aria-current={p === page ? "page" : undefined} + onClick={() => onChange(p)} + > + {p} + </button> + </li> + ))} + <li> + <button + type="button" + onClick={() => onChange(Math.min(pageCount, page + 1))} + disabled={page === pageCount} + aria-label="Page suivante" + > + <Icon name="arrow-right-line" /> + </button> + </li> + </ul> + </nav> + ); +} diff --git a/packages/react/src/Pictogram.tsx b/packages/react/src/Pictogram.tsx new file mode 100644 index 0000000..78a2959 --- /dev/null +++ b/packages/react/src/Pictogram.tsx @@ -0,0 +1,696 @@ +import type { CSSProperties, JSX } from "react"; +import { cx } from "./utils"; + +/** + * Pictogrammes ManageMate — 80×80, palette artwork stable cross-theme. + * + * Tokens utilisés (définis dans tokens.css) : + * --mmg-color-art-major rose marque + * --mmg-color-art-minor rose foncé + * --mmg-color-art-light fond pâle (rose en light, sombre teinté en dark) + * --mmg-color-art-dark silhouette sombre (clair en dark mode) + * --mmg-color-art-accent bleu pour accent rare + * + * Inspiration : DSFR & defense.gouv.fr — illustrations plates, 2-3 couleurs, + * silhouette claire, pas plus de 4 formes par picto. + */ +export type PictogramName = + // — Démarches / documents —————————————— + | "certificate" + | "transfer" + | "document" + | "duplicate" + | "address" + // — Produits SIRH ————————————————————— + | "people" + | "payroll" + | "calendar" + | "training" + | "shopping" + | "news" + // — Marketing / général —————————————— + | "rocket" + | "shield" + | "settings" + // — Nouveaux v0.2 ———————————————————— + | "success" + | "alert" + | "search" + | "support" + | "growth" + | "target" + | "innovation" + | "savings" + | "handshake" + | "cloud" + | "lock-secure" + | "globe" + | "mobile" + | "analytics" + | "gift" + | "messaging" + // — v0.5 marine ———————————————————— + | "marine-casquette" + | "marine-ancre" + | "marine-porte-avion" + // — v0.6 ManageMate Group products —————————————— + | "synapse" + | "hrtime" + | "forge" + | "orbit" + | "automation" + | "insights" + | "integration" + | "workflow"; + +const MAJOR = "var(--mmg-color-art-major)"; +const MINOR = "var(--mmg-color-art-minor)"; +const LIGHT = "var(--mmg-color-art-light)"; +const DARK = "var(--mmg-color-art-dark)"; +const ACCENT = "var(--mmg-color-art-accent)"; + +const PICTOS: Record<PictogramName, JSX.Element> = { + certificate: ( + <> + <rect x="14" y="10" width="52" height="62" rx="4" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <line x1="22" y1="24" x2="58" y2="24" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="22" y1="32" x2="50" y2="32" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="22" y1="40" x2="46" y2="40" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <circle cx="56" cy="58" r="10" fill={MAJOR} /> + <path d="M52 58 L55 61 L61 55" stroke="white" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + </> + ), + + transfer: ( + <> + <rect x="6" y="34" width="32" height="22" rx="3" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <circle cx="14" cy="56" r="4" fill={DARK} /> + <circle cx="30" cy="56" r="4" fill={DARK} /> + <rect x="42" y="40" width="32" height="22" rx="3" fill={MAJOR} /> + <circle cx="50" cy="62" r="4" fill={DARK} /> + <circle cx="66" cy="62" r="4" fill={DARK} /> + <path d="M36 26 L44 26 L44 22 L52 30 L44 38 L44 34 L36 34 Z" fill={MAJOR} /> + </> + ), + + document: ( + <> + <path d="M22 8 L46 8 L58 20 L58 70 Q58 74 54 74 L22 74 Q18 74 18 70 L18 12 Q18 8 22 8 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <path d="M46 8 L46 20 L58 20" fill="none" stroke={MAJOR} strokeWidth="2" strokeLinejoin="round" /> + <line x1="26" y1="34" x2="50" y2="34" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="26" y1="44" x2="50" y2="44" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="26" y1="54" x2="42" y2="54" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + </> + ), + + duplicate: ( + <> + <rect x="10" y="20" width="40" height="50" rx="3" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="22" y="10" width="40" height="50" rx="3" fill="white" stroke={MAJOR} strokeWidth="2" /> + <line x1="30" y1="26" x2="54" y2="26" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="30" y1="34" x2="50" y2="34" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="30" y1="42" x2="46" y2="42" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + </> + ), + + address: ( + <> + <ellipse cx="40" cy="72" rx="14" ry="3" fill={LIGHT} /> + <path d="M40 8 C28 8 20 16 20 28 C20 44 40 70 40 70 C40 70 60 44 60 28 C60 16 52 8 40 8 Z" fill={MAJOR} /> + <circle cx="40" cy="28" r="8" fill="white" /> + </> + ), + + people: ( + <> + <circle cx="28" cy="26" r="10" fill={MAJOR} /> + <circle cx="52" cy="26" r="10" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <path d="M10 60 Q10 46 28 46 Q46 46 46 60 L46 70 L10 70 Z" fill={MAJOR} /> + <path d="M34 60 Q34 46 52 46 Q70 46 70 60 L70 70 L46 70 L46 60 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + </> + ), + + payroll: ( + <> + <rect x="10" y="18" width="60" height="44" rx="4" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="10" y="26" width="60" height="6" fill={MAJOR} /> + <circle cx="40" cy="48" r="10" fill="white" stroke={MAJOR} strokeWidth="2" /> + <text x="40" y="52" fontSize="14" fontWeight="700" fill={MAJOR} textAnchor="middle" fontFamily="system-ui, sans-serif">€</text> + <line x1="18" y1="44" x2="26" y2="44" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="18" y1="52" x2="26" y2="52" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="54" y1="44" x2="62" y2="44" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="54" y1="52" x2="62" y2="52" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + </> + ), + + calendar: ( + <> + <rect x="10" y="16" width="60" height="56" rx="4" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="10" y="16" width="60" height="14" rx="4" fill={MAJOR} /> + <line x1="22" y1="10" x2="22" y2="22" stroke={DARK} strokeWidth="3" strokeLinecap="round" /> + <line x1="58" y1="10" x2="58" y2="22" stroke={DARK} strokeWidth="3" strokeLinecap="round" /> + <rect x="20" y="38" width="8" height="8" fill={MAJOR} /> + <rect x="36" y="38" width="8" height="8" fill={MAJOR} fillOpacity="0.4" /> + <rect x="52" y="38" width="8" height="8" fill={MAJOR} fillOpacity="0.4" /> + <rect x="20" y="52" width="8" height="8" fill={MAJOR} fillOpacity="0.4" /> + <rect x="36" y="52" width="8" height="8" fill={MAJOR} /> + <rect x="52" y="52" width="8" height="8" fill={MAJOR} fillOpacity="0.4" /> + </> + ), + + training: ( + <> + <path d="M10 30 L40 16 L70 30 L40 44 Z" fill={MAJOR} /> + <path d="M22 36 L22 54 Q22 64 40 64 Q58 64 58 54 L58 36" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <line x1="68" y1="32" x2="68" y2="50" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <circle cx="68" cy="54" r="3" fill={MAJOR} /> + </> + ), + + shopping: ( + <> + <path d="M14 20 L20 20 L26 56 Q26 60 30 60 L60 60 Q64 60 64 56 L68 30 L24 30" fill={LIGHT} stroke={MAJOR} strokeWidth="2" strokeLinejoin="round" /> + <circle cx="32" cy="68" r="4" fill={MAJOR} /> + <circle cx="58" cy="68" r="4" fill={MAJOR} /> + <path d="M30 36 L30 44 M40 36 L40 44 M50 36 L50 44 M60 36 L60 44" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + </> + ), + + news: ( + <> + <rect x="8" y="18" width="56" height="50" rx="3" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="64" y="30" width="10" height="38" rx="2" fill="white" stroke={MAJOR} strokeWidth="2" /> + <rect x="14" y="24" width="20" height="14" fill={MAJOR} /> + <line x1="38" y1="26" x2="58" y2="26" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="38" y1="32" x2="58" y2="32" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="38" y1="38" x2="54" y2="38" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="14" y1="46" x2="58" y2="46" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="14" y1="52" x2="58" y2="52" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + <line x1="14" y1="58" x2="50" y2="58" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + </> + ), + + rocket: ( + <> + <path d="M40 8 Q52 16 52 36 L52 50 L28 50 L28 36 Q28 16 40 8 Z" fill={MAJOR} /> + <circle cx="40" cy="28" r="6" fill="white" /> + <path d="M28 50 L18 60 L18 68 L28 64 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2" strokeLinejoin="round" /> + <path d="M52 50 L62 60 L62 68 L52 64 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2" strokeLinejoin="round" /> + <path d="M34 50 L34 64 L40 70 L46 64 L46 50 Z" fill={ACCENT} /> + </> + ), + + shield: ( + <> + <path d="M40 6 L66 16 L66 38 Q66 60 40 74 Q14 60 14 38 L14 16 Z" fill={MAJOR} /> + <path d="M40 14 L60 22 L60 38 Q60 54 40 66 Q20 54 20 38 L20 22 Z" fill={LIGHT} /> + <path d="M30 38 L37 45 L52 30" stroke={MAJOR} strokeWidth="3.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + </> + ), + + settings: ( + <> + <circle cx="40" cy="40" r="28" fill={LIGHT} /> + <path d="M40 14 L40 18 M40 62 L40 66 M14 40 L18 40 M62 40 L66 40 M22 22 L25 25 M55 55 L58 58 M22 58 L25 55 M55 25 L58 22" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <circle cx="40" cy="40" r="14" fill={MAJOR} /> + <circle cx="40" cy="40" r="6" fill="white" /> + </> + ), + + // ─── NOUVEAUX v0.2 ───────────────────────────────── + + success: ( + <> + {/* trophée / médaille */} + <ellipse cx="40" cy="72" rx="22" ry="3" fill={LIGHT} /> + <path d="M28 12 L52 12 L52 28 Q52 44 40 50 Q28 44 28 28 Z" fill={MAJOR} /> + <path d="M28 18 L18 18 L18 28 Q18 38 28 38" fill="none" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <path d="M52 18 L62 18 L62 28 Q62 38 52 38" fill="none" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <rect x="34" y="50" width="12" height="14" fill={MINOR} /> + <rect x="26" y="62" width="28" height="6" rx="2" fill={DARK} /> + <path d="M36 24 L40 30 L46 18" stroke="white" strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + </> + ), + + alert: ( + <> + <path d="M40 8 L72 64 L8 64 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" strokeLinejoin="round" /> + <rect x="37" y="28" width="6" height="20" rx="2" fill={MAJOR} /> + <circle cx="40" cy="56" r="3" fill={MAJOR} /> + </> + ), + + search: ( + <> + <circle cx="32" cy="32" r="20" fill={LIGHT} stroke={MAJOR} strokeWidth="3" /> + <circle cx="32" cy="32" r="10" fill="white" stroke={MAJOR} strokeWidth="2" /> + <line x1="48" y1="48" x2="68" y2="68" stroke={MAJOR} strokeWidth="6" strokeLinecap="round" /> + </> + ), + + support: ( + <> + {/* casque audio + bulle */} + <path d="M14 44 Q14 18 40 18 Q66 18 66 44 L66 54" fill="none" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <rect x="10" y="44" width="14" height="22" rx="4" fill={MAJOR} /> + <rect x="56" y="44" width="14" height="22" rx="4" fill={MAJOR} /> + <path d="M58 64 Q58 72 50 72 L42 72" fill="none" stroke={DARK} strokeWidth="2.5" strokeLinecap="round" /> + <circle cx="40" cy="72" r="3" fill={DARK} /> + </> + ), + + growth: ( + <> + {/* graphe en barres + flèche montante */} + <line x1="12" y1="68" x2="68" y2="68" stroke={DARK} strokeWidth="2.5" strokeLinecap="round" /> + <line x1="12" y1="68" x2="12" y2="14" stroke={DARK} strokeWidth="2.5" strokeLinecap="round" /> + <rect x="20" y="48" width="10" height="20" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="34" y="36" width="10" height="32" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="48" y="22" width="10" height="46" fill={MAJOR} /> + <path d="M16 56 L30 42 L44 30 L60 16" stroke={MAJOR} strokeWidth="3" fill="none" strokeLinecap="round" /> + <path d="M52 16 L60 16 L60 24" stroke={MAJOR} strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + </> + ), + + target: ( + <> + <circle cx="40" cy="40" r="32" fill={LIGHT} /> + <circle cx="40" cy="40" r="22" fill="white" stroke={MAJOR} strokeWidth="2.5" /> + <circle cx="40" cy="40" r="12" fill={MAJOR} /> + <circle cx="40" cy="40" r="4" fill="white" /> + <path d="M58 22 L70 10 M58 22 L65 22 M58 22 L58 15" stroke={DARK} strokeWidth="2.5" fill="none" strokeLinecap="round" /> + </> + ), + + innovation: ( + <> + {/* ampoule */} + <path d="M40 8 Q22 8 22 28 Q22 38 30 46 L30 56 L50 56 L50 46 Q58 38 58 28 Q58 8 40 8 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" /> + <rect x="32" y="58" width="16" height="6" rx="1" fill={DARK} /> + <rect x="34" y="66" width="12" height="4" rx="1" fill={DARK} /> + <path d="M40 22 L40 42 M34 28 L40 22 L46 28" stroke={MAJOR} strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + <circle cx="14" cy="20" r="2.5" fill={MAJOR} /> + <circle cx="66" cy="20" r="2.5" fill={MAJOR} /> + <circle cx="40" cy="74" r="0" /> + </> + ), + + savings: ( + <> + {/* tirelire */} + <ellipse cx="40" cy="74" rx="20" ry="2" fill={LIGHT} /> + <path d="M16 44 Q16 28 32 24 Q34 18 40 18 Q46 18 48 24 Q64 28 64 44 L64 56 Q64 66 50 66 L30 66 Q16 66 16 56 Z" fill={MAJOR} /> + <circle cx="56" cy="38" r="3" fill="white" /> + <rect x="34" y="20" width="12" height="3" rx="1" fill={DARK} /> + <line x1="32" y1="64" x2="32" y2="72" stroke={DARK} strokeWidth="3" strokeLinecap="round" /> + <line x1="48" y1="64" x2="48" y2="72" stroke={DARK} strokeWidth="3" strokeLinecap="round" /> + </> + ), + + handshake: ( + <> + {/* poignée de main */} + <rect x="6" y="32" width="22" height="14" rx="2" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="52" y="32" width="22" height="14" rx="2" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <path d="M28 38 L34 38 L40 44 L48 36 L52 36" stroke={MAJOR} strokeWidth="3" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + <path d="M40 44 L46 50 L52 44 L48 40" fill={MAJOR} /> + <path d="M28 32 L48 32" stroke={MAJOR} strokeWidth="2.5" strokeLinecap="round" /> + </> + ), + + cloud: ( + <> + <path d="M22 50 Q12 50 12 40 Q12 30 22 28 Q24 18 36 18 Q48 18 50 26 Q60 24 64 32 Q72 32 72 42 Q72 52 62 52 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" strokeLinejoin="round" /> + <path d="M40 36 L40 56 M32 50 L40 56 L48 50" stroke={MAJOR} strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + </> + ), + + "lock-secure": ( + <> + <rect x="16" y="34" width="48" height="36" rx="4" fill={MAJOR} /> + <path d="M22 34 L22 24 Q22 8 40 8 Q58 8 58 24 L58 34" fill="none" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <circle cx="40" cy="48" r="6" fill={LIGHT} /> + <rect x="38" y="50" width="4" height="10" rx="1" fill={LIGHT} /> + </> + ), + + globe: ( + <> + <circle cx="40" cy="40" r="30" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" /> + <ellipse cx="40" cy="40" rx="14" ry="30" fill="none" stroke={MAJOR} strokeWidth="2" /> + <line x1="10" y1="40" x2="70" y2="40" stroke={MAJOR} strokeWidth="2" /> + <path d="M14 28 Q40 22 66 28" fill="none" stroke={MAJOR} strokeWidth="2" /> + <path d="M14 52 Q40 58 66 52" fill="none" stroke={MAJOR} strokeWidth="2" /> + <circle cx="58" cy="22" r="4" fill={ACCENT} /> + </> + ), + + mobile: ( + <> + <rect x="22" y="8" width="36" height="64" rx="6" fill={MAJOR} /> + <rect x="26" y="14" width="28" height="46" rx="2" fill={LIGHT} /> + <circle cx="40" cy="66" r="2.5" fill="white" /> + <line x1="34" y1="11" x2="46" y2="11" stroke="white" strokeWidth="1.5" strokeLinecap="round" /> + <rect x="32" y="22" width="16" height="2.5" rx="1" fill={MAJOR} /> + <rect x="32" y="30" width="12" height="2.5" rx="1" fill={DARK} /> + <rect x="32" y="38" width="14" height="2.5" rx="1" fill={DARK} /> + </> + ), + + analytics: ( + <> + {/* écran avec graphe */} + <rect x="6" y="14" width="68" height="44" rx="3" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="32" y="60" width="16" height="4" fill={DARK} /> + <rect x="22" y="64" width="36" height="4" rx="1" fill={DARK} /> + <polyline points="14,46 24,38 32,42 42,28 52,32 66,20" fill="none" stroke={MAJOR} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" /> + <circle cx="14" cy="46" r="2.5" fill={MAJOR} /> + <circle cx="42" cy="28" r="2.5" fill={MAJOR} /> + <circle cx="66" cy="20" r="2.5" fill={MAJOR} /> + </> + ), + + gift: ( + <> + <rect x="10" y="32" width="60" height="38" rx="3" fill={MAJOR} /> + <rect x="10" y="22" width="60" height="14" rx="2" fill={MINOR} /> + <rect x="36" y="22" width="8" height="48" fill={LIGHT} /> + <path d="M28 22 Q24 14 28 10 Q32 6 36 10 Q40 14 40 22" fill="none" stroke={LIGHT} strokeWidth="3" strokeLinecap="round" /> + <path d="M52 22 Q56 14 52 10 Q48 6 44 10 Q40 14 40 22" fill="none" stroke={LIGHT} strokeWidth="3" strokeLinecap="round" /> + </> + ), + + messaging: ( + <> + <path d="M10 18 Q10 14 14 14 L66 14 Q70 14 70 18 L70 50 Q70 54 66 54 L32 54 L20 66 L20 54 L14 54 Q10 54 10 50 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" strokeLinejoin="round" /> + <circle cx="26" cy="34" r="3" fill={MAJOR} /> + <circle cx="40" cy="34" r="3" fill={MAJOR} /> + <circle cx="54" cy="34" r="3" fill={MAJOR} /> + </> + ), + + // ─── Marine v0.5 (defense.gouv-inspired) ───────────────── + "marine-casquette": ( + <> + {/* casquette d'officier de marine — visière arrondie + bande + insigne */} + <ellipse cx="40" cy="68" rx="26" ry="3" fill={LIGHT} /> + {/* visière */} + <path d="M14 56 Q14 52 18 50 L62 50 Q66 52 66 56 Q66 60 62 60 L18 60 Q14 60 14 56 Z" fill={MINOR} /> + {/* bande dorée (band) */} + <rect x="14" y="44" width="52" height="6" fill={DARK} /> + {/* dôme principal */} + <path d="M16 44 Q16 18 40 18 Q64 18 64 44 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" strokeLinejoin="round" /> + {/* insigne ancré */} + <circle cx="40" cy="32" r="6" fill={MAJOR} /> + <line x1="40" y1="28" x2="40" y2="38" stroke="white" strokeWidth="1.5" strokeLinecap="round" /> + <path d="M36 36 Q40 40 44 36" stroke="white" strokeWidth="1.5" fill="none" strokeLinecap="round" /> + {/* feuille d'olivier sur la visière */} + <path d="M22 54 Q26 56 30 54" stroke={DARK} strokeWidth="1" fill="none" strokeLinecap="round" /> + <path d="M50 54 Q54 56 58 54" stroke={DARK} strokeWidth="1" fill="none" strokeLinecap="round" /> + </> + ), + + "marine-ancre": ( + <> + {/* ombre */} + <ellipse cx="40" cy="74" rx="20" ry="2" fill={LIGHT} /> + {/* anneau supérieur */} + <circle cx="40" cy="14" r="6" fill="none" stroke={MAJOR} strokeWidth="3" /> + {/* tige verticale */} + <line x1="40" y1="20" x2="40" y2="60" stroke={MAJOR} strokeWidth="4" strokeLinecap="round" /> + {/* barre horizontale (jas) */} + <line x1="26" y1="28" x2="54" y2="28" stroke={MAJOR} strokeWidth="3.5" strokeLinecap="round" /> + <circle cx="26" cy="28" r="2.5" fill={MAJOR} /> + <circle cx="54" cy="28" r="2.5" fill={MAJOR} /> + {/* bras gauche + patte */} + <path d="M40 56 Q22 56 16 44" fill="none" stroke={MAJOR} strokeWidth="3.5" strokeLinecap="round" /> + <path d="M16 44 L12 50 M16 44 L20 48" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + {/* bras droit + patte */} + <path d="M40 56 Q58 56 64 44" fill="none" stroke={MAJOR} strokeWidth="3.5" strokeLinecap="round" /> + <path d="M64 44 L68 50 M64 44 L60 48" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + {/* corde enroulée — visualisée par 2 ondes */} + <path d="M30 68 Q35 64 40 68 T50 68" fill="none" stroke={DARK} strokeWidth="2" strokeLinecap="round" /> + </> + ), + + // ─── ManageMate Group products v0.6 ─────────────── + + /* Synapse — flux/connexion (réseau de neurones) */ + synapse: ( + <> + <ellipse cx="40" cy="72" rx="20" ry="2" fill={LIGHT} /> + {/* Nœuds (neurones) */} + <circle cx="20" cy="20" r="6" fill={MAJOR} /> + <circle cx="60" cy="20" r="6" fill={MAJOR} /> + <circle cx="14" cy="48" r="6" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <circle cx="40" cy="40" r="9" fill={MAJOR} /> + <circle cx="66" cy="48" r="6" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <circle cx="40" cy="66" r="6" fill={MINOR} /> + {/* Synapses (connexions) */} + <line x1="20" y1="20" x2="40" y2="40" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="60" y1="20" x2="40" y2="40" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="14" y1="48" x2="40" y2="40" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="66" y1="48" x2="40" y2="40" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="40" y1="40" x2="40" y2="66" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + {/* Pulse au centre */} + <circle cx="40" cy="40" r="4" fill="white" /> + </> + ), + + /* HRTime — équipe + horloge (gestion du temps RH) */ + hrtime: ( + <> + <ellipse cx="40" cy="72" rx="22" ry="2" fill={LIGHT} /> + {/* Cadran d'horloge en arrière-plan */} + <circle cx="40" cy="40" r="28" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + {/* Marques d'heures */} + <line x1="40" y1="14" x2="40" y2="18" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="40" y1="62" x2="40" y2="66" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="14" y1="40" x2="18" y2="40" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <line x1="62" y1="40" x2="66" y2="40" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + {/* Aiguilles */} + <line x1="40" y1="40" x2="40" y2="24" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <line x1="40" y1="40" x2="52" y2="44" stroke={MAJOR} strokeWidth="3" strokeLinecap="round" /> + <circle cx="40" cy="40" r="3" fill={MAJOR} /> + {/* Trois personnes en silhouette devant l'horloge */} + <circle cx="28" cy="50" r="5" fill={MAJOR} /> + <path d="M20 66 Q20 56 28 56 Q36 56 36 66 Z" fill={MAJOR} /> + <circle cx="52" cy="50" r="5" fill={MAJOR} /> + <path d="M44 66 Q44 56 52 56 Q60 56 60 66 Z" fill={MAJOR} /> + </> + ), + + /* Forge — outils (clé + engrenage = construire) */ + forge: ( + <> + <ellipse cx="40" cy="72" rx="20" ry="2" fill={LIGHT} /> + {/* Engrenage central */} + <circle cx="42" cy="38" r="14" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" /> + {/* Dents de l'engrenage */} + <rect x="40" y="18" width="4" height="6" fill={MAJOR} /> + <rect x="40" y="52" width="4" height="6" fill={MAJOR} /> + <rect x="22" y="36" width="6" height="4" fill={MAJOR} /> + <rect x="56" y="36" width="6" height="4" fill={MAJOR} /> + <rect x="27" y="22" width="6" height="4" fill={MAJOR} transform="rotate(-45 30 24)" /> + <rect x="51" y="22" width="6" height="4" fill={MAJOR} transform="rotate(45 54 24)" /> + <rect x="27" y="50" width="6" height="4" fill={MAJOR} transform="rotate(45 30 52)" /> + <rect x="51" y="50" width="6" height="4" fill={MAJOR} transform="rotate(-45 54 52)" /> + <circle cx="42" cy="38" r="5" fill={MAJOR} /> + {/* Clé qui croise l'engrenage */} + <circle cx="14" cy="60" r="6" fill="none" stroke={MAJOR} strokeWidth="3" /> + <line x1="18" y1="56" x2="32" y2="42" stroke={MAJOR} strokeWidth="3.5" strokeLinecap="round" /> + <line x1="28" y1="46" x2="32" y2="50" stroke={MAJOR} strokeWidth="3.5" strokeLinecap="round" /> + <line x1="34" y1="40" x2="36" y2="42" stroke={MAJOR} strokeWidth="3.5" strokeLinecap="round" /> + </> + ), + + /* Orbit — planète + satellites (data orchestration) */ + orbit: ( + <> + <ellipse cx="40" cy="72" rx="22" ry="2" fill={LIGHT} /> + {/* Orbite extérieure (anneau elliptique) */} + <ellipse + cx="40" + cy="40" + rx="32" + ry="14" + fill="none" + stroke={MAJOR} + strokeWidth="2" + strokeDasharray="3 4" + transform="rotate(-25 40 40)" + /> + {/* Planète centrale */} + <circle cx="40" cy="40" r="14" fill={MAJOR} /> + <ellipse cx="40" cy="40" rx="14" ry="5" fill={MINOR} opacity="0.7" /> + <circle cx="36" cy="36" r="3" fill="white" opacity="0.5" /> + {/* Satellites sur l'orbite */} + <circle cx="68" cy="28" r="4" fill={MAJOR} /> + <circle cx="14" cy="56" r="3" fill={MAJOR} /> + <circle cx="62" cy="58" r="3" fill={MINOR} /> + {/* Trail */} + <path d="M68 28 Q66 30 64 30" stroke={MAJOR} strokeWidth="1" strokeLinecap="round" opacity="0.4" /> + </> + ), + + /* Automation — robot/process automatisé */ + automation: ( + <> + <ellipse cx="40" cy="72" rx="20" ry="2" fill={LIGHT} /> + {/* Tête du robot */} + <rect x="20" y="20" width="40" height="32" rx="6" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" /> + {/* Antenne */} + <line x1="40" y1="14" x2="40" y2="20" stroke={MAJOR} strokeWidth="2.5" strokeLinecap="round" /> + <circle cx="40" cy="12" r="3" fill={MAJOR} /> + {/* Yeux */} + <circle cx="30" cy="34" r="4" fill={MAJOR} /> + <circle cx="50" cy="34" r="4" fill={MAJOR} /> + <circle cx="30" cy="34" r="1.5" fill="white" /> + <circle cx="50" cy="34" r="1.5" fill="white" /> + {/* Bouche / interface */} + <rect x="32" y="42" width="16" height="3" rx="1" fill={MAJOR} /> + {/* Corps avec circuits */} + <rect x="26" y="54" width="28" height="14" rx="3" fill={MAJOR} /> + <line x1="32" y1="60" x2="36" y2="60" stroke="white" strokeWidth="1.5" strokeLinecap="round" /> + <line x1="40" y1="60" x2="48" y2="60" stroke="white" strokeWidth="1.5" strokeLinecap="round" /> + </> + ), + + /* Insights — loupe + données (analytique) */ + insights: ( + <> + <ellipse cx="40" cy="72" rx="20" ry="2" fill={LIGHT} /> + {/* Tableau de bord en arrière */} + <rect x="14" y="14" width="44" height="36" rx="3" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + <rect x="20" y="20" width="14" height="3" rx="1" fill={MAJOR} opacity="0.6" /> + {/* Mini barchart */} + <rect x="20" y="38" width="4" height="8" fill={MAJOR} /> + <rect x="26" y="32" width="4" height="14" fill={MAJOR} /> + <rect x="32" y="36" width="4" height="10" fill={MAJOR} opacity="0.7" /> + <rect x="38" y="28" width="4" height="18" fill={MAJOR} /> + <rect x="44" y="34" width="4" height="12" fill={MAJOR} opacity="0.7" /> + {/* Loupe en superposition */} + <circle cx="50" cy="50" r="14" fill="white" stroke={MAJOR} strokeWidth="3" /> + <line x1="60" y1="60" x2="70" y2="70" stroke={MAJOR} strokeWidth="4" strokeLinecap="round" /> + {/* Trend line dans la loupe */} + <polyline points="42,54 46,50 50,52 54,46 58,48" fill="none" stroke={MAJOR} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" /> + </> + ), + + /* Integration — modules connectés (puzzle/blocks) */ + integration: ( + <> + <ellipse cx="40" cy="72" rx="20" ry="2" fill={LIGHT} /> + {/* Bloc supérieur gauche */} + <path d="M14 16 L34 16 L34 24 Q34 28 38 28 Q42 28 42 24 L42 16 L42 36 L34 36 Q30 36 30 40 Q30 44 34 44 L42 44 L42 50 L14 50 Z" fill={MAJOR} /> + {/* Bloc inférieur droit complémentaire */} + <path d="M42 30 L62 30 L62 50 L62 60 Q62 64 58 64 Q54 64 54 60 L54 56 L42 56 Z" fill={LIGHT} stroke={MAJOR} strokeWidth="2" /> + {/* Bloc top droit */} + <rect x="48" y="14" width="20" height="14" rx="3" fill={MINOR} /> + {/* Petits accent */} + <circle cx="58" cy="21" r="2" fill="white" /> + </> + ), + + /* Workflow — flèches en boucle (process) */ + workflow: ( + <> + <ellipse cx="40" cy="72" rx="22" ry="2" fill={LIGHT} /> + {/* Étape 1 (cercle haut gauche) */} + <circle cx="22" cy="22" r="10" fill={MAJOR} /> + <text x="22" y="27" fontSize="14" fontWeight="700" fill="white" textAnchor="middle" fontFamily="system-ui, sans-serif">1</text> + {/* Étape 2 (cercle haut droit) */} + <circle cx="58" cy="22" r="10" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" /> + <text x="58" y="27" fontSize="14" fontWeight="700" fill={MAJOR} textAnchor="middle" fontFamily="system-ui, sans-serif">2</text> + {/* Étape 3 (cercle bas droit) */} + <circle cx="58" cy="58" r="10" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" /> + <text x="58" y="63" fontSize="14" fontWeight="700" fill={MAJOR} textAnchor="middle" fontFamily="system-ui, sans-serif">3</text> + {/* Étape 4 (cercle bas gauche) */} + <circle cx="22" cy="58" r="10" fill={LIGHT} stroke={MAJOR} strokeWidth="2.5" /> + <text x="22" y="63" fontSize="14" fontWeight="700" fill={MAJOR} textAnchor="middle" fontFamily="system-ui, sans-serif">4</text> + {/* Flèches entre les étapes */} + <path d="M32 22 L48 22" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <path d="M44 19 L48 22 L44 25" stroke={MAJOR} strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + <path d="M58 32 L58 48" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <path d="M55 44 L58 48 L61 44" stroke={MAJOR} strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + <path d="M48 58 L32 58" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <path d="M36 55 L32 58 L36 61" stroke={MAJOR} strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + <path d="M22 48 L22 32" stroke={MAJOR} strokeWidth="2" strokeLinecap="round" /> + <path d="M19 36 L22 32 L25 36" stroke={MAJOR} strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" /> + </> + ), + + "marine-porte-avion": ( + <> + {/* mer + reflets */} + <path d="M0 64 Q20 60 40 64 T80 64 L80 80 L0 80 Z" fill={LIGHT} /> + <path d="M4 70 Q14 68 24 70" stroke={ACCENT} strokeWidth="1.5" fill="none" strokeLinecap="round" /> + <path d="M50 72 Q60 70 70 72" stroke={ACCENT} strokeWidth="1.5" fill="none" strokeLinecap="round" /> + {/* coque grise */} + <path d="M4 56 L76 56 L70 64 L10 64 Z" fill={DARK} /> + {/* pont d'envol — plan supérieur avec angle */} + <path d="M2 50 L78 50 L74 56 L6 56 Z" fill="#3D4757" /> + {/* îlot (tour de commandement) */} + <rect x="48" y="32" width="12" height="18" fill={DARK} /> + <rect x="50" y="34" width="3" height="3" fill={LIGHT} /> + <rect x="55" y="34" width="3" height="3" fill={LIGHT} /> + <rect x="50" y="40" width="3" height="3" fill={LIGHT} /> + <rect x="55" y="40" width="3" height="3" fill={LIGHT} /> + {/* radar — mât + plateau */} + <line x1="54" y1="20" x2="54" y2="32" stroke={DARK} strokeWidth="2" /> + <ellipse cx="54" cy="20" rx="6" ry="2" fill={MAJOR} /> + {/* tour antenne secondaire */} + <line x1="60" y1="26" x2="60" y2="32" stroke={DARK} strokeWidth="1.5" /> + <circle cx="60" cy="26" r="1.5" fill={MAJOR} /> + {/* avion sur le pont — silhouette simplifiée */} + <path d="M14 48 L24 44 L28 44 L26 48 L18 50 Z" fill={MAJOR} /> + <path d="M22 44 L22 40 M26 46 L30 44" stroke={MAJOR} strokeWidth="1.5" strokeLinecap="round" /> + {/* marquage centré du pont */} + <line x1="32" y1="53" x2="44" y2="53" stroke="white" strokeWidth="1" strokeDasharray="2 2" /> + </> + ), +}; + +export type PictogramProps = { + name: PictogramName; + size?: number; + className?: string; + style?: CSSProperties; + title?: string; +}; + +export function Pictogram({ + name, + size = 80, + className, + style, + title, +}: PictogramProps) { + return ( + <svg + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 80 80" + width={size} + height={size} + className={cx("mmg-pictogram", className)} + style={style} + role={title ? "img" : "presentation"} + aria-label={title} + > + {title && <title>{title}} + {PICTOS[name]} + + ); +} + +export const PICTOGRAM_NAMES: PictogramName[] = [ + "certificate", "transfer", "document", "duplicate", "address", + "people", "payroll", "calendar", "training", "shopping", "news", + "rocket", "shield", "settings", + "success", "alert", "search", "support", "growth", "target", + "innovation", "savings", "handshake", "cloud", "lock-secure", + "globe", "mobile", "analytics", "gift", "messaging", + "marine-casquette", "marine-ancre", "marine-porte-avion", + "synapse", "hrtime", "forge", "orbit", + "automation", "insights", "integration", "workflow", +]; diff --git a/packages/react/src/Popover.tsx b/packages/react/src/Popover.tsx new file mode 100644 index 0000000..0b6d04b --- /dev/null +++ b/packages/react/src/Popover.tsx @@ -0,0 +1,55 @@ +import { type ReactNode } from "react"; +import * as RadixPopover from "@radix-ui/react-popover"; +import { cx } from "./utils"; + +export type PopoverProps = { + trigger: ReactNode; + children: ReactNode; + open?: boolean; + onOpenChange?: (open: boolean) => void; + defaultOpen?: boolean; + side?: "top" | "right" | "bottom" | "left"; + align?: "start" | "center" | "end"; + sideOffset?: number; + modal?: boolean; + className?: string; +}; + +/** + * Popover — wrapper Radix UI Popover. + * + * Couvre les cas usuels (trigger + contenu). Pour des compositions plus + * fines (close button, anchor séparé, sub-popover) utiliser PopoverPrimitive. + */ +export function Popover({ + trigger, + children, + open, + onOpenChange, + defaultOpen, + side = "bottom", + align = "start", + sideOffset = 8, + modal, + className, +}: PopoverProps) { + return ( + + {trigger} + + + {children} + + + + + ); +} + +export { RadixPopover as PopoverPrimitive }; diff --git a/packages/react/src/PricingCard.tsx b/packages/react/src/PricingCard.tsx new file mode 100644 index 0000000..23357e7 --- /dev/null +++ b/packages/react/src/PricingCard.tsx @@ -0,0 +1,90 @@ +import { type ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; + +export type PricingFeature = { + label: ReactNode; + /** Si false, affiche un icône "x" (feature non incluse dans ce tier). */ + included?: boolean; + /** Texte d'aide en survol. */ + hint?: ReactNode; +}; + +export type PricingCardProps = { + /** Nom du plan (ex: "Starter", "Pro", "Enterprise"). */ + name: ReactNode; + /** Description courte sous le nom. */ + description?: ReactNode; + /** Prix principal (ex: "29 €", "Sur devis"). */ + price: ReactNode; + /** Suffixe du prix (ex: "/ mois / utilisateur"). */ + pricePeriod?: ReactNode; + /** Liste de features. */ + features: PricingFeature[]; + /** CTA principal. */ + cta: ReactNode; + /** Marque ce plan comme "recommandé" (mise en avant visuelle). */ + highlighted?: boolean; + /** Badge en haut à droite (ex: "Populaire", "-20%"). */ + badge?: ReactNode; + className?: string; +}; + +/** + * PricingCard — carte de tarification. + * + * Pattern Stripe / Vercel / Linear : nom + prix + features + CTA. Une + * variante `highlighted` met en avant le plan recommandé via une bordure + * accent et un fond légèrement teinté. + */ +export function PricingCard({ + name, + description, + price, + pricePeriod, + features, + cta, + highlighted, + badge, + className, +}: PricingCardProps) { + return ( +
+ {badge &&
{badge}
} +
+

{name}

+ {description &&

{description}

} +
+
+ {price} + {pricePeriod && {pricePeriod}} +
+
    + {features.map((f, i) => ( +
  • + + {f.label} +
  • + ))} +
+
{cta}
+
+ ); +} diff --git a/packages/react/src/ProfileHeader.tsx b/packages/react/src/ProfileHeader.tsx new file mode 100644 index 0000000..7f9da10 --- /dev/null +++ b/packages/react/src/ProfileHeader.tsx @@ -0,0 +1,92 @@ +import { type ReactNode } from "react"; +import { cx } from "./utils"; +import { Avatar, type AvatarStatus } from "./Avatar"; + +export type ProfileHeaderProps = { + name: ReactNode; + /** Sous-titre (poste, organisation…). */ + subtitle?: ReactNode; + /** Description longue / bio. */ + bio?: ReactNode; + /** URL de la photo de profil. */ + src?: string; + initials?: string; + status?: AvatarStatus; + /** URL de la photo de couverture (cover). Si absente, gradient accent. */ + coverSrc?: string; + /** Stats à droite des actions (commits, reviews, années…). */ + stats?: { label: ReactNode; value: ReactNode }[]; + /** Slot d'actions sous la bio (boutons, menu…). */ + actions?: ReactNode; + /** Slot de badges (sous le nom). */ + badges?: ReactNode; + className?: string; +}; + +/** + * ProfileHeader — en-tête de profil avec photo de couverture + avatar + * en débord (LinkedIn / GitHub / Twitter pattern). + * + * - Cover : image fournie ou gradient accent par défaut. + * - Avatar large (xl) en débord sur la cover. + * - Identité (nom + sous-titre + bio). + * - Stats inline + actions (Suivre, Message…). + */ +export function ProfileHeader({ + name, + subtitle, + bio, + src, + initials, + status, + coverSrc, + stats, + actions, + badges, + className, +}: ProfileHeaderProps) { + return ( +
+
+ {coverSrc ? ( + + ) : ( +
+ )} +
+
+
+ +
+
+
+
+

{name}

+ {subtitle &&
{subtitle}
} + {badges &&
{badges}
} +
+ {actions &&
{actions}
} +
+ {bio &&

{bio}

} + {stats && stats.length > 0 && ( +
+ {stats.map((s, i) => ( +
+
{s.label}
+
{s.value}
+
+ ))} +
+ )} +
+
+
+ ); +} diff --git a/packages/react/src/Progress.tsx b/packages/react/src/Progress.tsx new file mode 100644 index 0000000..9016daf --- /dev/null +++ b/packages/react/src/Progress.tsx @@ -0,0 +1,37 @@ +import type { HTMLAttributes } from "react"; +import { cx } from "./utils"; + +export type ProgressProps = HTMLAttributes & { + value?: number; + max?: number; + variant?: "success" | "warning" | "danger"; + indeterminate?: boolean; +}; + +export function Progress({ + value, + max = 100, + variant, + indeterminate, + className, + ...rest +}: ProgressProps) { + const pct = indeterminate ? 100 : Math.min(100, Math.max(0, ((value ?? 0) / max) * 100)); + return ( +
+
+
+ ); +} diff --git a/packages/react/src/Quote.tsx b/packages/react/src/Quote.tsx new file mode 100644 index 0000000..1f30bc1 --- /dev/null +++ b/packages/react/src/Quote.tsx @@ -0,0 +1,17 @@ +import type { ReactNode } from "react"; +import { cx } from "./utils"; + +export type QuoteProps = { + author?: ReactNode; + children: ReactNode; + className?: string; +}; + +export function Quote({ author, children, className }: QuoteProps) { + return ( +
+

{children}

+ {author && — {author}} +
+ ); +} diff --git a/packages/react/src/SearchBar.tsx b/packages/react/src/SearchBar.tsx new file mode 100644 index 0000000..ec2a525 --- /dev/null +++ b/packages/react/src/SearchBar.tsx @@ -0,0 +1,39 @@ +import { useState, type InputHTMLAttributes } from "react"; +import { cx } from "./utils"; + +export type SearchBarProps = Omit, "onSubmit"> & { + onSearch?: (q: string) => void; + buttonLabel?: string; +}; + +export function SearchBar({ + placeholder = "Rechercher…", + onSearch, + buttonLabel = "Rechercher", + className, + ...rest +}: SearchBarProps) { + const [val, setVal] = useState(""); + return ( +
{ + e.preventDefault(); + onSearch?.(val); + }} + > + setVal(e.target.value)} + {...rest} + /> + +
+ ); +} diff --git a/packages/react/src/Sheet.tsx b/packages/react/src/Sheet.tsx new file mode 100644 index 0000000..f7dd9dc --- /dev/null +++ b/packages/react/src/Sheet.tsx @@ -0,0 +1,90 @@ +import { type ReactNode } from "react"; +import * as RadixDialog from "@radix-ui/react-dialog"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; + +export type SheetSide = "left" | "right" | "top" | "bottom"; +export type SheetSize = "sm" | "md" | "lg" | "xl" | "full"; + +export type SheetProps = { + open: boolean; + onOpenChange: (open: boolean) => void; + /** Côté d'apparition. Défaut "right" (le plus courant pour un sheet desktop). */ + side?: SheetSide; + /** Largeur (left/right) ou hauteur (top/bottom). */ + size?: SheetSize; + title?: ReactNode; + description?: ReactNode; + children: ReactNode; + footer?: ReactNode; + /** Cache le bouton de fermeture en haut à droite. */ + hideClose?: boolean; + className?: string; +}; + +/** + * Sheet — panneau latéral / drawer (Radix Dialog avec position custom). + * + * Différence avec Dialog : Sheet glisse depuis un bord (latéral, top, bottom). + * Différence avec Drawer (legacy) : Sheet utilise Radix → focus trap, scroll + * lock, restitution focus, escape, aria-* tout est natif. Préférer Sheet. + * + * Usage typique : édition rapide d'une ressource, navigation mobile, + * filtres avancés, prévisualisation détaillée. + */ +export function Sheet({ + open, + onOpenChange, + side = "right", + size = "md", + title, + description, + children, + footer, + hideClose, + className, +}: SheetProps) { + return ( + + + + + {(title || !hideClose) && ( +
+
+ {title && ( + + {title} + + )} + {description && ( + + {description} + + )} +
+ {!hideClose && ( + + + + )} +
+ )} +
{children}
+ {footer &&
{footer}
} +
+
+
+ ); +} + +export { RadixDialog as SheetPrimitive }; diff --git a/packages/react/src/Shortcut.tsx b/packages/react/src/Shortcut.tsx new file mode 100644 index 0000000..ad41bac --- /dev/null +++ b/packages/react/src/Shortcut.tsx @@ -0,0 +1,364 @@ +import { + createContext, + useCallback, + useContext, + useEffect, + useMemo, + useRef, + useState, + type ReactNode, +} from "react"; + +/** + * Système global de raccourcis clavier — DSMMG. + * + * Architecture : + * - au sommet de l'app + * - useShortcut(key, handler, options) dans n'importe quel composant + * - ou hook useShortcutList() pour afficher tous + * les raccourcis enregistrés + * + * Conformité a11y : + * - WCAG 2.1.1 (clavier) : tout le système est navigable au clavier + * - WCAG 2.1.4 (raccourcis caractère seul) : on accepte les modifiers + * Ctrl/Cmd/Alt/Shift, ou les chords (g i) — un caractère unique seul + * est désactivé si une saisie est focus (input, textarea, contenteditable) + * + * Format de clé : + * - "cmd+k", "ctrl+/", "shift+?" + * - Chord : "g i", "g h", "y y" + * - Touche simple : "/" , "?" (uniquement si aucun champ focus) + */ + +export type ShortcutOptions = { + /** Catégorie pour le regroupement dans la cheatsheet */ + category?: string; + /** Description affichée dans la cheatsheet */ + description?: string; + /** Désactive le raccourci si vrai */ + disabled?: boolean; + /** Autorise même quand un input/textarea est focusé */ + allowInInput?: boolean; + /** Empêche le default du browser */ + preventDefault?: boolean; +}; + +export type ShortcutEntry = { + id: string; + keys: string; + category: string; + description: string; +}; + +type ShortcutHandler = (event: KeyboardEvent) => void; + +type Registered = { + keys: string; + handler: ShortcutHandler; + options: ShortcutOptions; +}; + +type Ctx = { + register: (id: string, entry: Registered) => () => void; + list: () => ShortcutEntry[]; +}; + +const ShortcutContext = createContext(null); + +const isMac = + typeof navigator !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.platform); + +function normalizeCombo(combo: string): string { + return combo + .toLowerCase() + .split("+") + .map((p) => p.trim()) + .map((p) => (p === "cmd" || p === "meta" ? (isMac ? "meta" : "ctrl") : p)) + .sort() + .join("+"); +} + +function eventToCombo(e: KeyboardEvent): string { + const parts: string[] = []; + if (e.ctrlKey) parts.push("ctrl"); + if (e.metaKey) parts.push("meta"); + if (e.altKey) parts.push("alt"); + if (e.shiftKey) parts.push("shift"); + // Skip the modifier itself if user is just holding modifiers + const k = e.key.toLowerCase(); + if (!["control", "meta", "alt", "shift"].includes(k)) parts.push(k); + return parts.sort().join("+"); +} + +function isInsideEditableElement(target: EventTarget | null): boolean { + if (!(target instanceof HTMLElement)) return false; + const tag = target.tagName; + if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true; + if (target.isContentEditable) return true; + return false; +} + +export function ShortcutProvider({ children }: { children: ReactNode }) { + const registry = useRef(new Map()); + const chordBuffer = useRef<{ key: string; expires: number } | null>(null); + const CHORD_WINDOW_MS = 800; + + const register = useCallback((id: string, entry: Registered) => { + registry.current.set(id, entry); + return () => { + registry.current.delete(id); + }; + }, []); + + const list = useCallback((): ShortcutEntry[] => { + return Array.from(registry.current.entries()).map(([id, e]) => ({ + id, + keys: e.keys, + category: e.options.category ?? "Général", + description: e.options.description ?? "", + })); + }, []); + + useEffect(() => { + const onKey = (e: KeyboardEvent) => { + const inEditable = isInsideEditableElement(e.target); + + const combo = eventToCombo(e); + const now = Date.now(); + + // Test chord + if (chordBuffer.current && chordBuffer.current.expires > now) { + const chordCombo = `${chordBuffer.current.key} ${combo}`; + for (const [, entry] of registry.current) { + if (entry.options.disabled) continue; + if (inEditable && !entry.options.allowInInput) continue; + const normalized = entry.keys + .split(" ") + .map(normalizeCombo) + .join(" "); + if (normalized === chordCombo) { + if (entry.options.preventDefault !== false) e.preventDefault(); + entry.handler(e); + chordBuffer.current = null; + return; + } + } + } + + // Test single combo + for (const [, entry] of registry.current) { + if (entry.options.disabled) continue; + if (inEditable && !entry.options.allowInInput) continue; + const normalized = normalizeCombo(entry.keys); + if (normalized === combo) { + if (entry.options.preventDefault !== false) e.preventDefault(); + entry.handler(e); + return; + } + } + + // Si la touche n'a pas matché et n'est pas un modifier, mémoriser comme début de chord + if ( + !e.ctrlKey && + !e.metaKey && + !e.altKey && + e.key.length === 1 && + !inEditable + ) { + chordBuffer.current = { + key: combo, + expires: now + CHORD_WINDOW_MS, + }; + } + }; + document.addEventListener("keydown", onKey); + return () => document.removeEventListener("keydown", onKey); + }, []); + + const value = useMemo(() => ({ register, list }), [register, list]); + + return ( + + {children} + + ); +} + +/** + * Hook pour enregistrer un raccourci local au cycle de vie du composant. + * + * useShortcut("cmd+k", () => setOpen(true), { + * description: "Ouvrir la palette", + * category: "Navigation", + * }); + */ +export function useShortcut( + keys: string, + handler: ShortcutHandler, + options: ShortcutOptions = {}, +) { + const ctx = useContext(ShortcutContext); + if (!ctx) + throw new Error("useShortcut requiert un ancêtre."); + + const handlerRef = useRef(handler); + handlerRef.current = handler; + + useEffect(() => { + const id = `${keys}-${Math.random().toString(36).slice(2, 8)}`; + return ctx.register(id, { + keys, + handler: (e) => handlerRef.current(e), + options, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [keys, options.disabled, options.allowInInput, options.preventDefault]); +} + +/** + * Liste tous les raccourcis enregistrés (pour cheatsheet). + */ +export function useShortcutList(): ShortcutEntry[] { + const ctx = useContext(ShortcutContext); + if (!ctx) return []; + const [, force] = useState(0); + // Re-render léger — la liste peut bouger + useEffect(() => { + const t = setInterval(() => force((n) => n + 1), 1000); + return () => clearInterval(t); + }, []); + return ctx.list(); +} + +/** + * Affichage cheatsheet (ouvert via "?" par défaut). + */ +export function ShortcutCheatsheet({ + open, + onClose, +}: { + open: boolean; + onClose: () => void; +}) { + const list = useShortcutList(); + + useEffect(() => { + if (!open) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape") onClose(); + }; + document.addEventListener("keydown", onKey); + return () => document.removeEventListener("keydown", onKey); + }, [open, onClose]); + + if (!open) return null; + + // Group by category + const groups = list.reduce>((acc, e) => { + (acc[e.category] ??= []).push(e); + return acc; + }, {}); + + return ( +
{ + if (e.target === e.currentTarget) onClose(); + }} + > +
+
+

Raccourcis clavier

+ +
+
+ {Object.keys(groups).length === 0 ? ( +

+ Aucun raccourci enregistré dans le contexte actuel. +

+ ) : ( + Object.entries(groups).map(([cat, entries]) => ( +
+

+ {cat} +

+
+ {entries.map((e) => ( +
+
+ {e.description || e.id} +
+
+ +
+
+ ))} +
+
+ )) + )} +
+
+
+ ); +} + +/** + * Affichage joli des keys d'un raccourci (chunks ). + */ +export function ShortcutKeys({ keys }: { keys: string }) { + const chords = keys.split(" "); + return ( + + {chords.map((chord, i) => ( + + {chord.split("+").map((k, j) => ( + + {k === "cmd" || k === "meta" ? (isMac ? "⌘" : "Ctrl") : k.toUpperCase()} + + ))} + {i < chords.length - 1 && then} + + ))} + + ); +} diff --git a/packages/react/src/SkipLink.tsx b/packages/react/src/SkipLink.tsx new file mode 100644 index 0000000..4d231bc --- /dev/null +++ b/packages/react/src/SkipLink.tsx @@ -0,0 +1,14 @@ +import type { ReactNode } from "react"; + +export type SkipLinkProps = { + targetId?: string; + children?: ReactNode; +}; + +export function SkipLink({ targetId = "main", children = "Aller au contenu" }: SkipLinkProps) { + return ( + + {children} + + ); +} diff --git a/packages/react/src/Slider.tsx b/packages/react/src/Slider.tsx new file mode 100644 index 0000000..27d1476 --- /dev/null +++ b/packages/react/src/Slider.tsx @@ -0,0 +1,79 @@ +import { type ReactNode } from "react"; +import * as RadixSlider from "@radix-ui/react-slider"; +import { cx } from "./utils"; + +export type SliderProps = { + /** Valeur(s) du slider. Tableau pour permettre les ranges (2 thumbs). */ + value: number[]; + onValueChange: (value: number[]) => void; + /** Valeur min. Défaut 0. */ + min?: number; + /** Valeur max. Défaut 100. */ + max?: number; + /** Pas (granularité). Défaut 1. */ + step?: number; + /** Désactivé. */ + disabled?: boolean; + /** Label accessible (lu par les lecteurs d'écran). */ + label?: string; + /** Si true, affiche la valeur au-dessus du thumb actif. */ + showValue?: boolean; + /** Format de la valeur affichée. Défaut: identité. */ + formatValue?: (v: number) => string; + className?: string; +}; + +/** + * Slider — sélecteur de valeur (single ou range, Radix UI). + * + * - Clavier : flèches (step), Page Up/Down (×10 step), Home/End (min/max). + * - aria-valuenow/min/max/text gérés par Radix. + * - Pour un range, passer un tableau de 2 valeurs. + * + * Style DSMMG : track fin, thumb cerclé pill, accent au remplissage. + * Focus visible : halo accent autour du thumb. + */ +export function Slider({ + value, + onValueChange, + min = 0, + max = 100, + step = 1, + disabled, + label, + showValue, + formatValue = (v) => `${v}`, + className, +}: SliderProps) { + return ( + + + + + {value.map((v, i) => ( + + {showValue && ( + + {formatValue(v)} + + )} + + ))} + + ); +} + +export { RadixSlider as SliderPrimitive }; diff --git a/packages/react/src/Slot.tsx b/packages/react/src/Slot.tsx new file mode 100644 index 0000000..7c375ab --- /dev/null +++ b/packages/react/src/Slot.tsx @@ -0,0 +1,130 @@ +import { + Children, + cloneElement, + forwardRef, + isValidElement, + type CSSProperties, + type HTMLAttributes, + type ReactElement, + type ReactNode, + type Ref, +} from "react"; + +/** + * Slot — pattern Radix UI / shadcn pour le polymorphisme `asChild`. + * + * Permet à un composant DSMMG de "passer" son comportement (props, ref, + * className fusionnée) à son unique enfant React. Cas d'usage typique : + * + * + * Aller à Synapse + * + * + * Ici, le `` reçoit toutes les props du Button (className, onClick, + * aria-*, ref) tout en restant un vrai `` côté DOM. Cela évite de + * dupliquer un Button et un ButtonAsLink, et préserve la sémantique + * native du tag enfant (RGAA 7.1, ARIA rule #1). + */ + +export type SlotProps = HTMLAttributes & { + children?: ReactNode; +}; + +/** + * Fusionne deux className ; conserve l'ordre source → destination. + * Pas de dépendance externe. + */ +function mergeClassNames( + parent?: string, + child?: string, +): string | undefined { + if (!parent && !child) return undefined; + if (!parent) return child; + if (!child) return parent; + return `${parent} ${child}`; +} + +/** + * Fusionne deux styles ; les styles enfants priment (override). + */ +function mergeStyles( + parent?: CSSProperties, + child?: CSSProperties, +): CSSProperties | undefined { + if (!parent && !child) return undefined; + return { ...parent, ...child }; +} + +/** + * Fusionne deux event handlers ; appelle l'enfant en premier — si + * `event.defaultPrevented` est vrai, on n'appelle pas le parent + * (laisse l'enfant override le comportement). + */ +function composeEventHandlers( + parentHandler?: (event: E) => void, + childHandler?: (event: E) => void, +): ((event: E) => void) | undefined { + if (!parentHandler && !childHandler) return undefined; + return (event: E) => { + childHandler?.(event); + if (!event.defaultPrevented) parentHandler?.(event); + }; +} + +/** + * Fusionne refs (callback ou objet). + */ +function composeRefs(...refs: Array | undefined>): Ref { + return (node: T | null) => { + refs.forEach((ref) => { + if (typeof ref === "function") ref(node); + else if (ref != null) (ref as React.MutableRefObject).current = node; + }); + }; +} + +export const Slot = forwardRef(function Slot( + { children, ...slotProps }, + forwardedRef, +) { + if (!isValidElement(children)) { + return null; + } + + const childElement = Children.only(children) as ReactElement< + HTMLAttributes & { ref?: Ref } + >; + const childProps = childElement.props; + + const merged: Record = { ...slotProps }; + + // className : slot puis enfant (l'enfant override visuellement) + merged.className = mergeClassNames(slotProps.className, childProps.className); + merged.style = mergeStyles(slotProps.style, childProps.style); + + // Compose event handlers + for (const key in slotProps) { + if (key.startsWith("on") && typeof (slotProps as any)[key] === "function") { + merged[key] = composeEventHandlers( + (slotProps as any)[key], + (childProps as any)[key], + ); + } + } + + // Ref combinée + merged.ref = composeRefs(forwardedRef, (childElement as any).ref); + + return cloneElement(childElement, merged as never); +}); + +/** + * Helper pour les composants qui acceptent `asChild` : retourne `Slot` si + * `asChild` est vrai, sinon le tag par défaut. + */ +export function getSlotComponent( + asChild: boolean | undefined, + defaultTag: T, +): T | typeof Slot { + return asChild ? Slot : defaultTag; +} diff --git a/packages/react/src/Stat.tsx b/packages/react/src/Stat.tsx new file mode 100644 index 0000000..325bf38 --- /dev/null +++ b/packages/react/src/Stat.tsx @@ -0,0 +1,26 @@ +import type { ReactNode } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type StatProps = { + icon?: IconName; + value: ReactNode; + label: ReactNode; + className?: string; +}; + +export function Stat({ icon, value, label, className }: StatProps) { + return ( +
+ {icon && ( +
+ +
+ )} +
+
{value}
+
{label}
+
+
+ ); +} diff --git a/packages/react/src/Stepper.tsx b/packages/react/src/Stepper.tsx new file mode 100644 index 0000000..584d21d --- /dev/null +++ b/packages/react/src/Stepper.tsx @@ -0,0 +1,38 @@ +import type { ReactNode } from "react"; +import { cx } from "./utils"; + +export type StepperProps = { + current: number; + total: number; + title: ReactNode; + nextTitle?: ReactNode; + className?: string; +}; + +export function Stepper({ current, total, title, nextTitle, className }: StepperProps) { + return ( +
+
+ Étape {current} sur {total} +
+
+ {Array.from({ length: total }, (_, i) => ( +
+ ))} +
+
{title}
+ {nextTitle && current < total && ( +
+ Étape suivante : {nextTitle} +
+ )} +
+ ); +} diff --git a/packages/react/src/Tabs.tsx b/packages/react/src/Tabs.tsx new file mode 100644 index 0000000..1644122 --- /dev/null +++ b/packages/react/src/Tabs.tsx @@ -0,0 +1,30 @@ +import type { ReactNode } from "react"; +import { cx } from "./utils"; + +export type TabItem = { id: string; label: ReactNode }; + +export type TabsProps = { + items: TabItem[]; + value: string; + onChange: (id: string) => void; + className?: string; +}; + +export function Tabs({ items, value, onChange, className }: TabsProps) { + return ( +
+ {items.map((t) => ( + + ))} +
+ ); +} diff --git a/packages/react/src/Tag.tsx b/packages/react/src/Tag.tsx new file mode 100644 index 0000000..9cf891d --- /dev/null +++ b/packages/react/src/Tag.tsx @@ -0,0 +1,30 @@ +import type { HTMLAttributes } from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type TagProps = HTMLAttributes & { + selected?: boolean; + onSelect?: () => void; + icon?: IconName; +}; + +export function Tag({ selected, onSelect, children, className, icon, ...rest }: TagProps) { + const Comp = onSelect ? "button" : "span"; + return ( + + {icon && } + {children} + + ); +} diff --git a/packages/react/src/Text.tsx b/packages/react/src/Text.tsx new file mode 100644 index 0000000..3bf532e --- /dev/null +++ b/packages/react/src/Text.tsx @@ -0,0 +1,135 @@ +import type { ElementType, HTMLAttributes, ReactNode } from "react"; +import { cx } from "./utils"; + +export type TextVariant = + // Display (landing marketing — Hero produits) + | "display-2xl" + | "display-xl" + | "display-lg" + | "display-md" + // Headlines (apps + pages) + | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" + // Body + | "body-lg" | "body" | "body-sm" | "body-xs" + // Auxiliaires + | "eyebrow" | "lead" | "overline" | "caption"; + +export type TextElement = "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "span" | "div"; + +export type TextProps = HTMLAttributes & { + /** Variante typographique. Détermine taille/poids/letter-spacing/line-height. */ + variant?: TextVariant; + /** Tag HTML rendu. Choisir selon la sémantique, pas selon la taille. */ + as?: TextElement; + /** Police mono (JetBrains Mono / SF Mono) pour code, IDs, valeurs tabulaires. */ + mono?: boolean; + /** Numérique tabular (alignement vertical des chiffres). Pour stats / tableaux. */ + tabular?: boolean; + /** Gradient accent → accent-strong sur le texte (modern Hero touch). */ + gradient?: boolean; + /** Effet "rainbow" animé. À utiliser une seule fois par page max. */ + rainbow?: boolean; + /** text-wrap: balance — équilibre les retours à la ligne (titres). */ + balance?: boolean; + /** text-wrap: pretty — évite veuves/orphelines (body). */ + pretty?: boolean; + /** Italique — pour titres d'œuvre, citations, mots-clefs sémantiquement à part. */ + italic?: boolean; + /** Italique + couleur d'accent — emphase éditoriale (mot-clef ressortir). */ + emphasis?: boolean; + /** Surligneur teinté accent — highlight ponctuel dans un body. */ + highlight?: boolean; + /** Souligné épais accent — accent fort sur un mot-clef. */ + underline?: boolean; + /** Barré — prix barré, élément déprécié. */ + strike?: boolean; + children?: ReactNode; +}; + +/** + * Text — composant typographique sémantique du DSMMG. + * + * **Choisir le tag (`as`) selon la SÉMANTIQUE, pas selon la taille.** + * Un titre de page reste `

` même si visuellement il s'affiche en + * `display-xl`. Un sous-titre marketing décoratif peut être un `

` + * stylé en `display-lg`. + * + * Usage typique sur une landing produit (HRTime, Synapse…) : + * + * SIRH simple + * + * Le temps de vos équipes, au cordeau. + * + * + * Plannings, congés, paie. Une seule plateforme, sans surprise. + * + * + * Usage app (DataTable, dashboard) : + * + * Effectifs + * 432 collaborateurs actifs. + * Section + */ +export function Text({ + variant = "body", + as, + mono, + tabular, + gradient, + rainbow, + balance, + pretty, + italic, + emphasis, + highlight, + underline, + strike, + className, + children, + ...rest +}: TextProps) { + const Comp: ElementType = + as ?? + (variant.startsWith("display") ? "h1" : + variant === "h1" || variant === "h2" || variant === "h3" || + variant === "h4" || variant === "h5" || variant === "h6" ? variant : + variant === "lead" ? "p" : + "span"); + return ( + + {children} + + ); +} + +/* — Helpers raccourcis pour les variants les plus utilisés ———————————— */ + +export function Display(props: Omit & { size?: "md" | "lg" | "xl" | "2xl" }) { + const { size = "xl", ...rest } = props; + return ; +} + +export function Eyebrow(props: Omit) { + return ; +} + +export function Lead(props: Omit) { + return ; +} diff --git a/packages/react/src/ThemePicker.test.tsx b/packages/react/src/ThemePicker.test.tsx new file mode 100644 index 0000000..f7b4626 --- /dev/null +++ b/packages/react/src/ThemePicker.test.tsx @@ -0,0 +1,76 @@ +import { describe, expect, it, beforeEach } from "vitest"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { axe } from "vitest-axe"; +import { ThemePicker } from "./ThemePicker"; +import { ACCENT_PRESETS } from "./useAccent"; + +describe("ThemePicker", () => { + beforeEach(() => { + document.documentElement.removeAttribute("data-mmg-accent"); + window.localStorage.clear(); + }); + + it("rend une option par preset", () => { + render(); + const radios = screen.getAllByRole("radio"); + expect(radios).toHaveLength(ACCENT_PRESETS.length); + }); + + it("synapse est sélectionné par défaut", () => { + render(); + const synapse = screen.getByRole("radio", { name: /synapse/i }); + expect(synapse).toHaveAttribute("aria-checked", "true"); + }); + + it("clic sur un preset l'active", async () => { + const user = userEvent.setup(); + render(); + const blue = screen.getByRole("radio", { name: /^Bleu$/i }); + await user.click(blue); + expect(blue).toHaveAttribute("aria-checked", "true"); + expect(document.documentElement.getAttribute("data-mmg-accent")).toBe("blue"); + expect(window.localStorage.getItem("mmg-accent")).toBe("blue"); + }); + + it("navigation flèche droite passe au preset suivant", async () => { + const user = userEvent.setup(); + render(); + const synapse = screen.getByRole("radio", { name: /synapse/i }); + synapse.focus(); + await user.keyboard("{ArrowRight}"); + const rose = screen.getByRole("radio", { name: /^Rose vif$/i }); + expect(rose).toHaveAttribute("aria-checked", "true"); + }); + + it("navigation flèche gauche revient au précédent (avec wrap)", async () => { + const user = userEvent.setup(); + render(); + const synapse = screen.getByRole("radio", { name: /synapse/i }); + synapse.focus(); + await user.keyboard("{ArrowLeft}"); + // Wrap : passe au dernier (slate) + const slate = screen.getByRole("radio", { name: /ardoise/i }); + expect(slate).toHaveAttribute("aria-checked", "true"); + }); + + it("Home / End naviguent aux extrêmes", async () => { + const user = userEvent.setup(); + render(); + screen.getByRole("radio", { name: /synapse/i }).focus(); + await user.keyboard("{End}"); + expect(screen.getByRole("radio", { name: /ardoise/i })).toHaveAttribute("aria-checked", "true"); + await user.keyboard("{Home}"); + expect(screen.getByRole("radio", { name: /synapse/i })).toHaveAttribute("aria-checked", "true"); + }); + + it("expose un radiogroup labelisé", () => { + render(); + expect(screen.getByRole("radiogroup")).toBeInTheDocument(); + }); + + it("n'a pas de violations axe-core", async () => { + const { container } = render(); + expect(await axe(container)).toHaveNoViolations(); + }); +}); diff --git a/packages/react/src/ThemePicker.tsx b/packages/react/src/ThemePicker.tsx new file mode 100644 index 0000000..df8f8c4 --- /dev/null +++ b/packages/react/src/ThemePicker.tsx @@ -0,0 +1,108 @@ +import { useRef, type KeyboardEvent } from "react"; +import { cx } from "./utils"; +import { Icon } from "./Icon"; +import { ACCENT_PRESETS, useAccent, type AccentName } from "./useAccent"; + +export type { AccentName }; + +export type ThemePickerProps = { + /** Légende lue par les lecteurs d'écran. Défaut : "Couleur d'accent". */ + legend?: string; + /** Cache le bouton de réinitialisation au défaut Synapse. */ + hideReset?: boolean; + className?: string; +}; + +/** + * ThemePicker — sélecteur de couleur d'accent utilisateur. + * + * Pattern radiogroup : roving tabindex, navigation flèches gauche/droite, + * sélection à Espace ou Entrée. Persiste l'accent choisi dans localStorage. + * + * Accessibilité : + * - role="radiogroup" + aria-labelledby + * - chaque pastille : role="radio" + aria-checked + * - focus-visible géré, contraste validé sur fonds light & dark + * - le label texte ("Rose Synapse", "Bleu", …) est accessible aux lecteurs + * d'écran via aria-label, pas seulement la couleur (RGAA 9 — couleur seule) + */ +export function ThemePicker({ legend = "Couleur d'accent", hideReset, className }: ThemePickerProps) { + const { accent, setAccent, reset } = useAccent(); + const refs = useRef<(HTMLButtonElement | null)[]>([]); + const headingId = "mmg-theme-picker-heading"; + + const focusIndex = (i: number) => { + const next = (i + ACCENT_PRESETS.length) % ACCENT_PRESETS.length; + refs.current[next]?.focus(); + }; + + const onKey = (e: KeyboardEvent, idx: number) => { + switch (e.key) { + case "ArrowRight": + case "ArrowDown": + e.preventDefault(); + focusIndex(idx + 1); + setAccent(ACCENT_PRESETS[(idx + 1) % ACCENT_PRESETS.length].name); + break; + case "ArrowLeft": + case "ArrowUp": + e.preventDefault(); + focusIndex(idx - 1); + setAccent(ACCENT_PRESETS[(idx - 1 + ACCENT_PRESETS.length) % ACCENT_PRESETS.length].name); + break; + case "Home": + e.preventDefault(); + focusIndex(0); + setAccent(ACCENT_PRESETS[0].name); + break; + case "End": + e.preventDefault(); + focusIndex(ACCENT_PRESETS.length - 1); + setAccent(ACCENT_PRESETS[ACCENT_PRESETS.length - 1].name); + break; + } + }; + + return ( +

+
+ {legend} +
+
+ {ACCENT_PRESETS.map((preset, i) => { + const checked = preset.name === accent; + return ( + + ); + })} +
+ {!hideReset && accent !== "synapse" && ( + + )} +
+ ); +} diff --git a/packages/react/src/Toast.tsx b/packages/react/src/Toast.tsx new file mode 100644 index 0000000..28ad5b1 --- /dev/null +++ b/packages/react/src/Toast.tsx @@ -0,0 +1,392 @@ +import { + createContext, + useCallback, + useContext, + useEffect, + useLayoutEffect, + useMemo, + useRef, + useState, + type ReactNode, +} from "react"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +type Severity = "info" | "success" | "warning" | "danger"; + +export type ToastInput = { + title: ReactNode; + description?: ReactNode; + severity?: Severity; + /** Durée avant auto-dismiss (ms). 0 = persistant. Par défaut 5000. */ + duration?: number; + /** Action optionnelle dans le toast. */ + action?: { label: ReactNode; onClick: () => void }; +}; + +type ToastInternal = ToastInput & { id: string; createdAt: number }; + +type Ctx = { + toast: (t: ToastInput) => string; + dismiss: (id: string) => void; + clear: () => void; +}; + +const ToastContext = createContext(null); + +const SEV_ICON: Record = { + info: "information-fill", + success: "checkbox-circle-fill", + warning: "alert-fill", + danger: "error-warning-fill", +}; + +export type ToastProviderProps = { + children: ReactNode; + position?: "bottom-right" | "bottom-left" | "top-right" | "top-left"; + /** Nombre max conservé en mémoire avant écrêtage du plus ancien. Défaut 5. */ + max?: number; + /** Nombre visible avant collapse en pile (Sonner-style). Défaut 3. */ + visibleCount?: number; + /** Durée par défaut (ms) avant auto-dismiss si non précisé. */ + defaultDuration?: number; + /** Gap entre toasts en mode expanded (px). Défaut 12. */ + gap?: number; + /** Offset entre toasts en pile collapsée (px par cran). Défaut 14. */ + stackOffset?: number; +}; + +const DEFAULT_GAP = 12; +const DEFAULT_STACK_OFFSET = 14; +const SCALE_PER_INDEX = 0.045; + +/** + * ToastProvider — système de notifications empilables (Sonner-style). + * + * Architecture : + * - Chaque toast est en `position: absolute`, ancré bottom: 0 (positions + * bottom-*) ou top: 0 (positions top-*). + * - Les heights sont mesurées via ResizeObserver et exposées en CSS vars. + * - Au repos : translateY = -stackOffset × index (collapsed-y), + * scale = 1 - 0.045 × index. Front-most reste pleine taille. + * - Au hover/focus : translateY = -(somme des heights précédentes + gap × i) + * (expanded-y), scale = 1. + * - La hauteur du region s'ajuste : front-most height (collapsed) ou + * somme totale (expanded), pour ne pas voler de clics au contenu. + * + * A11y : + * - aria-live="polite" — les toasts s'annoncent sans interrompre. + * - Severity "danger" → role="alert" (urgent), sinon role="status". + * - Bouton fermer focusable, label complet ("Fermer la notification"). + * - Pause des timers au hover/focus, reprise au mouseleave/blur. + */ +export function ToastProvider({ + children, + position = "bottom-right", + max = 5, + visibleCount = 3, + defaultDuration = 5000, + gap = DEFAULT_GAP, + stackOffset = DEFAULT_STACK_OFFSET, +}: ToastProviderProps) { + const [toasts, setToasts] = useState([]); + const [expanded, setExpanded] = useState(false); + const [heights, setHeights] = useState>({}); + const timers = useRef(new Map()); + const remainingTimes = useRef(new Map()); + const pausedRef = useRef(false); + const itemRefs = useRef(new Map()); + const observerRef = useRef(null); + + const isTop = position.startsWith("top"); + + // — Lifecycle ———————————————————————————————————————— + const dismiss = useCallback((id: string) => { + setToasts((prev) => prev.filter((t) => t.id !== id)); + const timer = timers.current.get(id); + if (timer) { + window.clearTimeout(timer); + timers.current.delete(id); + } + remainingTimes.current.delete(id); + itemRefs.current.delete(id); + setHeights((h) => { + if (!(id in h)) return h; + const next = { ...h }; + delete next[id]; + return next; + }); + }, []); + + const scheduleDismiss = useCallback( + (id: string, duration: number) => { + if (duration <= 0) return; + const t = window.setTimeout(() => dismiss(id), duration); + timers.current.set(id, t); + remainingTimes.current.set(id, duration); + }, + [dismiss], + ); + + const toast = useCallback( + (input: ToastInput) => { + const id = `t_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`; + const duration = input.duration ?? defaultDuration; + const item: ToastInternal = { ...input, id, createdAt: Date.now() }; + setToasts((prev) => { + const next = [...prev, item]; + return next.length > max ? next.slice(-max) : next; + }); + // Si la pile est déjà hover/focused, on enchaîne en pause aussi. + if (!pausedRef.current) scheduleDismiss(id, duration); + else remainingTimes.current.set(id, duration); + return id; + }, + [defaultDuration, max, scheduleDismiss], + ); + + const clear = useCallback(() => { + timers.current.forEach((t) => window.clearTimeout(t)); + timers.current.clear(); + remainingTimes.current.clear(); + setToasts([]); + }, []); + + const pauseAll = useCallback(() => { + if (pausedRef.current) return; + pausedRef.current = true; + for (const [id, timerId] of timers.current.entries()) { + window.clearTimeout(timerId); + timers.current.delete(id); + } + }, []); + const resumeAll = useCallback(() => { + if (!pausedRef.current) return; + pausedRef.current = false; + for (const [id, remaining] of remainingTimes.current.entries()) { + const t = window.setTimeout(() => dismiss(id), remaining); + timers.current.set(id, t); + } + }, [dismiss]); + + useEffect( + () => () => { + timers.current.forEach((t) => window.clearTimeout(t)); + observerRef.current?.disconnect(); + }, + [], + ); + + // — Mesure des hauteurs via ResizeObserver ———————————— + // Indispensable pour calculer l'expanded-y précisément (somme des heights + // précédentes + gap × index). Évite tout layout shift visible. + useLayoutEffect(() => { + if (typeof ResizeObserver === "undefined") return; + const ro = new ResizeObserver((entries) => { + let mutated = false; + const updates: Record = {}; + for (const entry of entries) { + const el = entry.target as HTMLLIElement; + const id = el.dataset.toastId; + if (!id) continue; + const h = el.offsetHeight; + updates[id] = h; + mutated = true; + } + if (mutated) { + setHeights((prev) => { + let changed = false; + const next = { ...prev }; + for (const [id, h] of Object.entries(updates)) { + if (next[id] !== h) { + next[id] = h; + changed = true; + } + } + return changed ? next : prev; + }); + } + }); + observerRef.current = ro; + for (const el of itemRefs.current.values()) ro.observe(el); + return () => ro.disconnect(); + }, []); + + // Ré-observer lors de l'ajout/retrait + useLayoutEffect(() => { + const ro = observerRef.current; + if (!ro) return; + for (const el of itemRefs.current.values()) ro.observe(el); + }, [toasts.length]); + + // Setter de ref qui (ré-)observe le node + const setItemRef = useCallback( + (id: string) => (el: HTMLLIElement | null) => { + const ro = observerRef.current; + if (el) { + itemRefs.current.set(id, el); + ro?.observe(el); + // Capture immédiate pour éviter un flash au premier render + const h = el.offsetHeight; + if (h > 0) { + setHeights((prev) => (prev[id] === h ? prev : { ...prev, [id]: h })); + } + } else { + const old = itemRefs.current.get(id); + if (old && ro) ro.unobserve(old); + itemRefs.current.delete(id); + } + }, + [], + ); + + // — Ordre + offsets calculés ———————————————————————— + // ordered[i].stackIndex : 0 = front-most (le plus récent). + // Pour bottom-* : DOM order = ancien → récent (column-reverse côté CSS + // n'est plus utilisé maintenant qu'on est en absolute). Le récent est + // au-dessus visuellement → stackIndex 0 = dernier ajouté. + const ordered = useMemo(() => { + const list = toasts.map((t, i) => ({ + ...t, + stackIndex: toasts.length - 1 - i, + })); + // Les offsets dépendent des heights (mesurés) : + // - collapsedOffset = stackOffset × stackIndex (signe selon position) + // - expandedOffset = somme des heights des toasts plus récents (stackIndex < self.stackIndex) + gap × count + return list.map((t) => { + const collapsed = stackOffset * t.stackIndex; + let expanded = 0; + for (let j = 0; j < t.stackIndex; j++) { + const sibling = list.find((o) => o.stackIndex === j); + if (!sibling) continue; + const h = heights[sibling.id] ?? 64; // fallback raisonnable avant mesure + expanded += h + gap; + } + return { ...t, collapsed, expanded }; + }); + }, [toasts, heights, gap, stackOffset]); + + // Hauteur du region : front-most en collapsed, somme en expanded. + const regionHeight = useMemo(() => { + if (toasts.length === 0) return 0; + if (expanded) { + return ordered.reduce((sum, t) => sum + (heights[t.id] ?? 64), 0) + gap * (toasts.length - 1); + } + const front = ordered.find((t) => t.stackIndex === 0); + return heights[front?.id ?? ""] ?? 64; + }, [ordered, heights, gap, expanded, toasts.length]); + + const ctx = useMemo(() => ({ toast, dismiss, clear }), [toast, dismiss, clear]); + + return ( + + {children} +
    { + setExpanded(true); + pauseAll(); + }} + onMouseLeave={() => { + setExpanded(false); + resumeAll(); + }} + onFocus={() => { + setExpanded(true); + pauseAll(); + }} + onBlur={(e) => { + if (!e.currentTarget.contains(e.relatedTarget as Node)) { + setExpanded(false); + resumeAll(); + } + }} + > + {ordered.map((t) => { + const isHidden = !expanded && t.stackIndex >= visibleCount; + // Signes selon position : bottom-* → translateY négatif (vers haut), + // top-* → translateY positif (vers bas). + const sign = isTop ? 1 : -1; + const collapsedY = sign * t.collapsed; + const expandedY = sign * t.expanded; + return ( +
  1. + } + > + +
    +
    {t.title}
    + {t.description &&
    {t.description}
    } + {t.action && ( + + )} +
    + +
  2. + ); + })} +
+
+ ); +} + +/** Hook d'accès au système de toasts. Doit être utilisé sous un ToastProvider. */ +export function useToast() { + const ctx = useContext(ToastContext); + if (!ctx) + throw new Error( + "useToast doit être utilisé dans un . Wrappe ton App.", + ); + return ctx; +} diff --git a/packages/react/src/ToggleGroup.tsx b/packages/react/src/ToggleGroup.tsx new file mode 100644 index 0000000..0bb1ef8 --- /dev/null +++ b/packages/react/src/ToggleGroup.tsx @@ -0,0 +1,81 @@ +import { type ReactNode } from "react"; +import * as RadixToggleGroup from "@radix-ui/react-toggle-group"; +import { cx } from "./utils"; +import { Icon, type IconName } from "./Icon"; + +export type ToggleGroupItem = { + value: string; + label: ReactNode; + icon?: IconName; + /** Affiche uniquement l'icône (label devient aria-label). */ + iconOnly?: boolean; + disabled?: boolean; +}; + +type ToggleGroupCommonProps = { + items: ToggleGroupItem[]; + size?: "sm" | "md" | "lg"; + variant?: "outline" | "solid"; + disabled?: boolean; + /** Label accessible du groupe. */ + ariaLabel?: string; + className?: string; +}; + +export type ToggleGroupSingleProps = ToggleGroupCommonProps & { + type: "single"; + value: string | undefined; + onValueChange: (value: string) => void; +}; + +export type ToggleGroupMultipleProps = ToggleGroupCommonProps & { + type: "multiple"; + value: string[]; + onValueChange: (value: string[]) => void; +}; + +export type ToggleGroupProps = ToggleGroupSingleProps | ToggleGroupMultipleProps; + +/** + * ToggleGroup — groupe de boutons toggle (single ou multiple). + * + * Différence avec SegmentedControl : ToggleGroup peut être en mode multiple + * (plusieurs boutons actifs simultanément) et ne demande pas de label + * obligatoire au-dessus. + * + * Wrapper Radix : roving tabindex, navigation flèches, aria-pressed. + */ +export function ToggleGroup(props: ToggleGroupProps) { + const { items, size = "md", variant = "outline", disabled, ariaLabel, className } = props; + const root = ( + void} + disabled={disabled} + aria-label={ariaLabel} + className={cx( + "mmg-toggle-group", + `mmg-toggle-group--${size}`, + `mmg-toggle-group--${variant}`, + className, + )} + > + {items.map((item) => ( + + {item.icon && } + {!item.iconOnly && {item.label}} + + ))} + + ); + return root; +} + +export { RadixToggleGroup as ToggleGroupPrimitive }; diff --git a/packages/react/src/Tooltip.tsx b/packages/react/src/Tooltip.tsx new file mode 100644 index 0000000..50db15a --- /dev/null +++ b/packages/react/src/Tooltip.tsx @@ -0,0 +1,66 @@ +import { type ReactNode, type ComponentProps } from "react"; +import * as RadixTooltip from "@radix-ui/react-tooltip"; +import { cx } from "./utils"; + +export type TooltipPlacement = "top" | "bottom" | "left" | "right"; + +export type TooltipProps = { + content: ReactNode; + children: ReactNode; + placement?: TooltipPlacement; + /** Délai avant apparition (ms). */ + delay?: number; + /** Décalage par rapport à la cible (px). Défaut 8. */ + sideOffset?: number; + className?: string; +}; + +/** + * Tooltip — wrapper Radix. + * + * - Positionnement intelligent (auto-flip si pas de place) via Floating UI. + * - Focus / hover / Escape gérés par Radix. + * - Respecte prefers-reduced-motion. + * - Pour usage avancé : utiliser TooltipPrimitive.* directement. + * + * Exige un à la racine de l'app (déjà inclus dans + * AppShell). Sinon wrap localement avec . + */ +export function Tooltip({ + content, + children, + placement = "top", + delay = 200, + sideOffset = 8, + className, +}: TooltipProps) { + return ( + + {children} + + + {content} + + + + + ); +} + +export type TooltipProviderProps = ComponentProps; + +/** + * Provider à mettre une fois à la racine de l'app pour partager les délais + * et la file d'attente des tooltips (skipDelayDuration). + */ +export function TooltipProvider(props: TooltipProviderProps) { + return ; +} + +/** Sous-primitives Radix réexportées pour usage avancé (compound). */ +export { RadixTooltip as TooltipPrimitive }; diff --git a/packages/react/src/UserCard.tsx b/packages/react/src/UserCard.tsx new file mode 100644 index 0000000..19f5d5a --- /dev/null +++ b/packages/react/src/UserCard.tsx @@ -0,0 +1,93 @@ +import { type ReactNode } from "react"; +import { cx } from "./utils"; +import { Avatar, type AvatarStatus } from "./Avatar"; + +export type UserCardProps = { + name: ReactNode; + /** Rôle / poste / sous-titre. */ + role?: ReactNode; + /** URL d'image (sinon initiales générées depuis name). */ + src?: string; + initials?: string; + status?: AvatarStatus; + /** Métadonnée optionnelle (e-mail, équipe…). */ + meta?: ReactNode; + /** Slot d'actions à droite (Button, Menu trigger…). */ + actions?: ReactNode; + /** Densité visuelle. */ + size?: "sm" | "md" | "lg"; + /** Si fourni, rend la carte cliquable (entièrement). */ + href?: string; + onClick?: () => void; + className?: string; +}; + +function autoInitials(name: ReactNode) { + if (typeof name !== "string") return undefined; + return name + .split(/\s+/) + .filter(Boolean) + .slice(0, 2) + .map((s) => s[0]) + .join("") + .toUpperCase(); +} + +/** + * UserCard — carte utilisateur compacte (avatar + identité + actions). + * + * Pattern Slack/Linear/Notion : une rangée alignée verticalement avec + * avatar à gauche, identité au milieu, actions à droite. Cliquable en + * entier si href ou onClick. + */ +export function UserCard({ + name, + role, + src, + initials, + status, + meta, + actions, + size = "md", + href, + onClick, + className, +}: UserCardProps) { + const Comp: "a" | "button" | "div" = href ? "a" : onClick ? "button" : "div"; + const interactive = Boolean(href || onClick); + const avatarSize = size === "sm" ? "sm" : size === "lg" ? "lg" : "md"; + + const inner = ( + <> + +
+
{name}
+ {role &&
{role}
} + {meta &&
{meta}
} +
+ {actions &&
{actions}
} + + ); + + return ( + + {inner} + + ); +} diff --git a/packages/react/src/cva.ts b/packages/react/src/cva.ts new file mode 100644 index 0000000..0ee4055 --- /dev/null +++ b/packages/react/src/cva.ts @@ -0,0 +1,116 @@ +/** + * cva — class-variance-authority (implémentation locale légère). + * + * Inspiré de https://cva.style — pas de dépendance externe pour garder + * le bundle DSMMG minimal. Permet de définir des variants typés et + * compositionnés pour un composant. + * + * Usage : + * + * const buttonStyles = cva("mmg-btn", { + * variants: { + * variant: { + * primary: "mmg-btn--primary", + * tonal: "mmg-btn--tonal", + * ghost: "mmg-btn--ghost", + * }, + * size: { + * sm: "mmg-btn--sm", + * md: "mmg-btn--md", + * lg: "mmg-btn--lg", + * }, + * }, + * defaultVariants: { variant: "primary", size: "md" }, + * compoundVariants: [ + * { variant: "ghost", size: "sm", class: "mmg-btn--ghost-sm-tweak" }, + * ], + * }); + * + * buttonStyles({ variant: "tonal", size: "lg" }); + * // → "mmg-btn mmg-btn--tonal mmg-btn--lg" + */ + +type VariantsMap = Record>; + +/** + * Map JS object keys back to their external prop type. Les clés "true"/"false" + * sont des strings côté objet mais on les expose comme `boolean` côté API + * pour que `loading={true}` type-check sans cast. + */ +type ExternalKey = K extends "true" + ? boolean + : K extends "false" + ? boolean + : K; + +type VariantPropsFor = { + [K in keyof V]?: ExternalKey; +}; + +type CompoundVariant = VariantPropsFor & { + class?: string; + className?: string; +}; + +export type CvaConfig = { + variants?: V; + defaultVariants?: VariantPropsFor; + compoundVariants?: CompoundVariant[]; +}; + +export type CvaResult = { + (props?: VariantPropsFor & { className?: string }): string; + /** Pour debug/instrumentation */ + variants: V | undefined; +}; + +export function cva( + base: string, + config: CvaConfig = {}, +): CvaResult { + const { variants, defaultVariants = {}, compoundVariants = [] } = config; + + const fn = (props: (VariantPropsFor & { className?: string }) | undefined = {}) => { + const classes: string[] = [base]; + const merged = { ...defaultVariants, ...props } as VariantPropsFor & { + className?: string; + }; + + if (variants) { + for (const variantKey in variants) { + const value = merged[variantKey] as string | undefined; + if (value != null) { + const variantValueClass = variants[variantKey][value as string]; + if (variantValueClass) classes.push(variantValueClass); + } + } + } + + for (const cv of compoundVariants) { + const matches = Object.entries(cv).every(([k, v]) => { + if (k === "class" || k === "className") return true; + return (merged as any)[k] === v; + }); + if (matches) { + const cn = cv.class ?? cv.className; + if (cn) classes.push(cn); + } + } + + if (props?.className) classes.push(props.className); + return classes.filter(Boolean).join(" "); + }; + + return Object.assign(fn, { variants }); +} + +/** + * Type helper pour extraire les props variants d'un cva ; à utiliser + * dans les composants pour exposer des types stricts : + * + * type ButtonVariants = VariantProps; + */ +export type VariantProps string> = + T extends (props?: infer P & { className?: string }) => string + ? Omit + : never; diff --git a/packages/react/src/index.tsx b/packages/react/src/index.tsx new file mode 100644 index 0000000..01e63cd --- /dev/null +++ b/packages/react/src/index.tsx @@ -0,0 +1,174 @@ +/* ════════════════════════════════════════════════════════════════ + @managemate/react — entry barrel + Exports nommés pour permettre tree-shaking. + Chaque composant vit dans son propre fichier (sideEffects: false). +════════════════════════════════════════════════════════════════ */ + +// — Primitives —————————————————————————————— +export { Slot, type SlotProps } from "./Slot"; +export { cva, type VariantProps, type CvaConfig, type CvaResult } from "./cva"; +export { useFocusTrap } from "./useFocusTrap"; +export { cx } from "./utils"; + +// — Shortcut system ———————————————————————— +export { + ShortcutProvider, + useShortcut, + useShortcutList, + ShortcutCheatsheet, + ShortcutKeys, + type ShortcutEntry, + type ShortcutOptions, +} from "./Shortcut"; + +// — Icon / Pictogram —————————————————————————— +export { Icon, type IconProps, type IconName } from "./Icon"; +export { IconBlock, type IconBlockProps } from "./IconBlock"; +export { + Pictogram, + PICTOGRAM_NAMES, + type PictogramProps, + type PictogramName, +} from "./Pictogram"; + +// — Button —————————————————————————————— +export { Button, type ButtonProps, type ButtonVariants } from "./Button"; + +// — Forms —————————————————————————————— +export { + Field, + Input, + Textarea, + Select, + Checkbox, + Radio, + Switch, + type InputProps, + type TextareaProps, + type SelectProps, + type SelectOption, +} from "./Form"; + +// — Layout —————————————————————————————— +export { + Container, + Section, + Stack, + Inline, + Card, + Tile, + Hero, + type ContainerProps, + type SectionProps, + type TileProps, +} from "./Layout"; + +// — Feedback —————————————————————————————— +export { + Alert, + Notice, + Badge, + Modal, + ToastRegion, + Spinner, + type ToastItem, +} from "./Feedback"; + +// — Chrome (Header / Footer / Nav / Shell) ———————— +export { Header, type HeaderProps, type HeaderNavItem, type NavItemSimple, type NavItemMega, type MegaMenuLink, type MegaMenuColumn, type MegaMenuFeatured } from "./Header"; +export { Footer, type FooterProps, type FooterColumn } from "./Footer"; +export { Breadcrumb, type BreadcrumbProps } from "./Breadcrumb"; +export { Tabs, type TabsProps, type TabItem } from "./Tabs"; +export { Pagination, type PaginationProps } from "./Pagination"; +export { AppShell, Sidebar, AppMain, Topbar, type SidebarProps, type SidebarItem, type SidebarSection, type TopbarProps } from "./AppShell"; +export { Avatar, type AvatarProps, type AvatarSize, type AvatarStatus, type AvatarShape } from "./Avatar"; +export { AvatarGroup, type AvatarGroupProps } from "./AvatarGroup"; +export { UserCard, type UserCardProps } from "./UserCard"; +export { ProfileHeader, type ProfileHeaderProps } from "./ProfileHeader"; +export { MetricCard, type MetricCardProps, type MetricTrend } from "./MetricCard"; +export { PricingCard, type PricingCardProps, type PricingFeature } from "./PricingCard"; +export { FeatureCard, type FeatureCardProps } from "./FeatureCard"; +export { Text, Display, Eyebrow, Lead, type TextProps, type TextVariant, type TextElement } from "./Text"; +export { Stat, type StatProps } from "./Stat"; +export { SkipLink, type SkipLinkProps } from "./SkipLink"; + +// — Advanced (chacun dans son propre fichier) ———————— +export { Stepper, type StepperProps } from "./Stepper"; +export { Accordion, type AccordionProps } from "./Accordion"; +export { Tag, type TagProps } from "./Tag"; +export { Progress, type ProgressProps } from "./Progress"; +export { Drawer, type DrawerProps } from "./Drawer"; +export { Fab, type FabProps } from "./Fab"; +export { Highlight, type HighlightProps } from "./Highlight"; +export { Quote, type QuoteProps } from "./Quote"; +export { Callout, type CalloutProps } from "./Callout"; +export { Banner, type BannerProps } from "./Banner"; +export { FileUpload, type FileUploadProps } from "./FileUpload"; +export { SearchBar, type SearchBarProps } from "./SearchBar"; + +// — Overlays (Radix-backed) —————————————————————— +export { + Tooltip, + TooltipProvider, + TooltipPrimitive, + type TooltipProps, + type TooltipPlacement, + type TooltipProviderProps, +} from "./Tooltip"; +export { Popover, PopoverPrimitive, type PopoverProps } from "./Popover"; +export { Menu, MenuPrimitive, type MenuItem, type MenuProps } from "./Menu"; +export { Dialog, DialogPrimitive, type DialogProps } from "./Dialog"; +export { ConfirmDialog, type ConfirmDialogProps } from "./ConfirmDialog"; +export { Combobox, type ComboboxProps, type ComboboxOption } from "./Combobox"; +export { Sheet, SheetPrimitive, type SheetProps, type SheetSide, type SheetSize } from "./Sheet"; +export { HoverCard, HoverCardPrimitive, type HoverCardProps } from "./HoverCard"; +export { ContextMenu, ContextMenuPrimitive, type ContextMenuProps, type ContextMenuItem } from "./ContextMenu"; +export { Slider, SliderPrimitive, type SliderProps } from "./Slider"; +export { ToggleGroup, ToggleGroupPrimitive, type ToggleGroupProps, type ToggleGroupItem } from "./ToggleGroup"; + +// — DataTable / Tables / Pickers —————————————— +export { + DataTable, + type DataTableProps, + type DataTableColumn, +} from "./DataTable"; +export { + CommandMenu, + useCommandMenu, + type Command, +} from "./CommandMenu"; +export { DatePicker, type DatePickerProps } from "./DatePicker"; +export { + DateRangePicker, + type DateRangePickerProps, + type DateRange, +} from "./DateRangePicker"; + +// — Toast (provider + hook) —————————————————————— +export { ToastProvider, useToast, type ToastInput } from "./Toast"; + +// — EmptyState —————————————————————————————— +export { EmptyState, type EmptyStateProps } from "./EmptyState"; + +// — Extras —————————————————————————————— +export { + SegmentedControl, + DescriptionList, + Sparkline, + Kbd, + type SegmentedItem, + type DListItem, +} from "./Extras"; + +// — Article —————————————————————————————— +export { ArticlePage, type ArticlePageProps } from "./ArticlePage"; +export { ArticleHeader, type ArticleHeaderProps } from "./ArticleHeader"; +export { ArticleAside, type ArticleAsideProps } from "./ArticleAside"; +export { ArticleFooter, type ArticleFooterProps } from "./ArticleFooter"; +export { ArticleCallout, type ArticleCalloutProps } from "./ArticleCallout"; +export { ArticleTOC, type ArticleTOCProps } from "./ArticleTOC"; + +// — Theming (Phase 2) —————————————————————————— +export { ThemePicker, type ThemePickerProps, type AccentName } from "./ThemePicker"; +export { useAccent, applyAccent, ACCENT_PRESETS } from "./useAccent"; +export { useTheme, applyTheme, type ThemeMode } from "./useTheme"; diff --git a/packages/react/src/test-setup.ts b/packages/react/src/test-setup.ts new file mode 100644 index 0000000..59c74e3 --- /dev/null +++ b/packages/react/src/test-setup.ts @@ -0,0 +1,50 @@ +import { afterEach, expect } from "vitest"; +import { cleanup } from "@testing-library/react"; +import * as matchers from "@testing-library/jest-dom/matchers"; +import * as axeMatchers from "vitest-axe/matchers"; + +expect.extend(matchers); +expect.extend(axeMatchers); + +afterEach(() => { + cleanup(); +}); + +// Polyfills attendus par certains composants +if (!("ResizeObserver" in globalThis)) { + // @ts-expect-error — minimal stub for jsdom + globalThis.ResizeObserver = class { + observe() {} + unobserve() {} + disconnect() {} + }; +} + +if (!("IntersectionObserver" in globalThis)) { + // @ts-expect-error — minimal stub for jsdom + globalThis.IntersectionObserver = class { + observe() {} + unobserve() {} + disconnect() {} + takeRecords() { + return []; + } + }; +} + +// matchMedia polyfill (utilisé par Radix UI pour reduced-motion) +if (typeof window !== "undefined" && !window.matchMedia) { + Object.defineProperty(window, "matchMedia", { + writable: true, + value: (query: string) => ({ + matches: false, + media: query, + onchange: null, + addEventListener: () => {}, + removeEventListener: () => {}, + addListener: () => {}, + removeListener: () => {}, + dispatchEvent: () => false, + }), + }); +} diff --git a/packages/react/src/useAccent.ts b/packages/react/src/useAccent.ts new file mode 100644 index 0000000..ef5d06d --- /dev/null +++ b/packages/react/src/useAccent.ts @@ -0,0 +1,95 @@ +import { useCallback, useEffect, useState } from "react"; + +export type AccentName = + | "synapse" + | "rose" + | "blue" + | "violet" + | "green" + | "amber" + | "red" + | "cyan" + | "slate"; + +export const ACCENT_PRESETS: { name: AccentName; label: string; sample: string }[] = [ + { name: "synapse", label: "Rose Synapse", sample: "#D12B6A" }, + { name: "rose", label: "Rose vif", sample: "#E11D48" }, + { name: "blue", label: "Bleu", sample: "#2563EB" }, + { name: "violet", label: "Violet", sample: "#7C3AED" }, + { name: "green", label: "Vert", sample: "#0E9F6E" }, + { name: "amber", label: "Ambre", sample: "#D97706" }, + { name: "red", label: "Rouge", sample: "#DC2626" }, + { name: "cyan", label: "Cyan", sample: "#0891B2" }, + { name: "slate", label: "Ardoise", sample: "#475569" }, +]; + +const STORAGE_KEY = "mmg-accent"; +const DEFAULT_ACCENT: AccentName = "synapse"; + +/** + * Applique un accent au document. Pose [data-mmg-accent="..."] sur . + * Persiste optionnellement dans localStorage. À appeler tôt (avant React) + * pour éviter le flash visuel non désiré. + */ +export function applyAccent(accent: AccentName, persist = true) { + if (typeof document === "undefined") return; + const root = document.documentElement; + if (accent === DEFAULT_ACCENT) { + root.removeAttribute("data-mmg-accent"); + } else { + root.setAttribute("data-mmg-accent", accent); + } + if (persist && typeof window !== "undefined") { + try { + window.localStorage.setItem(STORAGE_KEY, accent); + } catch { + // localStorage may be unavailable (private mode, server) — silently ignore + } + } +} + +/** + * Récupère l'accent stocké côté navigateur, ou le défaut si rien n'est posé. + * Safe SSR : retourne DEFAULT_ACCENT si window n'existe pas. + */ +export function readStoredAccent(): AccentName { + if (typeof window === "undefined") return DEFAULT_ACCENT; + try { + const v = window.localStorage.getItem(STORAGE_KEY); + if (v && ACCENT_PRESETS.some((p) => p.name === v)) return v as AccentName; + } catch { + /* noop */ + } + return DEFAULT_ACCENT; +} + +export type UseAccentReturn = { + accent: AccentName; + setAccent: (a: AccentName) => void; + reset: () => void; +}; + +/** + * Hook pour lire et changer l'accent global. Synchronise localStorage et + * l'attribut [data-mmg-accent] sur . Le composant ThemePicker + * consomme ce hook. + */ +export function useAccent(): UseAccentReturn { + const [accent, setAccentState] = useState(() => readStoredAccent()); + + // Applique au mount pour SSR-safe (l'attribut peut être absent côté serveur). + useEffect(() => { + applyAccent(accent, false); + }, [accent]); + + const setAccent = useCallback((a: AccentName) => { + setAccentState(a); + applyAccent(a, true); + }, []); + + const reset = useCallback(() => { + setAccent(DEFAULT_ACCENT); + }, [setAccent]); + + return { accent, setAccent, reset }; +} diff --git a/packages/react/src/useFocusTrap.ts b/packages/react/src/useFocusTrap.ts new file mode 100644 index 0000000..ee0bf0f --- /dev/null +++ b/packages/react/src/useFocusTrap.ts @@ -0,0 +1,76 @@ +import { useEffect, useRef } from "react"; + +const FOCUSABLE = [ + 'a[href]:not([disabled])', + 'button:not([disabled])', + 'input:not([disabled]):not([type="hidden"])', + 'select:not([disabled])', + 'textarea:not([disabled])', + '[tabindex]:not([tabindex="-1"])', + '[contenteditable="true"]', +].join(","); + +/** + * Piège le focus à l'intérieur du conteneur tant que `active` est vrai. + * - Tab cycle vers le premier élément après le dernier (et inversement). + * - Au montage : focus sur le premier élément focusable. + * - Au démontage : restitution du focus à l'élément précédemment actif. + * + * Conforme WCAG SC 2.4.3 (Focus Order) et WAI-ARIA Authoring Practices + * pour les dialogues modaux. + */ +export function useFocusTrap(active: boolean) { + const ref = useRef(null); + + useEffect(() => { + if (!active) return; + const container = ref.current; + if (!container) return; + + const previouslyFocused = document.activeElement as HTMLElement | null; + + // Focus initial : premier focusable, sinon le conteneur lui-même + const focusables = container.querySelectorAll(FOCUSABLE); + const first = focusables[0] ?? container; + // tabindex sur le conteneur pour qu'il puisse recevoir le focus + if (first === container && !container.hasAttribute("tabindex")) { + container.setAttribute("tabindex", "-1"); + } + // setTimeout pour laisser l'animation d'ouverture se poser + const t = window.setTimeout(() => first.focus({ preventScroll: false }), 30); + + const onKeyDown = (e: KeyboardEvent) => { + if (e.key !== "Tab") return; + const focusables = Array.from( + container.querySelectorAll(FOCUSABLE), + ).filter((el) => el.offsetParent !== null); + if (focusables.length === 0) { + e.preventDefault(); + return; + } + const first = focusables[0]; + const last = focusables[focusables.length - 1]; + + if (e.shiftKey && document.activeElement === first) { + e.preventDefault(); + last.focus(); + } else if (!e.shiftKey && document.activeElement === last) { + e.preventDefault(); + first.focus(); + } + }; + + document.addEventListener("keydown", onKeyDown); + + return () => { + window.clearTimeout(t); + document.removeEventListener("keydown", onKeyDown); + // Restitution du focus + if (previouslyFocused && document.contains(previouslyFocused)) { + previouslyFocused.focus({ preventScroll: true }); + } + }; + }, [active]); + + return ref; +} diff --git a/packages/react/src/useTheme.ts b/packages/react/src/useTheme.ts new file mode 100644 index 0000000..0c9bdcd --- /dev/null +++ b/packages/react/src/useTheme.ts @@ -0,0 +1,56 @@ +import { useCallback, useEffect, useState } from "react"; + +export type ThemeMode = "light" | "dark" | "system"; +const STORAGE_KEY = "mmg-theme"; + +export function applyTheme(mode: ThemeMode, persist = true) { + if (typeof document === "undefined") return; + const root = document.documentElement; + if (mode === "system") { + root.removeAttribute("data-mmg-theme"); + } else { + root.setAttribute("data-mmg-theme", mode); + } + if (persist && typeof window !== "undefined") { + try { + window.localStorage.setItem(STORAGE_KEY, mode); + } catch { + /* noop */ + } + } +} + +function readStoredTheme(): ThemeMode { + if (typeof window === "undefined") return "system"; + try { + const v = window.localStorage.getItem(STORAGE_KEY); + if (v === "light" || v === "dark" || v === "system") return v; + } catch { + /* noop */ + } + return "system"; +} + +export function useTheme() { + const [theme, setThemeState] = useState(() => readStoredTheme()); + + useEffect(() => { + applyTheme(theme, false); + }, [theme]); + + const setTheme = useCallback((t: ThemeMode) => { + setThemeState(t); + applyTheme(t, true); + }, []); + + const toggle = useCallback(() => { + // light → dark → system → light + setThemeState((prev) => { + const next: ThemeMode = prev === "light" ? "dark" : prev === "dark" ? "system" : "light"; + applyTheme(next, true); + return next; + }); + }, []); + + return { theme, setTheme, toggle }; +} diff --git a/packages/react/src/utils.ts b/packages/react/src/utils.ts new file mode 100644 index 0000000..fd49964 --- /dev/null +++ b/packages/react/src/utils.ts @@ -0,0 +1,31 @@ +/** + * Concatène des classNames en filtrant les falsy. + * + * Accepte string, number (0/NaN ignorés), boolean (false ignoré), + * null/undefined, BigInt (0n ignoré, pour les contextes JSX modernes), + * et Record (clés ajoutées si la valeur est truthy). + * + * Pratique avec les patterns `condition && "class"` qui produisent + * facilement des unions type-larges en TS strict. + */ +type ClassValue = + | string + | number + | bigint + | boolean + | null + | undefined + | Record; + +export function cx(...args: ClassValue[]): string { + const out: string[] = []; + for (const a of args) { + if (!a) continue; + if (typeof a === "string") { + out.push(a); + } else if (typeof a === "object") { + for (const k in a) if (a[k]) out.push(k); + } + } + return out.join(" "); +} diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json new file mode 100644 index 0000000..7b3450b --- /dev/null +++ b/packages/react/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "jsx": "react-jsx", + "strict": true, + "noUncheckedIndexedAccess": false, + "noImplicitOverride": true, + "esModuleInterop": true, + "skipLibCheck": true, + "isolatedModules": true, + "verbatimModuleSyntax": false, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./dist", + "rootDir": "./src", + "noEmit": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "**/*.test.tsx", "**/*.test.ts"] +} diff --git a/packages/react/tsup.config.ts b/packages/react/tsup.config.ts new file mode 100644 index 0000000..eb1ee39 --- /dev/null +++ b/packages/react/tsup.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from "tsup"; + +/** + * @managemate/react — build config + * + * - Output dual (ESM + CJS) avec types .d.ts + * - Tree-shaking : sideEffects: false dans package.json garantit que les + * imports inutilisés sont droppés par les bundlers consommateurs. + * - Ne bundle PAS les peerDependencies (react, react-dom, @managemate/css). + */ +export default defineConfig({ + entry: ["src/index.tsx"], + format: ["esm", "cjs"], + dts: true, + sourcemap: true, + clean: true, + splitting: true, // ESM code-splitting pour permettre le tree-shaking par composant + treeshake: true, + minify: false, + target: "es2022", + external: ["react", "react-dom", "react/jsx-runtime", "@managemate/css", "@managemate/icons"], + // Garantit que les imports d'effet (CSS) ne sont pas tree-shakés par erreur, + // même si on en avait. Cf. https://webpack.js.org/guides/tree-shaking/ +}); diff --git a/packages/react/vitest.config.ts b/packages/react/vitest.config.ts new file mode 100644 index 0000000..51c76ff --- /dev/null +++ b/packages/react/vitest.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from "vitest/config"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react()], + test: { + environment: "jsdom", + globals: true, + setupFiles: ["./src/test-setup.ts"], + css: false, + coverage: { + provider: "v8", + reporter: ["text", "html", "lcov"], + include: ["src/**/*.{ts,tsx}"], + exclude: ["src/**/*.stories.{ts,tsx}", "src/test-setup.ts"], + thresholds: { + lines: 60, + functions: 60, + branches: 60, + statements: 60, + }, + }, + }, +}); diff --git a/packages/tokens/README.md b/packages/tokens/README.md new file mode 100644 index 0000000..e3f9bc4 --- /dev/null +++ b/packages/tokens/README.md @@ -0,0 +1,55 @@ +# @managemate/tokens + +Source unique des tokens DSMMG au format **W3C Design Tokens Community Group (DTCG)**. + +## Usage + +```sh +pnpm --filter @managemate/tokens build +``` + +Génère dans `dist/` : + +| Fichier | Format | Pour qui | +|---|---|---| +| `tokens.css` | CSS custom properties `--mmg-*` | Le navigateur, importé par `@managemate/css` | +| `tokens.js` | ESM | Code Node/Bundler — JS/TS apps | +| `tokens.cjs` | CommonJS | Code Node legacy | +| `tokens.d.ts` | TypeScript declarations | Auto-complete dans les IDEs | +| `figma-tokens.json` | [Tokens Studio](https://tokens.studio/) | Plugin Figma → sync designer↔code | + +## Workflow Figma + +1. Le designer modifie les variables dans Figma via [Tokens Studio](https://tokens.studio/). +2. Export → push vers `packages/tokens/src/tokens.json` (PR avec changeset minor). +3. CI valide les contrastes et regen les sorties. +4. Ou inversement : modifier `tokens.json` → CI regen Figma JSON → designer pull dans Figma. + +## DTCG schema + +Chaque token a une forme : + +```json +{ + "$value": "#D12B6A", + "$type": "color", + "$description": "(optionnel)" +} +``` + +Types supportés : `color`, `dimension`, `fontWeight`, `duration`. + +## Conventions de naming + +- `color..` : `color.synapse.500` +- `spacing.` : `spacing.4` (= 16px) +- `radius.` : `radius.md` +- `fontSize.` : `fontSize.base` +- `fontWeight.` : `fontWeight.semi` +- `duration.` : `duration.fast` + +Le préfixe CSS `--mmg-` est ajouté automatiquement par Style Dictionary. + +## Présets accent (cross-pkg) + +Les tokens primitifs sont publiés ici. Les presets accent (`[data-mmg-accent="…"]`) restent définis dans `@managemate/css` (`tokens/accent.css`) car ils dépendent du contexte (light/dark, sélection user). diff --git a/packages/tokens/build.mjs b/packages/tokens/build.mjs new file mode 100644 index 0000000..76cc887 --- /dev/null +++ b/packages/tokens/build.mjs @@ -0,0 +1,196 @@ +#!/usr/bin/env node +/** + * @managemate/tokens — build pipeline + * + * Source de vérité unique : src/tokens.json (format W3C DTCG). + * Génère : + * - dist/tokens.css : CSS custom properties --mmg-color-* + * - dist/tokens.js / .d.ts: objet JS/TS pour consommation programmatique + * - dist/tokens.cjs : CommonJS + * - dist/figma-tokens.json: format Tokens Studio pour sync Figma + */ +import StyleDictionary from "style-dictionary"; +import { mkdir, writeFile, readFile } from "node:fs/promises"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { existsSync } from "node:fs"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ROOT = __dirname; +const DIST = join(ROOT, "dist"); +const SOURCE = join(ROOT, "src", "tokens.json"); + +if (!existsSync(DIST)) await mkdir(DIST, { recursive: true }); + +// — Style Dictionary config ———————————————————————————————————— +const sd = new StyleDictionary({ + source: [SOURCE], + log: { warnings: "warn", verbosity: "default" }, + platforms: { + css: { + transformGroup: "css", + buildPath: "dist/", + files: [ + { + destination: "tokens.css", + format: "css/variables", + options: { + outputReferences: false, + selector: ":root", + }, + }, + ], + prefix: "mmg", + }, + js: { + transformGroup: "js", + buildPath: "dist/", + files: [ + { + destination: "tokens.js", + format: "javascript/esm", + }, + { + destination: "tokens.cjs", + format: "javascript/module", + }, + { + destination: "tokens.d.ts", + format: "typescript/es6-declarations", + }, + ], + prefix: "mmg", + }, + }, +}); + +await sd.cleanAllPlatforms(); +await sd.buildAllPlatforms(); + +// — Figma Tokens Studio export ———————————————————————————————————— +// Plugin Tokens Studio attend un format proche de DTCG mais avec une +// structure aplatie : { "color/neutral/50": { "value": "...", "type": "color" } } +const dtcg = JSON.parse(await readFile(SOURCE, "utf8")); + +function flatten(obj, prefix = "") { + const out = {}; + for (const [k, v] of Object.entries(obj)) { + if (k.startsWith("$")) continue; + const path = prefix ? `${prefix}/${k}` : k; + if (v && typeof v === "object" && "$value" in v) { + out[path] = { value: v.$value, type: v.$type }; + } else if (v && typeof v === "object") { + Object.assign(out, flatten(v, path)); + } + } + return out; +} + +const figmaTokens = { + global: flatten(dtcg), + $themes: [], + $metadata: { + tokenSetOrder: ["global"], + generatedAt: new Date().toISOString(), + generatedBy: "@managemate/tokens build.mjs", + }, +}; + +await writeFile(join(DIST, "figma-tokens.json"), JSON.stringify(figmaTokens, null, 2)); + +// — Tailwind v3 export (theme.extend JSON) ———————————————————————— +function buildTailwindV3() { + const colors = {}; + for (const [name, ramp] of Object.entries(dtcg.color ?? {})) { + if (!ramp || typeof ramp !== "object") continue; + const shades = {}; + for (const [shade, val] of Object.entries(ramp)) { + if (val && typeof val === "object" && "$value" in val) { + shades[shade] = val.$value; + } + } + if (Object.keys(shades).length > 0) colors[name] = shades; + } + const spacing = {}; + for (const [k, v] of Object.entries(dtcg.spacing ?? {})) { + if (v && typeof v === "object" && "$value" in v) { + spacing[`mmg-${k}`] = v.$value; + } + } + const radius = {}; + for (const [k, v] of Object.entries(dtcg.radius ?? {})) { + if (v && typeof v === "object" && "$value" in v) { + radius[`mmg-${k}`] = v.$value; + } + } + const fontSize = {}; + for (const [k, v] of Object.entries(dtcg.fontSize ?? {})) { + if (v && typeof v === "object" && "$value" in v) { + fontSize[`mmg-${k}`] = v.$value; + } + } + return { + theme: { + extend: { + colors: { mmg: colors }, + spacing, + borderRadius: radius, + fontSize, + }, + }, + }; +} + +await writeFile( + join(DIST, "tailwind.config.json"), + JSON.stringify(buildTailwindV3(), null, 2), +); + +// — Tailwind v4 export (@theme CSS block) ———————————————————————— +function buildTailwindV4() { + const lines = ["/* DSMMG tokens — Tailwind v4 @theme block. */", "@theme {"]; + // Colors + for (const [name, ramp] of Object.entries(dtcg.color ?? {})) { + if (!ramp || typeof ramp !== "object") continue; + for (const [shade, val] of Object.entries(ramp)) { + if (val && typeof val === "object" && "$value" in val) { + lines.push(` --color-mmg-${name}-${shade}: ${val.$value};`); + } + } + } + // Spacing + for (const [k, v] of Object.entries(dtcg.spacing ?? {})) { + if (v && typeof v === "object" && "$value" in v) { + lines.push(` --spacing-mmg-${k}: ${v.$value};`); + } + } + // Radius + for (const [k, v] of Object.entries(dtcg.radius ?? {})) { + if (v && typeof v === "object" && "$value" in v) { + lines.push(` --radius-mmg-${k}: ${v.$value};`); + } + } + // Font sizes + for (const [k, v] of Object.entries(dtcg.fontSize ?? {})) { + if (v && typeof v === "object" && "$value" in v) { + lines.push(` --text-mmg-${k}: ${v.$value};`); + } + } + // Durations + for (const [k, v] of Object.entries(dtcg.duration ?? {})) { + if (v && typeof v === "object" && "$value" in v) { + lines.push(` --animate-duration-mmg-${k}: ${v.$value};`); + } + } + lines.push("}"); + return lines.join("\n") + "\n"; +} + +await writeFile(join(DIST, "tailwind.css"), buildTailwindV4()); + +console.log(`✓ Tokens built → ${DIST}`); +console.log(` - tokens.css (CSS custom properties)`); +console.log(` - tokens.{js,cjs,d.ts} (ESM / CJS / TypeScript)`); +console.log(` - figma-tokens.json (Tokens Studio for Figma sync)`); +console.log(` - tailwind.config.json (Tailwind v3 theme.extend)`); +console.log(` - tailwind.css (Tailwind v4 @theme block)`); diff --git a/packages/tokens/package.json b/packages/tokens/package.json new file mode 100644 index 0000000..24506fd --- /dev/null +++ b/packages/tokens/package.json @@ -0,0 +1,36 @@ +{ + "name": "@managemate/tokens", + "version": "0.1.0", + "description": "DSMMG design tokens — DTCG source + Style Dictionary build (CSS, TS, Figma)", + "type": "module", + "license": "UNLICENSED", + "private": true, + "sideEffects": false, + "main": "./dist/tokens.cjs", + "module": "./dist/tokens.js", + "types": "./dist/tokens.d.ts", + "exports": { + ".": { + "types": "./dist/tokens.d.ts", + "import": "./dist/tokens.js", + "require": "./dist/tokens.cjs" + }, + "./css": "./dist/tokens.css", + "./figma": "./dist/figma-tokens.json", + "./tailwind": "./dist/tailwind.config.json", + "./tailwind.css": "./dist/tailwind.css", + "./source": "./src/tokens.json", + "./package.json": "./package.json" + }, + "files": [ + "dist", + "src" + ], + "scripts": { + "build": "node build.mjs", + "watch": "node build.mjs --watch" + }, + "devDependencies": { + "style-dictionary": "^4.3.3" + } +} diff --git a/packages/tokens/src/tokens.json b/packages/tokens/src/tokens.json new file mode 100644 index 0000000..7f24600 --- /dev/null +++ b/packages/tokens/src/tokens.json @@ -0,0 +1,173 @@ +{ + "$schema": "https://schemas.tr.designtokens.org/format/", + "color": { + "neutral": { + "0": { "$value": "#FFFFFF", "$type": "color" }, + "50": { "$value": "#F7F6FB", "$type": "color" }, + "100": { "$value": "#F0EFF9", "$type": "color" }, + "150": { "$value": "#EDEDFA", "$type": "color" }, + "200": { "$value": "#E4E3F4", "$type": "color" }, + "300": { "$value": "#C9C7E0", "$type": "color" }, + "400": { "$value": "#AAA8C9", "$type": "color" }, + "500": { "$value": "#7875A1", "$type": "color" }, + "600": { "$value": "#56557A", "$type": "color" }, + "700": { "$value": "#3B3A56", "$type": "color" }, + "800": { "$value": "#1F1E32", "$type": "color" }, + "900": { "$value": "#111120", "$type": "color" } + }, + "synapse": { + "50": { "$value": "#FEF0F4", "$type": "color" }, + "100": { "$value": "#FCE0EA", "$type": "color" }, + "200": { "$value": "#FAD0DF", "$type": "color" }, + "300": { "$value": "#F4A0BD", "$type": "color" }, + "400": { "$value": "#ED608E", "$type": "color" }, + "500": { "$value": "#D12B6A", "$type": "color" }, + "600": { "$value": "#BA245F", "$type": "color" }, + "700": { "$value": "#A82257", "$type": "color" }, + "800": { "$value": "#831B45", "$type": "color" }, + "900": { "$value": "#5A132F", "$type": "color" } + }, + "rose": { + "50": { "$value": "#FFF1F2", "$type": "color" }, + "100": { "$value": "#FFE4E6", "$type": "color" }, + "200": { "$value": "#FECDD3", "$type": "color" }, + "300": { "$value": "#FDA4AF", "$type": "color" }, + "400": { "$value": "#FB7185", "$type": "color" }, + "500": { "$value": "#E11D48", "$type": "color" }, + "600": { "$value": "#BE123C", "$type": "color" }, + "700": { "$value": "#9F1239", "$type": "color" }, + "800": { "$value": "#881337", "$type": "color" }, + "900": { "$value": "#4C0519", "$type": "color" } + }, + "blue": { + "50": { "$value": "#EFF6FF", "$type": "color" }, + "100": { "$value": "#DBEAFE", "$type": "color" }, + "200": { "$value": "#BFDBFE", "$type": "color" }, + "300": { "$value": "#93C5FD", "$type": "color" }, + "400": { "$value": "#60A5FA", "$type": "color" }, + "500": { "$value": "#2563EB", "$type": "color" }, + "600": { "$value": "#1D4ED8", "$type": "color" }, + "700": { "$value": "#1E40AF", "$type": "color" }, + "800": { "$value": "#1E3A8A", "$type": "color" }, + "900": { "$value": "#172554", "$type": "color" } + }, + "violet": { + "50": { "$value": "#F5F3FF", "$type": "color" }, + "100": { "$value": "#EDE9FE", "$type": "color" }, + "200": { "$value": "#DDD6FE", "$type": "color" }, + "300": { "$value": "#C4B5FD", "$type": "color" }, + "400": { "$value": "#A78BFA", "$type": "color" }, + "500": { "$value": "#7C3AED", "$type": "color" }, + "600": { "$value": "#6D28D9", "$type": "color" }, + "700": { "$value": "#5B21B6", "$type": "color" }, + "800": { "$value": "#4C1D95", "$type": "color" }, + "900": { "$value": "#2E1065", "$type": "color" } + }, + "green": { + "50": { "$value": "#ECFDF5", "$type": "color" }, + "100": { "$value": "#D1FAE5", "$type": "color" }, + "200": { "$value": "#BAEFD3", "$type": "color" }, + "300": { "$value": "#6EE7B7", "$type": "color" }, + "400": { "$value": "#34D399", "$type": "color" }, + "500": { "$value": "#0E9F6E", "$type": "color" }, + "600": { "$value": "#0B8861", "$type": "color" }, + "700": { "$value": "#086B4D", "$type": "color" }, + "800": { "$value": "#064E3B", "$type": "color" }, + "900": { "$value": "#022C22", "$type": "color" } + }, + "amber": { + "50": { "$value": "#FFFBEB", "$type": "color" }, + "100": { "$value": "#FEF3C7", "$type": "color" }, + "200": { "$value": "#FDE68A", "$type": "color" }, + "300": { "$value": "#FCD34D", "$type": "color" }, + "400": { "$value": "#FBBF24", "$type": "color" }, + "500": { "$value": "#D97706", "$type": "color" }, + "600": { "$value": "#B45309", "$type": "color" }, + "700": { "$value": "#92400E", "$type": "color" }, + "800": { "$value": "#78350F", "$type": "color" }, + "900": { "$value": "#451A03", "$type": "color" } + }, + "red": { + "50": { "$value": "#FEF2F2", "$type": "color" }, + "100": { "$value": "#FEE2E2", "$type": "color" }, + "200": { "$value": "#FECACA", "$type": "color" }, + "300": { "$value": "#FCA5A5", "$type": "color" }, + "400": { "$value": "#F87171", "$type": "color" }, + "500": { "$value": "#DC2626", "$type": "color" }, + "600": { "$value": "#B91C1C", "$type": "color" }, + "700": { "$value": "#991B1B", "$type": "color" }, + "800": { "$value": "#7F1D1D", "$type": "color" }, + "900": { "$value": "#450A0A", "$type": "color" } + }, + "cyan": { + "50": { "$value": "#ECFEFF", "$type": "color" }, + "100": { "$value": "#CFFAFE", "$type": "color" }, + "200": { "$value": "#A5F3FC", "$type": "color" }, + "300": { "$value": "#67E8F9", "$type": "color" }, + "400": { "$value": "#22D3EE", "$type": "color" }, + "500": { "$value": "#0891B2", "$type": "color" }, + "600": { "$value": "#0E7490", "$type": "color" }, + "700": { "$value": "#155E75", "$type": "color" }, + "800": { "$value": "#164E63", "$type": "color" }, + "900": { "$value": "#083344", "$type": "color" } + }, + "slate": { + "50": { "$value": "#F8FAFC", "$type": "color" }, + "100": { "$value": "#F1F5F9", "$type": "color" }, + "200": { "$value": "#E2E8F0", "$type": "color" }, + "300": { "$value": "#CBD5E1", "$type": "color" }, + "400": { "$value": "#94A3B8", "$type": "color" }, + "500": { "$value": "#475569", "$type": "color" }, + "600": { "$value": "#334155", "$type": "color" }, + "700": { "$value": "#1E293B", "$type": "color" }, + "800": { "$value": "#0F172A", "$type": "color" }, + "900": { "$value": "#020617", "$type": "color" } + } + }, + "spacing": { + "0": { "$value": "0px", "$type": "dimension" }, + "1": { "$value": "4px", "$type": "dimension" }, + "2": { "$value": "8px", "$type": "dimension" }, + "3": { "$value": "12px", "$type": "dimension" }, + "4": { "$value": "16px", "$type": "dimension" }, + "5": { "$value": "20px", "$type": "dimension" }, + "6": { "$value": "24px", "$type": "dimension" }, + "7": { "$value": "32px", "$type": "dimension" }, + "8": { "$value": "40px", "$type": "dimension" }, + "9": { "$value": "48px", "$type": "dimension" }, + "10": { "$value": "64px", "$type": "dimension" }, + "11": { "$value": "80px", "$type": "dimension" }, + "12": { "$value": "120px", "$type": "dimension" } + }, + "radius": { + "sm": { "$value": "8px", "$type": "dimension" }, + "md": { "$value": "12px", "$type": "dimension" }, + "card": { "$value": "20px", "$type": "dimension" }, + "panel": { "$value": "24px", "$type": "dimension" }, + "icon": { "$value": "12px", "$type": "dimension" }, + "pill": { "$value": "9999px", "$type": "dimension" } + }, + "fontSize": { + "xs": { "$value": "11px", "$type": "dimension" }, + "sm": { "$value": "13px", "$type": "dimension" }, + "base": { "$value": "15px", "$type": "dimension" }, + "lg": { "$value": "17px", "$type": "dimension" }, + "xl": { "$value": "20px", "$type": "dimension" }, + "2xl": { "$value": "24px", "$type": "dimension" }, + "3xl": { "$value": "30px", "$type": "dimension" }, + "4xl": { "$value": "36px", "$type": "dimension" }, + "5xl": { "$value": "48px", "$type": "dimension" } + }, + "fontWeight": { + "regular": { "$value": 400, "$type": "fontWeight" }, + "medium": { "$value": 500, "$type": "fontWeight" }, + "semi": { "$value": 600, "$type": "fontWeight" }, + "bold": { "$value": 700, "$type": "fontWeight" }, + "extra": { "$value": 800, "$type": "fontWeight" } + }, + "duration": { + "fast": { "$value": "120ms", "$type": "duration" }, + "base": { "$value": "200ms", "$type": "duration" }, + "slow": { "$value": "320ms", "$type": "duration" } + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..9d5ba35 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,11621 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@changesets/cli': + specifier: ^2.27.11 + version: 2.31.0(@types/node@24.12.2) + '@size-limit/preset-small-lib': + specifier: ^11.1.6 + version: 11.2.0(size-limit@11.2.0) + size-limit: + specifier: ^11.1.6 + version: 11.2.0 + + demo: + dependencies: + '@managemate/css': + specifier: workspace:* + version: link:../packages/css + '@managemate/icons': + specifier: workspace:* + version: link:../packages/icons + '@managemate/react': + specifier: workspace:* + version: link:../packages/react + react: + specifier: ^19.2.5 + version: 19.2.5 + react-dom: + specifier: ^19.2.5 + version: 19.2.5(react@19.2.5) + devDependencies: + '@types/react': + specifier: ^19.2.14 + version: 19.2.14 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react': + specifier: ^6.0.1 + version: 6.0.1(vite@8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4)) + typescript: + specifier: ~6.0.2 + version: 6.0.3 + vite: + specifier: ^8.0.10 + version: 8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4) + + docs: + dependencies: + '@astrojs/starlight': + specifier: ^0.30.0 + version: 0.30.6(astro@5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4)) + '@managemate/css': + specifier: workspace:* + version: link:../packages/css + '@managemate/icons': + specifier: workspace:* + version: link:../packages/icons + astro: + specifier: ^5.0.0 + version: 5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4) + sharp: + specifier: ^0.33.0 + version: 0.33.5 + + packages/css: + devDependencies: + autoprefixer: + specifier: ^10.4.20 + version: 10.5.0(postcss@8.5.13) + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + cssnano: + specifier: ^7.0.7 + version: 7.1.8(postcss@8.5.13) + postcss: + specifier: ^8.5.0 + version: 8.5.13 + postcss-cli: + specifier: ^11.0.0 + version: 11.0.1(jiti@2.6.1)(postcss@8.5.13) + postcss-import: + specifier: ^16.1.0 + version: 16.1.1(postcss@8.5.13) + + packages/icons: + dependencies: + remixicon: + specifier: ^4.9.1 + version: 4.9.1 + + packages/react: + dependencies: + '@floating-ui/react': + specifier: ^0.27.0 + version: 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@managemate/css': + specifier: workspace:* + version: link:../css + '@managemate/icons': + specifier: workspace:* + version: link:../icons + '@radix-ui/react-context-menu': + specifier: ^2.2.14 + version: 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-dialog': + specifier: ^1.1.13 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-dropdown-menu': + specifier: ^2.1.14 + version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-hover-card': + specifier: ^1.1.13 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-popover': + specifier: ^1.1.13 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slider': + specifier: ^1.3.4 + version: 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-toggle-group': + specifier: ^1.1.9 + version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-tooltip': + specifier: ^1.2.6 + version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: + specifier: '>=18' + version: 19.2.5 + react-dom: + specifier: '>=18' + version: 19.2.5(react@19.2.5) + devDependencies: + '@testing-library/jest-dom': + specifier: ^6.6.3 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.1.0 + version: 16.3.2(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@testing-library/user-event': + specifier: ^14.5.2 + version: 14.6.1(@testing-library/dom@10.4.0) + '@types/react': + specifier: ^19.2.14 + version: 19.2.14 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.7.0(vite@8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4)) + axe-core: + specifier: ^4.10.2 + version: 4.11.4 + jsdom: + specifier: ^25.0.1 + version: 25.0.1 + tsup: + specifier: ^8.5.0 + version: 8.5.1(jiti@2.6.1)(postcss@8.5.13)(typescript@5.7.3)(yaml@2.8.4) + typescript: + specifier: ~5.7.0 + version: 5.7.3 + vitest: + specifier: ^2.1.9 + version: 2.1.9(@types/node@24.12.2)(jsdom@25.0.1)(lightningcss@1.32.0) + vitest-axe: + specifier: ^0.1.0 + version: 0.1.0(vitest@2.1.9(@types/node@24.12.2)(jsdom@25.0.1)(lightningcss@1.32.0)) + + packages/tokens: + devDependencies: + style-dictionary: + specifier: ^4.3.3 + version: 4.4.0(tslib@2.8.1) + + storybook: + dependencies: + '@managemate/css': + specifier: workspace:* + version: link:../packages/css + '@managemate/icons': + specifier: workspace:* + version: link:../packages/icons + '@managemate/react': + specifier: workspace:* + version: link:../packages/react + react: + specifier: ^19.2.5 + version: 19.2.5 + react-dom: + specifier: ^19.2.5 + version: 19.2.5(react@19.2.5) + devDependencies: + '@storybook/addon-a11y': + specifier: ^8.5.0 + version: 8.6.18(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-essentials': + specifier: ^8.5.0 + version: 8.6.14(@types/react@19.2.14)(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-interactions': + specifier: ^8.5.0 + version: 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/blocks': + specifier: ^8.5.0 + version: 8.6.14(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3)) + '@storybook/react': + specifier: ^8.5.0 + version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.3)))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3))(typescript@5.7.3) + '@storybook/react-vite': + specifier: ^8.5.0 + version: 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.3)))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(rollup@4.60.2)(storybook@8.6.18(prettier@3.8.3))(typescript@5.7.3)(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0)) + '@storybook/test': + specifier: ^8.5.0 + version: 8.6.15(storybook@8.6.18(prettier@3.8.3)) + '@types/react': + specifier: ^19.2.14 + version: 19.2.14 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.7.0(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0)) + storybook: + specifier: ^8.5.0 + version: 8.6.18(prettier@3.8.3) + typescript: + specifier: ~5.7.0 + version: 5.7.3 + vite: + specifier: ^5.4.11 + version: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + +packages: + + '@adobe/css-tools@4.4.4': + resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + + '@astrojs/compiler@2.13.1': + resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==} + + '@astrojs/internal-helpers@0.7.6': + resolution: {integrity: sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q==} + + '@astrojs/markdown-remark@6.3.11': + resolution: {integrity: sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==} + + '@astrojs/mdx@4.3.14': + resolution: {integrity: sha512-FBrqJQORVm+rkRa2TS5CjU9PBA6hkhrwLVBSS9A77gN2+iehvjq1w6yya/d0YKC7osiVorKkr3Qd9wNbl0ZkGA==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + peerDependencies: + astro: ^5.0.0 + + '@astrojs/prism@3.3.0': + resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@astrojs/sitemap@3.7.2': + resolution: {integrity: sha512-PqkzkcZTb5ICiyIR8VoKbIAP/laNRXi5tw616N1Ckk+40oNB8Can1AzVV56lrbC5GKSZFCyJYUVYqVivMisvpA==} + + '@astrojs/starlight@0.30.6': + resolution: {integrity: sha512-/AoLXjPPD1MqixkTd2Lp3qahSzfCejePWHZQ3+fDjj1CuXI7Gjrr5bR3zNV0b9tynloPAIBM0HOyBNEGAo9uAQ==} + peerDependencies: + astro: ^5.0.0 + + '@astrojs/telemetry@3.3.0': + resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0} + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.3': + resolution: {integrity: sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.3': + resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@bundled-es-modules/deepmerge@4.3.1': + resolution: {integrity: sha512-Rk453EklPUPC3NRWc3VUNI/SSUjdBaFoaQvFRmNBNtMHVtOFD5AntiWg5kEE1hqcPqedYFDzxE3ZcMYPcA195w==} + + '@bundled-es-modules/glob@10.4.2': + resolution: {integrity: sha512-740y5ofkzydsFao5EXJrGilcIL6EFEw/cmPf2uhTw9J6G1YOhiIFjNFCHdpgEiiH5VlU3G0SARSjlFlimRRSMA==} + + '@bundled-es-modules/memfs@4.17.0': + resolution: {integrity: sha512-ykdrkEmQr9BV804yd37ikXfNnvxrwYfY9Z2/EtMHFEFadEjsQXJ1zL9bVZrKNLDtm91UdUOEHso6Aweg93K6xQ==} + + '@capsizecss/unpack@4.0.0': + resolution: {integrity: sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==} + engines: {node: '>=18'} + + '@changesets/apply-release-plan@7.1.1': + resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==} + + '@changesets/assemble-release-plan@6.0.10': + resolution: {integrity: sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/cli@2.31.0': + resolution: {integrity: sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg==} + hasBin: true + + '@changesets/config@3.1.4': + resolution: {integrity: sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.4': + resolution: {integrity: sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==} + + '@changesets/get-release-plan@4.0.16': + resolution: {integrity: sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.4': + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.3': + resolution: {integrity: sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.7': + resolution: {integrity: sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + + '@colordx/core@5.4.3': + resolution: {integrity: sha512-kIxYSfA5T8HXjav55UaaH/o/cKivF6jCCGIb8eqtcsfI46wsvlSiT8jMDyrl779qLec3c2c2oHBZo4oAhvbjrQ==} + + '@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-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@ctrl/tinycolor@4.2.0': + resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} + engines: {node: '>=14'} + + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + 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'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + 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'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + 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'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + 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.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + 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.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + 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.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@expressive-code/core@0.38.3': + resolution: {integrity: sha512-s0/OtdRpBONwcn23O8nVwDNQqpBGKscysejkeBkwlIeHRLZWgiTVrusT5Idrdz1d8cW5wRk9iGsAIQmwDPXgJg==} + + '@expressive-code/plugin-frames@0.38.3': + resolution: {integrity: sha512-qL2oC6FplmHNQfZ8ZkTR64/wKo9x0c8uP2WDftR/ydwN/yhe1ed7ZWYb8r3dezxsls+tDokCnN4zYR594jbpvg==} + + '@expressive-code/plugin-shiki@0.38.3': + resolution: {integrity: sha512-kqHnglZeesqG3UKrb6e9Fq5W36AZ05Y9tCREmSN2lw8LVTqENIeCIkLDdWtQ5VoHlKqwUEQFTVlRehdwoY7Gmw==} + + '@expressive-code/plugin-text-markers@0.38.3': + resolution: {integrity: sha512-dPK3+BVGTbTmGQGU3Fkj3jZ3OltWUAlxetMHI6limUGCWBCucZiwoZeFM/WmqQa71GyKRzhBT+iEov6kkz2xVA==} + + '@floating-ui/core@1.7.5': + resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} + + '@floating-ui/dom@1.7.6': + resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} + + '@floating-ui/react-dom@2.1.8': + resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.27.19': + resolution: {integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==} + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@floating-ui/utils@0.2.11': + resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-arm64@0.34.5': + resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.5': + resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.4': + resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.4': + resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm64@1.2.4': + resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.2.4': + resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.2.4': + resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.2.4': + resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.2.4': + resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.2.4': + resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm64@0.34.5': + resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.34.5': + resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.34.5': + resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.34.5': + resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.34.5': + resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.34.5': + resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-arm64@0.34.5': + resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.34.5': + resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-wasm32@0.34.5': + resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.5': + resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-ia32@0.34.5': + resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@img/sharp-win32-x64@0.34.5': + resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0': + resolution: {integrity: sha512-qYDdL7fPwLRI+bJNurVcis+tNgJmvWjH4YTBGXTA8xMuxFrnAz6E5o35iyzyKbq5J5Lr8mJGfrR5GXl+WGwhgQ==} + peerDependencies: + typescript: '>= 4.3.x' + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/base64@17.67.0': + resolution: {integrity: sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@1.2.1': + resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@17.67.0': + resolution: {integrity: sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@1.0.0': + resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@17.67.0': + resolution: {integrity: sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-core@4.57.2': + resolution: {integrity: sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-fsa@4.57.2': + resolution: {integrity: sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-builtins@4.57.2': + resolution: {integrity: sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-to-fsa@4.57.2': + resolution: {integrity: sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-utils@4.57.2': + resolution: {integrity: sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node@4.57.2': + resolution: {integrity: sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-print@4.57.2': + resolution: {integrity: sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-snapshot@4.57.2': + resolution: {integrity: sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.21.0': + resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@17.67.0': + resolution: {integrity: sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@1.0.2': + resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@17.67.0': + resolution: {integrity: sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.9.0': + resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@17.67.0': + resolution: {integrity: sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@mdx-js/mdx@3.1.1': + resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} + + '@mdx-js/react@3.1.1': + resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + '@oxc-project/types@0.127.0': + resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==} + + '@pagefind/darwin-arm64@1.5.2': + resolution: {integrity: sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ==} + cpu: [arm64] + os: [darwin] + + '@pagefind/darwin-x64@1.5.2': + resolution: {integrity: sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw==} + cpu: [x64] + os: [darwin] + + '@pagefind/default-ui@1.5.2': + resolution: {integrity: sha512-pm1LMnQg8N2B3n2TnjKlhaFihpz6zTiA4HiGQ6/slKO/+8K9CAU5kcjdSSPgpuk1PMuuN4hxLipUIifnrkl3Sg==} + + '@pagefind/freebsd-x64@1.5.2': + resolution: {integrity: sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA==} + cpu: [x64] + os: [freebsd] + + '@pagefind/linux-arm64@1.5.2': + resolution: {integrity: sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==} + cpu: [arm64] + os: [linux] + + '@pagefind/linux-x64@1.5.2': + resolution: {integrity: sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==} + cpu: [x64] + os: [linux] + + '@pagefind/windows-arm64@1.5.2': + resolution: {integrity: sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==} + cpu: [arm64] + os: [win32] + + '@pagefind/windows-x64@1.5.2': + resolution: {integrity: sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==} + cpu: [x64] + os: [win32] + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@radix-ui/number@1.1.1': + resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} + + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-context-menu@2.2.16': + resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.1.15': + resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-hover-card@1.1.15': + resolution: {integrity: sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popover@1.1.15': + resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slider@1.3.6': + resolution: {integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-toggle-group@1.1.11': + resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-toggle@1.1.10': + resolution: {integrity: sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-tooltip@1.2.8': + resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-previous@1.1.1': + resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-visually-hidden@1.2.3': + resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + + '@rolldown/binding-android-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.17': + resolution: {integrity: sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + resolution: {integrity: sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + resolution: {integrity: sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + resolution: {integrity: sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + resolution: {integrity: sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + resolution: {integrity: sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + resolution: {integrity: sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + resolution: {integrity: sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + resolution: {integrity: sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + resolution: {integrity: sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + + '@rolldown/pluginutils@1.0.0-rc.17': + resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} + + '@rolldown/pluginutils@1.0.0-rc.7': + resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==} + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.60.2': + resolution: {integrity: sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.60.2': + resolution: {integrity: sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.60.2': + resolution: {integrity: sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.60.2': + resolution: {integrity: sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.60.2': + resolution: {integrity: sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.2': + resolution: {integrity: sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.2': + resolution: {integrity: sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.60.2': + resolution: {integrity: sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.60.2': + resolution: {integrity: sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.60.2': + resolution: {integrity: sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.60.2': + resolution: {integrity: sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-loong64-musl@4.60.2': + resolution: {integrity: sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.60.2': + resolution: {integrity: sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-musl@4.60.2': + resolution: {integrity: sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.60.2': + resolution: {integrity: sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.60.2': + resolution: {integrity: sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.60.2': + resolution: {integrity: sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.60.2': + resolution: {integrity: sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.60.2': + resolution: {integrity: sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openbsd-x64@4.60.2': + resolution: {integrity: sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.2': + resolution: {integrity: sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.2': + resolution: {integrity: sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.2': + resolution: {integrity: sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.2': + resolution: {integrity: sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.2': + resolution: {integrity: sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==} + cpu: [x64] + os: [win32] + + '@shikijs/core@1.29.2': + resolution: {integrity: sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==} + + '@shikijs/core@3.23.0': + resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} + + '@shikijs/engine-javascript@1.29.2': + resolution: {integrity: sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==} + + '@shikijs/engine-javascript@3.23.0': + resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==} + + '@shikijs/engine-oniguruma@1.29.2': + resolution: {integrity: sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==} + + '@shikijs/engine-oniguruma@3.23.0': + resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} + + '@shikijs/langs@1.29.2': + resolution: {integrity: sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==} + + '@shikijs/langs@3.23.0': + resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} + + '@shikijs/themes@1.29.2': + resolution: {integrity: sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==} + + '@shikijs/themes@3.23.0': + resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} + + '@shikijs/types@1.29.2': + resolution: {integrity: sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==} + + '@shikijs/types@3.23.0': + resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} + + '@shikijs/vscode-textmate@10.0.2': + resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + + '@size-limit/esbuild@11.2.0': + resolution: {integrity: sha512-vSg9H0WxGQPRzDnBzeDyD9XT0Zdq0L+AI3+77/JhxznbSCMJMMr8ndaWVQRhOsixl97N0oD4pRFw2+R1Lcvi6A==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + size-limit: 11.2.0 + + '@size-limit/file@11.2.0': + resolution: {integrity: sha512-OZHE3putEkQ/fgzz3Tp/0hSmfVo3wyTpOJSRNm6AmcwX4Nm9YtTfbQQ/hZRwbBFR23S7x2Sd9EbqYzngKwbRoA==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + size-limit: 11.2.0 + + '@size-limit/preset-small-lib@11.2.0': + resolution: {integrity: sha512-RFbbIVfv8/QDgTPyXzjo5NKO6CYyK5Uq5xtNLHLbw5RgSKrgo8WpiB/fNivZuNd/5Wk0s91PtaJ9ThNcnFuI3g==} + peerDependencies: + size-limit: 11.2.0 + + '@storybook/addon-a11y@8.6.18': + resolution: {integrity: sha512-LFvudttdIfDTNWprA8/N1vbiWbJRrNscyt2OP9Qwi85E1d3LKLy+e8AWiqY08gpy2OUYujK7AjxfpKtNeddrxw==} + peerDependencies: + storybook: ^8.6.18 + + '@storybook/addon-actions@8.6.14': + resolution: {integrity: sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-backgrounds@8.6.14': + resolution: {integrity: sha512-l9xS8qWe5n4tvMwth09QxH2PmJbCctEvBAc1tjjRasAfrd69f7/uFK4WhwJAstzBTNgTc8VXI4w8ZR97i1sFbg==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-controls@8.6.14': + resolution: {integrity: sha512-IiQpkNJdiRyA4Mq9mzjZlvQugL/aE7hNgVxBBGPiIZG6wb6Ht9hNnBYpap5ZXXFKV9p2qVI0FZK445ONmAa+Cw==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-docs@8.6.14': + resolution: {integrity: sha512-Obpd0OhAF99JyU5pp5ci17YmpcQtMNgqW2pTXV8jAiiipWpwO++hNDeQmLmlSXB399XjtRDOcDVkoc7rc6JzdQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-essentials@8.6.14': + resolution: {integrity: sha512-5ZZSHNaW9mXMOFkoPyc3QkoNGdJHETZydI62/OASR0lmPlJ1065TNigEo5dJddmZNn0/3bkE8eKMAzLnO5eIdA==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-highlight@8.6.14': + resolution: {integrity: sha512-4H19OJlapkofiE9tM6K/vsepf4ir9jMm9T+zw5L85blJZxhKZIbJ6FO0TCG9PDc4iPt3L6+aq5B0X29s9zicNQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-highlight@8.6.18': + resolution: {integrity: sha512-wTFJ1DPM0C8gK6nGTJxH75byayQj7BPAz02fME4AOmT6clrBpVl1zSTFTkXaSr+k4xOfeMR/xNUfVskaXz6T9w==} + peerDependencies: + storybook: ^8.6.18 + + '@storybook/addon-interactions@8.6.14': + resolution: {integrity: sha512-8VmElhm2XOjh22l/dO4UmXxNOolGhNiSpBcls2pqWSraVh4a670EyYBZsHpkXqfNHo2YgKyZN3C91+9zfH79qQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-measure@8.6.14': + resolution: {integrity: sha512-1Tlyb72NX8aAqm6I6OICsUuGOP6hgnXcuFlXucyhKomPa6j3Eu2vKu561t/f0oGtAK2nO93Z70kVaEh5X+vaGw==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-outline@8.6.14': + resolution: {integrity: sha512-CW857JvN6OxGWElqjlzJO2S69DHf+xO3WsEfT5mT3ZtIjmsvRDukdWfDU9bIYUFyA2lFvYjncBGjbK+I91XR7w==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-toolbars@8.6.14': + resolution: {integrity: sha512-W/wEXT8h3VyZTVfWK/84BAcjAxTdtRiAkT2KAN0nbSHxxB5KEM1MjKpKu2upyzzMa3EywITqbfy4dP6lpkVTwQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-viewport@8.6.14': + resolution: {integrity: sha512-gNzVQbMqRC+/4uQTPI2ZrWuRHGquTMZpdgB9DrD88VTEjNudP+J6r8myLfr2VvGksBbUMHkGHMXHuIhrBEnXYA==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/blocks@8.6.14': + resolution: {integrity: sha512-rBMHAfA39AGHgkrDze4RmsnQTMw1ND5fGWobr9pDcJdnDKWQWNRD7Nrlxj0gFlN3n4D9lEZhWGdFrCbku7FVAQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^8.6.14 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + + '@storybook/builder-vite@8.6.18': + resolution: {integrity: sha512-XLqnOv4C36jlTd4uC8xpWBxv+7GV4/05zWJ0wAcU4qflorropUTirt4UQPGkwIzi+BVAhs9pJj+m4k0IWJtpHg==} + peerDependencies: + storybook: ^8.6.18 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + + '@storybook/components@8.6.18': + resolution: {integrity: sha512-55yViiZzPS/cPBuOeW4QGxGqrusjXVyxuknmbYCIwDtFyyvI/CgbjXRHdxNBaIjz+IlftxvBmmSaOqFG5+/dkA==} + 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.18': + resolution: {integrity: sha512-dRBP2TnX6fGdS0T2mXBHjkS/3Nlu1ra1huovZVFuM67CYMzrhM/3hX/zru1vWSC5rqY93ZaAhjMciPW4pK5mMQ==} + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + + '@storybook/csf-plugin@8.6.14': + resolution: {integrity: sha512-dErtc9teAuN+eelN8FojzFE635xlq9cNGGGEu0WEmMUQ4iJ8pingvBO1N8X3scz4Ry7KnxX++NNf3J3gpxS8qQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/csf-plugin@8.6.18': + resolution: {integrity: sha512-x1ioz/L0CwaelCkHci3P31YtvwayN3FBftvwQOPbvRh9qeb4Cpz5IdVDmyvSxxYwXN66uAORNoqgjTi7B4/y5Q==} + peerDependencies: + storybook: ^8.6.18 + + '@storybook/global@5.0.0': + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} + + '@storybook/icons@1.6.0': + resolution: {integrity: sha512-hcFZIjW8yQz8O8//2WTIXylm5Xsgc+lW9ISLgUk1xGmptIJQRdlhVIXCpSyLrQaaRiyhQRaVg7l3BD9S216BHw==} + engines: {node: '>=14.0.0'} + 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/instrumenter@8.6.14': + resolution: {integrity: sha512-iG4MlWCcz1L7Yu8AwgsnfVAmMbvyRSk700Mfy2g4c8y5O+Cv1ejshE1LBBsCwHgkuqU0H4R0qu4g23+6UnUemQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/instrumenter@8.6.15': + resolution: {integrity: sha512-TvHR/+yyIAOp/1bLulFai2kkhIBtAlBw7J6Jd9DKyInoGhTWNE1G1Y61jD5GWXX29AlwaHfzGUaX5NL1K+FJpg==} + peerDependencies: + storybook: ^8.6.15 + + '@storybook/instrumenter@8.6.18': + resolution: {integrity: sha512-viEC1BGlYyjAzi1Tv3LZjByh7Y3Oh04u6QKsujxdeUbr5rUOH4pa/wCKmxXmY6yWrD4WjcNtojmUvQZN/66FXQ==} + peerDependencies: + storybook: ^8.6.18 + + '@storybook/manager-api@8.6.18': + resolution: {integrity: sha512-BjIp12gEMgzFkEsgKpDIbZdnSWTZpm2dlws8WiPJCpgJtG+HWSxZ0/Ms30Au9yfwzQEKRSbV/5zpsKMGc2SIJw==} + 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.18': + resolution: {integrity: sha512-joXRXh3GdVvzhbfIgmix1xs90p8Q/nja7AhEAC2egn5Pl7SKsIYZUCYI6UdrQANb2myg9P552LKXfPect8llKg==} + peerDependencies: + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + + '@storybook/react-dom-shim@8.6.14': + resolution: {integrity: sha512-0hixr3dOy3f3M+HBofp3jtMQMS+sqzjKNgl7Arfuj3fvjmyXOks/yGjDImySR4imPtEllvPZfhiQNlejheaInw==} + 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.14 + + '@storybook/react-dom-shim@8.6.18': + resolution: {integrity: sha512-N4xULcAWZQTUv4jy1/d346Tyb4gufuC3UaLCuU/iVSZ1brYF4OW3ANr+096btbMxY8pR/65lmtoqr5CTGwnBvA==} + 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.18 + + '@storybook/react-vite@8.6.18': + resolution: {integrity: sha512-qpSYyH2IizlEsI95MJTdIL6xpLSgiNCMoJpHu+IEqLnyvmecRR/YEZvcHalgdtawuXlimH0bAYuwIu3l8Vo6FQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@storybook/test': 8.6.18 + 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.18 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + '@storybook/test': + optional: true + + '@storybook/react@8.6.18': + resolution: {integrity: sha512-BuLpzMkKtF+UCQCbi+lYVX9cdcAMG86Lu2dDn7UFkPi5HRNFq/zHPSvlz1XDgL0OYMtcqB1aoVzFzcyzUBhhjw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@storybook/test': 8.6.18 + 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.18 + typescript: '>= 4.2.x' + peerDependenciesMeta: + '@storybook/test': + optional: true + typescript: + optional: true + + '@storybook/test@8.6.14': + resolution: {integrity: sha512-GkPNBbbZmz+XRdrhMtkxPotCLOQ1BaGNp/gFZYdGDk2KmUWBKmvc5JxxOhtoXM2703IzNFlQHSSNnhrDZYuLlw==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/test@8.6.15': + resolution: {integrity: sha512-EwquDRUDVvWcZds3T2abmB5wSN/Vattal4YtZ6fpBlIUqONV4o/cOBX39cFfQSUCBrIXIjQ6RmapQCHK/PvBYw==} + peerDependencies: + storybook: ^8.6.15 + + '@storybook/test@8.6.18': + resolution: {integrity: sha512-u/RwfWMyHcH0N2hqfMTw2CoZ58IXdeED3b8NmcHc8bmERB3byI5vVAkwYbcD7+WeRHIiym38ZHi0SRn+IpkO3Q==} + peerDependencies: + storybook: ^8.6.18 + + '@storybook/theming@8.6.18': + resolution: {integrity: sha512-n6OEjEtHupa2PdTwWzRepr7cO8NkDd4rgF6BKLitRbujOspLxzMBEqdphs+QLcuiCIgf33SqmEA64QWnbSMhPw==} + 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'} + + '@testing-library/jest-dom@6.5.0': + 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.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + 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' + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} + + '@types/doctrine@0.0.9': + resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + + '@types/node@24.12.2': + resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + + '@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.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + + '@types/resolve@1.20.6': + resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} + + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + + '@vitejs/plugin-react@6.0.1': + resolution: {integrity: sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + + '@vitest/expect@2.0.5': + resolution: {integrity: sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==} + + '@vitest/expect@2.1.9': + resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + + '@vitest/mocker@2.1.9': + resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.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/runner@2.1.9': + resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} + + '@vitest/snapshot@2.1.9': + resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} + + '@vitest/spy@2.0.5': + resolution: {integrity: sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==} + + '@vitest/spy@2.1.9': + resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + + '@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==} + + '@yarnpkg/lockfile@1.1.0': + resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + + '@zip.js/zip.js@2.8.26': + resolution: {integrity: sha512-RQ4h9F6DOiHxpdocUDrOl6xBM+yOtz+LkUol47AVWcfebGBDpZ7w7Xvz9PS24JgXvLGiXXzSAfdCdVy1tPlaFA==} + engines: {bun: '>=0.7.0', deno: '>=1.0.0', node: '>=18.0.0'} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + astring@1.9.0: + resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} + hasBin: true + + astro-expressive-code@0.38.3: + resolution: {integrity: sha512-Tvdc7RV0G92BbtyEOsfJtXU35w41CkM94fOAzxbQP67Wj5jArfserJ321FO4XA7WG9QMV0GIBmQq77NBIRDzpQ==} + peerDependencies: + astro: ^4.0.0-beta || ^5.0.0-beta || ^3.3.0 + + astro@5.18.1: + resolution: {integrity: sha512-m4VWilWZ+Xt6NPoYzC4CgGZim/zQUO7WFL0RHCH0AiEavF1153iC3+me2atDvXpf/yX4PyGUeD8wZLq1cirT3g==} + engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + autoprefixer@10.5.0: + resolution: {integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.11.4: + resolution: {integrity: sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==} + engines: {node: '>=4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.10.27: + resolution: {integrity: sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==} + engines: {node: '>=6.0.0'} + hasBin: true + + bcp-47-match@2.0.3: + resolution: {integrity: sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==} + + bcp-47@2.1.0: + resolution: {integrity: sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==} + + better-opn@3.0.2: + resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} + engines: {node: '>=12.0.0'} + + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + + brace-expansion@2.1.0: + resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-assert@1.2.1: + resolution: {integrity: sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==} + + browserslist@4.28.2: + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + + bytes-iec@3.1.1: + resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==} + engines: {node: '>= 0.8'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + caniuse-api@3.0.0: + resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + + caniuse-lite@1.0.30001791: + resolution: {integrity: sha512-yk0l/YSrOnFZk3UROpDLQD9+kC1l4meK/wed583AXrzoarMGJcbRi2Q4RaUYbKxYAsZ8sWmaSa/DsLmdBeI1vQ==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chokidar@5.0.0: + resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} + engines: {node: '>= 20.19.0'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + collapse-white-space@2.1.0: + resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + + component-emitter@2.0.0: + resolution: {integrity: sha512-4m5s3Me2xxlVKG9PkZpQqHQR7bgpnN7joDMJ4yvVkVXngjoITG76IaZmzmywSeRTeTpc6N6r3H3+KyUurV8OYw==} + engines: {node: '>=18'} + + confbox@0.1.8: + resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} + + consola@3.4.2: + resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} + engines: {node: ^14.18.0 || >=16.10.0} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-es@1.2.3: + resolution: {integrity: sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crossws@0.3.5: + resolution: {integrity: sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==} + + css-declaration-sorter@7.4.0: + resolution: {integrity: sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss: ^8.0.9 + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-selector-parser@3.3.0: + resolution: {integrity: sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + 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'} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssnano-preset-default@7.0.16: + resolution: {integrity: sha512-W0hiFi/ca/u2OTptL11OdApaz1vh9jyfd2ku9dMjou6KdpdgbMTagaXHKNl5kaEyRSCu9GIIaPRp5YLdqRAZMw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + cssnano-utils@5.0.3: + resolution: {integrity: sha512-ynIREMICLxkxm7e9bCR9sh75s4Q5drICi0ua1yxo5jH2XPBqSKkl4dOh4EbFqtUmnTMhRffHgYL0EKKkMjtJTg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + cssnano@7.1.8: + resolution: {integrity: sha512-OGXtXqXmwEoIGfXM2QoD35vweUAtx+J8ZvLSZHOEV0Jv9Hs9ScTdGGjRzZXun5J4PEZhEoytKig2O2NR8NXxKw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + defu@6.1.7: + resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dependency-graph@1.0.0: + resolution: {integrity: sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==} + engines: {node: '>=4'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destr@2.0.5: + resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} + + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + + deterministic-object-hash@2.0.2: + resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} + engines: {node: '>=18'} + + devalue@5.8.0: + resolution: {integrity: sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@8.0.4: + resolution: {integrity: sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + direction@2.0.1: + resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} + hasBin: true + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.349: + resolution: {integrity: sha512-QsWVGyRuY07Aqb234QytTfwd5d9AJlfNIQ5wIOl1L+PZDzI9d9+Fn0FRale/QYlFxt/bUnB0/nLd1jFPGxGK1A==} + + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + + emoji-regex@10.6.0: + resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + 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'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esast-util-from-estree@2.0.0: + resolution: {integrity: sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==} + + esast-util-from-js@2.0.1: + resolution: {integrity: sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==} + + esbuild-register@3.6.0: + resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} + peerDependencies: + esbuild: '>=0.12 <1' + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estree-util-attach-comments@3.0.0: + resolution: {integrity: sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==} + + estree-util-build-jsx@3.0.1: + resolution: {integrity: sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==} + + estree-util-is-identifier-name@3.0.0: + resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} + + estree-util-scope@1.0.0: + resolution: {integrity: sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==} + + estree-util-to-js@2.0.0: + resolution: {integrity: sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==} + + estree-util-visit@2.0.0: + resolution: {integrity: sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + expressive-code@0.38.3: + resolution: {integrity: sha512-COM04AiUotHCKJgWdn7NtW2lqu8OW8owAidMpkXt1qxrZ9Q2iC7+tok/1qIn2ocGnczvr9paIySgGnEwFeEQ8Q==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + 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 + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + find-yarn-workspace-root@2.0.0: + resolution: {integrity: sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==} + + fix-dts-default-cjs-exports@1.0.1: + resolution: {integrity: sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg==} + + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + fontace@0.4.1: + resolution: {integrity: sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==} + + fontkitten@1.0.3: + resolution: {integrity: sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==} + engines: {node: '>=20'} + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@11.3.4: + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.5.0: + resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + engines: {node: '>=18'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-to-regex.js@1.2.0: + resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + h3@1.15.11: + resolution: {integrity: sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.3: + resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} + engines: {node: '>= 0.4'} + + hast-util-embedded@3.0.0: + resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} + + hast-util-format@1.1.0: + resolution: {integrity: sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.3: + resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} + + hast-util-has-property@3.0.0: + resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==} + + hast-util-is-body-ok-link@3.0.1: + resolution: {integrity: sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-minify-whitespace@1.0.1: + resolution: {integrity: sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-phrasing@3.0.1: + resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} + + hast-util-raw@9.1.0: + resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} + + hast-util-select@6.0.4: + resolution: {integrity: sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==} + + hast-util-to-estree@3.1.3: + resolution: {integrity: sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==} + + hast-util-to-html@9.0.5: + resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} + + hast-util-to-jsx-runtime@2.3.6: + resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} + + hast-util-to-parse5@8.0.1: + resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==} + + hast-util-to-string@3.0.1: + resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hastscript@9.0.1: + resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} + + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + html-whitespace-sensitive-tag-names@3.0.1: + resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + 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 + + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + i18next@23.16.8: + resolution: {integrity: sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + inline-style-parser@0.2.7: + resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} + + iron-webcrypto@1.2.1: + resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + + is-arrayish@0.3.4: + resolution: {integrity: sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + 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'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsdoc-type-pratt-parser@4.8.0: + resolution: {integrity: sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==} + engines: {node: '>=12.0.0'} + + jsdom@25.0.1: + resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-stable-stringify@1.3.0: + resolution: {integrity: sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==} + engines: {node: '>= 0.4'} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.2.1: + resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==} + + jsonify@0.0.1: + resolution: {integrity: sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==} + + klaw-sync@6.0.0: + resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.18.1: + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.3.5: + resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + + map-or-similar@1.5.0: + resolution: {integrity: sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==} + + markdown-extensions@2.0.0: + resolution: {integrity: sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==} + engines: {node: '>=16'} + + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdast-util-definitions@6.0.0: + resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + + mdast-util-directive@3.1.0: + resolution: {integrity: sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==} + + mdast-util-find-and-replace@3.0.2: + resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} + + mdast-util-from-markdown@2.0.3: + resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.1.0: + resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.1.0: + resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} + + mdast-util-mdx-expression@2.0.1: + resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} + + mdast-util-mdx-jsx@3.2.0: + resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} + + mdast-util-mdx@3.0.0: + resolution: {integrity: sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==} + + mdast-util-mdxjs-esm@2.0.1: + resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + + memfs@4.57.2: + resolution: {integrity: sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==} + peerDependencies: + tslib: '2' + + memoizerific@1.11.3: + resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromark-core-commonmark@2.0.3: + resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} + + micromark-extension-directive@3.0.2: + resolution: {integrity: sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.1: + resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-extension-mdx-expression@3.0.1: + resolution: {integrity: sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==} + + micromark-extension-mdx-jsx@3.0.2: + resolution: {integrity: sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==} + + micromark-extension-mdx-md@2.0.0: + resolution: {integrity: sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==} + + micromark-extension-mdxjs-esm@3.0.0: + resolution: {integrity: sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==} + + micromark-extension-mdxjs@3.0.0: + resolution: {integrity: sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-mdx-expression@2.0.3: + resolution: {integrity: sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-events-to-acorn@2.0.3: + resolution: {integrity: sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.1.0: + resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.2: + resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} + + micromark@4.0.2: + resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} + + mri@1.2.0: + 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==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + nanoid@5.1.11: + resolution: {integrity: sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==} + engines: {node: ^18 || >=20} + hasBin: true + + nanospinner@1.2.2: + resolution: {integrity: sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==} + + neotraverse@0.6.18: + resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + engines: {node: '>= 10'} + + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + + node-fetch-native@1.6.7: + resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} + + node-mock-http@1.0.4: + resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + + node-releases@2.0.38: + resolution: {integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nwsapi@2.2.23: + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + ofetch@1.5.1: + resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} + + ohash@2.0.11: + resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} + + oniguruma-parser@0.12.2: + resolution: {integrity: sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==} + + oniguruma-to-es@2.3.0: + resolution: {integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==} + + oniguruma-to-es@4.3.6: + resolution: {integrity: sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==} + + open@7.4.2: + resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} + engines: {node: '>=8'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@6.2.0: + resolution: {integrity: sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==} + engines: {node: '>=18'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-queue@8.1.1: + resolution: {integrity: sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==} + engines: {node: '>=18'} + + p-timeout@6.1.4: + resolution: {integrity: sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==} + engines: {node: '>=14.16'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + package-manager-detector@0.2.11: + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} + + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} + + pagefind@1.5.2: + resolution: {integrity: sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q==} + hasBin: true + + parse-entities@4.0.2: + resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} + + parse-latin@7.0.0: + resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + patch-package@8.0.1: + resolution: {integrity: sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==} + engines: {node: '>=14', npm: '>5'} + hasBin: true + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + path-unified@0.2.0: + resolution: {integrity: sha512-MNKqvrKbbbb5p7XHXV6ZAsf/1f/yJQa13S/fcX0uua8ew58Tgc6jXV+16JyAbnR/clgCH+euKDxrF2STxMHdrg==} + + path@0.12.7: + resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + + piccolore@0.1.3: + resolution: {integrity: sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-types@1.3.1: + resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} + + polished@4.3.1: + resolution: {integrity: sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==} + engines: {node: '>=10'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-calc@10.1.1: + resolution: {integrity: sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==} + engines: {node: ^18.12 || ^20.9 || >=22.0} + peerDependencies: + postcss: ^8.4.38 + + postcss-cli@11.0.1: + resolution: {integrity: sha512-0UnkNPSayHKRe/tc2YGW6XnSqqOA9eqpiRMgRlV1S6HdGi16vwJBx7lviARzbV1HpQHqLLRH3o8vTcB0cLc+5g==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + postcss: ^8.0.0 + + postcss-colormin@7.0.10: + resolution: {integrity: sha512-yFr6JezOolHLta/buLE71VKPh2mXursp4saVe98/ol8ZnEWhL+racShqPKlvd/DKWLre/39B6HhcMXf7RZ3hxg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-convert-values@7.0.12: + resolution: {integrity: sha512-xurKu5qqk4viR3Cp3p4xBR4KfnZm4w4ys6+UBwBmeuBSNkH7+DtLnYOYnOffgtE4yx8sH9S1VZ6RAAvROXzP2Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-discard-comments@7.0.8: + resolution: {integrity: sha512-CvvS5S9WrXblFXCEJ9nVo+4z+eA7zSC7Z88V1HEJuwlQhlFnYTIjg1xJY+BCUiG2bvICap2tXii4mP22BD108Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-discard-duplicates@7.0.4: + resolution: {integrity: sha512-VBNn1+EuMZkeGVVtz0gRfbNGtx9IFgAsAV+E2pHtXPrp4qfGBkhTIiAuE/wrb+Y6Pakg9NewAlfTpYIFAWODtw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-discard-empty@7.0.3: + resolution: {integrity: sha512-M2pyjQCU+/7cMHVtL6bKTHjv0lZnPLMpicgr67Dlth7AbuV9gjVTtUqaRwn6Pp6BwSDspUzhz8SaUrRykJU5Dw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-discard-overridden@7.0.3: + resolution: {integrity: sha512-aNovXo9UsZuRNLzHJtp13lHIvinDPfiXBPePpXkSjCbgp++iU2FqE+YxvjIsg6EdyPZsASFbfu+JcBFVsErXIQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-import@16.1.1: + resolution: {integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-load-config@5.1.0: + resolution: {integrity: sha512-G5AJ+IX0aD0dygOE0yFZQ/huFFMSNneyfp0e3/bT05a8OfPC5FUoZRPfGijUdGOJNMewJiwzcHJXFafFzeKFVA==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + + postcss-merge-longhand@7.0.7: + resolution: {integrity: sha512-b3mfYUxR388u5Pt0HPcVIUtUDn/k15UfTY9M+ORW+meCR6JLNxoZffiYvXyOYQoRYQNZyX/UFkMCM/mNHxe1qA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-merge-rules@7.0.11: + resolution: {integrity: sha512-SJUPM18g2BmPhf8BVlbwqWz4aK3pLu6u6xjfwEzra7xL6IBR10sUaiB++EzqcVfadPHrKBSMlNdP+XieykhI+Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-minify-font-values@7.0.3: + resolution: {integrity: sha512-yilG/VOaNI74IylQvAQQxm3/wZVBkXyYUqNUAdxqwtbWUXPsbK1q8Ms0mL83v+f8YicgcyfYCRZtWACUdYajpA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-minify-gradients@7.0.5: + resolution: {integrity: sha512-YraROyQRg3BI1+Hg8E05B/JPdnTm8EDSVu4P2BxdM+CRiOyfmou809+chGIqo6fQqwjPGQ947nbGncSjmTU1WQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-minify-params@7.0.9: + resolution: {integrity: sha512-R8itbB8BhlpoYyBm1ou0dD+vJnQ3F6adQipR4UnkCHUwlo+S9WXJaDRg1RHjC8YVAtIdrQzSWvJl40HnGDTKjA==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-minify-selectors@7.1.1: + resolution: {integrity: sha512-MZWXwSTfcpmNVJIs7tddar/275a4/zT5nG9/gEndHPRZGTAQNpiSkk8s/dq+yZVX2jKfvVn1d5X8Z5SJHWnDoQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-normalize-charset@7.0.3: + resolution: {integrity: sha512-NoBfZu8PR4c2NlmjvrqQTzCzLY79hwcSRgNQ3ZiNK0ABzf9kYKloE/jNj+/8GQY1wsm8pRRgANk6ydLH8cwo0Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-display-values@7.0.3: + resolution: {integrity: sha512-ldsCX0QIt05pKIOobZtVQ48wXJecr+czw4+e1/YjVhLMqslShgpVxgPtI2CefURR8oyVoYaU/l829MMwExDMLw==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-positions@7.0.4: + resolution: {integrity: sha512-VEvlpeGd3Ju1Hqa/oN4jaP3+ms4laYwkEL9N9u+B6k54PZjXbW1n6wI+aVprf1BQXlCYpS5+1pl/7/vHiKgARg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-repeat-style@7.0.4: + resolution: {integrity: sha512-6mPKlY/8cSaDHxX502wERADarJsccwlky6yIrOapHH2ZgfoKAV94SbiTKfKEs4EEpdazuc3J72WsqeYk7hp9+Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-string@7.0.3: + resolution: {integrity: sha512-HnEQPUchi1eznmDKEYrKUTqrprEq97SrpUYClgUkv7V2zRODD9DFoUsYU+m9ZOetmD5ku7fEMZB/lwy8IT6xVQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-timing-functions@7.0.3: + resolution: {integrity: sha512-zmEzHdvpZBZu0OKlbJSfgASQvaayyAoVuWtvyr34IJ/LyS+DaOKvvR3EvFJ9RWWtNIx+CMvO125OVophaxNYew==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-unicode@7.0.9: + resolution: {integrity: sha512-DRAdWfeh/TjmhLJsw91vdiWCnUod9iwvM7xyS02/nF/sLsCR3A8l3pztrSUrWG8DSBqfX7yEk9FM0USaVJ2mSg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-url@7.0.3: + resolution: {integrity: sha512-CL93wmloq5qsffmFv+bw24MIRbmhHrp53qoh1LDAb/5TtjWEXI/np4xcP/Gw9oWCb2XyWnqHYLDUwiKRoJBA1Q==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-normalize-whitespace@7.0.3: + resolution: {integrity: sha512-FdHjjn+Ht5Z2ZRjNOmeCbNq6lq09sUYKpmlF/Aq0XjVNSLTL6fmHlA/3swN2wP2caY9GV/tjSDcIIyS7aN7W0A==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-ordered-values@7.0.4: + resolution: {integrity: sha512-nubSi49hDHQk4E8KIj+IbLY8Bg+8OcSUEhgyolgM+atnOvXjV7EjaR6bac4YGZoFyPa9mWoAF3EaYbWdFkKqVg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-reduce-initial@7.0.9: + resolution: {integrity: sha512-ztTNPdIxXTxtBcG03E9u8v44M4ElXbMIRT7pf2onlquGula0Y83nKKxqM22FA/hMgkfCjN7ohevkVlaNwI8iOQ==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-reduce-transforms@7.0.3: + resolution: {integrity: sha512-FXsnN9ZwcZTT8Yf8cAHA8qIGUXcX6WfLd9JoYhrdDfmvsVhhfqkkv7m4AC3rwFOfz+GzkUa87OCKF9dUcicd+g==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-reporter@7.1.0: + resolution: {integrity: sha512-/eoEylGWyy6/DOiMP5lmFRdmDKThqgn7D6hP2dXKJI/0rJSO1ADFNngZfDzxL0YAxFvws+Rtpuji1YIHj4mySA==} + engines: {node: '>=10'} + peerDependencies: + postcss: ^8.1.0 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-selector-parser@7.1.1: + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} + engines: {node: '>=4'} + + postcss-svgo@7.1.3: + resolution: {integrity: sha512-2QfoFOYMcj8lwcVEf9WeTlkVIAm7u2QvOEhMzkQU3KUhhGX/l8hVV9EtjMv4iq3E9iI3OeeMN0YoMLbGusuigw==} + engines: {node: ^18.12.0 || ^20.9.0 || >= 18} + peerDependencies: + postcss: ^8.5.13 + + postcss-unique-selectors@7.0.7: + resolution: {integrity: sha512-d+sCkaRnSefghOUdH8CMJZV9yUQhj2ojpe8Nw/lA+LV1UOfeleGkLTl6XdCFFSai9UJ+DJPb69FFuqthXYsY8w==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.13: + resolution: {integrity: sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==} + engines: {node: ^10 || ^12 || >=14} + + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + prettier@3.8.3: + resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + pretty-hrtime@1.0.3: + resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} + engines: {node: '>= 0.8'} + + prismjs@1.30.0: + resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} + engines: {node: '>=6'} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + property-information@7.1.0: + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} + + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.15.1: + resolution: {integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==} + engines: {node: '>=0.6'} + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + radix3@1.1.2: + resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} + + react-docgen-typescript@2.4.0: + resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==} + peerDependencies: + typescript: '>= 4.3.x' + + react-docgen@7.1.1: + resolution: {integrity: sha512-hlSJDQ2synMPKFZOsKo9Hi8WWZTC7POR8EmWvTSjow+VDgKzkmjQvFm2fk0tmRw+f0vTOIYKlarR0iL4996pdg==} + engines: {node: '>=16.14.0'} + + react-dom@19.2.5: + resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==} + peerDependencies: + react: ^19.2.5 + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.7.2: + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@19.2.5: + resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} + engines: {node: '>=0.10.0'} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + readdirp@5.0.0: + resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + engines: {node: '>= 20.19.0'} + + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + + recma-build-jsx@1.0.0: + resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==} + + recma-jsx@1.0.1: + resolution: {integrity: sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + recma-parse@1.0.0: + resolution: {integrity: sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==} + + recma-stringify@1.0.0: + resolution: {integrity: sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + regex-recursion@5.1.1: + resolution: {integrity: sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==} + + regex-recursion@6.0.2: + resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@5.1.1: + resolution: {integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==} + + regex@6.1.0: + resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} + + rehype-expressive-code@0.38.3: + resolution: {integrity: sha512-RYSSDkMBikoTbycZPkcWp6ELneANT4eTpND1DSRJ6nI2eVFUwTBDCvE2vO6jOOTaavwnPiydi4i/87NRyjpdOA==} + + rehype-format@5.0.1: + resolution: {integrity: sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==} + + rehype-parse@9.0.1: + resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==} + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + rehype-recma@1.0.0: + resolution: {integrity: sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==} + + rehype-stringify@10.0.1: + resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} + + rehype@13.0.2: + resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} + + remark-directive@3.0.1: + resolution: {integrity: sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==} + + remark-gfm@4.0.1: + resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} + + remark-mdx@3.1.1: + resolution: {integrity: sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.2: + resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} + + remark-smartypants@3.0.2: + resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==} + engines: {node: '>=16.0.0'} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + remixicon@4.9.1: + resolution: {integrity: sha512-36gLSoujkabnCFZFDyP17VNh9piuBA/rsXUb4auSJWLGsHVXtmxLj/EM5FjaEAGnk8oIAj1Azob/DZ2N+90lAQ==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve@1.22.12: + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} + hasBin: true + + retext-latin@4.0.0: + resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} + + retext-smartypants@6.2.0: + resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==} + + retext-stringify@4.0.0: + resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} + + retext@9.0.0: + resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rolldown@1.0.0-rc.17: + resolution: {integrity: sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.60.2: + resolution: {integrity: sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + + 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==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + sharp@0.34.5: + resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@1.29.2: + resolution: {integrity: sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==} + + shiki@3.23.0: + resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-swizzle@0.2.4: + resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + sitemap@9.0.1: + resolution: {integrity: sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==} + engines: {node: '>=20.19.5', npm: '>=10.8.2'} + hasBin: true + + size-limit@11.2.0: + resolution: {integrity: sha512-2kpQq2DD/pRpx3Tal/qRW1SYwcIeQ0iq8li5CJHQgOC+FtPn2BVmuDtzUCgNnpCrbgtfEHqh+iWzxK+Tq6C+RQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + slash@2.0.0: + resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} + engines: {node: '>=6'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + + smol-toml@1.6.1: + resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} + engines: {node: '>= 18'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + 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@8.6.18: + resolution: {integrity: sha512-p8seiSI6FiVY6P3V0pG+5v7c8pDMehMAFRWEhG5XqIBSQszzOjDnW2rNvm3odoLKfo3V3P6Cs6Hv9ILzymULyQ==} + hasBin: true + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + + stream-replace-string@2.0.0: + resolution: {integrity: sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==} + + stream@0.0.3: + resolution: {integrity: sha512-aMsbn7VKrl4A2T7QAQQbzgN7NVc70vgF5INQrBXqn4dCXN1zy3L9HGgLO5s7PExmdrzTJ8uR/27aviW8or8/+A==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-indent@4.1.1: + resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} + engines: {node: '>=12'} + + style-dictionary@4.4.0: + resolution: {integrity: sha512-+xU0IA1StzqAqFs/QtXkK+XJa7wpS4X5H+JQccRKsRCElgeLGocFU1U/UMvMUylKFw6vwGV+Y/a2wb2pm5rFFQ==} + engines: {node: '>=18.0.0'} + hasBin: true + + style-to-js@1.1.21: + resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} + + style-to-object@1.0.14: + resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} + + stylehacks@7.0.11: + resolution: {integrity: sha512-iODNfhXVLqc5LADs+Y6Oh5wJuK5ZcHbVng8aiK3y9pjMQdc5hLrBW0eFU6FtnpNrE6PoEg/MmFTU4waotj5WNg==} + engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} + peerDependencies: + postcss: ^8.5.13 + + sucrase@3.35.1: + resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svgo@4.0.1: + resolution: {integrity: sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==} + engines: {node: '>=16'} + hasBin: true + + 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'} + + thenby@1.4.1: + resolution: {integrity: sha512-D5a/bO0KdalOE3q8MlrRmSxjbKZHT3MQmXkJP+r97Vw8MMwOZKOwUSEyTtK7eSMj2y0kyAjpYMRMZmmLw1FtNQ==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + thingies@2.6.0: + resolution: {integrity: sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + + tiny-inflate@1.0.3: + resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyexec@1.1.2: + resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} + engines: {node: '>=18'} + + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} + + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + tree-dump@1.1.0: + resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tsconfck@3.1.6: + resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsup@8.5.1: + resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typescript@5.7.3: + resolution: {integrity: sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} + + ultrahtml@1.6.0: + resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==} + + uncrypto@0.1.3: + resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unifont@0.7.4: + resolution: {integrity: sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-is@6.0.1: + resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} + + unist-util-modify-children@4.0.0: + resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} + + unist-util-position-from-estree@2.0.0: + resolution: {integrity: sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-children@3.0.0: + resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} + + unist-util-visit-parents@6.0.2: + resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} + + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + + unstorage@1.17.5: + resolution: {integrity: sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==} + peerDependencies: + '@azure/app-configuration': ^1.8.0 + '@azure/cosmos': ^4.2.0 + '@azure/data-tables': ^13.3.0 + '@azure/identity': ^4.6.0 + '@azure/keyvault-secrets': ^4.9.0 + '@azure/storage-blob': ^12.26.0 + '@capacitor/preferences': ^6 || ^7 || ^8 + '@deno/kv': '>=0.9.0' + '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0 + '@planetscale/database': ^1.19.0 + '@upstash/redis': ^1.34.3 + '@vercel/blob': '>=0.27.1' + '@vercel/functions': ^2.2.12 || ^3.0.0 + '@vercel/kv': ^1 || ^2 || ^3 + aws4fetch: ^1.0.20 + db0: '>=0.2.1' + idb-keyval: ^6.2.1 + ioredis: ^5.4.2 + uploadthing: ^7.4.4 + peerDependenciesMeta: + '@azure/app-configuration': + optional: true + '@azure/cosmos': + optional: true + '@azure/data-tables': + optional: true + '@azure/identity': + optional: true + '@azure/keyvault-secrets': + optional: true + '@azure/storage-blob': + optional: true + '@capacitor/preferences': + optional: true + '@deno/kv': + optional: true + '@netlify/blobs': + optional: true + '@planetscale/database': + optional: true + '@upstash/redis': + optional: true + '@vercel/blob': + optional: true + '@vercel/functions': + optional: true + '@vercel/kv': + optional: true + aws4fetch: + optional: true + db0: + optional: true + idb-keyval: + optional: true + ioredis: + optional: true + uploadthing: + optional: true + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). + hasBin: true + + vfile-location@5.0.3: + resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} + + vfile-message@4.0.3: + resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite-node@2.1.9: + resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vite@6.4.2: + resolution: {integrity: sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + 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 + + vite@8.0.10: + resolution: {integrity: sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.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 + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.1.3: + resolution: {integrity: sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + vite: + optional: true + + vitest-axe@0.1.0: + resolution: {integrity: sha512-jvtXxeQPg8R/2ANTY8QicA5pvvdRP4F0FsVUAHANJ46YCDASie/cuhlSzu0DGcLmZvGBSBNsNuK3HqfaeknyvA==} + peerDependencies: + vitest: '>=0.16.0' + + vitest@2.1.9: + resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.9 + '@vitest/ui': 2.1.9 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + 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'} + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + + which-typed-array@1.1.20: + resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.2: + resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} + engines: {node: '>=18'} + + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + 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==} + + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@2.8.4: + resolution: {integrity: sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.2.2: + resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==} + engines: {node: '>=12.20'} + + yocto-spinner@0.2.3: + resolution: {integrity: sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==} + engines: {node: '>=18.19'} + + yoctocolors@2.1.2: + resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} + engines: {node: '>=18'} + + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + + zod-to-ts@1.2.0: + resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==} + peerDependencies: + typescript: ^4.9.4 || ^5.0.2 + zod: ^3 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@adobe/css-tools@4.4.4': {} + + '@asamuzakjp/css-color@3.2.0': + 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: 10.4.3 + + '@astrojs/compiler@2.13.1': {} + + '@astrojs/internal-helpers@0.7.6': {} + + '@astrojs/markdown-remark@6.3.11': + dependencies: + '@astrojs/internal-helpers': 0.7.6 + '@astrojs/prism': 3.3.0 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + import-meta-resolve: 4.2.0 + js-yaml: 4.1.1 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + remark-smartypants: 3.0.2 + shiki: 3.23.0 + smol-toml: 1.6.1 + unified: 11.0.5 + unist-util-remove-position: 5.0.0 + unist-util-visit: 5.1.0 + unist-util-visit-parents: 6.0.2 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/mdx@4.3.14(astro@5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4))': + dependencies: + '@astrojs/markdown-remark': 6.3.11 + '@mdx-js/mdx': 3.1.1 + acorn: 8.16.0 + astro: 5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4) + es-module-lexer: 1.7.0 + estree-util-visit: 2.0.0 + hast-util-to-html: 9.0.5 + piccolore: 0.1.3 + rehype-raw: 7.0.0 + remark-gfm: 4.0.1 + remark-smartypants: 3.0.2 + source-map: 0.7.6 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/prism@3.3.0': + dependencies: + prismjs: 1.30.0 + + '@astrojs/sitemap@3.7.2': + dependencies: + sitemap: 9.0.1 + stream-replace-string: 2.0.0 + zod: 4.4.3 + + '@astrojs/starlight@0.30.6(astro@5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4))': + dependencies: + '@astrojs/mdx': 4.3.14(astro@5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4)) + '@astrojs/sitemap': 3.7.2 + '@pagefind/default-ui': 1.5.2 + '@types/hast': 3.0.4 + '@types/js-yaml': 4.0.9 + '@types/mdast': 4.0.4 + astro: 5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4) + astro-expressive-code: 0.38.3(astro@5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4)) + bcp-47: 2.1.0 + hast-util-from-html: 2.0.3 + hast-util-select: 6.0.4 + hast-util-to-string: 3.0.1 + hastscript: 9.0.1 + i18next: 23.16.8 + js-yaml: 4.1.1 + mdast-util-directive: 3.1.0 + mdast-util-to-markdown: 2.1.2 + mdast-util-to-string: 4.0.0 + pagefind: 1.5.2 + rehype: 13.0.2 + rehype-format: 5.0.1 + remark-directive: 3.0.1 + unified: 11.0.5 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/telemetry@3.3.0': + dependencies: + ci-info: 4.4.0 + debug: 4.4.3 + dlv: 1.1.3 + dset: 3.1.4 + is-docker: 3.0.0 + is-wsl: 3.1.1 + which-pm-runs: 1.1.0 + transitivePeerDependencies: + - supports-color + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.3': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.3 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.3 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.28.6': {} + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.29.2': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + + '@babel/parser@7.29.3': + dependencies: + '@babel/types': 7.29.0 + + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/runtime@7.29.2': {} + + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 + + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.3 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bundled-es-modules/deepmerge@4.3.1': + dependencies: + deepmerge: 4.3.1 + + '@bundled-es-modules/glob@10.4.2': + dependencies: + buffer: 6.0.3 + events: 3.3.0 + glob: 10.5.0 + patch-package: 8.0.1 + path: 0.12.7 + stream: 0.0.3 + string_decoder: 1.3.0 + url: 0.11.4 + + '@bundled-es-modules/memfs@4.17.0(tslib@2.8.1)': + dependencies: + assert: 2.1.0 + buffer: 6.0.3 + events: 3.3.0 + memfs: 4.57.2(tslib@2.8.1) + path: 0.12.7 + stream: 0.0.3 + util: 0.12.5 + transitivePeerDependencies: + - tslib + + '@capsizecss/unpack@4.0.0': + dependencies: + fontkitten: 1.0.3 + + '@changesets/apply-release-plan@7.1.1': + dependencies: + '@changesets/config': 3.1.4 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.4 + + '@changesets/assemble-release-plan@6.0.10': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.4 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/cli@2.31.0(@types/node@24.12.2)': + dependencies: + '@changesets/apply-release-plan': 7.1.1 + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.4 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/get-release-plan': 4.0.16 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@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.12.2) + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + enquirer: 2.4.1 + fs-extra: 7.0.1 + mri: 1.2.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.4 + spawndamnit: 3.0.1 + term-size: 2.2.1 + transitivePeerDependencies: + - '@types/node' + + '@changesets/config@3.1.4': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/logger': 0.1.1 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.4': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.4 + + '@changesets/get-release-plan@4.0.16': + dependencies: + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/config': 3.1.4 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.3': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 4.1.1 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.7': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.3 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.1.3 + prettier: 2.8.8 + + '@colordx/core@5.4.3': {} + + '@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-tokenizer@3.0.4': {} + + '@ctrl/tinycolor@4.2.0': {} + + '@emnapi/core@1.10.0': + dependencies: + '@emnapi/wasi-threads': 1.2.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/aix-ppc64@0.27.7': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.27.7': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-arm@0.27.7': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/android-x64@0.27.7': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.27.7': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.27.7': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.27.7': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.27.7': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.27.7': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.27.7': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.27.7': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.27.7': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.27.7': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.27.7': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.27.7': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.27.7': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/linux-x64@0.27.7': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.27.7': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.27.7': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.27.7': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.27.7': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.27.7': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.27.7': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.27.7': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.27.7': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@esbuild/win32-x64@0.27.7': + optional: true + + '@expressive-code/core@0.38.3': + dependencies: + '@ctrl/tinycolor': 4.2.0 + hast-util-select: 6.0.4 + hast-util-to-html: 9.0.5 + hast-util-to-text: 4.0.2 + hastscript: 9.0.1 + postcss: 8.5.13 + postcss-nested: 6.2.0(postcss@8.5.13) + unist-util-visit: 5.1.0 + unist-util-visit-parents: 6.0.2 + + '@expressive-code/plugin-frames@0.38.3': + dependencies: + '@expressive-code/core': 0.38.3 + + '@expressive-code/plugin-shiki@0.38.3': + dependencies: + '@expressive-code/core': 0.38.3 + shiki: 1.29.2 + + '@expressive-code/plugin-text-markers@0.38.3': + dependencies: + '@expressive-code/core': 0.38.3 + + '@floating-ui/core@1.7.5': + dependencies: + '@floating-ui/utils': 0.2.11 + + '@floating-ui/dom@1.7.6': + dependencies: + '@floating-ui/core': 1.7.5 + '@floating-ui/utils': 0.2.11 + + '@floating-ui/react-dom@2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@floating-ui/dom': 1.7.6 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + + '@floating-ui/react@0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@floating-ui/utils': 0.2.11 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + tabbable: 6.4.0 + + '@floating-ui/utils@0.2.11': {} + + '@img/colour@1.1.0': + optional: true + + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.2.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-arm@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.4 + optional: true + + '@img/sharp-linux-ppc64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.4 + optional: true + + '@img/sharp-linux-riscv64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.2.4 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-s390x@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.10.0 + optional: true + + '@img/sharp-wasm32@0.34.5': + dependencies: + '@emnapi/runtime': 1.10.0 + optional: true + + '@img/sharp-win32-arm64@0.34.5': + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-ia32@0.34.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.34.5': + optional: true + + '@inquirer/external-editor@1.0.3(@types/node@24.12.2)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 24.12.2 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.7.3)(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0))': + dependencies: + glob: 10.5.0 + magic-string: 0.27.0 + react-docgen-typescript: 2.4.0(typescript@5.7.3) + vite: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + optionalDependencies: + typescript: 5.7.3 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/base64@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-core@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-fsa@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-builtins@4.57.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-to-fsa@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-utils@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-print@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-snapshot@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.29.2 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.29.2 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@mdx-js/mdx@3.1.1': + dependencies: + '@types/estree': 1.0.8 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdx': 2.0.13 + acorn: 8.16.0 + collapse-white-space: 2.1.0 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-util-scope: 1.0.0 + estree-walker: 3.0.3 + hast-util-to-jsx-runtime: 2.3.6 + markdown-extensions: 2.0.0 + recma-build-jsx: 1.0.0 + recma-jsx: 1.0.1(acorn@8.16.0) + recma-stringify: 1.0.0 + rehype-recma: 1.0.0 + remark-mdx: 3.1.1 + remark-parse: 11.0.0 + remark-rehype: 11.1.2 + source-map: 0.7.6 + unified: 11.0.5 + unist-util-position-from-estree: 2.0.0 + unist-util-stringify-position: 4.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 19.2.14 + react: 19.2.5 + + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@oslojs/encoding@1.1.0': {} + + '@oxc-project/types@0.127.0': {} + + '@pagefind/darwin-arm64@1.5.2': + optional: true + + '@pagefind/darwin-x64@1.5.2': + optional: true + + '@pagefind/default-ui@1.5.2': {} + + '@pagefind/freebsd-x64@1.5.2': + optional: true + + '@pagefind/linux-arm64@1.5.2': + optional: true + + '@pagefind/linux-x64@1.5.2': + optional: true + + '@pagefind/windows-arm64@1.5.2': + optional: true + + '@pagefind/windows-x64@1.5.2': + optional: true + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@radix-ui/number@1.1.1': {} + + '@radix-ui/primitive@1.1.3': {} + + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.5)': + dependencies: + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-context@1.1.2(@types/react@19.2.14)(react@19.2.5)': + dependencies: + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + aria-hidden: 1.2.6 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.5)': + dependencies: + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-id@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + aria-hidden: 1.2.6 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + aria-hidden: 1.2.6 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/rect': 1.1.1 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@radix-ui/rect': 1.1.1 + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.5)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + '@types/react': 19.2.14 + + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@radix-ui/rect@1.1.1': {} + + '@rolldown/binding-android-arm64@1.0.0-rc.17': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-rc.17': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-rc.17': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.17': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.17': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.17': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.17': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.17': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.17': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.27': {} + + '@rolldown/pluginutils@1.0.0-rc.17': {} + + '@rolldown/pluginutils@1.0.0-rc.7': {} + + '@rollup/pluginutils@5.3.0(rollup@4.60.2)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.4 + optionalDependencies: + rollup: 4.60.2 + + '@rollup/rollup-android-arm-eabi@4.60.2': + optional: true + + '@rollup/rollup-android-arm64@4.60.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.2': + optional: true + + '@rollup/rollup-darwin-x64@4.60.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.60.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.60.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.60.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.60.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.60.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.60.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.60.2': + optional: true + + '@rollup/rollup-openbsd-x64@4.60.2': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.60.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.60.2': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.2': + optional: true + + '@shikijs/core@1.29.2': + dependencies: + '@shikijs/engine-javascript': 1.29.2 + '@shikijs/engine-oniguruma': 1.29.2 + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/core@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + + '@shikijs/engine-javascript@1.29.2': + dependencies: + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 2.3.0 + + '@shikijs/engine-javascript@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.6 + + '@shikijs/engine-oniguruma@1.29.2': + dependencies: + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/engine-oniguruma@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + + '@shikijs/langs@1.29.2': + dependencies: + '@shikijs/types': 1.29.2 + + '@shikijs/langs@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/themes@1.29.2': + dependencies: + '@shikijs/types': 1.29.2 + + '@shikijs/themes@3.23.0': + dependencies: + '@shikijs/types': 3.23.0 + + '@shikijs/types@1.29.2': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/types@3.23.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@10.0.2': {} + + '@size-limit/esbuild@11.2.0(size-limit@11.2.0)': + dependencies: + esbuild: 0.25.12 + nanoid: 5.1.11 + size-limit: 11.2.0 + + '@size-limit/file@11.2.0(size-limit@11.2.0)': + dependencies: + size-limit: 11.2.0 + + '@size-limit/preset-small-lib@11.2.0(size-limit@11.2.0)': + dependencies: + '@size-limit/esbuild': 11.2.0(size-limit@11.2.0) + '@size-limit/file': 11.2.0(size-limit@11.2.0) + size-limit: 11.2.0 + + '@storybook/addon-a11y@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/addon-highlight': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + '@storybook/global': 5.0.0 + '@storybook/test': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + axe-core: 4.11.4 + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/addon-actions@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@types/uuid': 9.0.8 + dequal: 2.0.3 + polished: 4.3.1 + storybook: 8.6.18(prettier@3.8.3) + uuid: 9.0.1 + + '@storybook/addon-backgrounds@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + memoizerific: 1.11.3 + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + + '@storybook/addon-controls@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + dequal: 2.0.3 + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + + '@storybook/addon-docs@8.6.14(@types/react@19.2.14)(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.14)(react@19.2.5) + '@storybook/blocks': 8.6.14(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3)) + '@storybook/csf-plugin': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/react-dom-shim': 8.6.14(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3)) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + + '@storybook/addon-essentials@8.6.14(@types/react@19.2.14)(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/addon-actions': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-backgrounds': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-controls': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-docs': 8.6.14(@types/react@19.2.14)(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-highlight': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-measure': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-outline': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-toolbars': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/addon-viewport': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + + '@storybook/addon-highlight@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/addon-highlight@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/addon-interactions@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@storybook/test': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + polished: 4.3.1 + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + + '@storybook/addon-measure@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.18(prettier@3.8.3) + tiny-invariant: 1.3.3 + + '@storybook/addon-outline@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + + '@storybook/addon-toolbars@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/addon-viewport@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + memoizerific: 1.11.3 + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/blocks@8.6.14(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/icons': 1.6.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + optionalDependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + + '@storybook/builder-vite@8.6.18(storybook@8.6.18(prettier@3.8.3))(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0))': + dependencies: + '@storybook/csf-plugin': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + browser-assert: 1.2.1 + storybook: 8.6.18(prettier@3.8.3) + ts-dedent: 2.2.0 + vite: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + + '@storybook/components@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/core@8.6.18(prettier@3.8.3)(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/theming': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + better-opn: 3.0.2 + browser-assert: 1.2.1 + esbuild: 0.25.12 + esbuild-register: 3.6.0(esbuild@0.25.12) + jsdoc-type-pratt-parser: 4.8.0 + process: 0.11.10 + recast: 0.23.11 + semver: 7.7.4 + util: 0.12.5 + ws: 8.20.0 + optionalDependencies: + prettier: 3.8.3 + transitivePeerDependencies: + - bufferutil + - storybook + - supports-color + - utf-8-validate + + '@storybook/csf-plugin@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + storybook: 8.6.18(prettier@3.8.3) + unplugin: 1.16.1 + + '@storybook/csf-plugin@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + storybook: 8.6.18(prettier@3.8.3) + unplugin: 1.16.1 + + '@storybook/global@5.0.0': {} + + '@storybook/icons@1.6.0(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + + '@storybook/instrumenter@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@vitest/utils': 2.1.9 + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/instrumenter@8.6.15(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@vitest/utils': 2.1.9 + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/instrumenter@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@vitest/utils': 2.1.9 + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/manager-api@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/preview-api@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/react-dom-shim@8.6.14(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3))': + dependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/react-dom-shim@8.6.18(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3))': + dependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + storybook: 8.6.18(prettier@3.8.3) + + '@storybook/react-vite@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.3)))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(rollup@4.60.2)(storybook@8.6.18(prettier@3.8.3))(typescript@5.7.3)(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.7.3)(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0)) + '@rollup/pluginutils': 5.3.0(rollup@4.60.2) + '@storybook/builder-vite': 8.6.18(storybook@8.6.18(prettier@3.8.3))(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0)) + '@storybook/react': 8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.3)))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3))(typescript@5.7.3) + find-up: 5.0.0 + magic-string: 0.30.21 + react: 19.2.5 + react-docgen: 7.1.1 + react-dom: 19.2.5(react@19.2.5) + resolve: 1.22.12 + storybook: 8.6.18(prettier@3.8.3) + tsconfig-paths: 4.2.0 + vite: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + optionalDependencies: + '@storybook/test': 8.6.15(storybook@8.6.18(prettier@3.8.3)) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + + '@storybook/react@8.6.18(@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.3)))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3))(typescript@5.7.3)': + dependencies: + '@storybook/components': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + '@storybook/global': 5.0.0 + '@storybook/manager-api': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + '@storybook/preview-api': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + '@storybook/react-dom-shim': 8.6.18(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@8.6.18(prettier@3.8.3)) + '@storybook/theming': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + storybook: 8.6.18(prettier@3.8.3) + optionalDependencies: + '@storybook/test': 8.6.15(storybook@8.6.18(prettier@3.8.3)) + typescript: 5.7.3 + + '@storybook/test@8.6.14(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.14(storybook@8.6.18(prettier@3.8.3)) + '@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.18(prettier@3.8.3) + + '@storybook/test@8.6.15(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.15(storybook@8.6.18(prettier@3.8.3)) + '@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.18(prettier@3.8.3) + + '@storybook/test@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.18(storybook@8.6.18(prettier@3.8.3)) + '@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.18(prettier@3.8.3) + + '@storybook/theming@8.6.18(storybook@8.6.18(prettier@3.8.3))': + dependencies: + storybook: 8.6.18(prettier@3.8.3) + + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.29.2 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.5.0': + dependencies: + '@adobe/css-tools': 4.4.4 + aria-query: 5.3.2 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.18.1 + 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.2(@testing-library/dom@10.4.0)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + dependencies: + '@babel/runtime': 7.29.2 + '@testing-library/dom': 10.4.0 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) + + '@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 + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.0 + + '@types/debug@4.1.13': + dependencies: + '@types/ms': 2.1.0 + + '@types/doctrine@0.0.9': {} + + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.8 + + '@types/estree@1.0.8': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/js-yaml@4.0.9': {} + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdx@2.0.13': {} + + '@types/ms@2.1.0': {} + + '@types/nlcst@2.0.3': + dependencies: + '@types/unist': 3.0.3 + + '@types/node@12.20.55': {} + + '@types/node@24.12.2': + dependencies: + undici-types: 7.16.0 + + '@types/react-dom@19.2.3(@types/react@19.2.14)': + dependencies: + '@types/react': 19.2.14 + + '@types/react@19.2.14': + dependencies: + csstype: 3.2.3 + + '@types/resolve@1.20.6': {} + + '@types/sax@1.2.7': + dependencies: + '@types/node': 24.12.2 + + '@types/unist@2.0.11': {} + + '@types/unist@3.0.3': {} + + '@types/uuid@9.0.8': {} + + '@ungap/structured-clone@1.3.0': {} + + '@vitejs/plugin-react@4.7.0(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-react@4.7.0(vite@8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4) + transitivePeerDependencies: + - supports-color + + '@vitejs/plugin-react@6.0.1(vite@8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4))': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.7 + vite: 8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4) + + '@vitest/expect@2.0.5': + dependencies: + '@vitest/spy': 2.0.5 + '@vitest/utils': 2.0.5 + chai: 5.3.3 + tinyrainbow: 1.2.0 + + '@vitest/expect@2.1.9': + dependencies: + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + tinyrainbow: 1.2.0 + + '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0))': + dependencies: + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + + '@vitest/pretty-format@2.0.5': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/pretty-format@2.1.9': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/runner@2.1.9': + dependencies: + '@vitest/utils': 2.1.9 + pathe: 1.1.2 + + '@vitest/snapshot@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + magic-string: 0.30.21 + pathe: 1.1.2 + + '@vitest/spy@2.0.5': + dependencies: + tinyspy: 3.0.2 + + '@vitest/spy@2.1.9': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@2.0.5': + dependencies: + '@vitest/pretty-format': 2.0.5 + estree-walker: 3.0.3 + loupe: 3.2.1 + tinyrainbow: 1.2.0 + + '@vitest/utils@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + loupe: 3.2.1 + tinyrainbow: 1.2.0 + + '@yarnpkg/lockfile@1.1.0': {} + + '@zip.js/zip.js@2.8.26': {} + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@7.1.4: {} + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-colors@4.1.3: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + array-iterate@2.0.1: {} + + array-union@2.1.0: {} + + assert@2.1.0: + dependencies: + call-bind: 1.0.9 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.7 + util: 0.12.5 + + assertion-error@2.0.1: {} + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + astring@1.9.0: {} + + astro-expressive-code@0.38.3(astro@5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4)): + dependencies: + astro: 5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4) + rehype-expressive-code: 0.38.3 + + astro@5.18.1(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.60.2)(typescript@6.0.3)(yaml@2.8.4): + dependencies: + '@astrojs/compiler': 2.13.1 + '@astrojs/internal-helpers': 0.7.6 + '@astrojs/markdown-remark': 6.3.11 + '@astrojs/telemetry': 3.3.0 + '@capsizecss/unpack': 4.0.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.3.0(rollup@4.60.2) + acorn: 8.16.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + boxen: 8.0.1 + ci-info: 4.4.0 + clsx: 2.1.1 + common-ancestor-path: 1.0.1 + cookie: 1.1.1 + cssesc: 3.0.0 + debug: 4.4.3 + deterministic-object-hash: 2.0.2 + devalue: 5.8.0 + diff: 8.0.4 + dlv: 1.1.3 + dset: 3.1.4 + es-module-lexer: 1.7.0 + esbuild: 0.27.7 + estree-walker: 3.0.3 + flattie: 1.1.1 + fontace: 0.4.1 + github-slugger: 2.0.0 + html-escaper: 3.0.3 + http-cache-semantics: 4.2.0 + import-meta-resolve: 4.2.0 + js-yaml: 4.1.1 + magic-string: 0.30.21 + magicast: 0.5.2 + mrmime: 2.0.1 + neotraverse: 0.6.18 + p-limit: 6.2.0 + p-queue: 8.1.1 + package-manager-detector: 1.6.0 + piccolore: 0.1.3 + picomatch: 4.0.4 + prompts: 2.4.2 + rehype: 13.0.2 + semver: 7.7.4 + shiki: 3.23.0 + smol-toml: 1.6.1 + svgo: 4.0.1 + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + tsconfck: 3.1.6(typescript@6.0.3) + ultrahtml: 1.6.0 + unifont: 0.7.4 + unist-util-visit: 5.1.0 + unstorage: 1.17.5 + vfile: 6.0.3 + vite: 6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.4) + vitefu: 1.1.3(vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.4)) + xxhash-wasm: 1.1.0 + yargs-parser: 21.1.1 + yocto-spinner: 0.2.3 + zod: 3.25.76 + zod-to-json-schema: 3.25.2(zod@3.25.76) + zod-to-ts: 1.2.0(typescript@6.0.3)(zod@3.25.76) + optionalDependencies: + sharp: 0.34.5 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@types/node' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/functions' + - '@vercel/kv' + - aws4fetch + - db0 + - idb-keyval + - ioredis + - jiti + - less + - lightningcss + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - typescript + - uploadthing + - yaml + + asynckit@0.4.0: {} + + autoprefixer@10.5.0(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + caniuse-lite: 1.0.30001791 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.11.4: {} + + axobject-query@4.1.0: {} + + bail@2.0.2: {} + + balanced-match@1.0.2: {} + + base-64@1.0.0: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.27: {} + + bcp-47-match@2.0.3: {} + + bcp-47@2.1.0: + dependencies: + is-alphabetical: 2.0.1 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + + better-opn@3.0.2: + dependencies: + open: 8.4.2 + + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + + binary-extensions@2.3.0: {} + + boolbase@1.0.0: {} + + boxen@8.0.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 8.0.0 + chalk: 5.6.2 + cli-boxes: 3.0.0 + string-width: 7.2.0 + type-fest: 4.41.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.2 + + brace-expansion@2.1.0: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-assert@1.2.1: {} + + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.27 + caniuse-lite: 1.0.30001791 + electron-to-chromium: 1.5.349 + node-releases: 2.0.38 + update-browserslist-db: 1.2.3(browserslist@4.28.2) + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bundle-require@5.1.0(esbuild@0.27.7): + dependencies: + esbuild: 0.27.7 + load-tsconfig: 0.2.5 + + bytes-iec@3.1.1: {} + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + camelcase@8.0.0: {} + + caniuse-api@3.0.0: + dependencies: + browserslist: 4.28.2 + caniuse-lite: 1.0.30001791 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + + caniuse-lite@1.0.30001791: {} + + ccount@2.0.1: {} + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + change-case@5.4.4: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + character-reference-invalid@2.0.1: {} + + chardet@2.1.1: {} + + check-error@2.1.3: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chokidar@5.0.0: + dependencies: + readdirp: 5.0.0 + + ci-info@3.9.0: {} + + ci-info@4.4.0: {} + + cli-boxes@3.0.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clsx@2.1.1: {} + + collapse-white-space@2.1.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.4 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + comma-separated-tokens@2.0.3: {} + + commander@11.1.0: {} + + commander@12.1.0: {} + + commander@4.1.1: {} + + common-ancestor-path@1.0.1: {} + + component-emitter@2.0.0: {} + + confbox@0.1.8: {} + + consola@3.4.2: {} + + convert-source-map@2.0.0: {} + + cookie-es@1.2.3: {} + + cookie@1.1.1: {} + + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crossws@0.3.5: + dependencies: + uncrypto: 0.1.3 + + css-declaration-sorter@7.4.0(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-selector-parser@3.3.0: {} + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + + css-what@6.2.2: {} + + css.escape@1.5.1: {} + + cssesc@3.0.0: {} + + cssnano-preset-default@7.0.16(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + css-declaration-sorter: 7.4.0(postcss@8.5.13) + cssnano-utils: 5.0.3(postcss@8.5.13) + postcss: 8.5.13 + postcss-calc: 10.1.1(postcss@8.5.13) + postcss-colormin: 7.0.10(postcss@8.5.13) + postcss-convert-values: 7.0.12(postcss@8.5.13) + postcss-discard-comments: 7.0.8(postcss@8.5.13) + postcss-discard-duplicates: 7.0.4(postcss@8.5.13) + postcss-discard-empty: 7.0.3(postcss@8.5.13) + postcss-discard-overridden: 7.0.3(postcss@8.5.13) + postcss-merge-longhand: 7.0.7(postcss@8.5.13) + postcss-merge-rules: 7.0.11(postcss@8.5.13) + postcss-minify-font-values: 7.0.3(postcss@8.5.13) + postcss-minify-gradients: 7.0.5(postcss@8.5.13) + postcss-minify-params: 7.0.9(postcss@8.5.13) + postcss-minify-selectors: 7.1.1(postcss@8.5.13) + postcss-normalize-charset: 7.0.3(postcss@8.5.13) + postcss-normalize-display-values: 7.0.3(postcss@8.5.13) + postcss-normalize-positions: 7.0.4(postcss@8.5.13) + postcss-normalize-repeat-style: 7.0.4(postcss@8.5.13) + postcss-normalize-string: 7.0.3(postcss@8.5.13) + postcss-normalize-timing-functions: 7.0.3(postcss@8.5.13) + postcss-normalize-unicode: 7.0.9(postcss@8.5.13) + postcss-normalize-url: 7.0.3(postcss@8.5.13) + postcss-normalize-whitespace: 7.0.3(postcss@8.5.13) + postcss-ordered-values: 7.0.4(postcss@8.5.13) + postcss-reduce-initial: 7.0.9(postcss@8.5.13) + postcss-reduce-transforms: 7.0.3(postcss@8.5.13) + postcss-svgo: 7.1.3(postcss@8.5.13) + postcss-unique-selectors: 7.0.7(postcss@8.5.13) + + cssnano-utils@5.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + + cssnano@7.1.8(postcss@8.5.13): + dependencies: + cssnano-preset-default: 7.0.16(postcss@8.5.13) + lilconfig: 3.1.3 + postcss: 8.5.13 + + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + + csstype@3.2.3: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decimal.js@10.6.0: {} + + decode-named-character-reference@1.3.0: + dependencies: + character-entities: 2.0.2 + + deep-eql@5.0.2: {} + + deepmerge@4.3.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + defu@6.1.7: {} + + delayed-stream@1.0.0: {} + + dependency-graph@1.0.0: {} + + dequal@2.0.3: {} + + destr@2.0.5: {} + + detect-indent@6.1.0: {} + + detect-libc@2.1.2: {} + + detect-node-es@1.1.0: {} + + deterministic-object-hash@2.0.2: + dependencies: + base-64: 1.0.0 + + devalue@5.8.0: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff@8.0.4: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + direction@2.0.1: {} + + dlv@1.1.3: {} + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dset@3.1.4: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.349: {} + + emoji-regex-xs@1.0.0: {} + + emoji-regex@10.6.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + + entities@4.5.0: {} + + entities@6.0.1: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-module-lexer@1.7.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.3 + + esast-util-from-estree@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + unist-util-position-from-estree: 2.0.0 + + esast-util-from-js@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + acorn: 8.16.0 + esast-util-from-estree: 2.0.0 + vfile-message: 4.0.3 + + esbuild-register@3.6.0(esbuild@0.25.12): + dependencies: + debug: 4.4.3 + esbuild: 0.25.12 + transitivePeerDependencies: + - supports-color + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + esbuild@0.27.7: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + escalade@3.2.0: {} + + escape-string-regexp@5.0.0: {} + + esprima@4.0.1: {} + + estree-util-attach-comments@3.0.0: + dependencies: + '@types/estree': 1.0.8 + + estree-util-build-jsx@3.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + estree-walker: 3.0.3 + + estree-util-is-identifier-name@3.0.0: {} + + estree-util-scope@1.0.0: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + + estree-util-to-js@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + astring: 1.9.0 + source-map: 0.7.6 + + estree-util-visit@2.0.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 3.0.3 + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + esutils@2.0.3: {} + + eventemitter3@5.0.4: {} + + events@3.3.0: {} + + expect-type@1.3.0: {} + + expressive-code@0.38.3: + dependencies: + '@expressive-code/core': 0.38.3 + '@expressive-code/plugin-frames': 0.38.3 + '@expressive-code/plugin-shiki': 0.38.3 + '@expressive-code/plugin-text-markers': 0.38.3 + + extend@3.0.2: {} + + extendable-error@0.1.7: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + find-yarn-workspace-root@2.0.0: + dependencies: + micromatch: 4.0.8 + + fix-dts-default-cjs-exports@1.0.1: + dependencies: + magic-string: 0.30.21 + mlly: 1.8.2 + rollup: 4.60.2 + + flattie@1.1.1: {} + + fontace@0.4.1: + dependencies: + fontkitten: 1.0.3 + + fontkitten@1.0.3: + dependencies: + tiny-inflate: 1.0.3 + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.3 + mime-types: 2.1.35 + + fraction.js@5.3.4: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@11.3.4: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.5.0: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.3 + math-intrinsics: 1.1.0 + + get-nonce@1.0.1: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + github-slugger@2.0.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regex.js@1.2.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + h3@1.15.11: + dependencies: + cookie-es: 1.2.3 + crossws: 0.3.5 + defu: 6.1.7 + destr: 2.0.5 + iron-webcrypto: 1.2.1 + node-mock-http: 1.0.4 + radix3: 1.1.2 + ufo: 1.6.4 + uncrypto: 0.1.3 + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.3: + dependencies: + function-bind: 1.1.2 + + hast-util-embedded@3.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-is-element: 3.0.0 + + hast-util-format@1.1.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-minify-whitespace: 1.0.1 + hast-util-phrasing: 3.0.1 + hast-util-whitespace: 3.0.0 + html-whitespace-sensitive-tag-names: 3.0.1 + unist-util-visit-parents: 6.0.2 + + hast-util-from-html@2.0.3: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.3 + parse5: 7.3.0 + vfile: 6.0.3 + vfile-message: 4.0.3 + + hast-util-from-parse5@8.0.3: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + devlop: 1.1.0 + hastscript: 9.0.1 + property-information: 7.1.0 + vfile: 6.0.3 + vfile-location: 5.0.3 + web-namespaces: 2.0.1 + + hast-util-has-property@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-is-body-ok-link@3.0.1: + dependencies: + '@types/hast': 3.0.4 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-minify-whitespace@1.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-is-element: 3.0.0 + hast-util-whitespace: 3.0.0 + unist-util-is: 6.0.1 + + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-phrasing@3.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-embedded: 3.0.0 + hast-util-has-property: 3.0.0 + hast-util-is-body-ok-link: 3.0.1 + hast-util-is-element: 3.0.0 + + hast-util-raw@9.1.0: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + '@ungap/structured-clone': 1.3.0 + hast-util-from-parse5: 8.0.3 + hast-util-to-parse5: 8.0.1 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + parse5: 7.3.0 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-select@6.0.4: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + bcp-47-match: 2.0.3 + comma-separated-tokens: 2.0.3 + css-selector-parser: 3.3.0 + devlop: 1.1.0 + direction: 2.0.1 + hast-util-has-property: 3.0.0 + hast-util-to-string: 3.0.1 + hast-util-whitespace: 3.0.0 + nth-check: 2.1.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + hast-util-to-estree@3.1.3: + dependencies: + '@types/estree': 1.0.8 + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-attach-comments: 3.0.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + style-to-js: 1.1.21 + unist-util-position: 5.0.0 + zwitch: 2.0.4 + transitivePeerDependencies: + - supports-color + + hast-util-to-html@9.0.5: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-to-jsx-runtime@2.3.6: + dependencies: + '@types/estree': 1.0.8 + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + hast-util-whitespace: 3.0.0 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + style-to-js: 1.1.21 + unist-util-position: 5.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + hast-util-to-parse5@8.0.1: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-string@3.0.1: + dependencies: + '@types/hast': 3.0.4 + + hast-util-to-text@4.0.2: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hastscript@9.0.1: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 7.1.0 + space-separated-tokens: 2.0.2 + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + html-escaper@3.0.3: {} + + html-void-elements@3.0.0: {} + + html-whitespace-sensitive-tag-names@3.0.1: {} + + http-cache-semantics@4.2.0: {} + + 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: {} + + hyperdyperid@1.2.0: {} + + i18next@23.16.8: + dependencies: + '@babel/runtime': 7.29.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + import-meta-resolve@4.2.0: {} + + indent-string@4.0.0: {} + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + inline-style-parser@0.2.7: {} + + iron-webcrypto@1.2.1: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-arrayish@0.3.4: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.3 + + is-decimal@2.0.1: {} + + is-docker@2.2.1: {} + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hexadecimal@2.0.1: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-nan@1.3.2: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + + is-number@7.0.0: {} + + is-plain-obj@4.1.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.3 + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.20 + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@2.6.1: {} + + joycon@3.1.1: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@4.8.0: {} + + jsdom@25.0.1: + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + form-data: 4.0.5 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + rrweb-cssom: 0.7.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.20.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@3.1.0: {} + + json-stable-stringify@1.3.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + isarray: 2.0.5 + jsonify: 0.0.1 + object-keys: 1.1.1 + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.2.1: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonify@0.0.1: {} + + klaw-sync@6.0.0: + dependencies: + graceful-fs: 4.2.11 + + kleur@3.0.3: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + load-tsconfig@0.2.5: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.18.1: {} + + lodash.memoize@4.1.2: {} + + lodash.startcase@4.4.0: {} + + lodash.uniq@4.5.0: {} + + lodash@4.18.1: {} + + longest-streak@3.1.0: {} + + loupe@3.2.1: {} + + lru-cache@10.4.3: {} + + lru-cache@11.3.5: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lz-string@1.5.0: {} + + magic-string@0.27.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.2: + dependencies: + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + map-or-similar@1.5.0: {} + + markdown-extensions@2.0.0: {} + + markdown-table@3.0.4: {} + + math-intrinsics@1.1.0: {} + + mdast-util-definitions@6.0.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + unist-util-visit: 5.1.0 + + mdast-util-directive@3.1.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-visit-parents: 6.0.2 + transitivePeerDependencies: + - supports-color + + mdast-util-find-and-replace@3.0.2: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + mdast-util-from-markdown@2.0.3: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.2 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.2 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.1.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.1.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.1.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-expression@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@3.2.0: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + parse-entities: 4.0.2 + stringify-entities: 4.0.4 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.3 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.3 + mdast-util-mdx-expression: 2.0.1 + mdast-util-mdx-jsx: 3.2.0 + mdast-util-mdxjs-esm: 2.0.1 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@2.0.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.3 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.1 + + mdast-util-to-hast@13.2.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.3.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.1.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.1.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + mdn-data@2.0.28: {} + + mdn-data@2.27.1: {} + + memfs@4.57.2(tslib@2.8.1): + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + memoizerific@1.11.3: + dependencies: + map-or-similar: 1.5.0 + + merge2@1.4.1: {} + + micromark-core-commonmark@2.0.3: + dependencies: + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-directive@3.0.2: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + parse-entities: 4.0.2 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-table@2.1.1: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.1 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-expression@3.0.1: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-extension-mdx-jsx@3.0.2: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + estree-util-is-identifier-name: 3.0.0 + micromark-factory-mdx-expression: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-extension-mdx-md@2.0.0: + dependencies: + micromark-util-types: 2.0.2 + + micromark-extension-mdxjs-esm@3.0.0: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.3 + + micromark-extension-mdxjs@3.0.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + micromark-extension-mdx-expression: 3.0.1 + micromark-extension-mdx-jsx: 3.0.2 + micromark-extension-mdx-md: 2.0.0 + micromark-extension-mdxjs-esm: 3.0.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-mdx-expression@2.0.3: + dependencies: + '@types/estree': 1.0.8 + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-events-to-acorn: 2.0.3 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + unist-util-position-from-estree: 2.0.0 + vfile-message: 4.0.3 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.2 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.3.0 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-events-to-acorn@2.0.3: + dependencies: + '@types/estree': 1.0.8 + '@types/unist': 3.0.3 + devlop: 1.1.0 + estree-util-visit: 2.0.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + vfile-message: 4.0.3 + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.2 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.2: {} + + micromark@4.0.2: + dependencies: + '@types/debug': 4.1.13 + debug: 4.4.3 + decode-named-character-reference: 1.3.0 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.3 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.1.0 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.2 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + min-indent@1.0.1: {} + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.1.0 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + mlly@1.8.2: + dependencies: + acorn: 8.16.0 + pathe: 2.0.3 + pkg-types: 1.3.1 + ufo: 1.6.4 + + mri@1.2.0: {} + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.12: {} + + nanoid@5.1.11: {} + + nanospinner@1.2.2: + dependencies: + picocolors: 1.1.1 + + neotraverse@0.6.18: {} + + nlcst-to-string@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + + node-fetch-native@1.6.7: {} + + node-mock-http@1.0.4: {} + + node-releases@2.0.38: {} + + normalize-path@3.0.0: {} + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nwsapi@2.2.23: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + ofetch@1.5.1: + dependencies: + destr: 2.0.5 + node-fetch-native: 1.6.7 + ufo: 1.6.4 + + ohash@2.0.11: {} + + oniguruma-parser@0.12.2: {} + + oniguruma-to-es@2.3.0: + dependencies: + emoji-regex-xs: 1.0.0 + regex: 5.1.1 + regex-recursion: 5.1.1 + + oniguruma-to-es@4.3.6: + dependencies: + oniguruma-parser: 0.12.2 + regex: 6.1.0 + regex-recursion: 6.0.2 + + open@7.4.2: + dependencies: + is-docker: 2.2.1 + is-wsl: 2.2.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + outdent@0.5.0: {} + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@6.2.0: + dependencies: + yocto-queue: 1.2.2 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@2.1.0: {} + + p-queue@8.1.1: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 6.1.4 + + p-timeout@6.1.4: {} + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.11 + + package-manager-detector@1.6.0: {} + + pagefind@1.5.2: + optionalDependencies: + '@pagefind/darwin-arm64': 1.5.2 + '@pagefind/darwin-x64': 1.5.2 + '@pagefind/freebsd-x64': 1.5.2 + '@pagefind/linux-arm64': 1.5.2 + '@pagefind/linux-x64': 1.5.2 + '@pagefind/windows-arm64': 1.5.2 + '@pagefind/windows-x64': 1.5.2 + + parse-entities@4.0.2: + dependencies: + '@types/unist': 2.0.11 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.3.0 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + + parse-latin@7.0.0: + dependencies: + '@types/nlcst': 2.0.3 + '@types/unist': 3.0.3 + nlcst-to-string: 4.0.0 + unist-util-modify-children: 4.0.0 + unist-util-visit-children: 3.0.0 + vfile: 6.0.3 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + patch-package@8.0.1: + dependencies: + '@yarnpkg/lockfile': 1.1.0 + chalk: 4.1.2 + ci-info: 3.9.0 + cross-spawn: 7.0.6 + find-yarn-workspace-root: 2.0.0 + fs-extra: 10.1.0 + json-stable-stringify: 1.3.0 + klaw-sync: 6.0.0 + minimist: 1.2.8 + open: 7.4.2 + semver: 7.7.4 + slash: 2.0.0 + tmp: 0.2.5 + yaml: 2.8.4 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-type@4.0.0: {} + + path-unified@0.2.0: {} + + path@0.12.7: + dependencies: + process: 0.11.10 + util: 0.10.4 + + pathe@1.1.2: {} + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + piccolore@0.1.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + pify@2.3.0: {} + + pify@4.0.1: {} + + pirates@4.0.7: {} + + pkg-types@1.3.1: + dependencies: + confbox: 0.1.8 + mlly: 1.8.2 + pathe: 2.0.3 + + polished@4.3.1: + dependencies: + '@babel/runtime': 7.29.2 + + possible-typed-array-names@1.1.0: {} + + postcss-calc@10.1.1(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + + postcss-cli@11.0.1(jiti@2.6.1)(postcss@8.5.13): + dependencies: + chokidar: 3.6.0 + dependency-graph: 1.0.0 + fs-extra: 11.3.4 + picocolors: 1.1.1 + postcss: 8.5.13 + postcss-load-config: 5.1.0(jiti@2.6.1)(postcss@8.5.13) + postcss-reporter: 7.1.0(postcss@8.5.13) + pretty-hrtime: 1.0.3 + read-cache: 1.0.0 + slash: 5.1.0 + tinyglobby: 0.2.16 + yargs: 17.7.2 + transitivePeerDependencies: + - jiti + - tsx + + postcss-colormin@7.0.10(postcss@8.5.13): + dependencies: + '@colordx/core': 5.4.3 + browserslist: 4.28.2 + caniuse-api: 3.0.0 + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-convert-values@7.0.12(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-discard-comments@7.0.8(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-selector-parser: 7.1.1 + + postcss-discard-duplicates@7.0.4(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + + postcss-discard-empty@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + + postcss-discard-overridden@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + + postcss-import@16.1.1(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.12 + + postcss-load-config@5.1.0(jiti@2.6.1)(postcss@8.5.13): + dependencies: + lilconfig: 3.1.3 + yaml: 2.8.4 + optionalDependencies: + jiti: 2.6.1 + postcss: 8.5.13 + + postcss-load-config@6.0.1(jiti@2.6.1)(postcss@8.5.13)(yaml@2.8.4): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + jiti: 2.6.1 + postcss: 8.5.13 + yaml: 2.8.4 + + postcss-merge-longhand@7.0.7(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + stylehacks: 7.0.11(postcss@8.5.13) + + postcss-merge-rules@7.0.11(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + caniuse-api: 3.0.0 + cssnano-utils: 5.0.3(postcss@8.5.13) + postcss: 8.5.13 + postcss-selector-parser: 7.1.1 + + postcss-minify-font-values@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-minify-gradients@7.0.5(postcss@8.5.13): + dependencies: + '@colordx/core': 5.4.3 + cssnano-utils: 5.0.3(postcss@8.5.13) + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-minify-params@7.0.9(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + cssnano-utils: 5.0.3(postcss@8.5.13) + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-minify-selectors@7.1.1(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + caniuse-api: 3.0.0 + cssesc: 3.0.0 + postcss: 8.5.13 + postcss-selector-parser: 7.1.1 + + postcss-nested@6.2.0(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-selector-parser: 6.1.2 + + postcss-normalize-charset@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + + postcss-normalize-display-values@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-normalize-positions@7.0.4(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-normalize-repeat-style@7.0.4(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-normalize-string@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-normalize-timing-functions@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-normalize-unicode@7.0.9(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-normalize-url@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-normalize-whitespace@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-ordered-values@7.0.4(postcss@8.5.13): + dependencies: + cssnano-utils: 5.0.3(postcss@8.5.13) + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-reduce-initial@7.0.9(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + caniuse-api: 3.0.0 + postcss: 8.5.13 + + postcss-reduce-transforms@7.0.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + + postcss-reporter@7.1.0(postcss@8.5.13): + dependencies: + picocolors: 1.1.1 + postcss: 8.5.13 + thenby: 1.4.1 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@7.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-svgo@7.1.3(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-value-parser: 4.2.0 + svgo: 4.0.1 + + postcss-unique-selectors@7.0.7(postcss@8.5.13): + dependencies: + postcss: 8.5.13 + postcss-selector-parser: 7.1.1 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.13: + dependencies: + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier@2.8.8: {} + + prettier@3.8.3: {} + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + pretty-hrtime@1.0.3: {} + + prismjs@1.30.0: {} + + process@0.11.10: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + property-information@7.1.0: {} + + punycode@1.4.1: {} + + punycode@2.3.1: {} + + qs@6.15.1: + dependencies: + side-channel: 1.1.0 + + quansync@0.2.11: {} + + queue-microtask@1.2.3: {} + + radix3@1.1.2: {} + + react-docgen-typescript@2.4.0(typescript@5.7.3): + dependencies: + typescript: 5.7.3 + + react-docgen@7.1.1: + dependencies: + '@babel/core': 7.29.0 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + '@types/doctrine': 0.0.9 + '@types/resolve': 1.20.6 + doctrine: 3.0.0 + resolve: 1.22.12 + strip-indent: 4.1.1 + transitivePeerDependencies: + - supports-color + + react-dom@19.2.5(react@19.2.5): + dependencies: + react: 19.2.5 + scheduler: 0.27.0 + + react-is@17.0.2: {} + + react-refresh@0.17.0: {} + + react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.5): + dependencies: + react: 19.2.5 + react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.5) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + react-remove-scroll@2.7.2(@types/react@19.2.14)(react@19.2.5): + dependencies: + react: 19.2.5 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.14)(react@19.2.5) + react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.5) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.2.14)(react@19.2.5) + use-sidecar: 1.1.3(@types/react@19.2.14)(react@19.2.5) + optionalDependencies: + '@types/react': 19.2.14 + + react-style-singleton@2.2.3(@types/react@19.2.14)(react@19.2.5): + dependencies: + get-nonce: 1.0.1 + react: 19.2.5 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + react@19.2.5: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.2 + pify: 4.0.1 + strip-bom: 3.0.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + readdirp@4.1.2: {} + + readdirp@5.0.0: {} + + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + + recma-build-jsx@1.0.0: + dependencies: + '@types/estree': 1.0.8 + estree-util-build-jsx: 3.0.1 + vfile: 6.0.3 + + recma-jsx@1.0.1(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + estree-util-to-js: 2.0.0 + recma-parse: 1.0.0 + recma-stringify: 1.0.0 + unified: 11.0.5 + + recma-parse@1.0.0: + dependencies: + '@types/estree': 1.0.8 + esast-util-from-js: 2.0.1 + unified: 11.0.5 + vfile: 6.0.3 + + recma-stringify@1.0.0: + dependencies: + '@types/estree': 1.0.8 + estree-util-to-js: 2.0.0 + unified: 11.0.5 + vfile: 6.0.3 + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + regex-recursion@5.1.1: + dependencies: + regex: 5.1.1 + regex-utilities: 2.3.0 + + regex-recursion@6.0.2: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@5.1.1: + dependencies: + regex-utilities: 2.3.0 + + regex@6.1.0: + dependencies: + regex-utilities: 2.3.0 + + rehype-expressive-code@0.38.3: + dependencies: + expressive-code: 0.38.3 + + rehype-format@5.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-format: 1.1.0 + + rehype-parse@9.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-from-html: 2.0.3 + unified: 11.0.5 + + rehype-raw@7.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-raw: 9.1.0 + vfile: 6.0.3 + + rehype-recma@1.0.0: + dependencies: + '@types/estree': 1.0.8 + '@types/hast': 3.0.4 + hast-util-to-estree: 3.1.3 + transitivePeerDependencies: + - supports-color + + rehype-stringify@10.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + unified: 11.0.5 + + rehype@13.0.2: + dependencies: + '@types/hast': 3.0.4 + rehype-parse: 9.0.1 + rehype-stringify: 10.0.1 + unified: 11.0.5 + + remark-directive@3.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-directive: 3.1.0 + micromark-extension-directive: 3.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-gfm@4.0.1: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.1.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-mdx@3.1.1: + dependencies: + mdast-util-mdx: 3.0.0 + micromark-extension-mdxjs: 3.0.0 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.3 + micromark-util-types: 2.0.2 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-rehype@11.1.2: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.2.1 + unified: 11.0.5 + vfile: 6.0.3 + + remark-smartypants@3.0.2: + dependencies: + retext: 9.0.0 + retext-smartypants: 6.2.0 + unified: 11.0.5 + unist-util-visit: 5.1.0 + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 + + remixicon@4.9.1: {} + + require-directory@2.1.1: {} + + resolve-from@5.0.0: {} + + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retext-latin@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + parse-latin: 7.0.0 + unified: 11.0.5 + + retext-smartypants@6.2.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unist-util-visit: 5.1.0 + + retext-stringify@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unified: 11.0.5 + + retext@9.0.0: + dependencies: + '@types/nlcst': 2.0.3 + retext-latin: 4.0.0 + retext-stringify: 4.0.0 + unified: 11.0.5 + + reusify@1.1.0: {} + + rolldown@1.0.0-rc.17: + dependencies: + '@oxc-project/types': 0.127.0 + '@rolldown/pluginutils': 1.0.0-rc.17 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.17 + '@rolldown/binding-darwin-x64': 1.0.0-rc.17 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.17 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.17 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.17 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.17 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.17 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.17 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.17 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.17 + + rollup@4.60.2: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.2 + '@rollup/rollup-android-arm64': 4.60.2 + '@rollup/rollup-darwin-arm64': 4.60.2 + '@rollup/rollup-darwin-x64': 4.60.2 + '@rollup/rollup-freebsd-arm64': 4.60.2 + '@rollup/rollup-freebsd-x64': 4.60.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.2 + '@rollup/rollup-linux-arm-musleabihf': 4.60.2 + '@rollup/rollup-linux-arm64-gnu': 4.60.2 + '@rollup/rollup-linux-arm64-musl': 4.60.2 + '@rollup/rollup-linux-loong64-gnu': 4.60.2 + '@rollup/rollup-linux-loong64-musl': 4.60.2 + '@rollup/rollup-linux-ppc64-gnu': 4.60.2 + '@rollup/rollup-linux-ppc64-musl': 4.60.2 + '@rollup/rollup-linux-riscv64-gnu': 4.60.2 + '@rollup/rollup-linux-riscv64-musl': 4.60.2 + '@rollup/rollup-linux-s390x-gnu': 4.60.2 + '@rollup/rollup-linux-x64-gnu': 4.60.2 + '@rollup/rollup-linux-x64-musl': 4.60.2 + '@rollup/rollup-openbsd-x64': 4.60.2 + '@rollup/rollup-openharmony-arm64': 4.60.2 + '@rollup/rollup-win32-arm64-msvc': 4.60.2 + '@rollup/rollup-win32-ia32-msvc': 4.60.2 + '@rollup/rollup-win32-x64-gnu': 4.60.2 + '@rollup/rollup-win32-x64-msvc': 4.60.2 + fsevents: 2.3.3 + + rrweb-cssom@0.7.1: {} + + rrweb-cssom@0.8.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.2.1: {} + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + sax@1.6.0: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.27.0: {} + + semver@6.3.1: {} + + semver@7.7.4: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.1.2 + semver: 7.7.4 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + + sharp@0.34.5: + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.7.4 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.5 + '@img/sharp-darwin-x64': 0.34.5 + '@img/sharp-libvips-darwin-arm64': 1.2.4 + '@img/sharp-libvips-darwin-x64': 1.2.4 + '@img/sharp-libvips-linux-arm': 1.2.4 + '@img/sharp-libvips-linux-arm64': 1.2.4 + '@img/sharp-libvips-linux-ppc64': 1.2.4 + '@img/sharp-libvips-linux-riscv64': 1.2.4 + '@img/sharp-libvips-linux-s390x': 1.2.4 + '@img/sharp-libvips-linux-x64': 1.2.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 + '@img/sharp-libvips-linuxmusl-x64': 1.2.4 + '@img/sharp-linux-arm': 0.34.5 + '@img/sharp-linux-arm64': 0.34.5 + '@img/sharp-linux-ppc64': 0.34.5 + '@img/sharp-linux-riscv64': 0.34.5 + '@img/sharp-linux-s390x': 0.34.5 + '@img/sharp-linux-x64': 0.34.5 + '@img/sharp-linuxmusl-arm64': 0.34.5 + '@img/sharp-linuxmusl-x64': 0.34.5 + '@img/sharp-wasm32': 0.34.5 + '@img/sharp-win32-arm64': 0.34.5 + '@img/sharp-win32-ia32': 0.34.5 + '@img/sharp-win32-x64': 0.34.5 + optional: true + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shiki@1.29.2: + dependencies: + '@shikijs/core': 1.29.2 + '@shikijs/engine-javascript': 1.29.2 + '@shikijs/engine-oniguruma': 1.29.2 + '@shikijs/langs': 1.29.2 + '@shikijs/themes': 1.29.2 + '@shikijs/types': 1.29.2 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + shiki@3.23.0: + dependencies: + '@shikijs/core': 3.23.0 + '@shikijs/engine-javascript': 3.23.0 + '@shikijs/engine-oniguruma': 3.23.0 + '@shikijs/langs': 3.23.0 + '@shikijs/themes': 3.23.0 + '@shikijs/types': 3.23.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + simple-swizzle@0.2.4: + dependencies: + is-arrayish: 0.3.4 + + sisteransi@1.0.5: {} + + sitemap@9.0.1: + dependencies: + '@types/node': 24.12.2 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.6.0 + + size-limit@11.2.0: + dependencies: + bytes-iec: 3.1.1 + chokidar: 4.0.3 + jiti: 2.6.1 + lilconfig: 3.1.3 + nanospinner: 1.2.2 + picocolors: 1.1.1 + tinyglobby: 0.2.16 + + slash@2.0.0: {} + + slash@3.0.0: {} + + slash@5.1.0: {} + + smol-toml@1.6.1: {} + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + source-map@0.7.6: {} + + space-separated-tokens@2.0.2: {} + + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + sprintf-js@1.0.3: {} + + stackback@0.0.2: {} + + std-env@3.10.0: {} + + storybook@8.6.18(prettier@3.8.3): + dependencies: + '@storybook/core': 8.6.18(prettier@3.8.3)(storybook@8.6.18(prettier@3.8.3)) + optionalDependencies: + prettier: 3.8.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + stream-replace-string@2.0.0: {} + + stream@0.0.3: + dependencies: + component-emitter: 2.0.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.6.0 + get-east-asian-width: 1.5.0 + strip-ansi: 7.2.0 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-bom@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-indent@4.1.1: {} + + style-dictionary@4.4.0(tslib@2.8.1): + dependencies: + '@bundled-es-modules/deepmerge': 4.3.1 + '@bundled-es-modules/glob': 10.4.2 + '@bundled-es-modules/memfs': 4.17.0(tslib@2.8.1) + '@zip.js/zip.js': 2.8.26 + chalk: 5.6.2 + change-case: 5.4.4 + commander: 12.1.0 + is-plain-obj: 4.1.0 + json5: 2.2.3 + patch-package: 8.0.1 + path-unified: 0.2.0 + prettier: 3.8.3 + tinycolor2: 1.6.0 + transitivePeerDependencies: + - tslib + + style-to-js@1.1.21: + dependencies: + style-to-object: 1.0.14 + + style-to-object@1.0.14: + dependencies: + inline-style-parser: 0.2.7 + + stylehacks@7.0.11(postcss@8.5.13): + dependencies: + browserslist: 4.28.2 + postcss: 8.5.13 + postcss-selector-parser: 7.1.1 + + sucrase@3.35.1: + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + commander: 4.1.1 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.7 + tinyglobby: 0.2.16 + ts-interface-checker: 0.1.13 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svgo@4.0.1: + dependencies: + commander: 11.1.0 + css-select: 5.2.2 + css-tree: 3.2.1 + css-what: 6.2.2 + csso: 5.0.5 + picocolors: 1.1.1 + sax: 1.6.0 + + symbol-tree@3.2.4: {} + + tabbable@6.4.0: {} + + term-size@2.2.1: {} + + thenby@1.4.1: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + thingies@2.6.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + tiny-inflate@1.0.3: {} + + tiny-invariant@1.3.3: {} + + tinybench@2.9.0: {} + + tinycolor2@1.6.0: {} + + tinyexec@0.3.2: {} + + tinyexec@1.1.2: {} + + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinypool@1.1.1: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.2: {} + + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + + tmp@0.2.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + tree-dump@1.1.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + tree-kill@1.2.2: {} + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + ts-dedent@2.2.0: {} + + ts-interface-checker@0.1.13: {} + + tsconfck@3.1.6(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.8.1: {} + + tsup@8.5.1(jiti@2.6.1)(postcss@8.5.13)(typescript@5.7.3)(yaml@2.8.4): + dependencies: + bundle-require: 5.1.0(esbuild@0.27.7) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.2 + debug: 4.4.3 + esbuild: 0.27.7 + fix-dts-default-cjs-exports: 1.0.1 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(jiti@2.6.1)(postcss@8.5.13)(yaml@2.8.4) + resolve-from: 5.0.0 + rollup: 4.60.2 + source-map: 0.7.6 + sucrase: 3.35.1 + tinyexec: 0.3.2 + tinyglobby: 0.2.16 + tree-kill: 1.2.2 + optionalDependencies: + postcss: 8.5.13 + typescript: 5.7.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + + type-fest@4.41.0: {} + + typescript@5.7.3: {} + + typescript@6.0.3: {} + + ufo@1.6.4: {} + + ultrahtml@1.6.0: {} + + uncrypto@0.1.3: {} + + undici-types@7.16.0: {} + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unifont@0.7.4: + dependencies: + css-tree: 3.2.1 + ofetch: 1.5.1 + ohash: 2.0.11 + + unist-util-find-after@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-is@6.0.1: + dependencies: + '@types/unist': 3.0.3 + + unist-util-modify-children@4.0.0: + dependencies: + '@types/unist': 3.0.3 + array-iterate: 2.0.1 + + unist-util-position-from-estree@2.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-visit: 5.1.0 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-children@3.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + + unist-util-visit@5.1.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.1 + unist-util-visit-parents: 6.0.2 + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unplugin@1.16.1: + dependencies: + acorn: 8.16.0 + webpack-virtual-modules: 0.6.2 + + unstorage@1.17.5: + dependencies: + anymatch: 3.1.3 + chokidar: 5.0.0 + destr: 2.0.5 + h3: 1.15.11 + lru-cache: 11.3.5 + node-fetch-native: 1.6.7 + ofetch: 1.5.1 + ufo: 1.6.4 + + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.15.1 + + use-callback-ref@1.3.3(@types/react@19.2.14)(react@19.2.5): + dependencies: + react: 19.2.5 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + use-sidecar@1.1.3(@types/react@19.2.14)(react@19.2.5): + dependencies: + detect-node-es: 1.1.0 + react: 19.2.5 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.2.14 + + util-deprecate@1.0.2: {} + + util@0.10.4: + dependencies: + inherits: 2.0.3 + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.2 + is-typed-array: 1.1.15 + which-typed-array: 1.1.20 + + uuid@9.0.1: {} + + vfile-location@5.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile: 6.0.3 + + vfile-message@4.0.3: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.3 + + vite-node@2.1.9(@types/node@24.12.2)(lightningcss@1.32.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 1.1.2 + vite: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.5.13 + rollup: 4.60.2 + optionalDependencies: + '@types/node': 24.12.2 + fsevents: 2.3.3 + lightningcss: 1.32.0 + + vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.4): + dependencies: + esbuild: 0.25.12 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.13 + rollup: 4.60.2 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 24.12.2 + fsevents: 2.3.3 + jiti: 2.6.1 + lightningcss: 1.32.0 + yaml: 2.8.4 + + vite@8.0.10(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(yaml@2.8.4): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.13 + rolldown: 1.0.0-rc.17 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 24.12.2 + esbuild: 0.27.7 + fsevents: 2.3.3 + jiti: 2.6.1 + yaml: 2.8.4 + + vitefu@1.1.3(vite@6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.4)): + optionalDependencies: + vite: 6.4.2(@types/node@24.12.2)(jiti@2.6.1)(lightningcss@1.32.0)(yaml@2.8.4) + + vitest-axe@0.1.0(vitest@2.1.9(@types/node@24.12.2)(jsdom@25.0.1)(lightningcss@1.32.0)): + dependencies: + aria-query: 5.3.2 + axe-core: 4.11.4 + chalk: 5.6.2 + dom-accessibility-api: 0.5.16 + lodash-es: 4.18.1 + redent: 3.0.0 + vitest: 2.1.9(@types/node@24.12.2)(jsdom@25.0.1)(lightningcss@1.32.0) + + vitest@2.1.9(@types/node@24.12.2)(jsdom@25.0.1)(lightningcss@1.32.0): + dependencies: + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@24.12.2)(lightningcss@1.32.0)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 1.1.2 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.1.1 + tinyrainbow: 1.2.0 + vite: 5.4.21(@types/node@24.12.2)(lightningcss@1.32.0) + vite-node: 2.1.9(@types/node@24.12.2)(lightningcss@1.32.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.12.2 + jsdom: 25.0.1 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + web-namespaces@2.0.1: {} + + webidl-conversions@7.0.0: {} + + webpack-virtual-modules@0.6.2: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + which-pm-runs@1.1.0: {} + + which-typed-array@1.1.20: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + widest-line@5.0.0: + dependencies: + string-width: 7.2.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrap-ansi@9.0.2: + dependencies: + ansi-styles: 6.2.3 + string-width: 7.2.0 + strip-ansi: 7.2.0 + + ws@8.20.0: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + + xxhash-wasm@1.1.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml@2.8.4: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + yocto-queue@1.2.2: {} + + yocto-spinner@0.2.3: + dependencies: + yoctocolors: 2.1.2 + + yoctocolors@2.1.2: {} + + zod-to-json-schema@3.25.2(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod-to-ts@1.2.0(typescript@6.0.3)(zod@3.25.76): + dependencies: + typescript: 6.0.3 + zod: 3.25.76 + + zod@3.25.76: {} + + zod@4.4.3: {} + + zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..62386d6 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,5 @@ +packages: + - "packages/*" + - "demo" + - "storybook" + - "docs" diff --git a/scripts/lint-contrast.mjs b/scripts/lint-contrast.mjs new file mode 100644 index 0000000..871d3a6 --- /dev/null +++ b/scripts/lint-contrast.mjs @@ -0,0 +1,180 @@ +#!/usr/bin/env node +/** + * lint-contrast.mjs — vérifie WCAG AA sur les paires texte/fond du DSMMG + * + * Pour chaque preset accent (light + dark), valide : + * - text-primary / text-secondary / text-tertiary sur bg-page, bg-surface, bg-muted + * - accent-on sur accent (le bouton primary doit avoir 4.5:1) + * - accent sur bg-page (composant non-texte ≥ 3:1) + * + * Critères WCAG : + * - Texte normal ≥ 4.5:1 (AA) + * - Texte gros (18pt+/14pt+ bold) ≥ 3:1 (AA-large) + * - Composants non-texte ≥ 3:1 (AA, SC 1.4.11) + * + * Sortie : + * - Console + fichier dist/contrast-report.json + * - Exit code 1 si violation détectée → fail CI + */ +import { readFile, writeFile, mkdir } from "node:fs/promises"; +import { dirname, join } from "node:path"; +import { existsSync } from "node:fs"; +import { fileURLToPath } from "node:url"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(__dirname, ".."); +const REPORT_DIR = join(ROOT, "dist"); +const REPORT_PATH = join(REPORT_DIR, "contrast-report.json"); + +// — Lecture des tokens depuis le DTCG —————————————————————— +const tokensJson = JSON.parse( + await readFile(join(ROOT, "packages/tokens/src/tokens.json"), "utf8"), +); + +function flatten(obj, prefix = "") { + const out = {}; + for (const [k, v] of Object.entries(obj)) { + if (k.startsWith("$")) continue; + const path = prefix ? `${prefix}.${k}` : k; + if (v && typeof v === "object" && "$value" in v) { + out[path] = v.$value; + } else if (v && typeof v === "object") { + Object.assign(out, flatten(v, path)); + } + } + return out; +} + +const flat = flatten(tokensJson); + +// — Conversion hex → RGB → luminance relative ——————————————— +function hexToRgb(hex) { + const m = hex.replace("#", "").match(/.{2}/g); + if (!m || m.length !== 3) throw new Error(`Invalid hex: ${hex}`); + return m.map((h) => parseInt(h, 16)); +} + +/** WCAG relative luminance (sRGB). */ +function relLuminance([r, g, b]) { + const norm = [r, g, b].map((c) => { + const s = c / 255; + return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4); + }); + return 0.2126 * norm[0] + 0.7152 * norm[1] + 0.0722 * norm[2]; +} + +/** WCAG contrast ratio. */ +function ratio(c1, c2) { + const l1 = relLuminance(hexToRgb(c1)); + const l2 = relLuminance(hexToRgb(c2)); + const [a, b] = l1 > l2 ? [l1, l2] : [l2, l1]; + return (a + 0.05) / (b + 0.05); +} + +// — Définition des presets light —————————————————————————— +const PRESETS = ["synapse", "rose", "blue", "violet", "green", "amber", "red", "cyan", "slate"]; + +// Couleurs sémantiques light (résolues en hard-coded car semantic.css fait +// les indirections via var(--mmg-color-neutral-*) — équivalent ici). +// Reflète semantic.css (text-tertiary bumpé à neutral-600 pour AA). +const LIGHT = { + bgPage: flat["color.neutral.50"], + bgSurface: flat["color.neutral.0"], + bgMuted: flat["color.neutral.150"], + textPrimary: flat["color.neutral.900"], + textSecondary: flat["color.neutral.700"], + textTertiary: flat["color.neutral.600"], +}; + +// — Tests par preset ———————————————————————————————————————— +const results = []; +let failures = 0; + +function check(label, fg, bg, threshold = 4.5) { + const r = ratio(fg, bg); + const pass = r >= threshold; + if (!pass) failures++; + return { label, fg, bg, ratio: +r.toFixed(2), threshold, pass }; +} + +// 1. Texte sur bg-page / bg-surface / bg-muted (sémantique fixe) +results.push({ + group: "Sémantique fixe — light", + tests: [ + check("text-primary on bg-page", LIGHT.textPrimary, LIGHT.bgPage, 4.5), + check("text-secondary on bg-page", LIGHT.textSecondary, LIGHT.bgPage, 4.5), + check("text-tertiary on bg-page", LIGHT.textTertiary, LIGHT.bgPage, 4.5), + check("text-primary on bg-surface", LIGHT.textPrimary, LIGHT.bgSurface, 4.5), + check("text-secondary on bg-surface", LIGHT.textSecondary, LIGHT.bgSurface, 4.5), + check("text-primary on bg-muted", LIGHT.textPrimary, LIGHT.bgMuted, 4.5), + ], +}); + +// 2. Pour chaque preset accent (light) — accent-on sur accent (CTA primary) +// Reflète accent.css : green/cyan utilisent -700 (au lieu de -500), +// slate utilise -700, amber utilise -500 avec accent-on=text-primary. +const ACCENT_SHADE = { + synapse: 500, rose: 500, blue: 500, violet: 500, red: 500, + amber: 600, green: 700, cyan: 700, slate: 700, +}; +const ACCENT_ON = (_preset) => "#FFFFFF"; + +for (const preset of PRESETS) { + const shade = ACCENT_SHADE[preset]; + const accent = flat[`color.${preset}.${shade}`]; + const accentOn = ACCENT_ON(preset); + results.push({ + group: `Accent: ${preset} (${shade}) — light`, + tests: [ + check(`accent-on on ${preset}-${shade}`, accentOn, accent, 4.5), + check(`${preset}-${shade} on bg-page`, accent, LIGHT.bgPage, 3.0), + check(`${preset}-${shade} on bg-surface`, accent, LIGHT.bgSurface, 3.0), + ], + }); +} + +// 3. Sémantique fixe sur bg-page light +// Reflète semantic.css : warning bumpé à amber-600 pour passer AA. +const SEM = { + success: flat["color.green.500"], + warning: flat["color.amber.600"], + danger: flat["color.red.500"], + info: flat["color.blue.500"], +}; +results.push({ + group: "Sémantique success/warning/danger/info — light", + tests: [ + // success (vert): #0E9F6E sur fond clair → contraste sera < 4.5 mais ≥ 3 (composant) + check("success on bg-page", SEM.success, LIGHT.bgPage, 3.0), + check("warning on bg-page", SEM.warning, LIGHT.bgPage, 3.0), + check("danger on bg-page", SEM.danger, LIGHT.bgPage, 3.0), + check("info on bg-page", SEM.info, LIGHT.bgPage, 3.0), + ], +}); + +// — Sortie —————————————————————————————————————————————————— +const total = results.reduce((s, g) => s + g.tests.length, 0); +const passed = total - failures; + +console.log(`\n━━━ DSMMG contrast lint ━━━`); +for (const group of results) { + console.log(`\n${group.group}`); + for (const t of group.tests) { + const icon = t.pass ? "✓" : "✗"; + const color = t.pass ? "\x1b[32m" : "\x1b[31m"; + console.log(` ${color}${icon}\x1b[0m ${t.label.padEnd(40)} ${t.ratio.toFixed(2)}:1 (≥ ${t.threshold}:1)`); + } +} +console.log(`\n${passed}/${total} passed.`); + +if (!existsSync(REPORT_DIR)) await mkdir(REPORT_DIR, { recursive: true }); +await writeFile( + REPORT_PATH, + JSON.stringify({ passed, failed: failures, total, results }, null, 2), +); + +if (failures > 0) { + console.error(`\n✗ ${failures} contrast violation(s).`); + process.exit(1); +} +console.log(`\n✓ All contrast checks pass WCAG AA.`); diff --git a/scripts/migrate-tokens.mjs b/scripts/migrate-tokens.mjs new file mode 100644 index 0000000..0b5755e --- /dev/null +++ b/scripts/migrate-tokens.mjs @@ -0,0 +1,191 @@ +#!/usr/bin/env node +// DSMMG token migration codemod +// Renomme les références --mmg-* legacy vers la nomenclature --mmg-color-*. +// Sûr et idempotent : applique les mappings dans l'ordre du plus spécifique +// au plus générique (longest-match-first). +import { readFile, writeFile, readdir, stat } from "node:fs/promises"; +import { join, extname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { dirname } from "node:path"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(__dirname, ".."); + +// IMPORTANT : ordre du plus long au plus court pour éviter les collisions +// (ex: --mmg-text-1 doit matcher AVANT --mmg-text-). +const MAPPINGS = [ + // — Texte (couleur) — longest first —————————— + ["--mmg-text-inverse", "--mmg-color-text-inverse"], + ["--mmg-text-1", "--mmg-color-text-primary"], + ["--mmg-text-2", "--mmg-color-text-secondary"], + ["--mmg-text-3", "--mmg-color-text-tertiary"], + ["--mmg-text-4", "--mmg-color-text-quaternary"], + + // — Texte (font-size) — distincts —————————— + ["--mmg-text-xs", "--mmg-font-size-xs"], + ["--mmg-text-sm", "--mmg-font-size-sm"], + ["--mmg-text-base", "--mmg-font-size-base"], + ["--mmg-text-lg", "--mmg-font-size-lg"], + ["--mmg-text-xl", "--mmg-font-size-xl"], + ["--mmg-text-2xl", "--mmg-font-size-2xl"], + ["--mmg-text-3xl", "--mmg-font-size-3xl"], + ["--mmg-text-4xl", "--mmg-font-size-4xl"], + ["--mmg-text-5xl", "--mmg-font-size-5xl"], + + // — Background —————————— + ["--mmg-bg-page", "--mmg-color-bg-page"], + ["--mmg-bg-surface", "--mmg-color-bg-surface"], + ["--mmg-bg-raised", "--mmg-color-bg-raised"], + ["--mmg-bg-muted", "--mmg-color-bg-muted"], + ["--mmg-bg-subtle", "--mmg-color-bg-subtle"], + ["--mmg-bg-overlay", "--mmg-color-bg-overlay"], + + // — Border —————————— + ["--mmg-border-soft", "--mmg-color-border-soft"], + ["--mmg-border-strong", "--mmg-color-border-strong"], + ["--mmg-border", "--mmg-color-border"], + + // — Brand → Accent —————————— + ["--mmg-brand-hover", "--mmg-color-accent-hover"], + ["--mmg-brand-active", "--mmg-color-accent-active"], + ["--mmg-brand-soft", "--mmg-color-accent-soft"], + ["--mmg-brand-border", "--mmg-color-accent-border"], + ["--mmg-brand-strong", "--mmg-color-accent-strong"], + ["--mmg-brand-on", "--mmg-color-accent-on"], + ["--mmg-brand", "--mmg-color-accent"], + + // — Semantic colors —————————— + ["--mmg-success-soft", "--mmg-color-success-soft"], + ["--mmg-success-border", "--mmg-color-success-border"], + ["--mmg-success-strong", "--mmg-color-success-strong"], + ["--mmg-success-on", "--mmg-color-success-on"], + ["--mmg-success", "--mmg-color-success"], + ["--mmg-warning-soft", "--mmg-color-warning-soft"], + ["--mmg-warning-border", "--mmg-color-warning-border"], + ["--mmg-warning-strong", "--mmg-color-warning-strong"], + ["--mmg-warning-on", "--mmg-color-warning-on"], + ["--mmg-warning", "--mmg-color-warning"], + ["--mmg-danger-soft", "--mmg-color-danger-soft"], + ["--mmg-danger-border", "--mmg-color-danger-border"], + ["--mmg-danger-strong", "--mmg-color-danger-strong"], + ["--mmg-danger-on", "--mmg-color-danger-on"], + ["--mmg-danger", "--mmg-color-danger"], + ["--mmg-info-soft", "--mmg-color-info-soft"], + ["--mmg-info-border", "--mmg-color-info-border"], + ["--mmg-info-strong", "--mmg-color-info-strong"], + ["--mmg-info-on", "--mmg-color-info-on"], + ["--mmg-info", "--mmg-color-info"], + + // — Artwork —————————— + ["--mmg-art-major", "--mmg-color-art-major"], + ["--mmg-art-minor", "--mmg-color-art-minor"], + ["--mmg-art-light", "--mmg-color-art-light"], + ["--mmg-art-dark", "--mmg-color-art-dark"], + ["--mmg-art-accent", "--mmg-color-art-accent"], + + // — État système —————————— + ["--mmg-state-disabled-bg", "--mmg-color-state-disabled-bg"], + ["--mmg-state-disabled-text", "--mmg-color-state-disabled-text"], + ["--mmg-state-disabled-border", "--mmg-color-state-disabled-border"], + ["--mmg-state-selection-bg", "--mmg-color-state-selection-bg"], + ["--mmg-state-selection-text", "--mmg-color-state-selection-text"], + + // — Line height —————————— + ["--mmg-leading-tight", "--mmg-line-height-tight"], + ["--mmg-leading-snug", "--mmg-line-height-snug"], + ["--mmg-leading-normal", "--mmg-line-height-normal"], + + // — Font weight —————————— + ["--mmg-weight-regular", "--mmg-font-weight-regular"], + ["--mmg-weight-medium", "--mmg-font-weight-medium"], + ["--mmg-weight-semi", "--mmg-font-weight-semi"], + ["--mmg-weight-bold", "--mmg-font-weight-bold"], + ["--mmg-weight-extra", "--mmg-font-weight-extra"], + + // — Shadow accent —————————— + ["--mmg-shadow-brand-hover", "--mmg-shadow-accent-hover"], + ["--mmg-shadow-brand-soft", "--mmg-shadow-accent-soft"], + ["--mmg-shadow-brand", "--mmg-shadow-accent"], +]; + +// Cibles : tous les .css et .tsx hors node_modules / dist / tokens (déjà OK) +const TARGET_DIRS = [ + "packages/css/src/components", + "packages/css/src", // pour base.css uniquement, on filtre tokens via skip + "packages/react/src", + "demo/src", +]; +const SKIP_FILES = new Set([ + // Les nouveaux tokens sont déjà à la nouvelle nomenclature. + "tokens.css", + "primitives.css", + "semantic.css", + "accent.css", + "system.css", +]); +const EXTS = new Set([".css", ".tsx", ".ts"]); + +async function* walk(dir) { + const entries = await readdir(dir, { withFileTypes: true }); + for (const e of entries) { + if (e.name === "node_modules" || e.name === "dist") continue; + const full = join(dir, e.name); + if (e.isDirectory()) yield* walk(full); + else yield full; + } +} + +function migrate(content) { + let out = content; + let count = 0; + for (const [from, to] of MAPPINGS) { + // Word-boundary safe : --mmg-brand ne doit PAS matcher dans --mmg-brand-soft. + // Comme MAPPINGS est trié longest-first, lorsque --mmg-brand est traité, + // les longs ont déjà été remplacés. Mais on ajoute un lookahead négatif + // pour les caractères pouvant prolonger un identifiant CSS (-, lettre, chiffre). + const re = new RegExp(escape(from) + "(?![\\w-])", "g"); + const matches = out.match(re); + if (matches) { + count += matches.length; + out = out.replace(re, to); + } + } + return { out, count }; +} + +function escape(s) { + return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +async function main() { + let totalReplacements = 0; + let touched = 0; + for (const rel of TARGET_DIRS) { + const dir = join(ROOT, rel); + try { + await stat(dir); + } catch { + continue; + } + for await (const file of walk(dir)) { + const ext = extname(file); + if (!EXTS.has(ext)) continue; + const base = file.split(/[\\/]/).pop(); + if (SKIP_FILES.has(base)) continue; + const content = await readFile(file, "utf8"); + const { out, count } = migrate(content); + if (count > 0) { + await writeFile(file, out, "utf8"); + touched += 1; + totalReplacements += count; + console.log(` ${count.toString().padStart(4)} ${file.replace(ROOT, "")}`); + } + } + } + console.log(`\n✓ ${totalReplacements} replacements across ${touched} files`); +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/storybook/.storybook/main.ts b/storybook/.storybook/main.ts new file mode 100644 index 0000000..2c36fa6 --- /dev/null +++ b/storybook/.storybook/main.ts @@ -0,0 +1,27 @@ +import type { StorybookConfig } from "@storybook/react-vite"; + +const config: StorybookConfig = { + stories: ["../stories/**/*.mdx", "../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)"], + addons: [ + "@storybook/addon-essentials", + "@storybook/addon-interactions", + "@storybook/addon-a11y", + ], + framework: { + name: "@storybook/react-vite", + options: {}, + }, + docs: { + autodocs: "tag", + }, + typescript: { + reactDocgen: "react-docgen-typescript", + reactDocgenTypescriptOptions: { + shouldExtractLiteralValuesFromEnum: true, + propFilter: (prop) => + prop.parent ? !/node_modules/.test(prop.parent.fileName) : true, + }, + }, + staticDirs: ["../public"], +}; +export default config; diff --git a/storybook/.storybook/preview.css b/storybook/.storybook/preview.css new file mode 100644 index 0000000..9d8c3a4 --- /dev/null +++ b/storybook/.storybook/preview.css @@ -0,0 +1,3 @@ +/* Override le fond Storybook pour utiliser nos tokens */ +body { font-family: var(--mmg-font-sans); } +.docs-story { background: var(--mmg-color-bg-page); } diff --git a/storybook/.storybook/preview.ts b/storybook/.storybook/preview.ts new file mode 100644 index 0000000..fb3f3cd --- /dev/null +++ b/storybook/.storybook/preview.ts @@ -0,0 +1,126 @@ +import type { Preview } from "@storybook/react"; +import "@managemate/css"; +import "@managemate/icons"; +import "./preview.css"; + +const preview: Preview = { + parameters: { + layout: "padded", + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + backgrounds: { + default: "page", + values: [ + { name: "page", value: "var(--mmg-color-bg-page)" }, + { name: "surface", value: "var(--mmg-color-bg-surface)" }, + { name: "white", value: "#FFFFFF" }, + { name: "dark", value: "#0B0D14" }, + ], + }, + a11y: { + // axe-core configuration. WCAG 2.1 AA + RGAA tags. + config: { + rules: [ + { id: "color-contrast", enabled: true }, + { id: "label", enabled: true }, + { id: "button-name", enabled: true }, + ], + }, + options: { + runOnly: { + type: "tag", + values: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "best-practice"], + }, + }, + }, + options: { + storySort: { + order: [ + "Intro", + "Tokens", + ["Colors", "Spacing", "Typography", "Shadows", "Motion"], + "Layout", + "Forms", + ["Button", "Input", "Select", "Checkbox", "Radio", "Switch"], + "Feedback", + "Overlays", + "Navigation", + "Data display", + "Advanced", + "Theming", + ], + }, + }, + }, + globalTypes: { + theme: { + description: "Thème global", + defaultValue: "light", + toolbar: { + title: "Thème", + icon: "circlehollow", + items: [ + { value: "light", title: "Light" }, + { value: "dark", title: "Dark" }, + { value: "system", title: "Système" }, + ], + dynamicTitle: true, + }, + }, + accent: { + description: "Couleur d'accent (preset DSMMG)", + defaultValue: "synapse", + toolbar: { + title: "Accent", + icon: "paintbrush", + items: [ + { value: "synapse", title: "Synapse (rose)" }, + { value: "rose", title: "Rose vif" }, + { value: "blue", title: "Bleu" }, + { value: "violet", title: "Violet" }, + { value: "green", title: "Vert" }, + { value: "amber", title: "Ambre" }, + { value: "red", title: "Rouge" }, + { value: "cyan", title: "Cyan" }, + { value: "slate", title: "Ardoise" }, + ], + dynamicTitle: true, + }, + }, + density: { + description: "Densité", + defaultValue: "comfortable", + toolbar: { + title: "Densité", + icon: "component", + items: [ + { value: "comfortable", title: "Comfortable" }, + { value: "cozy", title: "Cozy" }, + { value: "compact", title: "Compact" }, + ], + dynamicTitle: true, + }, + }, + }, + decorators: [ + (Story, ctx) => { + const root = document.documentElement; + // Theme + if (ctx.globals.theme === "system") root.removeAttribute("data-mmg-theme"); + else root.setAttribute("data-mmg-theme", ctx.globals.theme); + // Accent + if (ctx.globals.accent === "synapse") root.removeAttribute("data-mmg-accent"); + else root.setAttribute("data-mmg-accent", ctx.globals.accent); + // Density + if (ctx.globals.density === "comfortable") root.removeAttribute("data-mmg-density"); + else root.setAttribute("data-mmg-density", ctx.globals.density); + return Story(); + }, + ], +}; + +export default preview; diff --git a/storybook/package.json b/storybook/package.json new file mode 100644 index 0000000..7e66bcb --- /dev/null +++ b/storybook/package.json @@ -0,0 +1,33 @@ +{ + "name": "storybook", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "storybook dev -p 6006", + "build": "storybook build", + "preview": "vite preview --outDir storybook-static" + }, + "dependencies": { + "@managemate/css": "workspace:*", + "@managemate/icons": "workspace:*", + "@managemate/react": "workspace:*", + "react": "^19.2.5", + "react-dom": "^19.2.5" + }, + "devDependencies": { + "@storybook/addon-a11y": "^8.5.0", + "@storybook/addon-essentials": "^8.5.0", + "@storybook/addon-interactions": "^8.5.0", + "@storybook/blocks": "^8.5.0", + "@storybook/react": "^8.5.0", + "@storybook/react-vite": "^8.5.0", + "@storybook/test": "^8.5.0", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^4.3.4", + "storybook": "^8.5.0", + "typescript": "~5.7.0", + "vite": "^5.4.11" + } +} diff --git a/storybook/stories/Button.stories.tsx b/storybook/stories/Button.stories.tsx new file mode 100644 index 0000000..c3bd02c --- /dev/null +++ b/storybook/stories/Button.stories.tsx @@ -0,0 +1,79 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Button } from "@managemate/react"; + +const meta = { + title: "Forms/Button", + component: Button, + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: + "Bouton DSMMG avec variants Material 3 / Fluent. Pill par défaut. Tous les états (default, hover, active, focus-visible, disabled, loading) sont stylés. Touch target 44×44 garanti pour `icon-only`.", + }, + }, + }, + argTypes: { + variant: { + control: "select", + options: ["primary", "tonal", "secondary", "tertiary", "ghost", "elevated", "danger", "success"], + }, + size: { control: "select", options: ["xs", "sm", "md", "lg", "xl"] }, + loading: { control: "boolean" }, + disabled: { control: "boolean" }, + block: { control: "boolean" }, + }, + args: { children: "Continuer", variant: "primary", size: "md" }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = {}; + +export const Tonal: Story = { args: { variant: "tonal" } }; +export const Secondary: Story = { args: { variant: "secondary" } }; +export const Tertiary: Story = { args: { variant: "tertiary" } }; +export const Ghost: Story = { args: { variant: "ghost" } }; +export const Elevated: Story = { args: { variant: "elevated" } }; +export const Danger: Story = { args: { variant: "danger", children: "Supprimer" } }; +export const Success: Story = { args: { variant: "success", children: "Valider" } }; + +export const Loading: Story = { args: { loading: true } }; +export const Disabled: Story = { args: { disabled: true } }; +export const Block: Story = { args: { block: true } }; + +export const WithIcon: Story = { + args: { icon: "arrow-right-line", iconPosition: "right" }, +}; + +export const IconOnly: Story = { + args: { icon: "settings-3-line", "aria-label": "Paramètres", children: undefined }, +}; + +export const AllSizes: Story = { + render: (args) => ( +
+ + + + + +
+ ), +}; + +export const AllVariants: Story = { + render: () => ( +
+ + + + + + + + +
+ ), +}; diff --git a/storybook/stories/Combobox.stories.tsx b/storybook/stories/Combobox.stories.tsx new file mode 100644 index 0000000..4be393a --- /dev/null +++ b/storybook/stories/Combobox.stories.tsx @@ -0,0 +1,46 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { useState } from "react"; +import { Combobox } from "@managemate/react"; + +const meta = { + title: "Forms/Combobox", + component: Combobox, + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: + "Combobox WAI-ARIA 1.2 (combobox + listbox). Floating UI pour positionnement, aria-activedescendant pour le focus virtuel sur l'option courante.", + }, + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const COUNTRIES = [ + { value: "fr", label: "France" }, + { value: "be", label: "Belgique" }, + { value: "ch", label: "Suisse" }, + { value: "ca", label: "Canada" }, + { value: "lu", label: "Luxembourg" }, + { value: "ma", label: "Maroc" }, + { value: "tn", label: "Tunisie" }, + { value: "sn", label: "Sénégal" }, + { value: "ci", label: "Côte d'Ivoire" }, +]; + +export const Default: Story = { + render: () => { + const [val, setVal] = useState(); + return ( +
+ +

+ Sélectionné : {val ?? "—"} +

+
+ ); + }, +}; diff --git a/storybook/stories/Dialog.stories.tsx b/storybook/stories/Dialog.stories.tsx new file mode 100644 index 0000000..c1eb232 --- /dev/null +++ b/storybook/stories/Dialog.stories.tsx @@ -0,0 +1,64 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { useState } from "react"; +import { Dialog, ConfirmDialog, Button } from "@managemate/react"; + +const meta = { + title: "Overlays/Dialog", + component: Dialog, + tags: ["autodocs"], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => { + const [open, setOpen] = useState(false); + return ( + <> + + + + +

+ } + > +

Contenu du dialog…

+ + + ); + }, +}; + +export const Confirm: Story = { + name: "ConfirmDialog (destructive)", + render: () => { + const [open, setOpen] = useState(false); + return ( + <> + + alert("Confirmé")} + /> + + ); + }, +}; diff --git a/storybook/stories/Intro.mdx b/storybook/stories/Intro.mdx new file mode 100644 index 0000000..f1885ae --- /dev/null +++ b/storybook/stories/Intro.mdx @@ -0,0 +1,58 @@ +import { Meta } from "@storybook/blocks"; + + + +# DSMMG — Design System ManageMate Group + +Référence pour designers et développeurs des produits ManageMate (Synapse, HRTime, Forge, Orbit, MSLM, Espace-Client, sites publics). + +## Principes + +1. **Accessibilité non-négociable** — RGAA 4.1 / WCAG 2.2 AA, validé via axe-core en CI sur chaque composant. +2. **Headless-first** — comportement (focus, keyboard, ARIA) découplé du style. Primitives Radix UI / Floating UI dessous. +3. **Tokens partout** — aucun hex en dur, aucun `--mmg-color-synapse` direct. Tout passe par les sémantiques (`--mmg-color-text-primary`, `--mmg-color-bg-surface`) et l'accent (`--mmg-color-accent`). +4. **Tree-shakable** — un composant = un fichier. `sideEffects: false`. Les imports inutilisés sont droppés par les bundlers consommateurs. + +## Theming utilisateur + +Chaque utilisateur peut choisir son accent (rose Synapse par défaut). 9 presets validés AA : +- `synapse` (rose corporate, défaut) +- `rose`, `blue`, `violet`, `green`, `amber`, `red`, `cyan`, `slate` + +Le picker change en live ici (toolbar Storybook → "Accent"). Voir aussi le composant **``** dans `Theming`. + +## Density + +3 modes adaptables via `[data-mmg-density]` : +- `comfortable` (défaut, public) +- `cozy` (apps métier) +- `compact` (power users) + +## Standards + +- shadcn/ui + Radix UI (architecture, primitives a11y) +- Linear, Notion, Vercel, Stripe (références SaaS dense) +- DSFR (méthodologie a11y) +- Atlassian DS, IBM Carbon (apps enterprise) + +## Conventions de naming + +| Catégorie | Préfixe | +|---|---| +| Tokens couleur | `--mmg-color-*` | +| Tokens taille | `--mmg-space-*`, `--mmg-radius-*`, `--mmg-font-size-*` | +| Tokens motion | `--mmg-duration-*`, `--mmg-ease-*` | +| Classes CSS | `mmg-` | +| Classes utilitaires | `mmg-u-*` | +| Variantes BEM | `mmg---` | +| Sous-éléments BEM | `mmg-__` | + +## Navigation + +- **Tokens** — primitives, sémantiques, accent, motion +- **Forms** — Button, Input, Select, Checkbox, Radio, Switch, Combobox +- **Layout** — Container, Stack, Grid, Card, Tile +- **Overlays** — Tooltip, Popover, Menu, Dialog (tous Radix-backed) +- **Navigation** — Header, Footer, Breadcrumb, Tabs, Pagination, AppShell +- **Data display** — DataTable, Stat, Avatar, Tag, Badge, Progress +- **Theming** — ThemePicker, dark mode toggle diff --git a/storybook/stories/ThemePicker.stories.tsx b/storybook/stories/ThemePicker.stories.tsx new file mode 100644 index 0000000..38ea605 --- /dev/null +++ b/storybook/stories/ThemePicker.stories.tsx @@ -0,0 +1,43 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ThemePicker, Button, Card } from "@managemate/react"; + +const meta = { + title: "Theming/ThemePicker", + component: ThemePicker, + tags: ["autodocs"], + parameters: { + docs: { + description: { + component: + "Sélecteur de couleur d'accent utilisateur. Pattern radiogroup avec navigation flèches, persistance localStorage. 9 presets validés AA.", + }, + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => , +}; + +export const InCard: Story = { + render: () => ( + +

Préférences d'apparence

+

+ Choisissez la couleur d'accent qui vous convient. Cette préférence est sauvegardée localement. +

+ +
+ + +
+
+ ), +}; + +export const HiddenReset: Story = { + render: () => , +}; diff --git a/storybook/stories/Tokens.stories.tsx b/storybook/stories/Tokens.stories.tsx new file mode 100644 index 0000000..706db3c --- /dev/null +++ b/storybook/stories/Tokens.stories.tsx @@ -0,0 +1,160 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +const meta = { + title: "Tokens/Colors", + parameters: { + layout: "padded", + docs: { + description: { + component: + "Tokens couleur DSMMG. Les sémantiques se réfèrent aux primitives — c'est ce que les composants consomment. L'accent est user-themable via `[data-mmg-accent]`.", + }, + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const Swatch = ({ name, css }: { name: string; css: string }) => ( +
+
+
+ {css} +
+
{name}
+
+); + +const Grid = ({ children }: { children: React.ReactNode }) => ( +
+ {children} +
+); + +export const Surfaces: Story = { + render: () => ( + + + + + + + + ), +}; + +export const Borders: Story = { + render: () => ( + + + + + + ), +}; + +export const Text: Story = { + render: () => ( + + + + + + + ), +}; + +export const Accent: Story = { + render: () => ( + + + + + + + + + + ), +}; + +export const Semantic: Story = { + render: () => ( + <> +

Success

+ + + + + + +

Warning

+ + + + + + +

Danger

+ + + + + + +

Info

+ + + + + + + + ), +}; + +const palette = (name: string, label: string) => { + const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]; + return ( + <> +

{label}

+ + {shades.map((s) => ( + + ))} + + + ); +}; + +export const Palettes: Story = { + render: () => ( + <> + {palette("synapse", "Synapse (default)")} + {palette("rose", "Rose")} + {palette("blue", "Blue")} + {palette("violet", "Violet")} + {palette("green", "Green")} + {palette("amber", "Amber")} + {palette("red", "Red")} + {palette("cyan", "Cyan")} + {palette("slate", "Slate")} + + ), +}; diff --git a/storybook/stories/Tooltip.stories.tsx b/storybook/stories/Tooltip.stories.tsx new file mode 100644 index 0000000..e6be430 --- /dev/null +++ b/storybook/stories/Tooltip.stories.tsx @@ -0,0 +1,47 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Tooltip, TooltipProvider, Button } from "@managemate/react"; + +const meta = { + title: "Overlays/Tooltip", + component: Tooltip, + tags: ["autodocs"], + decorators: [ + (Story) => ( + + + + ), + ], + parameters: { + docs: { + description: { + component: + "Tooltip basé sur Radix UI. Auto-flip, focus management, Escape, prefers-reduced-motion. Exige `` à la racine.", + }, + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { content: "Action sécurisée" }, + render: (args) => ( + + + + ), +}; + +export const Placements: Story = { + render: () => ( +
+ {(["top", "right", "bottom", "left"] as const).map((p) => ( + + + + ))} +
+ ), +};