@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.
Files changed (98) hide show
  1. package/.aigne/doc-smith/config.yaml +76 -0
  2. package/.aigne/doc-smith/history.yaml +9 -0
  3. package/.aigne/doc-smith/output/structure-plan.json +249 -0
  4. package/.aigne/doc-smith/upload-cache.yaml +528 -0
  5. package/docs/_sidebar.md +19 -0
  6. package/docs/components-component-management-blocklet-studio.ja.md +194 -0
  7. package/docs/components-component-management-blocklet-studio.md +194 -0
  8. package/docs/components-component-management-blocklet-studio.zh-TW.md +194 -0
  9. package/docs/components-component-management-blocklet-studio.zh.md +194 -0
  10. package/docs/components-component-management-component-installer.ja.md +256 -0
  11. package/docs/components-component-management-component-installer.md +256 -0
  12. package/docs/components-component-management-component-installer.zh-TW.md +256 -0
  13. package/docs/components-component-management-component-installer.zh.md +256 -0
  14. package/docs/components-component-management.ja.md +59 -0
  15. package/docs/components-component-management.md +59 -0
  16. package/docs/components-component-management.zh-TW.md +59 -0
  17. package/docs/components-component-management.zh.md +59 -0
  18. package/docs/components-layout-dashboard.ja.md +231 -0
  19. package/docs/components-layout-dashboard.md +231 -0
  20. package/docs/components-layout-dashboard.zh-TW.md +231 -0
  21. package/docs/components-layout-dashboard.zh.md +231 -0
  22. package/docs/components-layout-footer.ja.md +165 -0
  23. package/docs/components-layout-footer.md +165 -0
  24. package/docs/components-layout-footer.zh-TW.md +165 -0
  25. package/docs/components-layout-footer.zh.md +165 -0
  26. package/docs/components-layout-header.ja.md +233 -0
  27. package/docs/components-layout-header.md +233 -0
  28. package/docs/components-layout-header.zh-TW.md +233 -0
  29. package/docs/components-layout-header.zh.md +233 -0
  30. package/docs/components-layout.ja.md +50 -0
  31. package/docs/components-layout.md +50 -0
  32. package/docs/components-layout.zh-TW.md +50 -0
  33. package/docs/components-layout.zh.md +50 -0
  34. package/docs/components-notifications.ja.md +173 -0
  35. package/docs/components-notifications.md +173 -0
  36. package/docs/components-notifications.zh-TW.md +174 -0
  37. package/docs/components-notifications.zh.md +173 -0
  38. package/docs/components-user-management-user-center.ja.md +183 -0
  39. package/docs/components-user-management-user-center.md +183 -0
  40. package/docs/components-user-management-user-center.zh-TW.md +183 -0
  41. package/docs/components-user-management-user-center.zh.md +183 -0
  42. package/docs/components-user-management-user-sessions.ja.md +164 -0
  43. package/docs/components-user-management-user-sessions.md +164 -0
  44. package/docs/components-user-management-user-sessions.zh-TW.md +164 -0
  45. package/docs/components-user-management-user-sessions.zh.md +164 -0
  46. package/docs/components-user-management.ja.md +76 -0
  47. package/docs/components-user-management.md +76 -0
  48. package/docs/components-user-management.zh-TW.md +76 -0
  49. package/docs/components-user-management.zh.md +76 -0
  50. package/docs/components-utilities-icon.ja.md +106 -0
  51. package/docs/components-utilities-icon.md +106 -0
  52. package/docs/components-utilities-icon.zh-TW.md +106 -0
  53. package/docs/components-utilities-icon.zh.md +106 -0
  54. package/docs/components-utilities.ja.md +136 -0
  55. package/docs/components-utilities.md +136 -0
  56. package/docs/components-utilities.zh-TW.md +136 -0
  57. package/docs/components-utilities.zh.md +136 -0
  58. package/docs/components.ja.md +27 -0
  59. package/docs/components.md +27 -0
  60. package/docs/components.zh-TW.md +27 -0
  61. package/docs/components.zh.md +27 -0
  62. package/docs/core-concepts.ja.md +164 -0
  63. package/docs/core-concepts.md +164 -0
  64. package/docs/core-concepts.zh-TW.md +164 -0
  65. package/docs/core-concepts.zh.md +164 -0
  66. package/docs/getting-started.ja.md +132 -0
  67. package/docs/getting-started.md +132 -0
  68. package/docs/getting-started.zh-TW.md +132 -0
  69. package/docs/getting-started.zh.md +132 -0
  70. package/docs/hooks-api.ja.md +214 -0
  71. package/docs/hooks-api.md +214 -0
  72. package/docs/hooks-api.zh-TW.md +214 -0
  73. package/docs/hooks-api.zh.md +214 -0
  74. package/docs/how-to-guides.ja.md +413 -0
  75. package/docs/how-to-guides.md +413 -0
  76. package/docs/how-to-guides.zh-TW.md +413 -0
  77. package/docs/how-to-guides.zh.md +413 -0
  78. package/docs/overview.ja.md +91 -0
  79. package/docs/overview.md +91 -0
  80. package/docs/overview.zh-TW.md +91 -0
  81. package/docs/overview.zh.md +91 -0
  82. package/glossary.md +12 -0
  83. package/lib/Dashboard/index.js +46 -42
  84. package/lib/Footer/index.js +51 -36
  85. package/lib/Header/index.js +48 -44
  86. package/lib/UserCenter/components/settings.js +1 -0
  87. package/lib/UserCenter/components/user-center.js +133 -133
  88. package/lib/blocklets.d.ts +13 -2
  89. package/lib/blocklets.js +40 -40
  90. package/lib/common/header-addons.js +37 -33
  91. package/package.json +7 -7
  92. package/src/Dashboard/index.jsx +8 -3
  93. package/src/Footer/index.jsx +22 -4
  94. package/src/Header/index.tsx +7 -2
  95. package/src/UserCenter/components/settings.tsx +1 -0
  96. package/src/UserCenter/components/user-center.tsx +6 -6
  97. package/src/blocklets.js +18 -9
  98. package/src/common/header-addons.jsx +7 -2
