@blocklet/ui-react
Version:
Some useful front-end web components that can be used in Blocklets.
194 lines (172 loc) • 10.3 kB
Markdown
# BlockletStudio
`BlockletStudio` 元件提供了一個精簡、可嵌入的使用者介面,用於發佈和管理 blocklet 資源。它透過渲染一個全頁 `iframe` 來運作,該 `iframe` 從指定的 blocklet 服務載入一個專用的發佈介面。這讓您的應用程式能夠提供一致且強大的資源管理體驗,而無需從頭開始建構 UI。
宿主應用程式與 `BlockletStudio` iframe 之間的通訊使用 `window.postMessage` API 進行安全處理,為上傳、發佈和連線等事件啟用回呼。
## 使用範例
要整合 `BlockletStudio`,您需要管理其可見性狀態(例如,使用 `useState`)。由於 iframe 可能需要一些時間來載入,建議向使用者顯示一個載入指示器。`onOpened` 回呼可用於表示 iframe 內容已準備就緒,此時可以隱藏載入指示器。
以下範例示範如何實作一個按鈕,該按鈕可開啟 `BlockletStudio` 對話方塊並管理載入狀態。
```tsx icon=logos:react title="Exporter.tsx"
import { Icon } from '@iconify-icon/react';
import ArrowUp from '@iconify-icons/tabler/arrow-big-up-line';
import { Box, IconButton, CircularProgress as Spinner, svgIconClasses } from '@mui/material';
import { useState } from 'react';
import { BlockletStudio } from '@arcblock/ux-react';
// 提供工作室服務的 blocklet 的 DID。
const AI_STUDIO_COMPONENT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9';
export default function Exporter() {
const [showCreateResource, setShowCreateResource] = useState(false);
const [opening, setOpening] = useState(false);
const handleShowDialog = () => {
setOpening(true);
setShowCreateResource(true);
};
return (
<>
<IconButton
sx={{
position: 'relative',
minWidth: 40,
minHeight: 40,
borderRadius: '100%',
[`.${svgIconClasses.root}`]: {
color: 'text.secondary',
},
}}
onClick={handleShowDialog}>
{opening ? <Spinner size={16} /> : <Box component={Icon} icon={ArrowUp} style={{ fontSize: 24 }} />}
</IconButton>
<BlockletStudio
open={showCreateResource}
setOpen={setShowCreateResource}
onOpened={() => setOpening(false)}
componentDid={AI_STUDIO_COMPONENT_DID}
mode="dialog"
title="Demo Project"
description="This is a demo project for the 'aigne' blocklet."
note='Please review all resources and components before publishing.'
introduction="Welcome to the resource publisher."
tenantScope="test-tenant-scope-id-2"
resourcesParams={{ name: 'test-project', extra: true }}
dependentComponentsMode="readonly"
componentsTitle="Required Components"
resourcesTitle="Add Project Files"
onConnected={() => alert('Connected')}
onUploaded={() => alert('Uploaded')}
onReleased={() => alert('Released')}
components={[
{ did: 'z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ', included: true, required: true },
{ did: 'z2qZyjnsRffFtn2PDnDwDHTRbAu53RpKqDtFZ', included: true, required: false },
]}
resources={{
'z8iZpog7mcgcgBZzTiXJCWESvmnRrQmnd3XBB': [
'template-448698592710885376',
'template-448696391418511360',
],
}}
/>
</>
);
}
```
## 屬性
`BlockletStudio` 元件接受以下屬性來控制其行為和外觀。
<x-field-group>
<x-field data-name="open" data-type="boolean" data-required="true">
<x-field-desc markdown>控制 `BlockletStudio` iframe 的可見性。設定為 `true` 可顯示,`false` 可隱藏。</x-field-desc>
</x-field>
<x-field data-name="setOpen" data-type="(open: boolean) => void" data-required="true">
<x-field-desc markdown>一個回呼函式,`BlockletStudio` 用於請求關閉。通常,此函式會將與 `open` 屬性相關的狀態變數設定為 `false`。</x-field-desc>
</x-field>
<x-field data-name="componentDid" data-type="string" data-required="true">
<x-field-desc markdown>提供資源發佈服務的 blocklet 的去中心化識別碼 (DID)。這決定了載入哪個工作室介面。</x-field-desc>
</x-field>
<x-field data-name="onOpened" data-type="() => void" data-required="false">
<x-field-desc markdown>一個可選的回呼函式,當 `BlockletStudio` iframe 完成載入並準備好進行使用者互動時執行。</x-field-desc>
</x-field>
<x-field data-name="onUploaded" data-type="(data: unknown) => void" data-required="false">
<x-field-desc markdown>一個可選的回呼函式,在使用者成功上傳新資源後觸發。`data` 參數包含有關上傳項目的元資料。</x-field-desc>
</x-field>
<x-field data-name="onReleased" data-type="(data: unknown) => void" data-required="false">
<x-field-desc markdown>一個可選的回呼函式,在使用者發佈元件的新版本後觸發。`data` 參數包含有關新版本的資訊。</x-field-desc>
</x-field>
<x-field data-name="onConnected" data-type="(data: unknown) => void" data-required="false">
<x-field-desc markdown>一個可選的回呼函式,在使用者連線資源或元件後觸發。</x-field-desc>
</x-field>
<x-field data-name="tenantScope" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的字串,用於將資源範圍限定於特定租戶。這可用於確保多租戶環境中的資料隔離。</x-field-desc>
</x-field>
<x-field data-name="resourcesParams" data-type="Record<string, any>" data-required="false" data-default="{}">
<x-field-desc markdown>一個包含查詢參數的物件,這些參數將傳遞給 blocklet 的資源擷取 API 端點。這允許對資源進行動態篩選。</x-field-desc>
</x-field>
<x-field data-name="mode" data-type="string" data-required="false" data-default='"dialog"'>
<x-field-desc markdown>決定工作室介面的顯示模式。預設為 `'dialog'`。</x-field-desc>
</x-field>
<x-field data-name="title" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的標題,顯示在工作室介面的頂部。</x-field-desc>
</x-field>
<x-field data-name="logo" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的 logo URL,顯示在工作室介面中。</x-field-desc>
</x-field>
<x-field data-name="description" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的字串,提供簡短描述,顯示在工作室 UI 中。</x-field-desc>
</x-field>
<x-field data-name="introduction" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的字串,用於更詳細的介紹,顯示在工作室 UI 中。</x-field-desc>
</x-field>
<x-field data-name="note" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的字串,用於向使用者顯示註釋或重要訊息。</x-field-desc>
</x-field>
<x-field data-name="componentsTitle" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的字串,用於自訂元件部分的標題。</x-field-desc>
</x-field>
<x-field data-name="resourcesTitle" data-type="string" data-required="false">
<x-field-desc markdown>一個可選的字串,用於自訂資源部分的標題。</x-field-desc>
</x-field>
<x-field data-name="components" data-type="Record<string, unknown>[]" data-required="false" data-default="[]">
<x-field-desc markdown>一個物件陣列,代表在工作室中應預設預選的元件。</x-field-desc>
</x-field>
<x-field data-name="resources" data-type="Record<string, unknown>" data-required="false" data-default="{}">
<x-field-desc markdown>一個物件,代表在工作室中應預設預選的資源。</x-field-desc>
</x-field>
<x-field data-name="dependentComponentsMode" data-type="'auto' | 'readonly'" data-required="false">
<x-field-desc markdown>控制相依元件的行為。在 `'readonly'` 模式下,使用者無法取消選取作為所選資源的相依性而自動包含的元件。</x-field-desc>
</x-field>
<x-field data-name="style" data-type="React.CSSProperties" data-required="false" data-default="{}">
<x-field-desc markdown>一個用於將自訂 CSS 樣式應用於 `iframe` 元素的物件。</x-field-desc>
</x-field>
<x-field data-name="zIndex" data-type="number" data-required="false" data-default="9999">
<x-field-desc markdown>`iframe` 元素的 z-index CSS 屬性,控制其堆疊順序。</x-field-desc>
</x-field>
</x-field-group>
## 相依元件
為 `BlockletStudio` 提供資源 API 的 Blocklet 可以在資源資料中直接指定元件相依性。當使用者選取一個列出 `dependentComponents` 的資源時,`BlockletStudio` 將在 UI 中自動選取這些元件。
此功能透過確保所有必要的相依性都自動包含在內,簡化了使用者體驗。
要實作此功能,您的 blocklet 的資源 API 應返回一個包含所需元件 DID 的 `dependentComponents` 陣列。
### API 回應範例
以下是來自資源 API 端點的 JSON 回應範例。「應用程式」和「工具」資源宣告了它們的元件相依性。
```json 帶有相依性的 API 回應
{
"resources": [
{
"id": "application-448698592710885376",
"name": "My App (as Application)",
"dependentComponents": [
"error-did",
"z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9",
"z2qZyjnsRffFtn2PDnDwDHTRbAu53RpKqDtFZ",
"z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk"
]
},
{
"id": "tool-448698592710885376",
"name": "My App (as Tool)",
"dependentComponents": ["error-did", "z2qaCNvKMv5GjouKdcDWexv6WqtHbpNPQDnAk"]
},
{
"id": "template-448698592710885376",
"name": "My App (as Template)"
}
]
}
```
## 總結
`BlockletStudio` 元件提供了一種強大而便利的方式,可將資源和元件管理直接整合到您的應用程式中。透過利用 `iframe` 和一組清晰的屬性,它在簡化開發的同時提供了一致的使用者體驗。有關相依性管理的相關功能,您可能還想查閱 [ComponentInstaller](./components-component-management-component-installer.md) 文件。