@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';
// 提供 studio 服务的 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',
],
}}
/>
</>
);
}
```
## Props
`BlockletStudio` 组件接受以下 props 来控制其行为和外观。
<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` prop 关联的状态变量设置为 `false`。</x-field-desc>
</x-field>
<x-field data-name="componentDid" data-type="string" data-required="true">
<x-field-desc markdown>提供资源发布服务的 blocklet 的去中心化标识符 (DID)。这决定了加载哪个 studio 界面。</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>决定 studio 界面的显示模式。默认为 `'dialog'`。</x-field-desc>
</x-field>
<x-field data-name="title" data-type="string" data-required="false">
<x-field-desc markdown>一个可选的标题,显示在 studio 界面的顶部。</x-field-desc>
</x-field>
<x-field data-name="logo" data-type="string" data-required="false">
<x-field-desc markdown>一个可选的 logo URL,显示在 studio 界面中。</x-field-desc>
</x-field>
<x-field data-name="description" data-type="string" data-required="false">
<x-field-desc markdown>一个可选的字符串,提供简短描述,显示在 studio UI 中。</x-field-desc>
</x-field>
<x-field data-name="introduction" data-type="string" data-required="false">
<x-field-desc markdown>一个可选的字符串,用于更详细的介绍,显示在 studio 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>一个对象数组,代表在 studio 中默认应预先选中的组件。</x-field-desc>
</x-field>
<x-field data-name="resources" data-type="Record<string, unknown>" data-required="false" data-default="{}">
<x-field-desc markdown>一个对象,代表在 studio 中默认应预先选中的资源。</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 响应示例。"Application" 和 "Tool" 资源声明了它们的组件依赖项。
```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` 和一组清晰的 props,它在简化开发的同时提供了一致的用户体验。有关依赖项管理的相关功能,您可能还想查看 [ComponentInstaller](./components-component-management-component-installer.md) 文档。