Coloring commited on
Commit
e08e97a
·
1 Parent(s): f5c4c58

feat: WebSandbox

Browse files
app.py CHANGED
@@ -149,6 +149,15 @@ pro_menu_items = [{
149
  "label": get_text("MultimodalInput", "MultimodalInput 多模态输入框"),
150
  "key": "multimodal_input"
151
  }]
 
 
 
 
 
 
 
 
 
152
  }]
153
 
154
  antd_menu_items = [{
 
149
  "label": get_text("MultimodalInput", "MultimodalInput 多模态输入框"),
150
  "key": "multimodal_input"
151
  }]
152
+ }, {
153
+ "label":
154
+ get_text("Interactive Preview", "交互式预览"),
155
+ "type":
156
+ "group",
157
+ "children": [{
158
+ "label": get_text("WebSandbox", "WebSandbox 网页沙盒"),
159
+ "key": "web_sandbox"
160
+ }]
161
  }]
162
 
163
  antd_menu_items = [{
components/antd/breadcrumb/demos/basic.py CHANGED
@@ -9,10 +9,10 @@ with gr.Blocks() as demo:
9
  antd.Breadcrumb.Item(title="Ant Design")
10
  with antd.Breadcrumb.Item():
11
  with ms.Slot("title"):
12
- antd.Button(type="link", href="#")
13
  with antd.Breadcrumb.Item():
14
  with ms.Slot("title"):
15
- antd.Button(type="link", href="General")
16
  with ms.Slot("menu.items"):
17
  with antd.Menu.Item(key="1"):
18
  with ms.Slot("label"):
 
9
  antd.Breadcrumb.Item(title="Ant Design")
10
  with antd.Breadcrumb.Item():
11
  with ms.Slot("title"):
12
+ antd.Button("Link", type="link", href="#")
13
  with antd.Breadcrumb.Item():
14
  with ms.Slot("title"):
15
+ antd.Button("General", type="link", href="#")
16
  with ms.Slot("menu.items"):
17
  with antd.Menu.Item(key="1"):
18
  with ms.Slot("label"):
components/base/application/README-zh_CN.md CHANGED
@@ -18,3 +18,38 @@
18
  <demo name="theme_adaptation" title="根据用户界面主题返回不同权重内容"></demo>
19
 
20
  <demo name="custom_event" title="发送自定义事件"></demo>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  <demo name="theme_adaptation" title="根据用户界面主题返回不同权重内容"></demo>
19
 
20
  <demo name="custom_event" title="发送自定义事件"></demo>
21
+
22
+ ## API
23
+
24
+ ### 属性
25
+
26
+ | 属性 | 类型 | 默认值 | 描述 |
27
+ | ----- | ------------------- | ------ | -------- |
28
+ | value | ApplicationPageData | None | 页面数据 |
29
+
30
+ ### 事件
31
+
32
+ | 事件 | 描述 |
33
+ | --------------------------------- | ---------------------------------------------------------------------------- |
34
+ | `ms.Application.mount(fn, ···)` | 当页面加载时触发。 |
35
+ | `ms.Application.resize(fn, ···)` | 当页面尺寸变化时触发。 |
36
+ | `ms.Application.unmount(fn, ···)` | 当页面卸载时触发。 |
37
+ | `ms.Application.custom(fn, ···)` | 当用户在 JavaScript 中调用`window.ms_globals.dispatch`抛出自定义事件时触发。 |
38
+
39
+ ### 类型
40
+
41
+ ```python
42
+
43
+ class ApplicationPageScreenData(GradioModel):
44
+ width: float
45
+ height: float
46
+ scrollX: float
47
+ scrollY: float
48
+
49
+
50
+ class ApplicationPageData(GradioModel):
51
+ screen: ApplicationPageScreenData
52
+ language: str
53
+ theme: str
54
+ userAgent: str
55
+ ```
components/base/application/README.md CHANGED
@@ -18,3 +18,38 @@ In addition, this component provides the `custom` event, you can send events to
18
  <demo name="theme_adaptation" title="Return different weighted content based on user interface theme"></demo>
19
 
20
  <demo name="custom_event" title="Send custom events"></demo>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  <demo name="theme_adaptation" title="Return different weighted content based on user interface theme"></demo>
19
 
20
  <demo name="custom_event" title="Send custom events"></demo>
21
+
22
+ ## API
23
+
24
+ ### Props
25
+
26
+ | Attribute | Type | Default Value | Description |
27
+ | --------- | ------------------- | ------------- | ----------- |
28
+ | value | ApplicationPageData | None | Page data |
29
+
30
+ ### 事件
31
+
32
+ | Event | Description |
33
+ | --------------------------------- | --------------------------------------------------------------------------------------------------- |
34
+ | `ms.Application.mount(fn, ···)` | Triggered when the page is mounted. |
35
+ | `ms.Application.resize(fn, ···)` | Triggered when the page size changes. |
36
+ | `ms.Application.unmount(fn, ···)` | Triggered when the page is unmounted. |
37
+ | `ms.Application.custom(fn, ···)` | Triggered when the user throws a custom event by calling `window.ms_globals.dispatch` in Javascript |
38
+
39
+ ### Types
40
+
41
+ ```python
42
+
43
+ class ApplicationPageScreenData(GradioModel):
44
+ width: float
45
+ height: float
46
+ scrollX: float
47
+ scrollY: float
48
+
49
+
50
+ class ApplicationPageData(GradioModel):
51
+ screen: ApplicationPageScreenData
52
+ language: str
53
+ theme: str
54
+ userAgent: str
55
+ ```
components/base/each/README-zh_CN.md CHANGED
@@ -22,7 +22,9 @@
22
 
23
  <demo name="use_context_value" title="使用 context_value 参数"></demo>
24
 
25
- ### API
 
 
26
 
27
  | 属性 | 类型 | 默认值 | 描述 |
28
  | ------------- | ---- | ------ | ---------------- |
 
22
 
23
  <demo name="use_context_value" title="使用 context_value 参数"></demo>
24
 
25
+ ## API
26
+
27
+ ### 属性
28
 
29
  | 属性 | 类型 | 默认值 | 描述 |
30
  | ------------- | ---- | ------ | ---------------- |
components/base/each/README.md CHANGED
@@ -21,7 +21,9 @@ If you need to add certain unified properties to all list item components, you c
21
 
22
  <demo name="use_context_value" title="Using the context_value Parameter"></demo>
23
 
24
- ### API
 
 
25
 
26
  | Attribute | Type | Default Value | Description |
27
  | ------------- | ---- | ------------- | ----------------------------- |
 
21
 
22
  <demo name="use_context_value" title="Using the context_value Parameter"></demo>
23
 
24
+ ## API
25
+
26
+ ### Props
27
 
28
  | Attribute | Type | Default Value | Description |
29
  | ------------- | ---- | ------------- | ----------------------------- |
components/base/filter/README-zh_CN.md CHANGED
@@ -14,7 +14,7 @@
14
  <demo name="use_as_item" title="使用 as_item 参数"></demo>
15
  <demo name="use_params_mapping" title="使用 params_mapping 参数"></demo
16
 
17
- ### API
18
 
19
  | 属性 | 类型 | 默认值 | 描述 |
20
  | -------------- | ---- | ------ | -------------------------------------------------------------------------------------------- |
 
14
  <demo name="use_as_item" title="使用 as_item 参数"></demo>
15
  <demo name="use_params_mapping" title="使用 params_mapping 参数"></demo
16
 
17
+ ## API
18
 
19
  | 属性 | 类型 | 默认值 | 描述 |
20
  | -------------- | ---- | ------ | -------------------------------------------------------------------------------------------- |
components/base/filter/README.md CHANGED
@@ -14,7 +14,7 @@ If no parameters are provided, this component will block the context transmissio
14
  <demo name="use_as_item" title="Using the as_item Parameter"></demo>
15
  <demo name="use_params_mapping" title="Using the params_mapping Parameter"></demo>
16
 
17
- ### API
18
 
19
  | Property | Type | Default Value | Description |
20
  | -------------- | ---- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
 
14
  <demo name="use_as_item" title="Using the as_item Parameter"></demo>
15
  <demo name="use_params_mapping" title="Using the params_mapping Parameter"></demo>
16
 
17
+ ## API
18
 
19
  | Property | Type | Default Value | Description |
20
  | -------------- | ---- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
components/base/slot/README-zh_CN.md CHANGED
@@ -8,7 +8,7 @@
8
 
9
  <demo name="basic"></demo>
10
 
11
- ### API
12
 
13
  | 属性 | 类型 | 默认值 | 描述 |
14
  | -------------- | ---- | ------ | -------------------------------------------------------------------------------------------------------------------------- |
 
8
 
9
  <demo name="basic"></demo>
10
 
11
+ ## API
12
 
13
  | 属性 | 类型 | 默认值 | 描述 |
14
  | -------------- | ---- | ------ | -------------------------------------------------------------------------------------------------------------------------- |
components/base/slot/README.md CHANGED
@@ -8,7 +8,7 @@ The slots of components in `modelscope_studio` can be viewed by getting the `SLO
8
 
9
  <demo name="basic"></demo>
10
 
11
- ### API
12
 
13
  | Attribute | Type | Default Value | Description |
14
  | -------------- | ---- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
 
8
 
9
  <demo name="basic"></demo>
10
 
11
+ ## API
12
 
13
  | Attribute | Type | Default Value | Description |
14
  | -------------- | ---- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
components/pro/chatbot/README-zh_CN.md CHANGED
@@ -38,9 +38,9 @@
38
 
39
  <demo name="thinking" position="bottom" collapsible="true"></demo>
40
 
41
- ### API
42
 
43
- #### 属性
44
 
45
  | 属性 | 类型 | 默认值 | 描述 |
46
  | ------------------------------ | ----------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- |
@@ -56,7 +56,7 @@
56
  | max_height | `int \| float \| str \| None` | None | 组件的最大高度,如果传递的是数字,则以像素为单位指定,如果传递的是字符串,则以 CSS 单位指定。 |
57
  | min_height | `int \| float \| str \| None` | None | 组件的最小高度,如果传递的是数字,则以像素为单位指定,如果传递的是字符串,则以 CSS 单位指定。 |
58
 
59
- #### 事件
60
 
61
  | 事件 | 描述 |
62
  | -------------------------------------------- | ------------------------------------ |
@@ -127,6 +127,11 @@ class ChatbotMarkdownConfig(GradioModel):
127
  "right": "$$",
128
  "display": True
129
  },
 
 
 
 
 
130
  {
131
  "left": "\\(",
132
  "right": "\\)",
 
38
 
39
  <demo name="thinking" position="bottom" collapsible="true"></demo>
40
 
41
+ ## API
42
 
43
+ ### 属性
44
 
45
  | 属性 | 类型 | 默认值 | 描述 |
46
  | ------------------------------ | ----------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- |
 
56
  | max_height | `int \| float \| str \| None` | None | 组件的最大高度,如果传递的是数字,则以像素为单位指定,如果传递的是字符串,则以 CSS 单位指定。 |
57
  | min_height | `int \| float \| str \| None` | None | 组件的最小高度,如果传递的是数字,则以像素为单位指定,如果传递的是字符串,则以 CSS 单位指定。 |
58
 
59
+ ### 事件
60
 
61
  | 事件 | 描述 |
62
  | -------------------------------------------- | ------------------------------------ |
 
127
  "right": "$$",
128
  "display": True
129
  },
130
+ {
131
+ "left": "$",
132
+ "right": "$",
133
+ "display": False
134
+ },
135
  {
136
  "left": "\\(",
137
  "right": "\\)",
components/pro/chatbot/README.md CHANGED
@@ -37,7 +37,7 @@ The `message` object includes all configurations from `bot_config` and `user_con
37
 
38
  <demo name="thinking" position="bottom" collapsible="true"></demo>
39
 
40
- ### API
41
 
42
  ### Props
43
 
@@ -55,7 +55,7 @@ The `message` object includes all configurations from `bot_config` and `user_con
55
  | max_height | `int \| float \| str \| None` | None | The maximum height of the component, specified in pixels if a number is passed, or in CSS units if a string is passed.  |
56
  | min_height | `int \| float \| str \| None` | None | The minimum height of the component, specified in pixels if a number is passed, or in CSS units if a string is passed. |
57
 
58
- #### Events
59
 
60
  | Event | Description |
61
  | -------------------------------------------- | ------------------------------------------------------- |
@@ -126,6 +126,11 @@ class ChatbotMarkdownConfig(GradioModel):
126
  "right": "$$",
127
  "display": True
128
  },
 
 
 
 
 
129
  {
130
  "left": "\\(",
131
  "right": "\\)",
 
37
 
38
  <demo name="thinking" position="bottom" collapsible="true"></demo>
39
 
40
+ ## API
41
 
42
  ### Props
43
 
 
55
  | max_height | `int \| float \| str \| None` | None | The maximum height of the component, specified in pixels if a number is passed, or in CSS units if a string is passed.  |
56
  | min_height | `int \| float \| str \| None` | None | The minimum height of the component, specified in pixels if a number is passed, or in CSS units if a string is passed. |
57
 
58
+ ### Events
59
 
60
  | Event | Description |
61
  | -------------------------------------------- | ------------------------------------------------------- |
 
126
  "right": "$$",
127
  "display": True
128
  },
129
+ {
130
+ "left": "$",
131
+ "right": "$",
132
+ "display": False
133
+ },
134
  {
135
  "left": "\\(",
136
  "right": "\\)",
components/pro/multimodal_input/README-zh_CN.md CHANGED
@@ -24,19 +24,21 @@
24
 
25
  ### 属性
26
 
27
- | 属性 | 类型 | 默认值 | 描述 |
28
- | ------------- | --------------------------------------------- | ------- | ------------------------------------------------------ |
29
- | value | `dict \| MultimodalInputValue \| None` | None | 显示的默认值,格式为`{ "text":"", "files":[] }`。 |
30
- | loading | `bool \| None` | None | 输入框是否处处于加载状态,此时可以触发 `cancel` 事件。 |
31
- | read_only | `bool \| None` | None | 输入框是否为只读状态。 |
32
- | submit_type | `Literal['enter', 'shiftEnter'] \| None` | 'enter' | 输入框触发`submit`事件的方式。 |
33
- | placeholder | `str \| None` | None | 输入框的提示信息。 |
34
- | upload_config | `MultimodalInputUploadConfig \| dict \| None` | None | 文件上传配置。 |
 
 
35
 
36
  ### 插槽
37
 
38
  ```python
39
- SLOTS=["prefix"]
40
  ```
41
 
42
  ### 类型
 
24
 
25
  ### 属性
26
 
27
+ | 属性 | 类型 | 默认值 | 描述 |
28
+ | ------------- | -------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------- |
29
+ | value | `dict \| MultimodalInputValue \| None` | None | 显示的默认值,格式为`{ "text":"", "files":[] }`。 |
30
+ | loading | `bool \| None` | None | 输入框是否处处于加载状态,此时可以触发 `cancel` 事件。 |
31
+ | auto_size | `bool \| { minRows?: number; maxRows?: number } \| None` | { "maxRows": 8 } | 自适应内容高度,可设置为 True \| False 或对象:{ "minRows": 2, "maxRows": 6 }。 |
32
+ | read_only | `bool \| None` | None | 输入框是否为只读状态。 |
33
+ | submit_type | `Literal['enter', 'shiftEnter'] \| None` | 'enter' | 输入框触发`submit`事件的方式。 |
34
+ | placeholder | `str \| None` | None | 输入框的提示信息。 |
35
+ | disabled | `bool \| None` | None | 是否禁用。 |
36
+ | upload_config | `MultimodalInputUploadConfig \| dict \| None` | None | 文件上传配置。 |
37
 
38
  ### 插槽
39
 
40
  ```python
41
+ SLOTS=['actions', "prefix", 'footer', 'header']
42
  ```
43
 
44
  ### 类型
components/pro/multimodal_input/README.md CHANGED
@@ -24,19 +24,21 @@ A multimodal input component based on [Ant Design X](https://x.ant.design), supp
24
 
25
  ### Props
26
 
27
- | Attribute | Type | Default Value | Description |
28
- | ------------- | --------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------- |
29
- | value | `dict \| MultimodalInputValue \| None` | None | Default value to display, formatted as `{ "text":"", "files":[] }`. |
30
- | loading | `bool \| None` | None | Whether the input is in a loading state, in which case the `cancel` event can be triggered. |
31
- | read_only | `bool \| None` | None | Whether the input is read-only. |
32
- | submit_type | `Literal['enter', 'shiftEnter'] \| None` | 'enter' | How the input box triggers the `submit` event. |
33
- | placeholder | `str \| None` | None | Input placeholder text. |
34
- | upload_config | `MultimodalInputUploadConfig \| dict \| None` | None | File upload configuration. |
 
 
35
 
36
  ### Slots
37
 
38
  ```python
39
- SLOTS = ["prefix"]
40
  ```
41
 
42
  ### Types
@@ -102,5 +104,4 @@ class MultimodalInputUploadConfig(GradioModel):
102
  class MultimodalInputValue(GradioModel):
103
  files: Optional[ListFiles] = None
104
  text: Optional[str] = None
105
-
106
  ```
 
24
 
25
  ### Props
26
 
27
+ | Attribute | Type | Default Value | Description |
28
+ | ------------- | -------------------------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------- |
29
+ | value | `dict \| MultimodalInputValue \| None` | None | Default value to display, formatted as `{ "text":"", "files":[] }`. |
30
+ | loading | `bool \| None` | None | Whether the input is in a loading state, in which case the `cancel` event can be triggered. |
31
+ | auto_size | `bool \| { minRows?: number; maxRows?: number } \| None` | { "maxRows": 8 } | Height auto size feature, can be set to True \| False or an object { "minRows": 2, "maxRows": 6 }. |
32
+ | read_only | `bool \| None` | None | Whether the input is read-only. |
33
+ | submit_type | `Literal['enter', 'shiftEnter'] \| None` | 'enter' | How the input box triggers the `submit` event. |
34
+ | placeholder | `str \| None` | None | Input placeholder text. |
35
+ | disabled | `bool \| None` | None | Whether to disable. |
36
+ | upload_config | `MultimodalInputUploadConfig \| dict \| None` | None | File upload configuration. |
37
 
38
  ### Slots
39
 
40
  ```python
41
+ SLOTS=['actions', "prefix", 'footer', 'header']
42
  ```
43
 
44
  ### Types
 
104
  class MultimodalInputValue(GradioModel):
105
  files: Optional[ListFiles] = None
106
  text: Optional[str] = None
 
107
  ```
components/pro/web_sandbox/README-zh_CN.md ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # WebSandbox
2
+
3
+ 前端代码沙箱组件,能够将`React`或`HTML`类型的前端代码在页面编译并预览。
4
+
5
+ ## 示例
6
+
7
+ ### 预览 React 代码
8
+
9
+ 当`template`为`react`时,会自动在`imports`参数中添加以下依赖,当需要特定的某个 React 版本时,可以通过覆盖对应的 key 进行修改:
10
+
11
+ ```json
12
+ {
13
+ "react": "https://esm.sh/react",
14
+ "react/": "https://esm.sh/react/",
15
+ "react-dom": "https://esm.sh/react-dom",
16
+ "react-dom/": "https://esm.sh/react-dom/"
17
+ }
18
+ ```
19
+
20
+ <demo name="react"></demo>
21
+
22
+ ### 预览 HTML 代码
23
+
24
+ <demo name="html"></demo>
25
+
26
+ ### 处理错误
27
+
28
+ <demo name="error_handling"></demo>
29
+
30
+ ## API 
31
+
32
+ ### 属性
33
+
34
+ | 属性 | 类型 | 默认值 | 描述 |
35
+ | -------------------- | ---------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36
+ | value | `Dict[str, Union[str, SandboxFileData]]` | None | 传入 Sandbox 的文件集合。当`template`为`react`时,`['index.tsx', 'index.jsx', 'index.ts', 'index.js']` 为默认的入口文件,当`template`为`html`时,`['index.html']` 为默认的入口文件。你也可以通过对象的形式填写`is_entry`属性手动指定入口文件。 |
37
+ | template | `Literal['react', 'html']` | 'react' | Sandbox 渲染的模板类型。 |
38
+ | show_render_error | `bool` | True | 是否抛出渲染错误提示。 |
39
+ | show_compile_error | `bool` | True | 是否展示编译失败样式。 |
40
+ | compile_error_render | `str \| None` | None | 自定义编译失败样式,传入类型为 Javascript 的函数字符串。 |
41
+ | imports | `Dict[str, str]` | None | 对应 importmap 中的 imports 字段,见 [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap),可用于添加在线的前端依赖模块。 `template` 为 `react` 时会自动添加以下依赖,当需要特定的某个 React 版本时,可以通过覆盖对应的 key 进行修改: `{ "react": "https://esm.sh/react", "react/": "https://esm.sh/react/", "react-dom": "https://esm.sh/react-dom", "react-dom/": "https://esm.sh/react-dom/" }`。 |
42
+ | height | `str \| float \| int` | 400 | 组件的高度,如果值为数字,则以像素为单位指定,如果传递的是字符串,则以 CSS 单位指定。 |
43
+
44
+ ### 事件
45
+
46
+ | 事件 | 描述 |
47
+ | ----------------------------------------- | --------------------------- |
48
+ | `pro.WebSandbox.compile_success(fn, ···)` | 当 Sandbox 编译成功时触发。 |
49
+ | `pro.WebSandbox.compile_error(fn, ···)` | 当 Sandbox 编译失败时触发。 |
50
+ | `pro.WebSandbox.render_error(fn, ···)` | 当 Sandbox 渲染抛错时触发。 |
51
+
52
+ ### 插槽
53
+
54
+ ```python
55
+ SLOTS=['compileErrorRender']
56
+ ```
57
+
58
+ ### 类型
59
+
60
+ ```python
61
+ class SandboxFileData(TypedDict):
62
+ code: str
63
+ is_entry: Optional[bool]
64
+ ```
components/pro/web_sandbox/README.md ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # WebSandbox
2
+
3
+ A frontend code sandbox component that compiles and previews `React` or `HTML` code in the page.
4
+
5
+ ## Examples
6
+
7
+ ### React Code Preview
8
+
9
+ When `template` is set to `react`, the following dependencies will be automatically added to the `imports` parameter. When a specific React version is needed, you can override the corresponding keys:
10
+
11
+ ```json
12
+ {
13
+ "react": "https://esm.sh/react",
14
+ "react/": "https://esm.sh/react/",
15
+ "react-dom": "https://esm.sh/react-dom",
16
+ "react-dom/": "https://esm.sh/react-dom/"
17
+ }
18
+ ```
19
+
20
+ <demo name="react"></demo>
21
+
22
+ ### HTML Code Preview
23
+
24
+ <demo name="html"></demo>
25
+
26
+ ### Error Handling
27
+
28
+ <demo name="error_handling"></demo>
29
+
30
+ ## API
31
+
32
+ ### Props
33
+
34
+ | Attribute | Type | Default Value | Description |
35
+ | -------------------- | ---------------------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
36
+ | value | `Dict[str, Union[str, SandboxFileData]]` | None | Files collection passed to the Sandbox. When `template` is `react`, `['index.tsx', 'index.jsx', 'index.ts', 'index.js']` are the default entry files. When `template` is `html`, `['index.html']` is the default entry file. You can also manually specify the entry file by setting the `is_entry` property. |
37
+ | template | `Literal['react', 'html']` | 'react' | Template type for Sandbox rendering. |
38
+ | show_render_error | `bool` | True | Whether to show rendering error messages. |
39
+ | show_compile_error | `bool` | True | Whether to show compilation failure styles. |
40
+ | compile_error_render | `str \| None` | None | Custom compilation failure style, passed as a JavaScript function string. |
41
+ | imports | `Dict[str, str]` | None | Corresponds to the imports field in importmap, see [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/script/type/importmap), used for adding online frontend dependencies. When `template` is `react`, React-related dependencies are automatically added as shown in the example above. |
42
+ | height | `str \| float \| int` | 400 | Height of the component. If a number is passed, it's specified in pixels; if a string is passed, it's specified in CSS units. |
43
+
44
+ ### Events
45
+
46
+ | Event | Description |
47
+ | ----------------------------------------- | ------------------------------------------------- |
48
+ | `pro.WebSandbox.compile_success(fn, ···)` | Triggered when Sandbox compilation succeeds. |
49
+ | `pro.WebSandbox.compile_error(fn, ···)` | Triggered when Sandbox compilation fails. |
50
+ | `pro.WebSandbox.render_error(fn, ···)` | Triggered when Sandbox rendering throws an error. |
51
+
52
+ ### Slots
53
+
54
+ ```python
55
+ SLOTS=['compileErrorRender']
56
+ ```
57
+
58
+ ### Types
59
+
60
+ ```python
61
+ class SandboxFileData(TypedDict):
62
+ code: str
63
+ is_entry: Optional[bool]
64
+ ```
components/pro/web_sandbox/app.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from helper.Docs import Docs
2
+
3
+ docs = Docs(__file__)
4
+
5
+ if __name__ == "__main__":
6
+ docs.render().queue().launch()
components/pro/web_sandbox/demos/error_handling.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import modelscope_studio.components.antd as antd
3
+ import modelscope_studio.components.base as ms
4
+ import modelscope_studio.components.pro as pro
5
+
6
+ with gr.Blocks() as demo, ms.Application(), antd.ConfigProvider():
7
+ antd.Divider("Render Error")
8
+ pro.WebSandbox(value={
9
+ "index.tsx":
10
+ """
11
+ export default function App() {
12
+ return <button onClick={() => {
13
+ throw new Error('Test Error');
14
+ } }>Click to throw error</button>;
15
+ }
16
+ """
17
+ },
18
+ template="react")
19
+ antd.Divider("Compile Error")
20
+ pro.WebSandbox(value={}, template="react")
21
+ antd.Divider("Custom Compile Error Render")
22
+ with pro.WebSandbox(value={}, template="react"):
23
+ with ms.Slot("compileErrorRender",
24
+ params_mapping="(message) => ({ sub_title: message })"):
25
+ antd.Result(status="error", title="Compile Error")
26
+
27
+ if __name__ == "__main__":
28
+ demo.queue().launch()
components/pro/web_sandbox/demos/html.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import modelscope_studio.components.antd as antd
3
+ import modelscope_studio.components.base as ms
4
+ import modelscope_studio.components.pro as pro
5
+
6
+ with gr.Blocks() as demo, ms.Application(), antd.ConfigProvider():
7
+ pro.WebSandbox(
8
+ value={
9
+ "./index.html":
10
+ """<!DOCTYPE html>
11
+ <html lang="en">
12
+ <head>
13
+ <meta charset="UTF-8">
14
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
15
+ <title>TODO List</title>
16
+ </head>
17
+ <body>
18
+ <div class="todo-container">
19
+ <h1>TODO List</h1>
20
+ <input type="text" id="taskInput" placeholder="Add a new task...">
21
+ <button id="addButton">Add Task</button>
22
+ <ul id="taskList"></ul>
23
+ </div>
24
+
25
+ <script type="module">
26
+ import "./index.css";
27
+ function addTask() {
28
+ const taskInput = document.getElementById('taskInput');
29
+ const taskText = taskInput.value.trim();
30
+ if (taskText === '') return;
31
+
32
+ const taskList = document.getElementById('taskList');
33
+ const li = document.createElement('li');
34
+ li.textContent = taskText;
35
+
36
+ const deleteButton = document.createElement('button');
37
+ deleteButton.textContent = 'Delete';
38
+ deleteButton.onclick = function() {
39
+ taskList.removeChild(li);
40
+ };
41
+
42
+ li.appendChild(deleteButton);
43
+ taskList.appendChild(li);
44
+
45
+ taskInput.value = '';
46
+ }
47
+ document.getElementById('addButton').onclick = addTask;
48
+ </script>
49
+ </body>
50
+ </html>""",
51
+ "./index.css":
52
+ """body {
53
+ font-family: Arial, sans-serif;
54
+ background-color: #2c3e50;
55
+ color: #ecf0f1;
56
+ display: flex;
57
+ justify-content: center;
58
+ align-items: center;
59
+ height: 100vh;
60
+ margin: 0;
61
+ }
62
+ .todo-container {
63
+ background-color: #34495e;
64
+ padding: 20px;
65
+ border-radius: 8px;
66
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
67
+ width: 300px;
68
+ }
69
+ h1 {
70
+ text-align: center;
71
+ color: #ecf0f1;
72
+ }
73
+ input[type="text"] {
74
+ width: calc(100% - 22px);
75
+ padding: 10px;
76
+ margin-bottom: 10px;
77
+ border: none;
78
+ border-radius: 3px;
79
+ background-color: #ecf0f1;
80
+ color: #2c3e50;
81
+ }
82
+ ul {
83
+ list-style-type: none;
84
+ padding: 0;
85
+ }
86
+ li {
87
+ background-color: #2c3e50;
88
+ margin-bottom: 5px;
89
+ padding: 10px;
90
+ border-radius: 3px;
91
+ display: flex;
92
+ justify-content: space-between;
93
+ align-items: center;
94
+ }
95
+ button {
96
+ background-color: #e74c3c;
97
+ color: #ecf0f1;
98
+ border: none;
99
+ padding: 5px 10px;
100
+ border-radius: 3px;
101
+ cursor: pointer;
102
+ }
103
+ button:hover {
104
+ background-color: #c0392b;
105
+ }"""
106
+ },
107
+ template="html",
108
+ height=600,
109
+ )
110
+
111
+ if __name__ == "__main__":
112
+ demo.queue().launch()
components/pro/web_sandbox/demos/react.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import modelscope_studio.components.antd as antd
3
+ import modelscope_studio.components.base as ms
4
+ import modelscope_studio.components.pro as pro
5
+
6
+ with gr.Blocks() as demo, ms.Application(), antd.ConfigProvider():
7
+ pro.WebSandbox(value={
8
+ "./index.tsx":
9
+ """import Demo from './demo.tsx'
10
+ import "@tailwindcss/browser"
11
+
12
+ export default Demo
13
+ """,
14
+ "./demo.tsx":
15
+ """import { useState, useEffect } from 'react';
16
+
17
+ export default function App() {
18
+ const [messages, setMessages] = useState([
19
+ { id: 1, sender: 'ai', content: 'Hello! I am your AI assistant. How can I help you today?', timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) },
20
+ ]);
21
+ const [inputValue, setInputValue] = useState('');
22
+ const [isTyping, setIsTyping] = useState(false);
23
+ const [darkMode, setDarkMode] = useState(false);
24
+
25
+ // Simulate AI typing effect
26
+ const handleSendMessage = () => {
27
+ if (inputValue.trim() === '') return;
28
+
29
+ const userMessage = {
30
+ id: messages.length + 1,
31
+ sender: 'user',
32
+ content: inputValue,
33
+ timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
34
+ };
35
+
36
+ setMessages((prev) => [...prev, userMessage]);
37
+ setInputValue('');
38
+ setIsTyping(true);
39
+
40
+ // Simulate AI response after delay
41
+ setTimeout(() => {
42
+ const aiResponse = {
43
+ id: messages.length + 2,
44
+ sender: 'ai',
45
+ content: 'I am processing your request and will respond shortly.',
46
+ timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
47
+ };
48
+ setMessages((prev) => [...prev, aiResponse]);
49
+ setIsTyping(false);
50
+ }, 1500);
51
+ };
52
+
53
+ // Handle Enter key press
54
+ const handleKeyPress = (e) => {
55
+ if (e.key === 'Enter') {
56
+ handleSendMessage();
57
+ }
58
+ };
59
+
60
+ // Toggle dark mode
61
+ const toggleDarkMode = () => {
62
+ setDarkMode(!darkMode);
63
+ };
64
+
65
+ useEffect(() => {
66
+ const app = document.documentElement;
67
+ if (darkMode) {
68
+ app.classList.add('dark');
69
+ } else {
70
+ app.classList.remove('dark');
71
+ }
72
+ }, [darkMode]);
73
+
74
+ return (
75
+ <div className={"min-h-screen flex flex-col transition-colors duration-300 " + (darkMode ? 'bg-gray-900 text-white' : 'bg-gray-100 text-gray-900')}>
76
+ {/* Header */}
77
+ <header className={"px-6 py-4 shadow-md flex justify-between items-center " + (darkMode ? 'bg-gray-800' : 'bg-white')}>
78
+ <div className="flex items-center space-x-2">
79
+ <svg width="32" height="32" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" className="text-blue-500">
80
+ <path d="M12 4L4 8V16L12 20L20 16V8L12 4Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
81
+ <path d="M12 15L9 12H15L12 9V15Z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
82
+ </svg>
83
+ <h1 className="text-xl font-bold">Chatbot</h1>
84
+ </div>
85
+ <button onClick={toggleDarkMode} className="p-2 rounded-full hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
86
+ {darkMode ? (
87
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
88
+ <circle cx="12" cy="12" r="5" stroke="white" strokeWidth="2"/>
89
+ <path d="M12 2V4M12 20V22M4 12H2M6.31 6.31L4.9 4.9M17.69 6.31L19.1 4.9M6.31 17.69L4.9 19.1M17.69 17.69L19.1 19.1" stroke="white" strokeWidth="2" strokeLinecap="round"/>
90
+ </svg>
91
+ ) : (
92
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
93
+ <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
94
+ </svg>
95
+ )}
96
+ </button>
97
+ </header>
98
+
99
+ {/* Chat Area */}
100
+ <div className="flex-1 overflow-y-auto p-4 space-y-4">
101
+ {messages.map((message) => (
102
+ <div
103
+ key={message.id}
104
+ className={"flex " + (message.sender === 'user' ? 'justify-end' : 'justify-start')}
105
+ >
106
+ <div
107
+ className={"max-w-xs sm:max-w-md px-4 py-2 rounded-lg " +
108
+ (message.sender === 'user'
109
+ ? 'bg-blue-500 text-white rounded-br-none'
110
+ : (darkMode ? 'bg-gray-700' : 'bg-white') + ' rounded-bl-none')
111
+ }
112
+ >
113
+ <p>{message.content}</p>
114
+ <span className={"text-xs mt-1 block " + (message.sender === 'user' ? 'text-blue-100' : 'text-gray-500')}>
115
+ {message.timestamp}
116
+ </span>
117
+ </div>
118
+ </div>
119
+ ))}
120
+
121
+ {isTyping && (
122
+ <div className="flex justify-start">
123
+ <div className={"px-4 py-2 rounded-lg " + (darkMode ? 'bg-gray-700' : 'bg-white') + ' rounded-bl-none'}>
124
+ <div className="flex space-x-1">
125
+ <span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0ms' }}></span>
126
+ <span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '150ms' }}></span>
127
+ <span className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '300ms' }}></span>
128
+ </div>
129
+ </div>
130
+ </div>
131
+ )}
132
+ </div>
133
+
134
+ {/* Input Area */}
135
+ <div className={"p-4 border-t " + (darkMode ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200')}>
136
+ <div className="flex space-x-2">
137
+ <input
138
+ type="text"
139
+ value={inputValue}
140
+ onChange={(e) => setInputValue(e.target.value)}
141
+ onKeyPress={handleKeyPress}
142
+ placeholder="Type a message..."
143
+ className={"flex-1 px-4 py-2 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 " +
144
+ (darkMode ? 'bg-gray-700 text-white placeholder-gray-400' : 'bg-gray-100 text-gray-900 placeholder-gray-500')
145
+ }
146
+ />
147
+ <button
148
+ onClick={handleSendMessage}
149
+ disabled={inputValue.trim() === ''}
150
+ className={"px-4 py-2 rounded-lg font-medium text-white bg-blue-500 hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors " +
151
+ (inputValue.trim() === '' ? 'opacity-50 cursor-not-allowed' : '')
152
+ }
153
+ >
154
+ Send
155
+ </button>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ );
160
+ }"""
161
+ },
162
+ height=600,
163
+ template="react",
164
+ imports={
165
+ "@tailwindcss/browser":
166
+ "https://esm.sh/@tailwindcss/browser",
167
+ })
168
+
169
+ if __name__ == "__main__":
170
+ demo.queue().launch()
layout_templates/chatbot/demos/basic.py CHANGED
@@ -431,6 +431,9 @@ css = """
431
  #chatbot .chatbot-conversations .chatbot-conversations-list {
432
  padding-left: 0;
433
  padding-right: 0;
 
 
 
434
  }
435
 
436
  #chatbot .chatbot-chat {
@@ -479,6 +482,7 @@ with gr.Blocks(css=css, fill_width=True) as demo:
479
  with antd.Col(md=dict(flex="0 0 260px", span=24, order=0),
480
  span=0,
481
  order=1,
 
482
  elem_classes="chatbot-conversations"):
483
  with antd.Flex(vertical=True,
484
  gap="small",
 
431
  #chatbot .chatbot-conversations .chatbot-conversations-list {
432
  padding-left: 0;
433
  padding-right: 0;
434
+ flex: 1;
435
+ height: 0;
436
+ overflow: auto;
437
  }
438
 
439
  #chatbot .chatbot-chat {
 
482
  with antd.Col(md=dict(flex="0 0 260px", span=24, order=0),
483
  span=0,
484
  order=1,
485
+ elem_style=dict(width=0),
486
  elem_classes="chatbot-conversations"):
487
  with antd.Flex(vertical=True,
488
  gap="small",
layout_templates/chatbot/demos/fine_grained_control.py CHANGED
@@ -541,6 +541,7 @@ with gr.Blocks(css=css, fill_width=True) as demo:
541
  with antd.Col(md=dict(flex="0 0 260px", span=24, order=0),
542
  span=0,
543
  order=1,
 
544
  elem_classes="chatbot-conversations"):
545
  with antd.Flex(vertical=True,
546
  gap="small",
 
541
  with antd.Col(md=dict(flex="0 0 260px", span=24, order=0),
542
  span=0,
543
  order=1,
544
+ elem_style=dict(width=0),
545
  elem_classes="chatbot-conversations"):
546
  with antd.Flex(vertical=True,
547
  gap="small",
requirements.txt CHANGED
@@ -1,2 +1,2 @@
1
- modelscope_studio==1.2.3
2
  openai
 
1
+ modelscope_studio==1.3.0
2
  openai
src/pyproject.toml CHANGED
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
8
 
9
  [project]
10
  name = "modelscope_studio"
11
- version = "1.2.3"
12
  description = "A third-party component library based on Gradio."
13
  readme = "README.md"
14
  license = "Apache-2.0"
 
8
 
9
  [project]
10
  name = "modelscope_studio"
11
+ version = "1.3.0"
12
  description = "A third-party component library based on Gradio."
13
  readme = "README.md"
14
  license = "Apache-2.0"