@blocklet/ui-react
Version:
Some useful front-end web components that can be used in Blocklets.
413 lines (314 loc) • 15.2 kB
Markdown
# 操作指南
本節提供了實用的逐步指南,用於完成常見任務和使用該函式庫的元件實作特定工作流程。每個指南都設計為一組獨立的說明,旨在幫助您高效地達成特定成果。
<x-cards data-columns="2">
<x-card data-title="為 Header 新增自訂元素" data-icon="lucide:layout-template" data-href="#how-to-add-custom-elements-to-the-header">
了解如何使用 `addons` render prop 來擴展 `Header` 元件,新增自訂按鈕、導覽或其他互動元素。
</x-card>
<x-card data-title="處理可選元件依賴" data-icon="lucide:puzzle" data-href="#how-to-handle-optional-component-dependencies">
實作一個工作流程,提示管理員按需安裝必要的元件,確保您的 blocklet 功能順暢執行。
</x-card>
<x-card data-title="實作即時使用者通知" data-icon="lucide:bell-ring" data-href="#how-to-implement-real-time-user-notifications">
使用 WebSockets 設定一個即時通知系統,讓使用者隨時了解您應用程式中的重要事件。
</x-card>
<x-card data-title="使用 BlockletStudio 發布資源" data-icon="lucide:rocket" data-href="#how-to-publish-resources-with-blockletstudio">
整合 `BlockletStudio` 元件,提供一個用於發布和管理資源及依賴元件的使用者介面。
</x-card>
</x-cards>
---
## 如何為 Header 新增自訂元素
`Header` 元件被設計為可擴展的。您可以利用 `addons` prop,直接將自訂按鈕、搜尋欄或其他 React 元件新增到 Header 中。
### 目標
在主應用程式 Header 中新增一個自訂的「聊天」按鈕、一個搜尋輸入框以及額外的操作圖示。
### 先決條件
- 一個已安裝 `@arcblock/ux` 函式庫且功能正常的 React 應用程式。
- 一個現有的 `<Header>` 元件實例。更多資訊,請參閱 [Header 元件文件](./components-layout-header.md)。
### 步驟
`addons` prop 接受一個 render 函式。此函式會接收預設的插件(如 session 管理器)作為其第一個參數,讓您能夠決定將自訂元素放置在相對於預設插件的位置。
1. **定義 `addons` Render Prop**
在您的 `Header` 元件中,將一個函式傳遞給 `addons` prop。此函式應返回您想要渲染的 JSX。
```jsx
<Header
meta={meta}
addons={(defaultAddons, { navigation }) => {
// 您的自訂元件將放置於此
return (
<>
{/* 渲染您的自訂元件 */}
{defaultAddons}
</>
);
}}
/>
```
2. **新增自訂元件**
在 render 函式內部,您可以新增任何您需要的元件。在此範例中,我們將新增一個標準的 Material-UI `Button`、幾個用於圖示的 `AddonButton` 元件以及一個 `Divider`。
3. **與預設插件結合**
標準作法是渲染傳入函式的 `defaultAddons`。這能確保如地區設定切換器和 session 管理器等基本元素仍然顯示。您可以將自訂元件放置在 `defaultAddons` 之前或之後。
### 完整範例
以下是一個完整的範例,示範如何將多個自訂元素新增到 Header。這包括導覽、按鈕和圖示,並與預設的 session 管理器一同渲染。
```javascript 如何為 Header 新增自訂元素 icon=logos:react
import { Box, Divider, Button } from '@mui/material';
import { SessionContext } from '@arcblock/did-connect-react/lib/Session';
import { AddonButton } from '@arcblock/ux/lib/Header/addon-button';
import NavMenu from '@arcblock/ux/lib/NavMenu';
import SessionManager from '@arcblock/ux/lib/SessionManager';
import Header from '@arcblock/ux/lib/Header';
import { Icon } from '@iconify/react';
// 用於示範的模擬資料
const mockBlockletMeta = {
title: 'My App',
description: 'A great application',
logoUrl: 'https://www.arcblock.io/image-bin/uploads/eb1cf5d60cd85c42362920c49e3768cb.svg'
};
const mockSessionContextValue = {
session: {
user: {
fullName: 'Demo User',
did: 'z1ex...',
role: 'admin',
},
// ... 其他 session 屬性
},
};
export default function CustomHeaderGuide() {
const meta = {
...mockBlockletMeta,
enableConnect: true,
enableLocale: true,
};
return (
<SessionContext.Provider value={mockSessionContextValue}>
<Header
meta={meta}
homeLink="https://www.arcblock.io"
addons={(defaultAddons, { navigation }) => (
<>
{/* 1. 新增自訂導覽 */}
{navigation.navItems?.length > 0 && (
<NavMenu
activeId={navigation.activeId}
items={navigation.navItems}
className="header-nav"
/>
)}
{/* 2. 新增自訂按鈕 */}
<Button variant="contained" color="primary" size="small">
Button
</Button>
{/* 3. 新增自訂圖示按鈕 */}
<AddonButton icon={<Icon icon="tabler:message-circle" />}>Chat</AddonButton>
<AddonButton icon={<Icon icon="tabler:bell" />} />
<Divider orientation="vertical" flexItem sx={{ height: 12, alignSelf: 'center' }} />
{/* 4. 渲染預設插件 (包含 session 管理器) */}
{defaultAddons}
</>
)}
/>
</SessionContext.Provider>
);
}
```
---
## 如何處理可選元件依賴
許多 blocklets 依賴其他元件來提供特定功能。`ComponentInstaller` 讓您能夠建構依賴於可選元件的功能,如果這些元件未被安裝,它會為管理員提供一個友善的介面來安裝它們。
### 目標
保護一個需要安裝另一個 blocklet 元件才能使用的功能。如果該元件缺失,管理員將會看到一個安裝介面,而其他使用者則不會看到任何內容。
### 先決條件
- 您的應用程式中有一個依賴其他元件的功能(例如,一個需要「Media Kit」blocklet 的「媒體管理器」)。
- 依賴元件的 DID。
- 熟悉使用者角色(`owner`、`admin`)。
### 步驟
1. **匯入 `ComponentInstaller`**
首先,從函式庫中匯入該元件。
```javascript
import ComponentInstaller from '@arcblock/ux/lib/ComponentInstaller';
```
2. **包裹您的功能**
使用 `ComponentInstaller` 包裹具有依賴項的元件或功能。
3. **提供元件 DID**
將所需元件的 DID 傳遞給 `did` prop。如果有多個依賴項,這可以是一個字串或一個字串陣列。
4. **為非管理員配置行為**
使用 `noPermissionMute` prop。當設定為 `true` 時,沒有權限安裝元件的使用者(即非管理員)將不會看到安裝提示。您可以提供一個 `fallback` 元件來替代顯示。
### 完整範例
在此情境中,我們有一個 `MyFeatureButton`,只有在 DID 為 `z8ia...` 的元件被安裝後才應渲染。
```javascript 如何處理可選元件依賴 icon=logos:react
import ComponentInstaller from '@arcblock/ux/lib/ComponentInstaller';
import { Button } from '@mui/material';
const REQUIRED_COMPONENT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9'; // 範例 DID
// 這是需要依賴項的元件
function MyFeatureButton() {
return <Button variant="contained">Use Awesome Feature</Button>;
}
export default function OptionalComponentGuide() {
return (
<ComponentInstaller
// 要檢查的元件的 DID
did={REQUIRED_COMPONENT_DID}
// 允許查看安裝程式 UI 的角色列表
roles={['owner', 'admin']}
// 若為 true,非管理員將看不到安裝程式 UI
noPermissionMute
// 可選:當元件未安裝時,向非管理員顯示的內容
fallback={<div>This feature is not available.</div>}
// 成功安裝後觸發的回呼
onInstalled={() => console.log('Component was installed successfully!')}
>
{/* 只有在元件已安裝時,才會渲染此子元件 */}
<MyFeatureButton />
</ComponentInstaller>
);
}
```
當管理員訪問此頁面且元件未安裝時,他們將看到一個彈出視窗,允許他們安裝。普通使用者將看到備用訊息。一旦安裝完成,所有使用者都將看到 `MyFeatureButton`。
---
## 如何實作即時使用者通知
您可以透過監聽來自 Blocklet Server 的 WebSocket 事件,為使用者提供即時回饋和通知。`NotificationAddon` 元件是一個現成的解決方案,用於在 Header 中顯示未讀通知計數。
### 目標
在應用程式 Header 中新增一個通知鈴鐺圖示,該圖示會顯示帶有未讀通知數量的徽章,並即時更新。
### 先決條件
- 您的 blocklet 必須在支援通知服務的 Blocklet Server 版本(`1.16.42` 或更高)上執行。
- 一個用於放置通知圖示的 `<Header>` 元件。
- 一個提供使用者資訊的 session context。
### 關鍵概念
- **WebSocket 事件**:當通知被建立或讀取時,Blocklet Server 會廣播事件。
- **`useListenWsClient`**:一個用於獲取特定頻道(例如 'user')的 WebSocket 客戶端實例的 hook。
- **事件命名**:事件的作用域限定於使用者和 blocklet。新通知的格式為 `${blocklet.did}/${user.did}/notification:blocklet:create`。
### 步驟
`NotificationAddon` 元件封裝了監聽 WebSocket 事件和顯示未讀計數所需的所有邏輯。
1. **匯入 `NotificationAddon`**
```javascript
import NotificationAddon from '@arcblock/ux/lib/common/notification-addon';
```
2. **新增至 Header `addons`**
最簡單的使用方法是將其新增到 `Header` 的 `addons` render prop 中。
3. **傳遞 Session 物件**
`NotificationAddon` 元件需要 `session` 物件來識別目前使用者並管理未讀計數狀態。
### 完整範例
此範例展示如何將 `NotificationAddon` 整合到 `Header` 中。它將自動連接到 WebSocket、監聽事件並更新徽章計數。
```javascript 如何實作即時使用者通知 icon=logos:react
import { SessionContext } from '@arcblock/did-connect-react/lib/Session';
import Header from '@arcblock/ux/lib/Header';
import NotificationAddon from '@arcblock/ux/lib/common/notification-addon';
// 用於示範的模擬資料
const mockBlockletMeta = {
title: 'My App',
description: 'A great application',
logoUrl: 'https://www.arcblock.io/image-bin/uploads/eb1cf5d60cd85c42362920c49e3768cb.svg'
};
const mockSessionContextValue = {
session: {
user: {
fullName: 'Demo User',
did: 'z1ex...',
role: 'admin',
},
unReadCount: 3, // 初始未讀計數
setUnReadCount: () => {}, // 狀態設定函式
// ... 其他 session 屬性
},
};
export default function NotificationGuide() {
const meta = { ...mockBlockletMeta, enableConnect: true };
return (
<SessionContext.Provider value={mockSessionContextValue}>
<Header
meta={meta}
addons={(defaultAddons) => (
<>
{/* NotificationAddon 將處理即時更新 */}
<NotificationAddon session={mockSessionContextValue.session} />
{defaultAddons}
</>
)}
/>
</SessionContext.Provider>
);
}
```
當為已登入使用者建立新通知時,鈴鐺圖示上的徽章計數將自動增加。點擊該圖示將導覽使用者至他們的通知頁面。
---
## 如何使用 BlockletStudio 發布資源
`BlockletStudio` 元件提供了一個完整的、可嵌入的 UI,用於發布資源和元件。它處理使用者連接、資源選擇和發布流程,將一個複雜的工作流程簡化為單一元件。
### 目標
新增一個按鈕,該按鈕會打開一個對話框,允許使用者從 blocklet 中選擇並發布檔案和依賴元件。
### 先決條件
- 您的 blocklet 中有一個 API 端點,該端點返回可用資源列表。
- 提供發布 UI 的元件(「工作室」元件)的 DID。
### 步驟
1. **匯入 `BlockletStudio` 並管理狀態**
您需要使用元件狀態來管理工作室對話框的可見性。
```javascript
import { useState } from 'react';
import { BlockletStudio } from '@arcblock/ux/lib/BlockletStudio';
import { Button, CircularProgress } from '@mui/material';
```
2. **渲染元件**
將 `<BlockletStudio />` 元件放置在您的應用程式中,並使用 `open` 和 `setOpen` props 控制其可見性。
3. **配置必要 Props**
- `componentDid`:提供發布服務的工作室 blocklet 的 DID。
- `title`, `description`:正在發布的項目的元資料。
- `resourcesParams`:作為查詢參數傳遞給您的資源獲取 API 的物件。
- `components`:一個要預選或必需的元件陣列。
- `resources`:一個指定要預選的資源的物件。
4. **處理生命週期事件**
使用 `onOpened`、`onUploaded` 和 `onReleased` 回呼來回應發布生命週期中的事件,例如隱藏載入指示器或顯示成功訊息。
### 完整範例
此範例顯示一個按鈕,點擊後會打開 `BlockletStudio` 對話框。它還示範了如何管理載入狀態以提供更好的使用者體驗。
```javascript 如何使用 BlockletStudio 發布資源 icon=logos:react
import { useState } from 'react';
import { Button, CircularProgress } from '@mui/material';
import { BlockletStudio } from '@arcblock/ux/lib/BlockletStudio';
// 提供工作室/發布 UI 的 blocklet 的 DID
const AI_STUDIO_COMPONENT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9'; // 範例 DID
export default function PublisherGuide() {
const [isStudioOpen, setStudioOpen] = useState(false);
const [isOpening, setOpening] = useState(false);
const handleShowDialog = () => {
setOpening(true);
setStudioOpen(true);
};
return (
<>
<Button
variant="contained"
onClick={handleShowDialog}
disabled={isOpening}
startIcon={isOpening ? <CircularProgress size={16} /> : null}>
Publish to Studio
</Button>
<BlockletStudio
// 控制對話框的可見性
open={isStudioOpen}
setOpen={setStudioOpen}
// 已發布項目的基本資訊
title="My Demo Project"
description="This is a project published from my blocklet."
// 工作室服務元件的 DID
componentDid={AI_STUDIO_COMPONENT_DID}
// 發送到您的 blocklet 資源 API 的參數
resourcesParams={{ projectId: 'test-project-123' }}
// 預選元件
components={[
{ did: 'z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ', included: true, required: true },
{ did: 'z2qZyjnsRffFtn2PDnDwDHTRbAu53RpKqDtFZ', included: true, required: false },
]}
// 預選資源
resources={{
// 鍵值是資源提供者 blocklet 的 DID
z8iZpog7mcgcgBZzTiXJCWESvmnRrQmnd3XBB: [
'template-448698592710885376',
'example-448698592710885376',
],
}}
// 事件處理常式
onOpened={() => setOpening(false)}
onUploaded={() => alert('Upload complete!')}
onReleased={() => {
alert('Successfully released!');
setStudioOpen(false);
}}
/>
</>
);
}
```