feat(docs): add bilingual package documentation site
This commit is contained in:
@@ -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. 使用持久化外观控件完成应用。
|
||||
Reference in New Issue
Block a user