From 43fe76158c2cad6ae429a9cee43d0eae165be4d5 Mon Sep 17 00:00:00 2001 From: Tony James Date: Tue, 13 Oct 2026 22:16:21 +0100 Subject: [PATCH] Extract independent MIT Mortar kit and contribution workflow --- .gitea/workflows/check.yml | 22 + .gitignore | 7 + .prettierignore | 6 + AGENTS.md | 9 + CONTRIBUTING.md | 11 + DESIGN.md | 15 + LICENSE | 21 + README.md | 63 + baseline-policy.json | 11 + catalog.json | 1520 ++++++++++++ design-principles.json | 30 + manifests/mortar-action-link.json | 40 + manifests/mortar-activity-feed.json | 39 + manifests/mortar-app-shell.json | 45 + manifests/mortar-appearance-control.json | 36 + manifests/mortar-badge.json | 39 + manifests/mortar-button.json | 43 + manifests/mortar-call-to-action.json | 40 + manifests/mortar-checkbox.json | 40 + manifests/mortar-code-block.json | 39 + manifests/mortar-data-table.json | 49 + manifests/mortar-dropdown.json | 39 + manifests/mortar-empty-state.json | 40 + manifests/mortar-faq.json | 40 + manifests/mortar-feature-grid.json | 41 + manifests/mortar-feature-section.json | 41 + manifests/mortar-footer.json | 42 + manifests/mortar-hero.json | 44 + manifests/mortar-input.json | 44 + manifests/mortar-logo-cloud.json | 39 + manifests/mortar-marketing-header.json | 42 + manifests/mortar-metric-group.json | 39 + manifests/mortar-modal.json | 42 + manifests/mortar-notice.json | 41 + manifests/mortar-page-heading.json | 43 + manifests/mortar-pagination.json | 40 + manifests/mortar-preview-frame.json | 39 + manifests/mortar-pricing.json | 40 + manifests/mortar-radio-group.json | 42 + manifests/mortar-segmented-control.json | 41 + manifests/mortar-select.json | 43 + manifests/mortar-settings-section.json | 40 + manifests/mortar-switch.json | 40 + manifests/mortar-tabs.json | 41 + manifests/mortar-testimonial.json | 40 + manifests/mortar-text-area.json | 42 + manifests/mortar-theme-provider.json | 41 + package-lock.json | 2862 ++++++++++++++++++++++ package.json | 72 + playground/index.html | 12 + playground/main.tsx | 55 + playground/styles.css | 4 + playwright.config.mjs | 17 + previews/ActionLinkPreview.tsx | 4 + previews/ActivityFeedPreview.tsx | 4 + previews/AppShellPreview.tsx | 4 + previews/AppearanceControlPreview.tsx | 4 + previews/BadgePreview.tsx | 4 + previews/ButtonPreview.tsx | 4 + previews/CallToActionPreview.tsx | 4 + previews/CheckboxPreview.tsx | 4 + previews/CodeBlockPreview.tsx | 4 + previews/DataTablePreview.tsx | 4 + previews/DropdownPreview.tsx | 4 + previews/EmptyStatePreview.tsx | 4 + previews/FAQPreview.tsx | 4 + previews/FeatureGridPreview.tsx | 4 + previews/FeatureSectionPreview.tsx | 4 + previews/Fixture.tsx | 476 ++++ previews/FooterPreview.tsx | 4 + previews/HeroPreview.tsx | 4 + previews/InputPreview.tsx | 4 + previews/LogoCloudPreview.tsx | 4 + previews/MarketingHeaderPreview.tsx | 4 + previews/MetricGroupPreview.tsx | 4 + previews/ModalPreview.tsx | 4 + previews/NoticePreview.tsx | 4 + previews/PageHeadingPreview.tsx | 4 + previews/PaginationPreview.tsx | 4 + previews/PreviewFramePreview.tsx | 4 + previews/PricingPreview.tsx | 4 + previews/RadioGroupPreview.tsx | 4 + previews/SegmentedControlPreview.tsx | 4 + previews/SelectPreview.tsx | 4 + previews/SettingsSectionPreview.tsx | 4 + previews/SwitchPreview.tsx | 4 + previews/TabsPreview.tsx | 4 + previews/TestimonialPreview.tsx | 4 + previews/TextAreaPreview.tsx | 4 + previews/ThemeProviderPreview.tsx | 4 + scripts/check.mjs | 172 ++ scripts/release.mjs | 46 + src/application.tsx | 418 ++++ src/components.css | 1289 ++++++++++ src/foundation.tsx | 99 + src/index.ts | 57 + src/inspection.tsx | 59 + src/marketing.tsx | 342 +++ src/primitives.tsx | 429 ++++ src/tokens.css | 90 + styles.css | 15 + tests/baseline.test.mjs | 44 + tests/browser/components.spec.mjs | 33 + tests/browser/interactions.spec.mjs | 54 + tests/controls.test.mjs | 63 + tsconfig.json | 14 + tsconfig.playground.json | 15 + vite.config.ts | 9 + 108 files changed, 10081 insertions(+) create mode 100644 .gitea/workflows/check.yml create mode 100644 .gitignore create mode 100644 .prettierignore create mode 100644 AGENTS.md create mode 100644 CONTRIBUTING.md create mode 100644 DESIGN.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 baseline-policy.json create mode 100644 catalog.json create mode 100644 design-principles.json create mode 100644 manifests/mortar-action-link.json create mode 100644 manifests/mortar-activity-feed.json create mode 100644 manifests/mortar-app-shell.json create mode 100644 manifests/mortar-appearance-control.json create mode 100644 manifests/mortar-badge.json create mode 100644 manifests/mortar-button.json create mode 100644 manifests/mortar-call-to-action.json create mode 100644 manifests/mortar-checkbox.json create mode 100644 manifests/mortar-code-block.json create mode 100644 manifests/mortar-data-table.json create mode 100644 manifests/mortar-dropdown.json create mode 100644 manifests/mortar-empty-state.json create mode 100644 manifests/mortar-faq.json create mode 100644 manifests/mortar-feature-grid.json create mode 100644 manifests/mortar-feature-section.json create mode 100644 manifests/mortar-footer.json create mode 100644 manifests/mortar-hero.json create mode 100644 manifests/mortar-input.json create mode 100644 manifests/mortar-logo-cloud.json create mode 100644 manifests/mortar-marketing-header.json create mode 100644 manifests/mortar-metric-group.json create mode 100644 manifests/mortar-modal.json create mode 100644 manifests/mortar-notice.json create mode 100644 manifests/mortar-page-heading.json create mode 100644 manifests/mortar-pagination.json create mode 100644 manifests/mortar-preview-frame.json create mode 100644 manifests/mortar-pricing.json create mode 100644 manifests/mortar-radio-group.json create mode 100644 manifests/mortar-segmented-control.json create mode 100644 manifests/mortar-select.json create mode 100644 manifests/mortar-settings-section.json create mode 100644 manifests/mortar-switch.json create mode 100644 manifests/mortar-tabs.json create mode 100644 manifests/mortar-testimonial.json create mode 100644 manifests/mortar-text-area.json create mode 100644 manifests/mortar-theme-provider.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 playground/index.html create mode 100644 playground/main.tsx create mode 100644 playground/styles.css create mode 100644 playwright.config.mjs create mode 100644 previews/ActionLinkPreview.tsx create mode 100644 previews/ActivityFeedPreview.tsx create mode 100644 previews/AppShellPreview.tsx create mode 100644 previews/AppearanceControlPreview.tsx create mode 100644 previews/BadgePreview.tsx create mode 100644 previews/ButtonPreview.tsx create mode 100644 previews/CallToActionPreview.tsx create mode 100644 previews/CheckboxPreview.tsx create mode 100644 previews/CodeBlockPreview.tsx create mode 100644 previews/DataTablePreview.tsx create mode 100644 previews/DropdownPreview.tsx create mode 100644 previews/EmptyStatePreview.tsx create mode 100644 previews/FAQPreview.tsx create mode 100644 previews/FeatureGridPreview.tsx create mode 100644 previews/FeatureSectionPreview.tsx create mode 100644 previews/Fixture.tsx create mode 100644 previews/FooterPreview.tsx create mode 100644 previews/HeroPreview.tsx create mode 100644 previews/InputPreview.tsx create mode 100644 previews/LogoCloudPreview.tsx create mode 100644 previews/MarketingHeaderPreview.tsx create mode 100644 previews/MetricGroupPreview.tsx create mode 100644 previews/ModalPreview.tsx create mode 100644 previews/NoticePreview.tsx create mode 100644 previews/PageHeadingPreview.tsx create mode 100644 previews/PaginationPreview.tsx create mode 100644 previews/PreviewFramePreview.tsx create mode 100644 previews/PricingPreview.tsx create mode 100644 previews/RadioGroupPreview.tsx create mode 100644 previews/SegmentedControlPreview.tsx create mode 100644 previews/SelectPreview.tsx create mode 100644 previews/SettingsSectionPreview.tsx create mode 100644 previews/SwitchPreview.tsx create mode 100644 previews/TabsPreview.tsx create mode 100644 previews/TestimonialPreview.tsx create mode 100644 previews/TextAreaPreview.tsx create mode 100644 previews/ThemeProviderPreview.tsx create mode 100644 scripts/check.mjs create mode 100644 scripts/release.mjs create mode 100644 src/application.tsx create mode 100644 src/components.css create mode 100644 src/foundation.tsx create mode 100644 src/index.ts create mode 100644 src/inspection.tsx create mode 100644 src/marketing.tsx create mode 100644 src/primitives.tsx create mode 100644 src/tokens.css create mode 100644 styles.css create mode 100644 tests/baseline.test.mjs create mode 100644 tests/browser/components.spec.mjs create mode 100644 tests/browser/interactions.spec.mjs create mode 100644 tests/controls.test.mjs create mode 100644 tsconfig.json create mode 100644 tsconfig.playground.json create mode 100644 vite.config.ts diff --git a/.gitea/workflows/check.yml b/.gitea/workflows/check.yml new file mode 100644 index 0000000..b0a122f --- /dev/null +++ b/.gitea/workflows/check.yml @@ -0,0 +1,22 @@ +name: Mortar contribution checks +on: + push: + branches: [main, "codex/**"] + pull_request: + branches: [main] +jobs: + quality: + name: Mortar baseline and browser checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: actions/setup-node@v4 + with: + node-version: "22" + - run: npm ci --ignore-scripts + - run: npm run check + - run: npx playwright install --with-deps chromium + - run: npm run test:browser +# No package-publishing or cloud-governance credentials belong in this workflow. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a23c384 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +playground-dist/ +release/ +test-results/ +playwright-report/ +*.tgz diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..892d767 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +node_modules +dist +playground-dist +release +test-results +playwright-report diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..13953d6 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,9 @@ +# Contributing to Mortar + +Mortar is a public MIT kit. You can develop, preview and check it without any governance-service account. + +Read DESIGN.md before composing UI. Implement reusable components in src, previews in previews, and typed component contracts in manifests. Shells and chrome are shared components, not copies in consumer apps. Product data and actions belong in props and slots. + +Run npm ci, npm run catalog, npm run check and npm run test:browser. npm run check:json returns baseline rule IDs, files, lines and corrective messages. npm run dev opens the local playground. Update manifests when changing exports. Include a regression test for a bug fix. Never mark yourself approved, publish a release, or change protected CI rules to make a contribution pass. + +Open a PR with rationale, screenshots and actual check results. Maintainer review and protected final-commit CI precede releases. Baseline checks are not proof of visual quality; inspect desktop/mobile, light/dark, keyboard and focus states. Shared design changes require central fixes, not local overrides. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..8aed47c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contribute + +Clone, run npm ci, npm run catalog, npm run check, npm run dev. Use npm run test:browser for both-theme accessibility/rendering checks. The local playground defaults to port 4340. No service registration or npm token is required. + +Use src for central implementations, previews for fixtures and manifests for contracts. Read DESIGN.md and AGENTS.md. Include a reproducible issue and a regression test for fixes. Open a PR with actual check results and visual evidence. Shared shells are versioned alongside controls; applications supply content through props. + +Baseline rules are versioned in baseline-policy.json. CI must use the same rules but contributors cannot authorize weakening protected checks; policy, workflow and dependency changes require maintainer review. Branch protection must require successful checks and dismiss approvals when reviewed content changes. Public PR runners must be isolated from release credentials and production networks. + +Releases are operator-owned. Verify the final merged commit, run all checks, create an immutable version tag, and prepare the exact package using npm run release:prepare. Upload archives and integrity/provenance records before atomically advancing registry metadata. Never overwrite an existing version. The publisher must verify maintainer approval and successful final-commit CI independently. Publication does not call the paid service; ARC indexes published release manifests afterward. + +The cloud service may impose additional organisation adoption policies. Those policies cannot prevent development or installation of the public MIT kit. diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..042067d --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,15 @@ +# Mortar design principles + +1. **shell-first** — Choose the shared purpose shell before composing a page. Use AppShell for application screens and MarketingHeader for public pages. Document deliberate standalone exceptions. + +2. **page-pattern-reuse** — Reuse complete page patterns: navigation, headings, filters, list/detail workspaces, states and action placement. Reusing controls alone is insufficient. + +3. **project-agnostic-chrome** — Keep product names, routes, user data, permissions and actions in props and slots. Shared chrome must remain project agnostic. + +4. **central-fixes** — Contribute missing patterns centrally. Do not duplicate source, create repeated local wrappers or apply consumer CSS overrides. + +5. **semantic-themes** — Use semantic tokens; keep brand separate from appearance and feedback colours. Verify every supported theme. + +6. **interaction-quality** — Verify responsive layout, accessible names, keyboard operation, focus and loading/empty/error states. Automated checks alone cannot prove visual quality. + +The machine-readable contract is design-principles.json. Both the local contribution workflow and hosted MCP should expose these principles. Detection is split between structural checks and visual maintainer review. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..03bc1df --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Tony James and Mortar contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e4e8b72 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# Mortar + +A shared design foundation and purpose-built Application UI and Marketing UI kits for React 19 and Tailwind CSS 4. MIT licensed. No account, token, registry connection or subscription is required to use the kit, including use by coding agents. + +The package is `@tony-ui/mortar`, distributed from owner-hosted infrastructure. Releases are immutable and publicly downloadable without a service account. First publication is pending protected release verification. + +## Install + +After public release: + +```sh +npm config set @tony-ui:registry https://git.tony.codes/api/packages/tony/npm/ --location=project +npm install @tony-ui/mortar react react-dom tailwindcss +``` + +No UI service credential is needed. + +## Local install + +Build and pack from this workspace: + +```sh +npm run build +npm pack +``` + +Install the resulting `tony-ui-mortar-0.1.0.tgz` in the consuming app, with React 19, React DOM 19 and Tailwind 4. Public releases use https://git.tony.codes/api/packages/tony/npm/. + +In the app's Tailwind CSS entry: + +```css +@import "tailwindcss"; +@import "@tony-ui/mortar/styles.css"; +``` + +The package ships its component styles. Standalone use requires no source scanning or hosted account. The separately governed hosted workflow currently also requires `@source '../node_modules/@tony-ui/mortar/src';` in the CSS entry; generated agent starters include that policy declaration. + +```tsx +import { ThemeProvider, AppShell, Button } from "@tony-ui/mortar"; + + + + + +; +``` + +`brand` (`neutral | green`) and `density` (`compact | comfortable | spacious`) are controlled provider props. Appearance (`light | dark | system`) is changed using `AppearanceControl`; system changes are observed. Use one root provider. It restores document attributes on unmount. The provider uses effects: SSR applications should set matching initial document attributes to prevent a first-paint theme flash. + +## Purpose kits + +The catalogue assigns each export to one purpose. Foundation primitives serve both purpose kits. Application UI provides shells, page headings, metrics, selectable tables, settings and activity. Marketing UI provides headers, heroes, features, social proof, pricing, FAQs, calls to action and footers. Product content and callbacks remain in the consumer. Sample names and prices belong only in the catalogue demonstrations. + +Controls use native HTML and Headless UI. Tabs support arrow/Home/End navigation; dialogs and menus use Headless UI focus management. Density has a 44px control floor on coarse pointers. Feedback colours remain separate from the brand. + +## Hosted services + +Mortar Cloud's registry, agent discovery, approvals, audit and managed release workflow are separate proprietary hosted services. Payment buys service access, not permission to use the MIT components. The kit performs no network requests and contains no licence check or telemetry. + +This licence covers this package only. The central service, repository history, design reference documents, candidate fixtures and catalogue application are excluded from the public package. diff --git a/baseline-policy.json b/baseline-policy.json new file mode 100644 index 0000000..e56f24e --- /dev/null +++ b/baseline-policy.json @@ -0,0 +1,11 @@ +{ + "schemaVersion": 1, + "version": "1.0.0", + "rules": { + "M001": "Exports require unique manifests and preview fixtures", + "M002": "Source and preview paths stay inside the repository", + "M003": "Dependencies reference known component IDs", + "M004": "Shared components cannot depend on hosted services", + "M005": "Component implementations use semantic colour tokens" + } +} diff --git a/catalog.json b/catalog.json new file mode 100644 index 0000000..b21c51f --- /dev/null +++ b/catalog.json @@ -0,0 +1,1520 @@ +{ + "schemaVersion": 1, + "package": "@tony-ui/mortar", + "version": "0.1.0", + "policyVersion": "1.0.0", + "components": [ + { + "id": "mortar-action-link", + "logicalId": "action-link", + "name": "ActionLink", + "description": "Mortar foundation action link, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "ActionLink", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "href": "string", + "variant": "primary | secondary | ghost | danger" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { ActionLink } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ActionLinkPreview.tsx" + } + }, + { + "id": "mortar-activity-feed", + "logicalId": "activity-feed", + "name": "ActivityFeed", + "description": "Mortar application activity feed, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "ActivityFeed", + "source": "src/application.tsx", + "capabilities": ["theme", "application", "status"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "label": "string", + "items": "{ id: string; title: string; description?: string; time: string; tone?: Tone }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { ActivityFeed } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ActivityFeedPreview.tsx" + } + }, + { + "id": "mortar-app-shell", + "logicalId": "app-shell", + "name": "AppShell", + "description": "Mortar application app shell, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "AppShell", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "brand": "string", + "workspace": "string", + "navigation": "NavigationItem[]", + "secondaryNavigation": "{ label: string; items: NavigationItem[] }[]", + "user": "ReactNode", + "header": "ReactNode", + "actions": "ReactNode", + "children": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { AppShell } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button"] + }, + "preview": { + "source": "previews/AppShellPreview.tsx" + } + }, + { + "id": "mortar-appearance-control", + "logicalId": "appearance-control", + "name": "AppearanceControl", + "description": "Mortar foundation appearance control, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "AppearanceControl", + "source": "src/foundation.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": {}, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { AppearanceControl } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-theme-provider"] + }, + "preview": { + "source": "previews/AppearanceControlPreview.tsx" + } + }, + { + "id": "mortar-badge", + "logicalId": "badge", + "name": "Badge", + "description": "Mortar foundation badge, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Badge", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "status"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "children": "ReactNode", + "tone": "neutral | success | warning | danger" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Badge } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/BadgePreview.tsx" + } + }, + { + "id": "mortar-button", + "logicalId": "button", + "name": "Button", + "description": "Mortar foundation button, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Button", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "children": "ReactNode", + "variant": "primary | secondary | ghost | danger", + "loading": "boolean", + "disabled": "boolean", + "type": "button | submit | reset", + "onClick": "MouseEventHandler" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Button } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ButtonPreview.tsx" + } + }, + { + "id": "mortar-call-to-action", + "logicalId": "call-to-action", + "name": "CallToAction", + "description": "Mortar marketing call to action, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "CallToAction", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "actions": "LinkAction[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { CallToAction } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-action-link"] + }, + "preview": { + "source": "previews/CallToActionPreview.tsx" + } + }, + { + "id": "mortar-checkbox", + "logicalId": "checkbox", + "name": "Checkbox", + "description": "Mortar foundation checkbox, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Checkbox", + "source": "src/primitives.tsx", + "capabilities": [ + "theme", + "foundation", + "input", + "validation", + "keyboard" + ], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "checked": "boolean", + "onChange": "ChangeEventHandler" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Checkbox } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/CheckboxPreview.tsx" + } + }, + { + "id": "mortar-code-block", + "logicalId": "code-block", + "name": "CodeBlock", + "description": "Mortar application code block, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "CodeBlock", + "source": "src/inspection.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "code": "string", + "label": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { CodeBlock } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/CodeBlockPreview.tsx" + } + }, + { + "id": "mortar-data-table", + "logicalId": "data-table", + "name": "DataTable", + "description": "Mortar application data table, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "DataTable", + "source": "src/application.tsx", + "capabilities": ["theme", "application", "table"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "caption": "string", + "columns": "{ key: string; label: string; render: (row: T) => ReactNode; align?: left | right }[]", + "rows": "T[] where T extends { id: string }", + "rowLabel": "(row: T) => string", + "selectedIds": "string[]", + "onSelectionChange": "(ids: string[]) => void", + "toolbar": "ReactNode", + "bulkActions": "ReactNode", + "loading": "boolean", + "error": "string", + "emptyTitle": "string", + "emptyDescription": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { DataTable } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button", "mortar-empty-state", "mortar-notice"] + }, + "preview": { + "source": "previews/DataTablePreview.tsx" + } + }, + { + "id": "mortar-dropdown", + "logicalId": "dropdown", + "name": "Dropdown", + "description": "Mortar foundation dropdown, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Dropdown", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "items": "{ label: string; onSelect: () => void; danger?: boolean; disabled?: boolean }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Dropdown } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/DropdownPreview.tsx" + } + }, + { + "id": "mortar-empty-state", + "logicalId": "empty-state", + "name": "EmptyState", + "description": "Mortar foundation empty state, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "EmptyState", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "action": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { EmptyState } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/EmptyStatePreview.tsx" + } + }, + { + "id": "mortar-faq", + "logicalId": "faq", + "name": "FAQ", + "description": "Mortar marketing faq, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "FAQ", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "ReactNode", + "items": "{ question: string; answer: ReactNode }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { FAQ } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FAQPreview.tsx" + } + }, + { + "id": "mortar-feature-grid", + "logicalId": "feature-grid", + "name": "FeatureGrid", + "description": "Mortar marketing feature grid, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "FeatureGrid", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "eyebrow": "string", + "description": "string", + "items": "{ title: string; description: string; icon?: ReactNode }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { FeatureGrid } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FeatureGridPreview.tsx" + } + }, + { + "id": "mortar-feature-section", + "logicalId": "feature-section", + "name": "FeatureSection", + "description": "Mortar marketing feature section, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "FeatureSection", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "children": "ReactNode", + "reverse": "boolean" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { FeatureSection } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FeatureSectionPreview.tsx" + } + }, + { + "id": "mortar-footer", + "logicalId": "footer", + "name": "Footer", + "description": "Mortar marketing footer, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Footer", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "brand": "string", + "description": "string", + "columns": "{ title: string; links: LinkAction[] }[]", + "copyright": "string", + "legal": "LinkAction[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Footer } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FooterPreview.tsx" + } + }, + { + "id": "mortar-hero", + "logicalId": "hero", + "name": "Hero", + "description": "Mortar marketing hero, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Hero", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "eyebrow": "string", + "title": "string", + "description": "string", + "actions": "LinkAction[]", + "children": "ReactNode", + "align": "center | split", + "headingLevel": "1 | 2" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Hero } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-action-link"] + }, + "preview": { + "source": "previews/HeroPreview.tsx" + } + }, + { + "id": "mortar-input", + "logicalId": "input", + "name": "Input", + "description": "Mortar foundation input, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Input", + "source": "src/primitives.tsx", + "capabilities": [ + "theme", + "foundation", + "input", + "validation", + "keyboard" + ], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string | number", + "onChange": "ChangeEventHandler", + "hint": "string", + "error": "string", + "prefix": "string", + "suffix": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Input } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/InputPreview.tsx" + } + }, + { + "id": "mortar-logo-cloud", + "logicalId": "logo-cloud", + "name": "LogoCloud", + "description": "Mortar marketing logo cloud, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "LogoCloud", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "label": "string", + "items": "{ name: string; image?: string }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { LogoCloud } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/LogoCloudPreview.tsx" + } + }, + { + "id": "mortar-marketing-header", + "logicalId": "marketing-header", + "name": "MarketingHeader", + "description": "Mortar marketing marketing header, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "MarketingHeader", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "brand": "string", + "homeHref": "string", + "links": "LinkAction[]", + "action": "LinkAction", + "controls": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { MarketingHeader } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button", "mortar-action-link"] + }, + "preview": { + "source": "previews/MarketingHeaderPreview.tsx" + } + }, + { + "id": "mortar-metric-group", + "logicalId": "metric-group", + "name": "MetricGroup", + "description": "Mortar application metric group, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "MetricGroup", + "source": "src/application.tsx", + "capabilities": ["theme", "application", "summary"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "label": "string", + "items": "{ label: string; value: string; change?: string; tone?: Tone }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { MetricGroup } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/MetricGroupPreview.tsx" + } + }, + { + "id": "mortar-modal", + "logicalId": "modal", + "name": "Modal", + "description": "Mortar foundation modal, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Modal", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "title": "string", + "open": "boolean", + "onClose": "() => void", + "children": "ReactNode", + "actions": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Modal } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button"] + }, + "preview": { + "source": "previews/ModalPreview.tsx" + } + }, + { + "id": "mortar-notice", + "logicalId": "notice", + "name": "Notice", + "description": "Mortar foundation notice, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Notice", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "status"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "title": "string", + "children": "ReactNode", + "tone": "neutral | success | warning | danger", + "announce": "boolean" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Notice } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/NoticePreview.tsx" + } + }, + { + "id": "mortar-page-heading", + "logicalId": "page-heading", + "name": "PageHeading", + "description": "Mortar application page heading, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "PageHeading", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "eyebrow": "string", + "actions": "ReactNode", + "breadcrumbs": "{ label: string; href?: string }[]", + "headingLevel": "1 | 2" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { PageHeading } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/PageHeadingPreview.tsx" + } + }, + { + "id": "mortar-pagination", + "logicalId": "pagination", + "name": "Pagination", + "description": "Mortar application pagination, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Pagination", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "page": "number", + "pageCount": "number", + "onChange": "(page: number) => void" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Pagination } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button"] + }, + "preview": { + "source": "previews/PaginationPreview.tsx" + } + }, + { + "id": "mortar-preview-frame", + "logicalId": "preview-frame", + "name": "PreviewFrame", + "description": "Mortar application preview frame, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "PreviewFrame", + "source": "src/inspection.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "title": "string", + "src": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { PreviewFrame } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/PreviewFramePreview.tsx" + } + }, + { + "id": "mortar-pricing", + "logicalId": "pricing", + "name": "Pricing", + "description": "Mortar marketing pricing, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Pricing", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "plans": "PricingPlan[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Pricing } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-action-link"] + }, + "preview": { + "source": "previews/PricingPreview.tsx" + } + }, + { + "id": "mortar-radio-group", + "logicalId": "radio-group", + "name": "RadioGroup", + "description": "Mortar foundation radio group, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "RadioGroup", + "source": "src/primitives.tsx", + "capabilities": [ + "theme", + "foundation", + "input", + "validation", + "keyboard" + ], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "name": "string", + "value": "string", + "onChange": "(value: string) => void", + "options": "{ value: string; label: string; description?: string }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { RadioGroup } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/RadioGroupPreview.tsx" + } + }, + { + "id": "mortar-segmented-control", + "logicalId": "segmented-control", + "name": "SegmentedControl", + "description": "Mortar foundation segmented control, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "SegmentedControl", + "source": "src/inspection.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string", + "options": "{ value: string; label: string }[]", + "onChange": "(value: string) => void" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { SegmentedControl } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SegmentedControlPreview.tsx" + } + }, + { + "id": "mortar-select", + "logicalId": "select", + "name": "Select", + "description": "Mortar foundation select, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Select", + "source": "src/primitives.tsx", + "capabilities": [ + "theme", + "foundation", + "input", + "validation", + "keyboard" + ], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "options": "{ value: string; label: string }[]", + "value": "string", + "onChange": "ChangeEventHandler", + "hint": "string", + "error": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Select } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SelectPreview.tsx" + } + }, + { + "id": "mortar-settings-section", + "logicalId": "settings-section", + "name": "SettingsSection", + "description": "Mortar application settings section, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "SettingsSection", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "children": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { SettingsSection } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SettingsSectionPreview.tsx" + } + }, + { + "id": "mortar-switch", + "logicalId": "switch", + "name": "Switch", + "description": "Mortar foundation switch, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Switch", + "source": "src/primitives.tsx", + "capabilities": [ + "theme", + "foundation", + "input", + "validation", + "keyboard" + ], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "checked": "boolean", + "onChange": "ChangeEventHandler" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Switch } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SwitchPreview.tsx" + } + }, + { + "id": "mortar-tabs", + "logicalId": "tabs", + "name": "Tabs", + "description": "Mortar foundation tabs, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Tabs", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string", + "onChange": "(value: string) => void", + "items": "{ id: string; label: string; content: ReactNode }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Tabs } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/TabsPreview.tsx" + } + }, + { + "id": "mortar-testimonial", + "logicalId": "testimonial", + "name": "Testimonial", + "description": "Mortar marketing testimonial, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Testimonial", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "quote": "string", + "name": "string", + "role": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Testimonial } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/TestimonialPreview.tsx" + } + }, + { + "id": "mortar-text-area", + "logicalId": "text-area", + "name": "TextArea", + "description": "Mortar foundation text area, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "TextArea", + "source": "src/primitives.tsx", + "capabilities": [ + "theme", + "foundation", + "input", + "validation", + "keyboard" + ], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string", + "onChange": "ChangeEventHandler", + "hint": "string", + "error": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { TextArea } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/TextAreaPreview.tsx" + } + }, + { + "id": "mortar-theme-provider", + "logicalId": "theme-provider", + "name": "ThemeProvider", + "description": "Mortar foundation theme provider, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "ThemeProvider", + "source": "src/foundation.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "children": "ReactNode", + "initialAppearance": "light | dark | system", + "brand": "neutral | green", + "density": "compact | comfortable | spacious" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { ThemeProvider } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ThemeProviderPreview.tsx" + } + } + ] +} diff --git a/design-principles.json b/design-principles.json new file mode 100644 index 0000000..7f04100 --- /dev/null +++ b/design-principles.json @@ -0,0 +1,30 @@ +{ + "schemaVersion": 1, + "version": "1.0.0", + "principles": [ + { + "id": "shell-first", + "instruction": "Choose the shared purpose shell before composing a page. Use AppShell for application screens and MarketingHeader for public pages. Document deliberate standalone exceptions." + }, + { + "id": "page-pattern-reuse", + "instruction": "Reuse complete page patterns: navigation, headings, filters, list/detail workspaces, states and action placement. Reusing controls alone is insufficient." + }, + { + "id": "project-agnostic-chrome", + "instruction": "Keep product names, routes, user data, permissions and actions in props and slots. Shared chrome must remain project agnostic." + }, + { + "id": "central-fixes", + "instruction": "Contribute missing patterns centrally. Do not duplicate source, create repeated local wrappers or apply consumer CSS overrides." + }, + { + "id": "semantic-themes", + "instruction": "Use semantic tokens; keep brand separate from appearance and feedback colours. Verify every supported theme." + }, + { + "id": "interaction-quality", + "instruction": "Verify responsive layout, accessible names, keyboard operation, focus and loading/empty/error states. Automated checks alone cannot prove visual quality." + } + ] +} diff --git a/manifests/mortar-action-link.json b/manifests/mortar-action-link.json new file mode 100644 index 0000000..4264a28 --- /dev/null +++ b/manifests/mortar-action-link.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-action-link", + "logicalId": "action-link", + "name": "ActionLink", + "description": "Mortar foundation action link, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "ActionLink", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "href": "string", + "variant": "primary | secondary | ghost | danger" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { ActionLink } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ActionLinkPreview.tsx" + } +} diff --git a/manifests/mortar-activity-feed.json b/manifests/mortar-activity-feed.json new file mode 100644 index 0000000..fadd31e --- /dev/null +++ b/manifests/mortar-activity-feed.json @@ -0,0 +1,39 @@ +{ + "id": "mortar-activity-feed", + "logicalId": "activity-feed", + "name": "ActivityFeed", + "description": "Mortar application activity feed, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "ActivityFeed", + "source": "src/application.tsx", + "capabilities": ["theme", "application", "status"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "label": "string", + "items": "{ id: string; title: string; description?: string; time: string; tone?: Tone }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { ActivityFeed } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ActivityFeedPreview.tsx" + } +} diff --git a/manifests/mortar-app-shell.json b/manifests/mortar-app-shell.json new file mode 100644 index 0000000..480d3f7 --- /dev/null +++ b/manifests/mortar-app-shell.json @@ -0,0 +1,45 @@ +{ + "id": "mortar-app-shell", + "logicalId": "app-shell", + "name": "AppShell", + "description": "Mortar application app shell, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "AppShell", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "brand": "string", + "workspace": "string", + "navigation": "NavigationItem[]", + "secondaryNavigation": "{ label: string; items: NavigationItem[] }[]", + "user": "ReactNode", + "header": "ReactNode", + "actions": "ReactNode", + "children": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { AppShell } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button"] + }, + "preview": { + "source": "previews/AppShellPreview.tsx" + } +} diff --git a/manifests/mortar-appearance-control.json b/manifests/mortar-appearance-control.json new file mode 100644 index 0000000..128df1d --- /dev/null +++ b/manifests/mortar-appearance-control.json @@ -0,0 +1,36 @@ +{ + "id": "mortar-appearance-control", + "logicalId": "appearance-control", + "name": "AppearanceControl", + "description": "Mortar foundation appearance control, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "AppearanceControl", + "source": "src/foundation.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": {}, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { AppearanceControl } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-theme-provider"] + }, + "preview": { + "source": "previews/AppearanceControlPreview.tsx" + } +} diff --git a/manifests/mortar-badge.json b/manifests/mortar-badge.json new file mode 100644 index 0000000..fbf2a8e --- /dev/null +++ b/manifests/mortar-badge.json @@ -0,0 +1,39 @@ +{ + "id": "mortar-badge", + "logicalId": "badge", + "name": "Badge", + "description": "Mortar foundation badge, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Badge", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "status"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "children": "ReactNode", + "tone": "neutral | success | warning | danger" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Badge } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/BadgePreview.tsx" + } +} diff --git a/manifests/mortar-button.json b/manifests/mortar-button.json new file mode 100644 index 0000000..a672c12 --- /dev/null +++ b/manifests/mortar-button.json @@ -0,0 +1,43 @@ +{ + "id": "mortar-button", + "logicalId": "button", + "name": "Button", + "description": "Mortar foundation button, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Button", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "children": "ReactNode", + "variant": "primary | secondary | ghost | danger", + "loading": "boolean", + "disabled": "boolean", + "type": "button | submit | reset", + "onClick": "MouseEventHandler" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Button } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ButtonPreview.tsx" + } +} diff --git a/manifests/mortar-call-to-action.json b/manifests/mortar-call-to-action.json new file mode 100644 index 0000000..d232d95 --- /dev/null +++ b/manifests/mortar-call-to-action.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-call-to-action", + "logicalId": "call-to-action", + "name": "CallToAction", + "description": "Mortar marketing call to action, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "CallToAction", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "actions": "LinkAction[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { CallToAction } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-action-link"] + }, + "preview": { + "source": "previews/CallToActionPreview.tsx" + } +} diff --git a/manifests/mortar-checkbox.json b/manifests/mortar-checkbox.json new file mode 100644 index 0000000..cb5a447 --- /dev/null +++ b/manifests/mortar-checkbox.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-checkbox", + "logicalId": "checkbox", + "name": "Checkbox", + "description": "Mortar foundation checkbox, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Checkbox", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "input", "validation", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "checked": "boolean", + "onChange": "ChangeEventHandler" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Checkbox } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/CheckboxPreview.tsx" + } +} diff --git a/manifests/mortar-code-block.json b/manifests/mortar-code-block.json new file mode 100644 index 0000000..7d91764 --- /dev/null +++ b/manifests/mortar-code-block.json @@ -0,0 +1,39 @@ +{ + "id": "mortar-code-block", + "logicalId": "code-block", + "name": "CodeBlock", + "description": "Mortar application code block, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "CodeBlock", + "source": "src/inspection.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "code": "string", + "label": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { CodeBlock } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/CodeBlockPreview.tsx" + } +} diff --git a/manifests/mortar-data-table.json b/manifests/mortar-data-table.json new file mode 100644 index 0000000..8f7bb65 --- /dev/null +++ b/manifests/mortar-data-table.json @@ -0,0 +1,49 @@ +{ + "id": "mortar-data-table", + "logicalId": "data-table", + "name": "DataTable", + "description": "Mortar application data table, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "DataTable", + "source": "src/application.tsx", + "capabilities": ["theme", "application", "table"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "caption": "string", + "columns": "{ key: string; label: string; render: (row: T) => ReactNode; align?: left | right }[]", + "rows": "T[] where T extends { id: string }", + "rowLabel": "(row: T) => string", + "selectedIds": "string[]", + "onSelectionChange": "(ids: string[]) => void", + "toolbar": "ReactNode", + "bulkActions": "ReactNode", + "loading": "boolean", + "error": "string", + "emptyTitle": "string", + "emptyDescription": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { DataTable } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button", "mortar-empty-state", "mortar-notice"] + }, + "preview": { + "source": "previews/DataTablePreview.tsx" + } +} diff --git a/manifests/mortar-dropdown.json b/manifests/mortar-dropdown.json new file mode 100644 index 0000000..8b27c3f --- /dev/null +++ b/manifests/mortar-dropdown.json @@ -0,0 +1,39 @@ +{ + "id": "mortar-dropdown", + "logicalId": "dropdown", + "name": "Dropdown", + "description": "Mortar foundation dropdown, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Dropdown", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "items": "{ label: string; onSelect: () => void; danger?: boolean; disabled?: boolean }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Dropdown } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/DropdownPreview.tsx" + } +} diff --git a/manifests/mortar-empty-state.json b/manifests/mortar-empty-state.json new file mode 100644 index 0000000..6daa4fe --- /dev/null +++ b/manifests/mortar-empty-state.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-empty-state", + "logicalId": "empty-state", + "name": "EmptyState", + "description": "Mortar foundation empty state, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "EmptyState", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "action": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { EmptyState } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/EmptyStatePreview.tsx" + } +} diff --git a/manifests/mortar-faq.json b/manifests/mortar-faq.json new file mode 100644 index 0000000..f929632 --- /dev/null +++ b/manifests/mortar-faq.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-faq", + "logicalId": "faq", + "name": "FAQ", + "description": "Mortar marketing faq, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "FAQ", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "ReactNode", + "items": "{ question: string; answer: ReactNode }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { FAQ } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FAQPreview.tsx" + } +} diff --git a/manifests/mortar-feature-grid.json b/manifests/mortar-feature-grid.json new file mode 100644 index 0000000..8aa6f1d --- /dev/null +++ b/manifests/mortar-feature-grid.json @@ -0,0 +1,41 @@ +{ + "id": "mortar-feature-grid", + "logicalId": "feature-grid", + "name": "FeatureGrid", + "description": "Mortar marketing feature grid, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "FeatureGrid", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "eyebrow": "string", + "description": "string", + "items": "{ title: string; description: string; icon?: ReactNode }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { FeatureGrid } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FeatureGridPreview.tsx" + } +} diff --git a/manifests/mortar-feature-section.json b/manifests/mortar-feature-section.json new file mode 100644 index 0000000..7a54858 --- /dev/null +++ b/manifests/mortar-feature-section.json @@ -0,0 +1,41 @@ +{ + "id": "mortar-feature-section", + "logicalId": "feature-section", + "name": "FeatureSection", + "description": "Mortar marketing feature section, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "FeatureSection", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "children": "ReactNode", + "reverse": "boolean" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { FeatureSection } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FeatureSectionPreview.tsx" + } +} diff --git a/manifests/mortar-footer.json b/manifests/mortar-footer.json new file mode 100644 index 0000000..011e495 --- /dev/null +++ b/manifests/mortar-footer.json @@ -0,0 +1,42 @@ +{ + "id": "mortar-footer", + "logicalId": "footer", + "name": "Footer", + "description": "Mortar marketing footer, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Footer", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "brand": "string", + "description": "string", + "columns": "{ title: string; links: LinkAction[] }[]", + "copyright": "string", + "legal": "LinkAction[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Footer } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/FooterPreview.tsx" + } +} diff --git a/manifests/mortar-hero.json b/manifests/mortar-hero.json new file mode 100644 index 0000000..da2994d --- /dev/null +++ b/manifests/mortar-hero.json @@ -0,0 +1,44 @@ +{ + "id": "mortar-hero", + "logicalId": "hero", + "name": "Hero", + "description": "Mortar marketing hero, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Hero", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "eyebrow": "string", + "title": "string", + "description": "string", + "actions": "LinkAction[]", + "children": "ReactNode", + "align": "center | split", + "headingLevel": "1 | 2" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Hero } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-action-link"] + }, + "preview": { + "source": "previews/HeroPreview.tsx" + } +} diff --git a/manifests/mortar-input.json b/manifests/mortar-input.json new file mode 100644 index 0000000..12c0ec9 --- /dev/null +++ b/manifests/mortar-input.json @@ -0,0 +1,44 @@ +{ + "id": "mortar-input", + "logicalId": "input", + "name": "Input", + "description": "Mortar foundation input, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Input", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "input", "validation", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string | number", + "onChange": "ChangeEventHandler", + "hint": "string", + "error": "string", + "prefix": "string", + "suffix": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Input } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/InputPreview.tsx" + } +} diff --git a/manifests/mortar-logo-cloud.json b/manifests/mortar-logo-cloud.json new file mode 100644 index 0000000..f666626 --- /dev/null +++ b/manifests/mortar-logo-cloud.json @@ -0,0 +1,39 @@ +{ + "id": "mortar-logo-cloud", + "logicalId": "logo-cloud", + "name": "LogoCloud", + "description": "Mortar marketing logo cloud, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "LogoCloud", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "label": "string", + "items": "{ name: string; image?: string }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { LogoCloud } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/LogoCloudPreview.tsx" + } +} diff --git a/manifests/mortar-marketing-header.json b/manifests/mortar-marketing-header.json new file mode 100644 index 0000000..4bf1250 --- /dev/null +++ b/manifests/mortar-marketing-header.json @@ -0,0 +1,42 @@ +{ + "id": "mortar-marketing-header", + "logicalId": "marketing-header", + "name": "MarketingHeader", + "description": "Mortar marketing marketing header, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "MarketingHeader", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "brand": "string", + "homeHref": "string", + "links": "LinkAction[]", + "action": "LinkAction", + "controls": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { MarketingHeader } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button", "mortar-action-link"] + }, + "preview": { + "source": "previews/MarketingHeaderPreview.tsx" + } +} diff --git a/manifests/mortar-metric-group.json b/manifests/mortar-metric-group.json new file mode 100644 index 0000000..a2fa40c --- /dev/null +++ b/manifests/mortar-metric-group.json @@ -0,0 +1,39 @@ +{ + "id": "mortar-metric-group", + "logicalId": "metric-group", + "name": "MetricGroup", + "description": "Mortar application metric group, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "MetricGroup", + "source": "src/application.tsx", + "capabilities": ["theme", "application", "summary"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "label": "string", + "items": "{ label: string; value: string; change?: string; tone?: Tone }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { MetricGroup } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/MetricGroupPreview.tsx" + } +} diff --git a/manifests/mortar-modal.json b/manifests/mortar-modal.json new file mode 100644 index 0000000..793ee7f --- /dev/null +++ b/manifests/mortar-modal.json @@ -0,0 +1,42 @@ +{ + "id": "mortar-modal", + "logicalId": "modal", + "name": "Modal", + "description": "Mortar foundation modal, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Modal", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "title": "string", + "open": "boolean", + "onClose": "() => void", + "children": "ReactNode", + "actions": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Modal } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button"] + }, + "preview": { + "source": "previews/ModalPreview.tsx" + } +} diff --git a/manifests/mortar-notice.json b/manifests/mortar-notice.json new file mode 100644 index 0000000..046b579 --- /dev/null +++ b/manifests/mortar-notice.json @@ -0,0 +1,41 @@ +{ + "id": "mortar-notice", + "logicalId": "notice", + "name": "Notice", + "description": "Mortar foundation notice, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Notice", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "status"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "title": "string", + "children": "ReactNode", + "tone": "neutral | success | warning | danger", + "announce": "boolean" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Notice } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/NoticePreview.tsx" + } +} diff --git a/manifests/mortar-page-heading.json b/manifests/mortar-page-heading.json new file mode 100644 index 0000000..de16885 --- /dev/null +++ b/manifests/mortar-page-heading.json @@ -0,0 +1,43 @@ +{ + "id": "mortar-page-heading", + "logicalId": "page-heading", + "name": "PageHeading", + "description": "Mortar application page heading, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "PageHeading", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "eyebrow": "string", + "actions": "ReactNode", + "breadcrumbs": "{ label: string; href?: string }[]", + "headingLevel": "1 | 2" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { PageHeading } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/PageHeadingPreview.tsx" + } +} diff --git a/manifests/mortar-pagination.json b/manifests/mortar-pagination.json new file mode 100644 index 0000000..40e3a4a --- /dev/null +++ b/manifests/mortar-pagination.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-pagination", + "logicalId": "pagination", + "name": "Pagination", + "description": "Mortar application pagination, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Pagination", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "page": "number", + "pageCount": "number", + "onChange": "(page: number) => void" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Pagination } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-button"] + }, + "preview": { + "source": "previews/PaginationPreview.tsx" + } +} diff --git a/manifests/mortar-preview-frame.json b/manifests/mortar-preview-frame.json new file mode 100644 index 0000000..dc75f1e --- /dev/null +++ b/manifests/mortar-preview-frame.json @@ -0,0 +1,39 @@ +{ + "id": "mortar-preview-frame", + "logicalId": "preview-frame", + "name": "PreviewFrame", + "description": "Mortar application preview frame, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "PreviewFrame", + "source": "src/inspection.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "title": "string", + "src": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { PreviewFrame } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/PreviewFramePreview.tsx" + } +} diff --git a/manifests/mortar-pricing.json b/manifests/mortar-pricing.json new file mode 100644 index 0000000..c334cc8 --- /dev/null +++ b/manifests/mortar-pricing.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-pricing", + "logicalId": "pricing", + "name": "Pricing", + "description": "Mortar marketing pricing, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Pricing", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "plans": "PricingPlan[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Pricing } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": ["mortar-action-link"] + }, + "preview": { + "source": "previews/PricingPreview.tsx" + } +} diff --git a/manifests/mortar-radio-group.json b/manifests/mortar-radio-group.json new file mode 100644 index 0000000..f905f83 --- /dev/null +++ b/manifests/mortar-radio-group.json @@ -0,0 +1,42 @@ +{ + "id": "mortar-radio-group", + "logicalId": "radio-group", + "name": "RadioGroup", + "description": "Mortar foundation radio group, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "RadioGroup", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "input", "validation", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "name": "string", + "value": "string", + "onChange": "(value: string) => void", + "options": "{ value: string; label: string; description?: string }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { RadioGroup } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/RadioGroupPreview.tsx" + } +} diff --git a/manifests/mortar-segmented-control.json b/manifests/mortar-segmented-control.json new file mode 100644 index 0000000..774f4c7 --- /dev/null +++ b/manifests/mortar-segmented-control.json @@ -0,0 +1,41 @@ +{ + "id": "mortar-segmented-control", + "logicalId": "segmented-control", + "name": "SegmentedControl", + "description": "Mortar foundation segmented control, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "SegmentedControl", + "source": "src/inspection.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string", + "options": "{ value: string; label: string }[]", + "onChange": "(value: string) => void" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { SegmentedControl } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SegmentedControlPreview.tsx" + } +} diff --git a/manifests/mortar-select.json b/manifests/mortar-select.json new file mode 100644 index 0000000..3315b30 --- /dev/null +++ b/manifests/mortar-select.json @@ -0,0 +1,43 @@ +{ + "id": "mortar-select", + "logicalId": "select", + "name": "Select", + "description": "Mortar foundation select, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Select", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "input", "validation", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "options": "{ value: string; label: string }[]", + "value": "string", + "onChange": "ChangeEventHandler", + "hint": "string", + "error": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Select } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SelectPreview.tsx" + } +} diff --git a/manifests/mortar-settings-section.json b/manifests/mortar-settings-section.json new file mode 100644 index 0000000..3d89bb7 --- /dev/null +++ b/manifests/mortar-settings-section.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-settings-section", + "logicalId": "settings-section", + "name": "SettingsSection", + "description": "Mortar application settings section, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "SettingsSection", + "source": "src/application.tsx", + "capabilities": ["theme", "application"], + "owner": "Mortar maintainers", + "kitId": "application", + "provenance": { + "kitId": "application", + "exampleId": "mortar-application-reference", + "sourceDigest": "9c3a1c251ac5dcf28a566a4a6ee4ae6724296996e47b7eb3ccacad1517668ef3" + }, + "contract": { + "props": { + "title": "string", + "description": "string", + "children": "ReactNode" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { SettingsSection } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SettingsSectionPreview.tsx" + } +} diff --git a/manifests/mortar-switch.json b/manifests/mortar-switch.json new file mode 100644 index 0000000..5a25ba9 --- /dev/null +++ b/manifests/mortar-switch.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-switch", + "logicalId": "switch", + "name": "Switch", + "description": "Mortar foundation switch, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Switch", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "input", "validation", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "checked": "boolean", + "onChange": "ChangeEventHandler" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Switch } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/SwitchPreview.tsx" + } +} diff --git a/manifests/mortar-tabs.json b/manifests/mortar-tabs.json new file mode 100644 index 0000000..29ec41b --- /dev/null +++ b/manifests/mortar-tabs.json @@ -0,0 +1,41 @@ +{ + "id": "mortar-tabs", + "logicalId": "tabs", + "name": "Tabs", + "description": "Mortar foundation tabs, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Tabs", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "action", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string", + "onChange": "(value: string) => void", + "items": "{ id: string; label: string; content: ReactNode }[]" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Tabs } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/TabsPreview.tsx" + } +} diff --git a/manifests/mortar-testimonial.json b/manifests/mortar-testimonial.json new file mode 100644 index 0000000..7af280f --- /dev/null +++ b/manifests/mortar-testimonial.json @@ -0,0 +1,40 @@ +{ + "id": "mortar-testimonial", + "logicalId": "testimonial", + "name": "Testimonial", + "description": "Mortar marketing testimonial, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "Testimonial", + "source": "src/marketing.tsx", + "capabilities": ["theme", "marketing"], + "owner": "Mortar maintainers", + "kitId": "marketing", + "provenance": { + "kitId": "marketing", + "exampleId": "mortar-marketing-reference", + "sourceDigest": "4ec7866f2bbb06475a555bfde970c052111c84efde4ce0f38134e7fb400733d2" + }, + "contract": { + "props": { + "quote": "string", + "name": "string", + "role": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { Testimonial } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/TestimonialPreview.tsx" + } +} diff --git a/manifests/mortar-text-area.json b/manifests/mortar-text-area.json new file mode 100644 index 0000000..68ebcb2 --- /dev/null +++ b/manifests/mortar-text-area.json @@ -0,0 +1,42 @@ +{ + "id": "mortar-text-area", + "logicalId": "text-area", + "name": "TextArea", + "description": "Mortar foundation text area, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "TextArea", + "source": "src/primitives.tsx", + "capabilities": ["theme", "foundation", "input", "validation", "keyboard"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "label": "string", + "value": "string", + "onChange": "ChangeEventHandler", + "hint": "string", + "error": "string" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { TextArea } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/TextAreaPreview.tsx" + } +} diff --git a/manifests/mortar-theme-provider.json b/manifests/mortar-theme-provider.json new file mode 100644 index 0000000..347a6ee --- /dev/null +++ b/manifests/mortar-theme-provider.json @@ -0,0 +1,41 @@ +{ + "id": "mortar-theme-provider", + "logicalId": "theme-provider", + "name": "ThemeProvider", + "description": "Mortar foundation theme provider, using central semantic tokens.", + "stack": "react-tailwind", + "package": "@tony-ui/mortar", + "version": "0.1.0", + "export": "ThemeProvider", + "source": "src/foundation.tsx", + "capabilities": ["theme", "foundation"], + "owner": "Mortar maintainers", + "kitId": "foundation", + "provenance": { + "kitId": "foundation", + "exampleId": "mortar-foundation-reference", + "sourceDigest": "f132052b4ac52f3909ac437073c076b9f615849effea14dabf7d30759d714c2d" + }, + "contract": { + "props": { + "children": "ReactNode", + "initialAppearance": "light | dark | system", + "brand": "neutral | green", + "density": "compact | comfortable | spacious" + }, + "states": [ + "Light", + "Dark", + "Neutral brand", + "Green brand", + "Keyboard and focus" + ], + "usage": "Import { ThemeProvider } from @tony-ui/mortar. Compose with the public typed props.", + "avoid": "Do not copy implementations, override central colours or grant component approval.", + "accessibility": "Verify accessible names, keyboard interaction, visible focus, responsive layout and supported states.", + "dependencies": [] + }, + "preview": { + "source": "previews/ThemeProviderPreview.tsx" + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..40cb463 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2862 @@ +{ + "name": "@tony-ui/mortar", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@tony-ui/mortar", + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "@headlessui/react": "^2.2.0" + }, + "devDependencies": { + "@axe-core/playwright": "^4.13.0", + "@playwright/test": "^1.63.0", + "@tailwindcss/vite": "^4.0.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^5.0.0", + "prettier": "^3.9.9", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwindcss": "^4.0.0", + "typescript": "^5.9.3", + "vite": "^7.1.0" + }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwindcss": "^4.0.0" + } + }, + "node_modules/@axe-core/playwright": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.13.0.tgz", + "integrity": "sha512-6YLx+kxXu5GJceG4ozFg+33a2EMTdjYwWGloJ3sb9Kta5pp+ZNS53uxGVog5JetIY8s++P5UrtX+cri+u0VAVg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "axe-core": "~4.13.0" + }, + "peerDependencies": { + "playwright-core": ">= 1.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz", + "integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz", + "integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.9", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz", + "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.8.0", + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.9.tgz", + "integrity": "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.8.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", + "license": "MIT" + }, + "node_modules/@headlessui/react": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.10.tgz", + "integrity": "sha512-5pVLNK9wlpxTUTy9GpgbX/SdcRh+HBnPktjM2wbiLTH4p+2EPHBO1aoSryUCuKUIItdDWO9ITlhUL8UnUN/oIA==", + "license": "MIT", + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.20.2", + "@react-aria/interactions": "^3.25.0", + "@tanstack/react-virtual": "^3.13.9", + "use-sync-external-store": "^1.5.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@internationalized/date": { + "version": "3.12.4", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.4.tgz", + "integrity": "sha512-M1dEn4c1U1HsSlaVR8upZtSqvXrTkHDfv18H01uCSJyjVLDxnBR38v/fMxecmlwXKR4i9HeZcmgQAPE6A+aGJQ==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/number": { + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/@internationalized/number/-/number-3.6.9.tgz", + "integrity": "sha512-GgWy2caO/+hV9sT/oCTWGHvbjmJMPT9kkXzoKRLnkEq7adghhR7UprhvY9sXrKfrp3NcDfhF6QQHXR1KfQbB8g==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@internationalized/string": { + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/@internationalized/string/-/string-3.2.10.tgz", + "integrity": "sha512-PDx6//vHSpRnHfxqMqto11zQvhsaU74O3mKv2F/0eicGZcl9NLjQmGlbHz/LsJh5tLKp4A4L7ZVTzN1/MmMTvA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/lzma-linux-x64-gnu": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@napi-rs/lzma-linux-x64-gnu/-/lzma-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^22.20 || ^24.12 || >=25" + } + }, + "node_modules/@playwright/test": { + "version": "1.64.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.64.0.tgz", + "integrity": "sha512-oTN9FNYuN6bqQMwiho6jJKLCG2/QOYCixGXuCjRmzOq23eODeukuY2XiAVoVpAECbuezMt1MHQjAiQxK8F+Y+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.64.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@react-aria/focus": { + "version": "3.22.1", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.22.1.tgz", + "integrity": "sha512-CPxtkyrBi/HYY5P3lE/57sQ6qfa0lN8E55TOm89H0kNGv0lKt+/0zP7lWERzBjRr5IxBVrQX4gFEowBN52LPaA==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0", + "react-aria": "^3.48.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.28.1.tgz", + "integrity": "sha512-Bqb+HrD5I5MHS2SKBhISYqo2SW8Y2dfzgF/Y1lIJq7xqLxheo9vzxPGEHhz+XzkgGfoqEJx8A6a3C7uiqS3HWA==", + "license": "Apache-2.0", + "dependencies": { + "@react-types/shared": "^3.34.0", + "@swc/helpers": "^0.5.0", + "react-aria": "^3.48.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/shared": { + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.37.0.tgz", + "integrity": "sha512-VNlZuifu4tHdxWPfHvoMfKsHA9kVTCGkduv5vKVTdinm8wHFJNhyVB5RzIMiRFj0q3RKoCbP68u2zaoBSiFueg==", + "license": "Apache-2.0", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.64.6.tgz", + "integrity": "sha512-FkO19Fowv/OQeJZPVfdetJaI3/VpbZmBsnmAlR/rQ+b3QwfiGQiOpVegpSRH331kelvHTVw9hXYG3DwjAaRzyQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.64.6.tgz", + "integrity": "sha512-si5/Etm6MphPc2xYHnk455Shls/hoMjTy3mhXge4OPmvCw7TwC4KP4fKokAlKLV4XaQvLvgSHfafPcblLMYYdQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.64.6.tgz", + "integrity": "sha512-PQCl3q7b0BgvVt72i2xrWM6I5KliwwVe4GpWW5QDGyUQawDS9aPZss/aGyFqBmxdRxlE8wDc9CaxiQ5DHRSp/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.64.6.tgz", + "integrity": "sha512-l9DFl1Itb1YYdSrP1K3U8ih44AOHa/p+Q4WMMDfGvH5qVWp+ajfgS1DlYo4yCRh8wJ2ZJv0Fqccf+ULAmMFjmg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.64.6.tgz", + "integrity": "sha512-bR4GR3205N9+od0+l5Dd9/iZTDpJkIe6d6Ydp2qbcQZJLmKBdYQQRp8gbWpbMt92twKJY66o1vK4NkoKQODIrA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.64.6.tgz", + "integrity": "sha512-XTVNaDzcFl2TeBglvxdGgsCv9JGtAGRAoJENmGBR/XvDH2mA2K0IXc2aMfP0dR8mexSXSKifJ85FixoXX1wfTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.64.6.tgz", + "integrity": "sha512-qWc6qbc+25ugG9vqPR9P422KJBbVfZ05mjcMggoq8tsfWP+eRfC+/tiDdIlRF5VL2pDVZWN9zAhWsmu7R1+7Dw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.64.6.tgz", + "integrity": "sha512-V4Nwkp8844X/Xnww3PI1LYS0YPei8XQEVG70R+5MPZGO7AhYoun4hCN7Svs4U3wbQLZbwiz+9xRFhUZZdRl8Ww==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.64.6.tgz", + "integrity": "sha512-xb72A1aPaaIsp+a88VtRae/ovIEXislbUMyp7b9AQQU7ZkP2m/+ik6DW9TQcJyw5R8/RIailF9zExYwkjR++UA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.64.6.tgz", + "integrity": "sha512-pbcs1BVBwC43hZkjhjlF8Rx8m5G0KnhLZs9Azy/gqccP6UsNSzJr0hKGIAVPqzAH1O/NdPxxC9GVGb4msQg/aw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.64.6.tgz", + "integrity": "sha512-EKOC8os6Vsg487ZLKUqzLF99Jsmnq6tu7O7mAELakNpcA+8KadktFf/JYdRuHe/DzCUXmN38pUKu4XBcKlqGbQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.64.6.tgz", + "integrity": "sha512-v/SQ68GnSlr/HyjB79sNXesGDwkOPu9JjbHfmWaymCiM+nZsQ9TstG1KfA4MuEvTr2d3PoY8PhFxj9bt0e32JA==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.64.6.tgz", + "integrity": "sha512-G3pmliMQ7r15zFFNwBlaT/xTdSLi4lfgI7CUrQueyKYheNVhrd8JrWCE6Ll8xf4AA1RZFqq+mNJYntiElsVOyA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.64.6.tgz", + "integrity": "sha512-XQTB/IPoB/wG6x/wu9uomAt8YH61IAr5iZTubMiad/lu88sotq2ocz9hJd556+Jz2kIkF7ZQZIsUuWE3OWqtcA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.64.6.tgz", + "integrity": "sha512-O5mpokth6+ydMuwiGtY8fIjvOBfH7u6SzmDNmZ3k6GK5C6iEAC2q2ZN/T5L9jYILx0IcCT0KnfMDihQ5yQFSBw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.64.6.tgz", + "integrity": "sha512-aIFxbAD9v3TvIaEDsKmukjcDg1JS4/tFXw8SHyQQgzOwzWCQ4cyDK7Ju1pQKqUXDFkEu/BZCFDCDATsKhQcB/Q==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.64.6.tgz", + "integrity": "sha512-fuNo1UwBc6BxnHDOxxguQL/InhheMN3RJcJMb0b4xP8r5Q3CNCrJbVg0eCIFuJ4e/zAfjR2gYbOfbzO/G7CIyw==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.64.6.tgz", + "integrity": "sha512-05v6wFKDKJPZs9xlytVrrRu6IbRuoSvlH9xNwEOafXsKyjBFZPvAcZz2VIAB/M+lblYeKa9iOYC4RDVdfcAAaw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.64.6.tgz", + "integrity": "sha512-wJXKcdMjvkc/FaavZXNP1yW4i0pfOmhZAIWRSLG2yJ0PB0TWi7dkLErhX0u0vptDcXKKO/m1Y/YTeuyvb2MXwg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.64.6.tgz", + "integrity": "sha512-cwg7/h0ThvJwy8CBkmACdiHAxRWpbsCmIsjOt+Zzx0hTnIcSUmKYEV03bGg+hD827OnwUsbKh1ZZDW754xWyBA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.64.6.tgz", + "integrity": "sha512-T0RkYIJbdYXJEQFw+tMBO09KDFdgmNxkHsof3wWAABrvnx15Yh8RytmrgYy9+q9cBeBNZF66MMQZC+5nzEz6vg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.64.6.tgz", + "integrity": "sha512-KlfpmF1AAIdAWxt8QQNClbpLFlAUfYOzqIuJ7IXEStMHpFRuH78RG6FjqPb3Rqhh0K89F5npvG+/i3Fjl6IveQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.64.6.tgz", + "integrity": "sha512-MrTLjd7Jlt9/ZavJZYG61KQv9Iy9bzbY+yXy73Xvwoa2uP66wvDShkyBr5Chz/yrE6lbD/zHMuTmKQVNQqBApg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.64.6.tgz", + "integrity": "sha512-8fWDH1CkPI8GdBKAxzHDza7UmgficsKo2+MVbvUgOGhB0629w5sHMg3Qu5y7TZsrYKHHWpz8fla4KvoT7WsO3Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.64.6.tgz", + "integrity": "sha512-9/c9PWdr5GCIHkkxiHM1HjNBQMVdftP4O8QTcoUAaRza2FSqJ4axbf8QAnBuE6BIGQDl71SaRPeDdDYid5ecTw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-arm64": "4.3.3", + "@tailwindcss/oxide-darwin-x64": "4.3.3", + "@tailwindcss/oxide-freebsd-x64": "4.3.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.3", + "@tailwindcss/oxide-linux-x64-musl": "4.3.3", + "@tailwindcss/oxide-wasm32-wasi": "4.3.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.3.3.tgz", + "integrity": "sha512-yYU8cogLeSh/ms2jh8Fj7jaba/EWa7Ja6GoUqYZaraEuCI5YS6ms6ObZgjjedm+jm6XZjdNRWBpPP6Z86oOxcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "tailwindcss": "4.3.3" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7 || ^8" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.14.19", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.14.19.tgz", + "integrity": "sha512-zmVdJO8DDqHphZ2H6SnTmgpVXcUy5DprB+clZF0ik679/d0MQ1UPEb2jtaX6F5VTAX4o3ozSLQaRCnybS2KYLA==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.19.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "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" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.19.4", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.19.4.tgz", + "integrity": "sha512-ygZ3O99Il18dl0gG0q7sH78iSkb96F07G+xK9V83eCgV8NQbcNd7R+cgcJJMFO7llBoebd0A82sCCstQq2Vp6Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", + "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.3.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/axe-core": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.13.0.tgz", + "integrity": "sha512-UzGt8zg7Ny8djbYMhxl2zuEevVa7r2gJjYY5Lwr1xM7+XU2nd6CkIWFTVcCIbAP63vSz71NaVyyuSk9lHKcy0A==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.28", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.28.tgz", + "integrity": "sha512-br0LOmjJqr6Rt4AEkadbcNf67Zpo7EPwKsWbjnRrJIa1QYFHQBqM4C7F2WTbV8ahTEcg1Eo+Y0aWjjORInYFyA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.29.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", + "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.26", + "caniuse-lite": "^1.0.30001813", + "electron-to-chromium": "^1.5.439", + "node-releases": "^2.0.57", + "update-browserslist-db": "^1.3.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001816", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001816.tgz", + "integrity": "sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.454", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.454.tgz", + "integrity": "sha512-NqD5GhkXnxJpDQVCmmpc546qjH6kei2VI9m45CTF+sQU7bcS7YeVt7ba0cnjueMH1AXGRu/driZUP9iYVSv7vg==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.26.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz", + "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "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" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.58", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.58.tgz", + "integrity": "sha512-BdiKAgbfRlvfMq/XzO/AF9NPmaA8a+YpLAyAFTVFBj3gARrAIfWvNq7Q7NE4se3KgFu0KkrvQMxTS0XVnsGzHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/playwright": { + "version": "1.64.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.64.0.tgz", + "integrity": "sha512-kVzTnYFYEyQ9RGzBjNCd2+yEqWmVbxl3AHPynv3qQ6JTjv4a+kwRcnqQwIpuP3NnrnIrE/Q6wWAIAvMfIE2/Yg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.64.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/playwright-core": { + "version": "1.64.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.64.0.tgz", + "integrity": "sha512-T9r+MZkTECl2+oUcZ26YgZzTrYidTsIhYYkJix+6iDOymOb1FB2RLLSOxRGnZGv5DStt+aduIVbt+E8WygXYpg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/postcss": { + "version": "8.5.30", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.30.tgz", + "integrity": "sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.20", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prettier": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.10.tgz", + "integrity": "sha512-skGHTH1Yb9QvaTC4hWnRTzEYtCpApF0UMBPz+t/0ZPzP8ihefo/btKd+QA7pUE0fEwA1SbS/NmhyEcstdXOIdA==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-aria": { + "version": "3.53.1", + "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.53.1.tgz", + "integrity": "sha512-dikisyOjJd3D2fFrIDWmVWzqiLz5B86GzZv1zxs7xI4dVc0JIz/1Wa52I20gYvVL2WXeFXlygYsle/QcOMhtcg==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.12.4", + "@internationalized/number": "^3.6.9", + "@internationalized/string": "^3.2.10", + "@react-types/shared": "^3.37.0", + "@swc/helpers": "^0.5.0", + "aria-hidden": "^1.2.3", + "clsx": "^2.0.0", + "react-stately": "3.51.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.28.0" + }, + "peerDependencies": { + "react": "^19.3.0" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-stately": { + "version": "3.51.0", + "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.51.0.tgz", + "integrity": "sha512-YJcmkAXu2XOQP97hO/qz/cC3qv9kni3oVhwBlxWr358BHePJUpY15XwL3YSRMKxYt4EkslPqAz11JRirMfANGw==", + "license": "Apache-2.0", + "dependencies": { + "@internationalized/date": "^3.12.4", + "@internationalized/number": "^3.6.9", + "@internationalized/string": "^3.2.10", + "@react-types/shared": "^3.37.0", + "@swc/helpers": "^0.5.0", + "use-sync-external-store": "^1.6.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/rollup": { + "version": "4.64.6", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.64.6.tgz", + "integrity": "sha512-fX1Vy+UNKdXn+xKDnu/HBXbHVr1AY8cSdQj9BU4kLv5aFCMqGpvrVbyUMmjN3DdzWhSAuTbcX8PCNEVaumthYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@napi-rs/lzma-linux-x64-gnu": "1.5.1", + "@rollup/rollup-android-arm-eabi": "4.64.6", + "@rollup/rollup-android-arm64": "4.64.6", + "@rollup/rollup-darwin-arm64": "4.64.6", + "@rollup/rollup-darwin-x64": "4.64.6", + "@rollup/rollup-freebsd-arm64": "4.64.6", + "@rollup/rollup-freebsd-x64": "4.64.6", + "@rollup/rollup-linux-arm-gnueabihf": "4.64.6", + "@rollup/rollup-linux-arm-musleabihf": "4.64.6", + "@rollup/rollup-linux-arm64-gnu": "4.64.6", + "@rollup/rollup-linux-arm64-musl": "4.64.6", + "@rollup/rollup-linux-loong64-gnu": "4.64.6", + "@rollup/rollup-linux-loong64-musl": "4.64.6", + "@rollup/rollup-linux-ppc64-gnu": "4.64.6", + "@rollup/rollup-linux-ppc64-musl": "4.64.6", + "@rollup/rollup-linux-riscv64-gnu": "4.64.6", + "@rollup/rollup-linux-riscv64-musl": "4.64.6", + "@rollup/rollup-linux-s390x-gnu": "4.64.6", + "@rollup/rollup-linux-x64-gnu": "4.64.6", + "@rollup/rollup-linux-x64-musl": "4.64.6", + "@rollup/rollup-openbsd-x64": "4.64.6", + "@rollup/rollup-openharmony-arm64": "4.64.6", + "@rollup/rollup-win32-arm64-msvc": "4.64.6", + "@rollup/rollup-win32-ia32-msvc": "4.64.6", + "@rollup/rollup-win32-x64-gnu": "4.64.6", + "@rollup/rollup-win32-x64-msvc": "4.64.6", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map-js": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tabbable": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.5.0.tgz", + "integrity": "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA==", + "license": "MIT" + }, + "node_modules/tailwindcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", + "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.7.0.tgz", + "integrity": "sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/vite": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.7.tgz", + "integrity": "sha512-AHEzTORMbi7/7aXp7w7KZ5+DCUdSeLsJz0grY8xHpc9DHdYb0vQu6DqJfm2tOw3gDExNgPgnJTXxM6syYFHaCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..6a32036 --- /dev/null +++ b/package.json @@ -0,0 +1,72 @@ +{ + "name": "@tony-ui/mortar", + "version": "0.1.0", + "description": "Mortar: a shared design foundation, application and marketing UI for React and Tailwind.", + "type": "module", + "files": [ + "dist", + "src", + "styles.css", + "README.md", + "LICENSE", + "catalog.json", + "baseline-policy.json", + "design-principles.json", + "DESIGN.md" + ], + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./styles.css": "./styles.css" + }, + "sideEffects": [ + "**/*.css" + ], + "scripts": { + "build": "tsc -p tsconfig.json", + "dev": "vite --host 127.0.0.1", + "catalog": "node scripts/check.mjs --write-catalog", + "check": "npm run format:check && npm run build && node scripts/check.mjs && node --test tests/*.test.mjs && npm run build:playground", + "check:json": "node scripts/check.mjs --format json", + "test:browser": "playwright test", + "build:playground": "tsc --noEmit -p tsconfig.playground.json && vite build", + "format:check": "prettier --check .", + "release:prepare": "node scripts/release.mjs" + }, + "peerDependencies": { + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tailwindcss": "^4.0.0" + }, + "dependencies": { + "@headlessui/react": "^2.2.0" + }, + "devDependencies": { + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "typescript": "^5.9.3", + "vite": "^7.1.0", + "@vitejs/plugin-react": "^5.0.0", + "@tailwindcss/vite": "^4.0.0", + "tailwindcss": "^4.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "prettier": "^3.9.9", + "@playwright/test": "^1.63.0", + "@axe-core/playwright": "^4.13.0" + }, + "license": "MIT", + "publishConfig": { + "registry": "https://git.tony.codes/api/packages/tony/npm/", + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://git.tony.codes/tony/mortar.git" + }, + "homepage": "https://ui.tony.codes/" +} diff --git a/playground/index.html b/playground/index.html new file mode 100644 index 0000000..76d18ec --- /dev/null +++ b/playground/index.html @@ -0,0 +1,12 @@ + + + + + + Mortar component playground + + +
+ + + diff --git a/playground/main.tsx b/playground/main.tsx new file mode 100644 index 0000000..6822465 --- /dev/null +++ b/playground/main.tsx @@ -0,0 +1,55 @@ +import { Suspense, lazy, type ComponentType } from "react"; +import { createRoot } from "react-dom/client"; +import { + ThemeProvider, + Select, + AppearanceControl, + PageHeading, + Notice, +} from "../src/index.js"; +import catalog from "../catalog.json"; +import "./styles.css"; +const fixtures = import.meta.glob("../previews/*Preview.tsx"); +const params = new URLSearchParams(location.search); +const component = params.get("component") || "Button"; +const loader = fixtures[`../previews/${component}Preview.tsx`]; +const Preview = loader + ? lazy(loader as () => Promise<{ default: ComponentType }>) + : null; +createRoot(document.getElementById("root")!).render( + +
+ +
+ + ); +} +export function DataTable({ + caption, + columns, + rows, + selectedIds = [], + onSelectionChange, + rowLabel, + toolbar, + bulkActions, + emptyTitle = "No records", + emptyDescription = "Records will appear here when they are available.", + loading, + error, +}: DataTableProps) { + const selected = rows.filter((row) => selectedIds.includes(row.id)); + return ( +
+ {(toolbar || selected.length > 0) && ( +
+ {selected.length > 0 ? ( + <> + {selected.length} selected +
+ {bulkActions} + +
+ + ) : ( + toolbar + )} +
+ )} + {loading ? ( +

+ Loading records… +

+ ) : error ? ( + + {error} + + ) : !rows.length ? ( + + ) : ( +
+ + + + + {onSelectionChange && ( + + )} + {columns.map((col) => ( + + ))} + + + + {rows.map((row) => ( + + {onSelectionChange && ( + + )} + {columns.map((col, index) => + index === 0 ? ( + + ) : ( + + ), + )} + + ))} + +
{caption}
+ 0 && selected.length < rows.length + } + onChange={() => + onSelectionChange( + selected.length === rows.length + ? [] + : rows.map((r) => r.id), + ) + } + /> + + {col.label} +
+ + onSelectionChange( + selectedIds.includes(row.id) + ? selectedIds.filter((id) => id !== row.id) + : [...selectedIds, row.id], + ) + } + /> + + {col.render(row)} + + {col.render(row)} +
+
+ )} +
+ ); +} +export function Pagination({ + page, + pageCount, + onChange, +}: { + page: number; + pageCount: number; + onChange: (page: number) => void; +}) { + return ( + + ); +} +export function SettingsSection({ + title, + description, + children, +}: { + title: string; + description?: string; + children: ReactNode; +}) { + const id = useId(); + return ( +
+
+

{title}

+ {description &&

{description}

} +
+
{children}
+
+ ); +} +export function ActivityFeed({ + label, + items, +}: { + label: string; + items: { + id: string; + title: string; + description?: string; + time: string; + tone?: Tone; + }[]; +}) { + return ( +
    + {items.map((item) => ( +
  1. +
  2. + ))} +
+ ); +} diff --git a/src/components.css b/src/components.css new file mode 100644 index 0000000..8ebd75c --- /dev/null +++ b/src/components.css @@ -0,0 +1,1289 @@ +@layer components { + [data-mortar] body { + margin: 0; + background: var(--m-paper); + color: var(--m-ink); + font-family: var(--m-font); + font-size: 15px; + line-height: 1.5; + -webkit-font-smoothing: antialiased; + } + [data-mortar] :where(button, input, select, textarea) { + font: inherit; + color: inherit; + } + [data-mortar] + :where( + button, + a, + input, + select, + textarea, + summary, + [tabindex] + ):focus-visible { + outline: 2px solid var(--m-focus); + outline-offset: 3px; + } + [data-mortar] a { + color: var(--m-link); + } + [data-mortar] :where(h1, h2, h3, p, figure, dl) { + margin: 0; + } + .m-button { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-height: var(--m-control); + padding: 4px var(--m-pad); + border: 1px solid transparent; + border-radius: var(--m-radius); + font-size: var(--m-font-size); + font-weight: 600; + line-height: 1.35; + text-decoration: none; + cursor: pointer; + } + .m-button-primary { + background: var(--m-primary); + color: var(--m-on-primary) !important; + border-color: var(--m-primary); + } + .m-button-primary:hover { + background: var(--m-primary-hover); + } + .m-button-primary:active { + background: var(--m-primary-active); + } + .m-button-secondary { + background: var(--m-surface); + color: var(--m-ink); + border-color: var(--m-line-strong); + } + .m-button-secondary:hover, + .m-button-ghost:hover { + background: var(--m-sunken); + } + .m-button-ghost { + background: transparent; + color: var(--m-secondary); + } + .m-button-danger { + background: transparent; + color: var(--m-danger); + border-color: var(--m-danger); + } + .m-button-danger:hover { + background: var(--m-sunken); + } + .m-button:active:not(:disabled) { + transform: translateY(1px); + } + .m-button:disabled { + background: var(--m-sunken); + color: var(--m-muted) !important; + border: 1px dashed var(--m-line-strong); + cursor: not-allowed; + } + .m-spinner { + width: 13px; + height: 13px; + border: 2px solid currentColor; + border-right-color: transparent; + border-radius: 50%; + animation: m-spin 0.8s linear infinite; + } + .m-field { + display: flex; + flex-direction: column; + gap: 6px; + min-width: 0; + } + .m-field > label, + .m-radio-group > legend { + font-size: 13px; + font-weight: 600; + } + .m-field p { + font-size: 12px; + color: var(--m-muted); + } + .m-input-group { + display: flex; + align-items: stretch; + border: 1px solid var(--m-line-strong); + border-radius: var(--m-radius); + background: var(--m-surface); + overflow: hidden; + } + .m-input-group:focus-within { + outline: 2px solid var(--m-focus); + outline-offset: 2px; + } + .m-input-group input { + min-width: 0; + width: 100%; + min-height: var(--m-control); + padding: 4px var(--m-pad); + border: 0; + background: transparent; + font-size: var(--m-font-size); + outline: none; + } + .m-input-group input:focus-visible { + outline: none; + } + .m-input-group > span { + display: flex; + align-items: center; + background: var(--m-sunken); + padding: 0 10px; + color: var(--m-muted); + font: 12px var(--m-mono); + } + .m-input-group[data-invalid], + .m-field [aria-invalid="true"] { + border-color: var(--m-danger); + } + .m-field select, + .m-field textarea { + min-height: var(--m-control); + padding: 6px var(--m-pad); + border: 1px solid var(--m-line-strong); + border-radius: var(--m-radius); + background: var(--m-surface); + font-size: var(--m-font-size); + } + .m-select-control { + position: relative; + display: grid; + min-width: 0; + } + .m-select-control select { + appearance: none; + width: 100%; + min-width: 0; + line-height: 1.4; + } + .m-select-control:not([data-listbox]) select { + height: var(--m-control); + padding-block: 0; + padding-inline-end: calc(var(--m-pad) + 24px); + cursor: pointer; + } + .m-select-control select:hover:not(:disabled):not([aria-invalid="true"]) { + border-color: var(--m-secondary); + } + .m-select-control svg { + position: absolute; + inset-inline-end: var(--m-pad); + top: 50%; + width: 16px; + height: 16px; + transform: translateY(-50%); + color: var(--m-secondary); + pointer-events: none; + } + .m-select-control:has(select:disabled) svg { + color: var(--m-muted); + } + @media (forced-colors: active) { + .m-select-control select { + appearance: auto; + } + .m-select-control svg { + display: none; + } + } + .m-field textarea { + min-height: 110px; + resize: vertical; + } + .m-field :disabled { + color: var(--m-muted); + background: var(--m-sunken); + cursor: not-allowed; + } + .m-error, + .m-field .m-error, + .m-tone-danger { + color: var(--m-danger); + } + .m-tone-neutral { + color: var(--m-secondary); + } + .m-tone-success { + color: var(--m-success); + } + .m-tone-warning { + color: var(--m-warning); + } + .m-choice { + display: flex; + align-items: center; + gap: 10px; + min-height: var(--m-control); + font-size: var(--m-font-size); + cursor: pointer; + } + [data-mortar] input:is([type="checkbox"], [type="radio"]) { + width: 18px; + height: 18px; + flex-shrink: 0; + accent-color: var(--m-primary); + cursor: pointer; + } + [data-mortar] input.m-switch { + appearance: none; + width: 34px; + height: 20px; + border: 1px solid var(--m-line-strong); + border-radius: 20px; + background: var(--m-sunken); + position: relative; + } + .m-switch::after { + content: ""; + position: absolute; + width: 14px; + height: 14px; + top: 2px; + left: 2px; + border-radius: 50%; + background: var(--m-muted); + transition: transform 0.15s; + } + [data-mortar] input.m-switch:checked { + background: var(--m-primary); + border-color: var(--m-primary); + } + .m-switch:checked::after { + transform: translateX(14px); + background: var(--m-on-primary); + } + .m-radio-group { + border: 0; + padding: 0; + margin: 0; + display: grid; + gap: 10px; + } + .m-radio-group legend { + margin-bottom: 10px; + } + .m-radio-card { + display: flex; + align-items: start; + gap: 12px; + border: 1px solid var(--m-line); + padding: 16px; + border-radius: var(--m-radius); + cursor: pointer; + } + .m-radio-card:has(:checked) { + background: var(--m-selected); + border-color: var(--m-primary); + } + .m-radio-card strong, + .m-radio-card span > span { + display: block; + font-size: 13px; + } + .m-radio-card span > span { + color: var(--m-muted); + margin-top: 4px; + } + .m-badge { + display: inline-flex; + align-items: center; + padding: 2px 8px; + gap: 6px; + font-size: 12px; + font-weight: 600; + border: 1px solid var(--m-line); + border-radius: 20px; + } + .m-badge::before { + content: ""; + width: 6px; + height: 6px; + border-radius: 50%; + background: currentColor; + } + .m-segmented { + display: inline-flex; + width: fit-content; + background: var(--m-sunken); + padding: 3px; + gap: 2px; + border-radius: var(--m-radius); + } + .m-segmented button { + border: 1px solid transparent; + background: transparent; + color: var(--m-muted); + font-size: 12px; + font-weight: 500; + border-radius: 6px; + padding: 5px 10px; + cursor: pointer; + min-height: 28px; + } + .m-segmented [aria-pressed="true"] { + background: var(--m-surface); + color: var(--m-ink); + border-color: var(--m-line); + } + .m-tabs { + display: flex; + gap: 24px; + border-bottom: 1px solid var(--m-line); + overflow-x: auto; + } + .m-tabs button { + border: 0; + border-bottom: 2px solid transparent; + background: none; + color: var(--m-muted); + font-size: 14px; + font-weight: 600; + padding: 12px 0; + white-space: nowrap; + cursor: pointer; + } + .m-tabs [aria-selected="true"] { + color: var(--m-link); + border-bottom-color: var(--m-link); + } + [role="tabpanel"]:not([hidden]) { + padding-top: 24px; + } + .m-notice { + border: 1px solid var(--m-line); + border-radius: var(--m-radius); + padding: 16px; + font-size: 14px; + } + .m-notice > div { + margin-top: 6px; + } + .m-empty { + text-align: center; + padding: 64px 24px; + } + .m-empty h3 { + font-size: 18px; + font-weight: 600; + } + .m-empty p { + color: var(--m-muted); + margin: 10px 0 20px; + } + .m-dialog { + position: fixed; + inset: 0; + z-index: 100; + } + .m-backdrop { + position: fixed; + inset: 0; + background: rgb(0 0 0 / 0.5); + } + .m-dialog-position { + position: fixed; + inset: 0; + overflow-y: auto; + display: flex; + justify-content: center; + align-items: flex-start; + padding: 24px; + } + .m-dialog-panel { + margin-block: auto; + flex-shrink: 0; + width: 100%; + max-width: 520px; + border: 1px solid var(--m-line); + border-radius: var(--m-radius-lg); + background: var(--m-surface); + padding: 24px; + box-shadow: var(--m-float); + } + .m-dialog-heading { + display: flex; + justify-content: space-between; + align-items: center; + gap: 16px; + margin-bottom: 20px; + } + .m-dialog-heading h2 { + font-size: 20px; + font-weight: 600; + } + .m-dialog-panel > .m-actions { + margin-top: 24px; + justify-content: flex-end; + } + .m-menu { + z-index: 110; + min-width: 200px; + border: 1px solid var(--m-line); + padding: 6px; + border-radius: var(--m-radius); + background: var(--m-surface); + box-shadow: var(--m-float); + --anchor-gap: 6px; + } + .m-menu button { + display: block; + width: 100%; + text-align: left; + border: 0; + background: none; + padding: 8px 10px; + border-radius: 4px; + font-size: 14px; + cursor: pointer; + } + .m-menu button[data-focus] { + background: var(--m-selected); + } + .m-menu button[data-disabled] { + color: var(--m-muted); + cursor: not-allowed; + } + .m-actions { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 10px; + } + .m-stack { + display: flex; + flex-direction: column; + gap: 20px; + } + .m-sr-only, + .m-skip { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip-path: inset(50%); + white-space: nowrap; + } + .m-skip:focus { + width: auto; + height: auto; + padding: 12px; + top: 8px; + left: 8px; + clip-path: none; + z-index: 120; + background: var(--m-surface); + } + .m-app-shell { + min-height: 100vh; + background: var(--m-paper); + } + .m-sidebar { + position: fixed; + inset: 0 auto 0 0; + width: 240px; + padding: 12px; + border-right: 1px solid var(--m-line); + background: var(--m-sunken); + display: flex; + flex-direction: column; + overflow-y: auto; + z-index: 30; + } + .m-workspace { + display: flex; + align-items: center; + gap: 10px; + padding: 10px; + border: 1px solid var(--m-line); + border-radius: 10px; + background: var(--m-surface); + text-decoration: none; + } + .m-workspace strong { + font-size: 14px; + display: block; + } + .m-workspace small { + display: block; + color: var(--m-muted); + font-size: 11px; + } + .m-mark { + display: inline-block; + width: 22px; + height: 22px; + flex-shrink: 0; + border-radius: 5px; + background: var(--m-primary); + } + :is(.m-sidebar, .m-mobile-sidebar) nav { + margin-top: 18px; + display: flex; + flex-direction: column; + gap: 2px; + } + :is(.m-sidebar, .m-mobile-sidebar) nav a { + display: flex; + align-items: center; + gap: 10px; + padding: 6px 10px; + min-height: var(--m-control); + border-radius: var(--m-radius); + text-decoration: none; + font-size: var(--m-font-size); + font-weight: 500; + color: var(--m-secondary); + } + :is(.m-sidebar, .m-mobile-sidebar) nav a:hover { + background: var(--m-surface); + } + :is(.m-sidebar, .m-mobile-sidebar) nav a[aria-current="page"] { + background: var(--m-surface); + color: var(--m-link); + font-weight: 600; + } + .m-nav-marker { + width: 6px; + height: 6px; + border-radius: 2px; + background: var(--m-line-strong); + } + [aria-current="page"] .m-nav-marker { + background: currentColor; + } + .m-nav-count { + margin-left: auto; + font: 11px var(--m-mono); + color: var(--m-muted); + } + :is(.m-sidebar, .m-mobile-sidebar) nav h2 { + margin: 24px 10px 6px; + text-transform: uppercase; + font-size: 11px; + letter-spacing: 0.04em; + color: var(--m-muted); + } + .m-user { + margin-top: auto; + padding: 16px 8px 4px; + font-size: 13px; + } + .m-app-main { + margin-left: 240px; + min-width: 0; + } + .m-app-header { + display: flex; + align-items: center; + gap: 16px; + min-height: 56px; + padding: 10px 28px; + border-bottom: 1px solid var(--m-line); + background: var(--m-surface); + } + .m-header-context { + flex: 1; + min-width: 0; + color: var(--m-muted); + font-size: 13px; + } + .m-app-main > main { + padding: 28px; + } + .m-menu-trigger { + display: none; + } + .m-mobile-sidebar { + position: fixed; + inset: 0 auto 0 0; + width: min(320px, 90vw); + padding: 16px; + background: var(--m-sunken); + overflow-y: auto; + } + .m-page-heading :is(h1, h2) { + font-size: 28px; + letter-spacing: -0.025em; + line-height: 1.2; + font-weight: 600; + } + .m-page-heading p { + margin-top: 6px; + color: var(--m-muted); + font-size: 14px; + } + .m-heading-row { + display: flex; + align-items: end; + gap: 20px; + flex-wrap: wrap; + justify-content: space-between; + } + .m-page-heading nav ol { + display: flex; + gap: 8px; + margin: 0 0 12px; + padding: 0; + list-style: none; + font-size: 13px; + color: var(--m-muted); + } + .m-page-heading nav li:not(:first-child)::before { + content: "/"; + margin-right: 8px; + } + .m-eyebrow { + font: 12px var(--m-mono); + color: var(--m-muted); + margin-bottom: 16px !important; + } + .m-metrics { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + border: 1px solid var(--m-line); + border-radius: var(--m-radius-lg); + background: var(--m-surface); + overflow: hidden; + } + .m-metrics > div { + padding: 18px; + border-right: 1px solid var(--m-line); + } + .m-metrics > div:last-child { + border-right: 0; + } + .m-metrics dt { + font-size: 12px; + font-weight: 600; + color: var(--m-muted); + } + .m-metrics dd { + margin: 10px 0 0; + font-size: 26px; + font-weight: 600; + letter-spacing: -0.02em; + font-variant-numeric: tabular-nums; + } + .m-metrics span { + display: block; + margin-top: 4px; + font: 12px var(--m-mono); + } + .m-data-table { + border: 1px solid var(--m-line); + border-radius: var(--m-radius-lg); + background: var(--m-surface); + overflow: hidden; + min-width: 0; + } + .m-table-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 12px; + padding: 12px; + border-bottom: 1px solid var(--m-line); + font-size: 13px; + } + .m-table-scroll { + overflow-x: auto; + } + .m-data-table table { + border-collapse: collapse; + width: 100%; + font-size: var(--m-font-size); + text-align: left; + } + .m-data-table :is(th, td) { + padding: var(--m-row-pad); + border-bottom: 1px solid var(--m-line); + white-space: nowrap; + } + .m-data-table thead th { + color: var(--m-muted); + font-size: 12px; + font-weight: 600; + background: var(--m-paper); + } + .m-data-table tbody th { + font-weight: 600; + } + .m-data-table tr:last-child :is(th, td) { + border-bottom: 0; + } + .m-data-table [data-align="right"] { + text-align: right; + font-variant-numeric: tabular-nums; + } + .m-data-table [data-selected] { + background: var(--m-selected); + } + .m-table-state { + padding: 32px; + color: var(--m-muted); + } + .m-pagination { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + font-size: 13px; + color: var(--m-muted); + flex-wrap: wrap; + } + .m-settings-section { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + gap: 40px; + border-bottom: 1px solid var(--m-line); + padding: 28px 0; + } + .m-settings-section h2 { + font-size: 16px; + font-weight: 600; + } + .m-settings-section p { + margin-top: 6px; + font-size: 13px; + color: var(--m-muted); + } + .m-activity { + padding: 0; + margin: 0; + list-style: none; + } + .m-activity li { + display: flex; + align-items: start; + gap: 12px; + padding: 16px 0; + border-bottom: 1px solid var(--m-line); + font-size: 13px; + } + .m-activity li > div { + flex: 1; + } + .m-activity p, + .m-activity li > span:last-child { + color: var(--m-muted); + } + .m-activity-dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: currentColor; + margin-top: 6px; + flex-shrink: 0; + } + .m-marketing-header { + max-width: 1280px; + margin: auto; + padding: 18px 32px; + display: flex; + align-items: center; + gap: 28px; + border-bottom: 1px solid var(--m-line); + } + .m-brand { + display: flex; + align-items: center; + gap: 10px; + text-decoration: none; + font-size: 17px; + font-weight: 700; + letter-spacing: -0.02em; + } + .m-marketing-header nav { + display: flex; + gap: 22px; + flex: 1; + font-size: 13px; + } + .m-marketing-header nav a { + text-decoration: none; + color: var(--m-secondary); + } + .m-marketing-header > .m-actions { + margin-left: auto; + } + .m-hero { + padding: 100px 32px 80px; + max-width: 1280px; + margin: auto; + } + .m-hero-center { + text-align: center; + } + .m-hero :is(h1, h2) { + font-size: clamp(42px, 6vw, 80px); + font-weight: 600; + letter-spacing: -0.045em; + line-height: 1.02; + text-wrap: balance; + max-width: 960px; + margin: auto; + } + .m-hero-description { + color: var(--m-secondary); + font-size: 18px; + max-width: 660px; + margin: 28px auto !important; + text-wrap: pretty; + } + .m-hero-center .m-actions { + justify-content: center; + } + .m-hero-split { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 56px; + align-items: center; + } + .m-hero-split :is(h1, h2) { + font-size: clamp(40px, 5vw, 64px); + } + .m-hero-preview { + margin-top: 48px; + text-align: left; + min-width: 0; + } + .m-hero-split .m-hero-preview { + margin-top: 0; + } + .m-marketing-section, + .m-feature-section, + .m-faq { + max-width: 1280px; + margin: auto; + padding: 80px 32px; + border-top: 1px solid var(--m-line); + } + :is(.m-marketing-section, .m-feature-section, .m-faq, .m-cta) h2 { + font-size: clamp(30px, 3.5vw, 48px); + font-weight: 600; + letter-spacing: -0.035em; + line-height: 1.1; + text-wrap: balance; + max-width: 800px; + } + .m-section-description { + color: var(--m-secondary); + font-size: 16px; + margin-top: 18px !important; + max-width: 640px; + } + .m-feature-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 48px 40px; + margin-top: 48px; + } + .m-feature-icon { + display: grid; + place-items: center; + width: 36px; + height: 36px; + border: 1px solid var(--m-line); + border-radius: 8px; + font: 12px var(--m-mono); + margin-bottom: 16px; + } + .m-feature-grid h3 { + font-size: 16px; + font-weight: 600; + } + .m-feature-grid p, + .m-feature-section p { + color: var(--m-secondary); + font-size: 15px; + margin-top: 10px; + } + .m-feature-section { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); + gap: 56px; + align-items: center; + } + .m-feature-section[data-reverse="true"] > div:first-child { + order: 2; + } + .m-feature-preview { + border: 1px solid var(--m-line); + border-radius: 12px; + padding: 28px; + background: var(--m-sunken); + min-width: 0; + } + .m-testimonial { + padding: 64px 32px; + text-align: center; + max-width: 960px; + margin: auto; + } + .m-testimonial blockquote { + font-size: clamp(24px, 3vw, 36px); + line-height: 1.3; + letter-spacing: -0.02em; + margin: 0 0 28px; + } + .m-testimonial figcaption { + display: flex; + flex-direction: column; + font-size: 14px; + } + .m-testimonial figcaption span { + color: var(--m-muted); + } + .m-logo-cloud { + padding: 40px 32px; + text-align: center; + color: var(--m-muted); + } + .m-logo-cloud > p { + font-size: 13px; + } + .m-logo-cloud ul { + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 48px; + list-style: none; + padding: 24px 0; + margin: 0; + font-size: 22px; + font-weight: 600; + } + .m-logo-cloud img { + max-height: 32px; + max-width: 140px; + } + .m-pricing > .m-segmented { + margin-top: 28px; + } + .m-pricing-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); + gap: 18px; + margin-top: 36px; + } + .m-pricing-grid article { + border: 1px solid var(--m-line); + border-radius: 12px; + padding: 28px; + display: flex; + flex-direction: column; + } + .m-pricing-grid article[data-featured="true"] { + background: var(--m-ink); + color: var(--m-paper); + } + .m-pricing-grid h3 { + font-size: 18px; + font-weight: 600; + } + .m-pricing-grid p { + font-size: 14px; + margin-top: 6px; + } + .m-price { + margin: 28px 0; + display: flex; + flex-direction: column; + gap: 4px; + } + .m-price strong { + font-size: 44px; + line-height: 1; + letter-spacing: -0.04em; + font-weight: 600; + } + .m-price span { + font-size: 13px; + } + .m-pricing-grid ul { + list-style: none; + padding: 0; + margin: 0 0 28px; + flex: 1; + } + .m-pricing-grid li { + font-size: 14px; + margin: 10px 0; + } + .m-pricing-grid li::before { + content: "—"; + opacity: 0.6; + margin-right: 10px; + } + .m-faq { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 56px; + } + .m-faq > div > div { + color: var(--m-secondary); + margin-top: 14px; + } + .m-faq details { + border-bottom: 1px solid var(--m-line); + } + .m-faq details:first-child { + border-top: 1px solid var(--m-line); + } + .m-faq summary { + display: flex; + align-items: center; + justify-content: space-between; + gap: 20px; + font-size: 17px; + font-weight: 600; + padding: 20px 0; + cursor: pointer; + list-style: none; + } + .m-faq summary::-webkit-details-marker { + display: none; + } + .m-faq summary span { + font-size: 22px; + color: var(--m-muted); + } + .m-faq [open] summary span { + transform: rotate(45deg); + } + .m-faq details > div { + color: var(--m-secondary); + padding: 0 0 22px; + font-size: 15px; + } + .m-cta { + text-align: center; + background: var(--m-ink); + color: var(--m-paper); + padding: 96px 32px; + } + .m-cta h2 { + margin: auto; + } + .m-cta p { + margin: 20px auto; + max-width: 640px; + } + .m-cta .m-actions { + justify-content: center; + margin-top: 32px; + } + .m-cta .m-button-primary { + background: var(--m-paper); + color: var(--m-ink) !important; + border-color: var(--m-paper); + } + .m-cta .m-button-secondary { + background: transparent; + color: var(--m-paper); + border-color: var(--m-paper); + } + .m-footer { + max-width: 1280px; + padding: 56px 32px 32px; + margin: auto; + } + .m-footer-grid { + display: grid; + grid-template-columns: 1.5fr repeat(4, 1fr); + gap: 32px; + } + .m-footer-grid p { + color: var(--m-muted); + margin-top: 10px; + font-size: 14px; + max-width: 260px; + } + .m-footer-grid h2 { + font-size: 13px; + font-weight: 600; + margin-bottom: 12px; + } + .m-footer-grid nav a { + display: block; + font-size: 14px; + color: var(--m-muted); + text-decoration: none; + margin-top: 8px; + } + .m-footer-bottom { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + gap: 16px; + border-top: 1px solid var(--m-line); + margin-top: 56px; + padding-top: 20px; + color: var(--m-muted); + font-size: 13px; + } + .m-footer-bottom > div { + display: flex; + gap: 20px; + } + @media (max-width: 900px) { + .m-sidebar { + display: none; + } + .m-app-main { + margin-left: 0; + } + .m-menu-trigger { + display: inline-flex; + } + .m-app-header { + flex-wrap: wrap; + padding: 12px 20px; + } + .m-app-main > main { + padding: 24px 20px; + } + .m-marketing-header { + flex-wrap: wrap; + padding: 16px 20px; + gap: 16px; + } + .m-marketing-header .m-menu-trigger { + margin-left: auto; + } + .m-marketing-header > .m-actions { + margin-left: 0; + } + .m-marketing-header nav { + display: none; + order: 4; + flex-basis: 100%; + flex-direction: column; + } + .m-marketing-header nav[data-open="true"] { + display: flex; + } + .m-hero-split, + .m-feature-section, + .m-faq { + grid-template-columns: minmax(0, 1fr); + gap: 32px; + } + .m-feature-section[data-reverse="true"] > div:first-child { + order: 0; + } + .m-feature-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 32px; + } + .m-footer-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .m-footer-grid > div { + grid-column: 1/-1; + } + } + @media (max-width: 540px) { + .m-input-group input, + .m-field select, + .m-field textarea { + font-size: 16px; + } + .m-hero, + .m-marketing-section, + .m-feature-section, + .m-faq { + padding: 48px 20px; + } + .m-hero-description { + font-size: 16px; + } + .m-feature-grid { + grid-template-columns: 1fr; + } + .m-settings-section { + grid-template-columns: 1fr; + gap: 20px; + } + .m-pricing-grid article { + padding: 24px; + } + .m-metrics { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .m-metrics > div { + border-bottom: 1px solid var(--m-line); + } + .m-metrics dd { + font-size: 24px; + } + } + @media (prefers-reduced-motion: reduce) { + .m-spinner { + animation: none; + } + .m-switch::after { + transition: none; + } + } + @media (pointer: coarse) { + .m-segmented button, + .m-tabs button { + min-height: 44px; + } + } +} +@keyframes m-spin { + to { + transform: rotate(360deg); + } +} +@layer components { + .m-code-block { + min-width: 0; + margin: 0; + } + .m-code-block figcaption { + margin-bottom: 0.5rem; + color: var(--m-muted); + font-size: 0.875rem; + } + .m-code-block pre { + overflow: auto; + max-height: 32rem; + padding: 1rem; + border: 1px solid var(--m-line); + border-radius: 0.5rem; + background: var(--m-sunken); + font-size: 0.875rem; + line-height: 1.6; + } + .m-preview-frame { + display: grid; + min-width: 0; + gap: 0.75rem; + } + .m-preview-frame > a { + justify-self: end; + text-decoration: underline; + } + .m-preview-frame iframe { + width: 100%; + height: 36rem; + border: 1px solid var(--m-line); + border-radius: 0.5rem; + background: var(--m-paper); + } +} diff --git a/src/foundation.tsx b/src/foundation.tsx new file mode 100644 index 0000000..4c9afbd --- /dev/null +++ b/src/foundation.tsx @@ -0,0 +1,99 @@ +import { + createContext, + useContext, + useEffect, + useState, + type ReactNode, +} from "react"; + +export type Appearance = "light" | "dark" | "system"; +export type Brand = "neutral" | "green"; +export type Density = "compact" | "comfortable" | "spacious"; +type Theme = { + appearance: Appearance; + setAppearance: (value: Appearance) => void; + brand: Brand; + density: Density; +}; +const ThemeContext = createContext(null); +export interface ThemeProviderProps { + children: ReactNode; + initialAppearance?: Appearance; + brand?: Brand; + density?: Density; +} +/** One provider per application. Selection never requires a hosted account. */ +export function ThemeProvider({ + children, + initialAppearance = "system", + brand = "neutral", + density = "comfortable", +}: ThemeProviderProps) { + const [appearance, setAppearance] = useState(initialAppearance); + useEffect(() => { + const element = document.documentElement; + const attributes = { + "data-mortar": "", + "data-mortar-brand": brand, + "data-mortar-density": density, + }; + const previous = Object.keys(attributes).map( + (key) => [key, element.getAttribute(key)] as const, + ); + for (const [key, value] of Object.entries(attributes)) + element.setAttribute(key, value); + return () => { + for (const [key, value] of previous) + value === null + ? element.removeAttribute(key) + : element.setAttribute(key, value); + }; + }, [brand, density]); + useEffect(() => { + const element = document.documentElement; + const previous = element.getAttribute("data-mortar-appearance"); + const media = window.matchMedia("(prefers-color-scheme: dark)"); + const update = () => + element.setAttribute( + "data-mortar-appearance", + appearance === "system" + ? media.matches + ? "dark" + : "light" + : appearance, + ); + update(); + media.addEventListener("change", update); + return () => { + media.removeEventListener("change", update); + previous === null + ? element.removeAttribute("data-mortar-appearance") + : element.setAttribute("data-mortar-appearance", previous); + }; + }, [appearance]); + return ( + + {children} + + ); +} +export function AppearanceControl() { + const context = useContext(ThemeContext); + if (!context) throw new Error("AppearanceControl requires ThemeProvider"); + return ( +
+ {(["light", "dark", "system"] as const).map((value) => ( + + ))} +
+ ); +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..19c0e6a --- /dev/null +++ b/src/index.ts @@ -0,0 +1,57 @@ +export { ThemeProvider, AppearanceControl } from "./foundation.js"; +export type { + ThemeProviderProps, + Appearance, + Brand, + Density, +} from "./foundation.js"; +export { + Button, + ActionLink, + Input, + Select, + TextArea, + Checkbox, + RadioGroup, + Switch, + Badge, + Tabs, + Modal, + Dropdown, + Notice, + EmptyState, +} from "./primitives.js"; +export type { + ButtonProps, + InputProps, + LinkAction, + Tone, +} from "./primitives.js"; +export { + AppShell, + PageHeading, + MetricGroup, + DataTable, + Pagination, + SettingsSection, + ActivityFeed, +} from "./application.js"; +export type { + AppShellProps, + NavigationItem, + DataTableProps, +} from "./application.js"; +export { + MarketingHeader, + Hero, + FeatureGrid, + FeatureSection, + Testimonial, + LogoCloud, + Pricing, + FAQ, + CallToAction, + Footer, +} from "./marketing.js"; +export type { PricingPlan } from "./marketing.js"; +export { SegmentedControl, CodeBlock, PreviewFrame } from "./inspection.js"; diff --git a/src/inspection.tsx b/src/inspection.tsx new file mode 100644 index 0000000..9fdd390 --- /dev/null +++ b/src/inspection.tsx @@ -0,0 +1,59 @@ +import { useId } from "react"; +export function SegmentedControl({ + label, + value, + options, + onChange, +}: { + label: string; + value: string; + options: { value: string; label: string }[]; + onChange: (value: string) => void; +}) { + return ( +
+ {options.map((option) => ( + + ))} +
+ ); +} +export function CodeBlock({ + code, + label = "Code", +}: { + code: string; + label?: string; +}) { + const id = useId(); + return ( +
+
{label}
+
+        {code}
+      
+
+ ); +} +export function PreviewFrame({ title, src }: { title: string; src: string }) { + return ( +
+ + Open full preview + +