@blocklet/ui-react 3.1.47 → 3.1.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.aigne/doc-smith/config.yaml +76 -0
- package/.aigne/doc-smith/history.yaml +9 -0
- package/.aigne/doc-smith/output/structure-plan.json +249 -0
- package/.aigne/doc-smith/upload-cache.yaml +528 -0
- package/docs/_sidebar.md +19 -0
- package/docs/components-component-management-blocklet-studio.ja.md +194 -0
- package/docs/components-component-management-blocklet-studio.md +194 -0
- package/docs/components-component-management-blocklet-studio.zh-TW.md +194 -0
- package/docs/components-component-management-blocklet-studio.zh.md +194 -0
- package/docs/components-component-management-component-installer.ja.md +256 -0
- package/docs/components-component-management-component-installer.md +256 -0
- package/docs/components-component-management-component-installer.zh-TW.md +256 -0
- package/docs/components-component-management-component-installer.zh.md +256 -0
- package/docs/components-component-management.ja.md +59 -0
- package/docs/components-component-management.md +59 -0
- package/docs/components-component-management.zh-TW.md +59 -0
- package/docs/components-component-management.zh.md +59 -0
- package/docs/components-layout-dashboard.ja.md +231 -0
- package/docs/components-layout-dashboard.md +231 -0
- package/docs/components-layout-dashboard.zh-TW.md +231 -0
- package/docs/components-layout-dashboard.zh.md +231 -0
- package/docs/components-layout-footer.ja.md +165 -0
- package/docs/components-layout-footer.md +165 -0
- package/docs/components-layout-footer.zh-TW.md +165 -0
- package/docs/components-layout-footer.zh.md +165 -0
- package/docs/components-layout-header.ja.md +233 -0
- package/docs/components-layout-header.md +233 -0
- package/docs/components-layout-header.zh-TW.md +233 -0
- package/docs/components-layout-header.zh.md +233 -0
- package/docs/components-layout.ja.md +50 -0
- package/docs/components-layout.md +50 -0
- package/docs/components-layout.zh-TW.md +50 -0
- package/docs/components-layout.zh.md +50 -0
- package/docs/components-notifications.ja.md +173 -0
- package/docs/components-notifications.md +173 -0
- package/docs/components-notifications.zh-TW.md +174 -0
- package/docs/components-notifications.zh.md +173 -0
- package/docs/components-user-management-user-center.ja.md +183 -0
- package/docs/components-user-management-user-center.md +183 -0
- package/docs/components-user-management-user-center.zh-TW.md +183 -0
- package/docs/components-user-management-user-center.zh.md +183 -0
- package/docs/components-user-management-user-sessions.ja.md +164 -0
- package/docs/components-user-management-user-sessions.md +164 -0
- package/docs/components-user-management-user-sessions.zh-TW.md +164 -0
- package/docs/components-user-management-user-sessions.zh.md +164 -0
- package/docs/components-user-management.ja.md +76 -0
- package/docs/components-user-management.md +76 -0
- package/docs/components-user-management.zh-TW.md +76 -0
- package/docs/components-user-management.zh.md +76 -0
- package/docs/components-utilities-icon.ja.md +106 -0
- package/docs/components-utilities-icon.md +106 -0
- package/docs/components-utilities-icon.zh-TW.md +106 -0
- package/docs/components-utilities-icon.zh.md +106 -0
- package/docs/components-utilities.ja.md +136 -0
- package/docs/components-utilities.md +136 -0
- package/docs/components-utilities.zh-TW.md +136 -0
- package/docs/components-utilities.zh.md +136 -0
- package/docs/components.ja.md +27 -0
- package/docs/components.md +27 -0
- package/docs/components.zh-TW.md +27 -0
- package/docs/components.zh.md +27 -0
- package/docs/core-concepts.ja.md +164 -0
- package/docs/core-concepts.md +164 -0
- package/docs/core-concepts.zh-TW.md +164 -0
- package/docs/core-concepts.zh.md +164 -0
- package/docs/getting-started.ja.md +132 -0
- package/docs/getting-started.md +132 -0
- package/docs/getting-started.zh-TW.md +132 -0
- package/docs/getting-started.zh.md +132 -0
- package/docs/hooks-api.ja.md +214 -0
- package/docs/hooks-api.md +214 -0
- package/docs/hooks-api.zh-TW.md +214 -0
- package/docs/hooks-api.zh.md +214 -0
- package/docs/how-to-guides.ja.md +413 -0
- package/docs/how-to-guides.md +413 -0
- package/docs/how-to-guides.zh-TW.md +413 -0
- package/docs/how-to-guides.zh.md +413 -0
- package/docs/overview.ja.md +91 -0
- package/docs/overview.md +91 -0
- package/docs/overview.zh-TW.md +91 -0
- package/docs/overview.zh.md +91 -0
- package/glossary.md +12 -0
- package/lib/Dashboard/index.js +46 -42
- package/lib/Footer/index.js +51 -36
- package/lib/Header/index.js +48 -44
- package/lib/UserCenter/components/settings.js +1 -0
- package/lib/UserCenter/components/user-center.js +133 -133
- package/lib/blocklets.d.ts +13 -2
- package/lib/blocklets.js +40 -40
- package/lib/common/header-addons.js +37 -33
- package/package.json +7 -7
- package/src/Dashboard/index.jsx +8 -3
- package/src/Footer/index.jsx +22 -4
- package/src/Header/index.tsx +7 -2
- package/src/UserCenter/components/settings.tsx +1 -0
- package/src/UserCenter/components/user-center.tsx +6 -6
- package/src/blocklets.js +18 -9
- package/src/common/header-addons.jsx +7 -2
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Hooks API
|
|
2
|
+
|
|
3
|
+
本节为库中可用的自定义 React Hooks 提供了详细参考。这些 hooks 旨在封装和复用有状态逻辑,从而简化 Blocklet 环境中的常见任务和交互。
|
|
4
|
+
|
|
5
|
+
## useComponentInstalled
|
|
6
|
+
|
|
7
|
+
此 hook 检查一个或多个指定的可选组件(通过其 DID 识别)是否已安装。它对于实现依赖其他 Blocklet 的功能至关重要。该 hook 提供安装状态和必要的 URL,以便在需要时提示用户进行安装。
|
|
8
|
+
|
|
9
|
+
### 参数
|
|
10
|
+
|
|
11
|
+
该 hook 接受一个包含以下属性的对象:
|
|
12
|
+
|
|
13
|
+
<x-field-group>
|
|
14
|
+
<x-field data-name="did" data-type="string | string[]" data-required="true">
|
|
15
|
+
<x-field-desc markdown>要检查的组件的去中心化标识符(DID)或 DID 数组。单个字符串可包含多个由 `;;` 分隔的 DID。</x-field-desc>
|
|
16
|
+
</x-field>
|
|
17
|
+
<x-field data-name="onInstalled" data-type="function" data-required="false">
|
|
18
|
+
<x-field-desc markdown>一个可选的回调函数,当所有指定组件都已安装时触发。</x-field-desc>
|
|
19
|
+
</x-field>
|
|
20
|
+
<x-field data-name="onError" data-type="function" data-required="false">
|
|
21
|
+
<x-field-desc markdown>一个可选的回调函数,当一个或多个指定组件未安装时触发。</x-field-desc>
|
|
22
|
+
</x-field>
|
|
23
|
+
</x-field-group>
|
|
24
|
+
|
|
25
|
+
### 返回值
|
|
26
|
+
|
|
27
|
+
它返回一个包含安装状态和相关数据的对象:
|
|
28
|
+
|
|
29
|
+
<x-field-group>
|
|
30
|
+
<x-field data-name="optComponents" data-type="array">
|
|
31
|
+
<x-field-desc markdown>一个包含未安装组件对象的数组。每个对象都包含元数据,如 `meta.did`、`storeUrl` 和 `installUrl`。</x-field-desc>
|
|
32
|
+
</x-field>
|
|
33
|
+
<x-field data-name="installed" data-type="boolean">
|
|
34
|
+
<x-field-desc markdown>一个布尔值,如果所有指定组件都已安装并在 `blocklet.yml` 中定义,则为 `true`,否则为 `false`。</x-field-desc>
|
|
35
|
+
</x-field>
|
|
36
|
+
<x-field data-name="installStatus" data-type="object">
|
|
37
|
+
<x-field-desc markdown>一个对象,其中键是组件的 DID,值是其当前的安装状态(例如,'waiting'、'installing')。此状态通过 `window.postMessage` 事件更新。</x-field-desc>
|
|
38
|
+
</x-field>
|
|
39
|
+
<x-field data-name="setInstallStatus" data-type="function">
|
|
40
|
+
<x-field-desc markdown>用于手动更新 `installStatus` 对象的状态设置函数。</x-field-desc>
|
|
41
|
+
</x-field>
|
|
42
|
+
<x-field data-name="definedInBlockletYML" data-type="boolean">
|
|
43
|
+
<x-field-desc markdown>一个布尔值,指示组件是否在 blocklet 的配置(`blocklet.yml`)中定义。</x-field-desc>
|
|
44
|
+
</x-field>
|
|
45
|
+
</x-field-group>
|
|
46
|
+
|
|
47
|
+
### 示例用法
|
|
48
|
+
|
|
49
|
+
以下示例演示了如何在缺少依赖项时,使用 `useComponentInstalled` 来条件性地渲染一个功能或一个 `ComponentInstaller` 组件。
|
|
50
|
+
|
|
51
|
+
```javascript "ComponentFeature.js" icon=logos:javascript
|
|
52
|
+
import React from 'react';
|
|
53
|
+
import { useComponentInstalled, ComponentInstaller } from '@blocklet/ui-react';
|
|
54
|
+
|
|
55
|
+
const REQUIRED_DID = 'z8ia24z55nve2TSF5m1aZ5322d9f48a43D4a'; // 示例 DID
|
|
56
|
+
|
|
57
|
+
function ComponentFeature() {
|
|
58
|
+
const { installed, optComponents } = useComponentInstalled({ did: REQUIRED_DID });
|
|
59
|
+
|
|
60
|
+
if (!installed) {
|
|
61
|
+
// 如果组件不存在,则渲染安装器界面
|
|
62
|
+
return <ComponentInstaller components={optComponents} />;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 渲染依赖于已安装组件的功能
|
|
66
|
+
return (
|
|
67
|
+
<div>
|
|
68
|
+
<h2>My Feature</h2>
|
|
69
|
+
<p>This feature requires the component with DID: {REQUIRED_DID}</p>
|
|
70
|
+
{/* ... 功能实现 ... */}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default ComponentFeature;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## useFollow
|
|
79
|
+
|
|
80
|
+
此 hook 管理当前认证用户与另一位由其 DID 指定的用户之间的关注关系。它处理关注和取消关注的 API 调用,并提供当前的关注状态。
|
|
81
|
+
|
|
82
|
+
### 参数
|
|
83
|
+
|
|
84
|
+
<x-field-group>
|
|
85
|
+
<x-field data-name="userDid" data-type="string" data-required="true">
|
|
86
|
+
<x-field-desc markdown>要检查关注状态的用户配置文件的 DID。</x-field-desc>
|
|
87
|
+
</x-field>
|
|
88
|
+
<x-field data-name="t" data-type="function" data-required="true">
|
|
89
|
+
<x-field-desc markdown>用于显示成功或错误消息的翻译函数(例如,来自 `react-i18next`)。</x-field-desc>
|
|
90
|
+
</x-field>
|
|
91
|
+
<x-field data-name="isMySelf" data-type="boolean" data-required="true">
|
|
92
|
+
<x-field-desc markdown>一个布尔值,如果 `userDid` 属于当前登录的用户,则应设置为 `true`。</x-field-desc>
|
|
93
|
+
</x-field>
|
|
94
|
+
</x-field-group>
|
|
95
|
+
|
|
96
|
+
### 返回值
|
|
97
|
+
|
|
98
|
+
返回一个包含以下属性的对象:
|
|
99
|
+
|
|
100
|
+
<x-field-group>
|
|
101
|
+
<x-field data-name="followed" data-type="boolean">
|
|
102
|
+
<x-field-desc markdown>指示当前用户是否正在关注由 `userDid` 指定的用户。如果正在关注,则为 `true`,否则为 `false`。</x-field-desc>
|
|
103
|
+
</x-field>
|
|
104
|
+
<x-field data-name="followUser" data-type="function">
|
|
105
|
+
<x-field-desc markdown>一个稳定的函数,用于调用以关注用户。它处理 API 请求并在成功后更新 `followed` 状态。</x-field-desc>
|
|
106
|
+
</x-field>
|
|
107
|
+
<x-field data-name="unfollowUser" data-type="function">
|
|
108
|
+
<x-field-desc markdown>一个稳定的函数,用于调用以取消关注用户。它处理 API 请求并在成功后更新 `followed` 状态。</x-field-desc>
|
|
109
|
+
</x-field>
|
|
110
|
+
</x-field-group>
|
|
111
|
+
|
|
112
|
+
### 示例用法
|
|
113
|
+
|
|
114
|
+
此示例展示了如何创建一个 `FollowButton` 组件,该组件根据关系状态显示“关注”或“取消关注”操作。
|
|
115
|
+
|
|
116
|
+
```javascript "FollowButton.js" icon=logos:javascript
|
|
117
|
+
import React from 'react';
|
|
118
|
+
import Button from '@mui/material/Button';
|
|
119
|
+
import { useTranslation } from 'react-i18next';
|
|
120
|
+
import { useFollow } from '@blocklet/ui-react/hooks';
|
|
121
|
+
import { useSession } from '@blocklet/did-connect-react';
|
|
122
|
+
|
|
123
|
+
function FollowButton({ profileDid }) {
|
|
124
|
+
const { session } = useSession();
|
|
125
|
+
const { t } = useTranslation();
|
|
126
|
+
const isMySelf = session?.user?.did === profileDid;
|
|
127
|
+
|
|
128
|
+
const { followed, followUser, unfollowUser } = useFollow({
|
|
129
|
+
userDid: profileDid,
|
|
130
|
+
t,
|
|
131
|
+
isMySelf,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (isMySelf) {
|
|
135
|
+
return null; // 不在自己的个人资料页显示按钮
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const handleClick = () => {
|
|
139
|
+
if (followed) {
|
|
140
|
+
unfollowUser();
|
|
141
|
+
} else {
|
|
142
|
+
followUser();
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<Button variant="contained" onClick={handleClick}>
|
|
148
|
+
{followed ? t('profile.unfollow') : t('profile.follow')}
|
|
149
|
+
</Button>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default FollowButton;
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## useMobile
|
|
157
|
+
|
|
158
|
+
一个用于创建响应式组件的简单实用工具 hook。它利用 Material-UI 的 `useMediaQuery` 来确定当前视口宽度是否低于指定的断点。
|
|
159
|
+
|
|
160
|
+
### 参数
|
|
161
|
+
|
|
162
|
+
<x-field-group>
|
|
163
|
+
<x-field data-name="key" data-type="number | Breakpoint" data-default="'sm'" data-required="false">
|
|
164
|
+
<x-field-desc markdown>Material-UI 断点键(例如,`'xs'`、`'sm'`、`'md'`)或用于比较的像素值。如果屏幕宽度小于此值,该 hook 返回 `true`。</x-field-desc>
|
|
165
|
+
</x-field>
|
|
166
|
+
</x-field-group>
|
|
167
|
+
|
|
168
|
+
### 返回值
|
|
169
|
+
|
|
170
|
+
返回一个 `boolean` 值:如果视口小于指定的断点,则为 `true`,否则为 `false`。
|
|
171
|
+
|
|
172
|
+
### 示例用法
|
|
173
|
+
|
|
174
|
+
此 hook 必须在由 Material-UI `ThemeProvider` 包裹的组件树中使用。
|
|
175
|
+
|
|
176
|
+
```javascript "ResponsiveComponent.js" icon=logos:javascript
|
|
177
|
+
import React from 'react';
|
|
178
|
+
import Typography from '@mui/material/Typography';
|
|
179
|
+
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
|
180
|
+
import { useMobile } from '@blocklet/ui-react/hooks';
|
|
181
|
+
|
|
182
|
+
// 一个使用该 hook 的组件
|
|
183
|
+
function ResponsiveComponent() {
|
|
184
|
+
const isMobile = useMobile({ key: 'md' }); // 根据 'md' 断点进行检查
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<div>
|
|
188
|
+
{isMobile ? (
|
|
189
|
+
<Typography variant="h6">Mobile View</Typography>
|
|
190
|
+
) : (
|
|
191
|
+
<Typography variant="h4">Desktop View</Typography>
|
|
192
|
+
)}
|
|
193
|
+
<p>Resize your browser window to see the content change.</p>
|
|
194
|
+
</div>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 该组件必须被包裹在 ThemeProvider 中
|
|
199
|
+
const theme = createTheme();
|
|
200
|
+
|
|
201
|
+
function App() {
|
|
202
|
+
return (
|
|
203
|
+
<ThemeProvider theme={theme}>
|
|
204
|
+
<ResponsiveComponent />
|
|
205
|
+
</ThemeProvider>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export default App;
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
通过使用这些 hooks,您可以用最少的样板代码高效地实现复杂功能。有关可能使用这些 hooks 的组件的更多信息,请参阅 [组件](./components.md) 文档。
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# 操作ガイド
|
|
2
|
+
|
|
3
|
+
このセクションでは、ライブラリのコンポーネントを使用して一般的なタスクを完了したり、特定のワークフローを実装したりするための、実践的なステップバイステップガイドを提供します。各ガイドは、特定の結果を効率的に達成できるよう、自己完結型の説明書として設計されています。
|
|
4
|
+
|
|
5
|
+
<x-cards data-columns="2">
|
|
6
|
+
<x-card data-title="ヘッダーにカスタム要素を追加する" data-icon="lucide:layout-template" data-href="#how-to-add-custom-elements-to-the-header">
|
|
7
|
+
`addons`レンダープロップを使用して、`Header`コンポーネントをカスタムボタン、ナビゲーション、またはその他のインタラクティブな要素で拡張する方法を学びます。
|
|
8
|
+
</x-card>
|
|
9
|
+
<x-card data-title="オプションのコンポーネント依存関係を処理する" data-icon="lucide:puzzle" data-href="#how-to-handle-optional-component-dependencies">
|
|
10
|
+
管理者に必要なコンポーネントをオンデマンドでインストールするように促すワークフローを実装し、ブロックレットの機能がスムーズに実行されるようにします。
|
|
11
|
+
</x-card>
|
|
12
|
+
<x-card data-title="リアルタイムのユーザー通知を実装する" data-icon="lucide:bell-ring" data-href="#how-to-implement-real-time-user-notifications">
|
|
13
|
+
WebSocketを使用してリアルタイム通知システムを設定し、アプリケーション内の重要なイベントをユーザーに通知し続けます。
|
|
14
|
+
</x-card>
|
|
15
|
+
<x-card data-title="BlockletStudioでリソースを公開する" data-icon="lucide:rocket" data-href="#how-to-publish-resources-with-blockletstudio">
|
|
16
|
+
`BlockletStudio`コンポーネントを統合して、リソースと依存コンポーネントを公開および管理するためのユーザーインターフェイスを提供します。
|
|
17
|
+
</x-card>
|
|
18
|
+
</x-cards>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## ヘッダーにカスタム要素を追加する方法
|
|
23
|
+
|
|
24
|
+
`Header`コンポーネントは拡張可能に設計されています。`addons`プロップを利用することで、カスタムボタン、検索バー、またはその他のReactコンポーネントをヘッダーに直接追加できます。
|
|
25
|
+
|
|
26
|
+
### 目標
|
|
27
|
+
|
|
28
|
+
メインアプリケーションのヘッダーに、カスタムの「チャット」ボタン、検索入力、および追加のアクションアイコンを追加します。
|
|
29
|
+
|
|
30
|
+
### 前提条件
|
|
31
|
+
|
|
32
|
+
- `@arcblock/ux`ライブラリがインストールされた、機能するReactアプリケーション。
|
|
33
|
+
- 既存の`<Header>`コンポーネントインスタンス。詳細については、[Headerコンポーネントのドキュメント](./components-layout-header.md)を参照してください。
|
|
34
|
+
|
|
35
|
+
### 手順
|
|
36
|
+
|
|
37
|
+
`addons`プロップはレンダー関数を受け入れます。この関数は、最初の引数としてデフォルトのアドオン(セッションマネージャーなど)を受け取り、カスタム要素をデフォルトの要素に対してどこに配置するかを決定できます。
|
|
38
|
+
|
|
39
|
+
1. **`addons`レンダープロップを定義する**
|
|
40
|
+
|
|
41
|
+
`Header`コンポーネントで、`addons`プロップに関数を渡します。この関数は、レンダリングしたいJSXを返す必要があります。
|
|
42
|
+
|
|
43
|
+
```jsx
|
|
44
|
+
<Header
|
|
45
|
+
meta={meta}
|
|
46
|
+
addons={(defaultAddons, { navigation }) => {
|
|
47
|
+
// ここにカスタムコンポーネントを配置します
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
{/* カスタムコンポーネントをレンダリングします */}
|
|
51
|
+
{defaultAddons}
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
2. **カスタムコンポーネントを追加する**
|
|
59
|
+
|
|
60
|
+
レンダー関数内で、必要なコンポーネントを追加できます。この例では、標準のMaterial-UI `Button`、アイコン用のいくつかの`AddonButton`コンポーネント、および`Divider`を追加します。
|
|
61
|
+
|
|
62
|
+
3. **デフォルトのアドオンと組み合わせる**
|
|
63
|
+
|
|
64
|
+
関数に渡される`defaultAddons`をレンダリングするのが標準的な方法です。これにより、ロケールスイッチャーやセッションマネージャーなどの重要な要素が引き続き表示されるようになります。カスタムコンポーネントは`defaultAddons`の前または後に配置できます。
|
|
65
|
+
|
|
66
|
+
### 完全な例
|
|
67
|
+
|
|
68
|
+
これは、ヘッダーにいくつかのカスタム要素を追加する方法を示す完全な例です。これには、ナビゲーション、ボタン、アイコンが含まれ、デフォルトのセッションマネージャーと一緒にレンダリングされます。
|
|
69
|
+
|
|
70
|
+
```javascript ヘッダーにカスタム要素を追加する方法 icon=logos:react
|
|
71
|
+
import { Box, Divider, Button } from '@mui/material';
|
|
72
|
+
import { SessionContext } from '@arcblock/did-connect-react/lib/Session';
|
|
73
|
+
import { AddonButton } from '@arcblock/ux/lib/Header/addon-button';
|
|
74
|
+
import NavMenu from '@arcblock/ux/lib/NavMenu';
|
|
75
|
+
import SessionManager from '@arcblock/ux/lib/SessionManager';
|
|
76
|
+
import Header from '@arcblock/ux/lib/Header';
|
|
77
|
+
import { Icon } from '@iconify/react';
|
|
78
|
+
|
|
79
|
+
// デモンストレーション用のモックデータ
|
|
80
|
+
const mockBlockletMeta = {
|
|
81
|
+
title: 'My App',
|
|
82
|
+
description: 'A great application',
|
|
83
|
+
logoUrl: 'https://www.arcblock.io/image-bin/uploads/eb1cf5d60cd85c42362920c49e3768cb.svg'
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const mockSessionContextValue = {
|
|
87
|
+
session: {
|
|
88
|
+
user: {
|
|
89
|
+
fullName: 'Demo User',
|
|
90
|
+
did: 'z1ex...',
|
|
91
|
+
role: 'admin',
|
|
92
|
+
},
|
|
93
|
+
// ... その他のセッションプロパティ
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export default function CustomHeaderGuide() {
|
|
98
|
+
const meta = {
|
|
99
|
+
...mockBlockletMeta,
|
|
100
|
+
enableConnect: true,
|
|
101
|
+
enableLocale: true,
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<SessionContext.Provider value={mockSessionContextValue}>
|
|
106
|
+
<Header
|
|
107
|
+
meta={meta}
|
|
108
|
+
homeLink="https://www.arcblock.io"
|
|
109
|
+
addons={(defaultAddons, { navigation }) => (
|
|
110
|
+
<>
|
|
111
|
+
{/* 1. カスタムナビゲーションを追加 */}
|
|
112
|
+
{navigation.navItems?.length > 0 && (
|
|
113
|
+
<NavMenu
|
|
114
|
+
activeId={navigation.activeId}
|
|
115
|
+
items={navigation.navItems}
|
|
116
|
+
className="header-nav"
|
|
117
|
+
/>
|
|
118
|
+
)}
|
|
119
|
+
{/* 2. カスタムボタンを追加 */}
|
|
120
|
+
<Button variant="contained" color="primary" size="small">
|
|
121
|
+
Button
|
|
122
|
+
</Button>
|
|
123
|
+
{/* 3. カスタムアイコンボタンを追加 */}
|
|
124
|
+
<AddonButton icon={<Icon icon="tabler:message-circle" />}>Chat</AddonButton>
|
|
125
|
+
<AddonButton icon={<Icon icon="tabler:bell" />} />
|
|
126
|
+
<Divider orientation="vertical" flexItem sx={{ height: 12, alignSelf: 'center' }} />
|
|
127
|
+
{/* 4. デフォルトのアドオンをレンダリング(セッションマネージャーを含む) */}
|
|
128
|
+
{defaultAddons}
|
|
129
|
+
</>
|
|
130
|
+
)}
|
|
131
|
+
/>
|
|
132
|
+
</SessionContext.Provider>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## オプションのコンポーネント依存関係を処理する方法
|
|
140
|
+
|
|
141
|
+
多くのブロックレットは、特定の機能を提供するために他のコンポーネントに依存しています。`ComponentInstaller`を使用すると、オプションのコンポーネントに依存する機能を構築でき、それらがインストールされていない場合、管理者がそれらをインストールするためのユーザーフレンドリーな方法を提供します。
|
|
142
|
+
|
|
143
|
+
### 目標
|
|
144
|
+
|
|
145
|
+
別のブロックレットコンポーネントのインストールを必要とする機能を保護します。コンポーネントが見つからない場合、管理者にはそれをインストールするためのインターフェイスが表示されますが、他のユーザーには何も表示されません。
|
|
146
|
+
|
|
147
|
+
### 前提条件
|
|
148
|
+
|
|
149
|
+
- アプリケーション内の、別のコンポーネントに依存する機能(例:「メディアキット」ブロックレットを必要とする「メディアマネージャー」)。
|
|
150
|
+
- コンポーネント依存関係のDID。
|
|
151
|
+
- ユーザーロール(`owner`、`admin`)に関する知識。
|
|
152
|
+
|
|
153
|
+
### 手順
|
|
154
|
+
|
|
155
|
+
1. **`ComponentInstaller`をインポートする**
|
|
156
|
+
|
|
157
|
+
まず、ライブラリからコンポーネントをインポートします。
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
import ComponentInstaller from '@arcblock/ux/lib/ComponentInstaller';
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
2. **機能をラップする**
|
|
164
|
+
|
|
165
|
+
依存関係を持つコンポーネントまたは機能を`ComponentInstaller`でラップします。
|
|
166
|
+
|
|
167
|
+
3. **コンポーネントのDIDを提供する**
|
|
168
|
+
|
|
169
|
+
必要なコンポーネントのDIDを`did`プロップに渡します。複数の依存関係がある場合は、単一の文字列または文字列の配列にすることができます。
|
|
170
|
+
|
|
171
|
+
4. **非管理者向けの動作を設定する**
|
|
172
|
+
|
|
173
|
+
`noPermissionMute`プロップを使用します。`true`に設定すると、コンポーネントをインストールする権限を持たないユーザー(つまり非管理者)にはインストールプロンプトが表示されません。代わりに表示する`fallback`コンポーネントを提供できます。
|
|
174
|
+
|
|
175
|
+
### 完全な例
|
|
176
|
+
|
|
177
|
+
このシナリオでは、DID `z8ia...`を持つコンポーネントがインストールされている場合にのみレンダリングされるべき`MyFeatureButton`があります。
|
|
178
|
+
|
|
179
|
+
```javascript オプションのコンポーネント依存関係を処理する方法 icon=logos:react
|
|
180
|
+
import ComponentInstaller from '@arcblock/ux/lib/ComponentInstaller';
|
|
181
|
+
import { Button } from '@mui/material';
|
|
182
|
+
|
|
183
|
+
const REQUIRED_COMPONENT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9'; // DIDの例
|
|
184
|
+
|
|
185
|
+
// これが依存関係を必要とするコンポーネントです
|
|
186
|
+
function MyFeatureButton() {
|
|
187
|
+
return <Button variant="contained">Use Awesome Feature</Button>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export default function OptionalComponentGuide() {
|
|
191
|
+
return (
|
|
192
|
+
<ComponentInstaller
|
|
193
|
+
// チェックするコンポーネントのDID
|
|
194
|
+
did={REQUIRED_COMPONENT_DID}
|
|
195
|
+
// インストーラーUIの表示を許可されるロールのリスト
|
|
196
|
+
roles={['owner', 'admin']}
|
|
197
|
+
// trueの場合、非管理者はインストーラーUIを表示しません
|
|
198
|
+
noPermissionMute
|
|
199
|
+
// オプション:コンポーネントがインストールされていない場合に非管理者に表示するもの
|
|
200
|
+
fallback={<div>This feature is not available.</div>}
|
|
201
|
+
// インストール成功後に実行されるコールバック
|
|
202
|
+
onInstalled={() => console.log('Component was installed successfully!')}
|
|
203
|
+
>
|
|
204
|
+
{/* この子はコンポーネントがすでにインストールされている場合にのみレンダリングされます */}
|
|
205
|
+
<MyFeatureButton />
|
|
206
|
+
</ComponentInstaller>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
管理者がこのページにアクセスし、コンポーネントがインストールされていない場合、それをインストールするためのポップアップが表示されます。一般ユーザーにはフォールバックメッセージが表示されます。インストールされると、すべてのユーザーに`MyFeatureButton`が表示されます。
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## リアルタイムのユーザー通知を実装する方法
|
|
216
|
+
|
|
217
|
+
Blocklet ServerからのWebSocketイベントをリッスンすることで、ユーザーにリアルタイムのフィードバックと通知を提供できます。`NotificationAddon`コンポーネントは、ヘッダーに未読通知数を表示するためのすぐに使えるソリューションです。
|
|
218
|
+
|
|
219
|
+
### 目標
|
|
220
|
+
|
|
221
|
+
アプリケーションのヘッダーに通知ベルアイコンを追加し、未読通知数をバッジで表示してリアルタイムで更新します。
|
|
222
|
+
|
|
223
|
+
### 前提条件
|
|
224
|
+
|
|
225
|
+
- ブロックレットは、通知サービスをサポートするBlocklet Serverバージョン(`1.16.42`以降)で実行されている必要があります。
|
|
226
|
+
- 通知アイコンが配置される`<Header>`コンポーネント。
|
|
227
|
+
- ユーザー情報を提供するセッションコンテキスト。
|
|
228
|
+
|
|
229
|
+
### 主要な概念
|
|
230
|
+
|
|
231
|
+
- **WebSocketイベント**: Blocklet Serverは、通知が作成または読み取られたときにイベントをブロードキャストします。
|
|
232
|
+
- **`useListenWsClient`**: 特定のチャネル(例:「user」)のWebSocketクライアントインスタンスを取得するためのフック。
|
|
233
|
+
- **イベントの命名**: イベントはユーザーとブロックレットにスコープされます。新しい通知の形式は`${blocklet.did}/${user.did}/notification:blocklet:create`です。
|
|
234
|
+
|
|
235
|
+
### 手順
|
|
236
|
+
|
|
237
|
+
`NotificationAddon`コンポーネントは、WebSocketイベントをリッスンし、未読数を表示するために必要なすべてのロジックをカプセル化します。
|
|
238
|
+
|
|
239
|
+
1. **`NotificationAddon`をインポートする**
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
import NotificationAddon from '@arcblock/ux/lib/common/notification-addon';
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
2. **ヘッダーの`addons`に追加する**
|
|
246
|
+
|
|
247
|
+
これを使用する最も簡単な方法は、`Header`の`addons`レンダープロップ内に追加することです。
|
|
248
|
+
|
|
249
|
+
3. **セッションオブジェクトを渡す**
|
|
250
|
+
|
|
251
|
+
`NotificationAddon`コンポーネントは、現在のユーザーを識別し、未読数の状態を管理するために`session`オブジェクトを必要とします。
|
|
252
|
+
|
|
253
|
+
### 完全な例
|
|
254
|
+
|
|
255
|
+
この例は、`NotificationAddon`を`Header`に統合する方法を示しています。これは自動的にWebSocketに接続し、イベントをリッスンし、バッジ数を更新します。
|
|
256
|
+
|
|
257
|
+
```javascript リアルタイムのユーザー通知を実装する方法 icon=logos:react
|
|
258
|
+
import { SessionContext } from '@arcblock/did-connect-react/lib/Session';
|
|
259
|
+
import Header from '@arcblock/ux/lib/Header';
|
|
260
|
+
import NotificationAddon from '@arcblock/ux/lib/common/notification-addon';
|
|
261
|
+
|
|
262
|
+
// デモンストレーション用のモックデータ
|
|
263
|
+
const mockBlockletMeta = {
|
|
264
|
+
title: 'My App',
|
|
265
|
+
description: 'A great application',
|
|
266
|
+
logoUrl: 'https://www.arcblock.io/image-bin/uploads/eb1cf5d60cd85c42362920c49e3768cb.svg'
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const mockSessionContextValue = {
|
|
270
|
+
session: {
|
|
271
|
+
user: {
|
|
272
|
+
fullName: 'Demo User',
|
|
273
|
+
did: 'z1ex...',
|
|
274
|
+
role: 'admin',
|
|
275
|
+
},
|
|
276
|
+
unReadCount: 3, // 初期の未読数
|
|
277
|
+
setUnReadCount: () => {}, // 状態セッター関数
|
|
278
|
+
// ... その他のセッションプロパティ
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
export default function NotificationGuide() {
|
|
283
|
+
const meta = { ...mockBlockletMeta, enableConnect: true };
|
|
284
|
+
|
|
285
|
+
return (
|
|
286
|
+
<SessionContext.Provider value={mockSessionContextValue}>
|
|
287
|
+
<Header
|
|
288
|
+
meta={meta}
|
|
289
|
+
addons={(defaultAddons) => (
|
|
290
|
+
<>
|
|
291
|
+
{/* NotificationAddonがリアルタイムの更新を処理します */}
|
|
292
|
+
<NotificationAddon session={mockSessionContextValue.session} />
|
|
293
|
+
{defaultAddons}
|
|
294
|
+
</>
|
|
295
|
+
)}
|
|
296
|
+
/>
|
|
297
|
+
</SessionContext.Provider>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
ログインしているユーザーの新しい通知が作成されると、ベルアイコンのバッジ数が自動的に増加します。アイコンをクリックすると、ユーザーは通知ページに移動します。
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## BlockletStudioでリソースを公開する方法
|
|
307
|
+
|
|
308
|
+
`BlockletStudio`コンポーネントは、リソースとコンポーネントを公開するための、完全で埋め込み可能なUIを提供します。ユーザー接続、リソース選択、およびリリースプロセスを処理し、複雑なワークフローを単一のコンポーネントに簡素化します。
|
|
309
|
+
|
|
310
|
+
### 目標
|
|
311
|
+
|
|
312
|
+
ダイアログを開くボタンを追加し、ユーザーがブロックレットからファイルと依存コンポーネントを選択して公開できるようにします。
|
|
313
|
+
|
|
314
|
+
### 前提条件
|
|
315
|
+
|
|
316
|
+
- 利用可能なリソースのリストを返す、ブロックレット内のAPIエンドポイント。
|
|
317
|
+
- 公開UIを提供するコンポーネント(「スタジオ」コンポーネント)のDID。
|
|
318
|
+
|
|
319
|
+
### 手順
|
|
320
|
+
|
|
321
|
+
1. **`BlockletStudio`をインポートして状態を管理する**
|
|
322
|
+
|
|
323
|
+
コンポーネントの状態を使用して、スタジオダイアログの可視性を管理する必要があります。
|
|
324
|
+
|
|
325
|
+
```javascript
|
|
326
|
+
import { useState } from 'react';
|
|
327
|
+
import { BlockletStudio } from '@arcblock/ux/lib/BlockletStudio';
|
|
328
|
+
import { Button, CircularProgress } from '@mui/material';
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
2. **コンポーネントをレンダリングする**
|
|
332
|
+
|
|
333
|
+
`<BlockletStudio />`コンポーネントをアプリに配置し、`open`と`setOpen`プロップでその可視性を制御します。
|
|
334
|
+
|
|
335
|
+
3. **必須のプロップを設定する**
|
|
336
|
+
|
|
337
|
+
- `componentDid`: 公開サービスを提供するスタジオブロックレットのDID。
|
|
338
|
+
- `title`、`description`: 公開されるアイテムのメタデータ。
|
|
339
|
+
- `resourcesParams`: リソース取得APIにクエリパラメータとして渡されるオブジェクト。
|
|
340
|
+
- `components`: 事前に選択または必須とされるコンポーネントの配列。
|
|
341
|
+
- `resources`: 事前に選択するリソースを指定するオブジェクト。
|
|
342
|
+
|
|
343
|
+
4. **ライフサイクルイベントを処理する**
|
|
344
|
+
|
|
345
|
+
`onOpened`、`onUploaded`、および`onReleased`コールバックを使用して、ローディングスピナーを非表示にしたり、成功メッセージを表示したりするなど、公開ライフサイクル内のイベントに応答します。
|
|
346
|
+
|
|
347
|
+
### 完全な例
|
|
348
|
+
|
|
349
|
+
この例は、クリックすると`BlockletStudio`ダイアログを開くボタンを示しています。また、より良いユーザーエクスペリエンスのためにローディング状態を管理する方法も示しています。
|
|
350
|
+
|
|
351
|
+
```javascript BlockletStudioでリソースを公開する方法 icon=logos:react
|
|
352
|
+
import { useState } from 'react';
|
|
353
|
+
import { Button, CircularProgress } from '@mui/material';
|
|
354
|
+
import { BlockletStudio } from '@arcblock/ux/lib/BlockletStudio';
|
|
355
|
+
|
|
356
|
+
// スタジオ/公開UIを提供するブロックレットのDID
|
|
357
|
+
const AI_STUDIO_COMPONENT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9'; // DIDの例
|
|
358
|
+
|
|
359
|
+
export default function PublisherGuide() {
|
|
360
|
+
const [isStudioOpen, setStudioOpen] = useState(false);
|
|
361
|
+
const [isOpening, setOpening] = useState(false);
|
|
362
|
+
|
|
363
|
+
const handleShowDialog = () => {
|
|
364
|
+
setOpening(true);
|
|
365
|
+
setStudioOpen(true);
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
return (
|
|
369
|
+
<>
|
|
370
|
+
<Button
|
|
371
|
+
variant="contained"
|
|
372
|
+
onClick={handleShowDialog}
|
|
373
|
+
disabled={isOpening}
|
|
374
|
+
startIcon={isOpening ? <CircularProgress size={16} /> : null}>
|
|
375
|
+
Publish to Studio
|
|
376
|
+
</Button>
|
|
377
|
+
|
|
378
|
+
<BlockletStudio
|
|
379
|
+
// ダイアログの可視性を制御します
|
|
380
|
+
open={isStudioOpen}
|
|
381
|
+
setOpen={setStudioOpen}
|
|
382
|
+
// 公開されるアイテムの基本情報
|
|
383
|
+
title="My Demo Project"
|
|
384
|
+
description="This is a project published from my blocklet."
|
|
385
|
+
// スタジオサービスコンポーネントのDID
|
|
386
|
+
componentDid={AI_STUDIO_COMPONENT_DID}
|
|
387
|
+
// ブロックレットのリソースAPIに送信されるパラメータ
|
|
388
|
+
resourcesParams={{ projectId: 'test-project-123' }}
|
|
389
|
+
// 事前に選択されたコンポーネント
|
|
390
|
+
components={[
|
|
391
|
+
{ did: 'z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ', included: true, required: true },
|
|
392
|
+
{ did: 'z2qZyjnsRffFtn2PDnDwDHTRbAu53RpKqDtFZ', included: true, required: false },
|
|
393
|
+
]}
|
|
394
|
+
// 事前に選択されたリソース
|
|
395
|
+
resources={{
|
|
396
|
+
// キーはリソースプロバイダーブロックレットのDIDです
|
|
397
|
+
z8iZpog7mcgcgBZzTiXJCWESvmnRrQmnd3XBB: [
|
|
398
|
+
'template-448698592710885376',
|
|
399
|
+
'example-448698592710885376',
|
|
400
|
+
],
|
|
401
|
+
}}
|
|
402
|
+
// イベントハンドラ
|
|
403
|
+
onOpened={() => setOpening(false)}
|
|
404
|
+
onUploaded={() => alert('Upload complete!')}
|
|
405
|
+
onReleased={() => {
|
|
406
|
+
alert('Successfully released!');
|
|
407
|
+
setStudioOpen(false);
|
|
408
|
+
}}
|
|
409
|
+
/>
|
|
410
|
+
</>
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
```
|