Compare commits
19 Commits
94506aa349
...
f442c07dbf
| Author | SHA1 | Date | |
|---|---|---|---|
| f442c07dbf | |||
| 93e7941dc4 | |||
| e70ad64b19 | |||
| 2dbf51ba24 | |||
| dc80bd8ae0 | |||
| 60f6f1fb1a | |||
| a03b04ed3f | |||
| f246d81088 | |||
| 6cd981d6a2 | |||
| ea00a71112 | |||
| 1fc56b6982 | |||
| e02c3dceb5 | |||
| 2043c7d777 | |||
| 6cd7d436ef | |||
| 87df34a8ab | |||
| 2c05cfa86d | |||
| 5fced3817c | |||
| c64864b3b5 | |||
| bc84912e48 |
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
name: "icones"
|
||||||
|
description: "The same icon vocabulary, with an API that belongs in your React application."
|
||||||
|
---
|
||||||
|
|
||||||
|
Up-to-date icones documentation for this project. Read it before working with icones:
|
||||||
|
|
||||||
|
https://icones.go-slim.dev/llms/react/llms-full.txt
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
max_line_length = 120
|
||||||
|
tab_width = 2
|
||||||
|
|
||||||
|
[*.{json,md}]
|
||||||
|
insert_final_newline = false
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
indent_size = 4
|
||||||
+1
-1
@@ -19,4 +19,4 @@
|
|||||||
},
|
},
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"trailingComma": "es5"
|
"trailingComma": "es5"
|
||||||
}
|
}
|
||||||
+1
-1
@@ -30,4 +30,4 @@
|
|||||||
"import",
|
"import",
|
||||||
"vitest"
|
"vitest"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
+3
-2
@@ -22,5 +22,6 @@
|
|||||||
"!vscode-css-language-server"
|
"!vscode-css-language-server"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
"format_on_save": "off"
|
||||||
|
}
|
||||||
@@ -20,4 +20,4 @@
|
|||||||
"rtl": true,
|
"rtl": true,
|
||||||
"menuColor": "default",
|
"menuColor": "default",
|
||||||
"menuAccent": "subtle"
|
"menuAccent": "subtle"
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"sourceLocale": "en",
|
"sourceLocale": "en-US",
|
||||||
"locales": ["en", "zh-Hans"],
|
"locales": ["en-US", "zh-Hans"],
|
||||||
"catalogPath": "src/locales/{locale}/messages",
|
"catalogPath": "src/locales/{locale}/messages",
|
||||||
"catalogSources": [
|
"catalogSources": [
|
||||||
"@workspace/ui/locales/{locale}",
|
"@workspace/ui/locales/{locale}",
|
||||||
@@ -10,9 +10,14 @@
|
|||||||
"@workspace/blocks/media/locales/{locale}",
|
"@workspace/blocks/media/locales/{locale}",
|
||||||
"@workspace/blocks/navigation/locales/{locale}",
|
"@workspace/blocks/navigation/locales/{locale}",
|
||||||
"@workspace/blocks/notifications/locales/{locale}",
|
"@workspace/blocks/notifications/locales/{locale}",
|
||||||
"@workspace/blocks/search/locales/{locale}",
|
"@workspace/search/locales/{locale}",
|
||||||
"@workspace/lexical/locales/{locale}"
|
"@workspace/lexical/locales/{locale}"
|
||||||
],
|
],
|
||||||
"include": ["src", "../../packages/blocks/src", "../../packages/ui/src"],
|
"include": [
|
||||||
|
"src",
|
||||||
|
"../../packages/blocks/src",
|
||||||
|
"../../packages/search/src",
|
||||||
|
"../../packages/ui/src"
|
||||||
|
],
|
||||||
"exclude": ["**/*.test.{ts,tsx}", "**/node_modules/**"]
|
"exclude": ["**/*.test.{ts,tsx}", "**/node_modules/**"]
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"@base-ui/react": "^1.6.0",
|
"@base-ui/react": "^1.6.0",
|
||||||
"@base-ui/utils": "^0.3.1",
|
"@base-ui/utils": "^0.3.1",
|
||||||
"@floating-ui/utils": "^0.2.12",
|
"@floating-ui/utils": "^0.2.12",
|
||||||
"@iconify/react": "^6.0.2",
|
"@icones/react": "^0.0.1",
|
||||||
"@lingui/core": "^6",
|
"@lingui/core": "^6",
|
||||||
"@tanstack/react-form": "^1.33.2",
|
"@tanstack/react-form": "^1.33.2",
|
||||||
"@tanstack/react-hotkeys": "^0.10.0",
|
"@tanstack/react-hotkeys": "^0.10.0",
|
||||||
@@ -27,12 +27,10 @@
|
|||||||
"@tanstack/react-router": "^1.170.18",
|
"@tanstack/react-router": "^1.170.18",
|
||||||
"@tanstack/react-start": "^1.168.32",
|
"@tanstack/react-start": "^1.168.32",
|
||||||
"@workspace/blocks": "workspace:*",
|
"@workspace/blocks": "workspace:*",
|
||||||
"@workspace/icons": "workspace:*",
|
|
||||||
"@workspace/i18n": "workspace:*",
|
"@workspace/i18n": "workspace:*",
|
||||||
"@workspace/lexical": "workspace:*",
|
"@workspace/lexical": "workspace:*",
|
||||||
|
"@workspace/search": "workspace:*",
|
||||||
"@workspace/ui": "workspace:*",
|
"@workspace/ui": "workspace:*",
|
||||||
"country-flag-icons": "^1.6.20",
|
|
||||||
"lucide-react": "^1.27.0",
|
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-day-picker": "^10.0.1",
|
"react-day-picker": "^10.0.1",
|
||||||
"react-dom": "^19.2.6",
|
"react-dom": "^19.2.6",
|
||||||
@@ -40,6 +38,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/vite": "^4",
|
"@tailwindcss/vite": "^4",
|
||||||
|
"@icones/vite": "^0.0.1",
|
||||||
"@testing-library/react": "^16.3.2",
|
"@testing-library/react": "^16.3.2",
|
||||||
"@types/node": "^24",
|
"@types/node": "^24",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
@@ -51,4 +50,4 @@
|
|||||||
"vite": "^8",
|
"vite": "^8",
|
||||||
"vitest": "^4.1.10"
|
"vitest": "^4.1.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import type React from "react"
|
||||||
|
|
||||||
|
type Props = Omit<React.ComponentProps<"svg">, "role" | "viewBox" | "xmlns">
|
||||||
|
|
||||||
|
export function Logo(props: Props) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="#7AB55C"
|
||||||
|
aria-hidden="true"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<title>Shopify</title>
|
||||||
|
<path d="M15.337 23.979l7.216-1.561s-2.604-17.613-2.625-17.73c-.018-.116-.114-.192-.211-.192s-1.929-.136-1.929-.136-1.275-1.274-1.439-1.411c-.045-.037-.075-.057-.121-.074l-.914 21.104h.023zM11.71 11.305s-.81-.424-1.774-.424c-1.447 0-1.504.906-1.504 1.141 0 1.232 3.24 1.715 3.24 4.629 0 2.295-1.44 3.76-3.406 3.76-2.354 0-3.54-1.465-3.54-1.465l.646-2.086s1.245 1.066 2.28 1.066c.675 0 .975-.545.975-.932 0-1.619-2.654-1.694-2.654-4.359-.034-2.237 1.571-4.416 4.827-4.416 1.257 0 1.875.361 1.875.361l-.945 2.715-.02.01zM11.17.83c.136 0 .271.038.405.135-.984.465-2.064 1.639-2.508 3.992-.656.213-1.293.405-1.889.578C7.697 3.75 8.951.84 11.17.84V.83zm1.235 2.949v.135c-.754.232-1.583.484-2.394.736.466-1.777 1.333-2.645 2.085-2.971.193.501.309 1.176.309 2.1zm.539-2.234c.694.074 1.141.867 1.429 1.755-.349.114-.735.231-1.158.366v-.252c0-.752-.096-1.371-.271-1.871v.002zm2.992 1.289c-.02 0-.06.021-.078.021s-.289.075-.714.21c-.423-1.233-1.176-2.37-2.508-2.37h-.115C12.135.209 11.669 0 11.265 0 8.159 0 6.675 3.877 6.21 5.846c-1.194.365-2.063.636-2.16.674-.675.213-.694.232-.772.87-.075.462-1.83 14.063-1.83 14.063L15.009 24l.927-21.166z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
TriangleAlertIcon,
|
TriangleAlertIcon,
|
||||||
OctagonXIcon,
|
OctagonXIcon,
|
||||||
Loader2Icon,
|
Loader2Icon,
|
||||||
} from "lucide-react"
|
} from "@workspace/ui/components/icon"
|
||||||
|
|
||||||
const Toaster = ({ ...props }: ToasterProps) => {
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
const [themeMode] = useUiState("theme-mode")
|
const [themeMode] = useUiState("theme-mode")
|
||||||
|
|||||||
+77
-137
@@ -1,63 +1,3 @@
|
|||||||
import {
|
|
||||||
Alert02Icon,
|
|
||||||
Analytics01Icon,
|
|
||||||
AnalyticsUpIcon,
|
|
||||||
AppWindowIcon,
|
|
||||||
ArrowDataTransferHorizontalIcon,
|
|
||||||
BubbleChatIcon,
|
|
||||||
Calculator01Icon,
|
|
||||||
CallMissed01Icon,
|
|
||||||
CancelCircleIcon,
|
|
||||||
Chart01Icon,
|
|
||||||
ChartIncreaseIcon,
|
|
||||||
CheckmarkBadge01Icon,
|
|
||||||
CheckmarkCircle01Icon,
|
|
||||||
ClipboardListIcon,
|
|
||||||
Clock01Icon,
|
|
||||||
CodeSquareIcon,
|
|
||||||
Compass01Icon,
|
|
||||||
CreditCardIcon,
|
|
||||||
CrownIcon,
|
|
||||||
Delete02Icon,
|
|
||||||
DeliveryTruck01Icon,
|
|
||||||
Discount01Icon,
|
|
||||||
File01Icon,
|
|
||||||
GalleryHorizontalIcon,
|
|
||||||
GiftIcon,
|
|
||||||
HistoryIcon,
|
|
||||||
IdentityCardIcon,
|
|
||||||
InboxDownloadIcon,
|
|
||||||
InboxUploadIcon,
|
|
||||||
Invoice03Icon,
|
|
||||||
Key01Icon,
|
|
||||||
LinkCircleIcon,
|
|
||||||
Location01Icon,
|
|
||||||
LockKeyIcon,
|
|
||||||
Medal01Icon,
|
|
||||||
MoneySendSquareIcon,
|
|
||||||
Note01Icon,
|
|
||||||
Package02Icon,
|
|
||||||
PackageIcon,
|
|
||||||
Refresh01Icon,
|
|
||||||
RoadLocation01Icon,
|
|
||||||
SecurityWarningIcon,
|
|
||||||
Settings01Icon,
|
|
||||||
Settings03Icon,
|
|
||||||
Share01Icon,
|
|
||||||
ShoppingBag01Icon,
|
|
||||||
ShoppingCart01Icon,
|
|
||||||
StarCircleIcon,
|
|
||||||
StarIcon,
|
|
||||||
Store01Icon,
|
|
||||||
Structure01Icon,
|
|
||||||
Task01Icon,
|
|
||||||
Ticket01Icon,
|
|
||||||
UserGroupIcon,
|
|
||||||
UserShield01Icon,
|
|
||||||
Wallet01Icon,
|
|
||||||
WalletCardsIcon,
|
|
||||||
} from "@workspace/icons"
|
|
||||||
|
|
||||||
import type { NavigationGroup } from "@workspace/blocks/navigation"
|
import type { NavigationGroup } from "@workspace/blocks/navigation"
|
||||||
|
|
||||||
import { navigationMessages } from "./navigation-messages"
|
import { navigationMessages } from "./navigation-messages"
|
||||||
@@ -71,19 +11,19 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "overview-dashboard",
|
id: "overview-dashboard",
|
||||||
to: "/",
|
to: "/",
|
||||||
label: navigationMessages["overview-dashboard"],
|
label: navigationMessages["overview-dashboard"],
|
||||||
icon: Analytics01Icon,
|
icon: "huge:analytics-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "overview-realtime",
|
id: "overview-realtime",
|
||||||
to: "/analytics/realtime",
|
to: "/analytics/realtime",
|
||||||
label: navigationMessages["overview-realtime"],
|
label: navigationMessages["overview-realtime"],
|
||||||
icon: AnalyticsUpIcon,
|
icon: "huge:analytics-up",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "overview-tasks",
|
id: "overview-tasks",
|
||||||
to: "/workspace/tasks",
|
to: "/workspace/tasks",
|
||||||
label: navigationMessages["overview-tasks"],
|
label: navigationMessages["overview-tasks"],
|
||||||
icon: Task01Icon,
|
icon: "huge:task-01",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -94,42 +34,42 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
{
|
{
|
||||||
id: "catalog-products",
|
id: "catalog-products",
|
||||||
label: navigationMessages["catalog-products"],
|
label: navigationMessages["catalog-products"],
|
||||||
icon: ShoppingBag01Icon,
|
icon: "huge:shopping-bag-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "catalog-products-list",
|
id: "catalog-products-list",
|
||||||
to: "/catalog/products/list",
|
to: "/catalog/products/list",
|
||||||
label: navigationMessages["catalog-products-list"],
|
label: navigationMessages["catalog-products-list"],
|
||||||
icon: ShoppingBag01Icon,
|
icon: "huge:shopping-bag-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "catalog-products-drafts",
|
id: "catalog-products-drafts",
|
||||||
to: "/catalog/products/drafts",
|
to: "/catalog/products/drafts",
|
||||||
label: navigationMessages["catalog-products-drafts"],
|
label: navigationMessages["catalog-products-drafts"],
|
||||||
icon: File01Icon,
|
icon: "huge:file-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "catalog-products-bundles",
|
id: "catalog-products-bundles",
|
||||||
to: "/catalog/products/bundles",
|
to: "/catalog/products/bundles",
|
||||||
label: navigationMessages["catalog-products-bundles"],
|
label: navigationMessages["catalog-products-bundles"],
|
||||||
icon: Package02Icon,
|
icon: "huge:package-02",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "catalog-products-attributes",
|
id: "catalog-products-attributes",
|
||||||
label: navigationMessages["catalog-products-attributes"],
|
label: navigationMessages["catalog-products-attributes"],
|
||||||
icon: Settings03Icon,
|
icon: "huge:settings-03",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "catalog-product-specifications",
|
id: "catalog-product-specifications",
|
||||||
to: "/catalog/products/attributes/specifications",
|
to: "/catalog/products/attributes/specifications",
|
||||||
label: navigationMessages["catalog-product-specifications"],
|
label: navigationMessages["catalog-product-specifications"],
|
||||||
icon: ClipboardListIcon,
|
icon: "huge:clipboard",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "catalog-product-brands",
|
id: "catalog-product-brands",
|
||||||
to: "/catalog/products/attributes/brands",
|
to: "/catalog/products/attributes/brands",
|
||||||
label: navigationMessages["catalog-product-brands"],
|
label: navigationMessages["catalog-product-brands"],
|
||||||
icon: StarIcon,
|
icon: "huge:star",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -139,19 +79,19 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "catalog-categories",
|
id: "catalog-categories",
|
||||||
to: "/catalog/categories",
|
to: "/catalog/categories",
|
||||||
label: navigationMessages["catalog-categories"],
|
label: navigationMessages["catalog-categories"],
|
||||||
icon: ClipboardListIcon,
|
icon: "huge:clipboard",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "catalog-category-tree",
|
id: "catalog-category-tree",
|
||||||
to: "/catalog/categories/tree",
|
to: "/catalog/categories/tree",
|
||||||
label: navigationMessages["catalog-category-tree"],
|
label: navigationMessages["catalog-category-tree"],
|
||||||
icon: Structure01Icon,
|
icon: "huge:structure-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "catalog-category-navigation",
|
id: "catalog-category-navigation",
|
||||||
to: "/catalog/categories/navigation",
|
to: "/catalog/categories/navigation",
|
||||||
label: navigationMessages["catalog-category-navigation"],
|
label: navigationMessages["catalog-category-navigation"],
|
||||||
icon: Compass01Icon,
|
icon: "huge:compass-01",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -159,37 +99,37 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "inventory-center",
|
id: "inventory-center",
|
||||||
to: "/inventory",
|
to: "/inventory",
|
||||||
label: navigationMessages["inventory-center"],
|
label: navigationMessages["inventory-center"],
|
||||||
icon: PackageIcon,
|
icon: "huge:package",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "inventory-overview",
|
id: "inventory-overview",
|
||||||
to: "/inventory/overview",
|
to: "/inventory/overview",
|
||||||
label: navigationMessages["inventory-overview"],
|
label: navigationMessages["inventory-overview"],
|
||||||
icon: Chart01Icon,
|
icon: "huge:chart-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "inventory-inbound",
|
id: "inventory-inbound",
|
||||||
to: "/inventory/inbound",
|
to: "/inventory/inbound",
|
||||||
label: navigationMessages["inventory-inbound"],
|
label: navigationMessages["inventory-inbound"],
|
||||||
icon: InboxDownloadIcon,
|
icon: "huge:inbox-download",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "inventory-outbound",
|
id: "inventory-outbound",
|
||||||
to: "/inventory/outbound",
|
to: "/inventory/outbound",
|
||||||
label: navigationMessages["inventory-outbound"],
|
label: navigationMessages["inventory-outbound"],
|
||||||
icon: InboxUploadIcon,
|
icon: "huge:inbox-upload",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "inventory-transfers",
|
id: "inventory-transfers",
|
||||||
to: "/inventory/transfers",
|
to: "/inventory/transfers",
|
||||||
label: navigationMessages["inventory-transfers"],
|
label: navigationMessages["inventory-transfers"],
|
||||||
icon: ArrowDataTransferHorizontalIcon,
|
icon: "huge:arrow-data-transfer-horizontal",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "inventory-alerts",
|
id: "inventory-alerts",
|
||||||
to: "/inventory/alerts",
|
to: "/inventory/alerts",
|
||||||
label: navigationMessages["inventory-alerts"],
|
label: navigationMessages["inventory-alerts"],
|
||||||
icon: Alert02Icon,
|
icon: "huge:alert-02",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -197,25 +137,25 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "content-assets",
|
id: "content-assets",
|
||||||
to: "/content",
|
to: "/content",
|
||||||
label: navigationMessages["content-assets"],
|
label: navigationMessages["content-assets"],
|
||||||
icon: File01Icon,
|
icon: "huge:file-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "content-articles",
|
id: "content-articles",
|
||||||
to: "/content/articles",
|
to: "/content/articles",
|
||||||
label: navigationMessages["content-articles"],
|
label: navigationMessages["content-articles"],
|
||||||
icon: File01Icon,
|
icon: "huge:file-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "content-media",
|
id: "content-media",
|
||||||
to: "/content/media",
|
to: "/content/media",
|
||||||
label: navigationMessages["content-media"],
|
label: navigationMessages["content-media"],
|
||||||
icon: GalleryHorizontalIcon,
|
icon: "huge:album-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "content-pages",
|
id: "content-pages",
|
||||||
to: "/content/pages",
|
to: "/content/pages",
|
||||||
label: navigationMessages["content-pages"],
|
label: navigationMessages["content-pages"],
|
||||||
icon: AppWindowIcon,
|
icon: "huge:browser",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -229,37 +169,37 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "trade-orders",
|
id: "trade-orders",
|
||||||
to: "/trade/orders",
|
to: "/trade/orders",
|
||||||
label: navigationMessages["trade-orders"],
|
label: navigationMessages["trade-orders"],
|
||||||
icon: ShoppingCart01Icon,
|
icon: "huge:shopping-cart-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "trade-orders-awaiting-payment",
|
id: "trade-orders-awaiting-payment",
|
||||||
to: "/trade/orders/awaiting-payment",
|
to: "/trade/orders/awaiting-payment",
|
||||||
label: navigationMessages["trade-orders-awaiting-payment"],
|
label: navigationMessages["trade-orders-awaiting-payment"],
|
||||||
icon: WalletCardsIcon,
|
icon: "huge:wallet-cards",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "trade-orders-awaiting-shipment",
|
id: "trade-orders-awaiting-shipment",
|
||||||
to: "/trade/orders/awaiting-shipment",
|
to: "/trade/orders/awaiting-shipment",
|
||||||
label: navigationMessages["trade-orders-awaiting-shipment"],
|
label: navigationMessages["trade-orders-awaiting-shipment"],
|
||||||
icon: PackageIcon,
|
icon: "huge:package",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "trade-orders-shipped",
|
id: "trade-orders-shipped",
|
||||||
to: "/trade/orders/shipped",
|
to: "/trade/orders/shipped",
|
||||||
label: navigationMessages["trade-orders-shipped"],
|
label: navigationMessages["trade-orders-shipped"],
|
||||||
icon: DeliveryTruck01Icon,
|
icon: "huge:delivery-truck-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "trade-orders-completed",
|
id: "trade-orders-completed",
|
||||||
to: "/trade/orders/completed",
|
to: "/trade/orders/completed",
|
||||||
label: navigationMessages["trade-orders-completed"],
|
label: navigationMessages["trade-orders-completed"],
|
||||||
icon: CheckmarkCircle01Icon,
|
icon: "huge:checkmark-circle-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "trade-orders-canceled",
|
id: "trade-orders-canceled",
|
||||||
to: "/trade/orders/canceled",
|
to: "/trade/orders/canceled",
|
||||||
label: navigationMessages["trade-orders-canceled"],
|
label: navigationMessages["trade-orders-canceled"],
|
||||||
icon: CancelCircleIcon,
|
icon: "huge:cancel-circle",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -267,25 +207,25 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "fulfillment-center",
|
id: "fulfillment-center",
|
||||||
to: "/fulfillment",
|
to: "/fulfillment",
|
||||||
label: navigationMessages["fulfillment-center"],
|
label: navigationMessages["fulfillment-center"],
|
||||||
icon: DeliveryTruck01Icon,
|
icon: "huge:delivery-truck-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "fulfillment-deliveries",
|
id: "fulfillment-deliveries",
|
||||||
to: "/fulfillment/deliveries",
|
to: "/fulfillment/deliveries",
|
||||||
label: navigationMessages["fulfillment-deliveries"],
|
label: navigationMessages["fulfillment-deliveries"],
|
||||||
icon: Location01Icon,
|
icon: "huge:location-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "fulfillment-pickups",
|
id: "fulfillment-pickups",
|
||||||
to: "/fulfillment/pickups",
|
to: "/fulfillment/pickups",
|
||||||
label: navigationMessages["fulfillment-pickups"],
|
label: navigationMessages["fulfillment-pickups"],
|
||||||
icon: Store01Icon,
|
icon: "huge:store-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "fulfillment-freight-rules",
|
id: "fulfillment-freight-rules",
|
||||||
to: "/fulfillment/freight-rules",
|
to: "/fulfillment/freight-rules",
|
||||||
label: navigationMessages["fulfillment-freight-rules"],
|
label: navigationMessages["fulfillment-freight-rules"],
|
||||||
icon: RoadLocation01Icon,
|
icon: "huge:road-location-01",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -293,25 +233,25 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "after-sales-center",
|
id: "after-sales-center",
|
||||||
to: "/after-sales",
|
to: "/after-sales",
|
||||||
label: navigationMessages["after-sales-center"],
|
label: navigationMessages["after-sales-center"],
|
||||||
icon: CallMissed01Icon,
|
icon: "huge:call-missed-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "after-sales-returns",
|
id: "after-sales-returns",
|
||||||
to: "/after-sales/returns",
|
to: "/after-sales/returns",
|
||||||
label: navigationMessages["after-sales-returns"],
|
label: navigationMessages["after-sales-returns"],
|
||||||
icon: Refresh01Icon,
|
icon: "huge:refresh-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "after-sales-refunds",
|
id: "after-sales-refunds",
|
||||||
to: "/after-sales/refunds",
|
to: "/after-sales/refunds",
|
||||||
label: navigationMessages["after-sales-refunds"],
|
label: navigationMessages["after-sales-refunds"],
|
||||||
icon: MoneySendSquareIcon,
|
icon: "huge:money-send-square",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "after-sales-disputes",
|
id: "after-sales-disputes",
|
||||||
to: "/after-sales/disputes",
|
to: "/after-sales/disputes",
|
||||||
label: navigationMessages["after-sales-disputes"],
|
label: navigationMessages["after-sales-disputes"],
|
||||||
icon: SecurityWarningIcon,
|
icon: "huge:security-warning",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -325,31 +265,31 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "customer-center",
|
id: "customer-center",
|
||||||
to: "/customers",
|
to: "/customers",
|
||||||
label: navigationMessages["customer-center"],
|
label: navigationMessages["customer-center"],
|
||||||
icon: IdentityCardIcon,
|
icon: "huge:identity-card",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "customer-profiles",
|
id: "customer-profiles",
|
||||||
to: "/customers/profiles",
|
to: "/customers/profiles",
|
||||||
label: navigationMessages["customer-profiles"],
|
label: navigationMessages["customer-profiles"],
|
||||||
icon: IdentityCardIcon,
|
icon: "huge:identity-card",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "customer-segments",
|
id: "customer-segments",
|
||||||
to: "/customers/segments",
|
to: "/customers/segments",
|
||||||
label: navigationMessages["customer-segments"],
|
label: navigationMessages["customer-segments"],
|
||||||
icon: UserGroupIcon,
|
icon: "huge:user-group",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "customer-tiers",
|
id: "customer-tiers",
|
||||||
to: "/customers/tiers",
|
to: "/customers/tiers",
|
||||||
label: navigationMessages["customer-tiers"],
|
label: navigationMessages["customer-tiers"],
|
||||||
icon: CrownIcon,
|
icon: "huge:crown",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "customer-risk-list",
|
id: "customer-risk-list",
|
||||||
to: "/customers/risk-list",
|
to: "/customers/risk-list",
|
||||||
label: navigationMessages["customer-risk-list"],
|
label: navigationMessages["customer-risk-list"],
|
||||||
icon: SecurityWarningIcon,
|
icon: "huge:security-warning",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -357,31 +297,31 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "marketing-campaigns",
|
id: "marketing-campaigns",
|
||||||
to: "/marketing/campaigns",
|
to: "/marketing/campaigns",
|
||||||
label: navigationMessages["marketing-campaigns"],
|
label: navigationMessages["marketing-campaigns"],
|
||||||
icon: Discount01Icon,
|
icon: "huge:discount-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "marketing-coupons",
|
id: "marketing-coupons",
|
||||||
to: "/marketing/coupons",
|
to: "/marketing/coupons",
|
||||||
label: navigationMessages["marketing-coupons"],
|
label: navigationMessages["marketing-coupons"],
|
||||||
icon: Ticket01Icon,
|
icon: "huge:ticket-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "marketing-flash-sales",
|
id: "marketing-flash-sales",
|
||||||
to: "/marketing/flash-sales",
|
to: "/marketing/flash-sales",
|
||||||
label: navigationMessages["marketing-flash-sales"],
|
label: navigationMessages["marketing-flash-sales"],
|
||||||
icon: Clock01Icon,
|
icon: "huge:clock-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "marketing-gift-promotions",
|
id: "marketing-gift-promotions",
|
||||||
to: "/marketing/gift-promotions",
|
to: "/marketing/gift-promotions",
|
||||||
label: navigationMessages["marketing-gift-promotions"],
|
label: navigationMessages["marketing-gift-promotions"],
|
||||||
icon: GiftIcon,
|
icon: "huge:gift",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "marketing-referrals",
|
id: "marketing-referrals",
|
||||||
to: "/marketing/referrals",
|
to: "/marketing/referrals",
|
||||||
label: navigationMessages["marketing-referrals"],
|
label: navigationMessages["marketing-referrals"],
|
||||||
icon: Share01Icon,
|
icon: "huge:share-01",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -389,25 +329,25 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "loyalty-center",
|
id: "loyalty-center",
|
||||||
to: "/loyalty",
|
to: "/loyalty",
|
||||||
label: navigationMessages["loyalty-center"],
|
label: navigationMessages["loyalty-center"],
|
||||||
icon: Medal01Icon,
|
icon: "huge:medal-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "loyalty-points",
|
id: "loyalty-points",
|
||||||
to: "/loyalty/points",
|
to: "/loyalty/points",
|
||||||
label: navigationMessages["loyalty-points"],
|
label: navigationMessages["loyalty-points"],
|
||||||
icon: StarCircleIcon,
|
icon: "huge:star-circle",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "loyalty-stored-value",
|
id: "loyalty-stored-value",
|
||||||
to: "/loyalty/stored-value",
|
to: "/loyalty/stored-value",
|
||||||
label: navigationMessages["loyalty-stored-value"],
|
label: navigationMessages["loyalty-stored-value"],
|
||||||
icon: Wallet01Icon,
|
icon: "huge:wallet-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "loyalty-benefits",
|
id: "loyalty-benefits",
|
||||||
to: "/loyalty/benefits",
|
to: "/loyalty/benefits",
|
||||||
label: navigationMessages["loyalty-benefits"],
|
label: navigationMessages["loyalty-benefits"],
|
||||||
icon: CheckmarkBadge01Icon,
|
icon: "huge:checkmark-badge-01",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -421,31 +361,31 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "report-center",
|
id: "report-center",
|
||||||
to: "/reports",
|
to: "/reports",
|
||||||
label: navigationMessages["report-center"],
|
label: navigationMessages["report-center"],
|
||||||
icon: Chart01Icon,
|
icon: "huge:chart-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "report-sales",
|
id: "report-sales",
|
||||||
to: "/reports/sales",
|
to: "/reports/sales",
|
||||||
label: navigationMessages["report-sales"],
|
label: navigationMessages["report-sales"],
|
||||||
icon: AnalyticsUpIcon,
|
icon: "huge:analytics-up",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "report-products",
|
id: "report-products",
|
||||||
to: "/reports/products",
|
to: "/reports/products",
|
||||||
label: navigationMessages["report-products"],
|
label: navigationMessages["report-products"],
|
||||||
icon: ShoppingBag01Icon,
|
icon: "huge:shopping-bag-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "report-customers",
|
id: "report-customers",
|
||||||
to: "/reports/customers",
|
to: "/reports/customers",
|
||||||
label: navigationMessages["report-customers"],
|
label: navigationMessages["report-customers"],
|
||||||
icon: UserGroupIcon,
|
icon: "huge:user-group",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "report-channels",
|
id: "report-channels",
|
||||||
to: "/reports/channels",
|
to: "/reports/channels",
|
||||||
label: navigationMessages["report-channels"],
|
label: navigationMessages["report-channels"],
|
||||||
icon: ChartIncreaseIcon,
|
icon: "huge:chart-increase",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -453,31 +393,31 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "finance-center",
|
id: "finance-center",
|
||||||
to: "/finance",
|
to: "/finance",
|
||||||
label: navigationMessages["finance-center"],
|
label: navigationMessages["finance-center"],
|
||||||
icon: WalletCardsIcon,
|
icon: "huge:wallet-cards",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "finance-settlements",
|
id: "finance-settlements",
|
||||||
to: "/finance/settlements",
|
to: "/finance/settlements",
|
||||||
label: navigationMessages["finance-settlements"],
|
label: navigationMessages["finance-settlements"],
|
||||||
icon: Invoice03Icon,
|
icon: "huge:invoice-03",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "finance-reconciliation",
|
id: "finance-reconciliation",
|
||||||
to: "/finance/reconciliation",
|
to: "/finance/reconciliation",
|
||||||
label: navigationMessages["finance-reconciliation"],
|
label: navigationMessages["finance-reconciliation"],
|
||||||
icon: Calculator01Icon,
|
icon: "huge:calculator-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "finance-invoices",
|
id: "finance-invoices",
|
||||||
to: "/finance/invoices",
|
to: "/finance/invoices",
|
||||||
label: navigationMessages["finance-invoices"],
|
label: navigationMessages["finance-invoices"],
|
||||||
icon: File01Icon,
|
icon: "huge:file-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "finance-payouts",
|
id: "finance-payouts",
|
||||||
to: "/finance/payouts",
|
to: "/finance/payouts",
|
||||||
label: navigationMessages["finance-payouts"],
|
label: navigationMessages["finance-payouts"],
|
||||||
icon: MoneySendSquareIcon,
|
icon: "huge:money-send-square",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -491,25 +431,25 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "system-members",
|
id: "system-members",
|
||||||
to: "/system/members",
|
to: "/system/members",
|
||||||
label: navigationMessages["system-members"],
|
label: navigationMessages["system-members"],
|
||||||
icon: UserShield01Icon,
|
icon: "huge:user-shield-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "system-members-admins",
|
id: "system-members-admins",
|
||||||
to: "/system/members/admins",
|
to: "/system/members/admins",
|
||||||
label: navigationMessages["system-members-admins"],
|
label: navigationMessages["system-members-admins"],
|
||||||
icon: UserShield01Icon,
|
icon: "huge:user-shield-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "system-members-roles",
|
id: "system-members-roles",
|
||||||
to: "/system/members/roles",
|
to: "/system/members/roles",
|
||||||
label: navigationMessages["system-members-roles"],
|
label: navigationMessages["system-members-roles"],
|
||||||
icon: UserGroupIcon,
|
icon: "huge:user-group",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "system-members-permissions",
|
id: "system-members-permissions",
|
||||||
to: "/system/members/permissions",
|
to: "/system/members/permissions",
|
||||||
label: navigationMessages["system-members-permissions"],
|
label: navigationMessages["system-members-permissions"],
|
||||||
icon: LockKeyIcon,
|
icon: "huge:lock-key",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -517,19 +457,19 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "system-notifications",
|
id: "system-notifications",
|
||||||
to: "/system/notifications",
|
to: "/system/notifications",
|
||||||
label: navigationMessages["system-notifications"],
|
label: navigationMessages["system-notifications"],
|
||||||
icon: BubbleChatIcon,
|
icon: "huge:bubble-chat",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "system-notification-templates",
|
id: "system-notification-templates",
|
||||||
to: "/system/notifications/templates",
|
to: "/system/notifications/templates",
|
||||||
label: navigationMessages["system-notification-templates"],
|
label: navigationMessages["system-notification-templates"],
|
||||||
icon: File01Icon,
|
icon: "huge:file-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "system-notification-logs",
|
id: "system-notification-logs",
|
||||||
to: "/system/notifications/logs",
|
to: "/system/notifications/logs",
|
||||||
label: navigationMessages["system-notification-logs"],
|
label: navigationMessages["system-notification-logs"],
|
||||||
icon: HistoryIcon,
|
icon: "huge:time-schedule",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -537,25 +477,25 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "system-audit",
|
id: "system-audit",
|
||||||
to: "/system/audit",
|
to: "/system/audit",
|
||||||
label: navigationMessages["system-audit"],
|
label: navigationMessages["system-audit"],
|
||||||
icon: Note01Icon,
|
icon: "huge:note-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "system-integrations",
|
id: "system-integrations",
|
||||||
to: "/system/integrations",
|
to: "/system/integrations",
|
||||||
label: navigationMessages["system-integrations"],
|
label: navigationMessages["system-integrations"],
|
||||||
icon: CodeSquareIcon,
|
icon: "huge:code-square",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "system-integration-api-keys",
|
id: "system-integration-api-keys",
|
||||||
to: "/system/integrations/api-keys",
|
to: "/system/integrations/api-keys",
|
||||||
label: navigationMessages["system-integration-api-keys"],
|
label: navigationMessages["system-integration-api-keys"],
|
||||||
icon: Key01Icon,
|
icon: "huge:key-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "system-integration-webhooks",
|
id: "system-integration-webhooks",
|
||||||
to: "/system/integrations/webhooks",
|
to: "/system/integrations/webhooks",
|
||||||
label: navigationMessages["system-integration-webhooks"],
|
label: navigationMessages["system-integration-webhooks"],
|
||||||
icon: LinkCircleIcon,
|
icon: "huge:link-circle",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -563,25 +503,25 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "system-settings",
|
id: "system-settings",
|
||||||
to: "/system-configs",
|
to: "/system-configs",
|
||||||
label: navigationMessages["system-settings"],
|
label: navigationMessages["system-settings"],
|
||||||
icon: Settings01Icon,
|
icon: "huge:settings-01",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
id: "system-settings-store",
|
id: "system-settings-store",
|
||||||
to: "/system-configs/store",
|
to: "/system-configs/store",
|
||||||
label: navigationMessages["system-settings-store"],
|
label: navigationMessages["system-settings-store"],
|
||||||
icon: Store01Icon,
|
icon: "huge:store-01",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "system-settings-payments",
|
id: "system-settings-payments",
|
||||||
to: "/system-configs/payments",
|
to: "/system-configs/payments",
|
||||||
label: navigationMessages["system-settings-payments"],
|
label: navigationMessages["system-settings-payments"],
|
||||||
icon: CreditCardIcon,
|
icon: "huge:credit-card",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "system-settings-shipping",
|
id: "system-settings-shipping",
|
||||||
to: "/system-configs/shipping",
|
to: "/system-configs/shipping",
|
||||||
label: navigationMessages["system-settings-shipping"],
|
label: navigationMessages["system-settings-shipping"],
|
||||||
icon: DeliveryTruck01Icon,
|
icon: "huge:delivery-truck-01",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -589,7 +529,7 @@ export const primaryNavigationGroups: readonly NavigationGroup[] = [
|
|||||||
id: "system-recycle-bin",
|
id: "system-recycle-bin",
|
||||||
to: "/system/recycle-bin",
|
to: "/system/recycle-bin",
|
||||||
label: navigationMessages["system-recycle-bin"],
|
label: navigationMessages["system-recycle-bin"],
|
||||||
icon: Delete02Icon,
|
icon: "huge:delete-02",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +1,3 @@
|
|||||||
import {
|
|
||||||
DeliveryTruck01Icon,
|
|
||||||
Mail01Icon,
|
|
||||||
Message01Icon,
|
|
||||||
PackageIcon,
|
|
||||||
} from "@workspace/icons"
|
|
||||||
import type { QueryFunctionContext } from "@tanstack/react-query"
|
import type { QueryFunctionContext } from "@tanstack/react-query"
|
||||||
|
|
||||||
import type { Notification } from "@workspace/blocks/notifications"
|
import type { Notification } from "@workspace/blocks/notifications"
|
||||||
@@ -68,7 +62,7 @@ export const fallbackNotifications: readonly Notification[] = [
|
|||||||
isRead: true,
|
isRead: true,
|
||||||
media: {
|
media: {
|
||||||
kind: "icon",
|
kind: "icon",
|
||||||
icon: PackageIcon,
|
icon: "huge:package",
|
||||||
tone: "warning",
|
tone: "warning",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -81,7 +75,7 @@ export const fallbackNotifications: readonly Notification[] = [
|
|||||||
isRead: true,
|
isRead: true,
|
||||||
media: {
|
media: {
|
||||||
kind: "icon",
|
kind: "icon",
|
||||||
icon: DeliveryTruck01Icon,
|
icon: "huge:delivery-truck-01",
|
||||||
tone: "success",
|
tone: "success",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -94,7 +88,7 @@ export const fallbackNotifications: readonly Notification[] = [
|
|||||||
isRead: true,
|
isRead: true,
|
||||||
media: {
|
media: {
|
||||||
kind: "icon",
|
kind: "icon",
|
||||||
icon: Message01Icon,
|
icon: "huge:message-01",
|
||||||
tone: "info",
|
tone: "info",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -106,7 +100,7 @@ export const fallbackNotifications: readonly Notification[] = [
|
|||||||
isRead: true,
|
isRead: true,
|
||||||
media: {
|
media: {
|
||||||
kind: "icon",
|
kind: "icon",
|
||||||
icon: Mail01Icon,
|
icon: "huge:mail-01",
|
||||||
tone: "destructive",
|
tone: "destructive",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
I18nProvider as UiI18nProvider,
|
I18nProvider as UiI18nProvider,
|
||||||
type CalendarLocale,
|
type CalendarLocale,
|
||||||
} from "@workspace/ui/components/i18n"
|
} from "@workspace/ui/components/i18n"
|
||||||
import { calendarLocale as englishCalendarLocale } from "@workspace/ui/locales/en"
|
import { calendarLocale as englishCalendarLocale } from "@workspace/ui/locales/en-US"
|
||||||
import { calendarLocale as simplifiedChineseCalendarLocale } from "@workspace/ui/locales/zh-Hans"
|
import { calendarLocale as simplifiedChineseCalendarLocale } from "@workspace/ui/locales/zh-Hans"
|
||||||
|
|
||||||
import { appLocales, DEFAULT_APP_LOCALE, type AppLocale } from "./app-locales"
|
import { appLocales, DEFAULT_APP_LOCALE, type AppLocale } from "./app-locales"
|
||||||
@@ -27,7 +27,7 @@ import { AppI18nDevtool } from "./app-i18n-devtool"
|
|||||||
import { setAppLocale as persistAppLocale } from "@/server/app-locale.functions"
|
import { setAppLocale as persistAppLocale } from "@/server/app-locale.functions"
|
||||||
|
|
||||||
const appCalendarLocales: Partial<Record<AppLocale, CalendarLocale>> = {
|
const appCalendarLocales: Partial<Record<AppLocale, CalendarLocale>> = {
|
||||||
en: englishCalendarLocale,
|
"en-US": englishCalendarLocale,
|
||||||
"zh-Hans": simplifiedChineseCalendarLocale,
|
"zh-Hans": simplifiedChineseCalendarLocale,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,11 @@ import { AppLanguageSwitcher } from "./app-language-switcher"
|
|||||||
|
|
||||||
vi.mock("./app-i18n-provider", () => ({
|
vi.mock("./app-i18n-provider", () => ({
|
||||||
useAppLocale: () => ({
|
useAppLocale: () => ({
|
||||||
locale: "en",
|
locale: "en-US",
|
||||||
setLocale: vi.fn(),
|
setLocale: vi.fn(),
|
||||||
}),
|
}),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock("country-flag-icons/react/1x1", () => ({
|
|
||||||
CN: () => <svg />,
|
|
||||||
US: () => <svg />,
|
|
||||||
}))
|
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
vi.stubGlobal(
|
vi.stubGlobal(
|
||||||
"ResizeObserver",
|
"ResizeObserver",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { CN, US } from "country-flag-icons/react/1x1"
|
import { Icon } from "@icones/react"
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -13,11 +13,6 @@ import { HeaderActionButton } from "@workspace/blocks/layout"
|
|||||||
import { appLocales, isAppLocale, type AppLocaleCountry } from "./app-locales"
|
import { appLocales, isAppLocale, type AppLocaleCountry } from "./app-locales"
|
||||||
import { useAppLocale } from "./app-i18n-provider"
|
import { useAppLocale } from "./app-i18n-provider"
|
||||||
|
|
||||||
const localeFlags = {
|
|
||||||
CN,
|
|
||||||
US,
|
|
||||||
} satisfies Record<AppLocaleCountry, typeof CN>
|
|
||||||
|
|
||||||
function LocaleFlag({
|
function LocaleFlag({
|
||||||
country,
|
country,
|
||||||
className,
|
className,
|
||||||
@@ -25,8 +20,6 @@ function LocaleFlag({
|
|||||||
className?: string
|
className?: string
|
||||||
country: AppLocaleCountry
|
country: AppLocaleCountry
|
||||||
}) {
|
}) {
|
||||||
const Flag = localeFlags[country]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -35,7 +28,11 @@ function LocaleFlag({
|
|||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Flag className="size-full" />
|
{country === "CN" ? (
|
||||||
|
<Icon name="flag:cn-square" className="size-full" />
|
||||||
|
) : (
|
||||||
|
<Icon name="flag:us-square" className="size-full" />
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { LocaleDefinition } from "@workspace/i18n"
|
import type { LocaleDefinition } from "@workspace/i18n"
|
||||||
|
|
||||||
export type AppLocale = "en" | "zh-Hans"
|
export type AppLocale = "en-US" | "zh-Hans"
|
||||||
export type AppLocaleCountry = "CN" | "US"
|
export type AppLocaleCountry = "CN" | "US"
|
||||||
|
|
||||||
export interface AppLocaleDefinition extends LocaleDefinition {
|
export interface AppLocaleDefinition extends LocaleDefinition {
|
||||||
@@ -16,7 +16,7 @@ export const appLocales = [
|
|||||||
direction: "ltr",
|
direction: "ltr",
|
||||||
languageTag: "en-US",
|
languageTag: "en-US",
|
||||||
label: "English",
|
label: "English",
|
||||||
locale: "en",
|
locale: "en-US",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
country: "CN",
|
country: "CN",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: @lingui/cli\n"
|
"X-Generator: @lingui/cli\n"
|
||||||
"Language: en\n"
|
"Language: en-US\n"
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: \n"
|
"POT-Creation-Date: \n"
|
||||||
@@ -23,6 +23,21 @@ msgstr "Account password"
|
|||||||
msgid "blocks.appearance.active"
|
msgid "blocks.appearance.active"
|
||||||
msgstr "Active"
|
msgstr "Active"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:16
|
||||||
|
msgid "blocks.chats.actions.addEmoji"
|
||||||
|
msgstr "Add emoji"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:4
|
||||||
|
msgid "blocks.chats.actions.addFiles"
|
||||||
|
msgstr "Add files"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:8
|
||||||
|
msgid "blocks.chats.actions.addImage"
|
||||||
|
msgstr "Add image"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:276
|
#: src/data/navigation-messages.ts:276
|
||||||
msgid "app.navigation.system-members-admins"
|
msgid "app.navigation.system-members-admins"
|
||||||
@@ -33,6 +48,11 @@ msgstr "Administrator accounts"
|
|||||||
msgid "app.navigation.after-sales-center"
|
msgid "app.navigation.after-sales-center"
|
||||||
msgstr "After-sales"
|
msgstr "After-sales"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:12
|
||||||
|
msgid "blocks.chats.emojiPicker.allEmojis"
|
||||||
|
msgstr "All emojis"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:91
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:91
|
||||||
msgid "blocks.appearance.color.amber"
|
msgid "blocks.appearance.color.amber"
|
||||||
@@ -73,6 +93,11 @@ msgstr "Awaiting payment"
|
|||||||
msgid "app.navigation.trade-orders-awaiting-shipment"
|
msgid "app.navigation.trade-orders-awaiting-shipment"
|
||||||
msgstr "Awaiting shipment"
|
msgstr "Awaiting shipment"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:20
|
||||||
|
msgid "blocks.chats.actions.backToConversations"
|
||||||
|
msgstr "Back to conversations"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:16
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:16
|
||||||
msgid "blocks.appearance.baseColor"
|
msgid "blocks.appearance.baseColor"
|
||||||
@@ -124,7 +149,7 @@ msgid "app.navigation.report-channels"
|
|||||||
msgstr "Channel analysis"
|
msgstr "Channel analysis"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/chats/messages.ts:4
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:112
|
||||||
msgid "blocks.chats.title"
|
msgid "blocks.chats.title"
|
||||||
msgstr "Chats"
|
msgstr "Chats"
|
||||||
|
|
||||||
@@ -133,6 +158,11 @@ msgstr "Chats"
|
|||||||
msgid "blocks.notifications.error.description"
|
msgid "blocks.notifications.error.description"
|
||||||
msgstr "Check your network connection and try again."
|
msgstr "Check your network connection and try again."
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:108
|
||||||
|
msgid "blocks.chats.selectConversation.description"
|
||||||
|
msgstr "Choose a conversation from the list to read its messages."
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/ui/src/components/i18n.tsx:29
|
#: ../../packages/ui/src/components/i18n.tsx:29
|
||||||
msgid "ui.common.close"
|
msgid "ui.common.close"
|
||||||
@@ -158,6 +188,11 @@ msgstr "Completed orders"
|
|||||||
msgid "app.navigation.content-assets"
|
msgid "app.navigation.content-assets"
|
||||||
msgstr "Content"
|
msgstr "Content"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:24
|
||||||
|
msgid "blocks.chats.actions.conversationDetails"
|
||||||
|
msgstr "Conversation details"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:192
|
#: src/data/navigation-messages.ts:192
|
||||||
msgid "app.navigation.marketing-coupons"
|
msgid "app.navigation.marketing-coupons"
|
||||||
@@ -218,6 +253,11 @@ msgstr "Dark theme"
|
|||||||
msgid "app.navigation.data-and-finance"
|
msgid "app.navigation.data-and-finance"
|
||||||
msgstr "Data and finance"
|
msgstr "Data and finance"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:52
|
||||||
|
msgid "blocks.chats.messageStatus.delivered"
|
||||||
|
msgstr "Delivered"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:296
|
#: src/data/navigation-messages.ts:296
|
||||||
msgid "app.navigation.system-notification-logs"
|
msgid "app.navigation.system-notification-logs"
|
||||||
@@ -343,6 +383,11 @@ msgstr "Light theme"
|
|||||||
msgid "blocks.appearance.color.lime"
|
msgid "blocks.appearance.color.lime"
|
||||||
msgstr "Lime"
|
msgstr "Lime"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:28
|
||||||
|
msgid "blocks.chats.actions.loadEarlier"
|
||||||
|
msgstr "Load earlier messages"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/ui/src/components/i18n.tsx:37
|
#: ../../packages/ui/src/components/i18n.tsx:37
|
||||||
msgid "ui.common.loading"
|
msgid "ui.common.loading"
|
||||||
@@ -383,6 +428,11 @@ msgstr "Media"
|
|||||||
msgid "app.navigation.loyalty-center"
|
msgid "app.navigation.loyalty-center"
|
||||||
msgstr "Membership benefits"
|
msgstr "Membership benefits"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:84
|
||||||
|
msgid "blocks.chats.emptyMessages.description"
|
||||||
|
msgstr "Messages in this conversation will appear here."
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:127
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:127
|
||||||
msgid "blocks.appearance.color.mist"
|
msgid "blocks.appearance.color.mist"
|
||||||
@@ -433,11 +483,31 @@ msgstr "Next"
|
|||||||
msgid "ui.carousel.nextSlide"
|
msgid "ui.carousel.nextSlide"
|
||||||
msgstr "Next slide"
|
msgstr "Next slide"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:80
|
||||||
|
msgid "blocks.chats.emptyConversations.title"
|
||||||
|
msgstr "No conversations"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:92
|
||||||
|
msgid "blocks.chats.emptySearch"
|
||||||
|
msgstr "No conversations match your search."
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:88
|
||||||
|
msgid "blocks.chats.emptyMessages.title"
|
||||||
|
msgstr "No messages yet"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/notifications/messages.ts:12
|
#: ../../packages/blocks/src/blocks/notifications/messages.ts:12
|
||||||
msgid "blocks.notifications.empty.title"
|
msgid "blocks.notifications.empty.title"
|
||||||
msgstr "No notifications"
|
msgstr "No notifications"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:56
|
||||||
|
msgid "blocks.chats.messageStatus.failed"
|
||||||
|
msgstr "Not sent"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:292
|
#: src/data/navigation-messages.ts:292
|
||||||
msgid "app.navigation.system-notification-templates"
|
msgid "app.navigation.system-notification-templates"
|
||||||
@@ -543,6 +613,11 @@ msgstr "Pink"
|
|||||||
msgid "app.navigation.loyalty-points"
|
msgid "app.navigation.loyalty-points"
|
||||||
msgstr "Points rules"
|
msgstr "Points rules"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:44
|
||||||
|
msgid "blocks.chats.actions.sendOnEnter"
|
||||||
|
msgstr "Press Enter to send"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/ui/src/components/i18n.tsx:65
|
#: ../../packages/ui/src/components/i18n.tsx:65
|
||||||
msgid "ui.pagination.previous"
|
msgid "ui.pagination.previous"
|
||||||
@@ -598,11 +673,21 @@ msgstr "Products and inventory"
|
|||||||
msgid "blocks.appearance.color.purple"
|
msgid "blocks.appearance.color.purple"
|
||||||
msgstr "Purple"
|
msgstr "Purple"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:60
|
||||||
|
msgid "blocks.chats.messageStatus.read"
|
||||||
|
msgstr "Read"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:12
|
#: src/data/navigation-messages.ts:12
|
||||||
msgid "app.navigation.overview-realtime"
|
msgid "app.navigation.overview-realtime"
|
||||||
msgstr "Real-time monitoring"
|
msgstr "Real-time monitoring"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:64
|
||||||
|
msgid "blocks.chats.emojiPicker.recentEmojis"
|
||||||
|
msgstr "Recently used"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:256
|
#: src/data/navigation-messages.ts:256
|
||||||
msgid "app.navigation.finance-reconciliation"
|
msgid "app.navigation.finance-reconciliation"
|
||||||
@@ -638,6 +723,11 @@ msgstr "Refresh the current page data"
|
|||||||
msgid "app.navigation.after-sales-refunds"
|
msgid "app.navigation.after-sales-refunds"
|
||||||
msgstr "Refund review"
|
msgstr "Refund review"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:32
|
||||||
|
msgid "blocks.chats.actions.removeAttachment"
|
||||||
|
msgstr "Remove {name}"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:228
|
#: src/data/navigation-messages.ts:228
|
||||||
msgid "app.navigation.report-center"
|
msgid "app.navigation.report-center"
|
||||||
@@ -668,6 +758,36 @@ msgstr "Rose"
|
|||||||
msgid "app.navigation.report-sales"
|
msgid "app.navigation.report-sales"
|
||||||
msgstr "Sales analysis"
|
msgstr "Sales analysis"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:100
|
||||||
|
msgid "blocks.chats.search"
|
||||||
|
msgstr "Search conversations"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:104
|
||||||
|
msgid "blocks.chats.selectConversation"
|
||||||
|
msgstr "Select conversation {title}"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:40
|
||||||
|
msgid "blocks.chats.actions.send"
|
||||||
|
msgstr "Send"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:72
|
||||||
|
msgid "blocks.chats.messageStatus.sending"
|
||||||
|
msgstr "Sending"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:48
|
||||||
|
msgid "blocks.chats.actions.sending"
|
||||||
|
msgstr "Sending…"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:68
|
||||||
|
msgid "blocks.chats.messageStatus.sent"
|
||||||
|
msgstr "Sent"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:252
|
#: src/data/navigation-messages.ts:252
|
||||||
msgid "app.navigation.finance-settlements"
|
msgid "app.navigation.finance-settlements"
|
||||||
@@ -698,6 +818,11 @@ msgstr "Sky"
|
|||||||
msgid "app.navigation.catalog-product-specifications"
|
msgid "app.navigation.catalog-product-specifications"
|
||||||
msgstr "Specification templates"
|
msgstr "Specification templates"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:76
|
||||||
|
msgid "blocks.chats.emptyConversations.description"
|
||||||
|
msgstr "Start a conversation to see it here."
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:80
|
#: src/data/navigation-messages.ts:80
|
||||||
msgid "app.navigation.inventory-transfers"
|
msgid "app.navigation.inventory-transfers"
|
||||||
@@ -803,6 +928,11 @@ msgstr "Toggle theme"
|
|||||||
msgid "app.navigation.after-sales-disputes"
|
msgid "app.navigation.after-sales-disputes"
|
||||||
msgstr "Transaction disputes"
|
msgstr "Transaction disputes"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:36
|
||||||
|
msgid "blocks.chats.actions.retry"
|
||||||
|
msgstr "Try again"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/notifications/messages.ts:36
|
#: ../../packages/blocks/src/blocks/notifications/messages.ts:36
|
||||||
msgid "blocks.notifications.retry"
|
msgid "blocks.notifications.retry"
|
||||||
@@ -843,6 +973,11 @@ msgstr "Violet"
|
|||||||
msgid "app.navigation.system-integration-webhooks"
|
msgid "app.navigation.system-integration-webhooks"
|
||||||
msgstr "Webhook configuration"
|
msgstr "Webhook configuration"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:96
|
||||||
|
msgid "blocks.chats.messagePlaceholder"
|
||||||
|
msgstr "Write a message…"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:179
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:179
|
||||||
msgid "blocks.appearance.color.yellow"
|
msgid "blocks.appearance.color.yellow"
|
||||||
File diff suppressed because one or more lines are too long
@@ -23,6 +23,21 @@ msgstr "账号密码"
|
|||||||
msgid "blocks.appearance.active"
|
msgid "blocks.appearance.active"
|
||||||
msgstr "使用中"
|
msgstr "使用中"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:16
|
||||||
|
msgid "blocks.chats.actions.addEmoji"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:4
|
||||||
|
msgid "blocks.chats.actions.addFiles"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:8
|
||||||
|
msgid "blocks.chats.actions.addImage"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:276
|
#: src/data/navigation-messages.ts:276
|
||||||
msgid "app.navigation.system-members-admins"
|
msgid "app.navigation.system-members-admins"
|
||||||
@@ -33,6 +48,11 @@ msgstr "管理员账号"
|
|||||||
msgid "app.navigation.after-sales-center"
|
msgid "app.navigation.after-sales-center"
|
||||||
msgstr "售后中心"
|
msgstr "售后中心"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:12
|
||||||
|
msgid "blocks.chats.emojiPicker.allEmojis"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:91
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:91
|
||||||
msgid "blocks.appearance.color.amber"
|
msgid "blocks.appearance.color.amber"
|
||||||
@@ -73,6 +93,11 @@ msgstr "待付款订单"
|
|||||||
msgid "app.navigation.trade-orders-awaiting-shipment"
|
msgid "app.navigation.trade-orders-awaiting-shipment"
|
||||||
msgstr "待发货订单"
|
msgstr "待发货订单"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:20
|
||||||
|
msgid "blocks.chats.actions.backToConversations"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:16
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:16
|
||||||
msgid "blocks.appearance.baseColor"
|
msgid "blocks.appearance.baseColor"
|
||||||
@@ -124,7 +149,7 @@ msgid "app.navigation.report-channels"
|
|||||||
msgstr "渠道分析"
|
msgstr "渠道分析"
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/chats/messages.ts:4
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:112
|
||||||
msgid "blocks.chats.title"
|
msgid "blocks.chats.title"
|
||||||
msgstr "聊天"
|
msgstr "聊天"
|
||||||
|
|
||||||
@@ -133,6 +158,11 @@ msgstr "聊天"
|
|||||||
msgid "blocks.notifications.error.description"
|
msgid "blocks.notifications.error.description"
|
||||||
msgstr "请检查网络连接后重试。"
|
msgstr "请检查网络连接后重试。"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:108
|
||||||
|
msgid "blocks.chats.selectConversation.description"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/ui/src/components/i18n.tsx:29
|
#: ../../packages/ui/src/components/i18n.tsx:29
|
||||||
msgid "ui.common.close"
|
msgid "ui.common.close"
|
||||||
@@ -158,6 +188,11 @@ msgstr "已完成订单"
|
|||||||
msgid "app.navigation.content-assets"
|
msgid "app.navigation.content-assets"
|
||||||
msgstr "内容素材"
|
msgstr "内容素材"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:24
|
||||||
|
msgid "blocks.chats.actions.conversationDetails"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:192
|
#: src/data/navigation-messages.ts:192
|
||||||
msgid "app.navigation.marketing-coupons"
|
msgid "app.navigation.marketing-coupons"
|
||||||
@@ -218,6 +253,11 @@ msgstr "深色主题"
|
|||||||
msgid "app.navigation.data-and-finance"
|
msgid "app.navigation.data-and-finance"
|
||||||
msgstr "数据与财务"
|
msgstr "数据与财务"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:52
|
||||||
|
msgid "blocks.chats.messageStatus.delivered"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:296
|
#: src/data/navigation-messages.ts:296
|
||||||
msgid "app.navigation.system-notification-logs"
|
msgid "app.navigation.system-notification-logs"
|
||||||
@@ -343,6 +383,11 @@ msgstr "浅色主题"
|
|||||||
msgid "blocks.appearance.color.lime"
|
msgid "blocks.appearance.color.lime"
|
||||||
msgstr "青柠色"
|
msgstr "青柠色"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:28
|
||||||
|
msgid "blocks.chats.actions.loadEarlier"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/ui/src/components/i18n.tsx:37
|
#: ../../packages/ui/src/components/i18n.tsx:37
|
||||||
msgid "ui.common.loading"
|
msgid "ui.common.loading"
|
||||||
@@ -383,6 +428,11 @@ msgstr "媒体资源"
|
|||||||
msgid "app.navigation.loyalty-center"
|
msgid "app.navigation.loyalty-center"
|
||||||
msgstr "会员权益"
|
msgstr "会员权益"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:84
|
||||||
|
msgid "blocks.chats.emptyMessages.description"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:127
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:127
|
||||||
msgid "blocks.appearance.color.mist"
|
msgid "blocks.appearance.color.mist"
|
||||||
@@ -433,11 +483,31 @@ msgstr "下一页"
|
|||||||
msgid "ui.carousel.nextSlide"
|
msgid "ui.carousel.nextSlide"
|
||||||
msgstr "下一张"
|
msgstr "下一张"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:80
|
||||||
|
msgid "blocks.chats.emptyConversations.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:92
|
||||||
|
msgid "blocks.chats.emptySearch"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:88
|
||||||
|
msgid "blocks.chats.emptyMessages.title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/notifications/messages.ts:12
|
#: ../../packages/blocks/src/blocks/notifications/messages.ts:12
|
||||||
msgid "blocks.notifications.empty.title"
|
msgid "blocks.notifications.empty.title"
|
||||||
msgstr "暂无通知"
|
msgstr "暂无通知"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:56
|
||||||
|
msgid "blocks.chats.messageStatus.failed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:292
|
#: src/data/navigation-messages.ts:292
|
||||||
msgid "app.navigation.system-notification-templates"
|
msgid "app.navigation.system-notification-templates"
|
||||||
@@ -543,6 +613,11 @@ msgstr "粉色"
|
|||||||
msgid "app.navigation.loyalty-points"
|
msgid "app.navigation.loyalty-points"
|
||||||
msgstr "积分规则"
|
msgstr "积分规则"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:44
|
||||||
|
msgid "blocks.chats.actions.sendOnEnter"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/ui/src/components/i18n.tsx:65
|
#: ../../packages/ui/src/components/i18n.tsx:65
|
||||||
msgid "ui.pagination.previous"
|
msgid "ui.pagination.previous"
|
||||||
@@ -598,11 +673,21 @@ msgstr "商品与库存"
|
|||||||
msgid "blocks.appearance.color.purple"
|
msgid "blocks.appearance.color.purple"
|
||||||
msgstr "紫色"
|
msgstr "紫色"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:60
|
||||||
|
msgid "blocks.chats.messageStatus.read"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:12
|
#: src/data/navigation-messages.ts:12
|
||||||
msgid "app.navigation.overview-realtime"
|
msgid "app.navigation.overview-realtime"
|
||||||
msgstr "实时监控"
|
msgstr "实时监控"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:64
|
||||||
|
msgid "blocks.chats.emojiPicker.recentEmojis"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:256
|
#: src/data/navigation-messages.ts:256
|
||||||
msgid "app.navigation.finance-reconciliation"
|
msgid "app.navigation.finance-reconciliation"
|
||||||
@@ -638,6 +723,11 @@ msgstr "刷新当前页面的数据"
|
|||||||
msgid "app.navigation.after-sales-refunds"
|
msgid "app.navigation.after-sales-refunds"
|
||||||
msgstr "退款审核"
|
msgstr "退款审核"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:32
|
||||||
|
msgid "blocks.chats.actions.removeAttachment"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:228
|
#: src/data/navigation-messages.ts:228
|
||||||
msgid "app.navigation.report-center"
|
msgid "app.navigation.report-center"
|
||||||
@@ -668,6 +758,36 @@ msgstr "玫红色"
|
|||||||
msgid "app.navigation.report-sales"
|
msgid "app.navigation.report-sales"
|
||||||
msgstr "销售分析"
|
msgstr "销售分析"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:100
|
||||||
|
msgid "blocks.chats.search"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:104
|
||||||
|
msgid "blocks.chats.selectConversation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:40
|
||||||
|
msgid "blocks.chats.actions.send"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:72
|
||||||
|
msgid "blocks.chats.messageStatus.sending"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:48
|
||||||
|
msgid "blocks.chats.actions.sending"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:68
|
||||||
|
msgid "blocks.chats.messageStatus.sent"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:252
|
#: src/data/navigation-messages.ts:252
|
||||||
msgid "app.navigation.finance-settlements"
|
msgid "app.navigation.finance-settlements"
|
||||||
@@ -698,6 +818,11 @@ msgstr "天蓝色"
|
|||||||
msgid "app.navigation.catalog-product-specifications"
|
msgid "app.navigation.catalog-product-specifications"
|
||||||
msgstr "规格模板"
|
msgstr "规格模板"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:76
|
||||||
|
msgid "blocks.chats.emptyConversations.description"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: src/data/navigation-messages.ts:80
|
#: src/data/navigation-messages.ts:80
|
||||||
msgid "app.navigation.inventory-transfers"
|
msgid "app.navigation.inventory-transfers"
|
||||||
@@ -803,6 +928,11 @@ msgstr "切换主题"
|
|||||||
msgid "app.navigation.after-sales-disputes"
|
msgid "app.navigation.after-sales-disputes"
|
||||||
msgstr "交易纠纷"
|
msgstr "交易纠纷"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:36
|
||||||
|
msgid "blocks.chats.actions.retry"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/notifications/messages.ts:36
|
#: ../../packages/blocks/src/blocks/notifications/messages.ts:36
|
||||||
msgid "blocks.notifications.retry"
|
msgid "blocks.notifications.retry"
|
||||||
@@ -843,6 +973,11 @@ msgstr "紫罗兰色"
|
|||||||
msgid "app.navigation.system-integration-webhooks"
|
msgid "app.navigation.system-integration-webhooks"
|
||||||
msgstr "Webhook 配置"
|
msgstr "Webhook 配置"
|
||||||
|
|
||||||
|
#. js-lingui-explicit-id
|
||||||
|
#: ../../packages/blocks/src/blocks/chats/messages.ts:96
|
||||||
|
msgid "blocks.chats.messagePlaceholder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. js-lingui-explicit-id
|
#. js-lingui-explicit-id
|
||||||
#: ../../packages/blocks/src/blocks/appearance/messages.ts:179
|
#: ../../packages/blocks/src/blocks/appearance/messages.ts:179
|
||||||
msgid "blocks.appearance.color.yellow"
|
msgid "blocks.appearance.color.yellow"
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,256 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import {
|
||||||
|
ChatWorkspace,
|
||||||
|
type ChatConversation,
|
||||||
|
type ChatMessage,
|
||||||
|
} from "@workspace/blocks/chats"
|
||||||
|
|
||||||
|
const mockMediaUrls: Record<string, string> = {
|
||||||
|
"campaign-banner":
|
||||||
|
"https://images.unsplash.com/photo-1556742049-0cfed4f6a45d?auto=format&fit=crop&w=960&q=80",
|
||||||
|
"order-card-thumbnail":
|
||||||
|
"https://images.unsplash.com/photo-1556740749-887f6717d7e4?auto=format&fit=crop&w=320&q=80",
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialConversations: readonly ChatConversation[] = [
|
||||||
|
{
|
||||||
|
avatarUrl:
|
||||||
|
"https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/images/mock/avatar/avatar-1.webp",
|
||||||
|
description: "微信小程序客服会话",
|
||||||
|
id: "customer-service",
|
||||||
|
lastActivityLabel: "刚刚",
|
||||||
|
lastMessage: "我的订单",
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
author: { id: "customer-zhang", name: "张晓敏" },
|
||||||
|
createdAt: "2026-07-31T09:30:00+08:00",
|
||||||
|
direction: "incoming",
|
||||||
|
id: "welcome",
|
||||||
|
msgtype: "text",
|
||||||
|
text: { content: "你好,我想了解一下订单的配送进度。" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createdAt: "2026-07-31T09:31:00+08:00",
|
||||||
|
direction: "outgoing",
|
||||||
|
id: "campaign-image",
|
||||||
|
image: { media_id: "campaign-banner" },
|
||||||
|
msgtype: "image",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createdAt: "2026-07-31T09:32:00+08:00",
|
||||||
|
direction: "outgoing",
|
||||||
|
id: "help-link",
|
||||||
|
link: {
|
||||||
|
description: "查看商品、订单与售后服务说明。",
|
||||||
|
thumb_url:
|
||||||
|
"https://images.unsplash.com/photo-1556740758-90de374c12ad?auto=format&fit=crop&w=640&q=80",
|
||||||
|
title: "帮助中心",
|
||||||
|
url: "https://example.com/help",
|
||||||
|
},
|
||||||
|
msgtype: "link",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
createdAt: "2026-07-31T09:33:00+08:00",
|
||||||
|
direction: "outgoing",
|
||||||
|
id: "orders-card",
|
||||||
|
miniprogrampage: {
|
||||||
|
pagepath: "pages/orders/index",
|
||||||
|
thumb_media_id: "order-card-thumbnail",
|
||||||
|
title: "我的订单",
|
||||||
|
},
|
||||||
|
msgtype: "miniprogrampage",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "张晓敏",
|
||||||
|
unreadCount: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatarUrl:
|
||||||
|
"https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/images/mock/avatar/avatar-4.webp",
|
||||||
|
description: "微信小程序客服会话",
|
||||||
|
id: "shipping",
|
||||||
|
lastActivityLabel: "昨天",
|
||||||
|
lastMessage: "请问我的包裹什么时候可以送到?",
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
author: { id: "customer-li", name: "李雨晴" },
|
||||||
|
createdAt: "2026-07-30T16:20:00+08:00",
|
||||||
|
direction: "incoming",
|
||||||
|
id: "shipping-status",
|
||||||
|
msgtype: "text",
|
||||||
|
text: { content: "请问我的包裹什么时候可以送到?" },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
title: "李雨晴",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export function ChatsDemoPage() {
|
||||||
|
const [activeConversationId, setActiveConversationId] = React.useState(
|
||||||
|
initialConversations[0]!.id
|
||||||
|
)
|
||||||
|
const [conversations, setConversations] = React.useState(initialConversations)
|
||||||
|
const [hasMoreHistory, setHasMoreHistory] = React.useState(true)
|
||||||
|
const [mediaUrls, setMediaUrls] = React.useState(mockMediaUrls)
|
||||||
|
const objectUrlsRef = React.useRef(new Set<string>())
|
||||||
|
|
||||||
|
React.useEffect(
|
||||||
|
() => () => {
|
||||||
|
for (const url of objectUrlsRef.current) URL.revokeObjectURL(url)
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
const appendMessages = React.useCallback(
|
||||||
|
(conversationId: string, messages: readonly ChatMessage[]) => {
|
||||||
|
if (messages.length === 0) return
|
||||||
|
|
||||||
|
const lastMessage = messages.at(-1)!
|
||||||
|
setConversations((current) =>
|
||||||
|
current.map((conversation) =>
|
||||||
|
conversation.id === conversationId
|
||||||
|
? {
|
||||||
|
...conversation,
|
||||||
|
lastActivityLabel: "刚刚",
|
||||||
|
lastMessage: getMessagePreview(lastMessage),
|
||||||
|
messages: [...conversation.messages, ...messages],
|
||||||
|
unreadCount: 0,
|
||||||
|
}
|
||||||
|
: conversation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleSend = React.useCallback(
|
||||||
|
async ({
|
||||||
|
conversation,
|
||||||
|
files,
|
||||||
|
text,
|
||||||
|
}: Parameters<
|
||||||
|
NonNullable<React.ComponentProps<typeof ChatWorkspace>["onSend"]>
|
||||||
|
>[0]) => {
|
||||||
|
const createdAt = new Date().toISOString()
|
||||||
|
const prefix = `${Date.now()}`
|
||||||
|
const messages: ChatMessage[] = []
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
messages.push({
|
||||||
|
createdAt,
|
||||||
|
direction: "outgoing",
|
||||||
|
id: `${prefix}:text`,
|
||||||
|
msgtype: "text",
|
||||||
|
status: "sent",
|
||||||
|
text: { content: text },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const newMediaUrls: Record<string, string> = {}
|
||||||
|
for (const [index, file] of files.entries()) {
|
||||||
|
const url = URL.createObjectURL(file)
|
||||||
|
objectUrlsRef.current.add(url)
|
||||||
|
|
||||||
|
if (file.type.startsWith("image/")) {
|
||||||
|
const mediaId = `${prefix}:image:${index}`
|
||||||
|
newMediaUrls[mediaId] = url
|
||||||
|
messages.push({
|
||||||
|
createdAt,
|
||||||
|
direction: "outgoing",
|
||||||
|
id: mediaId,
|
||||||
|
image: { media_id: mediaId },
|
||||||
|
msgtype: "image",
|
||||||
|
status: "sent",
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
messages.push({
|
||||||
|
createdAt,
|
||||||
|
direction: "outgoing",
|
||||||
|
id: `${prefix}:link:${index}`,
|
||||||
|
link: {
|
||||||
|
description: "本地选择的文件(仅用于模拟)。",
|
||||||
|
thumb_url: "",
|
||||||
|
title: file.name,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
msgtype: "link",
|
||||||
|
status: "sent",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(newMediaUrls).length > 0) {
|
||||||
|
setMediaUrls((current) => ({ ...current, ...newMediaUrls }))
|
||||||
|
}
|
||||||
|
appendMessages(conversation.id, messages)
|
||||||
|
},
|
||||||
|
[appendMessages]
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleLoadEarlierMessages = React.useCallback(
|
||||||
|
(conversation: ChatConversation) => {
|
||||||
|
setHasMoreHistory(false)
|
||||||
|
setConversations((current) =>
|
||||||
|
current.map((currentConversation) =>
|
||||||
|
currentConversation.id === conversation.id
|
||||||
|
? {
|
||||||
|
...currentConversation,
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
author: { id: "customer-zhang", name: "张晓敏" },
|
||||||
|
createdAt: "2026-07-31T09:20:00+08:00",
|
||||||
|
direction: "incoming",
|
||||||
|
id: `${conversation.id}:earlier-message`,
|
||||||
|
msgtype: "text",
|
||||||
|
text: { content: "我昨天已经联系过客服了。" },
|
||||||
|
},
|
||||||
|
...currentConversation.messages,
|
||||||
|
],
|
||||||
|
}
|
||||||
|
: currentConversation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex min-w-0 flex-col gap-6">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-xl font-medium">聊天模拟器</h1>
|
||||||
|
<p className="mt-1 text-sm text-muted-foreground">
|
||||||
|
所有数据仅保存在浏览器内,可模拟微信小程序客服的文本、图片、图文链接和小程序卡片消息。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ChatWorkspace
|
||||||
|
activeConversationId={activeConversationId}
|
||||||
|
conversations={conversations}
|
||||||
|
hasMoreMessages={
|
||||||
|
hasMoreHistory && activeConversationId === "customer-service"
|
||||||
|
}
|
||||||
|
maxHeight="calc(100svh - 15rem)"
|
||||||
|
minHeight="min(36rem, calc(100svh - 15rem))"
|
||||||
|
onActiveConversationChange={(conversation) =>
|
||||||
|
setActiveConversationId(conversation.id)
|
||||||
|
}
|
||||||
|
onLoadEarlierMessages={handleLoadEarlierMessages}
|
||||||
|
onSend={handleSend}
|
||||||
|
resolveMediaUrl={(mediaId) => mediaUrls[mediaId]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMessagePreview(message: ChatMessage) {
|
||||||
|
switch (message.msgtype) {
|
||||||
|
case "text":
|
||||||
|
return message.text.content
|
||||||
|
case "image":
|
||||||
|
return "[图片]"
|
||||||
|
case "link":
|
||||||
|
return message.link.title
|
||||||
|
case "miniprogrampage":
|
||||||
|
return message.miniprogrampage.title
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
|
import { createPortal } from "react-dom"
|
||||||
import { formatForDisplay } from "@tanstack/react-hotkeys"
|
import { formatForDisplay } from "@tanstack/react-hotkeys"
|
||||||
import {
|
import {
|
||||||
LexicalActions,
|
LexicalActions,
|
||||||
@@ -10,6 +11,37 @@ import {
|
|||||||
LexicalRoot,
|
LexicalRoot,
|
||||||
} from "@workspace/lexical"
|
} from "@workspace/lexical"
|
||||||
import { Button } from "@workspace/ui/components/button"
|
import { Button } from "@workspace/ui/components/button"
|
||||||
|
import { MessageScrollerProvider } from "@workspace/ui/components/message-scroller"
|
||||||
|
import {
|
||||||
|
Card,
|
||||||
|
CardAction,
|
||||||
|
CardContent,
|
||||||
|
CardDescription,
|
||||||
|
CardFooter,
|
||||||
|
CardHeader,
|
||||||
|
CardTitle,
|
||||||
|
} from "@workspace/ui/components/card"
|
||||||
|
import {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupButton,
|
||||||
|
} from "@workspace/ui/components/input-group"
|
||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@workspace/ui/components/dropdown-menu"
|
||||||
|
import {
|
||||||
|
GlobeIcon,
|
||||||
|
ImageIcon,
|
||||||
|
PaperclipIcon,
|
||||||
|
PlusIcon,
|
||||||
|
TelescopeIcon,
|
||||||
|
} from "@workspace/ui/components/icon"
|
||||||
|
import { Checkbox } from "@workspace/ui/components/checkbox"
|
||||||
|
|
||||||
const initialEditorHtml = [
|
const initialEditorHtml = [
|
||||||
"<h2>Welcome to the Lexical editor</h2>",
|
"<h2>Welcome to the Lexical editor</h2>",
|
||||||
@@ -19,9 +51,87 @@ const initialEditorHtml = [
|
|||||||
|
|
||||||
export function DashboardPage() {
|
export function DashboardPage() {
|
||||||
const [html, setHtml] = React.useState(initialEditorHtml)
|
const [html, setHtml] = React.useState(initialEditorHtml)
|
||||||
|
const [portalTarget, setPortalTarget] = React.useState<HTMLElement>()
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setPortalTarget(document.body)
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex min-w-0 flex-col gap-6 bg-background">
|
<div className="flex min-w-0 flex-col gap-6 bg-background">
|
||||||
|
{portalTarget &&
|
||||||
|
createPortal(
|
||||||
|
<MessageScrollerProvider>
|
||||||
|
<Card className="fixed inset-y-20 left-1/2 z-1000 flex hidden w-4xl -translate-x-1/2 flex-col rounded-2xl border bg-background shadow-lg">
|
||||||
|
<CardHeader className="shrink-0">
|
||||||
|
<CardTitle>CardTitle</CardTitle>
|
||||||
|
<CardDescription>CardDescription</CardDescription>
|
||||||
|
<CardAction>CardAction</CardAction>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex-1"></CardContent>
|
||||||
|
<CardFooter className="shrink-0">
|
||||||
|
<form className="w-full">
|
||||||
|
<InputGroup>
|
||||||
|
<div className="h-14 w-full px-3 py-2.5" />
|
||||||
|
<InputGroupAddon align="block-end" className="gap-8">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger
|
||||||
|
render={
|
||||||
|
<InputGroupButton
|
||||||
|
aria-label="Add files"
|
||||||
|
type="button"
|
||||||
|
size="icon-sm"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
<PlusIcon />
|
||||||
|
</InputGroupButton>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<DropdownMenuContent
|
||||||
|
align="start"
|
||||||
|
side="top"
|
||||||
|
className="w-44"
|
||||||
|
>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<PaperclipIcon />
|
||||||
|
Add Photos & Files
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<ImageIcon />
|
||||||
|
Create Image
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<TelescopeIcon />
|
||||||
|
Deep Research
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<GlobeIcon />
|
||||||
|
Web Search
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
<label className="ml-auto inline-flex items-center gap-2">
|
||||||
|
<Checkbox />
|
||||||
|
按 Enter 发送
|
||||||
|
</label>
|
||||||
|
<InputGroupButton
|
||||||
|
variant="default"
|
||||||
|
size="icon-sm"
|
||||||
|
className="rounded-full"
|
||||||
|
>
|
||||||
|
<Icon name="huge:arrow-up-01" />
|
||||||
|
<span className="sr-only">Send</span>
|
||||||
|
</InputGroupButton>
|
||||||
|
</InputGroupAddon>
|
||||||
|
</InputGroup>
|
||||||
|
</form>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
</MessageScrollerProvider>,
|
||||||
|
portalTarget
|
||||||
|
)}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-xl font-medium">Lexical editor</h1>
|
<h1 className="text-xl font-medium">Lexical editor</h1>
|
||||||
<p className="mt-1 text-sm text-muted-foreground">
|
<p className="mt-1 text-sm text-muted-foreground">
|
||||||
|
|||||||
@@ -0,0 +1,257 @@
|
|||||||
|
import React, { useState } from "react"
|
||||||
|
import { useMutation } from "@tanstack/react-query"
|
||||||
|
import { Button } from "@workspace/ui/components/button"
|
||||||
|
import { Input } from "@workspace/ui/components/input"
|
||||||
|
import { EyeIcon, EyeOffIcon } from "@workspace/ui/components/icon"
|
||||||
|
import { cn } from "@workspace/ui/lib/utils"
|
||||||
|
import { ThemeToggleButton } from "@workspace/blocks/blocks/appearance"
|
||||||
|
import { Logo } from "@/components/logo"
|
||||||
|
|
||||||
|
export function LoginPage() {
|
||||||
|
return (
|
||||||
|
<div className="isolate h-svh min-h-148 w-svw lg:min-h-164.5">
|
||||||
|
<header className="relative z-10 h-0">
|
||||||
|
<div className="flex h-14 items-center justify-between px-6">
|
||||||
|
<div className="size-6 opacity-0 lg:opacity-100">
|
||||||
|
<Logo />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ThemeToggleButton />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main className="relative isolate flex size-full before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:bg-[url(https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/background/background-3-blur.webp)] before:bg-cover before:bg-center before:bg-no-repeat before:opacity-20">
|
||||||
|
<div className="pointer-events-none hidden w-120 flex-col justify-center gap-16 bg-linear-to-r from-secondary/10 to-muted/20 p-6 pt-18 select-none lg:flex">
|
||||||
|
<div className="text-center">
|
||||||
|
<h2 className="text-3xl font-bold tracking-tight text-foreground">
|
||||||
|
欢迎回来 👋🏻
|
||||||
|
</h2>
|
||||||
|
<p className="mt-4 text-muted-foreground">
|
||||||
|
让商品、订单与运营管理更简单高效。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
src="https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/illustrations/illustration-dashboard.webp"
|
||||||
|
alt=""
|
||||||
|
className="aspect-4/3 w-full object-cover object-center"
|
||||||
|
/>
|
||||||
|
<Features />
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-1 flex-col items-start gap-7 bg-sidebar/80 px-6 py-20 lg:justify-center lg:px-8">
|
||||||
|
<div className="mx-auto mb-10 w-full max-w-md lg:hidden">
|
||||||
|
<Logo className="size-12" />
|
||||||
|
</div>
|
||||||
|
<LoginForm />
|
||||||
|
<div className="lg:h-24" />
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
label: "Jwt",
|
||||||
|
img: "https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/icons/platforms/ic-jwt.svg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Firebase",
|
||||||
|
img: "https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/icons/platforms/ic-firebase.svg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Amplify",
|
||||||
|
img: "https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/icons/platforms/ic-amplify.svg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Auth0",
|
||||||
|
img: "https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/icons/platforms/ic-auth0.svg",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Supabase",
|
||||||
|
img: "https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/icons/platforms/ic-supabase.svg",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function Features() {
|
||||||
|
const [index, setIndex] = React.useState(0)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const timerId = setInterval(() => {
|
||||||
|
setIndex((currentIndex) => (currentIndex + 1) % features.length)
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearInterval(timerId)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul className="flex items-center justify-center gap-4">
|
||||||
|
{features.map((f, i) => (
|
||||||
|
<li
|
||||||
|
key={f.label}
|
||||||
|
className={cn(
|
||||||
|
"transition-[filter] duration-1000 ease-linear",
|
||||||
|
i === index ? "grayscale-0" : "grayscale-100"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<img className="size-8" alt={f.label} src={f.img} />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function LoginForm() {
|
||||||
|
// const navigate = useNavigate()
|
||||||
|
const [username, setUsername] = useState("")
|
||||||
|
const [password, setPassword] = useState("")
|
||||||
|
|
||||||
|
const mutation = useMutation({
|
||||||
|
// mutationFn: () => {
|
||||||
|
// return api.post<AdminAuthResponse>("/api/v1/admin/auth/login", {
|
||||||
|
// username,
|
||||||
|
// password,
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// onSuccess: () => {
|
||||||
|
// login()
|
||||||
|
// Toast("登录成功", "success")
|
||||||
|
// navigate("/", { replace: true })
|
||||||
|
// },
|
||||||
|
// onError: (err: Error) => toast(err.message || "登录失败", "error"),
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mx-auto w-full max-w-md">
|
||||||
|
<h5 className="mb-3 text-2xl font-bold tracking-tight text-foreground">
|
||||||
|
账号登录
|
||||||
|
</h5>
|
||||||
|
<p className="lg:text-md text-sm text-muted-foreground">
|
||||||
|
<span className="text-muted-foreground">
|
||||||
|
请输入您的帐户信息以开始管理您的系统
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<form
|
||||||
|
className="mt-8 space-y-8"
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
mutation.mutate()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
label="用户名"
|
||||||
|
inputId="username"
|
||||||
|
Component={UsernameInput}
|
||||||
|
value={username}
|
||||||
|
setValue={setUsername}
|
||||||
|
/>
|
||||||
|
<Field
|
||||||
|
label="密码"
|
||||||
|
inputId="password"
|
||||||
|
Component={PasswordInput}
|
||||||
|
value={password}
|
||||||
|
setValue={setPassword}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="mt-2 h-12 w-full rounded-lg"
|
||||||
|
disabled={mutation.isPending}
|
||||||
|
>
|
||||||
|
{mutation.isPending ? "登录中..." : "登录"}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FieldInputProps = {
|
||||||
|
inputId: string
|
||||||
|
className?: string
|
||||||
|
value: string
|
||||||
|
setValue: React.Dispatch<React.SetStateAction<string>>
|
||||||
|
}
|
||||||
|
|
||||||
|
type FieldInputComponent = React.ComponentType<FieldInputProps>
|
||||||
|
|
||||||
|
function Field({
|
||||||
|
label,
|
||||||
|
Component,
|
||||||
|
...props
|
||||||
|
}: Omit<FieldInputProps, "className"> & {
|
||||||
|
label: string
|
||||||
|
Component: FieldInputComponent
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<fieldset className="relative flex h-12 items-center rounded-lg border-2 border-border p-0 focus-within:border-primary focus-within:[&_label]:opacity-100">
|
||||||
|
<legend className="ml-2 flex h-0 px-0">
|
||||||
|
<label
|
||||||
|
className="h-fit -translate-y-1/2 px-1 text-sm opacity-50"
|
||||||
|
htmlFor={props.inputId}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
</legend>
|
||||||
|
<Component
|
||||||
|
className="h-full rounded-none border-none bg-transparent outline-none autofill:bg-transparent focus-visible:border-none focus-visible:ring-0 [&:-webkit-autofill]:[-webkit-background-clip:text] [&:-webkit-autofill]:[-webkit-text-fill-color:var(--foreground)] [&:-webkit-autofill]:[transition:background-color_9999s_ease-out]"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</fieldset>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function UsernameInput({
|
||||||
|
inputId,
|
||||||
|
className,
|
||||||
|
value,
|
||||||
|
setValue,
|
||||||
|
}: FieldInputProps) {
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
id={inputId}
|
||||||
|
value={value}
|
||||||
|
className={className}
|
||||||
|
onChange={(e) => setValue(e.target.value)}
|
||||||
|
placeholder="请输入用户名"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function PasswordInput({
|
||||||
|
inputId,
|
||||||
|
className,
|
||||||
|
value,
|
||||||
|
setValue,
|
||||||
|
}: FieldInputProps) {
|
||||||
|
const [isVisible, setVisile] = React.useState(false)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
id={inputId}
|
||||||
|
type={isVisible ? "text" : "password"}
|
||||||
|
value={value}
|
||||||
|
className={cn("relative z-1 pe-24", className)}
|
||||||
|
onChange={(e) => setValue(e.target.value)}
|
||||||
|
placeholder="请输入登录密码"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<div className="absolute top-0 right-0 z-2 flex h-11 w-11 items-center justify-center">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
setVisile((v) => !v)
|
||||||
|
}}
|
||||||
|
className="rounded-sm"
|
||||||
|
>
|
||||||
|
{isVisible ? <EyeIcon /> : <EyeOffIcon />}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -10,13 +10,20 @@
|
|||||||
|
|
||||||
import { Route as rootRouteImport } from './routes/__root'
|
import { Route as rootRouteImport } from './routes/__root'
|
||||||
import { Route as AppRouteImport } from './routes/_app'
|
import { Route as AppRouteImport } from './routes/_app'
|
||||||
|
import { Route as LoginRouteImport } from './routes/login'
|
||||||
import { Route as AppIndexRouteImport } from './routes/_app.index'
|
import { Route as AppIndexRouteImport } from './routes/_app.index'
|
||||||
import { Route as AppSplatRouteImport } from './routes/_app.$'
|
import { Route as AppSplatRouteImport } from './routes/_app.$'
|
||||||
|
import { Route as AppChatsRouteImport } from './routes/_app.chats'
|
||||||
|
|
||||||
const AppRoute = AppRouteImport.update({
|
const AppRoute = AppRouteImport.update({
|
||||||
id: '/_app',
|
id: '/_app',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const LoginRoute = LoginRouteImport.update({
|
||||||
|
id: '/login',
|
||||||
|
path: '/login',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
const AppIndexRoute = AppIndexRouteImport.update({
|
const AppIndexRoute = AppIndexRouteImport.update({
|
||||||
id: '/',
|
id: '/',
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -27,31 +34,43 @@ const AppSplatRoute = AppSplatRouteImport.update({
|
|||||||
path: '/$',
|
path: '/$',
|
||||||
getParentRoute: () => AppRoute,
|
getParentRoute: () => AppRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
const AppChatsRoute = AppChatsRouteImport.update({
|
||||||
|
id: '/chats',
|
||||||
|
path: '/chats',
|
||||||
|
getParentRoute: () => AppRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof AppIndexRoute
|
'/': typeof AppIndexRoute
|
||||||
|
'/login': typeof LoginRoute
|
||||||
'/$': typeof AppSplatRoute
|
'/$': typeof AppSplatRoute
|
||||||
|
'/chats': typeof AppChatsRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
|
'/login': typeof LoginRoute
|
||||||
'/$': typeof AppSplatRoute
|
'/$': typeof AppSplatRoute
|
||||||
|
'/chats': typeof AppChatsRoute
|
||||||
'/': typeof AppIndexRoute
|
'/': typeof AppIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
__root__: typeof rootRouteImport
|
__root__: typeof rootRouteImport
|
||||||
'/_app': typeof AppRouteWithChildren
|
'/_app': typeof AppRouteWithChildren
|
||||||
|
'/login': typeof LoginRoute
|
||||||
'/_app/$': typeof AppSplatRoute
|
'/_app/$': typeof AppSplatRoute
|
||||||
|
'/_app/chats': typeof AppChatsRoute
|
||||||
'/_app/': typeof AppIndexRoute
|
'/_app/': typeof AppIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
fullPaths: '/' | '/$'
|
fullPaths: '/' | '/login' | '/$' | '/chats'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to: '/$' | '/'
|
to: '/login' | '/$' | '/chats' | '/'
|
||||||
id: '__root__' | '/_app' | '/_app/$' | '/_app/'
|
id: '__root__' | '/_app' | '/login' | '/_app/$' | '/_app/chats' | '/_app/'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
AppRoute: typeof AppRouteWithChildren
|
AppRoute: typeof AppRouteWithChildren
|
||||||
|
LoginRoute: typeof LoginRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
@@ -63,6 +82,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AppRouteImport
|
preLoaderRoute: typeof AppRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/login': {
|
||||||
|
id: '/login'
|
||||||
|
path: '/login'
|
||||||
|
fullPath: '/login'
|
||||||
|
preLoaderRoute: typeof LoginRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
'/_app/': {
|
'/_app/': {
|
||||||
id: '/_app/'
|
id: '/_app/'
|
||||||
path: '/'
|
path: '/'
|
||||||
@@ -77,16 +103,25 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AppSplatRouteImport
|
preLoaderRoute: typeof AppSplatRouteImport
|
||||||
parentRoute: typeof AppRoute
|
parentRoute: typeof AppRoute
|
||||||
}
|
}
|
||||||
|
'/_app/chats': {
|
||||||
|
id: '/_app/chats'
|
||||||
|
path: '/chats'
|
||||||
|
fullPath: '/chats'
|
||||||
|
preLoaderRoute: typeof AppChatsRouteImport
|
||||||
|
parentRoute: typeof AppRoute
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AppRouteChildren {
|
interface AppRouteChildren {
|
||||||
AppSplatRoute: typeof AppSplatRoute
|
AppSplatRoute: typeof AppSplatRoute
|
||||||
|
AppChatsRoute: typeof AppChatsRoute
|
||||||
AppIndexRoute: typeof AppIndexRoute
|
AppIndexRoute: typeof AppIndexRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppRouteChildren: AppRouteChildren = {
|
const AppRouteChildren: AppRouteChildren = {
|
||||||
AppSplatRoute: AppSplatRoute,
|
AppSplatRoute: AppSplatRoute,
|
||||||
|
AppChatsRoute: AppChatsRoute,
|
||||||
AppIndexRoute: AppIndexRoute,
|
AppIndexRoute: AppIndexRoute,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +129,7 @@ const AppRouteWithChildren = AppRoute._addFileChildren(AppRouteChildren)
|
|||||||
|
|
||||||
const rootRouteChildren: RootRouteChildren = {
|
const rootRouteChildren: RootRouteChildren = {
|
||||||
AppRoute: AppRouteWithChildren,
|
AppRoute: AppRouteWithChildren,
|
||||||
|
LoginRoute: LoginRoute,
|
||||||
}
|
}
|
||||||
export const routeTree = rootRouteImport
|
export const routeTree = rootRouteImport
|
||||||
._addFileChildren(rootRouteChildren)
|
._addFileChildren(rootRouteChildren)
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
|
|
||||||
|
import { ChatsDemoPage } from "@/pages/chats-demo-page"
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/_app/chats")({
|
||||||
|
component: ChatsDemoPage,
|
||||||
|
})
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { LoginPage } from "@/pages/login-page"
|
||||||
|
import { createFileRoute } from "@tanstack/react-router"
|
||||||
|
|
||||||
|
export const Route = createFileRoute("/login")({
|
||||||
|
component: LoginPage,
|
||||||
|
})
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// oxlint-disable-next-line import/no-unassigned-import -- Enforces server-only module usage.
|
||||||
import "@tanstack/react-start/server-only"
|
import "@tanstack/react-start/server-only"
|
||||||
import { getCookie, setCookie } from "@tanstack/react-start/server"
|
import { getCookie, setCookie } from "@tanstack/react-start/server"
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// oxlint-disable-next-line import/no-unassigned-import -- Enforces server-only module usage.
|
||||||
import "@tanstack/react-start/server-only"
|
import "@tanstack/react-start/server-only"
|
||||||
import { getCookie, setCookie } from "@tanstack/react-start/server"
|
import { getCookie, setCookie } from "@tanstack/react-start/server"
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@import "@workspace/ui/globals.css";
|
@import "@workspace/ui/globals.css";
|
||||||
@import "@workspace/blocks/globals.css";
|
@import "@workspace/blocks/globals.css";
|
||||||
@import "@workspace/lexical/globals.css";
|
@import "@workspace/lexical/globals.css";
|
||||||
|
@import "@workspace/search/globals.css";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--ui-content-top-gap: --spacing(2);
|
--ui-content-top-gap: --spacing(2);
|
||||||
|
|||||||
@@ -28,4 +28,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
@@ -11,4 +11,4 @@
|
|||||||
"@workspace/ui/*": ["../../packages/ui/src/*"]
|
"@workspace/ui/*": ["../../packages/ui/src/*"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,4 +21,4 @@
|
|||||||
"noFallthroughCasesInSwitch": true
|
"noFallthroughCasesInSwitch": true
|
||||||
},
|
},
|
||||||
"include": ["vite.config.ts"]
|
"include": ["vite.config.ts"]
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from "path"
|
import path from "path"
|
||||||
import tailwindcss from "@tailwindcss/vite"
|
import tailwindcss from "@tailwindcss/vite"
|
||||||
|
import { icones } from "@icones/vite"
|
||||||
import { tanstackStart } from "@tanstack/react-start/plugin/vite"
|
import { tanstackStart } from "@tanstack/react-start/plugin/vite"
|
||||||
import { i18n } from "@workspace/i18n/vite"
|
import { i18n } from "@workspace/i18n/vite"
|
||||||
import react from "@vitejs/plugin-react"
|
import react from "@vitejs/plugin-react"
|
||||||
@@ -14,11 +15,9 @@ export default defineConfig({
|
|||||||
"@": path.resolve(__dirname, "./src"),
|
"@": path.resolve(__dirname, "./src"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
optimizeDeps: {
|
|
||||||
include: ["use-sync-external-store/shim/with-selector"],
|
|
||||||
},
|
|
||||||
plugins: [
|
plugins: [
|
||||||
i18n(),
|
i18n(),
|
||||||
|
icones({ mode: "symbol", emitData: false }),
|
||||||
tailwindcss(),
|
tailwindcss(),
|
||||||
tanstackStart({
|
tanstackStart({
|
||||||
router: {
|
router: {
|
||||||
@@ -31,6 +30,6 @@ export default defineConfig({
|
|||||||
],
|
],
|
||||||
server: {
|
server: {
|
||||||
host: "0.0.0.0",
|
host: "0.0.0.0",
|
||||||
port: 31573,
|
port: 7100,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import path from "node:path"
|
import path from "node:path"
|
||||||
|
import { icones } from "@icones/vite"
|
||||||
import react from "@vitejs/plugin-react"
|
import react from "@vitejs/plugin-react"
|
||||||
import { defineConfig } from "vitest/config"
|
import { defineConfig } from "vitest/config"
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [icones({ mode: "symbol", emitData: false }), react()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
"@": path.resolve(__dirname, "./src"),
|
"@": path.resolve(__dirname, "./src"),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"@base-ui/react": "^1.6.0",
|
"@base-ui/react": "^1.6.0",
|
||||||
"@base-ui/utils": "^0.3.1",
|
"@base-ui/utils": "^0.3.1",
|
||||||
"@floating-ui/utils": "^0.2.12",
|
"@floating-ui/utils": "^0.2.12",
|
||||||
"@iconify/react": "^6.0.2",
|
"@icones/react": "^0.0.1",
|
||||||
"@lingui/core": "^6",
|
"@lingui/core": "^6",
|
||||||
"@tanstack/react-form": "^1.33.2",
|
"@tanstack/react-form": "^1.33.2",
|
||||||
"@tanstack/react-hotkeys": "^0.10.0",
|
"@tanstack/react-hotkeys": "^0.10.0",
|
||||||
@@ -26,17 +26,16 @@
|
|||||||
"@tanstack/react-start": "^1.168.32",
|
"@tanstack/react-start": "^1.168.32",
|
||||||
"@workspace/blocks": "workspace:*",
|
"@workspace/blocks": "workspace:*",
|
||||||
"@workspace/i18n": "workspace:*",
|
"@workspace/i18n": "workspace:*",
|
||||||
"@workspace/icons": "workspace:*",
|
|
||||||
"@workspace/lexical": "workspace:*",
|
"@workspace/lexical": "workspace:*",
|
||||||
|
"@workspace/search": "workspace:*",
|
||||||
"@workspace/ui": "workspace:*",
|
"@workspace/ui": "workspace:*",
|
||||||
"country-flag-icons": "^1.6.20",
|
|
||||||
"lucide-react": "^1.27.0",
|
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-day-picker": "^10.0.1",
|
"react-day-picker": "^10.0.1",
|
||||||
"react-dom": "^19.2.6",
|
"react-dom": "^19.2.6",
|
||||||
"sonner": "^2.0.7",
|
"sonner": "^2.0.7",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@icones/vite": "^0.0.1",
|
||||||
"@tailwindcss/vite": "^4",
|
"@tailwindcss/vite": "^4",
|
||||||
"@testing-library/react": "^16.3.2",
|
"@testing-library/react": "^16.3.2",
|
||||||
"@types/node": "^24",
|
"@types/node": "^24",
|
||||||
@@ -50,6 +49,39 @@
|
|||||||
"vitest": "^4.1.10",
|
"vitest": "^4.1.10",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"docs": {
|
||||||
|
"name": "docs",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@icones/react": "^0.0.1",
|
||||||
|
"@workspace/i18n": "workspace:*",
|
||||||
|
"@workspace/preferences": "workspace:*",
|
||||||
|
"@workspace/search": "workspace:*",
|
||||||
|
"@workspace/ui": "workspace:*",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"react": "^19.2.8",
|
||||||
|
"react-dom": "^19.2.8",
|
||||||
|
"tailwind-merge": "^3.7.0",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.29.7",
|
||||||
|
"@icones/vite": "^0.0.1",
|
||||||
|
"@rolldown/plugin-babel": "^0.2.3",
|
||||||
|
"@tailwindcss/vite": "^4.3.3",
|
||||||
|
"@types/babel__core": "^7.20.5",
|
||||||
|
"@types/node": "^24.13.3",
|
||||||
|
"@types/react": "^19.2.18",
|
||||||
|
"@types/react-dom": "^19.2.7",
|
||||||
|
"@vitejs/plugin-react": "^6.1.1",
|
||||||
|
"babel-plugin-react-compiler": "^1.0.0",
|
||||||
|
"oxlint": "^1.81.0",
|
||||||
|
"satteri": "^0.10.5",
|
||||||
|
"tailwindcss": "^4.3.3",
|
||||||
|
"typescript": "~6.0.2",
|
||||||
|
"vite": "^8.3.0",
|
||||||
|
"vite-plugin-satteri": "^0.3.5",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/blocks": {
|
"packages/blocks": {
|
||||||
"name": "@workspace/blocks",
|
"name": "@workspace/blocks",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
@@ -57,14 +89,14 @@
|
|||||||
"@base-ui/react": "^1.6.0",
|
"@base-ui/react": "^1.6.0",
|
||||||
"@base-ui/utils": "^0.3.1",
|
"@base-ui/utils": "^0.3.1",
|
||||||
"@floating-ui/utils": "^0.2.12",
|
"@floating-ui/utils": "^0.2.12",
|
||||||
|
"@icones/react": "^0.0.1",
|
||||||
|
"@lexical/react": "^0.48.0",
|
||||||
"@tanstack/react-hotkeys": "^0.10.0",
|
"@tanstack/react-hotkeys": "^0.10.0",
|
||||||
"@tanstack/react-query": "^5.101.4",
|
"@tanstack/react-query": "^5.101.4",
|
||||||
"@tanstack/react-router": "^1.170.18",
|
"@tanstack/react-router": "^1.170.18",
|
||||||
"@workspace/i18n": "workspace:*",
|
"@workspace/i18n": "workspace:*",
|
||||||
"@workspace/icons": "workspace:*",
|
|
||||||
"@workspace/ui": "workspace:*",
|
"@workspace/ui": "workspace:*",
|
||||||
"cmdk": "^1.1.1",
|
"lexical": "^0.48.0",
|
||||||
"lucide-react": "^1.27.0",
|
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-dom": "^19.2.6",
|
"react-dom": "^19.2.6",
|
||||||
},
|
},
|
||||||
@@ -89,9 +121,9 @@
|
|||||||
"@lingui/core": "^6",
|
"@lingui/core": "^6",
|
||||||
"@lingui/react": "^6",
|
"@lingui/react": "^6",
|
||||||
"@vitejs/plugin-react": "^6",
|
"@vitejs/plugin-react": "^6",
|
||||||
|
"@workspace/ui": "workspace:*",
|
||||||
"ansi-to-react": "^6.2.6",
|
"ansi-to-react": "^6.2.6",
|
||||||
"cac": "^7.0.0",
|
"cac": "^7.0.0",
|
||||||
"lucide-react": "^1.27.0",
|
|
||||||
"open": "^11.0.0",
|
"open": "^11.0.0",
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-dom": "^19.2.6",
|
"react-dom": "^19.2.6",
|
||||||
@@ -107,19 +139,6 @@
|
|||||||
"vitest": "^4",
|
"vitest": "^4",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages/icons": {
|
|
||||||
"name": "@workspace/icons",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@hugeicons/core-free-icons": "^4.2.3",
|
|
||||||
"@hugeicons/react": "^1.1.9",
|
|
||||||
"react": "^19.2.6",
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/react": "^19",
|
|
||||||
"typescript": "~6",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"packages/lexical": {
|
"packages/lexical": {
|
||||||
"name": "@workspace/lexical",
|
"name": "@workspace/lexical",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
@@ -135,7 +154,6 @@
|
|||||||
"@workspace/i18n": "workspace:*",
|
"@workspace/i18n": "workspace:*",
|
||||||
"@workspace/ui": "workspace:*",
|
"@workspace/ui": "workspace:*",
|
||||||
"lexical": "^0.48.0",
|
"lexical": "^0.48.0",
|
||||||
"lucide-react": "^1.27.0",
|
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-dom": "^19.2.6",
|
"react-dom": "^19.2.6",
|
||||||
},
|
},
|
||||||
@@ -148,6 +166,42 @@
|
|||||||
"vitest": "^4.1.10",
|
"vitest": "^4.1.10",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"packages/preferences": {
|
||||||
|
"name": "@workspace/preferences",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^19.2.6",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@testing-library/react": "^16.3.2",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19",
|
||||||
|
"jsdom": "^30.0.1",
|
||||||
|
"react-dom": "^19.2.6",
|
||||||
|
"typescript": "~6",
|
||||||
|
"vitest": "^4.1.10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages/search": {
|
||||||
|
"name": "@workspace/search",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/react-hotkeys": "^0.10.0",
|
||||||
|
"@workspace/i18n": "workspace:*",
|
||||||
|
"@workspace/ui": "workspace:*",
|
||||||
|
"cmdk": "^1.1.1",
|
||||||
|
"react": "^19.2.6",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@testing-library/react": "^16.3.2",
|
||||||
|
"@types/react": "^19",
|
||||||
|
"@types/react-dom": "^19",
|
||||||
|
"jsdom": "^30.0.1",
|
||||||
|
"react-dom": "^19.2.6",
|
||||||
|
"typescript": "~6",
|
||||||
|
"vitest": "^4.1.10",
|
||||||
|
},
|
||||||
|
},
|
||||||
"packages/ui": {
|
"packages/ui": {
|
||||||
"name": "@workspace/ui",
|
"name": "@workspace/ui",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
@@ -155,6 +209,7 @@
|
|||||||
"@base-ui/react": "^1.6.0",
|
"@base-ui/react": "^1.6.0",
|
||||||
"@base-ui/utils": "^0.3.1",
|
"@base-ui/utils": "^0.3.1",
|
||||||
"@fontsource-variable/inter": "^5.3.0",
|
"@fontsource-variable/inter": "^5.3.0",
|
||||||
|
"@icones/react": "^0.0.1",
|
||||||
"@shadcn/react": "^0.2.1",
|
"@shadcn/react": "^0.2.1",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
@@ -162,7 +217,6 @@
|
|||||||
"date-fns": "^4.4.0",
|
"date-fns": "^4.4.0",
|
||||||
"embla-carousel-react": "^8.6.0",
|
"embla-carousel-react": "^8.6.0",
|
||||||
"input-otp": "^1.4.2",
|
"input-otp": "^1.4.2",
|
||||||
"lucide-react": "^1.27.0",
|
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-day-picker": "^10.0.1",
|
"react-day-picker": "^10.0.1",
|
||||||
"react-dom": "^19.2.6",
|
"react-dom": "^19.2.6",
|
||||||
@@ -184,6 +238,8 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
|
"@antfu/install-pkg": ["@antfu/install-pkg@2.0.1", "", { "dependencies": { "package-manager-detector": "^1.7.0", "tinyexec": "^1.2.4" } }, "sha512-iCKVQcIC0e3oDxEfs3SHQGW+ovhBMZmS1TE+bTk50rVyMCBmCfClv7Qi3HQKlumYwvjb/iIMeWCW2i67q6kFfQ=="],
|
||||||
|
|
||||||
"@asamuzakjp/css-color": ["@asamuzakjp/css-color@6.0.5", "", { "dependencies": { "@csstools/css-calc": "^3.2.1", "@csstools/css-color-parser": "^4.1.9", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0", "lru-cache": "^11.5.2" } }, "sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA=="],
|
"@asamuzakjp/css-color": ["@asamuzakjp/css-color@6.0.5", "", { "dependencies": { "@csstools/css-calc": "^3.2.1", "@csstools/css-color-parser": "^4.1.9", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0", "lru-cache": "^11.5.2" } }, "sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA=="],
|
||||||
|
|
||||||
"@asamuzakjp/dom-selector": ["@asamuzakjp/dom-selector@8.3.0", "", { "dependencies": { "bidi-js": "^1.0.3", "css-tree": "^3.2.1", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.5.2" } }, "sha512-UJLfKXBhrc8i1vH2eJXuYQMwlsLKWFw3O+CPqXSuVEiikeAim3UgrfWX0k4tA/X8cRFM8iZ7OaqBokFGbYusdg=="],
|
"@asamuzakjp/dom-selector": ["@asamuzakjp/dom-selector@8.3.0", "", { "dependencies": { "bidi-js": "^1.0.3", "css-tree": "^3.2.1", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.5.2" } }, "sha512-UJLfKXBhrc8i1vH2eJXuYQMwlsLKWFw3O+CPqXSuVEiikeAim3UgrfWX0k4tA/X8cRFM8iZ7OaqBokFGbYusdg=="],
|
||||||
@@ -252,8 +308,42 @@
|
|||||||
|
|
||||||
"@bramus/specificity": ["@bramus/specificity@2.4.2", "", { "dependencies": { "css-tree": "^3.0.0" }, "bin": { "specificity": "bin/cli.js" } }, "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw=="],
|
"@bramus/specificity": ["@bramus/specificity@2.4.2", "", { "dependencies": { "css-tree": "^3.0.0" }, "bin": { "specificity": "bin/cli.js" } }, "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-darwin-arm64": ["@bruits/satteri-darwin-arm64@0.10.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-27KTVl4TJkVahMy/ohyA7qd4938G5UNneFUz/PsScYfpIhj0IVAS23mpcJXdPF44sa6nva198lmV/cKIb2YPyA=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-darwin-x64": ["@bruits/satteri-darwin-x64@0.10.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-IjnLe3nKspq6qaeqGgjT7MT8VrTV74yWRlaag7ZdNsI8TDAYZ0iPxMCo+9KQZHUk5EyVB+reBI/PFWL5KuFw9Q=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-linux-arm64-gnu": ["@bruits/satteri-linux-arm64-gnu@0.10.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-glkYXZCJywjP13v67eAyAMSJdF+ncvEbYvgi/wOtffL9tQ27lr/zsyzUfgs+ovjJ9d8JNQKiXeiArJcX8PJL9w=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-linux-arm64-musl": ["@bruits/satteri-linux-arm64-musl@0.10.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-yWdgG1g17Nh2QyGVlFUxGRa3FEFwiMcpZEyMNWkbM3deC94cmVc+/i9OuyFpdKuWo3GkgoCtYVOoxk1uCnCZIA=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-linux-x64-gnu": ["@bruits/satteri-linux-x64-gnu@0.10.5", "", { "os": "linux", "cpu": "x64" }, "sha512-FVaLoPT1fBgGl0J+AYebyyXJYBachGl8Oyyrf1lye4RTqCB4S0Gwkj1uM9RJyThUOvx5VUmAT1CnNh1SFHA+kw=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-linux-x64-musl": ["@bruits/satteri-linux-x64-musl@0.10.5", "", { "os": "linux", "cpu": "x64" }, "sha512-EHpVAx2bqW3GINHTKkljtxVfQmVDGWIuwOYOP5YghTj+0PkBa2o8oKPRtQ9Kbsr1Fye8jtUcDjhwj2jMNugZKg=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-wasm32-wasi": ["@bruits/satteri-wasm32-wasi@0.10.5", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.2.3" }, "cpu": "none" }, "sha512-ypz8c/Zmipxp4IoeDa228Gstv6TLzVmNs3yC6wKCoNSOjx1iwpgzu87Y3hTkXFdwChVGU85qeUDuOIarGUZQLw=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-win32-arm64-msvc": ["@bruits/satteri-win32-arm64-msvc@0.10.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-siTV88nb0LRqNpkL2gXboqCwVdq95sLtzMHS1/3eONV2gLbB3NAK46wmSMvCO/yquBvI2lvaFIfd8P12ecsxBw=="],
|
||||||
|
|
||||||
|
"@bruits/satteri-win32-x64-msvc": ["@bruits/satteri-win32-x64-msvc@0.10.5", "", { "os": "win32", "cpu": "x64" }, "sha512-C3IfPvfvMXmlzBxaMPKFS1XiuV9pu2mC7YqkPk7PSvTgPZ8gbdASIpHpztDLvTTQjqZ0z1Ol8tK5X+V6XXC0wQ=="],
|
||||||
|
|
||||||
|
"@cloudflare/kv-asset-handler": ["@cloudflare/kv-asset-handler@0.5.0", "", {}, "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg=="],
|
||||||
|
|
||||||
|
"@cloudflare/unenv-preset": ["@cloudflare/unenv-preset@2.16.1", "", { "peerDependencies": { "unenv": "2.0.0-rc.24", "workerd": ">1.20260305.0 <2.0.0-0" }, "optionalPeers": ["workerd"] }, "sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw=="],
|
||||||
|
|
||||||
|
"@cloudflare/workerd-darwin-64": ["@cloudflare/workerd-darwin-64@1.20260908.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-t3juyCXFn12OklBL0S7UC98py3nLEmuioBOUOazeyeVsLUu8fv+pfJrR+XzwSH2Uh6rCXZNogRh+LtV0YpzMcQ=="],
|
||||||
|
|
||||||
|
"@cloudflare/workerd-darwin-arm64": ["@cloudflare/workerd-darwin-arm64@1.20260908.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-I1nwA4qm/fUNSKhPSO76YA6JAhcA0KU63yFcYHN6AiDowGbDyfjDPH9KCVopT5rI1LY4GfbdAi5b9gODqZsAkQ=="],
|
||||||
|
|
||||||
|
"@cloudflare/workerd-linux-64": ["@cloudflare/workerd-linux-64@1.20260908.1", "", { "os": "linux", "cpu": "x64" }, "sha512-s/h5uSW1UC6dGeVKSqrPLpTu+vo0fKJZCNEokW1Ol1qcCB2oN6WCRHhoyzo4Y69oONAXRgLfLBYaHWe7z51Vnw=="],
|
||||||
|
|
||||||
|
"@cloudflare/workerd-linux-arm64": ["@cloudflare/workerd-linux-arm64@1.20260908.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-PP/nUKl0R6colwfocggL8dctO/dFMqMft12unzFUkoAJr0aXQeT+ia0JuNmOUWXe6EfvyCSmAbijEsTKQ5t/ew=="],
|
||||||
|
|
||||||
|
"@cloudflare/workerd-windows-64": ["@cloudflare/workerd-windows-64@1.20260908.1", "", { "os": "win32", "cpu": "x64" }, "sha512-jkaS5EKKTvzAdIlbMfOYrHoTucWVRwYBwIig+xRsjXQv5BXTLA2Llg+iM8djlKtk0CjkztZhXmuxuqoqWKZmFw=="],
|
||||||
|
|
||||||
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
|
"@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="],
|
||||||
|
|
||||||
|
"@cspotcode/source-map-support": ["@cspotcode/source-map-support@0.8.1", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.9" } }, "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw=="],
|
||||||
|
|
||||||
"@csstools/color-helpers": ["@csstools/color-helpers@6.1.0", "", {}, "sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg=="],
|
"@csstools/color-helpers": ["@csstools/color-helpers@6.1.0", "", {}, "sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg=="],
|
||||||
|
|
||||||
"@csstools/css-calc": ["@csstools/css-calc@3.3.0", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ=="],
|
"@csstools/css-calc": ["@csstools/css-calc@3.3.0", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ=="],
|
||||||
@@ -356,14 +446,74 @@
|
|||||||
|
|
||||||
"@hono/node-server": ["@hono/node-server@1.19.15", "", { "peerDependencies": { "hono": "^4" } }, "sha512-Za2ai6TLdKjUvnur+eenO6nuYYipVAEhyCAdaV8IRvmU9kK8crOZUSYvIXn72E4f8fJqyAbpcJuTsYYmZp9Deg=="],
|
"@hono/node-server": ["@hono/node-server@1.19.15", "", { "peerDependencies": { "hono": "^4" } }, "sha512-Za2ai6TLdKjUvnur+eenO6nuYYipVAEhyCAdaV8IRvmU9kK8crOZUSYvIXn72E4f8fJqyAbpcJuTsYYmZp9Deg=="],
|
||||||
|
|
||||||
"@hugeicons/core-free-icons": ["@hugeicons/core-free-icons@4.2.3", "", {}, "sha512-fpiU0qFZkv4ABi23xJ2m4qNr0BBfuIaYjPboN8WDA6aj9D+OzXa7eykxKOpACZRuGbDz1U9S5DsNx1d5KNnsgA=="],
|
"@icones/core": ["@icones/core@0.0.1", "", { "dependencies": { "@icones/names": "^0.0.1" } }, "sha512-75LHdh7YxW+55sIU56vQx6LO+0PFUk3XU8mf4kchgP7r9HtSlMIZomCBIQ3dytZllKGDOvSbJlcHJ59fIGJpbQ=="],
|
||||||
|
|
||||||
"@hugeicons/react": ["@hugeicons/react@1.1.9", "", { "peerDependencies": { "react": ">=16.0.0" } }, "sha512-O+lWSWjbijoAvMCxn4K2bQWCGN5+mP1y5j+X99j23mXMj+s0X25fs71T6t9YJLaBodwmZdaewD27dzS/PiboQw=="],
|
"@icones/icons": ["@icones/icons@0.0.1", "", {}, "sha512-5krQCp13yYEsyUY/kshQNqmcuIiIBUHU9BkSoIc68IG7AOym29ocw5pilHftu+OX1il5BhyusuYVR3qTwyH8Ug=="],
|
||||||
|
|
||||||
"@iconify/react": ["@iconify/react@6.0.2", "", { "dependencies": { "@iconify/types": "^2.0.0" }, "peerDependencies": { "react": ">=16" } }, "sha512-SMmC2sactfpJD427WJEDN6PMyznTFMhByK9yLW0gOTtnjzzbsi/Ke/XqsumsavFPwNiXs8jSiYeZTmLCLwO+Fg=="],
|
"@icones/names": ["@icones/names@0.0.1", "", {}, "sha512-Vl/e1pmZv5PPbRTDE8fd39m0ohpx2vJSEGH8stkk425cmQFFbGhmXhhip/Q1MJ3kx4ZWgww5MrV7fzrHtdEvAw=="],
|
||||||
|
|
||||||
|
"@icones/react": ["@icones/react@0.0.1", "", { "dependencies": { "@icones/core": "^0.0.1" }, "peerDependencies": { "react": "^18.2.0 || ^19.0.0" } }, "sha512-80hN0gf6ozcL8oMUfjZIVLfxegatSOzU2jdmJuzAz6Zq2VIwJHOogi4EfKVJnyq7sWHt4MQr1R0XQrYldK/fFg=="],
|
||||||
|
|
||||||
|
"@icones/vite": ["@icones/vite@0.0.1", "", { "dependencies": { "@icones/core": "^0.0.1", "@icones/icons": "^0.0.1", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.7", "parse5": "^8.0.1", "saxes": "^6.0.0" }, "peerDependencies": { "vite": "^8.0.0" } }, "sha512-QLzjlZm79awfLTdt+p/mvQEKY6fB1QB1nyRUfUNoAq5ukolEmKAfbmANq5z3gR/FKk1wWHABMcK7LICzVIUkIA=="],
|
||||||
|
|
||||||
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
"@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
|
||||||
|
|
||||||
|
"@iconify/utils": ["@iconify/utils@3.1.7", "", { "dependencies": { "@antfu/install-pkg": "^2.0.1", "@iconify/types": "^2.0.0", "import-meta-resolve": "^4.2.0" } }, "sha512-JZHlwdID+dy+lTgbYC8NEC4zeugqeYsc6jewvzb4c58kHauJn+X7rNwQjxz5p2qSjqaEeQoLkCIQ9v/H4PK0/w=="],
|
||||||
|
|
||||||
|
"@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="],
|
||||||
|
|
||||||
|
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.1" }, "os": "darwin", "cpu": "arm64" }, "sha512-eEieHsMksAW4IiO5NzauESRl2D2qz3J/kwUxUrSfV06A93eEaRfMpHXyUb1mAqrR7i8U9A0GRqE9pjn6u1Jjpg=="],
|
||||||
|
|
||||||
|
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.1" }, "os": "darwin", "cpu": "x64" }, "sha512-BaktuGPCeHJMARpodR8jK4uKiZrPAy9WrfQW0sdI37clracq8Bp01AYS3SZgi5FS/y5twa9t4+LIuuxQjqRrWw=="],
|
||||||
|
|
||||||
|
"@img/sharp-freebsd-wasm32": ["@img/sharp-freebsd-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "os": "freebsd" }, "sha512-YoAxdnd8hPUkvLHd3bWY+YA8nw3xM/RyRopYucNsWHVSan8NLVM3X2volsfoRDcXdUJPg6tXahSd7HXPK7lRnw=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4V/M3roRMTYjiwZY9IOVQOE8OyeCxFAkYmyZDrZl51uOKjibm3oeEJ4WAmLxutAfzFbC9jqUiPs2gbnGflH+7g=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-c0/DxItpJv2+dGhgycJBBgotdqruGYDvA79drdh0MD1dFpy7JzJ/PlXwi1H4rFf0eTy8tgbI91aHDnZIceY3jQ=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.1", "", { "os": "linux", "cpu": "arm" }, "sha512-aGGy9aWzXgHBG7HNyQPWorZthlp7+x6fDRoPAQbGO3ThcttuTyKIx3NuSHb6zb4gBNq6/yNn9f1cy9nFKS/Vmg=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-JznefmcK9j1JKPz8AkQDh89kjojubyfOasWBPKfzMIhPwsgDy9evpE/naJTXXXmghS1iFwR8u/kTwh/I2/+GCw=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.3.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1EkwGNCZk6iWNCMWqrvdJ+r1j0PT1zIz60CNPhYnJlK/zyeWqlsPZIe+ocBVqPF8k/Ssee/NCk+tE9Ryrko6ng=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.3.1", "", { "os": "linux", "cpu": "none" }, "sha512-Ilays+w2bXdnxzxtQdmXR62u8o8GYa3eL4+Gr+1KiE4xperMZUslRaVPJwwPkzlHEjGfXAfRVAa/7CYCtSqsBw=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-VfBwVHQTbRoj4XlpA/KLZ7ltgMpz+4WSejFzQ+GnoImjo1PtEJ59QB2qR1xQEeRPYIkNrPIm2L4cICMvz4C2ew=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-+c8ukgwU62DS54nCAjw7keOfHUkmr0B5QHEdcOqRnodF/MNXJbVI8Eopoj4B/0H8Asr65I+A4Amrn7a85/md6A=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-qlKb/pwbkAi1WMsJrYHk7CuDrd12s27U2QnRhFYUoJNrRCmkosMTttuRFat/DDB3IlDm5qE1TJgZ4JDnHX8Ldw=="],
|
||||||
|
|
||||||
|
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-yO21HwoUVLN8Qa+/SBjQLMYwBWAVJjeGPNe+hc0OUeMeifEtJqu5a1c4HayE1nNpDih9y3/KkoltfkDodmKAlg=="],
|
||||||
|
|
||||||
|
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.1" }, "os": "linux", "cpu": "arm" }, "sha512-SE4kzF2mepn6z+6E7L6lsV8FzuLL6IPQdyX8ZiwROAG/G8td+hP/m7FsFPwidtrF19gvajuC9l6TxAVcsA4S7A=="],
|
||||||
|
|
||||||
|
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-af12Pnd0ZGu2HfP8NayB0kk6eC/lrfbQE6HlR4jD+34wdJ1Vw9TF6TMn6ZvffT+WgqVsl0hRbmNvz2u/23VmwA=="],
|
||||||
|
|
||||||
|
"@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.3.1" }, "os": "linux", "cpu": "ppc64" }, "sha512-hYSBm7zcNtDCozCxQHYZJiu63b/bXsgRZuOxCIBZsStMM9Vap47iFHdbX4kCvQsblPB/k+clhELpdQJHQLSHvg=="],
|
||||||
|
|
||||||
|
"@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.3.1" }, "os": "linux", "cpu": "none" }, "sha512-qQt0Kc13+Hoan/Awq/qMSQw3L+RI1NCRPgD5cUJ/1WSSmIoysLOc72jlRM3E0OHN9Yr313jgeQ2T+zW+F03QFA=="],
|
||||||
|
|
||||||
|
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.1" }, "os": "linux", "cpu": "s390x" }, "sha512-E4fLLfRPzDLlEeDaTzI98OFLcv++WL5ChLLMwPoVd0CIoZQqupBSNbOisPL5am9XsbQ9T84+iiMpUvbFtkunbA=="],
|
||||||
|
|
||||||
|
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-gi0zFJJRLswfCZmHtJdikXPOc5u7qamSOS3NHedLqLd4W8Q0NqjdBr6TTRIgsfFjqfTsHFgdfvJ9LwqSgcHiAA=="],
|
||||||
|
|
||||||
|
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.1" }, "os": "linux", "cpu": "arm64" }, "sha512-siWbOW1u6HFnFLrp0waKyW7VEf7jYvcDWdrXEFa8AkdAQgEvuu5Fz8/Y70w9EeqAdwDtfU012BhEHHaDqvQNzg=="],
|
||||||
|
|
||||||
|
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.2", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.1" }, "os": "linux", "cpu": "x64" }, "sha512-YBqMMcjDi4QGYiSn4vNOYBhmlC4z5AXqkOUUqI2e0AFA4urNv4ESgOgwNl3K+4etQhha0twXlzeF20bbULm9Yg=="],
|
||||||
|
|
||||||
|
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.35.2", "", { "dependencies": { "@emnapi/runtime": "^1.11.1" } }, "sha512-Mrv4JQNYVQ94xH+jzZ9r+gowleN8mv2FTgKT+PI6bx5C0G8TdNYndu161pg2i7uoBwxy2ImPMHrJOM2LZef7Bw=="],
|
||||||
|
|
||||||
|
"@img/sharp-webcontainers-wasm32": ["@img/sharp-webcontainers-wasm32@0.35.2", "", { "dependencies": { "@img/sharp-wasm32": "0.35.2" }, "cpu": "none" }, "sha512-QNV27pxs9wpApEiCfvHM1RDoP1w1+2KrUWWDPEhEwg+latvOrfuhWrHWZKwdSFwU6jh3myjw/yOCRsUIuOft3g=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.35.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-BiVRYc/t6/Vl3e1hBx0hugG4oN9Pydf4fgMSpxTQJmwGUg/YoXTWHiFeRymHfCZzifxu4F4rpk/I67D0LQ20wQ=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-YYEhx9PImCC7T0tI8JDMi4DB9LwLCXCU5OWNYEXAxh5Q1ShKkyC6byxzoBJ3gEFDnH2lQckWuDe70G7mB2XJog=="],
|
||||||
|
|
||||||
|
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.2", "", { "os": "win32", "cpu": "x64" }, "sha512-imoOyBcoM/iiUr4J6VPpCNjPnjvP/Gks95898yB8YqoGGYmHYbOyCuNv9FMhFgtaiHFGbHW8bxKqRV6VjtXThQ=="],
|
||||||
|
|
||||||
"@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
|
"@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
|
||||||
|
|
||||||
"@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="],
|
"@jest/types": ["@jest/types@29.6.3", "", { "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="],
|
||||||
@@ -448,7 +598,7 @@
|
|||||||
|
|
||||||
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="],
|
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.29.0", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ=="],
|
||||||
|
|
||||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="],
|
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" } }, "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g=="],
|
||||||
|
|
||||||
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
|
||||||
|
|
||||||
@@ -542,6 +692,12 @@
|
|||||||
|
|
||||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.76.0", "", { "os": "win32", "cpu": "x64" }, "sha512-5qcirPHO8nKfkoowEVWtpAoVTcYDy6g0UT0NGic450Qv8J2NrOqg4uQ8QppRP4MDTC7Xx47lbZnmadTH03CGGA=="],
|
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.76.0", "", { "os": "win32", "cpu": "x64" }, "sha512-5qcirPHO8nKfkoowEVWtpAoVTcYDy6g0UT0NGic450Qv8J2NrOqg4uQ8QppRP4MDTC7Xx47lbZnmadTH03CGGA=="],
|
||||||
|
|
||||||
|
"@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="],
|
||||||
|
|
||||||
|
"@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="],
|
||||||
|
|
||||||
|
"@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="],
|
||||||
|
|
||||||
"@preact/signals-core": ["@preact/signals-core@1.14.4", "", {}, "sha512-HNB6HYeYKhQbJ1aKl+YRjrS4+QWHLKX6qKoUsfS/m0vqzsVaEBiZiaKbG/e+NKk2ch5ALQr/ihWaMHxiCuuWHA=="],
|
"@preact/signals-core": ["@preact/signals-core@1.14.4", "", {}, "sha512-HNB6HYeYKhQbJ1aKl+YRjrS4+QWHLKX6qKoUsfS/m0vqzsVaEBiZiaKbG/e+NKk2ch5ALQr/ihWaMHxiCuuWHA=="],
|
||||||
|
|
||||||
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.7", "", {}, "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q=="],
|
"@radix-ui/primitive": ["@radix-ui/primitive@1.1.7", "", {}, "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q=="],
|
||||||
@@ -578,6 +734,8 @@
|
|||||||
|
|
||||||
"@reduxjs/toolkit": ["@reduxjs/toolkit@2.12.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw=="],
|
"@reduxjs/toolkit": ["@reduxjs/toolkit@2.12.0", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, "optionalPeers": ["react", "react-redux"] }, "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-android-arm-eabi": ["@rolldown/binding-android-arm-eabi@1.2.7", "", { "os": "android", "cpu": "arm" }, "sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ=="],
|
||||||
|
|
||||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.5", "", { "os": "android", "cpu": "arm64" }, "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ=="],
|
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.5", "", { "os": "android", "cpu": "arm64" }, "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ=="],
|
||||||
|
|
||||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.1.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw=="],
|
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.1.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw=="],
|
||||||
@@ -608,6 +766,8 @@
|
|||||||
|
|
||||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA=="],
|
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA=="],
|
||||||
|
|
||||||
|
"@rolldown/plugin-babel": ["@rolldown/plugin-babel@0.2.4", "", { "dependencies": { "picomatch": "^4.0.7" }, "peerDependencies": { "@babel/core": "^7.29.0 || ^8.0.0-rc.1", "@babel/plugin-transform-runtime": "^7.29.0 || ^8.0.0-rc.1", "@babel/runtime": "^7.27.0 || ^8.0.0-rc.1", "rolldown": "^1.0.0-rc.5", "vite": "^8.0.0" }, "optionalPeers": ["@babel/plugin-transform-runtime", "@babel/runtime", "vite"] }, "sha512-ygmm2j/mN+aCvstHo0x3IOu4uc6LqXT9SJ3q4kpfG/+Yhfz0B+E47FITcC0FljZADwUFARP6E2kiE+Lc26D8wg=="],
|
||||||
|
|
||||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="],
|
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="],
|
||||||
|
|
||||||
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
|
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
|
||||||
@@ -616,8 +776,12 @@
|
|||||||
|
|
||||||
"@sinclair/typebox": ["@sinclair/typebox@0.27.12", "", {}, "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g=="],
|
"@sinclair/typebox": ["@sinclair/typebox@0.27.12", "", {}, "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g=="],
|
||||||
|
|
||||||
|
"@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="],
|
||||||
|
|
||||||
"@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="],
|
"@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="],
|
||||||
|
|
||||||
|
"@speed-highlight/core": ["@speed-highlight/core@1.2.24", "", {}, "sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw=="],
|
||||||
|
|
||||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||||
|
|
||||||
"@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="],
|
"@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="],
|
||||||
@@ -714,6 +878,14 @@
|
|||||||
|
|
||||||
"@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="],
|
"@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="],
|
||||||
|
|
||||||
|
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
||||||
|
|
||||||
|
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
|
||||||
|
|
||||||
|
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
|
||||||
|
|
||||||
|
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
|
||||||
|
|
||||||
"@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
|
"@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
|
||||||
|
|
||||||
"@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
|
"@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
|
||||||
@@ -738,20 +910,28 @@
|
|||||||
|
|
||||||
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
|
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
|
||||||
|
|
||||||
|
"@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
|
||||||
|
|
||||||
|
"@types/hast": ["@types/hast@3.0.5", "", { "dependencies": { "@types/unist": "*" } }, "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g=="],
|
||||||
|
|
||||||
"@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="],
|
"@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="],
|
||||||
|
|
||||||
"@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.3", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA=="],
|
"@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.3", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA=="],
|
||||||
|
|
||||||
"@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="],
|
"@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="],
|
||||||
|
|
||||||
|
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="],
|
"@types/node": ["@types/node@24.13.3", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="],
|
"@types/react": ["@types/react@19.2.18", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w=="],
|
||||||
|
|
||||||
"@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
|
"@types/react-dom": ["@types/react-dom@19.3.0", "", { "peerDependencies": { "@types/react": "^19.3.0" } }, "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q=="],
|
||||||
|
|
||||||
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
"@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
|
||||||
|
|
||||||
|
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
||||||
|
|
||||||
"@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="],
|
"@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="],
|
||||||
|
|
||||||
"@types/validate-npm-package-name": ["@types/validate-npm-package-name@4.0.2", "", {}, "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw=="],
|
"@types/validate-npm-package-name": ["@types/validate-npm-package-name@4.0.2", "", {}, "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw=="],
|
||||||
@@ -766,7 +946,7 @@
|
|||||||
|
|
||||||
"@vitejs/devtools-kit": ["@vitejs/devtools-kit@0.4.9", "", { "dependencies": { "@devframes/hub": "^0.7.14", "@devframes/json-render": "^0.7.14", "devframe": "^0.7.14", "local-pkg": "^1.2.1", "mlly": "^1.8.2", "nostics": "^1.2.0", "nypm": "^0.6.8" }, "peerDependencies": { "vite": "*" } }, "sha512-uI1Gk4rfc6qCAK+5m5o3d5HCNVPpnGYi+RlGnLuWn6j9XNcvuP1MiZrgEMyXvpbQHEN3N4mcfUswIPc8XnBvsg=="],
|
"@vitejs/devtools-kit": ["@vitejs/devtools-kit@0.4.9", "", { "dependencies": { "@devframes/hub": "^0.7.14", "@devframes/json-render": "^0.7.14", "devframe": "^0.7.14", "local-pkg": "^1.2.1", "mlly": "^1.8.2", "nostics": "^1.2.0", "nypm": "^0.6.8" }, "peerDependencies": { "vite": "*" } }, "sha512-uI1Gk4rfc6qCAK+5m5o3d5HCNVPpnGYi+RlGnLuWn6j9XNcvuP1MiZrgEMyXvpbQHEN3N4mcfUswIPc8XnBvsg=="],
|
||||||
|
|
||||||
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.4", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-XcCQz0TBpBgljhj0gMuuDj49i6Ytqh5q1osT/Gp5uAVJUCTWxyskk/l1jwYYiu2xcNHHipdMz40EGfM1VdamVg=="],
|
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.1.1", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "oxc-transform-react": "^0.145.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler", "oxc-transform-react"] }, "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw=="],
|
||||||
|
|
||||||
"@vitest/expect": ["@vitest/expect@4.1.10", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA=="],
|
"@vitest/expect": ["@vitest/expect@4.1.10", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.10", "@vitest/utils": "4.1.10", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA=="],
|
||||||
|
|
||||||
@@ -804,10 +984,12 @@
|
|||||||
|
|
||||||
"@workspace/i18n": ["@workspace/i18n@workspace:packages/i18n"],
|
"@workspace/i18n": ["@workspace/i18n@workspace:packages/i18n"],
|
||||||
|
|
||||||
"@workspace/icons": ["@workspace/icons@workspace:packages/icons"],
|
|
||||||
|
|
||||||
"@workspace/lexical": ["@workspace/lexical@workspace:packages/lexical"],
|
"@workspace/lexical": ["@workspace/lexical@workspace:packages/lexical"],
|
||||||
|
|
||||||
|
"@workspace/preferences": ["@workspace/preferences@workspace:packages/preferences"],
|
||||||
|
|
||||||
|
"@workspace/search": ["@workspace/search@workspace:packages/search"],
|
||||||
|
|
||||||
"@workspace/ui": ["@workspace/ui@workspace:packages/ui"],
|
"@workspace/ui": ["@workspace/ui@workspace:packages/ui"],
|
||||||
|
|
||||||
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||||
@@ -844,6 +1026,8 @@
|
|||||||
|
|
||||||
"babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="],
|
"babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="],
|
||||||
|
|
||||||
|
"babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="],
|
||||||
|
|
||||||
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||||
|
|
||||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.11.4", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-s4+sLr9mZ/CyqeRritFeYV/Zx73OAtmaHn6kkBS1XRoJn1hrg3xIDUcpicAEX68tkcIN0iBCgti31C8zxtkhsQ=="],
|
"baseline-browser-mapping": ["baseline-browser-mapping@2.11.4", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-s4+sLr9mZ/CyqeRritFeYV/Zx73OAtmaHn6kkBS1XRoJn1hrg3xIDUcpicAEX68tkcIN0iBCgti31C8zxtkhsQ=="],
|
||||||
@@ -852,6 +1036,8 @@
|
|||||||
|
|
||||||
"birpc": ["birpc@4.0.0", "", {}, "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw=="],
|
"birpc": ["birpc@4.0.0", "", {}, "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw=="],
|
||||||
|
|
||||||
|
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
|
||||||
|
|
||||||
"body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="],
|
"body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@5.0.8", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg=="],
|
"brace-expansion": ["brace-expansion@5.0.8", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg=="],
|
||||||
@@ -926,8 +1112,6 @@
|
|||||||
|
|
||||||
"cosmiconfig": ["cosmiconfig@9.0.2", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg=="],
|
"cosmiconfig": ["cosmiconfig@9.0.2", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg=="],
|
||||||
|
|
||||||
"country-flag-icons": ["country-flag-icons@1.6.20", "", {}, "sha512-py8JiEKzjhYw6HPJ0L7SxLgCYim36UPRTZX43/kqGueUCZLSvnrqAiwW8HtQibur7mdkFQUkjOgdK+o/9FBtaw=="],
|
|
||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
|
|
||||||
"crossws": ["crossws@0.4.10", "", { "peerDependencies": { "srvx": ">=0.11.5" }, "optionalPeers": ["srvx"] }, "sha512-pz3oubH/dt12KjqsUB0IuXW4nwRDQ583iDsP4555Cpdqx0NoU7pGlWBcayyFI8f/l/idRpgjMEfwuOxSWJYlIA=="],
|
"crossws": ["crossws@0.4.10", "", { "peerDependencies": { "srvx": ">=0.11.5" }, "optionalPeers": ["srvx"] }, "sha512-pz3oubH/dt12KjqsUB0IuXW4nwRDQ583iDsP4555Cpdqx0NoU7pGlWBcayyFI8f/l/idRpgjMEfwuOxSWJYlIA=="],
|
||||||
@@ -998,6 +1182,8 @@
|
|||||||
|
|
||||||
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
||||||
|
|
||||||
|
"docs": ["docs@workspace:docs"],
|
||||||
|
|
||||||
"dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
|
"dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
|
||||||
|
|
||||||
"dot-prop": ["dot-prop@6.0.1", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA=="],
|
"dot-prop": ["dot-prop@6.0.1", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA=="],
|
||||||
@@ -1032,6 +1218,8 @@
|
|||||||
|
|
||||||
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
|
"error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
|
||||||
|
|
||||||
|
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
|
||||||
|
|
||||||
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
"es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
|
||||||
|
|
||||||
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
|
||||||
@@ -1154,6 +1342,8 @@
|
|||||||
|
|
||||||
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
||||||
|
|
||||||
|
"import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="],
|
||||||
|
|
||||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||||
|
|
||||||
"input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="],
|
"input-otp": ["input-otp@1.4.2", "", { "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA=="],
|
||||||
@@ -1240,29 +1430,29 @@
|
|||||||
|
|
||||||
"lib0": ["lib0@0.2.117", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0serve": "bin/0serve.js", "0gentesthtml": "bin/gentesthtml.js", "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js" } }, "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw=="],
|
"lib0": ["lib0@0.2.117", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0serve": "bin/0serve.js", "0gentesthtml": "bin/gentesthtml.js", "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js" } }, "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw=="],
|
||||||
|
|
||||||
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "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" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
"lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="],
|
||||||
|
|
||||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="],
|
||||||
|
|
||||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.33.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg=="],
|
||||||
|
|
||||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.33.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ=="],
|
||||||
|
|
||||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.33.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.33.0", "", { "os": "linux", "cpu": "arm" }, "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg=="],
|
||||||
|
|
||||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ=="],
|
||||||
|
|
||||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg=="],
|
||||||
|
|
||||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw=="],
|
||||||
|
|
||||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.33.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA=="],
|
||||||
|
|
||||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="],
|
||||||
|
|
||||||
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
"lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
|
||||||
|
|
||||||
@@ -1278,8 +1468,6 @@
|
|||||||
|
|
||||||
"lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="],
|
"lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="],
|
||||||
|
|
||||||
"lucide-react": ["lucide-react@1.27.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-rJicGl/3Fly/E0rOH1YmPZ6e49JCnKknh1ox1vpHnkfjujAkKA6sqUZvH3MTAaXXjgexyUwgNwTJzTtYuAFYJw=="],
|
|
||||||
|
|
||||||
"lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="],
|
"lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="],
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
@@ -1306,6 +1494,8 @@
|
|||||||
|
|
||||||
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
|
||||||
|
|
||||||
|
"miniflare": ["miniflare@5.20260908.0-alpha", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.35.2", "undici": "7.29.0", "workerd": "1.20260908.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" } }, "sha512-BHIknb0u6vLIvb+R8PsUAzgoWWk3OlW85DrV2SG0EydfSpIba28YT0rH6xZThjnSwDxzNuW3FDRNSWvbiI/DVw=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
||||||
|
|
||||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||||
@@ -1318,7 +1508,7 @@
|
|||||||
|
|
||||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
"nanoid": ["nanoid@3.3.16", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q=="],
|
"nanoid": ["nanoid@3.3.18", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="],
|
||||||
|
|
||||||
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||||
|
|
||||||
@@ -1370,6 +1560,8 @@
|
|||||||
|
|
||||||
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
|
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
|
||||||
|
|
||||||
|
"package-manager-detector": ["package-manager-detector@1.8.0", "", {}, "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A=="],
|
||||||
|
|
||||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||||
|
|
||||||
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
|
"parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
|
||||||
@@ -1386,7 +1578,7 @@
|
|||||||
|
|
||||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||||
|
|
||||||
"path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
|
"path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
|
||||||
|
|
||||||
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
"pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
|
||||||
|
|
||||||
@@ -1404,7 +1596,7 @@
|
|||||||
|
|
||||||
"pofile-ts": ["pofile-ts@4.0.3", "", {}, "sha512-sz1pnjgEfPyZ+QvaeX3NtCmbYnEvG01LZRLoN/uXoLtPZtxCIH5IctL7yXXc0fFyk/fqV6K8g3hlNfr6IJwupA=="],
|
"pofile-ts": ["pofile-ts@4.0.3", "", {}, "sha512-sz1pnjgEfPyZ+QvaeX3NtCmbYnEvG01LZRLoN/uXoLtPZtxCIH5IctL7yXXc0fFyk/fqV6K8g3hlNfr6IJwupA=="],
|
||||||
|
|
||||||
"postcss": ["postcss@8.5.23", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg=="],
|
"postcss": ["postcss@8.5.28", "", { "dependencies": { "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A=="],
|
||||||
|
|
||||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="],
|
"postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="],
|
||||||
|
|
||||||
@@ -1484,6 +1676,8 @@
|
|||||||
|
|
||||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||||
|
|
||||||
|
"satteri": ["satteri@0.10.5", "", { "dependencies": { "@types/estree-jsx": "^1.0.5", "@types/hast": "^3.0.5", "@types/mdast": "^4.0.4", "@types/unist": "^3.0.3" }, "optionalDependencies": { "@bruits/satteri-darwin-arm64": "0.10.5", "@bruits/satteri-darwin-x64": "0.10.5", "@bruits/satteri-linux-arm64-gnu": "0.10.5", "@bruits/satteri-linux-arm64-musl": "0.10.5", "@bruits/satteri-linux-x64-gnu": "0.10.5", "@bruits/satteri-linux-x64-musl": "0.10.5", "@bruits/satteri-wasm32-wasi": "0.10.5", "@bruits/satteri-win32-arm64-msvc": "0.10.5", "@bruits/satteri-win32-x64-msvc": "0.10.5" } }, "sha512-Ao1LKpAEa9Wdg0otgbVKViZHEq9ebdXe4DMrp3s9vQAU0HNIuHnFEuMuOcm0ZIXyV0Yzxj91NvhLpvXZJO/5ZQ=="],
|
||||||
|
|
||||||
"saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
|
"saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
|
||||||
|
|
||||||
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
"scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||||
@@ -1502,6 +1696,8 @@
|
|||||||
|
|
||||||
"shadcn": ["shadcn@4.15.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "kleur": "^4.1.5", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "undici": "^7.27.2", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-fFTpfOuRwqjpXGp/sKpAxJkjdgv1jf8bDrW1xi0cVn2k7WJ5ijV/gjkAlkAidGDjhEkgcUuxVdm4oRB9r8BivA=="],
|
"shadcn": ["shadcn@4.15.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "kleur": "^4.1.5", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "undici": "^7.27.2", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-fFTpfOuRwqjpXGp/sKpAxJkjdgv1jf8bDrW1xi0cVn2k7WJ5ijV/gjkAlkAidGDjhEkgcUuxVdm4oRB9r8BivA=="],
|
||||||
|
|
||||||
|
"sharp": ["sharp@0.35.2", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.4" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.2", "@img/sharp-darwin-x64": "0.35.2", "@img/sharp-freebsd-wasm32": "0.35.2", "@img/sharp-libvips-darwin-arm64": "1.3.1", "@img/sharp-libvips-darwin-x64": "1.3.1", "@img/sharp-libvips-linux-arm": "1.3.1", "@img/sharp-libvips-linux-arm64": "1.3.1", "@img/sharp-libvips-linux-ppc64": "1.3.1", "@img/sharp-libvips-linux-riscv64": "1.3.1", "@img/sharp-libvips-linux-s390x": "1.3.1", "@img/sharp-libvips-linux-x64": "1.3.1", "@img/sharp-libvips-linuxmusl-arm64": "1.3.1", "@img/sharp-libvips-linuxmusl-x64": "1.3.1", "@img/sharp-linux-arm": "0.35.2", "@img/sharp-linux-arm64": "0.35.2", "@img/sharp-linux-ppc64": "0.35.2", "@img/sharp-linux-riscv64": "0.35.2", "@img/sharp-linux-s390x": "0.35.2", "@img/sharp-linux-x64": "0.35.2", "@img/sharp-linuxmusl-arm64": "0.35.2", "@img/sharp-linuxmusl-x64": "0.35.2", "@img/sharp-webcontainers-wasm32": "0.35.2", "@img/sharp-win32-arm64": "0.35.2", "@img/sharp-win32-ia32": "0.35.2", "@img/sharp-win32-x64": "0.35.2" } }, "sha512-FVtFjtBCMiJS6yb5CX7Sop45WFMpeGw6oRKuJnXYgf/f1ms/D7LE/ZUSNxnW7rZ/dbslQWYkoqFHGPaDBtaK4w=="],
|
||||||
|
|
||||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||||
|
|
||||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||||
@@ -1520,6 +1716,8 @@
|
|||||||
|
|
||||||
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
||||||
|
|
||||||
|
"smol-toml": ["smol-toml@1.8.0", "", {}, "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ=="],
|
||||||
|
|
||||||
"sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="],
|
"sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="],
|
||||||
|
|
||||||
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
|
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
|
||||||
@@ -1554,7 +1752,7 @@
|
|||||||
|
|
||||||
"tabbable": ["tabbable@6.5.0", "", {}, "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA=="],
|
"tabbable": ["tabbable@6.5.0", "", {}, "sha512-wieBHXygIm7OyQOu5hQlkk62/WyCFYGlWg7L6/ZCUZwx0o398Zkn4pVmMyfYhfMG8kGrj/Krt8eIk6UKC6VzwA=="],
|
||||||
|
|
||||||
"tailwind-merge": ["tailwind-merge@3.6.0", "", {}, "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w=="],
|
"tailwind-merge": ["tailwind-merge@3.7.0", "", {}, "sha512-XPPUyAc+cvspz3lHTcR/QgPfW2A0lv/xQNIjX3HGhLR+Nq2lHaLq5MtTesHn8GUr3W3DguT2KT5x3NVgRtYwmA=="],
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="],
|
"tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="],
|
||||||
|
|
||||||
@@ -1634,7 +1832,9 @@
|
|||||||
|
|
||||||
"victory-vendor": ["victory-vendor@37.3.6", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ=="],
|
"victory-vendor": ["victory-vendor@37.3.6", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ=="],
|
||||||
|
|
||||||
"vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="],
|
"vite": ["vite@8.3.0", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.7", "postcss": "^8.5.28", "rolldown": "~1.2.6", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.7.1", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ=="],
|
||||||
|
|
||||||
|
"vite-plugin-satteri": ["vite-plugin-satteri@0.3.5", "", { "dependencies": { "smol-toml": "^1.6.1", "yaml": "^2.6.0" }, "peerDependencies": { "satteri": ">=0.10.0", "vite": "^5 || ^6 || ^7 || ^8" } }, "sha512-X41QiFHwlkfcnNE+nOIe6tCeE32M6BKyVN00Wd7irp94lsOmIqXyNtF+lLc2oPIxno0qlVjSyNNPMIZJDghtJQ=="],
|
||||||
|
|
||||||
"vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="],
|
"vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="],
|
||||||
|
|
||||||
@@ -1658,8 +1858,14 @@
|
|||||||
|
|
||||||
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
|
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
|
||||||
|
|
||||||
|
"workerd": ["workerd@1.20260908.1", "", { "optionalDependencies": { "@cloudflare/workerd-darwin-64": "1.20260908.1", "@cloudflare/workerd-darwin-arm64": "1.20260908.1", "@cloudflare/workerd-linux-64": "1.20260908.1", "@cloudflare/workerd-linux-arm64": "1.20260908.1", "@cloudflare/workerd-windows-64": "1.20260908.1" }, "bin": { "workerd": "bin/workerd" } }, "sha512-rYhpW6NWHD++p34ej+VXWzi5Pdnmd7ncdbB/ux4s+i3mf7IeOpW3O4roqClQ+Z8ernvyMCknBLCb76z1rA+a7Q=="],
|
||||||
|
|
||||||
|
"wrangler": ["wrangler@4.130.0", "", { "dependencies": { "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", "miniflare": "5.20260908.0-alpha", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", "workerd": "1.20260908.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "peerDependencies": { "@cloudflare/workers-types": "^5.20260908.1" }, "optionalPeers": ["@cloudflare/workers-types"], "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js", "cf-wrangler": "bin/cf-wrangler.js" } }, "sha512-fzNjnTzyZl31PGJOFXbiLeZqEIToQ9KOzkkvGdQz4wlB+BoHnl3BRwCR5xg8AqYyzVunvvMHlMzvlbThQ7rrAA=="],
|
||||||
|
|
||||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||||
|
|
||||||
|
"ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
|
||||||
|
|
||||||
"wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="],
|
"wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="],
|
||||||
|
|
||||||
"xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="],
|
"xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="],
|
||||||
@@ -1670,12 +1876,18 @@
|
|||||||
|
|
||||||
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||||
|
|
||||||
|
"yaml": ["yaml@2.9.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw=="],
|
||||||
|
|
||||||
"yjs": ["yjs@13.6.31", "", { "dependencies": { "lib0": "^0.2.99" } }, "sha512-Eq+5BRfbeGyqGVrTJL3bEcr8gKkxPuyuoHmAwpk52fDb8kOVMrfVSTRPd6yiGgX5Fskb96qCRjzjbRjrL4YEnw=="],
|
"yjs": ["yjs@13.6.31", "", { "dependencies": { "lib0": "^0.2.99" } }, "sha512-Eq+5BRfbeGyqGVrTJL3bEcr8gKkxPuyuoHmAwpk52fDb8kOVMrfVSTRPd6yiGgX5Fskb96qCRjzjbRjrL4YEnw=="],
|
||||||
|
|
||||||
"yocto-spinner": ["yocto-spinner@1.2.2", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-DODGl1wJjA/s5pnJFKau9lIYHT81lnhob1i3e1TjxZRxEhWRKl74nTbWE6H5KlkViQQTo/Z29YFdxzTZAMY3ng=="],
|
"yocto-spinner": ["yocto-spinner@1.2.2", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-DODGl1wJjA/s5pnJFKau9lIYHT81lnhob1i3e1TjxZRxEhWRKl74nTbWE6H5KlkViQQTo/Z29YFdxzTZAMY3ng=="],
|
||||||
|
|
||||||
"yoctocolors": ["yoctocolors@2.2.0", "", {}, "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg=="],
|
"yoctocolors": ["yoctocolors@2.2.0", "", {}, "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg=="],
|
||||||
|
|
||||||
|
"youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="],
|
||||||
|
|
||||||
|
"youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="],
|
||||||
|
|
||||||
"zigpty": ["zigpty@0.2.1", "", {}, "sha512-MR9JqJx2wf5f4wz8zpx050AlqrmWeIW+1h0SO5iEyhG3HFRjY5luC3szS2ux2EGuPjE5OU9ZAuiCBeMWBTrqZw=="],
|
"zigpty": ["zigpty@0.2.1", "", {}, "sha512-MR9JqJx2wf5f4wz8zpx050AlqrmWeIW+1h0SO5iEyhG3HFRjY5luC3szS2ux2EGuPjE5OU9ZAuiCBeMWBTrqZw=="],
|
||||||
|
|
||||||
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||||
@@ -1684,6 +1896,8 @@
|
|||||||
|
|
||||||
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||||
|
|
||||||
|
"@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
|
||||||
|
|
||||||
"@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
|
"@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
|
||||||
|
|
||||||
"@dotenvx/dotenvx/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
|
"@dotenvx/dotenvx/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
|
||||||
@@ -1692,10 +1906,20 @@
|
|||||||
|
|
||||||
"@dotenvx/dotenvx/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
"@dotenvx/dotenvx/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
||||||
|
|
||||||
|
"@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="],
|
||||||
|
|
||||||
"@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
"@jest/types/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
|
||||||
|
|
||||||
|
"@poppinss/dumper/supports-color": ["supports-color@10.2.2", "", {}, "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g=="],
|
||||||
|
|
||||||
"@reduxjs/toolkit/immer": ["immer@11.1.15", "", {}, "sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ=="],
|
"@reduxjs/toolkit/immer": ["immer@11.1.15", "", {}, "sha512-VrNANlmnWQnh5COXIIOQXM9oOJw7naGKlBT74ZOOR6lpVXc3gFEu9FJLDFcpCJ2j+NWr8TIwtWD//T6ZX6TKiQ=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="],
|
||||||
|
|
||||||
|
"@rolldown/plugin-babel/picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "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" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.3", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.3", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.3", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA=="],
|
||||||
@@ -1712,12 +1936,16 @@
|
|||||||
|
|
||||||
"@tanstack/start-plugin-core/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
|
"@tanstack/start-plugin-core/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "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" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
||||||
|
|
||||||
"@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
|
"@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
|
||||||
|
|
||||||
"@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
"@vue/compiler-core/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
"@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
"@vue/compiler-sfc/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||||
|
|
||||||
|
"@vue/compiler-sfc/postcss": ["postcss@8.5.23", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg=="],
|
||||||
|
|
||||||
"body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
"body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
||||||
|
|
||||||
"conf/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
"conf/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
||||||
@@ -1730,6 +1958,8 @@
|
|||||||
|
|
||||||
"data-urls/whatwg-url": ["whatwg-url@16.0.1", "", { "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", "webidl-conversions": "^8.0.1" } }, "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw=="],
|
"data-urls/whatwg-url": ["whatwg-url@16.0.1", "", { "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", "webidl-conversions": "^8.0.1" } }, "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw=="],
|
||||||
|
|
||||||
|
"docs/oxlint": ["oxlint@1.83.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.83.0", "@oxlint/binding-android-arm64": "1.83.0", "@oxlint/binding-darwin-arm64": "1.83.0", "@oxlint/binding-darwin-x64": "1.83.0", "@oxlint/binding-freebsd-x64": "1.83.0", "@oxlint/binding-linux-arm-gnueabihf": "1.83.0", "@oxlint/binding-linux-arm-musleabihf": "1.83.0", "@oxlint/binding-linux-arm64-gnu": "1.83.0", "@oxlint/binding-linux-arm64-musl": "1.83.0", "@oxlint/binding-linux-ppc64-gnu": "1.83.0", "@oxlint/binding-linux-riscv64-gnu": "1.83.0", "@oxlint/binding-linux-riscv64-musl": "1.83.0", "@oxlint/binding-linux-s390x-gnu": "1.83.0", "@oxlint/binding-linux-x64-gnu": "1.83.0", "@oxlint/binding-linux-x64-musl": "1.83.0", "@oxlint/binding-openharmony-arm64": "1.83.0", "@oxlint/binding-win32-arm64-msvc": "1.83.0", "@oxlint/binding-win32-ia32-msvc": "1.83.0", "@oxlint/binding-win32-x64-msvc": "1.83.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-cyDzSzaw3uzP0TeCeq3lLRPPoaUxkbB4ZOXj+kn+5r+BX9V+4bNVGk9lxer+WrgcpebH4JxLlJ3KQjveVztOLQ=="],
|
||||||
|
|
||||||
"dot-prop/is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="],
|
"dot-prop/is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="],
|
||||||
|
|
||||||
"enquirer/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"enquirer/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
@@ -1740,6 +1970,8 @@
|
|||||||
|
|
||||||
"micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
"micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
|
||||||
|
|
||||||
|
"miniflare/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
||||||
|
|
||||||
"mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
"mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
|
||||||
|
|
||||||
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||||
@@ -1760,18 +1992,34 @@
|
|||||||
|
|
||||||
"restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
|
"restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
|
||||||
|
|
||||||
|
"router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
|
||||||
|
|
||||||
"shadcn/ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="],
|
"shadcn/ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="],
|
||||||
|
|
||||||
|
"shadcn/postcss": ["postcss@8.5.23", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg=="],
|
||||||
|
|
||||||
|
"shadcn/tailwind-merge": ["tailwind-merge@3.6.0", "", {}, "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w=="],
|
||||||
|
|
||||||
"shadcn/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
"shadcn/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
||||||
|
|
||||||
"shadcn/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
"shadcn/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||||
|
|
||||||
|
"sharp/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||||
|
|
||||||
"string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
"string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||||
|
|
||||||
"strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
"strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||||
|
|
||||||
"type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
"type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
||||||
|
|
||||||
|
"vite/picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="],
|
||||||
|
|
||||||
|
"vite/rolldown": ["rolldown@1.2.7", "", { "dependencies": { "@oxc-project/types": "=0.148.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm-eabi": "1.2.7", "@rolldown/binding-android-arm64": "1.2.7", "@rolldown/binding-darwin-arm64": "1.2.7", "@rolldown/binding-darwin-x64": "1.2.7", "@rolldown/binding-freebsd-x64": "1.2.7", "@rolldown/binding-linux-arm-gnueabihf": "1.2.7", "@rolldown/binding-linux-arm64-gnu": "1.2.7", "@rolldown/binding-linux-arm64-musl": "1.2.7", "@rolldown/binding-linux-ppc64-gnu": "1.2.7", "@rolldown/binding-linux-s390x-gnu": "1.2.7", "@rolldown/binding-linux-x64-gnu": "1.2.7", "@rolldown/binding-linux-x64-musl": "1.2.7", "@rolldown/binding-openharmony-arm64": "1.2.7", "@rolldown/binding-win32-arm64-msvc": "1.2.7", "@rolldown/binding-win32-x64-msvc": "1.2.7" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-g0EtLvBjTUB7jhyV0S/TCup3v/XSVl45vUIGbOGU4QPiyjTenCe4mKuFvW9fEgYmS2Fo42AUssRmNuMziXdrig=="],
|
||||||
|
|
||||||
|
"vitest/vite": ["vite@8.1.5", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", "postcss": "^8.5.17", "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.3.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw=="],
|
||||||
|
|
||||||
|
"youch/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
|
||||||
|
|
||||||
"@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
|
"@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
|
||||||
|
|
||||||
"@dotenvx/dotenvx/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
|
"@dotenvx/dotenvx/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
|
||||||
@@ -1792,10 +2040,94 @@
|
|||||||
|
|
||||||
"@jest/types/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
"@jest/types/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
||||||
|
|
||||||
|
"@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
||||||
|
|
||||||
"@tanstack/react-router/@tanstack/react-store/@tanstack/store": ["@tanstack/store@0.9.3", "", {}, "sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw=="],
|
"@tanstack/react-router/@tanstack/react-store/@tanstack/store": ["@tanstack/store@0.9.3", "", {}, "sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
||||||
|
|
||||||
|
"@tanstack/start-plugin-core/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
||||||
|
|
||||||
|
"@vue/compiler-sfc/postcss/nanoid": ["nanoid@3.3.16", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q=="],
|
||||||
|
|
||||||
"cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
"cross-spawn/which/isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.83.0", "", { "os": "android", "cpu": "arm" }, "sha512-0yGY24EwsLk5YDe6F+VkmZyRHSwJDALa3nIrPpq7FXmp2lV2d0TzvBCGeZk+wgiULRGr5blhyr4QMp5KCXJUqA=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.83.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hHfJ0vc17A4iUjH5p9BsTUPYbYRNxGpvD2lbu1aBRk54bzNIx9o5TtYF39QPZcV95DagZd+4DEAw2RH3G2ZsMg=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.83.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hsOjYjszLb/3zym/TkzUMPAoQlTJcuzSyEPOAyA+skXJIX9M0o+4JfOtqopX/Vf4hSLrJ98j0nvFo23gzk8auQ=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.83.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-mjh5oH2EA+wl5yRJYT9K9G61O2zFlpuv+yf2JwZOi0+dq2FnTUtm1h8i+5Ik0fXPWIu/k84I1psZR9aQsLAnyA=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.83.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fNHr64/YaO8YssuoDVC8+F4Uk5enR86q5uxfHkQrjAPs1dbAILOrD2uaud+J7MO8Fx774g44ERLD0IGIvZE48w=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.83.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Qpwy3zzAwMj+8/lyYItHmkSMwbkprFNWTK7jPYDOxSyxEhaSLOWYUTCMkjF334J8/WD0nznCCsoBbIH6hpsuIw=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.83.0", "", { "os": "linux", "cpu": "arm" }, "sha512-s+BirYLFq7JL2k9sP0XI3ZXJ9dYvJ8sX3jLCLoag7tt+zrSHpZxP0jqznfL+Gdgwu7ay0dYgGYJXrQvq3iWloA=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.83.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-7lihXt3vKr+GIyapNbHrnFHm/biiW30le6Zv/DExbAFPF6YwCQXVFlONPFehxs0CpGO4CBfYPM9rdDT+XMoIlg=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.83.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-q63JalLYVkZiZvls1z3PPUnpmQluOMXp0khqQMznCeAPLGydfNY8JhvuA4WlK57JfrvikU8wB5lPVveqpIXvew=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.83.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-krQmDF+dRbxvdqVPV88ZuOoPPu8X5BuqDA8Hd+qcS4YMRQCb+nexA57DazgGsc/rGdKBe3QmV0mnv0bdpW/p5g=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.83.0", "", { "os": "linux", "cpu": "none" }, "sha512-MmOl8Y6txEAXZU1RG8Rr264jQ6D7VPmqFsU/45x/FeWsGe32hklTqGrLE6UxHzp5Rjt0wP+20tY8YXKgSFB3mw=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.83.0", "", { "os": "linux", "cpu": "none" }, "sha512-u1rMymh0W3JZkq370kzQsYPULGWqhE09pZRqnZvUSoYaI9pVO5yVX+iYIslmWuEgwuzH9YAaOsScJiobWCHoOw=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.83.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-y0zK3HNwGysu7rqtE+BQG/d0bx5gh/KwlOtghN8oWeK1KcWzeaLqtZrbm8owqdma1lFyrce/hTO5ismuNu+INQ=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.83.0", "", { "os": "linux", "cpu": "x64" }, "sha512-rS5gM0NgD7ngmuJmbIehsidtrOwKkLFwCQbKEeb9KuyQrrWNq5Zkn0uV6AYdXOMJ0grrWEiLwBuvMxt8w5vsNw=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.83.0", "", { "os": "linux", "cpu": "x64" }, "sha512-W2IH4EtpcPaWcvNGCA95YoDg4vxqE/ZiPCi3arrxEEpsK7+JQN9WYwrlYFx9pcdP6KPXqRqkv3zdQPHcx7b6YQ=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.83.0", "", { "os": "none", "cpu": "arm64" }, "sha512-6LyKkUyoajssTPLlZmDbZIbu4IZ5B4bGuRUnBgCGpEvHP3FQMaYITncHA/unPUo7q+Z+pIu2HhdkQ+8d1SG7iA=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.83.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Uz/fObEtF0jmNJQJ8CGRBKfefYstS0/wjD3s6IGzP8nUwsJykHQJBiN3npHwKiGRGn/vvBEgNr4B3cCzmmatvg=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.83.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-u7XcvPW6Bk58tY5iWs2ESb0vJjoE/kuSpHxopbwp/p3ZtWVQXZ6wor5w3ssVTHOqd/v8b+QdhSFWQ4grEUNWpA=="],
|
||||||
|
|
||||||
|
"docs/oxlint/@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.83.0", "", { "os": "win32", "cpu": "x64" }, "sha512-LZRubd7ph13QmAg4fFecTYVZkiYbROR2Htaxh/ufWRkDhPOm2wrwaEYR89e0YpPFD3dqBrPoxS7myBw5hmYA7Q=="],
|
||||||
|
|
||||||
"jest-validate/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
"jest-validate/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||||
|
|
||||||
"jest-validate/pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
"jest-validate/pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
|
||||||
@@ -1810,8 +2142,68 @@
|
|||||||
|
|
||||||
"shadcn/ora/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
"shadcn/ora/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||||
|
|
||||||
|
"shadcn/postcss/nanoid": ["nanoid@3.3.16", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@oxc-project/types": ["@oxc-project/types@0.148.0", "", {}, "sha512-Nm4s/jB+4FpFsPhWGEC4h7rzksesmtnMXomo6rCMcg/b8zLQuOziRgkCS1fxDCXOlJB/6Q8oABOZ/OP6RIPj9A=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.2.7", "", { "os": "android", "cpu": "arm64" }, "sha512-l17HE9EweWaqJZhuUuNBN/FzM62xw+DECVnJyvMsxn8vJFAGLy5QfLDoYAcronkAN8VxKZHezDpulHDPx95vFw=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.2.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-8ED8ELFvHXc6OCETIn4gXObPiaR6bckM/ipXtbzlPVDRMBfEGjCKgO90F9YtfdpDatVx/ZQw7aZ1vUMf/+T3Mw=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.2.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-/WPripjtiAIZ2tWY7ddijORT0Ujg87wxWW/qcoFVCKAWVDPhtY0xr7Dj0M3GyNGz60jGwTElhro/mkF9dT7dDQ=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.2.7", "", { "os": "freebsd", "cpu": "x64" }, "sha512-14DI4NcqpvbICxSnGLx3PmtDaWqRP/KGSGb6C+JLLVPeZRl6dKdHba3pGsqT3vpdTqhEYIPG0MMQ8c0xYqoJxA=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.2.7", "", { "os": "linux", "cpu": "arm" }, "sha512-bxrWIRvHWQvbJwi+VIie/kDJmQxcNE6xxWwZdqF/ExVAigtHkv54WTLQPb+QsZdnFy18fg7JPfWGL0RH6vwIlQ=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.2.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-toOY2BChBZyuxU7OYX6Tn389di4IzAqPTycVcci0O7FSfBqzRB3RZn+K5Is6ANf4tmgRd/K1yZTsNTXbkXsnLg=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.2.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-lAIXTH/aiLRLxsTgQvfhjo4K1ydWIp00+V0voOr9beb/9ZmkUFrSIb03dXNFRgMNvkE6oGsF10ioQ6UsI+vS5Q=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.2.7", "", { "os": "linux", "cpu": "ppc64" }, "sha512-kdnwS28Pkenp/mZMRwjXXXwxQ7pIsm+bF919LUK93BOyhcLsrVKdP2p9fxpiPNPAbNuch8ypQt0pm2P2LYCAGg=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.2.7", "", { "os": "linux", "cpu": "s390x" }, "sha512-516OdsyLdr5E65paF3yBF55t8mfm9+gmtCsK3xI7XKXIT7EfRlHhxL8K/NR6Hu8BWSgF5+1w74lTL0+nxcc8Qw=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.2.7", "", { "os": "linux", "cpu": "x64" }, "sha512-r8/z8n7GFaYRln3xmP1Cxy0HH/HLM0uBUPkEuSVEfKGDA89M0FsZRZJRSwe/tJjRx+fpH/gjorfhB8tmEbSFLA=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.2.7", "", { "os": "linux", "cpu": "x64" }, "sha512-pAsE8iiDxUg1xBqdhrTfg45AVDVpirjz00sblEYClGNNcMnDb+e8beQgqIAw6LvauX/APvgxUnwrgun/YYGBhw=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.2.7", "", { "os": "none", "cpu": "arm64" }, "sha512-lTcIYmmnQQA8Or/2DatS6oSqcdLHvendjS+zLu+FwgToynWMRSmQdpM65fTANJgIS4mjbMOo5KT2lnT9SAb96w=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.2.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-e3Gu3WxbNk/UqQhxqU7YIYO+9ZBvWNz3U+h/qRFosscMFzdRPbXYSaSWgSnklv2fz1TgzBTcti2z35c/7irsHw=="],
|
||||||
|
|
||||||
|
"vite/rolldown/@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.2.7", "", { "os": "win32", "cpu": "x64" }, "sha512-W/jg5qoRSqjsEv0+dZi4e687mcHqmVuU0P4fK6qS/xjetW2Gmc1W8j//z5nAeNcC8Ttm0hV46IjcYeuVwYhuiw=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "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" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
||||||
|
|
||||||
|
"vitest/vite/postcss": ["postcss@8.5.23", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg=="],
|
||||||
|
|
||||||
"shadcn/ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="],
|
"shadcn/ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="],
|
||||||
|
|
||||||
"shadcn/ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
"shadcn/ora/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
|
||||||
|
|
||||||
|
"vitest/vite/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
|
||||||
|
|
||||||
|
"vitest/vite/postcss/nanoid": ["nanoid@3.3.16", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q=="],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||||
|
"plugins": ["react", "typescript", "oxc"],
|
||||||
|
"rules": {
|
||||||
|
"react/rules-of-hooks": "error",
|
||||||
|
"react/only-export-components": ["warn", { "allowConstantExport": true }]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# React + TypeScript + Vite
|
||||||
|
|
||||||
|
This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules.
|
||||||
|
|
||||||
|
Currently, two official plugins are available:
|
||||||
|
|
||||||
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
|
||||||
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
|
||||||
|
|
||||||
|
## React Compiler
|
||||||
|
|
||||||
|
The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.
|
||||||
|
|
||||||
|
Note: This will impact Vite dev & build performances.
|
||||||
|
You can also try [the experimental native React Compiler support in plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md#rust-react-compiler) by using `compiler: true` in the plugin options instead of using the Babel plugin.
|
||||||
|
|
||||||
|
## Expanding the Oxlint configuration
|
||||||
|
|
||||||
|
If you are developing a production application, we recommend enabling type-aware lint rules by installing `oxlint-tsgolint` and editing `.oxlintrc.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||||
|
"plugins": ["react", "typescript", "oxc"],
|
||||||
|
"options": {
|
||||||
|
"typeAware": true
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"react/rules-of-hooks": "error",
|
||||||
|
"react/only-export-components": ["warn", { "allowConstantExport": true }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Oxlint rules documentation](https://oxc.rs/docs/guide/usage/linter/rules) for the full list of rules and categories.
|
||||||
+255
@@ -0,0 +1,255 @@
|
|||||||
|
{
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"configVersion": 1,
|
||||||
|
"workspaces": {
|
||||||
|
"": {
|
||||||
|
"name": "docs",
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^19.2.8",
|
||||||
|
"react-dom": "^19.2.8",
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.29.7",
|
||||||
|
"@rolldown/plugin-babel": "^0.2.3",
|
||||||
|
"@types/babel__core": "^7.20.5",
|
||||||
|
"@types/node": "^24.13.3",
|
||||||
|
"@types/react": "^19.2.18",
|
||||||
|
"@types/react-dom": "^19.2.7",
|
||||||
|
"@vitejs/plugin-react": "^6.1.1",
|
||||||
|
"babel-plugin-react-compiler": "^1.0.0",
|
||||||
|
"oxlint": "^1.81.0",
|
||||||
|
"typescript": "~6.0.2",
|
||||||
|
"vite": "^8.3.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="],
|
||||||
|
|
||||||
|
"@babel/compat-data": ["@babel/compat-data@7.29.7", "", {}, "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg=="],
|
||||||
|
|
||||||
|
"@babel/core": ["@babel/core@7.29.7", "", { "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" } }, "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA=="],
|
||||||
|
|
||||||
|
"@babel/generator": ["@babel/generator@7.29.8", "", { "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" } }, "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg=="],
|
||||||
|
|
||||||
|
"@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "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" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="],
|
||||||
|
|
||||||
|
"@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="],
|
||||||
|
|
||||||
|
"@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="],
|
||||||
|
|
||||||
|
"@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="],
|
||||||
|
|
||||||
|
"@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="],
|
||||||
|
|
||||||
|
"@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="],
|
||||||
|
|
||||||
|
"@babel/helper-validator-option": ["@babel/helper-validator-option@7.29.7", "", {}, "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw=="],
|
||||||
|
|
||||||
|
"@babel/helpers": ["@babel/helpers@7.29.7", "", { "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg=="],
|
||||||
|
|
||||||
|
"@babel/parser": ["@babel/parser@7.29.8", "", { "dependencies": { "@babel/types": "^7.29.8" }, "bin": "./bin/babel-parser.js" }, "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA=="],
|
||||||
|
|
||||||
|
"@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="],
|
||||||
|
|
||||||
|
"@babel/traverse": ["@babel/traverse@7.29.8", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.8", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.8", "@babel/template": "^7.29.7", "@babel/types": "^7.29.8", "debug": "^4.3.1" } }, "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg=="],
|
||||||
|
|
||||||
|
"@babel/types": ["@babel/types@7.29.8", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg=="],
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
|
||||||
|
|
||||||
|
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.6.0", "", {}, "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw=="],
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||||
|
|
||||||
|
"@oxc-project/types": ["@oxc-project/types@0.149.0", "", {}, "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.83.0", "", { "os": "android", "cpu": "arm" }, "sha512-0yGY24EwsLk5YDe6F+VkmZyRHSwJDALa3nIrPpq7FXmp2lV2d0TzvBCGeZk+wgiULRGr5blhyr4QMp5KCXJUqA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.83.0", "", { "os": "android", "cpu": "arm64" }, "sha512-hHfJ0vc17A4iUjH5p9BsTUPYbYRNxGpvD2lbu1aBRk54bzNIx9o5TtYF39QPZcV95DagZd+4DEAw2RH3G2ZsMg=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.83.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hsOjYjszLb/3zym/TkzUMPAoQlTJcuzSyEPOAyA+skXJIX9M0o+4JfOtqopX/Vf4hSLrJ98j0nvFo23gzk8auQ=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.83.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-mjh5oH2EA+wl5yRJYT9K9G61O2zFlpuv+yf2JwZOi0+dq2FnTUtm1h8i+5Ik0fXPWIu/k84I1psZR9aQsLAnyA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.83.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fNHr64/YaO8YssuoDVC8+F4Uk5enR86q5uxfHkQrjAPs1dbAILOrD2uaud+J7MO8Fx774g44ERLD0IGIvZE48w=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.83.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Qpwy3zzAwMj+8/lyYItHmkSMwbkprFNWTK7jPYDOxSyxEhaSLOWYUTCMkjF334J8/WD0nznCCsoBbIH6hpsuIw=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.83.0", "", { "os": "linux", "cpu": "arm" }, "sha512-s+BirYLFq7JL2k9sP0XI3ZXJ9dYvJ8sX3jLCLoag7tt+zrSHpZxP0jqznfL+Gdgwu7ay0dYgGYJXrQvq3iWloA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.83.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-7lihXt3vKr+GIyapNbHrnFHm/biiW30le6Zv/DExbAFPF6YwCQXVFlONPFehxs0CpGO4CBfYPM9rdDT+XMoIlg=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.83.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-q63JalLYVkZiZvls1z3PPUnpmQluOMXp0khqQMznCeAPLGydfNY8JhvuA4WlK57JfrvikU8wB5lPVveqpIXvew=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.83.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-krQmDF+dRbxvdqVPV88ZuOoPPu8X5BuqDA8Hd+qcS4YMRQCb+nexA57DazgGsc/rGdKBe3QmV0mnv0bdpW/p5g=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.83.0", "", { "os": "linux", "cpu": "none" }, "sha512-MmOl8Y6txEAXZU1RG8Rr264jQ6D7VPmqFsU/45x/FeWsGe32hklTqGrLE6UxHzp5Rjt0wP+20tY8YXKgSFB3mw=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.83.0", "", { "os": "linux", "cpu": "none" }, "sha512-u1rMymh0W3JZkq370kzQsYPULGWqhE09pZRqnZvUSoYaI9pVO5yVX+iYIslmWuEgwuzH9YAaOsScJiobWCHoOw=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.83.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-y0zK3HNwGysu7rqtE+BQG/d0bx5gh/KwlOtghN8oWeK1KcWzeaLqtZrbm8owqdma1lFyrce/hTO5ismuNu+INQ=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.83.0", "", { "os": "linux", "cpu": "x64" }, "sha512-rS5gM0NgD7ngmuJmbIehsidtrOwKkLFwCQbKEeb9KuyQrrWNq5Zkn0uV6AYdXOMJ0grrWEiLwBuvMxt8w5vsNw=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.83.0", "", { "os": "linux", "cpu": "x64" }, "sha512-W2IH4EtpcPaWcvNGCA95YoDg4vxqE/ZiPCi3arrxEEpsK7+JQN9WYwrlYFx9pcdP6KPXqRqkv3zdQPHcx7b6YQ=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.83.0", "", { "os": "none", "cpu": "arm64" }, "sha512-6LyKkUyoajssTPLlZmDbZIbu4IZ5B4bGuRUnBgCGpEvHP3FQMaYITncHA/unPUo7q+Z+pIu2HhdkQ+8d1SG7iA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.83.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-Uz/fObEtF0jmNJQJ8CGRBKfefYstS0/wjD3s6IGzP8nUwsJykHQJBiN3npHwKiGRGn/vvBEgNr4B3cCzmmatvg=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.83.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-u7XcvPW6Bk58tY5iWs2ESb0vJjoE/kuSpHxopbwp/p3ZtWVQXZ6wor5w3ssVTHOqd/v8b+QdhSFWQ4grEUNWpA=="],
|
||||||
|
|
||||||
|
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.83.0", "", { "os": "win32", "cpu": "x64" }, "sha512-LZRubd7ph13QmAg4fFecTYVZkiYbROR2Htaxh/ufWRkDhPOm2wrwaEYR89e0YpPFD3dqBrPoxS7myBw5hmYA7Q=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-android-arm-eabi": ["@rolldown/binding-android-arm-eabi@1.2.8", "", { "os": "android", "cpu": "arm" }, "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.2.8", "", { "os": "android", "cpu": "arm64" }, "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.2.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.2.8", "", { "os": "darwin", "cpu": "x64" }, "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.2.8", "", { "os": "freebsd", "cpu": "x64" }, "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.2.8", "", { "os": "linux", "cpu": "arm" }, "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.2.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.2.8", "", { "os": "linux", "cpu": "arm64" }, "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.2.8", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.2.8", "", { "os": "linux", "cpu": "s390x" }, "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.2.8", "", { "os": "linux", "cpu": "x64" }, "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.2.8", "", { "os": "linux", "cpu": "x64" }, "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.2.8", "", { "os": "none", "cpu": "arm64" }, "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.2.8", "", { "os": "win32", "cpu": "arm64" }, "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.2.8", "", { "os": "win32", "cpu": "x64" }, "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng=="],
|
||||||
|
|
||||||
|
"@rolldown/plugin-babel": ["@rolldown/plugin-babel@0.2.4", "", { "dependencies": { "picomatch": "^4.0.7" }, "peerDependencies": { "@babel/core": "^7.29.0 || ^8.0.0-rc.1", "@babel/plugin-transform-runtime": "^7.29.0 || ^8.0.0-rc.1", "@babel/runtime": "^7.27.0 || ^8.0.0-rc.1", "rolldown": "^1.0.0-rc.5", "vite": "^8.0.0" }, "optionalPeers": ["@babel/plugin-transform-runtime", "@babel/runtime", "vite"] }, "sha512-ygmm2j/mN+aCvstHo0x3IOu4uc6LqXT9SJ3q4kpfG/+Yhfz0B+E47FITcC0FljZADwUFARP6E2kiE+Lc26D8wg=="],
|
||||||
|
|
||||||
|
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.1", "", {}, "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw=="],
|
||||||
|
|
||||||
|
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
||||||
|
|
||||||
|
"@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
|
||||||
|
|
||||||
|
"@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
|
||||||
|
|
||||||
|
"@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
|
||||||
|
|
||||||
|
"@types/node": ["@types/node@24.13.5", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-TXyindR+lBr22aJIdMQzCFHPHR6cR4js838mRDCSz5hOKWZvZwsXSSiXDmjRj4iJmgl+sR9O+1mkoVBSMadNug=="],
|
||||||
|
|
||||||
|
"@types/react": ["@types/react@19.3.0", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg=="],
|
||||||
|
|
||||||
|
"@types/react-dom": ["@types/react-dom@19.3.0", "", { "peerDependencies": { "@types/react": "^19.3.0" } }, "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q=="],
|
||||||
|
|
||||||
|
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.1.1", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "oxc-transform-react": "^0.145.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler", "oxc-transform-react"] }, "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw=="],
|
||||||
|
|
||||||
|
"babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="],
|
||||||
|
|
||||||
|
"baseline-browser-mapping": ["baseline-browser-mapping@2.11.24", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-hYrgxie335U08WqICoGqKRzV1HFXv6zdxwJE4ekCb80CM9a0SVVsN4QPwT67RraRo+9h8IATk6uxHJw7QSkdOg=="],
|
||||||
|
|
||||||
|
"browserslist": ["browserslist@4.29.0", "", { "dependencies": { "baseline-browser-mapping": "^2.11.23", "caniuse-lite": "^1.0.30001810", "electron-to-chromium": "^1.5.427", "node-releases": "^2.0.55", "update-browserslist-db": "^1.3.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-3GSvyjvDI4Dur1Meg2BekJquu5uF+9R9a1+5M1Mde192eZoXbeXjzgOsgqPS2V8D5wrrip0gR5Hf/GhWQ9ZzaA=="],
|
||||||
|
|
||||||
|
"caniuse-lite": ["caniuse-lite@1.0.30001810", "", {}, "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg=="],
|
||||||
|
|
||||||
|
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
|
||||||
|
|
||||||
|
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||||
|
|
||||||
|
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||||
|
|
||||||
|
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
|
"electron-to-chromium": ["electron-to-chromium@1.5.430", "", {}, "sha512-e1QEj72Y4zd8RlNZVmoTg+iCOSVwpk05IOiiQwdrkwCSVlZfPthevErhE+nckGd2YbsXfp1SkisznhGVIXP2NQ=="],
|
||||||
|
|
||||||
|
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
|
||||||
|
|
||||||
|
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||||
|
|
||||||
|
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||||
|
|
||||||
|
"gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
|
||||||
|
|
||||||
|
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||||
|
|
||||||
|
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
||||||
|
|
||||||
|
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
|
||||||
|
|
||||||
|
"lightningcss": ["lightningcss@1.33.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.33.0", "lightningcss-darwin-arm64": "1.33.0", "lightningcss-darwin-x64": "1.33.0", "lightningcss-freebsd-x64": "1.33.0", "lightningcss-linux-arm-gnueabihf": "1.33.0", "lightningcss-linux-arm64-gnu": "1.33.0", "lightningcss-linux-arm64-musl": "1.33.0", "lightningcss-linux-x64-gnu": "1.33.0", "lightningcss-linux-x64-musl": "1.33.0", "lightningcss-win32-arm64-msvc": "1.33.0", "lightningcss-win32-x64-msvc": "1.33.0" } }, "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA=="],
|
||||||
|
|
||||||
|
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.33.0", "", { "os": "android", "cpu": "arm64" }, "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg=="],
|
||||||
|
|
||||||
|
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.33.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg=="],
|
||||||
|
|
||||||
|
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.33.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ=="],
|
||||||
|
|
||||||
|
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.33.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.33.0", "", { "os": "linux", "cpu": "arm" }, "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.33.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg=="],
|
||||||
|
|
||||||
|
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.33.0", "", { "os": "linux", "cpu": "x64" }, "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw=="],
|
||||||
|
|
||||||
|
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.33.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA=="],
|
||||||
|
|
||||||
|
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="],
|
||||||
|
|
||||||
|
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||||
|
|
||||||
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||||
|
|
||||||
|
"nanoid": ["nanoid@3.3.19", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug=="],
|
||||||
|
|
||||||
|
"node-releases": ["node-releases@2.0.55", "", {}, "sha512-mIrE/Cw9y+9Au6dS5vDKDhQza9YvG6w+ZrS6X+ZzA7yFW/soAeaups4Qzn1bL6g5FVy8WtP79+0j82oPIbqRjQ=="],
|
||||||
|
|
||||||
|
"oxlint": ["oxlint@1.83.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.83.0", "@oxlint/binding-android-arm64": "1.83.0", "@oxlint/binding-darwin-arm64": "1.83.0", "@oxlint/binding-darwin-x64": "1.83.0", "@oxlint/binding-freebsd-x64": "1.83.0", "@oxlint/binding-linux-arm-gnueabihf": "1.83.0", "@oxlint/binding-linux-arm-musleabihf": "1.83.0", "@oxlint/binding-linux-arm64-gnu": "1.83.0", "@oxlint/binding-linux-arm64-musl": "1.83.0", "@oxlint/binding-linux-ppc64-gnu": "1.83.0", "@oxlint/binding-linux-riscv64-gnu": "1.83.0", "@oxlint/binding-linux-riscv64-musl": "1.83.0", "@oxlint/binding-linux-s390x-gnu": "1.83.0", "@oxlint/binding-linux-x64-gnu": "1.83.0", "@oxlint/binding-linux-x64-musl": "1.83.0", "@oxlint/binding-openharmony-arm64": "1.83.0", "@oxlint/binding-win32-arm64-msvc": "1.83.0", "@oxlint/binding-win32-ia32-msvc": "1.83.0", "@oxlint/binding-win32-x64-msvc": "1.83.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-cyDzSzaw3uzP0TeCeq3lLRPPoaUxkbB4ZOXj+kn+5r+BX9V+4bNVGk9lxer+WrgcpebH4JxLlJ3KQjveVztOLQ=="],
|
||||||
|
|
||||||
|
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||||
|
|
||||||
|
"picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="],
|
||||||
|
|
||||||
|
"postcss": ["postcss@8.5.28", "", { "dependencies": { "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A=="],
|
||||||
|
|
||||||
|
"react": ["react@19.3.0", "", {}, "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog=="],
|
||||||
|
|
||||||
|
"react-dom": ["react-dom@19.3.0", "", { "dependencies": { "scheduler": "^0.28.0" }, "peerDependencies": { "react": "^19.3.0" } }, "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q=="],
|
||||||
|
|
||||||
|
"rolldown": ["rolldown@1.2.8", "", { "dependencies": { "@oxc-project/types": "=0.149.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm-eabi": "1.2.8", "@rolldown/binding-android-arm64": "1.2.8", "@rolldown/binding-darwin-arm64": "1.2.8", "@rolldown/binding-darwin-x64": "1.2.8", "@rolldown/binding-freebsd-x64": "1.2.8", "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", "@rolldown/binding-linux-arm64-gnu": "1.2.8", "@rolldown/binding-linux-arm64-musl": "1.2.8", "@rolldown/binding-linux-ppc64-gnu": "1.2.8", "@rolldown/binding-linux-s390x-gnu": "1.2.8", "@rolldown/binding-linux-x64-gnu": "1.2.8", "@rolldown/binding-linux-x64-musl": "1.2.8", "@rolldown/binding-openharmony-arm64": "1.2.8", "@rolldown/binding-win32-arm64-msvc": "1.2.8", "@rolldown/binding-win32-x64-msvc": "1.2.8" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ=="],
|
||||||
|
|
||||||
|
"scheduler": ["scheduler@0.28.0", "", {}, "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw=="],
|
||||||
|
|
||||||
|
"semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||||
|
|
||||||
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
||||||
|
"tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
|
||||||
|
|
||||||
|
"typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
|
||||||
|
|
||||||
|
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
||||||
|
|
||||||
|
"update-browserslist-db": ["update-browserslist-db@1.3.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ=="],
|
||||||
|
|
||||||
|
"vite": ["vite@8.3.0", "", { "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.7", "postcss": "^8.5.28", "rolldown": "~1.2.6", "tinyglobby": "^0.2.17" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.7.1", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ=="],
|
||||||
|
|
||||||
|
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-Hans">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>docs</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "docs",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"lint": "oxlint",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"typecheck": "tsc -b"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@icones/react": "^0.0.1",
|
||||||
|
"@workspace/i18n": "workspace:*",
|
||||||
|
"@workspace/preferences": "workspace:*",
|
||||||
|
"@workspace/ui": "workspace:*",
|
||||||
|
"@workspace/search": "workspace:*",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"react": "^19.2.8",
|
||||||
|
"react-dom": "^19.2.8",
|
||||||
|
"tailwind-merge": "^3.7.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.29.7",
|
||||||
|
"@icones/vite": "^0.0.1",
|
||||||
|
"@rolldown/plugin-babel": "^0.2.3",
|
||||||
|
"@tailwindcss/vite": "^4.3.3",
|
||||||
|
"@types/babel__core": "^7.20.5",
|
||||||
|
"@types/node": "^24.13.3",
|
||||||
|
"@types/react": "^19.2.18",
|
||||||
|
"@types/react-dom": "^19.2.7",
|
||||||
|
"@vitejs/plugin-react": "^6.1.1",
|
||||||
|
"babel-plugin-react-compiler": "^1.0.0",
|
||||||
|
"oxlint": "^1.81.0",
|
||||||
|
"satteri": "^0.10.5",
|
||||||
|
"tailwindcss": "^4.3.3",
|
||||||
|
"typescript": "~6.0.2",
|
||||||
|
"vite": "^8.3.0",
|
||||||
|
"vite-plugin-satteri": "^0.3.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.3 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<symbol id="bluesky-icon" viewBox="0 0 16 17">
|
||||||
|
<g clip-path="url(#bluesky-clip)"><path fill="#08060d" d="M7.75 7.735c-.693-1.348-2.58-3.86-4.334-5.097-1.68-1.187-2.32-.981-2.74-.79C.188 2.065.1 2.812.1 3.251s.241 3.602.398 4.13c.52 1.744 2.367 2.333 4.07 2.145-2.495.37-4.71 1.278-1.805 4.512 3.196 3.309 4.38-.71 4.987-2.746.608 2.036 1.307 5.91 4.93 2.746 2.72-2.746.747-4.143-1.747-4.512 1.702.189 3.55-.4 4.07-2.145.156-.528.397-3.691.397-4.13s-.088-1.186-.575-1.406c-.42-.19-1.06-.395-2.741.79-1.755 1.24-3.64 3.752-4.334 5.099"/></g>
|
||||||
|
<defs><clipPath id="bluesky-clip"><path fill="#fff" d="M.1.85h15.3v15.3H.1z"/></clipPath></defs>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="discord-icon" viewBox="0 0 20 19">
|
||||||
|
<path fill="#08060d" d="M16.224 3.768a14.5 14.5 0 0 0-3.67-1.153c-.158.286-.343.67-.47.976a13.5 13.5 0 0 0-4.067 0c-.128-.306-.317-.69-.476-.976A14.4 14.4 0 0 0 3.868 3.77C1.546 7.28.916 10.703 1.231 14.077a14.7 14.7 0 0 0 4.5 2.306q.545-.748.965-1.587a9.5 9.5 0 0 1-1.518-.74q.191-.14.372-.293c2.927 1.369 6.107 1.369 8.999 0q.183.152.372.294-.723.437-1.52.74.418.838.963 1.588a14.6 14.6 0 0 0 4.504-2.308c.37-3.911-.63-7.302-2.644-10.309m-9.13 8.234c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.894 0 1.614.82 1.599 1.82.001 1-.705 1.82-1.6 1.82m5.91 0c-.878 0-1.599-.82-1.599-1.82 0-.998.705-1.82 1.6-1.82.893 0 1.614.82 1.599 1.82 0 1-.706 1.82-1.6 1.82"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="documentation-icon" viewBox="0 0 21 20">
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="m15.5 13.333 1.533 1.322c.645.555.967.833.967 1.178s-.322.623-.967 1.179L15.5 18.333m-3.333-5-1.534 1.322c-.644.555-.966.833-.966 1.178s.322.623.966 1.179l1.534 1.321"/>
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M17.167 10.836v-4.32c0-1.41 0-2.117-.224-2.68-.359-.906-1.118-1.621-2.08-1.96-.599-.21-1.349-.21-2.848-.21-2.623 0-3.935 0-4.983.369-1.684.591-3.013 1.842-3.641 3.428C3 6.449 3 7.684 3 10.154v2.122c0 2.558 0 3.838.706 4.726q.306.383.713.671c.76.536 1.79.64 3.581.66"/>
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M3 10a2.78 2.78 0 0 1 2.778-2.778c.555 0 1.209.097 1.748-.047.48-.129.854-.503.982-.982.145-.54.048-1.194.048-1.749a2.78 2.78 0 0 1 2.777-2.777"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="github-icon" viewBox="0 0 19 19">
|
||||||
|
<path fill="#08060d" fill-rule="evenodd" d="M9.356 1.85C5.05 1.85 1.57 5.356 1.57 9.694a7.84 7.84 0 0 0 5.324 7.44c.387.079.528-.168.528-.376 0-.182-.013-.805-.013-1.454-2.165.467-2.616-.935-2.616-.935-.349-.91-.864-1.143-.864-1.143-.71-.48.051-.48.051-.48.787.051 1.2.805 1.2.805.695 1.194 1.817.857 2.268.649.064-.507.27-.857.49-1.052-1.728-.182-3.545-.857-3.545-3.87 0-.857.31-1.558.8-2.104-.078-.195-.349-1 .077-2.078 0 0 .657-.208 2.14.805a7.5 7.5 0 0 1 1.946-.26c.657 0 1.328.092 1.946.26 1.483-1.013 2.14-.805 2.14-.805.426 1.078.155 1.883.078 2.078.502.546.799 1.247.799 2.104 0 3.013-1.818 3.675-3.558 3.87.284.247.528.714.528 1.454 0 1.052-.012 1.896-.012 2.156 0 .208.142.455.528.377a7.84 7.84 0 0 0 5.324-7.441c.013-4.338-3.48-7.844-7.773-7.844" clip-rule="evenodd"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="social-icon" viewBox="0 0 20 20">
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M12.5 6.667a4.167 4.167 0 1 0-8.334 0 4.167 4.167 0 0 0 8.334 0"/>
|
||||||
|
<path fill="none" stroke="#aa3bff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.35" d="M2.5 16.667a5.833 5.833 0 0 1 8.75-5.053m3.837.474.513 1.035c.07.144.257.282.414.309l.93.155c.596.1.736.536.307.965l-.723.73a.64.64 0 0 0-.152.531l.207.903c.164.715-.213.991-.84.618l-.872-.52a.63.63 0 0 0-.577 0l-.872.52c-.624.373-1.003.094-.84-.618l.207-.903a.64.64 0 0 0-.152-.532l-.723-.729c-.426-.43-.289-.864.306-.964l.93-.156a.64.64 0 0 0 .412-.31l.513-1.034c.28-.562.735-.562 1.012 0"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="x-icon" viewBox="0 0 19 19">
|
||||||
|
<path fill="#08060d" fill-rule="evenodd" d="M1.893 1.98c.052.072 1.245 1.769 2.653 3.77l2.892 4.114c.183.261.333.48.333.486s-.068.089-.152.183l-.522.593-.765.867-3.597 4.087c-.375.426-.734.834-.798.905a1 1 0 0 0-.118.148c0 .01.236.017.664.017h.663l.729-.83c.4-.457.796-.906.879-.999a692 692 0 0 0 1.794-2.038c.034-.037.301-.34.594-.675l.551-.624.345-.392a7 7 0 0 1 .34-.374c.006 0 .93 1.306 2.052 2.903l2.084 2.965.045.063h2.275c1.87 0 2.273-.003 2.266-.021-.008-.02-1.098-1.572-3.894-5.547-2.013-2.862-2.28-3.246-2.273-3.266.008-.019.282-.332 2.085-2.38l2-2.274 1.567-1.782c.022-.028-.016-.03-.65-.03h-.674l-.3.342a871 871 0 0 1-1.782 2.025c-.067.075-.405.458-.75.852a100 100 0 0 1-.803.91c-.148.172-.299.344-.99 1.127-.304.343-.32.358-.345.327-.015-.019-.904-1.282-1.976-2.808L6.365 1.85H1.8zm1.782.91 8.078 11.294c.772 1.08 1.413 1.973 1.425 1.984.016.017.241.02 1.05.017l1.03-.004-2.694-3.766L7.796 5.75 5.722 2.852l-1.039-.004-1.039-.004z" clip-rule="evenodd"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,145 @@
|
|||||||
|
import {
|
||||||
|
Suspense,
|
||||||
|
lazy,
|
||||||
|
startTransition,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
type ComponentType,
|
||||||
|
} from "react"
|
||||||
|
import { rootCSSVariables } from "./components/layout"
|
||||||
|
import { LocaleProvider } from "./components/locale-provider"
|
||||||
|
import { DocsPreferencesProvider } from "./components/preferences-provider"
|
||||||
|
import { DocsSearchProvider } from "./components/docs-search-provider"
|
||||||
|
import { resolveDocLocale } from "./content/registry"
|
||||||
|
import { useTranslate } from "./lib/locale"
|
||||||
|
|
||||||
|
const Index = lazy(() => import("./pages/index"))
|
||||||
|
const Article = lazy(() => import("./pages/article"))
|
||||||
|
const Settings = lazy(() => import("./pages/settings"))
|
||||||
|
|
||||||
|
type RouteDefinition = {
|
||||||
|
Component: ComponentType
|
||||||
|
matches: (pathname: string) => boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const routes: RouteDefinition[] = [
|
||||||
|
{
|
||||||
|
Component: Index,
|
||||||
|
matches: (pathname) =>
|
||||||
|
pathname === "/" || /^\/(?:en-US|zh-Hans)\/?$/.test(pathname),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: Article,
|
||||||
|
matches: (pathname) =>
|
||||||
|
/^(?:\/(?:en-US|zh-Hans))?\/articles?(?:\/|$)/.test(pathname),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: Settings,
|
||||||
|
matches: (pathname) =>
|
||||||
|
/^(?:\/(?:en-US|zh-Hans))?\/settings\/?$/.test(pathname),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
const [currentUrl, setCurrentUrl] = useState(() => window.location.href)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function updateRoute() {
|
||||||
|
startTransition(() => setCurrentUrl(window.location.href))
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigate(event: MouseEvent) {
|
||||||
|
if (
|
||||||
|
event.defaultPrevented ||
|
||||||
|
event.button !== 0 ||
|
||||||
|
event.metaKey ||
|
||||||
|
event.ctrlKey ||
|
||||||
|
event.shiftKey ||
|
||||||
|
event.altKey
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = event.target
|
||||||
|
if (!(target instanceof Element)) return
|
||||||
|
|
||||||
|
const anchor = target.closest<HTMLAnchorElement>("a[href]")
|
||||||
|
if (
|
||||||
|
!anchor ||
|
||||||
|
anchor.hasAttribute("download") ||
|
||||||
|
(anchor.target && anchor.target !== "_self")
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const destination = new URL(anchor.href, window.location.href)
|
||||||
|
if (destination.origin !== window.location.origin) return
|
||||||
|
|
||||||
|
const current = new URL(window.location.href)
|
||||||
|
if (
|
||||||
|
destination.pathname === current.pathname &&
|
||||||
|
destination.search === current.search &&
|
||||||
|
destination.hash
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
window.history.pushState(null, "", destination)
|
||||||
|
window.scrollTo({ left: 0, top: 0 })
|
||||||
|
updateRoute()
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("popstate", updateRoute)
|
||||||
|
document.addEventListener("click", navigate)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("popstate", updateRoute)
|
||||||
|
document.removeEventListener("click", navigate)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const { pathname } = new URL(currentUrl)
|
||||||
|
const Route = routes.find((route) => route.matches(pathname))?.Component
|
||||||
|
const locale = resolveDocLocale(pathname)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DocsPreferencesProvider routeLocale={locale}>
|
||||||
|
<LocaleProvider locale={locale}>
|
||||||
|
<DocsSearchProvider>
|
||||||
|
<div style={rootCSSVariables}>
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<p className="p-6 text-slate-500 dark:text-slate-400">
|
||||||
|
Loading…
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{Route ? <Route key={pathname} /> : <NotFound />}
|
||||||
|
</Suspense>
|
||||||
|
</div>
|
||||||
|
</DocsSearchProvider>
|
||||||
|
</LocaleProvider>
|
||||||
|
</DocsPreferencesProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function NotFound() {
|
||||||
|
const t = useTranslate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="mx-auto flex min-h-dvh max-w-xl flex-col justify-center px-6">
|
||||||
|
<h1 className="text-4xl">
|
||||||
|
{t({ zh: "页面不存在", us: "Page not found" })}
|
||||||
|
</h1>
|
||||||
|
<a
|
||||||
|
className="mt-4 w-fit text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
||||||
|
href="/"
|
||||||
|
>
|
||||||
|
{t({ zh: "返回首页", us: "Back to home" })}
|
||||||
|
</a>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 4.0 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.5 KiB |
@@ -0,0 +1,179 @@
|
|||||||
|
import { I18nProvider } from "@workspace/i18n"
|
||||||
|
import {
|
||||||
|
SearchDialog,
|
||||||
|
SearchProvider,
|
||||||
|
type SearchAdapter,
|
||||||
|
type SearchResultItem,
|
||||||
|
} from "@workspace/search"
|
||||||
|
import { messages as searchMessagesEnUS } from "@workspace/search/locales/en-US"
|
||||||
|
import { messages as searchMessagesZhHans } from "@workspace/search/locales/zh-Hans"
|
||||||
|
import React from "react"
|
||||||
|
|
||||||
|
import {
|
||||||
|
getDocHref,
|
||||||
|
getDocPackages,
|
||||||
|
getDocSearchText,
|
||||||
|
getDocSectionLabel,
|
||||||
|
} from "../content/registry"
|
||||||
|
import type {
|
||||||
|
DocLocale,
|
||||||
|
DocPackage,
|
||||||
|
DocPage,
|
||||||
|
DocTocItem,
|
||||||
|
} from "../content/types"
|
||||||
|
import { useLocale } from "../lib/locale"
|
||||||
|
|
||||||
|
const searchCatalogs = {
|
||||||
|
"en-US": searchMessagesEnUS,
|
||||||
|
"zh-Hans": searchMessagesZhHans,
|
||||||
|
} as const
|
||||||
|
|
||||||
|
type DocsSearchPayload = {
|
||||||
|
href: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DocsSearchProvider({
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
const locale = useLocale()
|
||||||
|
const adapter = React.useMemo(() => createDocsSearchAdapter(locale), [locale])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<I18nProvider catalogs={searchCatalogs} locale={locale}>
|
||||||
|
<SearchProvider
|
||||||
|
adapter={adapter}
|
||||||
|
historyStorageKey={`docs-search-history:${locale}`}
|
||||||
|
onSelect={({ item }) => {
|
||||||
|
if (isDocsSearchPayload(item.payload)) navigate(item.payload.href)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<SearchDialog className="font-sans" />
|
||||||
|
</SearchProvider>
|
||||||
|
</I18nProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDocsSearchAdapter(locale: DocLocale): SearchAdapter {
|
||||||
|
const docPackages = getDocPackages(locale)
|
||||||
|
|
||||||
|
return {
|
||||||
|
async search({ query, signal }) {
|
||||||
|
const normalizedQuery = normalize(query)
|
||||||
|
if (!normalizedQuery) return { groups: [] }
|
||||||
|
|
||||||
|
const terms = normalizedQuery.split(/\s+/).filter(Boolean)
|
||||||
|
const groups = docPackages.flatMap((docPackage) => {
|
||||||
|
const items = docPackage.pages
|
||||||
|
.map((page) => ({
|
||||||
|
item: createResultItem(docPackage, page, locale),
|
||||||
|
score: getMatchScore(
|
||||||
|
normalizedQuery,
|
||||||
|
terms,
|
||||||
|
docPackage.label,
|
||||||
|
page
|
||||||
|
),
|
||||||
|
}))
|
||||||
|
.filter((result) => result.score >= 0)
|
||||||
|
.sort(
|
||||||
|
(left, right) =>
|
||||||
|
right.score - left.score ||
|
||||||
|
left.item.title.localeCompare(right.item.title, locale)
|
||||||
|
)
|
||||||
|
.map((result) => result.item)
|
||||||
|
|
||||||
|
return items.length > 0
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
id: docPackage.key,
|
||||||
|
label: docPackage.label,
|
||||||
|
items,
|
||||||
|
total: items.length,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []
|
||||||
|
})
|
||||||
|
|
||||||
|
if (signal.aborted) return { groups: [] }
|
||||||
|
return { groups }
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createResultItem(
|
||||||
|
docPackage: DocPackage,
|
||||||
|
page: DocPage,
|
||||||
|
locale: DocLocale
|
||||||
|
): SearchResultItem {
|
||||||
|
return {
|
||||||
|
id: `${page.section}/${page.slug}`,
|
||||||
|
title: page.title,
|
||||||
|
description: page.description,
|
||||||
|
keywords: [
|
||||||
|
docPackage.label,
|
||||||
|
getDocSectionLabel(page.section, locale),
|
||||||
|
...page.toc.flatMap(flattenTocTitles),
|
||||||
|
getDocSearchText(page),
|
||||||
|
],
|
||||||
|
meta: [getDocSectionLabel(page.section, locale)],
|
||||||
|
payload: {
|
||||||
|
href: getDocHref(docPackage, page),
|
||||||
|
} satisfies DocsSearchPayload,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMatchScore(
|
||||||
|
query: string,
|
||||||
|
terms: readonly string[],
|
||||||
|
packageLabel: string,
|
||||||
|
page: DocPage
|
||||||
|
) {
|
||||||
|
const title = normalize(page.title)
|
||||||
|
const description = normalize(page.description)
|
||||||
|
const packageName = normalize(packageLabel)
|
||||||
|
const toc = normalize(page.toc.flatMap(flattenTocTitles).join(" "))
|
||||||
|
const body = normalize(getDocSearchText(page))
|
||||||
|
const searchableText = [packageName, title, description, toc, body].join(" ")
|
||||||
|
|
||||||
|
if (!terms.every((term) => searchableText.includes(term))) return -1
|
||||||
|
|
||||||
|
let score = 0
|
||||||
|
if (title === query) score += 100
|
||||||
|
else if (title.startsWith(query)) score += 70
|
||||||
|
else if (title.includes(query)) score += 50
|
||||||
|
if (packageName === query) score += 40
|
||||||
|
else if (packageName.includes(query)) score += 20
|
||||||
|
if (description.includes(query)) score += 15
|
||||||
|
if (toc.includes(query)) score += 10
|
||||||
|
if (page.section === "overview") score += 2
|
||||||
|
|
||||||
|
return score
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenTocTitles(item: DocTocItem): readonly string[] {
|
||||||
|
return [item.title, ...(item.items?.flatMap(flattenTocTitles) ?? [])]
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalize(value: string) {
|
||||||
|
return value.normalize("NFKC").toLocaleLowerCase().trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDocsSearchPayload(value: unknown): value is DocsSearchPayload {
|
||||||
|
return (
|
||||||
|
typeof value === "object" &&
|
||||||
|
value !== null &&
|
||||||
|
"href" in value &&
|
||||||
|
typeof value.href === "string"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigate(href: string) {
|
||||||
|
const destination = new URL(href, window.location.href)
|
||||||
|
if (destination.href === window.location.href) return
|
||||||
|
|
||||||
|
window.history.pushState(null, "", destination)
|
||||||
|
window.scrollTo({ left: 0, top: 0 })
|
||||||
|
window.dispatchEvent(new PopStateEvent("popstate"))
|
||||||
|
}
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import { usePreference } from "@workspace/preferences"
|
||||||
|
import { useEffect, useId, useRef, useState } from "react"
|
||||||
|
import { createPortal } from "react-dom"
|
||||||
|
|
||||||
|
import { LocaleFlag } from "./locale-flag"
|
||||||
|
import { getLocalizedHref } from "../content/registry"
|
||||||
|
import type { DocLocale } from "../content/types"
|
||||||
|
import { useLocale, useTranslate } from "../lib/locale"
|
||||||
|
import { useIsMobile } from "../lib/use-mobile"
|
||||||
|
|
||||||
|
type LocaleOption = {
|
||||||
|
label: string
|
||||||
|
locale: DocLocale
|
||||||
|
}
|
||||||
|
|
||||||
|
const localeOptions: readonly LocaleOption[] = [
|
||||||
|
{ label: "简体中文", locale: "zh-Hans" },
|
||||||
|
{ label: "English", locale: "en-US" },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function LanguageSwitcher() {
|
||||||
|
const locale = useLocale()
|
||||||
|
const t = useTranslate()
|
||||||
|
const isMobile = useIsMobile()
|
||||||
|
const [, setLocaleMode] = usePreference("locale-mode")
|
||||||
|
const [, setPreferredLocale] = usePreference("locale")
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const rootRef = useRef<HTMLDivElement>(null)
|
||||||
|
const menuRef = useRef<HTMLDivElement>(null)
|
||||||
|
const triggerRef = useRef<HTMLButtonElement>(null)
|
||||||
|
const menuId = useId()
|
||||||
|
const selectedLocale = getLocaleOption(locale)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return
|
||||||
|
|
||||||
|
function isInsideSwitcher(target: EventTarget | null) {
|
||||||
|
return (
|
||||||
|
target instanceof Node &&
|
||||||
|
(rootRef.current?.contains(target) || menuRef.current?.contains(target))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAndRestoreFocus() {
|
||||||
|
setOpen(false)
|
||||||
|
window.requestAnimationFrame(() => triggerRef.current?.focus())
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePointerDown(event: PointerEvent) {
|
||||||
|
if (isInsideSwitcher(event.target)) return
|
||||||
|
|
||||||
|
if (isMobile) {
|
||||||
|
closeAndRestoreFocus()
|
||||||
|
} else {
|
||||||
|
setOpen(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFocusIn(event: FocusEvent) {
|
||||||
|
if (!isMobile && !isInsideSwitcher(event.target)) setOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
event.preventDefault()
|
||||||
|
closeAndRestoreFocus()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMobile || event.key !== "Tab") return
|
||||||
|
|
||||||
|
const items = getMenuItems(menuRef.current)
|
||||||
|
const firstItem = items[0]
|
||||||
|
const lastItem = items.at(-1)
|
||||||
|
if (!firstItem || !lastItem) return
|
||||||
|
|
||||||
|
if (event.shiftKey && document.activeElement === firstItem) {
|
||||||
|
event.preventDefault()
|
||||||
|
lastItem.focus()
|
||||||
|
} else if (!event.shiftKey && document.activeElement === lastItem) {
|
||||||
|
event.preventDefault()
|
||||||
|
firstItem.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const previousOverflow = document.body.style.overflow
|
||||||
|
if (isMobile) {
|
||||||
|
document.body.style.overflow = "hidden"
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
menuRef.current
|
||||||
|
?.querySelector<HTMLElement>('[aria-checked="true"]')
|
||||||
|
?.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("pointerdown", handlePointerDown)
|
||||||
|
document.addEventListener("focusin", handleFocusIn)
|
||||||
|
document.addEventListener("keydown", handleKeyDown)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("pointerdown", handlePointerDown)
|
||||||
|
document.removeEventListener("focusin", handleFocusIn)
|
||||||
|
document.removeEventListener("keydown", handleKeyDown)
|
||||||
|
if (isMobile) document.body.style.overflow = previousOverflow
|
||||||
|
}
|
||||||
|
}, [isMobile, open])
|
||||||
|
|
||||||
|
function focusMenuItem(position: "first" | "last") {
|
||||||
|
setOpen(true)
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
const items = getMenuItems(menuRef.current)
|
||||||
|
const item = position === "first" ? items[0] : items.at(-1)
|
||||||
|
item?.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectLocale(nextLocale: DocLocale) {
|
||||||
|
setPreferredLocale(nextLocale)
|
||||||
|
setLocaleMode("manual")
|
||||||
|
setOpen(false)
|
||||||
|
window.requestAnimationFrame(() => triggerRef.current?.focus())
|
||||||
|
}
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<div
|
||||||
|
ref={menuRef}
|
||||||
|
id={menuId}
|
||||||
|
role={isMobile ? "dialog" : undefined}
|
||||||
|
aria-label={t({ zh: "语言", us: "Language" })}
|
||||||
|
aria-modal={isMobile || undefined}
|
||||||
|
className="w-[min(80vw,20rem)] rounded-xl border border-slate-200 bg-white/95 p-4 shadow-2xl backdrop-blur-md md:w-auto md:min-w-40 md:p-1 dark:border-slate-800 dark:bg-slate-950/95 dark:shadow-black/60"
|
||||||
|
>
|
||||||
|
<p className="px-2 py-2 text-sm text-slate-500 md:text-xs dark:text-slate-400">
|
||||||
|
{t({ zh: "语言", us: "Language" })}
|
||||||
|
</p>
|
||||||
|
<ul
|
||||||
|
role="menu"
|
||||||
|
aria-label={t({ zh: "语言", us: "Languages" })}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (
|
||||||
|
event.key !== "ArrowDown" &&
|
||||||
|
event.key !== "ArrowUp" &&
|
||||||
|
event.key !== "Home" &&
|
||||||
|
event.key !== "End"
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
const items = getMenuItems(event.currentTarget)
|
||||||
|
const currentIndex = items.indexOf(
|
||||||
|
document.activeElement as HTMLButtonElement
|
||||||
|
)
|
||||||
|
let nextIndex = currentIndex
|
||||||
|
|
||||||
|
if (event.key === "Home") nextIndex = 0
|
||||||
|
if (event.key === "End") nextIndex = items.length - 1
|
||||||
|
if (event.key === "ArrowDown") {
|
||||||
|
nextIndex = (currentIndex + 1) % items.length
|
||||||
|
}
|
||||||
|
if (event.key === "ArrowUp") {
|
||||||
|
nextIndex = (currentIndex - 1 + items.length) % items.length
|
||||||
|
}
|
||||||
|
|
||||||
|
items[nextIndex]?.focus()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{localeOptions.map((option) => {
|
||||||
|
const selected = option.locale === locale
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li role="none" key={option.locale}>
|
||||||
|
<a
|
||||||
|
role="menuitemradio"
|
||||||
|
aria-checked={selected}
|
||||||
|
lang={option.locale}
|
||||||
|
href={getLocalizedHref(window.location.pathname, option.locale)}
|
||||||
|
className="flex h-11 w-full cursor-pointer items-center gap-2 rounded-lg px-2 text-left whitespace-nowrap transition-colors hover:bg-slate-100 focus:bg-slate-100 focus:outline-none aria-checked:text-indigo-600 dark:hover:bg-slate-900 dark:focus:bg-slate-900 dark:aria-checked:text-indigo-400"
|
||||||
|
onClick={() => selectLocale(option.locale)}
|
||||||
|
>
|
||||||
|
<LocaleFlag
|
||||||
|
locale={option.locale}
|
||||||
|
className="size-5 shrink-0"
|
||||||
|
/>
|
||||||
|
<span>{option.label}</span>
|
||||||
|
{selected && (
|
||||||
|
<Icon
|
||||||
|
name="tabler:check"
|
||||||
|
className="ml-auto size-4 shrink-0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={rootRef} className="flex items-center md:relative">
|
||||||
|
<button
|
||||||
|
ref={triggerRef}
|
||||||
|
type="button"
|
||||||
|
aria-controls={open ? menuId : undefined}
|
||||||
|
aria-expanded={open}
|
||||||
|
aria-haspopup={isMobile ? "dialog" : "menu"}
|
||||||
|
aria-label={t({ zh: "选择语言", us: "Choose language" })}
|
||||||
|
title={t({ zh: "选择语言", us: "Choose language" })}
|
||||||
|
className="inline-flex size-8 cursor-pointer items-center justify-center rounded-full transition-colors outline-none hover:bg-slate-100 focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 dark:hover:bg-slate-800 dark:focus-visible:ring-indigo-400 dark:focus-visible:ring-offset-slate-950"
|
||||||
|
onClick={() => setOpen((current) => !current)}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.key === "ArrowDown") {
|
||||||
|
event.preventDefault()
|
||||||
|
focusMenuItem("first")
|
||||||
|
} else if (event.key === "ArrowUp") {
|
||||||
|
event.preventDefault()
|
||||||
|
focusMenuItem("last")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LocaleFlag locale={selectedLocale.locale} className="size-7" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{open &&
|
||||||
|
(isMobile ? (
|
||||||
|
createPortal(
|
||||||
|
<div className="fixed inset-0 z-100 flex items-center justify-center p-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
tabIndex={-1}
|
||||||
|
aria-label={t({
|
||||||
|
zh: "关闭语言菜单",
|
||||||
|
us: "Close language menu",
|
||||||
|
})}
|
||||||
|
className="absolute inset-0 cursor-default bg-black/60 backdrop-blur-sm"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(false)
|
||||||
|
window.requestAnimationFrame(() =>
|
||||||
|
triggerRef.current?.focus()
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="relative">{menu}</div>
|
||||||
|
</div>,
|
||||||
|
document.body
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<div className="absolute top-full right-0 z-100 pt-2">{menu}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMenuItems(root: ParentNode | null) {
|
||||||
|
return Array.from(
|
||||||
|
root?.querySelectorAll<HTMLElement>('[role="menuitemradio"]') ?? []
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLocaleOption(locale: DocLocale) {
|
||||||
|
return localeOptions.find((option) => option.locale === locale)!
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import { cn } from "../lib/utils"
|
||||||
|
import { useTranslate } from "../lib/locale"
|
||||||
|
import React from "react"
|
||||||
|
import { SearchTrigger } from "./search-trigger"
|
||||||
|
import { SettingsLink } from "./settings-link"
|
||||||
|
|
||||||
|
// oxlint-disable-next-line react/only-export-components -- Shared layout tokens are consumed by App.
|
||||||
|
export const rootCSSVariables = {
|
||||||
|
"--cw": "60rem",
|
||||||
|
"--max-lw": "18rem",
|
||||||
|
"--max-rw": "15rem",
|
||||||
|
"--min-lw": "12rem",
|
||||||
|
"--min-rw": "10rem",
|
||||||
|
"--w": "calc(var(--max-lw) + var(--cw) + var(--max-rw))",
|
||||||
|
"--page-pl": "calc(2rem + max(0px, (100vw - var(--w)) * 6 / 11 - 1px))",
|
||||||
|
"--page-pr": "calc(2rem + max(0px, 100vw - var(--w)) * 5 / 11)",
|
||||||
|
} as const as React.CSSProperties
|
||||||
|
|
||||||
|
export function Container({ className, ...rest }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn("px-4 md:pr-(--page-pr) md:pl-(--page-pl)", className)}
|
||||||
|
{...rest}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function HomeButton({
|
||||||
|
href = "/",
|
||||||
|
label,
|
||||||
|
}: {
|
||||||
|
href?: string
|
||||||
|
label?: string
|
||||||
|
}) {
|
||||||
|
const t = useTranslate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
className="flex items-center gap-2 py-1 transition-colors hover:text-indigo-500 dark:hover:text-indigo-400"
|
||||||
|
>
|
||||||
|
<Icon name="tabler:smart-home" className="size-5" />
|
||||||
|
{label ?? t({ zh: "首页", us: "Home" })}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BackButton({
|
||||||
|
href,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
href?: string
|
||||||
|
children?: React.ReactNode
|
||||||
|
}) {
|
||||||
|
const t = useTranslate()
|
||||||
|
|
||||||
|
function handleClick(e: React.MouseEvent) {
|
||||||
|
if (!href) {
|
||||||
|
e.preventDefault()
|
||||||
|
history.back()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={href ?? "/"}
|
||||||
|
onClick={href ? undefined : handleClick}
|
||||||
|
className="flex items-center gap-2 py-1 transition-colors hover:text-indigo-500 dark:hover:text-indigo-400"
|
||||||
|
>
|
||||||
|
<span className="inline-flex h-6 w-4 items-center justify-center rounded-xl bg-slate-200 dark:bg-slate-800">
|
||||||
|
<Icon name="tabler:chevron-compact-left" className="size-4" />
|
||||||
|
</span>
|
||||||
|
{children ?? <span>{t({ zh: "返回", us: "Back" })}</span>}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SlashLine({ className }: { className?: string }) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn("mx-2 h-4 w-px rotate-30 bg-current opacity-35", className)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Actions({ className }: { className?: string }) {
|
||||||
|
return (
|
||||||
|
<div className={cn("inline-flex items-center gap-2", className)}>
|
||||||
|
<SearchTrigger />
|
||||||
|
<SettingsLink />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
|
||||||
|
import type { DocLocale } from "../content/types"
|
||||||
|
|
||||||
|
export function LocaleFlag({
|
||||||
|
className,
|
||||||
|
locale,
|
||||||
|
}: {
|
||||||
|
className?: string
|
||||||
|
locale: DocLocale
|
||||||
|
}) {
|
||||||
|
return locale === "zh-Hans" ? (
|
||||||
|
<Icon name="flag:cn-circle" className={className} />
|
||||||
|
) : (
|
||||||
|
<Icon name="flag:us-circle" className={className} />
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import { useEffect, type ReactNode } from "react"
|
||||||
|
|
||||||
|
import type { DocLocale } from "../content/types"
|
||||||
|
import { LocaleContext } from "../lib/locale"
|
||||||
|
|
||||||
|
export function LocaleProvider({
|
||||||
|
children,
|
||||||
|
locale,
|
||||||
|
}: {
|
||||||
|
children: ReactNode
|
||||||
|
locale: DocLocale
|
||||||
|
}) {
|
||||||
|
useEffect(() => {
|
||||||
|
document.documentElement.lang = locale
|
||||||
|
}, [locale])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LocaleContext.Provider value={locale}>{children}</LocaleContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
import type { MdxComponents } from "../content/types"
|
||||||
|
|
||||||
|
/* oxlint-disable react/only-export-components -- This module exports an MDX component registry. */
|
||||||
|
export const mdxComponents: MdxComponents = {
|
||||||
|
a: MdxAnchor,
|
||||||
|
blockquote: MdxBlockquote,
|
||||||
|
code: MdxCode,
|
||||||
|
h2: MdxHeading2,
|
||||||
|
h3: MdxHeading3,
|
||||||
|
pre: MdxPre,
|
||||||
|
}
|
||||||
|
|
||||||
|
function MdxHeading2({ children, id, ...props }: React.ComponentProps<"h2">) {
|
||||||
|
return (
|
||||||
|
<h2
|
||||||
|
id={id}
|
||||||
|
className="group scroll-mt-24 pt-7 text-2xl font-semibold tracking-tight text-slate-950 first:pt-0 dark:text-slate-100"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{id ? (
|
||||||
|
<a className="text-inherit no-underline" href={`#${id}`}>
|
||||||
|
{children}
|
||||||
|
<span className="ml-2 text-indigo-500 opacity-0 transition-opacity group-hover:opacity-100 dark:text-indigo-400">
|
||||||
|
#
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
children
|
||||||
|
)}
|
||||||
|
</h2>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function MdxHeading3({ children, id, ...props }: React.ComponentProps<"h3">) {
|
||||||
|
return (
|
||||||
|
<h3
|
||||||
|
id={id}
|
||||||
|
className="group scroll-mt-24 pt-5 text-xl font-semibold tracking-tight text-slate-950 dark:text-slate-100"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{id ? (
|
||||||
|
<a className="text-inherit no-underline" href={`#${id}`}>
|
||||||
|
{children}
|
||||||
|
<span className="ml-2 text-indigo-500 opacity-0 transition-opacity group-hover:opacity-100 dark:text-indigo-400">
|
||||||
|
#
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
children
|
||||||
|
)}
|
||||||
|
</h3>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function MdxAnchor({ className, ...props }: React.ComponentProps<"a">) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className={`font-medium text-indigo-600 underline decoration-indigo-300 underline-offset-4 transition-colors hover:text-indigo-500 dark:text-indigo-400 dark:decoration-indigo-800 dark:hover:text-indigo-300 ${className ?? ""}`}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function MdxBlockquote({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"blockquote">) {
|
||||||
|
return (
|
||||||
|
<blockquote
|
||||||
|
className={`rounded-r-lg border-l-2 border-indigo-500 bg-indigo-50 px-4 py-3 text-slate-700 dark:border-indigo-400 dark:bg-indigo-950/30 dark:text-slate-300 ${className ?? ""}`}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function MdxCode({ className, ...props }: React.ComponentProps<"code">) {
|
||||||
|
return (
|
||||||
|
<code
|
||||||
|
className={`rounded bg-slate-100 px-1.5 py-0.5 font-mono text-[0.9em] text-slate-900 dark:bg-slate-900 dark:text-slate-100 ${className ?? ""}`}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function MdxPre({ className, ...props }: React.ComponentProps<"pre">) {
|
||||||
|
return (
|
||||||
|
<pre
|
||||||
|
className={`overflow-x-auto rounded-xl border border-slate-200 bg-slate-50 p-4 font-mono text-sm leading-6 text-slate-900 shadow-sm dark:border-slate-800 dark:bg-black/40 dark:text-slate-100 dark:shadow-none [&_code]:bg-transparent [&_code]:p-0 [&_code]:text-inherit ${className ?? ""}`}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/* oxlint-enable react/only-export-components */
|
||||||
@@ -0,0 +1,228 @@
|
|||||||
|
import {
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useLayoutEffect,
|
||||||
|
useRef,
|
||||||
|
useState,
|
||||||
|
type MutableRefObject,
|
||||||
|
type ReactNode,
|
||||||
|
} from "react"
|
||||||
|
import {
|
||||||
|
PreferencesProvider,
|
||||||
|
usePreference,
|
||||||
|
usePreferences,
|
||||||
|
type PreferenceChangeHandler,
|
||||||
|
type PreferenceUpdate,
|
||||||
|
type Preferences,
|
||||||
|
} from "@workspace/preferences"
|
||||||
|
|
||||||
|
import type { DocLocale } from "../content/types"
|
||||||
|
import { navigateToLocale } from "../lib/locale-navigation"
|
||||||
|
import {
|
||||||
|
detectLocale,
|
||||||
|
docsPreferenceEffects,
|
||||||
|
isDocsPreferenceUpdate,
|
||||||
|
parseDocsPreferences,
|
||||||
|
persistDocsPreference,
|
||||||
|
readDocsPreferences,
|
||||||
|
} from "../lib/preferences"
|
||||||
|
|
||||||
|
const preferencesChannelName = "docs-preferences-sync"
|
||||||
|
|
||||||
|
type PreferencesMessage =
|
||||||
|
| { type: "request" }
|
||||||
|
| { preferences: unknown; type: "snapshot" }
|
||||||
|
| { type: "update"; update: unknown }
|
||||||
|
|
||||||
|
export function DocsPreferencesProvider({
|
||||||
|
children,
|
||||||
|
routeLocale,
|
||||||
|
}: {
|
||||||
|
children: ReactNode
|
||||||
|
routeLocale: DocLocale
|
||||||
|
}) {
|
||||||
|
const [initialPreferences] = useState(() => readDocsPreferences(routeLocale))
|
||||||
|
const channelRef = useRef<BroadcastChannel>(null)
|
||||||
|
const applyingExternalUpdateRef = useRef(false)
|
||||||
|
|
||||||
|
const handlePreferenceChange = useCallback<PreferenceChangeHandler>(
|
||||||
|
(update) => {
|
||||||
|
persistDocsPreference(update)
|
||||||
|
if (!applyingExternalUpdateRef.current) {
|
||||||
|
channelRef.current?.postMessage({ type: "update", update })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PreferencesProvider
|
||||||
|
effects={docsPreferenceEffects}
|
||||||
|
initialPreferences={initialPreferences}
|
||||||
|
onPreferenceChange={handlePreferenceChange}
|
||||||
|
>
|
||||||
|
<PreferencesRuntime
|
||||||
|
applyingExternalUpdateRef={applyingExternalUpdateRef}
|
||||||
|
channelRef={channelRef}
|
||||||
|
routeLocale={routeLocale}
|
||||||
|
/>
|
||||||
|
{children}
|
||||||
|
</PreferencesProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function PreferencesRuntime({
|
||||||
|
applyingExternalUpdateRef,
|
||||||
|
channelRef,
|
||||||
|
routeLocale,
|
||||||
|
}: {
|
||||||
|
applyingExternalUpdateRef: MutableRefObject<boolean>
|
||||||
|
channelRef: MutableRefObject<BroadcastChannel | null>
|
||||||
|
routeLocale: DocLocale
|
||||||
|
}) {
|
||||||
|
const preferences = usePreferences()
|
||||||
|
const preferencesRef = useRef(preferences)
|
||||||
|
const [, setAccentColor] = usePreference("accent-color")
|
||||||
|
const [, setBackgroundShade] = usePreference("background-shade")
|
||||||
|
const [, setForegroundShade] = usePreference("foreground-shade")
|
||||||
|
const [, setLocaleMode] = usePreference("locale-mode")
|
||||||
|
const [, setLocale] = usePreference("locale")
|
||||||
|
const [, setThemeMode] = usePreference("theme-mode")
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
preferencesRef.current = preferences
|
||||||
|
}, [preferences])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!("BroadcastChannel" in window)) return
|
||||||
|
|
||||||
|
const channel = new BroadcastChannel(preferencesChannelName)
|
||||||
|
channelRef.current = channel
|
||||||
|
|
||||||
|
function applyUpdate(update: PreferenceUpdate) {
|
||||||
|
applyingExternalUpdateRef.current = true
|
||||||
|
try {
|
||||||
|
switch (update.key) {
|
||||||
|
case "accent-color":
|
||||||
|
setAccentColor(update.value)
|
||||||
|
break
|
||||||
|
case "background-shade":
|
||||||
|
setBackgroundShade(update.value)
|
||||||
|
break
|
||||||
|
case "foreground-shade":
|
||||||
|
setForegroundShade(update.value)
|
||||||
|
break
|
||||||
|
case "locale-mode":
|
||||||
|
setLocaleMode(update.value)
|
||||||
|
break
|
||||||
|
case "locale":
|
||||||
|
setLocale(update.value)
|
||||||
|
break
|
||||||
|
case "theme-mode":
|
||||||
|
setThemeMode(update.value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
applyingExternalUpdateRef.current = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function applySnapshot(nextPreferences: Preferences) {
|
||||||
|
preferencesRef.current = nextPreferences
|
||||||
|
for (const [key, value] of Object.entries(nextPreferences)) {
|
||||||
|
const update = { key, value }
|
||||||
|
if (isDocsPreferenceUpdate(update)) applyUpdate(update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function synchronizeRoute(nextPreferences: Preferences) {
|
||||||
|
const locale =
|
||||||
|
nextPreferences["locale-mode"] === "auto"
|
||||||
|
? detectLocale()
|
||||||
|
: nextPreferences.locale
|
||||||
|
navigateToLocale(locale, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMessage(event: MessageEvent<unknown>) {
|
||||||
|
const message = event.data as Partial<PreferencesMessage> | undefined
|
||||||
|
if (!message || typeof message !== "object") return
|
||||||
|
|
||||||
|
if (message.type === "request") {
|
||||||
|
channel.postMessage({
|
||||||
|
type: "snapshot",
|
||||||
|
preferences: preferencesRef.current,
|
||||||
|
} satisfies PreferencesMessage)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.type === "update" && isDocsPreferenceUpdate(message.update)) {
|
||||||
|
const nextPreferences = {
|
||||||
|
...preferencesRef.current,
|
||||||
|
[message.update.key]: message.update.value,
|
||||||
|
}
|
||||||
|
preferencesRef.current = nextPreferences
|
||||||
|
applyUpdate(message.update)
|
||||||
|
synchronizeRoute(nextPreferences)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.type === "snapshot") {
|
||||||
|
const nextPreferences = parseDocsPreferences(message.preferences)
|
||||||
|
if (!nextPreferences) return
|
||||||
|
applySnapshot(nextPreferences)
|
||||||
|
synchronizeRoute(nextPreferences)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
channel.addEventListener("message", handleMessage)
|
||||||
|
channel.postMessage({ type: "request" } satisfies PreferencesMessage)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
channelRef.current = null
|
||||||
|
channel.close()
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
applyingExternalUpdateRef,
|
||||||
|
channelRef,
|
||||||
|
setAccentColor,
|
||||||
|
setBackgroundShade,
|
||||||
|
setForegroundShade,
|
||||||
|
setLocale,
|
||||||
|
setLocaleMode,
|
||||||
|
setThemeMode,
|
||||||
|
])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (preferences["locale-mode"] !== "auto") return
|
||||||
|
|
||||||
|
function synchronizeDetectedLocale() {
|
||||||
|
navigateToLocale(detectLocale(), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleVisibilityChange() {
|
||||||
|
if (document.visibilityState === "visible") synchronizeDetectedLocale()
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronizeDetectedLocale()
|
||||||
|
window.addEventListener("focus", synchronizeDetectedLocale)
|
||||||
|
window.addEventListener("languagechange", synchronizeDetectedLocale)
|
||||||
|
document.addEventListener("visibilitychange", handleVisibilityChange)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("focus", synchronizeDetectedLocale)
|
||||||
|
window.removeEventListener("languagechange", synchronizeDetectedLocale)
|
||||||
|
document.removeEventListener("visibilitychange", handleVisibilityChange)
|
||||||
|
}
|
||||||
|
}, [preferences])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
preferences["locale-mode"] === "manual" &&
|
||||||
|
preferences.locale !== routeLocale
|
||||||
|
) {
|
||||||
|
setLocale(routeLocale)
|
||||||
|
}
|
||||||
|
}, [preferences, routeLocale, setLocale])
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import { SearchTrigger as RawSearchTrigger } from "@workspace/search"
|
||||||
|
|
||||||
|
import { useTranslate } from "../lib/locale"
|
||||||
|
|
||||||
|
export function SearchTrigger() {
|
||||||
|
const t = useTranslate()
|
||||||
|
const label = t({ zh: "搜索文档", us: "Search documentation" })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RawSearchTrigger
|
||||||
|
type="button"
|
||||||
|
aria-label={label}
|
||||||
|
title={label}
|
||||||
|
className="inline-flex h-9 shrink-0 items-center gap-2 rounded-lg px-2 text-slate-500 transition-colors sm:hover:bg-slate-100 hover:text-slate-950 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 sm:px-3 dark:text-slate-400 sm:dark:hover:bg-slate-900 dark:hover:text-slate-100"
|
||||||
|
>
|
||||||
|
<Icon name="tabler:search" className="size-5" />
|
||||||
|
<span className="hidden sm:inline">{label}</span>
|
||||||
|
<kbd className="hidden rounded border border-slate-200 bg-white px-1.5 py-0.5 font-sans text-[0.6875rem] leading-none text-slate-400 lg:inline dark:border-slate-700 dark:bg-slate-950 dark:text-slate-500">
|
||||||
|
⌘K
|
||||||
|
</kbd>
|
||||||
|
</RawSearchTrigger>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import type { ComponentProps } from "react"
|
||||||
|
|
||||||
|
import { getLocalizedHref } from "../content/registry"
|
||||||
|
import { useLocale, useTranslate } from "../lib/locale"
|
||||||
|
import { cn } from "../lib/utils"
|
||||||
|
|
||||||
|
export type SettingsLinkProps = Omit<
|
||||||
|
ComponentProps<"a">,
|
||||||
|
"children" | "href"
|
||||||
|
> & {
|
||||||
|
label?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SettingsLink({
|
||||||
|
className,
|
||||||
|
label,
|
||||||
|
...props
|
||||||
|
}: SettingsLinkProps) {
|
||||||
|
const locale = useLocale()
|
||||||
|
const t = useTranslate()
|
||||||
|
const accessibleLabel = label ?? t({ zh: "设置", us: "Settings" })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={getLocalizedHref("/settings", locale)}
|
||||||
|
aria-label={accessibleLabel}
|
||||||
|
title={accessibleLabel}
|
||||||
|
className={cn(
|
||||||
|
"inline-flex size-9 shrink-0 items-center justify-center rounded-lg text-slate-500 transition-colors hover:text-slate-950 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 dark:text-slate-400 dark:hover:text-slate-100",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<Icon name="tabler:settings" className="size-5" />
|
||||||
|
<span className="sr-only">{accessibleLabel}</span>
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import type { ComponentProps } from "react"
|
||||||
|
|
||||||
|
import { cn } from "../lib/utils"
|
||||||
|
|
||||||
|
export type SwatchProps = Omit<ComponentProps<"button">, "children"> & {
|
||||||
|
light: string
|
||||||
|
dark?: string
|
||||||
|
selected?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Swatch({
|
||||||
|
className,
|
||||||
|
light,
|
||||||
|
dark = light,
|
||||||
|
selected = false,
|
||||||
|
...props
|
||||||
|
}: SwatchProps) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-pressed={selected}
|
||||||
|
className={cn(
|
||||||
|
"relative inline-flex flex-col size-10 shrink-0 cursor-pointer gap-px overflow-hidden rounded-full border border-slate-200 transition-transform outline-none hover:scale-105 focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 active:scale-95 aria-pressed:ring-2 aria-pressed:ring-indigo-500 aria-pressed:ring-offset-2 dark:border-slate-700 dark:ring-offset-(--docs-background-dark) text-xs text-center",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className="block size-full dark:hidden"
|
||||||
|
style={{ backgroundColor: light }}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className="hidden dark:block size-full"
|
||||||
|
style={{ backgroundColor: dark }}
|
||||||
|
/>
|
||||||
|
{selected && (
|
||||||
|
<span className="absolute inset-0 flex items-center justify-center">
|
||||||
|
<span className="flex size-5 items-center justify-center rounded-full bg-white/90 text-slate-950 shadow-sm ring-1 ring-black/10">
|
||||||
|
<Icon name="tabler:check" className="size-3.5" />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import { usePreference } from "@workspace/preferences"
|
||||||
|
|
||||||
|
import { useResolvedTheme } from "../lib/appearance"
|
||||||
|
import { useTranslate } from "../lib/locale"
|
||||||
|
|
||||||
|
export function ThemeSwitch({ className }: { className?: string }) {
|
||||||
|
const t = useTranslate()
|
||||||
|
const [, setThemeMode] = usePreference("theme-mode")
|
||||||
|
const resolvedTheme = useResolvedTheme()
|
||||||
|
const dark = resolvedTheme === "dark"
|
||||||
|
const label = dark
|
||||||
|
? t({ zh: "切换到浅色主题", us: "Switch to light theme" })
|
||||||
|
: t({ zh: "切换到深色主题", us: "Switch to dark theme" })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
role="switch"
|
||||||
|
aria-checked={dark}
|
||||||
|
aria-label={label}
|
||||||
|
title={label}
|
||||||
|
className={[
|
||||||
|
"relative inline-flex h-7 w-13 shrink-0 cursor-pointer items-center rounded-full border transition-colors duration-200",
|
||||||
|
"focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 motion-reduce:transition-none",
|
||||||
|
dark
|
||||||
|
? "border-zinc-700 bg-zinc-900 shadow-inner hover:border-zinc-600"
|
||||||
|
: "border-slate-300 bg-slate-100 shadow-inner hover:border-slate-400",
|
||||||
|
className,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" ")}
|
||||||
|
onClick={() => {
|
||||||
|
setThemeMode(dark ? "light" : "dark")
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
className={[
|
||||||
|
"absolute top-px left-px inline-flex size-6 items-center justify-center rounded-full ring-1 shadow-sm transition-transform duration-200 ease-out motion-reduce:transition-none",
|
||||||
|
dark
|
||||||
|
? "translate-x-6 bg-black text-zinc-100 ring-zinc-700"
|
||||||
|
: "translate-x-0 bg-white text-slate-500 ring-slate-200",
|
||||||
|
].join(" ")}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="tabler:sun-high"
|
||||||
|
altName="tabler:moon"
|
||||||
|
showAlt={dark}
|
||||||
|
className="z-10 size-4"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,355 @@
|
|||||||
|
import {
|
||||||
|
defaultDocLocale,
|
||||||
|
docLocales,
|
||||||
|
docSections,
|
||||||
|
type DocLocale,
|
||||||
|
type DocLocation,
|
||||||
|
type DocPackage,
|
||||||
|
type DocPage,
|
||||||
|
type DocSection,
|
||||||
|
type DocTocItem,
|
||||||
|
type MdxComponents,
|
||||||
|
} from "./types"
|
||||||
|
import { trans, type Translation } from "../lib/locale"
|
||||||
|
|
||||||
|
type DocModule = {
|
||||||
|
default: React.ComponentType<{ components?: MdxComponents }>
|
||||||
|
frontmatter: Record<string, unknown>
|
||||||
|
}
|
||||||
|
|
||||||
|
type LocalizedText = Translation<string>
|
||||||
|
|
||||||
|
type PackageDefinition = {
|
||||||
|
key: string
|
||||||
|
label: string
|
||||||
|
description: LocalizedText
|
||||||
|
}
|
||||||
|
|
||||||
|
type ParsedDocPage = DocPage & {
|
||||||
|
packageKey: string
|
||||||
|
searchText: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const packageDefinitions: readonly PackageDefinition[] = [
|
||||||
|
{
|
||||||
|
key: "blocks",
|
||||||
|
label: "Blocks",
|
||||||
|
description: {
|
||||||
|
zh: "构建应用外壳,并接入导航、通知、聊天、媒体和外观控制。",
|
||||||
|
us: "Build an application shell and add navigation, notifications, chat, media, and appearance controls.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "i18n",
|
||||||
|
label: "I18n",
|
||||||
|
description: {
|
||||||
|
zh: "接入应用自有词典、本地化运行时、开发工具和完整翻译工作流。",
|
||||||
|
us: "Add application-owned catalogs, localized runtime rendering, development tools, and translation workflows.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "lexical",
|
||||||
|
label: "Lexical",
|
||||||
|
description: {
|
||||||
|
zh: "从根节点和内容区域开始,逐步构建支持自定义操作与媒体的富文本编辑器。",
|
||||||
|
us: "Build a rich-text editor progressively from its root and content surface to custom actions and media.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "preferences",
|
||||||
|
label: "Preferences",
|
||||||
|
description: {
|
||||||
|
zh: "使用 SSR 快照、持久化回调和可组合副作用管理类型安全且可扩展的应用偏好。",
|
||||||
|
us: "Manage typed, extensible application preferences with SSR snapshots, persistence callbacks, and composable effects.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "search",
|
||||||
|
label: "Search",
|
||||||
|
description: {
|
||||||
|
zh: "通过可替换的 Adapter、分组结果、分页和搜索历史构建应用级搜索体验。",
|
||||||
|
us: "Build application search with a replaceable adapter, grouped results, pagination, and search history.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "ui",
|
||||||
|
label: "UI",
|
||||||
|
description: {
|
||||||
|
zh: "配置共享 UI 层,并学习组合组件、Hooks、图标和本地化词典。",
|
||||||
|
us: "Set up the shared UI layer and learn how to compose its components, hooks, icons, and locale catalogs.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const docModules = import.meta.glob<DocModule>(
|
||||||
|
"../../../packages/*/docs/*/**/*.mdx",
|
||||||
|
{ eager: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
const docSources = import.meta.glob<string>(
|
||||||
|
"../../../packages/*/docs/*/**/*.mdx",
|
||||||
|
{ eager: true, import: "default", query: "?docs-search-raw" }
|
||||||
|
)
|
||||||
|
|
||||||
|
const parsedPages = Object.entries(docModules).map(([path, module]) =>
|
||||||
|
parseDocPage(path, module, docSources[path] ?? "")
|
||||||
|
)
|
||||||
|
|
||||||
|
const packagesByLocale: Record<DocLocale, readonly DocPackage[]> = {
|
||||||
|
"zh-Hans": packageDefinitions.map((definition) =>
|
||||||
|
createDocPackage(definition, "zh-Hans")
|
||||||
|
),
|
||||||
|
"en-US": packageDefinitions.map((definition) =>
|
||||||
|
createDocPackage(definition, "en-US")
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
validateLocalizedPagePairs(packagesByLocale)
|
||||||
|
|
||||||
|
export function getDocPackages(locale: DocLocale = defaultDocLocale) {
|
||||||
|
return packagesByLocale[locale]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDocHref(docPackage: DocPackage, page?: DocPage) {
|
||||||
|
const prefix = getLocalePrefix(docPackage.locale)
|
||||||
|
const target = page ?? getOverviewPage(docPackage)
|
||||||
|
const pagePath =
|
||||||
|
target.section === "overview"
|
||||||
|
? ""
|
||||||
|
: `/${target.section}/${encodeURIComponent(target.slug)}`
|
||||||
|
|
||||||
|
return `${prefix}/articles/${docPackage.key}${pagePath}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDocsHomeHref(locale: DocLocale) {
|
||||||
|
return getLocalePrefix(locale) || "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLocalizedHref(pathname: string, locale: DocLocale) {
|
||||||
|
if (/^(?:\/(?:en-US|zh-Hans))?\/settings\/?$/.test(pathname)) {
|
||||||
|
return `${getLocalePrefix(locale)}/settings`
|
||||||
|
}
|
||||||
|
|
||||||
|
const location = resolveDocLocation(pathname)
|
||||||
|
if (!location) return getDocsHomeHref(locale)
|
||||||
|
|
||||||
|
const docPackage = getDocPackages(locale).find(
|
||||||
|
(item) => item.key === location.package.key
|
||||||
|
)
|
||||||
|
const page = docPackage?.pages.find(
|
||||||
|
(item) =>
|
||||||
|
item.section === location.page.section && item.slug === location.page.slug
|
||||||
|
)
|
||||||
|
|
||||||
|
return docPackage && page
|
||||||
|
? getDocHref(docPackage, page)
|
||||||
|
: getDocsHomeHref(locale)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveDocLocale(pathname: string): DocLocale {
|
||||||
|
const firstSegment = pathname.split("/").filter(Boolean)[0]
|
||||||
|
return isDocLocale(firstSegment) ? firstSegment : defaultDocLocale
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveDocLocation(pathname: string): DocLocation | undefined {
|
||||||
|
const segments = pathname.split("/").filter(Boolean)
|
||||||
|
let locale: DocLocale = defaultDocLocale
|
||||||
|
if (isDocLocale(segments[0])) {
|
||||||
|
locale = segments.shift() as DocLocale
|
||||||
|
}
|
||||||
|
const [resource, packageKey, sectionValue, pageSlug, ...extra] = segments
|
||||||
|
|
||||||
|
if (resource !== "articles" || extra.length > 0) return undefined
|
||||||
|
|
||||||
|
const docPackage = getDocPackages(locale).find(
|
||||||
|
(item) => item.key === packageKey
|
||||||
|
)
|
||||||
|
if (!docPackage) return undefined
|
||||||
|
|
||||||
|
if (sectionValue === undefined) {
|
||||||
|
const page = getOverviewPage(docPackage)
|
||||||
|
return { locale, package: docPackage, page }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectionValue === "overview" || !isDocSection(sectionValue) || !pageSlug) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const page = docPackage.pages.find(
|
||||||
|
(item) => item.section === sectionValue && item.slug === pageSlug
|
||||||
|
)
|
||||||
|
|
||||||
|
return page ? { locale, package: docPackage, page } : undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDocSectionLabel(section: DocSection, locale: DocLocale) {
|
||||||
|
const labels: Record<DocSection, Translation> = {
|
||||||
|
overview: { zh: "概览", us: "Overview" },
|
||||||
|
guide: { zh: "指南", us: "Guide" },
|
||||||
|
advanced: { zh: "进阶", us: "Advanced" },
|
||||||
|
examples: { zh: "示例", us: "Examples" },
|
||||||
|
}
|
||||||
|
|
||||||
|
return trans(locale, labels[section])
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDocSearchText(page: DocPage) {
|
||||||
|
return (page as ParsedDocPage).searchText
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDocPackage(
|
||||||
|
definition: PackageDefinition,
|
||||||
|
locale: DocLocale
|
||||||
|
): DocPackage {
|
||||||
|
const pages = parsedPages
|
||||||
|
.filter(
|
||||||
|
(page) => page.packageKey === definition.key && page.locale === locale
|
||||||
|
)
|
||||||
|
.sort(
|
||||||
|
(left, right) =>
|
||||||
|
docSections.indexOf(left.section) -
|
||||||
|
docSections.indexOf(right.section) ||
|
||||||
|
left.order - right.order ||
|
||||||
|
left.slug.localeCompare(right.slug)
|
||||||
|
)
|
||||||
|
|
||||||
|
const overviewCount = pages.filter(
|
||||||
|
(page) => page.section === "overview"
|
||||||
|
).length
|
||||||
|
if (overviewCount !== 1) {
|
||||||
|
throw new Error(
|
||||||
|
`${definition.key}/${locale} must contain exactly one docs/${locale}/overview.mdx file.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const section of docSections.slice(1)) {
|
||||||
|
if (!pages.some((page) => page.section === section)) {
|
||||||
|
throw new Error(
|
||||||
|
`${definition.key}/${locale} must contain at least one ${section} document.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: definition.key,
|
||||||
|
label: definition.label,
|
||||||
|
description: trans(locale, definition.description),
|
||||||
|
locale,
|
||||||
|
pages,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseDocPage(
|
||||||
|
path: string,
|
||||||
|
module: DocModule,
|
||||||
|
source: string
|
||||||
|
): ParsedDocPage {
|
||||||
|
const match = path.match(
|
||||||
|
/\/packages\/([^/]+)\/docs\/([^/]+)\/(overview|guide|advanced|examples)(?:\/([^/]+))?\.mdx$/
|
||||||
|
)
|
||||||
|
if (!match) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid documentation path "${path}". Expected docs/<locale>/overview.mdx or docs/<locale>/<guide|advanced|examples>/*.mdx.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const [, packageKey, localeValue, sectionValue, nestedSlug] = match
|
||||||
|
if (!isDocLocale(localeValue)) {
|
||||||
|
throw new Error(
|
||||||
|
`Unsupported documentation locale "${localeValue}" in "${path}".`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!isDocSection(sectionValue)) {
|
||||||
|
throw new Error(`Unsupported documentation section in "${path}".`)
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(sectionValue === "overview" && nestedSlug !== undefined) ||
|
||||||
|
(sectionValue !== "overview" && nestedSlug === undefined)
|
||||||
|
) {
|
||||||
|
throw new Error(`Documentation file is in the wrong directory: "${path}".`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const frontmatter = module.frontmatter
|
||||||
|
return {
|
||||||
|
Content: module.default,
|
||||||
|
description: readString(frontmatter, "description"),
|
||||||
|
locale: localeValue,
|
||||||
|
order: readNumber(frontmatter, "order"),
|
||||||
|
packageKey,
|
||||||
|
searchText: source,
|
||||||
|
section: sectionValue,
|
||||||
|
slug: nestedSlug ?? "overview",
|
||||||
|
title: readString(frontmatter, "title"),
|
||||||
|
toc: readToc(frontmatter.toc),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateLocalizedPagePairs(
|
||||||
|
packages: Record<DocLocale, readonly DocPackage[]>
|
||||||
|
) {
|
||||||
|
for (const definition of packageDefinitions) {
|
||||||
|
const keysByLocale = docLocales.map((locale) => {
|
||||||
|
const docPackage = packages[locale].find(
|
||||||
|
(item) => item.key === definition.key
|
||||||
|
)!
|
||||||
|
return docPackage.pages.map((page) => `${page.section}/${page.slug}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
if (keysByLocale[0]?.join("\n") !== keysByLocale[1]?.join("\n")) {
|
||||||
|
throw new Error(
|
||||||
|
`${definition.key} documentation must contain matching zh-Hans and en-US page paths.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOverviewPage(docPackage: DocPackage) {
|
||||||
|
return docPackage.pages.find((page) => page.section === "overview")!
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLocalePrefix(locale: DocLocale) {
|
||||||
|
return locale === defaultDocLocale ? "" : `/${locale}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDocLocale(value: unknown): value is DocLocale {
|
||||||
|
return docLocales.some((locale) => locale === value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDocSection(value: unknown): value is DocSection {
|
||||||
|
return docSections.some((section) => section === value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function readString(frontmatter: Record<string, unknown>, key: string) {
|
||||||
|
const value = frontmatter[key]
|
||||||
|
if (typeof value === "string" && value.trim()) return value
|
||||||
|
throw new Error(`Documentation frontmatter requires a string "${key}".`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function readNumber(frontmatter: Record<string, unknown>, key: string) {
|
||||||
|
const value = frontmatter[key]
|
||||||
|
if (typeof value === "number" && Number.isFinite(value)) return value
|
||||||
|
throw new Error(`Documentation frontmatter requires a number "${key}".`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function readToc(value: unknown): readonly DocTocItem[] {
|
||||||
|
if (value === undefined) return []
|
||||||
|
if (!Array.isArray(value)) {
|
||||||
|
throw new Error('Documentation frontmatter "toc" must be an array.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.map((item) => {
|
||||||
|
if (!isRecord(item)) {
|
||||||
|
throw new Error('Each documentation "toc" entry must be an object.')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: readString(item, "id"),
|
||||||
|
title: readString(item, "title"),
|
||||||
|
items: item.items === undefined ? undefined : readToc(item.items),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
|
return typeof value === "object" && value !== null
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
import type { ComponentType, ElementType } from "react"
|
||||||
|
|
||||||
|
export const docLocales = ["zh-Hans", "en-US"] as const
|
||||||
|
export const defaultDocLocale = "zh-Hans" as const
|
||||||
|
export const docSections = [
|
||||||
|
"overview",
|
||||||
|
"guide",
|
||||||
|
"advanced",
|
||||||
|
"examples",
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export type DocLocale = (typeof docLocales)[number]
|
||||||
|
export type DocSection = (typeof docSections)[number]
|
||||||
|
export type MdxComponents = Record<string, ElementType>
|
||||||
|
|
||||||
|
export type DocTocItem = {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
items?: readonly DocTocItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DocPage = {
|
||||||
|
Content: ComponentType<{ components?: MdxComponents }>
|
||||||
|
description: string
|
||||||
|
locale: DocLocale
|
||||||
|
order: number
|
||||||
|
section: DocSection
|
||||||
|
slug: string
|
||||||
|
title: string
|
||||||
|
toc: readonly DocTocItem[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DocPackage = {
|
||||||
|
key: string
|
||||||
|
label: string
|
||||||
|
description: string
|
||||||
|
locale: DocLocale
|
||||||
|
pages: readonly DocPage[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DocLocation = {
|
||||||
|
locale: DocLocale
|
||||||
|
package: DocPackage
|
||||||
|
page: DocPage
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
@import "@workspace/ui/globals.css";
|
||||||
|
@import "@workspace/search/globals.css";
|
||||||
|
|
||||||
|
@custom-variant dark (&:where(.dark, .dark *));
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
@apply border-slate-200 dark:border-slate-800;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
@apply antialiased;
|
||||||
|
background-color: var(--docs-background-light, var(--color-white));
|
||||||
|
color: var(--docs-foreground-light, var(--color-slate-950));
|
||||||
|
font-family: "DM Serif Display", Georgia, serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark {
|
||||||
|
background-color: var(--docs-background-dark, var(--color-slate-950));
|
||||||
|
color: var(--docs-foreground-dark, var(--color-slate-100));
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: var(--docs-background-light, var(--color-white));
|
||||||
|
--foreground: var(--docs-foreground-light, var(--color-slate-950));
|
||||||
|
--card: var(--docs-background-light, var(--color-white));
|
||||||
|
--card-foreground: var(--docs-foreground-light, var(--color-slate-950));
|
||||||
|
--popover: var(--docs-background-light, var(--color-white));
|
||||||
|
--popover-foreground: var(--docs-foreground-light, var(--color-slate-950));
|
||||||
|
--primary: var(--color-indigo-600);
|
||||||
|
--primary-foreground: var(--color-white);
|
||||||
|
--secondary: var(--docs-surface-light, var(--color-slate-100));
|
||||||
|
--secondary-foreground: var(
|
||||||
|
--docs-foreground-light,
|
||||||
|
var(--color-slate-950)
|
||||||
|
);
|
||||||
|
--muted: var(--docs-surface-light, var(--color-slate-100));
|
||||||
|
--muted-foreground: var(--docs-muted-light, var(--color-slate-600));
|
||||||
|
--accent: var(--docs-surface-light, var(--color-slate-100));
|
||||||
|
--accent-foreground: var(--docs-foreground-light, var(--color-slate-950));
|
||||||
|
--border: var(--color-slate-200);
|
||||||
|
--input: var(--color-slate-200);
|
||||||
|
--ring: var(--color-indigo-500);
|
||||||
|
--sidebar: var(--docs-background-light, var(--color-white));
|
||||||
|
--sidebar-foreground: var(--docs-foreground-light, var(--color-slate-950));
|
||||||
|
--sidebar-border: var(--color-slate-200);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark {
|
||||||
|
--background: var(--docs-background-dark, var(--color-slate-950));
|
||||||
|
--foreground: var(--docs-foreground-dark, var(--color-slate-100));
|
||||||
|
--card: var(--docs-surface-dark, var(--color-slate-900));
|
||||||
|
--card-foreground: var(--docs-foreground-dark, var(--color-slate-100));
|
||||||
|
--popover: var(--docs-surface-dark, var(--color-slate-900));
|
||||||
|
--popover-foreground: var(--docs-foreground-dark, var(--color-slate-100));
|
||||||
|
--primary: var(--color-indigo-400);
|
||||||
|
--primary-foreground: var(--color-slate-950);
|
||||||
|
--secondary: var(--color-slate-800);
|
||||||
|
--secondary-foreground: var(--docs-foreground-dark, var(--color-slate-100));
|
||||||
|
--muted: var(--color-slate-800);
|
||||||
|
--muted-foreground: var(--docs-muted-dark, var(--color-slate-400));
|
||||||
|
--accent: var(--color-slate-800);
|
||||||
|
--accent-foreground: var(--docs-foreground-dark, var(--color-slate-100));
|
||||||
|
--border: var(--color-slate-800);
|
||||||
|
--input: var(--color-slate-700);
|
||||||
|
--ring: var(--color-indigo-400);
|
||||||
|
--sidebar: var(--docs-surface-dark, var(--color-slate-900));
|
||||||
|
--sidebar-foreground: var(--docs-foreground-dark, var(--color-slate-100));
|
||||||
|
--sidebar-border: var(--color-slate-800);
|
||||||
|
}
|
||||||
|
|
||||||
|
body,
|
||||||
|
#root {
|
||||||
|
@apply min-h-dvh;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply bg-inherit text-inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
::selection {
|
||||||
|
@apply bg-indigo-200 text-indigo-950 dark:bg-indigo-500/40 dark:text-indigo-50;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
import { useCallback, useSyncExternalStore } from "react"
|
||||||
|
import { usePreference } from "@workspace/preferences"
|
||||||
|
import colors from "tailwindcss/colors"
|
||||||
|
|
||||||
|
export const themeModes = ["light", "dark", "system"] as const
|
||||||
|
export const accentColors = [
|
||||||
|
"neutral",
|
||||||
|
"blue",
|
||||||
|
"cyan",
|
||||||
|
"emerald",
|
||||||
|
"fuchsia",
|
||||||
|
"green",
|
||||||
|
"indigo",
|
||||||
|
"lime",
|
||||||
|
"orange",
|
||||||
|
"pink",
|
||||||
|
"purple",
|
||||||
|
"red",
|
||||||
|
"rose",
|
||||||
|
"sky",
|
||||||
|
"teal",
|
||||||
|
"violet",
|
||||||
|
"yellow",
|
||||||
|
] as const
|
||||||
|
export const backgroundShades = [
|
||||||
|
"neutral",
|
||||||
|
"stone",
|
||||||
|
"zinc",
|
||||||
|
"mauve",
|
||||||
|
"olive",
|
||||||
|
"mist",
|
||||||
|
"taupe",
|
||||||
|
] as const
|
||||||
|
export const foregroundShades = ["slate", "neutral", "stone"] as const
|
||||||
|
|
||||||
|
export type ThemeMode = (typeof themeModes)[number]
|
||||||
|
export type AccentColor = (typeof accentColors)[number]
|
||||||
|
export type BackgroundShade = (typeof backgroundShades)[number]
|
||||||
|
export type ForegroundShade = (typeof foregroundShades)[number]
|
||||||
|
export type ResolvedTheme = Exclude<ThemeMode, "system">
|
||||||
|
|
||||||
|
export type Appearance = {
|
||||||
|
accentColor: AccentColor
|
||||||
|
backgroundShade: BackgroundShade
|
||||||
|
foregroundShade: ForegroundShade
|
||||||
|
themeMode: ThemeMode
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AppearanceController = Appearance & {
|
||||||
|
updateAppearance: (update: Partial<Appearance>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const systemThemeQuery = "(prefers-color-scheme: dark)"
|
||||||
|
const colorSteps = [
|
||||||
|
50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950,
|
||||||
|
] as const
|
||||||
|
|
||||||
|
type ColorStep = (typeof colorSteps)[number]
|
||||||
|
type ColorScale = Record<ColorStep, string>
|
||||||
|
|
||||||
|
export function useAppearance(): AppearanceController {
|
||||||
|
const [accentColor, setAccentColor] = usePreference("accent-color")
|
||||||
|
const [backgroundShade, setBackgroundShade] =
|
||||||
|
usePreference("background-shade")
|
||||||
|
const [foregroundShade, setForegroundShade] =
|
||||||
|
usePreference("foreground-shade")
|
||||||
|
const [themeMode, setThemeMode] = usePreference("theme-mode")
|
||||||
|
|
||||||
|
const updateAppearance = useCallback(
|
||||||
|
(update: Partial<Appearance>) => {
|
||||||
|
if (update.accentColor !== undefined) {
|
||||||
|
setAccentColor(update.accentColor)
|
||||||
|
}
|
||||||
|
if (update.backgroundShade !== undefined) {
|
||||||
|
setBackgroundShade(update.backgroundShade)
|
||||||
|
}
|
||||||
|
if (update.foregroundShade !== undefined) {
|
||||||
|
setForegroundShade(update.foregroundShade)
|
||||||
|
}
|
||||||
|
if (update.themeMode !== undefined) setThemeMode(update.themeMode)
|
||||||
|
},
|
||||||
|
[setAccentColor, setBackgroundShade, setForegroundShade, setThemeMode]
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
accentColor,
|
||||||
|
backgroundShade,
|
||||||
|
foregroundShade,
|
||||||
|
themeMode,
|
||||||
|
updateAppearance,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useResolvedTheme() {
|
||||||
|
const [themeMode] = usePreference("theme-mode")
|
||||||
|
const systemTheme = useSyncExternalStore(
|
||||||
|
subscribeToSystemTheme,
|
||||||
|
getSystemTheme,
|
||||||
|
() => "light" as const
|
||||||
|
)
|
||||||
|
|
||||||
|
return themeMode === "system" ? systemTheme : themeMode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPaletteColor(
|
||||||
|
color: AccentColor | BackgroundShade | ForegroundShade,
|
||||||
|
step: ColorStep = 500
|
||||||
|
) {
|
||||||
|
return getColorScale(color)[step]
|
||||||
|
}
|
||||||
|
|
||||||
|
export function applyAppearance(appearance: Appearance) {
|
||||||
|
if (typeof document === "undefined") return
|
||||||
|
|
||||||
|
const root = document.documentElement
|
||||||
|
const resolvedTheme =
|
||||||
|
appearance.themeMode === "system" ? getSystemTheme() : appearance.themeMode
|
||||||
|
const accentScale = getColorScale(appearance.accentColor)
|
||||||
|
const backgroundScale = getColorScale(appearance.backgroundShade)
|
||||||
|
const foregroundScale = getColorScale(appearance.foregroundShade)
|
||||||
|
|
||||||
|
root.classList.toggle("dark", resolvedTheme === "dark")
|
||||||
|
root.style.colorScheme = resolvedTheme
|
||||||
|
root.dataset.themeMode = appearance.themeMode
|
||||||
|
root.dataset.accentColor = appearance.accentColor
|
||||||
|
root.dataset.backgroundShade = appearance.backgroundShade
|
||||||
|
root.dataset.foregroundShade = appearance.foregroundShade
|
||||||
|
|
||||||
|
for (const step of colorSteps) {
|
||||||
|
root.style.setProperty(`--color-indigo-${step}`, accentScale[step])
|
||||||
|
}
|
||||||
|
|
||||||
|
root.style.setProperty("--docs-background-light", backgroundScale[50])
|
||||||
|
root.style.setProperty("--docs-background-dark", backgroundScale[950])
|
||||||
|
root.style.setProperty("--docs-surface-light", backgroundScale[100])
|
||||||
|
root.style.setProperty("--docs-surface-dark", backgroundScale[900])
|
||||||
|
root.style.setProperty("--docs-foreground-light", foregroundScale[950])
|
||||||
|
root.style.setProperty("--docs-foreground-dark", foregroundScale[50])
|
||||||
|
root.style.setProperty("--docs-muted-light", foregroundScale[600])
|
||||||
|
root.style.setProperty("--docs-muted-dark", foregroundScale[400])
|
||||||
|
}
|
||||||
|
|
||||||
|
export function subscribeToSystemTheme(listener: VoidFunction) {
|
||||||
|
const mediaQuery = window.matchMedia(systemThemeQuery)
|
||||||
|
mediaQuery.addEventListener("change", listener)
|
||||||
|
return () => mediaQuery.removeEventListener("change", listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSystemTheme(): ResolvedTheme {
|
||||||
|
return window.matchMedia(systemThemeQuery).matches ? "dark" : "light"
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColorScale(color: string) {
|
||||||
|
return colors[color as keyof typeof colors] as ColorScale
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { getLocalizedHref } from "../content/registry"
|
||||||
|
import type { DocLocale } from "../content/types"
|
||||||
|
|
||||||
|
export function navigateToLocale(locale: DocLocale, replace = false) {
|
||||||
|
const href = getLocalizedHref(window.location.pathname, locale)
|
||||||
|
if (href === window.location.pathname) return
|
||||||
|
|
||||||
|
if (replace) {
|
||||||
|
window.history.replaceState(null, "", href)
|
||||||
|
} else {
|
||||||
|
window.history.pushState(null, "", href)
|
||||||
|
}
|
||||||
|
window.dispatchEvent(new PopStateEvent("popstate"))
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import { createContext, useCallback, useContext } from "react"
|
||||||
|
|
||||||
|
import { defaultDocLocale, type DocLocale } from "../content/types"
|
||||||
|
|
||||||
|
export type Translation<Value = string> = Readonly<{
|
||||||
|
zh: Value
|
||||||
|
us: Value
|
||||||
|
}>
|
||||||
|
|
||||||
|
export type Translate = <Value>(translation: Translation<Value>) => Value
|
||||||
|
|
||||||
|
export const LocaleContext = createContext<DocLocale>(defaultDocLocale)
|
||||||
|
|
||||||
|
export function useLocale() {
|
||||||
|
return useContext(LocaleContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useTranslate(): Translate {
|
||||||
|
const locale = useLocale()
|
||||||
|
|
||||||
|
return useCallback(
|
||||||
|
<Value>(translation: Translation<Value>) => trans(locale, translation),
|
||||||
|
[locale]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function trans<Value>(
|
||||||
|
locale: DocLocale,
|
||||||
|
translation: Translation<Value>
|
||||||
|
): Value {
|
||||||
|
return locale === "zh-Hans" ? translation.zh : translation.us
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
import {
|
||||||
|
createPreferenceUpdateGuard,
|
||||||
|
type PreferenceDefinitions,
|
||||||
|
type PreferenceEffect,
|
||||||
|
type PreferenceUpdate,
|
||||||
|
type Preferences,
|
||||||
|
} from "@workspace/preferences"
|
||||||
|
|
||||||
|
import { defaultDocLocale, docLocales, type DocLocale } from "../content/types"
|
||||||
|
import {
|
||||||
|
accentColors,
|
||||||
|
applyAppearance,
|
||||||
|
backgroundShades,
|
||||||
|
foregroundShades,
|
||||||
|
subscribeToSystemTheme,
|
||||||
|
themeModes,
|
||||||
|
type AccentColor,
|
||||||
|
type Appearance,
|
||||||
|
type BackgroundShade,
|
||||||
|
type ForegroundShade,
|
||||||
|
type ThemeMode,
|
||||||
|
} from "./appearance"
|
||||||
|
|
||||||
|
export type LocaleMode = "auto" | "manual"
|
||||||
|
|
||||||
|
export type DocsPreferences = {
|
||||||
|
"accent-color": AccentColor
|
||||||
|
"background-shade": BackgroundShade
|
||||||
|
"foreground-shade": ForegroundShade
|
||||||
|
"locale-mode": LocaleMode
|
||||||
|
locale: DocLocale
|
||||||
|
"theme-mode": ThemeMode
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "@workspace/preferences" {
|
||||||
|
interface PreferencesCustom extends DocsPreferences {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const docsPreferenceDefinitions = {
|
||||||
|
"accent-color": createStringPreference(
|
||||||
|
"docs-accent-color",
|
||||||
|
"indigo",
|
||||||
|
accentColors
|
||||||
|
),
|
||||||
|
"background-shade": createStringPreference(
|
||||||
|
"docs-background-shade",
|
||||||
|
"neutral",
|
||||||
|
backgroundShades
|
||||||
|
),
|
||||||
|
"foreground-shade": createStringPreference(
|
||||||
|
"docs-foreground-shade",
|
||||||
|
"slate",
|
||||||
|
foregroundShades
|
||||||
|
),
|
||||||
|
"locale-mode": {
|
||||||
|
cookie: "docs-locale-auto-detect",
|
||||||
|
defaultValue: "manual",
|
||||||
|
is: (value): value is LocaleMode => value === "auto" || value === "manual",
|
||||||
|
parse: (value) => (value === "1" || value === "auto" ? "auto" : "manual"),
|
||||||
|
serialize: (value) => (value === "auto" ? "1" : "0"),
|
||||||
|
},
|
||||||
|
locale: createStringPreference("docs-locale", defaultDocLocale, docLocales),
|
||||||
|
"theme-mode": createStringPreference("docs-theme", "system", themeModes),
|
||||||
|
} satisfies PreferenceDefinitions<DocsPreferences>
|
||||||
|
|
||||||
|
export const isDocsPreferenceUpdate = createPreferenceUpdateGuard(
|
||||||
|
docsPreferenceDefinitions
|
||||||
|
)
|
||||||
|
|
||||||
|
export const docsPreferenceEffects = [
|
||||||
|
{
|
||||||
|
layoutEffect: ({ preferences }) => {
|
||||||
|
applyAppearance(toAppearance(preferences))
|
||||||
|
},
|
||||||
|
effect: ({ preferences, store }) => {
|
||||||
|
if (preferences["theme-mode"] !== "system") return
|
||||||
|
|
||||||
|
return subscribeToSystemTheme(() => {
|
||||||
|
applyAppearance(toAppearance(store.getSnapshot()))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] satisfies readonly PreferenceEffect[]
|
||||||
|
|
||||||
|
export function initializeDocsPreferences() {
|
||||||
|
applyAppearance(toAppearance(readDocsPreferences()))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function readDocsPreferences(
|
||||||
|
fallbackLocale: DocLocale = defaultDocLocale
|
||||||
|
): Preferences {
|
||||||
|
const preferences = Object.fromEntries(
|
||||||
|
(
|
||||||
|
Object.keys(docsPreferenceDefinitions) as Array<keyof DocsPreferences>
|
||||||
|
).map((key) => {
|
||||||
|
const definition = docsPreferenceDefinitions[key]
|
||||||
|
return [key, readStoredValue(definition.cookie, definition.parse)]
|
||||||
|
})
|
||||||
|
) as DocsPreferences
|
||||||
|
|
||||||
|
if (!readStoredString(docsPreferenceDefinitions.locale.cookie)) {
|
||||||
|
preferences.locale = fallbackLocale
|
||||||
|
}
|
||||||
|
|
||||||
|
return preferences
|
||||||
|
}
|
||||||
|
|
||||||
|
export function persistDocsPreference(update: PreferenceUpdate) {
|
||||||
|
const definition = docsPreferenceDefinitions[update.key]
|
||||||
|
const serializedValue =
|
||||||
|
update.key === "locale-mode"
|
||||||
|
? docsPreferenceDefinitions["locale-mode"].serialize(update.value)
|
||||||
|
: update.value
|
||||||
|
writeStoredString(definition.cookie, serializedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseDocsPreferences(value: unknown): Preferences | undefined {
|
||||||
|
if (!value || typeof value !== "object") return undefined
|
||||||
|
|
||||||
|
const candidate = value as Partial<Record<keyof DocsPreferences, unknown>>
|
||||||
|
for (const key of Object.keys(docsPreferenceDefinitions) as Array<
|
||||||
|
keyof DocsPreferences
|
||||||
|
>) {
|
||||||
|
if (!docsPreferenceDefinitions[key].is(candidate[key])) return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
return candidate as DocsPreferences
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toAppearance(preferences: Preferences): Appearance {
|
||||||
|
return {
|
||||||
|
accentColor: preferences["accent-color"],
|
||||||
|
backgroundShade: preferences["background-shade"],
|
||||||
|
foregroundShade: preferences["foreground-shade"],
|
||||||
|
themeMode: preferences["theme-mode"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function detectLocale(): DocLocale {
|
||||||
|
const languages = navigator.languages.length
|
||||||
|
? navigator.languages
|
||||||
|
: [navigator.language]
|
||||||
|
return languages.some((language) => language.toLowerCase().startsWith("zh"))
|
||||||
|
? "zh-Hans"
|
||||||
|
: "en-US"
|
||||||
|
}
|
||||||
|
|
||||||
|
function createStringPreference<const Options extends readonly string[]>(
|
||||||
|
cookie: string,
|
||||||
|
defaultValue: Options[number],
|
||||||
|
options: Options
|
||||||
|
) {
|
||||||
|
const is = (value: unknown): value is Options[number] =>
|
||||||
|
typeof value === "string" && options.some((option) => option === value)
|
||||||
|
|
||||||
|
return {
|
||||||
|
cookie,
|
||||||
|
defaultValue,
|
||||||
|
is,
|
||||||
|
parse: (value: string | undefined) => (is(value) ? value : defaultValue),
|
||||||
|
serialize: (value: Options[number]) => value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readStoredValue<Value>(
|
||||||
|
key: string,
|
||||||
|
parse: (value: string | undefined) => Value
|
||||||
|
) {
|
||||||
|
return parse(readStoredString(key))
|
||||||
|
}
|
||||||
|
|
||||||
|
function readStoredString(key: string) {
|
||||||
|
if (typeof window === "undefined") return undefined
|
||||||
|
|
||||||
|
try {
|
||||||
|
return window.sessionStorage.getItem(key) ?? undefined
|
||||||
|
} catch {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeStoredString(key: string, value: string) {
|
||||||
|
try {
|
||||||
|
window.sessionStorage.setItem(key, value)
|
||||||
|
} catch {
|
||||||
|
// The in-memory preference remains active when storage is unavailable.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
const MOBILE_BREAKPOINT = 768
|
||||||
|
|
||||||
|
export function useIsMobile() {
|
||||||
|
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
||||||
|
const onChange = () => {
|
||||||
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
||||||
|
}
|
||||||
|
mql.addEventListener("change", onChange)
|
||||||
|
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
||||||
|
return () => mql.removeEventListener("change", onChange)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return !!isMobile
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { clsx, type ClassValue } from "clsx"
|
||||||
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
|
export type { ClassValue }
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { StrictMode } from "react"
|
||||||
|
import { createRoot } from "react-dom/client"
|
||||||
|
|
||||||
|
import App from "./App.tsx"
|
||||||
|
import "./index.css"
|
||||||
|
import { initializeDocsPreferences } from "./lib/preferences"
|
||||||
|
|
||||||
|
document.documentElement.lang = window.location.pathname.startsWith("/en-US")
|
||||||
|
? "en-US"
|
||||||
|
: "zh-Hans"
|
||||||
|
|
||||||
|
initializeDocsPreferences()
|
||||||
|
|
||||||
|
createRoot(document.getElementById("root")!).render(
|
||||||
|
<StrictMode>
|
||||||
|
<App />
|
||||||
|
</StrictMode>
|
||||||
|
)
|
||||||
@@ -0,0 +1,719 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { createPortal } from "react-dom"
|
||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import {
|
||||||
|
getDocHref,
|
||||||
|
getDocPackages,
|
||||||
|
getDocSectionLabel,
|
||||||
|
getDocsHomeHref,
|
||||||
|
resolveDocLocation,
|
||||||
|
} from "../content/registry"
|
||||||
|
import type {
|
||||||
|
DocLocation,
|
||||||
|
DocPage,
|
||||||
|
DocTocItem,
|
||||||
|
} from "../content/types"
|
||||||
|
import { Actions, Container, HomeButton, SlashLine } from "../components/layout"
|
||||||
|
import { mdxComponents } from "../components/mdx"
|
||||||
|
import { useLocale, useTranslate } from "../lib/locale"
|
||||||
|
|
||||||
|
const noTocItems: readonly DocTocItem[] = []
|
||||||
|
|
||||||
|
export default function ArticlePage() {
|
||||||
|
const t = useTranslate()
|
||||||
|
const docLocation = resolveDocLocation(window.location.pathname)
|
||||||
|
const visibleTocIds = useVisibleTocIds(docLocation?.page.toc ?? noTocItems)
|
||||||
|
const [mobilePanel, setMobilePanel] = React.useState<
|
||||||
|
"navigation" | "toc" | null
|
||||||
|
>(null)
|
||||||
|
const mobilePanelRef = React.useRef<HTMLDivElement>(null)
|
||||||
|
const navigationTriggerRef = React.useRef<HTMLButtonElement>(null)
|
||||||
|
const tocTriggerRef = React.useRef<HTMLButtonElement>(null)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!mobilePanel) return
|
||||||
|
|
||||||
|
const previousOverflow = document.body.style.overflow
|
||||||
|
document.body.style.overflow = "hidden"
|
||||||
|
const unavailableAt = window.matchMedia(
|
||||||
|
mobilePanel === "navigation" ? "(min-width: 48rem)" : "(min-width: 64rem)"
|
||||||
|
)
|
||||||
|
|
||||||
|
const animationFrame = window.requestAnimationFrame(() => {
|
||||||
|
mobilePanelRef.current
|
||||||
|
?.querySelector<HTMLElement>(
|
||||||
|
'a[href], button:not(:disabled), [tabindex]:not([tabindex="-1"])'
|
||||||
|
)
|
||||||
|
?.focus()
|
||||||
|
})
|
||||||
|
|
||||||
|
function handleKeyDown(event: KeyboardEvent) {
|
||||||
|
if (event.key === "Escape") {
|
||||||
|
event.preventDefault()
|
||||||
|
setMobilePanel(null)
|
||||||
|
const trigger =
|
||||||
|
mobilePanel === "navigation"
|
||||||
|
? navigationTriggerRef.current
|
||||||
|
: tocTriggerRef.current
|
||||||
|
trigger?.focus()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key !== "Tab") return
|
||||||
|
|
||||||
|
const focusableElements = Array.from(
|
||||||
|
mobilePanelRef.current?.querySelectorAll<HTMLElement>(
|
||||||
|
'a[href], button:not(:disabled), [tabindex]:not([tabindex="-1"])'
|
||||||
|
) ?? []
|
||||||
|
)
|
||||||
|
const firstElement = focusableElements[0]
|
||||||
|
const lastElement = focusableElements.at(-1)
|
||||||
|
|
||||||
|
if (!firstElement || !lastElement) return
|
||||||
|
|
||||||
|
if (event.shiftKey && document.activeElement === firstElement) {
|
||||||
|
event.preventDefault()
|
||||||
|
lastElement.focus()
|
||||||
|
} else if (!event.shiftKey && document.activeElement === lastElement) {
|
||||||
|
event.preventDefault()
|
||||||
|
firstElement.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBreakpointChange(event: MediaQueryListEvent) {
|
||||||
|
if (event.matches) setMobilePanel(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("keydown", handleKeyDown)
|
||||||
|
unavailableAt.addEventListener("change", handleBreakpointChange)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.cancelAnimationFrame(animationFrame)
|
||||||
|
document.removeEventListener("keydown", handleKeyDown)
|
||||||
|
unavailableAt.removeEventListener("change", handleBreakpointChange)
|
||||||
|
document.body.style.overflow = previousOverflow
|
||||||
|
}
|
||||||
|
}, [mobilePanel])
|
||||||
|
|
||||||
|
if (!docLocation) return <ArticleNotFound />
|
||||||
|
|
||||||
|
const currentIndex = docLocation.package.pages.indexOf(docLocation.page)
|
||||||
|
const previousPage = docLocation.package.pages[currentIndex - 1]
|
||||||
|
const nextPage = docLocation.package.pages[currentIndex + 1]
|
||||||
|
const previous = previousPage
|
||||||
|
? {
|
||||||
|
locale: docLocation.locale,
|
||||||
|
package: docLocation.package,
|
||||||
|
page: previousPage,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
const next = nextPage
|
||||||
|
? {
|
||||||
|
locale: docLocation.locale,
|
||||||
|
package: docLocation.package,
|
||||||
|
page: nextPage,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header
|
||||||
|
data-article-sticky-header
|
||||||
|
className="z-10 h-16 border-b bg-white/70 backdrop-blur-sm md:sticky md:top-0 dark:border-slate-800 dark:bg-slate-950/80"
|
||||||
|
>
|
||||||
|
<Container className="flex size-full items-center gap-4">
|
||||||
|
<HomeButton href={getDocsHomeHref(docLocation.locale)} />
|
||||||
|
<SlashLine />
|
||||||
|
<h1 className="truncate">{docLocation.package.label}</h1>
|
||||||
|
<Actions className="ml-auto" />
|
||||||
|
</Container>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section
|
||||||
|
data-article-sticky-header
|
||||||
|
className="sticky top-0 z-20 flex items-center justify-between border-b bg-white/70 backdrop-blur-sm md:hidden dark:border-slate-800 dark:bg-slate-950/80"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
ref={navigationTriggerRef}
|
||||||
|
type="button"
|
||||||
|
className="inline-flex h-12 cursor-pointer items-center gap-2 px-4 transition-colors"
|
||||||
|
aria-controls="article-mobile-navigation"
|
||||||
|
aria-expanded={mobilePanel === "navigation"}
|
||||||
|
onClick={() =>
|
||||||
|
setMobilePanel((current) =>
|
||||||
|
current === "navigation" ? null : "navigation"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon name="tabler:menu" className="size-5" />
|
||||||
|
<span>{t({ zh: "文档菜单", us: "Docs Menu" })}</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
ref={tocTriggerRef}
|
||||||
|
type="button"
|
||||||
|
className="ml-auto inline-flex h-12 cursor-pointer items-center gap-2 px-4 transition-colors"
|
||||||
|
aria-controls="article-mobile-toc"
|
||||||
|
aria-expanded={mobilePanel === "toc"}
|
||||||
|
onClick={() =>
|
||||||
|
setMobilePanel((current) => (current === "toc" ? null : "toc"))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span>{t({ zh: "本页内容", us: "On this page" })}</span>
|
||||||
|
<Icon name="tabler:list" className="size-5 rotate-180" />
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{mobilePanel &&
|
||||||
|
typeof document !== "undefined" &&
|
||||||
|
createPortal(
|
||||||
|
<div className="fixed inset-0 z-50">
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 bg-slate-950/50 backdrop-blur-[1px] dark:bg-black/70"
|
||||||
|
aria-hidden="true"
|
||||||
|
onClick={() => {
|
||||||
|
const trigger =
|
||||||
|
mobilePanel === "navigation"
|
||||||
|
? navigationTriggerRef.current
|
||||||
|
: tocTriggerRef.current
|
||||||
|
setMobilePanel(null)
|
||||||
|
window.requestAnimationFrame(() => trigger?.focus())
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
ref={mobilePanelRef}
|
||||||
|
id={
|
||||||
|
mobilePanel === "navigation"
|
||||||
|
? "article-mobile-navigation"
|
||||||
|
: "article-mobile-toc"
|
||||||
|
}
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-label={
|
||||||
|
mobilePanel === "navigation"
|
||||||
|
? t({ zh: "文档导航", us: "Documentation navigation" })
|
||||||
|
: t({ zh: "本页内容", us: "On this page" })
|
||||||
|
}
|
||||||
|
className={[
|
||||||
|
"absolute inset-y-0 w-[min(88vw,35rem)] overflow-y-auto overscroll-contain bg-white p-7 shadow-2xl dark:bg-slate-950 dark:shadow-black/60",
|
||||||
|
mobilePanel === "navigation" ? "left-0" : "right-0",
|
||||||
|
].join(" ")}
|
||||||
|
onClick={(event) => {
|
||||||
|
if (
|
||||||
|
event.target instanceof Element &&
|
||||||
|
event.target.closest("a[href]")
|
||||||
|
) {
|
||||||
|
setMobilePanel(null)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{mobilePanel === "navigation" ? (
|
||||||
|
<nav aria-label="Documentation navigation">
|
||||||
|
<Sidebar current={docLocation} />
|
||||||
|
</nav>
|
||||||
|
) : (
|
||||||
|
<TableOfContents
|
||||||
|
activeIds={visibleTocIds}
|
||||||
|
items={docLocation.page.toc}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
document.body
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex w-full">
|
||||||
|
<div
|
||||||
|
data-slot="left"
|
||||||
|
className="sticky top-16 hidden h-[calc(100svh-(--spacing(16)))] min-w-(--min-lw) flex-[6_1_var(--min-lw)] overflow-y-auto border-r bg-slate-50 md:block dark:border-slate-800 dark:bg-slate-900/50"
|
||||||
|
>
|
||||||
|
<aside className="ml-auto w-full max-w-(--max-lw) p-8">
|
||||||
|
<Sidebar current={docLocation} />
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-slot="center"
|
||||||
|
className="min-w-0 flex-1 sm:flex-[0_1_var(--cw)]"
|
||||||
|
>
|
||||||
|
<main className="w-full max-w-(--cw) px-4 pt-8 pb-16 md:px-22">
|
||||||
|
<Header docLocation={docLocation} />
|
||||||
|
<ArticleContent page={docLocation.page} />
|
||||||
|
<Footer next={next} previous={previous} />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
data-slot="right"
|
||||||
|
className="sticky top-16 hidden h-[calc(100svh-(--spacing(16)))] min-w-(--min-rw) flex-[5_1_var(--min-rw)] lg:block"
|
||||||
|
>
|
||||||
|
<div className="h-full w-full max-w-(--max-rw)">
|
||||||
|
<TableOfContents
|
||||||
|
activeIds={visibleTocIds}
|
||||||
|
items={docLocation.page.toc}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer className="border-t py-8 text-slate-500 dark:border-slate-800 dark:text-slate-400">
|
||||||
|
<Container className="flex h-full w-full items-center">
|
||||||
|
Copyright © 2026
|
||||||
|
</Container>
|
||||||
|
</footer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Sidebar({ current }: { current: DocLocation }) {
|
||||||
|
const overview = current.package.pages.find(
|
||||||
|
(page) => page.section === "overview"
|
||||||
|
)
|
||||||
|
const groups = current.package.pages
|
||||||
|
.filter((page) => page.section !== "overview")
|
||||||
|
.reduce<Array<{ section: DocPage["section"]; pages: DocPage[] }>>(
|
||||||
|
(result, page) => {
|
||||||
|
const group = result.at(-1)
|
||||||
|
if (group?.section === page.section) {
|
||||||
|
group.pages.push(page)
|
||||||
|
} else {
|
||||||
|
result.push({ section: page.section, pages: [page] })
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
{overview && (
|
||||||
|
<li>
|
||||||
|
<SidebarPageLink current={current} page={overview} prominent />
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{groups.map((group) => (
|
||||||
|
<li className="not-first:mt-8" key={group.section}>
|
||||||
|
<h2 className="font-semibold">
|
||||||
|
{getDocSectionLabel(group.section, current.locale)}
|
||||||
|
</h2>
|
||||||
|
<ul className="mt-1.5">
|
||||||
|
{group.pages.map((page) => (
|
||||||
|
<li key={`${page.section}/${page.slug}`}>
|
||||||
|
<SidebarPageLink current={current} page={page} />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SidebarPageLink({
|
||||||
|
current,
|
||||||
|
page,
|
||||||
|
prominent = false,
|
||||||
|
}: {
|
||||||
|
current: DocLocation
|
||||||
|
page: DocPage
|
||||||
|
prominent?: boolean
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className={`block py-1 transition-colors hover:text-indigo-500 aria-[current=page]:text-indigo-500 dark:hover:text-indigo-300 dark:aria-[current=page]:text-indigo-400 ${prominent ? "font-semibold text-slate-950 dark:text-slate-100" : "text-gray-600 aria-[current=page]:font-medium dark:text-slate-400"}`}
|
||||||
|
href={getDocHref(current.package, page)}
|
||||||
|
aria-current={
|
||||||
|
current.page.section === page.section && current.page.slug === page.slug
|
||||||
|
? "page"
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{page.title}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Header({ docLocation }: { docLocation: DocLocation }) {
|
||||||
|
return (
|
||||||
|
<header className="mb-12 border-b pb-12">
|
||||||
|
<ul className="flex items-center gap-2">
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href={getDocHref(docLocation.package)}
|
||||||
|
className="transition-colors hover:text-indigo-500 dark:hover:text-indigo-300"
|
||||||
|
>
|
||||||
|
{docLocation.package.label}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-slate-200 dark:text-slate-700">/</span>
|
||||||
|
</li>
|
||||||
|
{docLocation.page.section !== "overview" && (
|
||||||
|
<>
|
||||||
|
<li>
|
||||||
|
<span className="text-slate-500 dark:text-slate-400">
|
||||||
|
{getDocSectionLabel(
|
||||||
|
docLocation.page.section,
|
||||||
|
docLocation.locale
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-slate-200 dark:text-slate-700">/</span>
|
||||||
|
</li>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<li>
|
||||||
|
<span className="text-indigo-500 dark:text-indigo-400">
|
||||||
|
{docLocation.page.title}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h1 className="mt-4 text-4xl">{docLocation.page.title}</h1>
|
||||||
|
<p className="mt-2 text-slate-500 dark:text-slate-400">
|
||||||
|
{docLocation.page.description}
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ArticleContent({ page }: { page: DocPage }) {
|
||||||
|
const Content = page.Content
|
||||||
|
|
||||||
|
return (
|
||||||
|
<article
|
||||||
|
data-article-content
|
||||||
|
className="space-y-5 text-slate-700 dark:text-slate-300 [&_hr]:my-12 [&_hr]:border-slate-200 dark:[&_hr]:border-slate-800 [&_li]:leading-7 [&_ol]:list-decimal [&_ol]:space-y-2 [&_ol]:pl-6 [&_p]:leading-7 [&_strong]:font-semibold [&_strong]:text-slate-950 dark:[&_strong]:text-slate-100 [&_table]:w-full [&_table]:border-collapse [&_td]:border [&_td]:border-slate-200 [&_td]:p-3 dark:[&_td]:border-slate-800 [&_th]:border [&_th]:border-slate-200 [&_th]:bg-slate-50 [&_th]:p-3 [&_th]:text-left dark:[&_th]:border-slate-800 dark:[&_th]:bg-slate-900 [&_ul]:list-disc [&_ul]:space-y-2 [&_ul]:pl-6"
|
||||||
|
>
|
||||||
|
<Content components={mdxComponents} />
|
||||||
|
</article>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableOfContents({
|
||||||
|
activeIds,
|
||||||
|
items,
|
||||||
|
}: {
|
||||||
|
activeIds: readonly string[]
|
||||||
|
items: readonly DocTocItem[]
|
||||||
|
}) {
|
||||||
|
const t = useTranslate()
|
||||||
|
const label = t({ zh: "本页内容", us: "On this page" })
|
||||||
|
const rootRef = React.useRef<HTMLElement>(null)
|
||||||
|
const railRef = React.useRef<HTMLDivElement>(null)
|
||||||
|
const [marker, setMarker] = React.useState<{
|
||||||
|
height: number
|
||||||
|
top: number
|
||||||
|
} | null>(null)
|
||||||
|
const activeKey = activeIds.join("\n")
|
||||||
|
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
|
const root = rootRef.current
|
||||||
|
const rail = railRef.current
|
||||||
|
if (!root || !rail) return
|
||||||
|
|
||||||
|
function measureMarker() {
|
||||||
|
const activeIdSet = new Set(activeIds)
|
||||||
|
const activeRows = Array.from(
|
||||||
|
root!.querySelectorAll<HTMLElement>("[data-toc-id]")
|
||||||
|
).filter((row) => activeIdSet.has(row.dataset.tocId ?? ""))
|
||||||
|
|
||||||
|
if (activeRows.length === 0 || rail!.offsetHeight === 0) {
|
||||||
|
setMarker(null)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const railRect = rail!.getBoundingClientRect()
|
||||||
|
const firstRect = activeRows[0]!.getBoundingClientRect()
|
||||||
|
const lastRect = activeRows.at(-1)!.getBoundingClientRect()
|
||||||
|
setMarker({
|
||||||
|
top: firstRect.top - railRect.top,
|
||||||
|
height: lastRect.bottom - firstRect.top,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
measureMarker()
|
||||||
|
const resizeObserver = new ResizeObserver(measureMarker)
|
||||||
|
resizeObserver.observe(root)
|
||||||
|
window.addEventListener("resize", measureMarker)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
window.removeEventListener("resize", measureMarker)
|
||||||
|
}
|
||||||
|
}, [activeKey, activeIds])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<aside
|
||||||
|
ref={rootRef}
|
||||||
|
aria-label={label}
|
||||||
|
className="relative max-h-full overflow-y-auto p-8"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
ref={railRef}
|
||||||
|
className="absolute top-8 bottom-6 left-8 hidden w-px bg-slate-200 md:block dark:bg-slate-800"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="absolute left-0 w-px bg-indigo-500 transition-[height,transform,opacity] duration-200 dark:bg-indigo-400"
|
||||||
|
style={{
|
||||||
|
height: marker?.height ?? 0,
|
||||||
|
opacity: marker ? 1 : 0,
|
||||||
|
transform: `translateY(${marker?.top ?? 0}px)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="md:ps-4">
|
||||||
|
<h2 className="shrink-0">{label}</h2>
|
||||||
|
<ul className="mt-2">
|
||||||
|
{items.map((item) => (
|
||||||
|
<TocItem activeIds={activeIds} item={item} key={item.id} />
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TocItem({
|
||||||
|
activeIds,
|
||||||
|
item,
|
||||||
|
}: {
|
||||||
|
activeIds: readonly string[]
|
||||||
|
item: DocTocItem
|
||||||
|
}) {
|
||||||
|
const active = activeIds.includes(item.id)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<TocAnchor
|
||||||
|
active={active}
|
||||||
|
href={`#${item.id}`}
|
||||||
|
itemId={item.id}
|
||||||
|
title={item.title}
|
||||||
|
/>
|
||||||
|
{item.items && item.items.length > 0 && (
|
||||||
|
<ul className="ps-4">
|
||||||
|
{item.items.map((child) => (
|
||||||
|
<TocItem activeIds={activeIds} item={child} key={child.id} />
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function TocAnchor({
|
||||||
|
active,
|
||||||
|
href,
|
||||||
|
itemId,
|
||||||
|
title,
|
||||||
|
}: {
|
||||||
|
active: boolean
|
||||||
|
href: string
|
||||||
|
itemId: string
|
||||||
|
title: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="py-1" data-toc-id={itemId}>
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
data-active={active || undefined}
|
||||||
|
className="text-slate-600 transition-colors hover:text-indigo-500 data-active:font-medium data-active:text-indigo-600 dark:text-slate-400 dark:hover:text-indigo-300 dark:data-active:text-indigo-400"
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TocVisibilityEntry = {
|
||||||
|
id: string
|
||||||
|
parentIds: readonly string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
function useVisibleTocIds(items: readonly DocTocItem[]) {
|
||||||
|
const entries = React.useMemo(() => flattenTocItems(items), [items])
|
||||||
|
const [activeIds, setActiveIds] = React.useState<readonly string[]>([])
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (entries.length === 0) {
|
||||||
|
setActiveIds([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let animationFrame: number | undefined
|
||||||
|
const articleElement = document.querySelector<HTMLElement>(
|
||||||
|
"[data-article-content]"
|
||||||
|
)
|
||||||
|
if (!articleElement) return
|
||||||
|
const article = articleElement
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
animationFrame = undefined
|
||||||
|
const headings = entries.flatMap((entry) => {
|
||||||
|
const element = document.getElementById(entry.id)
|
||||||
|
return element ? [{ element, entry }] : []
|
||||||
|
})
|
||||||
|
const viewportTop = getVisibleViewportTop()
|
||||||
|
const viewportBottom = window.innerHeight
|
||||||
|
const articleBottom = article.getBoundingClientRect().bottom
|
||||||
|
const visibleIds = new Set<string>()
|
||||||
|
|
||||||
|
headings.forEach(({ element, entry }, index) => {
|
||||||
|
const sectionTop = element.getBoundingClientRect().top
|
||||||
|
const sectionBottom =
|
||||||
|
headings[index + 1]?.element.getBoundingClientRect().top ??
|
||||||
|
articleBottom
|
||||||
|
|
||||||
|
if (sectionBottom > viewportTop && sectionTop < viewportBottom) {
|
||||||
|
entry.parentIds.forEach((id) => visibleIds.add(id))
|
||||||
|
visibleIds.add(entry.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const nextActiveIds = entries
|
||||||
|
.map((entry) => entry.id)
|
||||||
|
.filter((id) => visibleIds.has(id))
|
||||||
|
setActiveIds((current) =>
|
||||||
|
arraysEqual(current, nextActiveIds) ? current : nextActiveIds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleUpdate() {
|
||||||
|
if (animationFrame !== undefined) return
|
||||||
|
animationFrame = window.requestAnimationFrame(update)
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduleUpdate()
|
||||||
|
const resizeObserver = new ResizeObserver(scheduleUpdate)
|
||||||
|
resizeObserver.observe(article)
|
||||||
|
window.addEventListener("scroll", scheduleUpdate, { passive: true })
|
||||||
|
window.addEventListener("resize", scheduleUpdate)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (animationFrame !== undefined) {
|
||||||
|
window.cancelAnimationFrame(animationFrame)
|
||||||
|
}
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
window.removeEventListener("scroll", scheduleUpdate)
|
||||||
|
window.removeEventListener("resize", scheduleUpdate)
|
||||||
|
}
|
||||||
|
}, [entries])
|
||||||
|
|
||||||
|
return activeIds
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenTocItems(
|
||||||
|
items: readonly DocTocItem[],
|
||||||
|
parentIds: readonly string[] = []
|
||||||
|
): readonly TocVisibilityEntry[] {
|
||||||
|
return items.flatMap((item) => [
|
||||||
|
{ id: item.id, parentIds },
|
||||||
|
...flattenTocItems(item.items ?? [], [...parentIds, item.id]),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVisibleViewportTop() {
|
||||||
|
return Array.from(
|
||||||
|
document.querySelectorAll<HTMLElement>("[data-article-sticky-header]")
|
||||||
|
).reduce((bottom, element) => {
|
||||||
|
const rect = element.getBoundingClientRect()
|
||||||
|
return rect.top <= 0 && rect.bottom > 0
|
||||||
|
? Math.max(bottom, rect.bottom)
|
||||||
|
: bottom
|
||||||
|
}, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
function arraysEqual(left: readonly string[], right: readonly string[]) {
|
||||||
|
return (
|
||||||
|
left.length === right.length &&
|
||||||
|
left.every((value, index) => value === right[index])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Footer({
|
||||||
|
next,
|
||||||
|
previous,
|
||||||
|
}: {
|
||||||
|
next?: DocLocation
|
||||||
|
previous?: DocLocation
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<footer className="mt-12 flex flex-col gap-4 border-t border-dashed pt-12 md:grid md:grid-cols-2 md:gap-8">
|
||||||
|
{previous && (
|
||||||
|
<Surround
|
||||||
|
href={getDocHref(previous.package, previous.page)}
|
||||||
|
title={previous.page.title}
|
||||||
|
description={previous.page.description}
|
||||||
|
align="left"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{next && (
|
||||||
|
<Surround
|
||||||
|
href={getDocHref(next.package, next.page)}
|
||||||
|
title={next.page.title}
|
||||||
|
description={next.page.description}
|
||||||
|
align="right"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</footer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Surround({
|
||||||
|
href,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
align = "right",
|
||||||
|
}: {
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
align?: "left" | "right"
|
||||||
|
href: string
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
className={[
|
||||||
|
"group flex min-w-0 flex-col gap-1 rounded-xl border p-4",
|
||||||
|
"transition-colors hover:bg-slate-50 dark:hover:bg-slate-900",
|
||||||
|
align === "left"
|
||||||
|
? "col-start-1 items-start text-left"
|
||||||
|
: "col-start-2 items-end text-right",
|
||||||
|
].join(" ")}
|
||||||
|
>
|
||||||
|
<div className="flex size-8 items-center justify-center rounded-full border bg-slate-50 text-sm font-bold transition-colors group-hover:border-indigo-500 group-hover:bg-indigo-100 group-hover:text-indigo-500 dark:border-slate-700 dark:bg-slate-900 dark:group-hover:border-indigo-400 dark:group-hover:bg-indigo-950/70 dark:group-hover:text-indigo-300">
|
||||||
|
{align === "left" ? (
|
||||||
|
<Icon name="tabler:arrow-left" />
|
||||||
|
) : (
|
||||||
|
<Icon name="tabler:arrow-right" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<h2 className="mt-4 w-full min-w-0 truncate text-lg">{title}</h2>
|
||||||
|
<p className="text-md mt-1 line-clamp-2 w-full min-w-0 break-all text-slate-500 dark:text-slate-400">
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ArticleNotFound() {
|
||||||
|
const locale = useLocale()
|
||||||
|
const t = useTranslate()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="mx-auto flex min-h-dvh max-w-xl flex-col justify-center px-6">
|
||||||
|
<h1 className="text-4xl">
|
||||||
|
{t({ zh: "未找到文档", us: "Document not found" })}
|
||||||
|
</h1>
|
||||||
|
<p className="mt-3 text-slate-500 dark:text-slate-400">
|
||||||
|
{t({
|
||||||
|
zh: "请求的文档包或页面不存在。",
|
||||||
|
us: "The requested package or document does not exist.",
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
className="mt-6 w-fit text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
|
||||||
|
href={getDocHref(getDocPackages(locale)[0]!)}
|
||||||
|
>
|
||||||
|
{t({ zh: "打开文档", us: "Open the documentation" })}
|
||||||
|
</a>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
import { Actions, Container } from "../components/layout"
|
||||||
|
import { getDocHref, getDocPackages } from "../content/registry"
|
||||||
|
import { useLocale, useTranslate } from "../lib/locale"
|
||||||
|
|
||||||
|
export default function IndexPage() {
|
||||||
|
const locale = useLocale()
|
||||||
|
const t = useTranslate()
|
||||||
|
const docPackages = getDocPackages(locale)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Container className="flex items-center justify-between gap-4 pt-8 pb-10 sm:pt-12 sm:pb-14 lg:pb-16">
|
||||||
|
<h1 className="min-w-0 text-2xl font-semibold capitalize sm:text-3xl">
|
||||||
|
my-shadcn-ui
|
||||||
|
</h1>
|
||||||
|
<Actions className="ml-auto" />
|
||||||
|
</Container>
|
||||||
|
<Container
|
||||||
|
className="grid grid-cols-1 gap-4 sm:grid-cols-2 sm:gap-6 lg:grid-cols-3 lg:gap-8"
|
||||||
|
aria-label={t({ zh: "文档导航", us: "Documentation" })}
|
||||||
|
>
|
||||||
|
{docPackages.map((docPackage, index) => (
|
||||||
|
<a
|
||||||
|
key={docPackage.key}
|
||||||
|
href={getDocHref(docPackage)}
|
||||||
|
className="block overflow-hidden rounded-xl border border-slate-200 bg-indigo-50 outline-0 outline-offset-2 transition-colors hover:border-indigo-500 hover:bg-indigo-50 focus-visible:outline-2 focus-visible:outline-indigo-500 dark:border-slate-800 dark:bg-slate-900 dark:hover:border-indigo-400 dark:hover:bg-slate-800/80 dark:focus-visible:outline-indigo-400"
|
||||||
|
>
|
||||||
|
<div className="min-h-fit p-4 sm:min-h-40 lg:min-h-46">
|
||||||
|
<div className="text-slate-400 dark:text-slate-500">
|
||||||
|
{index > 9 ? `${index + 1}` : `0${index + 1}`}
|
||||||
|
</div>
|
||||||
|
<h2 className="mt-2 mb-4 text-xl font-semibold text-slate-950 dark:text-slate-100">
|
||||||
|
{docPackage.label}
|
||||||
|
</h2>
|
||||||
|
<p className="text-slate-700 dark:text-slate-300">
|
||||||
|
{docPackage.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
))}
|
||||||
|
</Container>
|
||||||
|
<footer className="py-8 sm:py-12">
|
||||||
|
<Container className="text-center text-slate-500 dark:text-slate-400">
|
||||||
|
<div>Copyright © 2026</div>
|
||||||
|
</Container>
|
||||||
|
</footer>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
import { Icon } from "@icones/react"
|
||||||
|
import { usePreference } from "@workspace/preferences"
|
||||||
|
|
||||||
|
import { BackButton, Container, SlashLine } from "../components/layout"
|
||||||
|
import { LocaleFlag } from "../components/locale-flag"
|
||||||
|
import { SearchTrigger } from "../components/search-trigger"
|
||||||
|
import { Swatch } from "../components/swatch"
|
||||||
|
import { getLocalizedHref } from "../content/registry"
|
||||||
|
import type { DocLocale } from "../content/types"
|
||||||
|
import {
|
||||||
|
accentColors,
|
||||||
|
backgroundShades,
|
||||||
|
getPaletteColor,
|
||||||
|
themeModes,
|
||||||
|
useAppearance,
|
||||||
|
type AccentColor,
|
||||||
|
type BackgroundShade,
|
||||||
|
type ForegroundShade,
|
||||||
|
type ThemeMode,
|
||||||
|
} from "../lib/appearance"
|
||||||
|
import { useLocale, useTranslate, type Translation } from "../lib/locale"
|
||||||
|
import { navigateToLocale } from "../lib/locale-navigation"
|
||||||
|
import { detectLocale } from "../lib/preferences"
|
||||||
|
|
||||||
|
const foregroundOptions: ReadonlyArray<{
|
||||||
|
label: Translation
|
||||||
|
value: ForegroundShade
|
||||||
|
}> = [
|
||||||
|
{ value: "slate", label: { zh: "冷色", us: "Cool" } },
|
||||||
|
{ value: "neutral", label: { zh: "中性", us: "Neutral" } },
|
||||||
|
{ value: "stone", label: { zh: "暖色", us: "Warm" } },
|
||||||
|
]
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
accent: { zh: "强调色", us: "Accent color" },
|
||||||
|
appearance: { zh: "外观", us: "Appearance" },
|
||||||
|
autoDetect: { zh: "自动检测", us: "Automatic detection" },
|
||||||
|
autoDetectDescription: {
|
||||||
|
zh: "跟随浏览器或操作系统语言设置。",
|
||||||
|
us: "Follow the browser or operating system language.",
|
||||||
|
},
|
||||||
|
background: { zh: "背景色调", us: "Background shade" },
|
||||||
|
enable: { zh: "启用", us: "Enable" },
|
||||||
|
foreground: { zh: "前景色调", us: "Foreground shade" },
|
||||||
|
language: { zh: "语言", us: "Language" },
|
||||||
|
settings: { zh: "设置", us: "Settings" },
|
||||||
|
theme: { zh: "主题", us: "Theme" },
|
||||||
|
themeModes: {
|
||||||
|
light: { zh: "浅色", us: "Light" },
|
||||||
|
dark: { zh: "深色", us: "Dark" },
|
||||||
|
system: { zh: "跟随系统", us: "System" },
|
||||||
|
},
|
||||||
|
} as const
|
||||||
|
|
||||||
|
export default function SettingsPage() {
|
||||||
|
const locale = useLocale()
|
||||||
|
const t = useTranslate()
|
||||||
|
const appearance = useAppearance()
|
||||||
|
const [localeMode, setLocaleMode] = usePreference("locale-mode")
|
||||||
|
const [, setPreferredLocale] = usePreference("locale")
|
||||||
|
const autoDetectLocale = localeMode === "auto"
|
||||||
|
|
||||||
|
function selectLocale(nextLocale: DocLocale) {
|
||||||
|
setPreferredLocale(nextLocale)
|
||||||
|
setLocaleMode("manual")
|
||||||
|
navigateToLocale(nextLocale)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAutomaticLocale(enabled: boolean) {
|
||||||
|
if (enabled) {
|
||||||
|
setLocaleMode("auto")
|
||||||
|
navigateToLocale(detectLocale())
|
||||||
|
} else {
|
||||||
|
setPreferredLocale(locale)
|
||||||
|
setLocaleMode("manual")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header className="border-b bg-white/70 backdrop-blur-sm dark:border-slate-800 dark:bg-slate-950/80">
|
||||||
|
<Container className="flex h-16 items-center gap-4">
|
||||||
|
<BackButton />
|
||||||
|
<SlashLine />
|
||||||
|
<h1 className="text-xl font-semibold">{t(messages.settings)}</h1>
|
||||||
|
<div className="ml-auto">
|
||||||
|
<SearchTrigger />
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<Container className="py-8 sm:py-12">
|
||||||
|
<section aria-labelledby="appearance-heading">
|
||||||
|
<h2 id="appearance-heading" className="mb-4 text-xl font-semibold">
|
||||||
|
{t(messages.appearance)}
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-8 rounded-xl border bg-white/50 p-5 sm:p-8 dark:border-slate-800 dark:bg-slate-900/30">
|
||||||
|
<fieldset>
|
||||||
|
<legend className="mb-3">{t(messages.theme)}</legend>
|
||||||
|
<div
|
||||||
|
role="radiogroup"
|
||||||
|
aria-label={t(messages.theme)}
|
||||||
|
className="w-full space-y-1 rounded-xl border p-1 sm:w-fit sm:min-w-56 dark:border-slate-700"
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (
|
||||||
|
event.key !== "ArrowDown" &&
|
||||||
|
event.key !== "ArrowUp" &&
|
||||||
|
event.key !== "ArrowRight" &&
|
||||||
|
event.key !== "ArrowLeft" &&
|
||||||
|
event.key !== "Home" &&
|
||||||
|
event.key !== "End"
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
const options = Array.from(
|
||||||
|
event.currentTarget.querySelectorAll<HTMLButtonElement>(
|
||||||
|
'[role="radio"]'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
const currentIndex = options.indexOf(
|
||||||
|
document.activeElement as HTMLButtonElement
|
||||||
|
)
|
||||||
|
const moveForward =
|
||||||
|
event.key === "ArrowDown" || event.key === "ArrowRight"
|
||||||
|
let nextIndex = currentIndex
|
||||||
|
|
||||||
|
if (event.key === "Home") nextIndex = 0
|
||||||
|
else if (event.key === "End") nextIndex = options.length - 1
|
||||||
|
else if (moveForward) {
|
||||||
|
nextIndex = (currentIndex + 1) % options.length
|
||||||
|
} else {
|
||||||
|
nextIndex =
|
||||||
|
(currentIndex - 1 + options.length) % options.length
|
||||||
|
}
|
||||||
|
|
||||||
|
options[nextIndex]?.focus()
|
||||||
|
options[nextIndex]?.click()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{themeModes.map((mode) => {
|
||||||
|
const selected = appearance.themeMode === mode
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={mode}
|
||||||
|
type="button"
|
||||||
|
role="radio"
|
||||||
|
aria-checked={selected}
|
||||||
|
tabIndex={selected ? 0 : -1}
|
||||||
|
className="flex h-11 w-full cursor-pointer items-center gap-3 rounded-lg px-3 text-left transition-colors hover:bg-slate-100 focus-visible:outline-2 focus-visible:outline-indigo-500 aria-checked:bg-indigo-100 aria-checked:text-indigo-700 dark:hover:bg-slate-800 dark:aria-checked:bg-indigo-950 dark:aria-checked:text-indigo-300"
|
||||||
|
onClick={() =>
|
||||||
|
appearance.updateAppearance({ themeMode: mode })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ThemeIcon mode={mode} />
|
||||||
|
<span>{t(messages.themeModes[mode])}</span>
|
||||||
|
{selected && (
|
||||||
|
<Icon
|
||||||
|
name="tabler:check"
|
||||||
|
className="ml-auto size-4"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<ColorField
|
||||||
|
label={t(messages.accent)}
|
||||||
|
value={appearance.accentColor}
|
||||||
|
options={accentColors}
|
||||||
|
getColors={(accentColor) => ({
|
||||||
|
light: getPaletteColor(accentColor, 600),
|
||||||
|
dark: getPaletteColor(accentColor, 400),
|
||||||
|
})}
|
||||||
|
onChange={(accentColor) =>
|
||||||
|
appearance.updateAppearance({ accentColor })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ColorField
|
||||||
|
label={t(messages.background)}
|
||||||
|
value={appearance.backgroundShade}
|
||||||
|
options={backgroundShades}
|
||||||
|
getColors={(backgroundShade) => ({
|
||||||
|
light: getPaletteColor(backgroundShade, 50),
|
||||||
|
dark: getPaletteColor(backgroundShade, 950),
|
||||||
|
})}
|
||||||
|
onChange={(backgroundShade) =>
|
||||||
|
appearance.updateAppearance({ backgroundShade })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend className="mb-3">{t(messages.foreground)}</legend>
|
||||||
|
<div className="flex flex-wrap items-center gap-4">
|
||||||
|
{foregroundOptions.map((option) => (
|
||||||
|
<Swatch
|
||||||
|
key={option.value}
|
||||||
|
light={getPaletteColor(option.value, 950)}
|
||||||
|
dark={getPaletteColor(option.value, 50)}
|
||||||
|
aria-label={t(option.label)}
|
||||||
|
title={t(option.label)}
|
||||||
|
selected={appearance.foregroundShade === option.value}
|
||||||
|
onClick={() =>
|
||||||
|
appearance.updateAppearance({
|
||||||
|
foregroundShade: option.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
className="mt-10 sm:mt-12"
|
||||||
|
aria-labelledby="language-heading"
|
||||||
|
>
|
||||||
|
<h2 id="language-heading" className="mb-4 text-xl font-semibold">
|
||||||
|
{t(messages.language)}
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-8 rounded-xl border bg-white/50 p-5 sm:p-8 dark:border-slate-800 dark:bg-slate-900/30">
|
||||||
|
<fieldset>
|
||||||
|
<legend className="mb-3">{t(messages.language)}</legend>
|
||||||
|
<div className="w-full space-y-1 rounded-xl border p-1 sm:w-fit sm:min-w-48 dark:border-slate-700">
|
||||||
|
<LocaleLink
|
||||||
|
disabled={autoDetectLocale}
|
||||||
|
href={getLocalizedHref(window.location.pathname, "zh-Hans")}
|
||||||
|
label="简体中文"
|
||||||
|
locale="zh-Hans"
|
||||||
|
selected={locale === "zh-Hans"}
|
||||||
|
onClick={() => selectLocale("zh-Hans")}
|
||||||
|
/>
|
||||||
|
<LocaleLink
|
||||||
|
disabled={autoDetectLocale}
|
||||||
|
href={getLocalizedHref(window.location.pathname, "en-US")}
|
||||||
|
label="English"
|
||||||
|
locale="en-US"
|
||||||
|
selected={locale === "en-US"}
|
||||||
|
onClick={() => selectLocale("en-US")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div>{t(messages.autoDetect)}</div>
|
||||||
|
<label className="inline-flex w-fit cursor-pointer items-center gap-3">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="size-4 accent-indigo-600"
|
||||||
|
checked={autoDetectLocale}
|
||||||
|
onChange={(event) =>
|
||||||
|
setAutomaticLocale(event.currentTarget.checked)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span>{t(messages.enable)}</span>
|
||||||
|
</label>
|
||||||
|
<p className="text-sm text-(--docs-muted-light) dark:text-(--docs-muted-dark)">
|
||||||
|
{t(messages.autoDetectDescription)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</Container>
|
||||||
|
</main>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ColorField<T extends AccentColor | BackgroundShade>({
|
||||||
|
getColors,
|
||||||
|
label,
|
||||||
|
onChange,
|
||||||
|
options,
|
||||||
|
value,
|
||||||
|
}: {
|
||||||
|
getColors: (value: T) => { dark: string; light: string }
|
||||||
|
label: string
|
||||||
|
onChange: (value: T) => void
|
||||||
|
options: readonly T[]
|
||||||
|
value: T
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<fieldset>
|
||||||
|
<legend className="mb-3">{label}</legend>
|
||||||
|
<div className="flex flex-wrap items-center gap-4">
|
||||||
|
{options.map((option) => {
|
||||||
|
const colors = getColors(option)
|
||||||
|
const optionLabel = capitalize(option)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Swatch
|
||||||
|
key={option}
|
||||||
|
light={colors.light}
|
||||||
|
dark={colors.dark}
|
||||||
|
aria-label={optionLabel}
|
||||||
|
title={optionLabel}
|
||||||
|
selected={option === value}
|
||||||
|
onClick={() => onChange(option)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ThemeIcon({ mode }: { mode: ThemeMode }) {
|
||||||
|
if (mode === "light") {
|
||||||
|
return <Icon name="tabler:sun-high" className="size-5" />
|
||||||
|
}
|
||||||
|
if (mode === "dark") {
|
||||||
|
return <Icon name="tabler:moon" className="size-5" />
|
||||||
|
}
|
||||||
|
return <Icon name="tabler:device-desktop" className="size-5" />
|
||||||
|
}
|
||||||
|
|
||||||
|
function LocaleLink({
|
||||||
|
disabled,
|
||||||
|
href,
|
||||||
|
label,
|
||||||
|
locale,
|
||||||
|
onClick,
|
||||||
|
selected,
|
||||||
|
}: {
|
||||||
|
disabled: boolean
|
||||||
|
href: string
|
||||||
|
label: string
|
||||||
|
locale: DocLocale
|
||||||
|
onClick: () => void
|
||||||
|
selected: boolean
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={href}
|
||||||
|
hrefLang={locale}
|
||||||
|
lang={locale}
|
||||||
|
aria-disabled={disabled}
|
||||||
|
aria-current={selected ? "page" : undefined}
|
||||||
|
tabIndex={disabled ? -1 : undefined}
|
||||||
|
className="flex h-11 items-center gap-2 rounded-lg px-3 transition-colors hover:bg-slate-100 focus-visible:outline-2 focus-visible:outline-indigo-500 aria-disabled:cursor-not-allowed aria-disabled:opacity-45 aria-disabled:hover:bg-transparent aria-[current=page]:bg-indigo-100 aria-[current=page]:text-indigo-700 dark:hover:bg-slate-800 dark:aria-disabled:hover:bg-transparent dark:aria-[current=page]:bg-indigo-950 dark:aria-[current=page]:text-indigo-300"
|
||||||
|
onClick={(event) => {
|
||||||
|
if (disabled) {
|
||||||
|
event.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
onClick()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LocaleFlag locale={locale} className="size-5" />
|
||||||
|
<span>{label}</span>
|
||||||
|
{selected && <Icon name="tabler:check" className="ml-auto size-4" />}
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function capitalize(value: string) {
|
||||||
|
return value.charAt(0).toUpperCase() + value.slice(1)
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
declare module "*.mdx" {
|
||||||
|
import type { ComponentType, ElementType } from "react"
|
||||||
|
|
||||||
|
const MDXContent: ComponentType<{
|
||||||
|
components?: Record<string, ElementType>
|
||||||
|
}>
|
||||||
|
export const frontmatter: Record<string, unknown>
|
||||||
|
export default MDXContent
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||||
|
"target": "es2023",
|
||||||
|
"lib": ["ES2023", "DOM"],
|
||||||
|
"module": "esnext",
|
||||||
|
"types": ["vite/client"],
|
||||||
|
"allowArbitraryExtensions": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||||
|
"target": "es2023",
|
||||||
|
"lib": ["ES2023"],
|
||||||
|
"types": ["node"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"module": "nodenext",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"verbatimModuleSyntax": true,
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"erasableSyntaxOnly": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import react, { reactCompilerPreset } from "@vitejs/plugin-react"
|
||||||
|
import babel from "@rolldown/plugin-babel"
|
||||||
|
import tailwindcss from "@tailwindcss/vite"
|
||||||
|
import { icones } from "@icones/vite"
|
||||||
|
import { readFile } from "node:fs/promises"
|
||||||
|
import { fileURLToPath } from "node:url"
|
||||||
|
import { defineConfig, type Plugin } from "vite"
|
||||||
|
import satteri from "vite-plugin-satteri"
|
||||||
|
|
||||||
|
const packagesDirectory = fileURLToPath(new URL("../packages", import.meta.url))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vite 默认监听 docs 根目录。现有的外部 MDX 会作为模块被监听,但新建 package
|
||||||
|
* 或新建 MDX 文件在首次进入模块图之前不会触发 import.meta.glob 重新计算。
|
||||||
|
*/
|
||||||
|
function watchPackageDocs(): Plugin {
|
||||||
|
return {
|
||||||
|
name: "watch-package-docs",
|
||||||
|
configureServer(server) {
|
||||||
|
server.watcher.add(packagesDirectory)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadDocSearchSources(): Plugin {
|
||||||
|
const suffix = "?docs-search-raw"
|
||||||
|
const virtualPrefix = "\0docs-search-raw:"
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: "load-doc-search-sources",
|
||||||
|
enforce: "pre",
|
||||||
|
async resolveId(id, importer) {
|
||||||
|
if (!id.endsWith(suffix)) return
|
||||||
|
|
||||||
|
const sourceId = id.slice(0, -suffix.length)
|
||||||
|
const resolved = await this.resolve(sourceId, importer, {
|
||||||
|
skipSelf: true,
|
||||||
|
})
|
||||||
|
const filename = resolved?.id ?? sourceId
|
||||||
|
return `${virtualPrefix}${encodeURIComponent(filename)}.js`
|
||||||
|
},
|
||||||
|
async load(id) {
|
||||||
|
if (!id.startsWith(virtualPrefix)) return
|
||||||
|
|
||||||
|
const sourceId = decodeURIComponent(
|
||||||
|
id.slice(virtualPrefix.length, -".js".length)
|
||||||
|
)
|
||||||
|
const filename = sourceId.startsWith("/@fs/")
|
||||||
|
? sourceId.slice("/@fs".length)
|
||||||
|
: sourceId
|
||||||
|
this.addWatchFile(filename)
|
||||||
|
const source = await readFile(filename, "utf8")
|
||||||
|
return `export default ${JSON.stringify(source)}`
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://vite.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
watchPackageDocs(),
|
||||||
|
loadDocSearchSources(),
|
||||||
|
satteri({
|
||||||
|
features: {
|
||||||
|
frontmatter: true,
|
||||||
|
gfm: true,
|
||||||
|
headingAttributes: true,
|
||||||
|
},
|
||||||
|
mdx: {
|
||||||
|
jsxImportSource: "react",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
tailwindcss(),
|
||||||
|
icones({
|
||||||
|
mode: "symbol",
|
||||||
|
emitData: false,
|
||||||
|
}),
|
||||||
|
react(),
|
||||||
|
babel({ presets: [reactCompilerPreset()] }),
|
||||||
|
],
|
||||||
|
})
|
||||||
+2
-1
@@ -23,6 +23,7 @@
|
|||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*",
|
"apps/*",
|
||||||
|
"docs",
|
||||||
"packages/*"
|
"packages/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
title: Appearance
|
||||||
|
description: Finish the application with persistent theme, color, and compact-layout preferences.
|
||||||
|
order: 22
|
||||||
|
toc:
|
||||||
|
- id: provide-ui-state
|
||||||
|
title: Provide UI state
|
||||||
|
- id: apply-preferences
|
||||||
|
title: Apply preferences
|
||||||
|
- id: add-locales
|
||||||
|
title: Add locales
|
||||||
|
---
|
||||||
|
|
||||||
|
## Provide UI state {#provide-ui-state}
|
||||||
|
|
||||||
|
Mount `UiStateProvider` near the application root. A controlled provider can persist every state update through its change handler.
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<UiStateProvider>
|
||||||
|
<AppearanceController />
|
||||||
|
<App />
|
||||||
|
<ThemeToggleButton />
|
||||||
|
</UiStateProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Apply preferences {#apply-preferences}
|
||||||
|
|
||||||
|
Render `AppearanceController` once so the current state becomes document classes and theme variables. `useUiState` reads or updates individual preferences, while `useResolvedTheme` returns the effective light or dark scheme after resolving system mode.
|
||||||
|
|
||||||
|
## Add locales {#add-locales}
|
||||||
|
|
||||||
|
Add the appearance catalog only when the application uses these controls:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"catalogSources": ["@workspace/blocks/appearance/locales/{locale}"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The application shell is now complete. Add only the other block-specific catalogs used by the product.
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: Media library
|
||||||
|
description: Supply a storage adapter and add browsing, upload, folders, and asset selection.
|
||||||
|
order: 21
|
||||||
|
toc:
|
||||||
|
- id: implement-the-adapter
|
||||||
|
title: Implement the adapter
|
||||||
|
- id: provide-media
|
||||||
|
title: Provide media
|
||||||
|
- id: selection-flows
|
||||||
|
title: Selection flows
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implement the adapter {#implement-the-adapter}
|
||||||
|
|
||||||
|
`MediaAdapter` is the media feature's complete persistence boundary. Implement its query, upload, folder, update, and delete operations with the product's storage service.
|
||||||
|
|
||||||
|
## Provide media {#provide-media}
|
||||||
|
|
||||||
|
Mount the adapter once around the media surfaces:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { MediaLibrary, MediaProvider } from "@workspace/blocks/media"
|
||||||
|
|
||||||
|
;<MediaProvider adapter={mediaAdapter} notify={showNotice}>
|
||||||
|
<MediaLibrary />
|
||||||
|
</MediaProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
The optional `notify` callback translates operational results into the application's toast or notification system.
|
||||||
|
|
||||||
|
## Selection flows {#selection-flows}
|
||||||
|
|
||||||
|
Use `MediaPickerDialog` for single or multiple asset selection. `readMediaDimensions`, `formatMediaFileSize`, and `defaultMediaReference` cover the common presentation work around uploads and previews.
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: Notifications
|
||||||
|
description: Connect notification state without coupling the UI to a backend.
|
||||||
|
order: 20
|
||||||
|
toc:
|
||||||
|
- id: notifications-query
|
||||||
|
title: Notifications query
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notifications query {#notifications-query}
|
||||||
|
|
||||||
|
Notifications use TanStack Query as their data boundary:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const notifications = useNotifications({
|
||||||
|
queryKey: ["notifications"],
|
||||||
|
queryFn: loadNotifications,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The result includes unread counts, optimistic read-state updates, action execution, refetching, and pending or error status. `AppLayout` can create the sheet directly from the same query options.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: Chats
|
||||||
|
description: Add a responsive conversation workspace and connect its events to application services.
|
||||||
|
order: 30
|
||||||
|
toc:
|
||||||
|
- id: render-the-workspace
|
||||||
|
title: Render the workspace
|
||||||
|
- id: controlled-state
|
||||||
|
title: Controlled state
|
||||||
|
- id: media-and-pagination
|
||||||
|
title: Media and pagination
|
||||||
|
---
|
||||||
|
|
||||||
|
## Render the workspace {#render-the-workspace}
|
||||||
|
|
||||||
|
`ChatWorkspace` renders conversation discovery, the active thread, and the composer:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ChatWorkspace } from "@workspace/blocks/chats"
|
||||||
|
|
||||||
|
;<ChatWorkspace
|
||||||
|
conversations={conversations}
|
||||||
|
onSend={({ conversation, message }) => sendMessage(conversation, message)}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Controlled state {#controlled-state}
|
||||||
|
|
||||||
|
The active conversation, draft, search query, and Enter-to-send preference can be controlled individually. Leave a value undefined when the workspace should own that state.
|
||||||
|
|
||||||
|
The UI emits events but does not select a transport or persistence format. Map API responses into `ChatConversation` and the exported message variants at the application boundary.
|
||||||
|
|
||||||
|
## Media and pagination {#media-and-pagination}
|
||||||
|
|
||||||
|
Provide `resolveMediaUrl` when stored media references need signed or transformed URLs. Use `onLoadEarlierMessages` with `hasMoreMessages` and `isLoadingMoreMessages` to connect historical pagination.
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
title: Application shell
|
||||||
|
description: Assemble the shared header, sidebar, breadcrumbs, chat, and notification surfaces.
|
||||||
|
order: 11
|
||||||
|
toc:
|
||||||
|
- id: render-app-layout
|
||||||
|
title: Render AppLayout
|
||||||
|
- id: layout-inputs
|
||||||
|
title: Layout inputs
|
||||||
|
- id: optional-preset
|
||||||
|
title: Optional preset
|
||||||
|
---
|
||||||
|
|
||||||
|
## Render AppLayout {#render-app-layout}
|
||||||
|
|
||||||
|
`AppLayout` is the integration point for the rest of this tutorial:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppLayout } from "@workspace/blocks/layout"
|
||||||
|
|
||||||
|
export function WorkspaceLayout() {
|
||||||
|
return (
|
||||||
|
<AppLayout
|
||||||
|
navigationGroups={navigationGroups}
|
||||||
|
notifications={{
|
||||||
|
queryKey: ["notifications"],
|
||||||
|
queryFn: loadNotifications,
|
||||||
|
}}
|
||||||
|
chatThreads={chatThreads}
|
||||||
|
>
|
||||||
|
<Outlet />
|
||||||
|
</AppLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Layout inputs {#layout-inputs}
|
||||||
|
|
||||||
|
The shell composes `AppSidebar`, `AppBreadcrumb`, `AppQueryIndicator`, `UserMenu`, a notification sheet, and chat threads. Pass `headerActions` when the product needs additional global controls.
|
||||||
|
|
||||||
|
The route content remains the layout's `children`, so the package does not constrain the router used by the application.
|
||||||
|
|
||||||
|
## Optional preset {#optional-preset}
|
||||||
|
|
||||||
|
`@workspace/blocks/layouts/vega` provides an optional visual shell. It lives on a separate entry point so the standard layout does not include preset-specific code.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
title: Installation
|
||||||
|
description: Add the package, its styles, and the providers required by the tutorial.
|
||||||
|
order: 10
|
||||||
|
toc:
|
||||||
|
- id: add-the-package
|
||||||
|
title: Add the package
|
||||||
|
- id: import-styles
|
||||||
|
title: Import styles
|
||||||
|
- id: application-providers
|
||||||
|
title: Application providers
|
||||||
|
---
|
||||||
|
|
||||||
|
## Add the package {#add-the-package}
|
||||||
|
|
||||||
|
Add the workspace dependency to the consuming application:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@workspace/blocks": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Blocks use `@workspace/ui`, React Query, and the workspace internationalization runtime. The workspace package manager resolves those dependencies for local applications.
|
||||||
|
|
||||||
|
## Import styles {#import-styles}
|
||||||
|
|
||||||
|
Import the block stylesheet once from the application entry:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import "@workspace/blocks/globals.css"
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep feature imports on their explicit subpaths. For example, importing `@workspace/blocks/media` does not pull chat into the same module graph.
|
||||||
|
|
||||||
|
## Application providers {#application-providers}
|
||||||
|
|
||||||
|
The full shell expects React Query and internationalization to be available above it. Add those providers before the route tree, then continue to the application-shell chapter.
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
title: Navigation
|
||||||
|
description: Define navigation groups once and connect them to desktop and mobile surfaces.
|
||||||
|
order: 12
|
||||||
|
toc:
|
||||||
|
- id: define-groups
|
||||||
|
title: Define groups
|
||||||
|
- id: provide-navigation
|
||||||
|
title: Provide navigation
|
||||||
|
- id: route-state
|
||||||
|
title: Route state
|
||||||
|
---
|
||||||
|
|
||||||
|
## Define groups {#define-groups}
|
||||||
|
|
||||||
|
Start with typed `NavigationGroup` values. Items may represent direct routes or nested navigation branches.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { NavigationGroup } from "@workspace/blocks/navigation"
|
||||||
|
|
||||||
|
export const navigationGroups: NavigationGroup[] = [
|
||||||
|
{
|
||||||
|
id: "workspace",
|
||||||
|
label: "Workspace",
|
||||||
|
items: [
|
||||||
|
{ id: "dashboard", label: "Dashboard", to: "/dashboard" },
|
||||||
|
{ id: "media", label: "Media", to: "/media" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Provide navigation {#provide-navigation}
|
||||||
|
|
||||||
|
`AppLayout` already mounts the provider and the responsive navigation surfaces. For a custom shell, compose them directly:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<NavigationProvider groups={navigationGroups}>
|
||||||
|
<PrimaryNavigation groups={navigationGroups} />
|
||||||
|
<MobileNavigationSheet groups={navigationGroups} />
|
||||||
|
</NavigationProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Route state {#route-state}
|
||||||
|
|
||||||
|
Use `resolveNavigationRouteState` for the standard route model. Applications with custom routing can supply a `GetNavigationRouteState` implementation while keeping the same navigation UI.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
title: Overview
|
||||||
|
description: Understand how the Blocks package turns UI primitives into complete application features.
|
||||||
|
order: 1
|
||||||
|
toc:
|
||||||
|
- id: what-you-will-build
|
||||||
|
title: What you will build
|
||||||
|
- id: design-boundary
|
||||||
|
title: Design boundary
|
||||||
|
- id: tutorial-map
|
||||||
|
title: Tutorial map
|
||||||
|
---
|
||||||
|
|
||||||
|
## What you will build {#what-you-will-build}
|
||||||
|
|
||||||
|
This tutorial builds an application shell step by step. You will begin with the shared layout, connect navigation, then add notifications, chat, media, and appearance preferences.
|
||||||
|
|
||||||
|
By the end, the application owns its data and business rules while `@workspace/blocks` owns the reusable presentation and interaction patterns.
|
||||||
|
|
||||||
|
## Design boundary {#design-boundary}
|
||||||
|
|
||||||
|
Blocks sit above `@workspace/ui`. They combine low-level components into features, but they do not choose your API, database, router configuration, or storage provider.
|
||||||
|
|
||||||
|
> Keep data access in the host application. Pass it into a block through props, query functions, providers, or adapters.
|
||||||
|
|
||||||
|
## Tutorial map {#tutorial-map}
|
||||||
|
|
||||||
|
1. Install the package and global styles.
|
||||||
|
2. Create the application shell.
|
||||||
|
3. Define navigation and route state.
|
||||||
|
4. Connect notifications.
|
||||||
|
5. Add chat and media workflows.
|
||||||
|
6. Finish with persistent appearance controls.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
title: 外观设置
|
||||||
|
description: 使用可持久化的主题、颜色和紧凑布局偏好完成应用。
|
||||||
|
order: 22
|
||||||
|
toc:
|
||||||
|
- id: provide-ui-state
|
||||||
|
title: 提供 UI 状态
|
||||||
|
- id: apply-preferences
|
||||||
|
title: 应用偏好
|
||||||
|
- id: add-locales
|
||||||
|
title: 添加词典
|
||||||
|
---
|
||||||
|
|
||||||
|
## 提供 UI 状态 {#provide-ui-state}
|
||||||
|
|
||||||
|
在应用根节点附近挂载 `UiStateProvider`。受控 Provider 可以通过变更处理器持久化每次状态更新。
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<UiStateProvider>
|
||||||
|
<AppearanceController />
|
||||||
|
<App />
|
||||||
|
<ThemeToggleButton />
|
||||||
|
</UiStateProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 应用偏好 {#apply-preferences}
|
||||||
|
|
||||||
|
渲染一次 `AppearanceController`,使当前状态转换为文档类名和主题变量。`useUiState` 读取或更新单个偏好,`useResolvedTheme` 在解析系统模式后返回最终的亮色或暗色主题。
|
||||||
|
|
||||||
|
## 添加词典 {#add-locales}
|
||||||
|
|
||||||
|
只有应用使用这些控件时才添加外观词典:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"catalogSources": ["@workspace/blocks/appearance/locales/{locale}"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
至此应用外壳已经完成。其他功能也只需添加产品实际使用的 Block 词典。
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
title: 媒体库
|
||||||
|
description: 提供存储 Adapter,并加入浏览、上传、文件夹和资源选择能力。
|
||||||
|
order: 21
|
||||||
|
toc:
|
||||||
|
- id: implement-the-adapter
|
||||||
|
title: 实现 Adapter
|
||||||
|
- id: provide-media
|
||||||
|
title: 提供媒体能力
|
||||||
|
- id: selection-flows
|
||||||
|
title: 选择流程
|
||||||
|
---
|
||||||
|
|
||||||
|
## 实现 Adapter {#implement-the-adapter}
|
||||||
|
|
||||||
|
`MediaAdapter` 是媒体功能完整的持久化边界。通过产品存储服务实现查询、上传、文件夹、更新和删除操作。
|
||||||
|
|
||||||
|
## 提供媒体能力 {#provide-media}
|
||||||
|
|
||||||
|
在媒体界面外挂载一次 Adapter:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { MediaLibrary, MediaProvider } from "@workspace/blocks/media"
|
||||||
|
|
||||||
|
;<MediaProvider adapter={mediaAdapter} notify={showNotice}>
|
||||||
|
<MediaLibrary />
|
||||||
|
</MediaProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
可选的 `notify` 回调把操作结果转换为应用的 Toast 或通知。
|
||||||
|
|
||||||
|
## 选择流程 {#selection-flows}
|
||||||
|
|
||||||
|
单选或多选资源使用 `MediaPickerDialog`。`readMediaDimensions`、`formatMediaFileSize` 和 `defaultMediaReference` 覆盖上传与预览相关的常用展示工作。
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
title: 通知
|
||||||
|
description: 接入通知状态,同时避免让 UI 与后端耦合。
|
||||||
|
order: 20
|
||||||
|
toc:
|
||||||
|
- id: notifications-query
|
||||||
|
title: 通知查询
|
||||||
|
---
|
||||||
|
|
||||||
|
## 通知查询 {#notifications-query}
|
||||||
|
|
||||||
|
通知以 TanStack Query 作为数据边界:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
const notifications = useNotifications({
|
||||||
|
queryKey: ["notifications"],
|
||||||
|
queryFn: loadNotifications,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
返回结果包含未读数量、乐观已读更新、操作执行、重新请求以及等待和错误状态。`AppLayout` 可以直接通过相同查询选项创建通知 Sheet。
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
title: 聊天示例
|
||||||
|
description: 添加响应式会话工作区,并将事件连接到应用服务。
|
||||||
|
order: 30
|
||||||
|
toc:
|
||||||
|
- id: render-the-workspace
|
||||||
|
title: 渲染工作区
|
||||||
|
- id: controlled-state
|
||||||
|
title: 受控状态
|
||||||
|
- id: media-and-pagination
|
||||||
|
title: 媒体与分页
|
||||||
|
---
|
||||||
|
|
||||||
|
## 渲染工作区 {#render-the-workspace}
|
||||||
|
|
||||||
|
`ChatWorkspace` 渲染会话查找、当前线程和消息编辑器:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { ChatWorkspace } from "@workspace/blocks/chats"
|
||||||
|
|
||||||
|
;<ChatWorkspace
|
||||||
|
conversations={conversations}
|
||||||
|
onSend={({ conversation, message }) => sendMessage(conversation, message)}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 受控状态 {#controlled-state}
|
||||||
|
|
||||||
|
当前会话、草稿、搜索词和回车发送偏好都可以单独受控。当工作区应自行管理某项状态时,不传对应值即可。
|
||||||
|
|
||||||
|
UI 只发送事件,不选择传输方式或持久化格式。在应用边界将 API 响应转换为 `ChatConversation` 和导出的消息类型。
|
||||||
|
|
||||||
|
## 媒体与分页 {#media-and-pagination}
|
||||||
|
|
||||||
|
当已存储媒体需要签名或转换 URL 时,提供 `resolveMediaUrl`。使用 `onLoadEarlierMessages`、`hasMoreMessages` 和 `isLoadingMoreMessages` 接入历史消息分页。
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
title: 应用外壳
|
||||||
|
description: 组装共享 Header、Sidebar、面包屑、聊天和通知界面。
|
||||||
|
order: 11
|
||||||
|
toc:
|
||||||
|
- id: render-app-layout
|
||||||
|
title: 渲染 AppLayout
|
||||||
|
- id: layout-inputs
|
||||||
|
title: 布局输入
|
||||||
|
- id: optional-preset
|
||||||
|
title: 可选预设
|
||||||
|
---
|
||||||
|
|
||||||
|
## 渲染 AppLayout {#render-app-layout}
|
||||||
|
|
||||||
|
`AppLayout` 是本教程其余部分的集成点:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
import { AppLayout } from "@workspace/blocks/layout"
|
||||||
|
|
||||||
|
export function WorkspaceLayout() {
|
||||||
|
return (
|
||||||
|
<AppLayout
|
||||||
|
navigationGroups={navigationGroups}
|
||||||
|
notifications={{
|
||||||
|
queryKey: ["notifications"],
|
||||||
|
queryFn: loadNotifications,
|
||||||
|
}}
|
||||||
|
chatThreads={chatThreads}
|
||||||
|
>
|
||||||
|
<Outlet />
|
||||||
|
</AppLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 布局输入 {#layout-inputs}
|
||||||
|
|
||||||
|
应用外壳组合了 `AppSidebar`、`AppBreadcrumb`、`AppQueryIndicator`、`UserMenu`、通知 Sheet 和聊天线程。产品需要更多全局控件时可传入 `headerActions`。
|
||||||
|
|
||||||
|
路由内容仍作为布局的 `children`,因此该包不会限制应用使用的路由器。
|
||||||
|
|
||||||
|
## 可选预设 {#optional-preset}
|
||||||
|
|
||||||
|
`@workspace/blocks/layouts/vega` 提供可选的视觉外壳。它位于独立入口,因此标准布局不会包含预设专属代码。
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
title: 安装
|
||||||
|
description: 添加教程所需的包、样式和 Providers。
|
||||||
|
order: 10
|
||||||
|
toc:
|
||||||
|
- id: add-the-package
|
||||||
|
title: 添加包
|
||||||
|
- id: import-styles
|
||||||
|
title: 导入样式
|
||||||
|
- id: application-providers
|
||||||
|
title: 应用 Providers
|
||||||
|
---
|
||||||
|
|
||||||
|
## 添加包 {#add-the-package}
|
||||||
|
|
||||||
|
在使用方应用中添加工作区依赖:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@workspace/blocks": "workspace:*"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Blocks 使用 `@workspace/ui`、React Query 和工作区国际化运行时。工作区包管理器会为本地应用解析这些依赖。
|
||||||
|
|
||||||
|
## 导入样式 {#import-styles}
|
||||||
|
|
||||||
|
在应用入口导入一次 Block 样式:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import "@workspace/blocks/globals.css"
|
||||||
|
```
|
||||||
|
|
||||||
|
功能模块应始终从显式子路径导入。例如,导入 `@workspace/blocks/media` 不会把聊天功能加入同一个模块图。
|
||||||
|
|
||||||
|
## 应用 Providers {#application-providers}
|
||||||
|
|
||||||
|
完整应用外壳要求上层已经提供 React Query 和国际化。在路由树之前加入这些 Providers,然后继续应用外壳章节。
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
title: 导航
|
||||||
|
description: 统一定义导航分组,并将其连接到桌面和移动端界面。
|
||||||
|
order: 12
|
||||||
|
toc:
|
||||||
|
- id: define-groups
|
||||||
|
title: 定义分组
|
||||||
|
- id: provide-navigation
|
||||||
|
title: 提供导航
|
||||||
|
- id: route-state
|
||||||
|
title: 路由状态
|
||||||
|
---
|
||||||
|
|
||||||
|
## 定义分组 {#define-groups}
|
||||||
|
|
||||||
|
从类型安全的 `NavigationGroup` 开始。导航项可以是直接路由,也可以是嵌套导航分支。
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { NavigationGroup } from "@workspace/blocks/navigation"
|
||||||
|
|
||||||
|
export const navigationGroups: NavigationGroup[] = [
|
||||||
|
{
|
||||||
|
id: "workspace",
|
||||||
|
label: "工作区",
|
||||||
|
items: [
|
||||||
|
{ id: "dashboard", label: "仪表盘", to: "/dashboard" },
|
||||||
|
{ id: "media", label: "媒体", to: "/media" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 提供导航 {#provide-navigation}
|
||||||
|
|
||||||
|
`AppLayout` 已经挂载 Provider 和响应式导航界面。自定义外壳可以直接组合它们:
|
||||||
|
|
||||||
|
```tsx
|
||||||
|
<NavigationProvider groups={navigationGroups}>
|
||||||
|
<PrimaryNavigation groups={navigationGroups} />
|
||||||
|
<MobileNavigationSheet groups={navigationGroups} />
|
||||||
|
</NavigationProvider>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 路由状态 {#route-state}
|
||||||
|
|
||||||
|
标准路由模型使用 `resolveNavigationRouteState`。使用自定义路由的应用可以提供 `GetNavigationRouteState` 实现,同时复用相同导航 UI。
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
title: 概览
|
||||||
|
description: 了解 Blocks 包如何把 UI 基础组件组合成完整应用功能。
|
||||||
|
order: 1
|
||||||
|
toc:
|
||||||
|
- id: what-you-will-build
|
||||||
|
title: 将要构建的内容
|
||||||
|
- id: design-boundary
|
||||||
|
title: 设计边界
|
||||||
|
- id: tutorial-map
|
||||||
|
title: 教程路线
|
||||||
|
---
|
||||||
|
|
||||||
|
## 将要构建的内容 {#what-you-will-build}
|
||||||
|
|
||||||
|
本教程会逐步构建一个应用外壳。你将从共享布局开始,接入导航,再添加通知、聊天、媒体和外观偏好。
|
||||||
|
|
||||||
|
完成后,应用负责数据和业务规则,`@workspace/blocks` 负责可复用的展示与交互模式。
|
||||||
|
|
||||||
|
## 设计边界 {#design-boundary}
|
||||||
|
|
||||||
|
Blocks 位于 `@workspace/ui` 之上。它们将底层组件组合成完整功能,但不会替你选择 API、数据库、路由配置或存储服务。
|
||||||
|
|
||||||
|
> 将数据访问保留在宿主应用中,通过属性、查询函数、Provider 或 Adapter 传给 Block。
|
||||||
|
|
||||||
|
## 教程路线 {#tutorial-map}
|
||||||
|
|
||||||
|
1. 安装包和全局样式。
|
||||||
|
2. 创建应用外壳。
|
||||||
|
3. 定义导航和路由状态。
|
||||||
|
4. 接入通知。
|
||||||
|
5. 添加聊天和媒体工作流。
|
||||||
|
6. 使用持久化外观控件完成应用。
|
||||||
@@ -11,14 +11,14 @@
|
|||||||
"@base-ui/react": "^1.6.0",
|
"@base-ui/react": "^1.6.0",
|
||||||
"@base-ui/utils": "^0.3.1",
|
"@base-ui/utils": "^0.3.1",
|
||||||
"@floating-ui/utils": "^0.2.12",
|
"@floating-ui/utils": "^0.2.12",
|
||||||
|
"@icones/react": "^0.0.1",
|
||||||
|
"@lexical/react": "^0.48.0",
|
||||||
"@tanstack/react-hotkeys": "^0.10.0",
|
"@tanstack/react-hotkeys": "^0.10.0",
|
||||||
"@tanstack/react-query": "^5.101.4",
|
"@tanstack/react-query": "^5.101.4",
|
||||||
"@tanstack/react-router": "^1.170.18",
|
"@tanstack/react-router": "^1.170.18",
|
||||||
"@workspace/icons": "workspace:*",
|
|
||||||
"@workspace/i18n": "workspace:*",
|
"@workspace/i18n": "workspace:*",
|
||||||
"@workspace/ui": "workspace:*",
|
"@workspace/ui": "workspace:*",
|
||||||
"cmdk": "^1.1.1",
|
"lexical": "^0.48.0",
|
||||||
"lucide-react": "^1.27.0",
|
|
||||||
"react": "^19.2.6",
|
"react": "^19.2.6",
|
||||||
"react-dom": "^19.2.6"
|
"react-dom": "^19.2.6"
|
||||||
},
|
},
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
"./layout": "./src/blocks/layout/index.ts",
|
"./layout": "./src/blocks/layout/index.ts",
|
||||||
"./layout/locales": "./src/blocks/layout/locales/catalogs.ts",
|
"./layout/locales": "./src/blocks/layout/locales/catalogs.ts",
|
||||||
"./layout/locales/*": "./src/blocks/layout/locales/*.ts",
|
"./layout/locales/*": "./src/blocks/layout/locales/*.ts",
|
||||||
|
"./layouts/vega": "./src/blocks/layouts/vega/index.tsx",
|
||||||
"./media": "./src/blocks/media/index.ts",
|
"./media": "./src/blocks/media/index.ts",
|
||||||
"./media/locales": "./src/blocks/media/locales/catalogs.ts",
|
"./media/locales": "./src/blocks/media/locales/catalogs.ts",
|
||||||
"./media/locales/*": "./src/blocks/media/locales/*.ts",
|
"./media/locales/*": "./src/blocks/media/locales/*.ts",
|
||||||
@@ -52,9 +53,6 @@
|
|||||||
"./navigation/locales/*": "./src/blocks/navigation/locales/*.ts",
|
"./navigation/locales/*": "./src/blocks/navigation/locales/*.ts",
|
||||||
"./notifications": "./src/blocks/notifications/index.ts",
|
"./notifications": "./src/blocks/notifications/index.ts",
|
||||||
"./notifications/locales": "./src/blocks/notifications/locales/catalogs.ts",
|
"./notifications/locales": "./src/blocks/notifications/locales/catalogs.ts",
|
||||||
"./notifications/locales/*": "./src/blocks/notifications/locales/*.ts",
|
"./notifications/locales/*": "./src/blocks/notifications/locales/*.ts"
|
||||||
"./search": "./src/blocks/search/index.ts",
|
|
||||||
"./search/locales": "./src/blocks/search/locales/catalogs.ts",
|
|
||||||
"./search/locales/*": "./src/blocks/search/locales/*.ts"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
export { appearanceDialogHandle, AppearanceTrigger } from "./dialog"
|
export { appearanceDialogHandle, AppearanceTrigger } from "./dialog"
|
||||||
export { AppearanceController } from "./controller"
|
export { AppearanceController } from "./controller"
|
||||||
|
export { ThemeToggleButton } from "./theme-toggle-button"
|
||||||
export {
|
export {
|
||||||
UiStateProvider,
|
UiStateProvider,
|
||||||
type UiStateProviderProps,
|
type UiStateProviderProps,
|
||||||
|
|||||||
@@ -3,27 +3,15 @@ import { describe, it } from "vitest"
|
|||||||
import { expectCompleteCatalogs } from "../../../i18n/test-catalogs"
|
import { expectCompleteCatalogs } from "../../../i18n/test-catalogs"
|
||||||
import { appearanceMessages, themeColorMessages } from "../messages"
|
import { appearanceMessages, themeColorMessages } from "../messages"
|
||||||
import { appearanceCatalogLocales } from "./catalogs"
|
import { appearanceCatalogLocales } from "./catalogs"
|
||||||
import { messages as de } from "./de"
|
import { messages as enUS } from "./en-US"
|
||||||
import { messages as en } from "./en"
|
|
||||||
import { messages as es } from "./es"
|
|
||||||
import { messages as fr } from "./fr"
|
|
||||||
import { messages as ja } from "./ja"
|
|
||||||
import { messages as ko } from "./ko"
|
|
||||||
import { messages as zhHans } from "./zh-Hans"
|
import { messages as zhHans } from "./zh-Hans"
|
||||||
import { messages as zhHant } from "./zh-Hant"
|
|
||||||
|
|
||||||
describe("appearance locale catalogs", () => {
|
describe("appearance locale catalogs", () => {
|
||||||
it("ship every appearance message in every built-in locale", () => {
|
it("ship every appearance message in every built-in locale", () => {
|
||||||
expectCompleteCatalogs({
|
expectCompleteCatalogs({
|
||||||
catalogs: {
|
catalogs: {
|
||||||
de,
|
"en-US": enUS,
|
||||||
en,
|
|
||||||
es,
|
|
||||||
fr,
|
|
||||||
ja,
|
|
||||||
ko,
|
|
||||||
"zh-Hans": zhHans,
|
"zh-Hans": zhHans,
|
||||||
"zh-Hant": zhHant,
|
|
||||||
},
|
},
|
||||||
locales: appearanceCatalogLocales,
|
locales: appearanceCatalogLocales,
|
||||||
messageIds: [
|
messageIds: [
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
import type { AppearanceMessageCatalog } from "./catalogs"
|
|
||||||
|
|
||||||
export const locale = "de"
|
|
||||||
export const languageTag = "de-DE"
|
|
||||||
|
|
||||||
export const messages = {
|
|
||||||
"blocks.appearance.active": "Aktiv",
|
|
||||||
"blocks.appearance.baseColor": "Basisfarbe",
|
|
||||||
"blocks.appearance.color.amber": "Bernstein",
|
|
||||||
"blocks.appearance.color.blue": "Blau",
|
|
||||||
"blocks.appearance.color.cyan": "Cyan",
|
|
||||||
"blocks.appearance.color.emerald": "Smaragd",
|
|
||||||
"blocks.appearance.color.fuchsia": "Fuchsia",
|
|
||||||
"blocks.appearance.color.green": "Grün",
|
|
||||||
"blocks.appearance.color.indigo": "Indigo",
|
|
||||||
"blocks.appearance.color.lime": "Limette",
|
|
||||||
"blocks.appearance.color.mauve": "Malve",
|
|
||||||
"blocks.appearance.color.mist": "Nebel",
|
|
||||||
"blocks.appearance.color.neutral": "Neutral",
|
|
||||||
"blocks.appearance.color.olive": "Oliv",
|
|
||||||
"blocks.appearance.color.orange": "Orange",
|
|
||||||
"blocks.appearance.color.pink": "Rosa",
|
|
||||||
"blocks.appearance.color.purple": "Lila",
|
|
||||||
"blocks.appearance.color.red": "Rot",
|
|
||||||
"blocks.appearance.color.rose": "Rose",
|
|
||||||
"blocks.appearance.color.sky": "Himmelblau",
|
|
||||||
"blocks.appearance.color.stone": "Stein",
|
|
||||||
"blocks.appearance.color.taupe": "Taupe",
|
|
||||||
"blocks.appearance.color.teal": "Blaugrün",
|
|
||||||
"blocks.appearance.color.violet": "Violett",
|
|
||||||
"blocks.appearance.color.yellow": "Gelb",
|
|
||||||
"blocks.appearance.color.zinc": "Zink",
|
|
||||||
"blocks.appearance.command.description":
|
|
||||||
"Design- und Layout-Einstellungen öffnen",
|
|
||||||
"blocks.appearance.compact.description":
|
|
||||||
"Eine kompakte Breite für den Hauptinhalt verwenden",
|
|
||||||
"blocks.appearance.compact.title": "Kompaktes Layout",
|
|
||||||
"blocks.appearance.description": "Design- und Layout-Einstellungen",
|
|
||||||
"blocks.appearance.mode.dark": "Dunkel",
|
|
||||||
"blocks.appearance.mode.dark.description":
|
|
||||||
"Die Oberfläche verwendet immer das dunkle Design",
|
|
||||||
"blocks.appearance.mode.light": "Hell",
|
|
||||||
"blocks.appearance.mode.light.description":
|
|
||||||
"Die Oberfläche verwendet immer das helle Design",
|
|
||||||
"blocks.appearance.mode.system": "System",
|
|
||||||
"blocks.appearance.mode.system.description":
|
|
||||||
"Das Design der Oberfläche folgt der Systemeinstellung",
|
|
||||||
"blocks.appearance.mode.title": "Darstellungsmodus",
|
|
||||||
"blocks.appearance.primaryColor": "Primärfarbe",
|
|
||||||
"blocks.appearance.theme.dark": "Dunkles Design",
|
|
||||||
"blocks.appearance.theme.dark.description":
|
|
||||||
"Dieses Design wird im dunklen Systemmodus verwendet",
|
|
||||||
"blocks.appearance.theme.light": "Helles Design",
|
|
||||||
"blocks.appearance.theme.light.description":
|
|
||||||
"Dieses Design wird im hellen Systemmodus verwendet",
|
|
||||||
"blocks.appearance.title": "Darstellung",
|
|
||||||
"blocks.appearance.toggleTheme": "Design wechseln",
|
|
||||||
"blocks.appearance.toggleTheme.description":
|
|
||||||
"Zwischen hellem und dunklem Design wechseln",
|
|
||||||
} as const satisfies AppearanceMessageCatalog
|
|
||||||
+1
-1
@@ -3,7 +3,7 @@ import type { MessageDescriptor } from "@workspace/i18n"
|
|||||||
import { appearanceMessages, themeColorMessages } from "../messages.ts"
|
import { appearanceMessages, themeColorMessages } from "../messages.ts"
|
||||||
import type { AppearanceMessageCatalog } from "./catalogs"
|
import type { AppearanceMessageCatalog } from "./catalogs"
|
||||||
|
|
||||||
export const locale = "en"
|
export const locale = "en-US"
|
||||||
export const languageTag = "en-US"
|
export const languageTag = "en-US"
|
||||||
|
|
||||||
function createSourceCatalog(
|
function createSourceCatalog(
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
import type { AppearanceMessageCatalog } from "./catalogs"
|
|
||||||
|
|
||||||
export const locale = "es"
|
|
||||||
export const languageTag = "es-ES"
|
|
||||||
|
|
||||||
export const messages = {
|
|
||||||
"blocks.appearance.active": "Activo",
|
|
||||||
"blocks.appearance.baseColor": "Color base",
|
|
||||||
"blocks.appearance.color.amber": "Ámbar",
|
|
||||||
"blocks.appearance.color.blue": "Azul",
|
|
||||||
"blocks.appearance.color.cyan": "Cian",
|
|
||||||
"blocks.appearance.color.emerald": "Esmeralda",
|
|
||||||
"blocks.appearance.color.fuchsia": "Fucsia",
|
|
||||||
"blocks.appearance.color.green": "Verde",
|
|
||||||
"blocks.appearance.color.indigo": "Índigo",
|
|
||||||
"blocks.appearance.color.lime": "Lima",
|
|
||||||
"blocks.appearance.color.mauve": "Malva",
|
|
||||||
"blocks.appearance.color.mist": "Niebla",
|
|
||||||
"blocks.appearance.color.neutral": "Neutro",
|
|
||||||
"blocks.appearance.color.olive": "Oliva",
|
|
||||||
"blocks.appearance.color.orange": "Naranja",
|
|
||||||
"blocks.appearance.color.pink": "Rosa",
|
|
||||||
"blocks.appearance.color.purple": "Morado",
|
|
||||||
"blocks.appearance.color.red": "Rojo",
|
|
||||||
"blocks.appearance.color.rose": "Rosa intenso",
|
|
||||||
"blocks.appearance.color.sky": "Celeste",
|
|
||||||
"blocks.appearance.color.stone": "Piedra",
|
|
||||||
"blocks.appearance.color.taupe": "Topo",
|
|
||||||
"blocks.appearance.color.teal": "Verde azulado",
|
|
||||||
"blocks.appearance.color.violet": "Violeta",
|
|
||||||
"blocks.appearance.color.yellow": "Amarillo",
|
|
||||||
"blocks.appearance.color.zinc": "Zinc",
|
|
||||||
"blocks.appearance.command.description":
|
|
||||||
"Abrir las preferencias de tema y diseño",
|
|
||||||
"blocks.appearance.compact.description":
|
|
||||||
"Usar un ancho compacto para el contenido principal",
|
|
||||||
"blocks.appearance.compact.title": "Diseño compacto",
|
|
||||||
"blocks.appearance.description": "Preferencias de tema y diseño",
|
|
||||||
"blocks.appearance.mode.dark": "Oscuro",
|
|
||||||
"blocks.appearance.mode.dark.description":
|
|
||||||
"La interfaz siempre usará el tema oscuro",
|
|
||||||
"blocks.appearance.mode.light": "Claro",
|
|
||||||
"blocks.appearance.mode.light.description":
|
|
||||||
"La interfaz siempre usará el tema claro",
|
|
||||||
"blocks.appearance.mode.system": "Sistema",
|
|
||||||
"blocks.appearance.mode.system.description":
|
|
||||||
"El tema de la interfaz seguirá la apariencia del sistema",
|
|
||||||
"blocks.appearance.mode.title": "Modo de tema",
|
|
||||||
"blocks.appearance.primaryColor": "Color principal",
|
|
||||||
"blocks.appearance.theme.dark": "Tema oscuro",
|
|
||||||
"blocks.appearance.theme.dark.description":
|
|
||||||
"Este tema se usa cuando el sistema está en modo oscuro",
|
|
||||||
"blocks.appearance.theme.light": "Tema claro",
|
|
||||||
"blocks.appearance.theme.light.description":
|
|
||||||
"Este tema se usa cuando el sistema está en modo claro",
|
|
||||||
"blocks.appearance.title": "Apariencia",
|
|
||||||
"blocks.appearance.toggleTheme": "Cambiar tema",
|
|
||||||
"blocks.appearance.toggleTheme.description":
|
|
||||||
"Cambiar entre los temas claro y oscuro",
|
|
||||||
} as const satisfies AppearanceMessageCatalog
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user