@@ -0,0 +1,413 @@
1
+ # 操作指南
2
+
3
+ 本節提供了實用的逐步指南,用於完成常見任務和使用該函式庫的元件實作特定工作流程。每個指南都設計為一組獨立的說明,旨在幫助您高效地達成特定成果。
4
+
5
+ <x-cards data-columns="2">
6
+ <x-card data-title="為 Header 新增自訂元素" data-icon="lucide:layout-template" data-href="#how-to-add-custom-elements-to-the-header">
7
+ 了解如何使用 `addons` render prop 來擴展 `Header` 元件,新增自訂按鈕、導覽或其他互動元素。
8
+ </x-card>
9
+ <x-card data-title="處理可選元件依賴" data-icon="lucide:puzzle" data-href="#how-to-handle-optional-component-dependencies">
10
+ 實作一個工作流程,提示管理員按需安裝必要的元件,確保您的 blocklet 功能順暢執行。
11
+ </x-card>
12
+ <x-card data-title="實作即時使用者通知" data-icon="lucide:bell-ring" data-href="#how-to-implement-real-time-user-notifications">
13
+ 使用 WebSockets 設定一個即時通知系統,讓使用者隨時了解您應用程式中的重要事件。
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
+ ## 如何為 Header 新增自訂元素
23
+
24
+ `Header` 元件被設計為可擴展的。您可以利用 `addons` prop,直接將自訂按鈕、搜尋欄或其他 React 元件新增到 Header 中。
25
+
26
+ ### 目標
27
+
28
+ 在主應用程式 Header 中新增一個自訂的「聊天」按鈕、一個搜尋輸入框以及額外的操作圖示。
29
+
30
+ ### 先決條件
31
+
32
+ - 一個已安裝 `@arcblock/ux` 函式庫且功能正常的 React 應用程式。
33
+ - 一個現有的 `<Header>` 元件實例。更多資訊,請參閱 [Header 元件文件](./components-layout-header.md)。
34
+
35
+ ### 步驟
36
+
37
+ `addons` prop 接受一個 render 函式。此函式會接收預設的插件(如 session 管理器)作為其第一個參數,讓您能夠決定將自訂元素放置在相對於預設插件的位置。
38
+
39
+ 1. **定義 `addons` Render Prop**
40
+
41
+ 在您的 `Header` 元件中,將一個函式傳遞給 `addons` prop。此函式應返回您想要渲染的 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
+ 在 render 函式內部,您可以新增任何您需要的元件。在此範例中,我們將新增一個標準的 Material-UI `Button`、幾個用於圖示的 `AddonButton` 元件以及一個 `Divider`。
61
+
62
+ 3. **與預設插件結合**
63
+
64
+ 標準作法是渲染傳入函式的 `defaultAddons`。這能確保如地區設定切換器和 session 管理器等基本元素仍然顯示。您可以將自訂元件放置在 `defaultAddons` 之前或之後。
65
+
66
+ ### 完整範例
67
+
68
+ 以下是一個完整的範例,示範如何將多個自訂元素新增到 Header。這包括導覽、按鈕和圖示,並與預設的 session 管理器一同渲染。
69
+
70
+ ```javascript 如何為 Header 新增自訂元素 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
+ // ... 其他 session 屬性
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. 渲染預設插件 (包含 session 管理器) */}
128
+ {defaultAddons}
129
+ </>
130
+ )}
131
+ />
132
+ </SessionContext.Provider>
133
+ );
134
+ }
135
+ ```
136
+
137
+ ---
138
+
139
+ ## 如何處理可選元件依賴
140
+
141
+ 許多 blocklets 依賴其他元件來提供特定功能。`ComponentInstaller` 讓您能夠建構依賴於可選元件的功能,如果這些元件未被安裝,它會為管理員提供一個友善的介面來安裝它們。
142
+
143
+ ### 目標
144
+
145
+ 保護一個需要安裝另一個 blocklet 元件才能使用的功能。如果該元件缺失,管理員將會看到一個安裝介面,而其他使用者則不會看到任何內容。
146
+
147
+ ### 先決條件
148
+
149
+ - 您的應用程式中有一個依賴其他元件的功能(例如,一個需要「Media Kit」blocklet 的「媒體管理器」)。
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` prop。如果有多個依賴項,這可以是一個字串或一個字串陣列。
170
+
171
+ 4. **為非管理員配置行為**
172
+
173
+ 使用 `noPermissionMute` prop。當設定為 `true` 時,沒有權限安裝元件的使用者(即非管理員)將不會看到安裝提示。您可以提供一個 `fallback` 元件來替代顯示。
174
+
175
+ ### 完整範例
176
+
177
+ 在此情境中,我們有一個 `MyFeatureButton`,只有在 DID 為 `z8ia...` 的元件被安裝後才應渲染。
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` 元件是一個現成的解決方案,用於在 Header 中顯示未讀通知計數。
218
+
219
+ ### 目標
220
+
221
+ 在應用程式 Header 中新增一個通知鈴鐺圖示,該圖示會顯示帶有未讀通知數量的徽章,並即時更新。
222
+
223
+ ### 先決條件
224
+
225
+ - 您的 blocklet 必須在支援通知服務的 Blocklet Server 版本(`1.16.42` 或更高)上執行。
226
+ - 一個用於放置通知圖示的 `<Header>` 元件。
227
+ - 一個提供使用者資訊的 session context。
228
+
229
+ ### 關鍵概念
230
+
231
+ - **WebSocket 事件**:當通知被建立或讀取時,Blocklet Server 會廣播事件。
232
+ - **`useListenWsClient`**:一個用於獲取特定頻道(例如 'user')的 WebSocket 客戶端實例的 hook。
233
+ - **事件命名**:事件的作用域限定於使用者和 blocklet。新通知的格式為 `${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. **新增至 Header `addons`**
246
+
247
+ 最簡單的使用方法是將其新增到 `Header` 的 `addons` render prop 中。
248
+
249
+ 3. **傳遞 Session 物件**
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
+ // ... 其他 session 屬性
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
+ 新增一個按鈕,該按鈕會打開一個對話框,允許使用者從 blocklet 中選擇並發布檔案和依賴元件。
313
+
314
+ ### 先決條件
315
+
316
+ - 您的 blocklet 中有一個 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` props 控制其可見性。
334
+
335
+ 3. **配置必要 Props**
336
+
337
+ - `componentDid`:提供發布服務的工作室 blocklet 的 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 的 blocklet 的 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
+ // 發送到您的 blocklet 資源 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
+ // 鍵值是資源提供者 blocklet 的 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
+ ```