@blocklet/ui-react 3.1.48 → 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 Hook の詳細なリファレンスを提供します。これらのフックは、ステートフルなロジックをカプセル化して再利用するように設計されており、Blocklet 環境内での一般的なタスクやインタラクションを簡素化します。
|
|
4
|
+
|
|
5
|
+
## useComponentInstalled
|
|
6
|
+
|
|
7
|
+
このフックは、指定された1つ以上のオプションコンポーネント(DID によって識別される)がインストールされているかどうかをチェックします。これは、他の Blocklet を依存関係として利用する機能を実装するために不可欠です。このフックは、インストールのステータスと、必要に応じてユーザーにインストールを促すために必要な URL を提供します。
|
|
8
|
+
|
|
9
|
+
### パラメータ
|
|
10
|
+
|
|
11
|
+
このフックは、以下のプロパティを持つ単一のオブジェクトを受け入れます:
|
|
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>指定された1つ以上のコンポーネントがインストールされていない場合にトリガーされるオプションのコールバック関数。</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
|
+
// コンポーネントが存在しない場合は、インストーラー UI をレンダリングします
|
|
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
|
+
このフックは、現在認証されているユーザーと、その 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
|
+
レスポンシブコンポーネントを作成するためのシンプルなユーティリティフックです。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'`)または比較対象のピクセル値。画面幅がこの値より小さい場合にフックは `true` を返します。</x-field-desc>
|
|
165
|
+
</x-field>
|
|
166
|
+
</x-field-group>
|
|
167
|
+
|
|
168
|
+
### 戻り値
|
|
169
|
+
|
|
170
|
+
`boolean` 値を返します。ビューポートが指定されたブレークポイントより小さい場合は `true`、そうでない場合は `false` です。
|
|
171
|
+
|
|
172
|
+
### 使用例
|
|
173
|
+
|
|
174
|
+
このフックは、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
|
+
// フックを使用するコンポーネント
|
|
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
|
+
これらのフックを使用することで、最小限のボイラープレートコードで複雑な機能を効率的に実装できます。これらのフックを使用する可能性のあるコンポーネントの詳細については、[コンポーネント](./components.md) のドキュメントを参照してください。
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Hooks API
|
|
2
|
+
|
|
3
|
+
This section provides a detailed reference for the custom React Hooks available within the library. These hooks are designed to encapsulate and reuse stateful logic, simplifying common tasks and interactions within a Blocklet environment.
|
|
4
|
+
|
|
5
|
+
## useComponentInstalled
|
|
6
|
+
|
|
7
|
+
This hook checks whether one or more specified optional components (identified by their DIDs) are installed. It is essential for implementing features that rely on other Blocklets as dependencies. The hook provides the installation status and necessary URLs to prompt the user for installation if required.
|
|
8
|
+
|
|
9
|
+
### Parameters
|
|
10
|
+
|
|
11
|
+
The hook accepts a single object with the following properties:
|
|
12
|
+
|
|
13
|
+
<x-field-group>
|
|
14
|
+
<x-field data-name="did" data-type="string | string[]" data-required="true">
|
|
15
|
+
<x-field-desc markdown>The Decentralized Identifier (DID) or an array of DIDs for the component(s) to check. A single string can contain multiple DIDs separated by `;;`.</x-field-desc>
|
|
16
|
+
</x-field>
|
|
17
|
+
<x-field data-name="onInstalled" data-type="function" data-required="false">
|
|
18
|
+
<x-field-desc markdown>An optional callback function that is triggered when all specified components are already installed.</x-field-desc>
|
|
19
|
+
</x-field>
|
|
20
|
+
<x-field data-name="onError" data-type="function" data-required="false">
|
|
21
|
+
<x-field-desc markdown>An optional callback function that is triggered when one or more specified components are not installed.</x-field-desc>
|
|
22
|
+
</x-field>
|
|
23
|
+
</x-field-group>
|
|
24
|
+
|
|
25
|
+
### Returns
|
|
26
|
+
|
|
27
|
+
It returns an object containing the installation state and related data:
|
|
28
|
+
|
|
29
|
+
<x-field-group>
|
|
30
|
+
<x-field data-name="optComponents" data-type="array">
|
|
31
|
+
<x-field-desc markdown>An array of component objects that are not installed. Each object includes metadata such as `meta.did`, `storeUrl`, and `installUrl`.</x-field-desc>
|
|
32
|
+
</x-field>
|
|
33
|
+
<x-field data-name="installed" data-type="boolean">
|
|
34
|
+
<x-field-desc markdown>A boolean value that is `true` if all specified components are installed and defined in the `blocklet.yml`, and `false` otherwise.</x-field-desc>
|
|
35
|
+
</x-field>
|
|
36
|
+
<x-field data-name="installStatus" data-type="object">
|
|
37
|
+
<x-field-desc markdown>An object where keys are component DIDs and values are their current installation status (e.g., 'waiting', 'installing'). This state is updated via `window.postMessage` events.</x-field-desc>
|
|
38
|
+
</x-field>
|
|
39
|
+
<x-field data-name="setInstallStatus" data-type="function">
|
|
40
|
+
<x-field-desc markdown>The state setter function to manually update the `installStatus` object.</x-field-desc>
|
|
41
|
+
</x-field>
|
|
42
|
+
<x-field data-name="definedInBlockletYML" data-type="boolean">
|
|
43
|
+
<x-field-desc markdown>A boolean indicating whether the component is defined in the blocklet's configuration (`blocklet.yml`).</x-field-desc>
|
|
44
|
+
</x-field>
|
|
45
|
+
</x-field-group>
|
|
46
|
+
|
|
47
|
+
### Example Usage
|
|
48
|
+
|
|
49
|
+
The following example demonstrates how to use `useComponentInstalled` to conditionally render a feature or a `ComponentInstaller` component if a dependency is missing.
|
|
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'; // Example DID
|
|
56
|
+
|
|
57
|
+
function ComponentFeature() {
|
|
58
|
+
const { installed, optComponents } = useComponentInstalled({ did: REQUIRED_DID });
|
|
59
|
+
|
|
60
|
+
if (!installed) {
|
|
61
|
+
// Render the installer UI if the component is not present
|
|
62
|
+
return <ComponentInstaller components={optComponents} />;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Render the feature that depends on the installed component
|
|
66
|
+
return (
|
|
67
|
+
<div>
|
|
68
|
+
<h2>My Feature</h2>
|
|
69
|
+
<p>This feature requires the component with DID: {REQUIRED_DID}</p>
|
|
70
|
+
{/* ... feature implementation ... */}
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default ComponentFeature;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## useFollow
|
|
79
|
+
|
|
80
|
+
This hook manages the following relationship between the currently authenticated user and another user specified by their DID. It handles the API calls for following and unfollowing, and provides the current follow status.
|
|
81
|
+
|
|
82
|
+
### Parameters
|
|
83
|
+
|
|
84
|
+
<x-field-group>
|
|
85
|
+
<x-field data-name="userDid" data-type="string" data-required="true">
|
|
86
|
+
<x-field-desc markdown>The DID of the user profile to check the follow status against.</x-field-desc>
|
|
87
|
+
</x-field>
|
|
88
|
+
<x-field data-name="t" data-type="function" data-required="true">
|
|
89
|
+
<x-field-desc markdown>A translation function used for displaying success or error messages (e.g., from `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>A boolean that should be set to `true` if the `userDid` belongs to the currently logged-in user.</x-field-desc>
|
|
93
|
+
</x-field>
|
|
94
|
+
</x-field-group>
|
|
95
|
+
|
|
96
|
+
### Returns
|
|
97
|
+
|
|
98
|
+
Returns an object with the following properties:
|
|
99
|
+
|
|
100
|
+
<x-field-group>
|
|
101
|
+
<x-field data-name="followed" data-type="boolean">
|
|
102
|
+
<x-field-desc markdown>Indicates if the current user is following the user specified by `userDid`. `true` if following, `false` otherwise.</x-field-desc>
|
|
103
|
+
</x-field>
|
|
104
|
+
<x-field data-name="followUser" data-type="function">
|
|
105
|
+
<x-field-desc markdown>A stable function to call to follow the user. It handles the API request and updates the `followed` state on success.</x-field-desc>
|
|
106
|
+
</x-field>
|
|
107
|
+
<x-field data-name="unfollowUser" data-type="function">
|
|
108
|
+
<x-field-desc markdown>A stable function to call to unfollow the user. It handles the API request and updates the `followed` state on success.</x-field-desc>
|
|
109
|
+
</x-field>
|
|
110
|
+
</x-field-group>
|
|
111
|
+
|
|
112
|
+
### Example Usage
|
|
113
|
+
|
|
114
|
+
This example shows how to create a `FollowButton` component that displays a "Follow" or "Unfollow" action based on the relationship status.
|
|
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; // Do not show button on your own profile
|
|
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
|
+
A simple utility hook for creating responsive components. It leverages Material-UI's `useMediaQuery` to determine if the current viewport width is below a specified breakpoint.
|
|
159
|
+
|
|
160
|
+
### Parameters
|
|
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>The Material-UI breakpoint key (e.g., `'xs'`, `'sm'`, `'md'`) or a pixel value to check against. The hook returns `true` if the screen width is smaller than this value.</x-field-desc>
|
|
165
|
+
</x-field>
|
|
166
|
+
</x-field-group>
|
|
167
|
+
|
|
168
|
+
### Returns
|
|
169
|
+
|
|
170
|
+
Returns a `boolean` value: `true` if the viewport is smaller than the specified breakpoint, `false` otherwise.
|
|
171
|
+
|
|
172
|
+
### Example Usage
|
|
173
|
+
|
|
174
|
+
This hook must be used within a component tree that is wrapped by a 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
|
+
// A component that uses the hook
|
|
183
|
+
function ResponsiveComponent() {
|
|
184
|
+
const isMobile = useMobile({ key: 'md' }); // Check against the 'md' breakpoint
|
|
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
|
+
// The component must be wrapped in a 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
|
+
By using these hooks, you can efficiently implement complex features with minimal boilerplate code. For more information on the components that might use these hooks, please see the [Components](./components.md) documentation.
|
|
@@ -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
|
+
// 如果元件不存在,則渲染安裝程式 UI
|
|
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)文件。
|