diff --git a/backend/modelscope_studio/components/antd/__init__.py b/backend/modelscope_studio/components/antd/__init__.py index 54762a00..79cb6428 100644 --- a/backend/modelscope_studio/components/antd/__init__.py +++ b/backend/modelscope_studio/components/antd/__init__.py @@ -76,6 +76,7 @@ from .menu.item import AntdMenuItem as MenuItem from .message import AntdMessage as Message from .modal import AntdModal as Modal +from .modal.static import AntdModalStatic as ModalStatic from .notification import AntdNotification as Notification from .pagination import AntdPagination as Pagination from .popconfirm import AntdPopconfirm as Popconfirm diff --git a/backend/modelscope_studio/components/antd/components.py b/backend/modelscope_studio/components/antd/components.py index 921a0855..c46db396 100644 --- a/backend/modelscope_studio/components/antd/components.py +++ b/backend/modelscope_studio/components/antd/components.py @@ -73,6 +73,7 @@ from .menu.item import AntdMenuItem from .message import AntdMessage from .modal import AntdModal +from .modal.static import AntdModalStatic from .notification import AntdNotification from .pagination import AntdPagination from .popconfirm import AntdPopconfirm diff --git a/backend/modelscope_studio/components/antd/message/__init__.py b/backend/modelscope_studio/components/antd/message/__init__.py index e80b16e1..155cb8e0 100644 --- a/backend/modelscope_studio/components/antd/message/__init__.py +++ b/backend/modelscope_studio/components/antd/message/__init__.py @@ -1,5 +1,7 @@ from __future__ import annotations +from typing import Literal + from gradio.events import EventListener from ....utils.dev import ModelScopeLayoutComponent, resolve_frontend_dir @@ -23,15 +25,17 @@ class AntdMessage(ModelScopeLayoutComponent): def __init__( self, - content: str | None = "", + content: str | None = None, props: dict | None = None, *, - duration: float | int | None = 3, + type: Literal['success', 'info', 'warning', 'error', 'loading'] + | None = None, + duration: float | int | None = None, icon: str | None = None, key: str | int | float | None = None, get_container: str | None = None, rtl: bool | None = None, - top: int | float | None = 8, + top: int | float | None = None, root_class_name: str | None = None, as_item: str | None = None, _internal: None = None, @@ -52,6 +56,7 @@ def __init__( self.content = content self.duration = duration self.icon = icon + self.type = type self.key = key self.get_container = get_container self.rtl = rtl diff --git a/backend/modelscope_studio/components/antd/modal/__init__.py b/backend/modelscope_studio/components/antd/modal/__init__.py index b223bb41..05c4e2ef 100644 --- a/backend/modelscope_studio/components/antd/modal/__init__.py +++ b/backend/modelscope_studio/components/antd/modal/__init__.py @@ -5,12 +5,16 @@ from gradio.events import EventListener from ....utils.dev import ModelScopeLayoutComponent, resolve_frontend_dir +from .static import AntdModalStatic class AntdModal(ModelScopeLayoutComponent): """ Ant Design: https://ant.design/components/modal """ + + Static = AntdModalStatic + EVENTS = [ EventListener( "ok", diff --git a/backend/modelscope_studio/components/antd/modal/static/__init__.py b/backend/modelscope_studio/components/antd/modal/static/__init__.py new file mode 100644 index 00000000..9d9d37e1 --- /dev/null +++ b/backend/modelscope_studio/components/antd/modal/static/__init__.py @@ -0,0 +1,132 @@ +from __future__ import annotations + +from typing import Any, Literal + +from gradio.events import EventListener + +from .....utils.dev import ModelScopeLayoutComponent, resolve_frontend_dir + + +class AntdModalStatic(ModelScopeLayoutComponent): + """ + Ant Design: https://ant.design/components/modal + """ + EVENTS = [ + EventListener( + "ok", + callback=lambda block: block._internal.update(bind_ok_event=True)), + EventListener("cancel", + callback=lambda block: block._internal.update( + bind_cancel_event=True)) + ] + + # supported slots + SLOTS = [ + 'closeIcon', 'cancelButtonProps.icon', 'cancelText', + 'closable.closeIcon', 'closeIcon', 'footer', 'title', 'content', + 'okButtonProps.icon', 'okText', 'modalRender' + ] + + def __init__( + self, + props: dict | None = None, + *, + after_close: str | None = None, + auto_focus_button: Literal['ok', 'cancel'] | None = 'ok', + type: Literal['info', 'success', 'error', 'warning', 'confirm'] + | None = None, + class_names: dict | None = None, + styles: dict | None = None, + cancel_button_props: dict | None = None, + cancel_text: str | None = None, + centered: bool | None = None, + closable: bool | dict | None = None, + close_icon: str | None = None, + confirm_loading: bool | None = None, + destroy_on_close: bool | None = None, + focus_trigger_after_close: bool | None = None, + content: str | None = None, + footer: str | None = None, + force_render: bool | None = None, + get_container: str | None = None, + keyboard: bool | None = None, + mask: bool | None = None, + mask_closable: bool | None = None, + modal_render: str | None = None, + ok_text: str | None = None, + ok_type: str | None = None, + ok_button_props: dict | None = None, + loading: bool | None = None, + title: str | None = None, + width: int | float | str | None = None, + wrap_class_name: str | None = None, + z_index: int | None = None, + after_open_change: str | None = None, + root_class_name: str | None = None, + as_item: str | None = None, + _internal: None = None, + # gradio properties + visible: bool = True, + elem_id: str | None = None, + elem_classes: list[str] | str | None = None, + elem_style: dict | None = None, + render: bool = True, + **kwargs): + super().__init__(visible=visible, + elem_id=elem_id, + elem_classes=elem_classes, + render=render, + as_item=as_item, + elem_style=elem_style, + **kwargs) + self.props = props + self.after_close = after_close + self.auto_focus_button = auto_focus_button + self.class_names = class_names + self.styles = styles + self.type = type + self.cancel_button_props = cancel_button_props + self.cancel_text = cancel_text + self.centered = centered + self.closable = closable + self.close_icon = close_icon + self.confirm_loading = confirm_loading + self.destroy_on_close = destroy_on_close + self.focus_trigger_after_close = focus_trigger_after_close + self.content = content + self.footer = footer + self.force_render = force_render + self.get_container = get_container + self.keyboard = keyboard + self.mask = mask + self.mask_closable = mask_closable + self.modal_render = modal_render + self.ok_text = ok_text + self.ok_type = ok_type + self.ok_button_props = ok_button_props + self.loading = loading + self.title = title + self.width = width + self.wrap_class_name = wrap_class_name + self.z_index = z_index + self.after_open_change = after_open_change + self.root_class_name = root_class_name + + FRONTEND_DIR = resolve_frontend_dir("modal", "static") + + @property + def skip_api(self): + return True + + def preprocess(self, payload: None) -> None: + return payload + + def postprocess(self, value: None) -> None: + + return value + + def example_payload(self) -> Any: + return None + + def example_value(self) -> Any: + return None diff --git a/backend/modelscope_studio/components/antd/notification/__init__.py b/backend/modelscope_studio/components/antd/notification/__init__.py index 61e0cbfc..adfeeebb 100644 --- a/backend/modelscope_studio/components/antd/notification/__init__.py +++ b/backend/modelscope_studio/components/antd/notification/__init__.py @@ -29,6 +29,7 @@ def __init__( description: str | None = "", props: dict | None = None, *, + type: Literal['success', 'info', 'warning', 'error'] | None = None, btn: str | None = None, close_icon: str | bool | None = None, duration: int | float | None = 4.5, @@ -63,6 +64,7 @@ def __init__( **kwargs) self.props = props self.message = message + self.type = type self.description = description self.btn = btn self.close_icon = close_icon diff --git a/docs/app.py b/docs/app.py index 323053df..a209b617 100644 --- a/docs/app.py +++ b/docs/app.py @@ -303,6 +303,36 @@ def get_docs(file_path: str, type: Literal["antd", "base"]): "children": [{ "label": get_text("Alert", "Alert 警告提示"), "key": "alert" + }, { + "label": get_text("Drawer", "Drawer 抽屉"), + "key": "drawer" + }, { + "label": get_text("Message", "Message 全局提示"), + "key": "message" + }, { + "label": get_text("Modal", "Modal 对话框"), + "key": "modal" + }, { + "label": get_text("Notification", "Notification 通知提醒框"), + "key": "notification" + }, { + "label": get_text("Popconfirm", "Popconfirm 气泡确认框"), + "key": "popconfirm" + }, { + "label": get_text("Progress", "Progress 进度条"), + "key": "progress" + }, { + "label": get_text("Result", "Result 结果"), + "key": "result" + }, { + "label": get_text("Skeleton", "Skeleton 骨架屏"), + "key": "skeleton" + }, { + "label": get_text("Spin", "Spin 加载中"), + "key": "spin" + }, { + "label": get_text("Watermark", "Watermark 水印"), + "key": "watermark" }] }, { "label": diff --git a/docs/components/antd/drawer/README-zh_CN.md b/docs/components/antd/drawer/README-zh_CN.md new file mode 100644 index 00000000..9db674ce --- /dev/null +++ b/docs/components/antd/drawer/README-zh_CN.md @@ -0,0 +1,8 @@ +# Drawer + +A panel that slides out from the edge of the screen. See [Ant Design](https://ant.design/components/drawer/) for more information. + +## Examples + + + diff --git a/docs/components/antd/drawer/README.md b/docs/components/antd/drawer/README.md new file mode 100644 index 00000000..9db674ce --- /dev/null +++ b/docs/components/antd/drawer/README.md @@ -0,0 +1,8 @@ +# Drawer + +A panel that slides out from the edge of the screen. See [Ant Design](https://ant.design/components/drawer/) for more information. + +## Examples + + + diff --git a/docs/components/antd/drawer/app.py b/docs/components/antd/drawer/app.py new file mode 100644 index 00000000..0018b7c1 --- /dev/null +++ b/docs/components/antd/drawer/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/docs/components/antd/drawer/demos/basic.py b/docs/components/antd/drawer/demos/basic.py new file mode 100644 index 00000000..e75ed307 --- /dev/null +++ b/docs/components/antd/drawer/demos/basic.py @@ -0,0 +1,19 @@ +import gradio as gr + +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + btn = antd.Button("Open Drawer", type="primary") + with antd.Drawer(open=False, title="Basic Drawer") as drawer: + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + btn.click(fn=lambda: gr.update(open=True), outputs=[drawer]) + + drawer.close(fn=lambda: gr.update(open=False), outputs=[drawer]) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/docs/components/antd/drawer/demos/extra_actions.py b/docs/components/antd/drawer/demos/extra_actions.py new file mode 100644 index 00000000..21661caf --- /dev/null +++ b/docs/components/antd/drawer/demos/extra_actions.py @@ -0,0 +1,36 @@ +import gradio as gr + +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + +default_placement = 'right' + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + with antd.Space(): + placement = antd.RadioGroup( + options=["top", "bottom", "left", "right"], + value=default_placement) + btn = antd.Button("Open Drawer", type="primary") + with antd.Drawer(open=False, + title="Drawer with extra actions", + width=500) as drawer: + with ms.Slot("extra"): + with antd.Space(): + cancel_btn = antd.Button("Cancel") + ok_btn = antd.Button("OK", type="primary") + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + placement.change(fn=lambda p: gr.update(placement=p), + inputs=[placement], + outputs=[drawer]) + btn.click(fn=lambda: gr.update(open=True), outputs=[drawer]) + + gr.on([drawer.close, ok_btn.click, cancel_btn.click], + fn=lambda: gr.update(open=False), + outputs=[drawer]) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/docs/components/antd/message/README-zh_CN.md b/docs/components/antd/message/README-zh_CN.md new file mode 100644 index 00000000..6a29b623 --- /dev/null +++ b/docs/components/antd/message/README-zh_CN.md @@ -0,0 +1,7 @@ +# Message + +Display global messages as feedback in response to user operations. See [Ant Design](https://ant.design/components/message/) for more information. + +## Examples + + diff --git a/docs/components/antd/message/README.md b/docs/components/antd/message/README.md new file mode 100644 index 00000000..6a29b623 --- /dev/null +++ b/docs/components/antd/message/README.md @@ -0,0 +1,7 @@ +# Message + +Display global messages as feedback in response to user operations. See [Ant Design](https://ant.design/components/message/) for more information. + +## Examples + + diff --git a/docs/components/antd/message/app.py b/docs/components/antd/message/app.py new file mode 100644 index 00000000..0018b7c1 --- /dev/null +++ b/docs/components/antd/message/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/docs/components/antd/message/demos/basic.py b/docs/components/antd/message/demos/basic.py new file mode 100644 index 00000000..36d34b55 --- /dev/null +++ b/docs/components/antd/message/demos/basic.py @@ -0,0 +1,51 @@ +import gradio as gr + +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + + +def info(): + return gr.update(visible=True, + type="info", + content="This is a info message.", + key="info") + + +def success(): + return gr.update(visible=True, + type="success", + content="This is a success message.", + key="success") + + +def error(): + return gr.update(visible=True, + type="error", + content="This is an error message.", + key="error") + + +def warning(): + return gr.update(visible=True, + type="warning", + content="This is a warning message.", + key="warning") + + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + with antd.Space(): + info_btn = antd.Button("Info") + success_btn = antd.Button("Success") + error_btn = antd.Button("Error") + warning_btn = antd.Button("Warning") + + message = antd.Message(visible=False) + info_btn.click(info, outputs=[message]) + success_btn.click(success, outputs=[message]) + error_btn.click(error, outputs=[message]) + warning_btn.click(warning, outputs=[message]) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/docs/components/antd/modal/README-zh_CN.md b/docs/components/antd/modal/README-zh_CN.md new file mode 100644 index 00000000..3e0f5e09 --- /dev/null +++ b/docs/components/antd/modal/README-zh_CN.md @@ -0,0 +1,12 @@ +# Modal + +Display a modal dialog box, providing a title, content area, and action buttons. See [Ant Design](https://ant.design/components/modal/) for more information. + +## Examples + + + + +Like `Message` and `Notification`, `Modal` can be used as a static method. + + diff --git a/docs/components/antd/modal/README.md b/docs/components/antd/modal/README.md new file mode 100644 index 00000000..3e0f5e09 --- /dev/null +++ b/docs/components/antd/modal/README.md @@ -0,0 +1,12 @@ +# Modal + +Display a modal dialog box, providing a title, content area, and action buttons. See [Ant Design](https://ant.design/components/modal/) for more information. + +## Examples + + + + +Like `Message` and `Notification`, `Modal` can be used as a static method. + + diff --git a/docs/components/antd/modal/app.py b/docs/components/antd/modal/app.py new file mode 100644 index 00000000..0018b7c1 --- /dev/null +++ b/docs/components/antd/modal/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/docs/components/antd/modal/demos/basic.py b/docs/components/antd/modal/demos/basic.py new file mode 100644 index 00000000..b0aa1bfe --- /dev/null +++ b/docs/components/antd/modal/demos/basic.py @@ -0,0 +1,19 @@ +import gradio as gr + +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + btn = antd.Button("Open Modal", type="primary") + with antd.Modal(open=False, title="Basic Modal") as modal: + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + btn.click(lambda: gr.update(open=True), outputs=[modal]) + + modal.ok(lambda: gr.update(open=False), outputs=[modal]) + modal.cancel(lambda: gr.update(open=False), outputs=[modal]) +if __name__ == "__main__": + demo.queue().launch() diff --git a/docs/components/antd/modal/demos/custom_footer.py b/docs/components/antd/modal/demos/custom_footer.py new file mode 100644 index 00000000..c69e9115 --- /dev/null +++ b/docs/components/antd/modal/demos/custom_footer.py @@ -0,0 +1,31 @@ +import gradio as gr + +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + btn = antd.Button("Open Modal", type="primary") + with antd.Modal(open=False, title="Basic Modal") as modal: + with ms.Slot("footer"): + cancel_btn = antd.Button("Return") + submit_btn = antd.Button("Submit", type="primary") + link_btn = antd.Button("Search on Google", + type="primary", + href_target="_blank", + href="https://google.com") + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + antd.Typography.Paragraph("Some contents...") + btn.click(lambda: gr.update(open=True), outputs=[modal]) + + modal.ok(lambda: gr.update(open=False), outputs=[modal]) + + cancel_btn.click(lambda: gr.update(open=False), outputs=[modal]) + modal.cancel(lambda: gr.update(open=False), outputs=[modal]) + gr.on([submit_btn.click, link_btn.click], + fn=lambda: gr.update(open=False), + outputs=[modal]) +if __name__ == "__main__": + demo.queue().launch() diff --git a/docs/components/antd/modal/demos/static.py b/docs/components/antd/modal/demos/static.py new file mode 100644 index 00000000..5b1ad89b --- /dev/null +++ b/docs/components/antd/modal/demos/static.py @@ -0,0 +1,74 @@ +import gradio as gr + +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + + +def info(): + return gr.update( + visible=True, + mask_closable=False, + title="Info", + type="info", + content="This is a info message.", + ) + + +def success(): + return gr.update( + visible=True, + mask_closable=False, + title="Success", + type="success", + content="This is a success message.", + ) + + +def error(): + return gr.update( + visible=True, + mask_closable=False, + title="Error", + type="error", + content="This is an error message.", + ) + + +def warning(): + return gr.update( + visible=True, + mask_closable=False, + title="Warning", + type="warning", + content="This is a warning message.", + ) + + +def confirm(): + return gr.update( + visible=True, + mask_closable=True, + title="Confirm", + type="confirm", + content="This is a confirm message.", + ) + + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + with antd.Space(): + info_btn = antd.Button("Info") + success_btn = antd.Button("Success") + error_btn = antd.Button("Error") + warning_btn = antd.Button("Warning") + confirm_btn = antd.Button("Confirm") + + modal = antd.Modal.Static(visible=False) + info_btn.click(info, outputs=[modal]) + success_btn.click(success, outputs=[modal]) + error_btn.click(error, outputs=[modal]) + warning_btn.click(warning, outputs=[modal]) + confirm_btn.click(confirm, outputs=[modal]) +if __name__ == "__main__": + demo.queue().launch() diff --git a/docs/components/antd/notification/README-zh_CN.md b/docs/components/antd/notification/README-zh_CN.md new file mode 100644 index 00000000..0070d377 --- /dev/null +++ b/docs/components/antd/notification/README-zh_CN.md @@ -0,0 +1,7 @@ +# Notification + +Prompt notification message globally. See [Ant Design](https://ant.design/components/notification/) for more information. + +## Examples + + diff --git a/docs/components/antd/notification/README.md b/docs/components/antd/notification/README.md new file mode 100644 index 00000000..0070d377 --- /dev/null +++ b/docs/components/antd/notification/README.md @@ -0,0 +1,7 @@ +# Notification + +Prompt notification message globally. See [Ant Design](https://ant.design/components/notification/) for more information. + +## Examples + + diff --git a/docs/components/antd/notification/app.py b/docs/components/antd/notification/app.py new file mode 100644 index 00000000..0018b7c1 --- /dev/null +++ b/docs/components/antd/notification/app.py @@ -0,0 +1,6 @@ +from helper.Docs import Docs + +docs = Docs(__file__) + +if __name__ == "__main__": + docs.render().queue().launch() diff --git a/docs/components/antd/notification/demos/basic.py b/docs/components/antd/notification/demos/basic.py new file mode 100644 index 00000000..c3cae097 --- /dev/null +++ b/docs/components/antd/notification/demos/basic.py @@ -0,0 +1,59 @@ +import gradio as gr + +import modelscope_studio.components.antd as antd +import modelscope_studio.components.base as ms + + +def info(): + return gr.update(visible=True, + type="info", + message="Info Notification Message", + description="This is a info description.", + placement="topLeft", + key="info") + + +def success(): + return gr.update(visible=True, + type="success", + message="Success Notification Message", + description="This is a success description.", + placement="topRight", + key="success") + + +def error(): + return gr.update(visible=True, + type="error", + message="Error Notification Message", + description="This is an error description.", + placement="bottomLeft", + key="error") + + +def warning(): + return gr.update(visible=True, + type="warning", + message="Warning Notification Message", + description="This is a warning description.", + placement="bottomRight", + key="warning") + + +with gr.Blocks() as demo: + with ms.Application(): + with antd.ConfigProvider(): + with antd.Space(): + info_btn = antd.Button("Info") + success_btn = antd.Button("Success") + error_btn = antd.Button("Error") + warning_btn = antd.Button("Warning") + + notification = antd.Notification(visible=False) + info_btn.click(info, outputs=[notification]) + success_btn.click(success, outputs=[notification]) + error_btn.click(error, outputs=[notification]) + warning_btn.click(warning, outputs=[notification]) + +if __name__ == "__main__": + demo.queue().launch() diff --git a/frontend/antd/config-provider/config-provider.tsx b/frontend/antd/config-provider/config-provider.tsx index 5f01c7a4..fdcefb06 100644 --- a/frontend/antd/config-provider/config-provider.tsx +++ b/frontend/antd/config-provider/config-provider.tsx @@ -60,7 +60,7 @@ export const ConfigProvider = sveltify< id, className, style, - locale: localeProp, + locale: localeProp = 'en_US', getTargetContainer, getPopupContainer, renderEmpty, diff --git a/frontend/antd/message/Index.svelte b/frontend/antd/message/Index.svelte index 00777e64..ea2c175a 100644 --- a/frontend/antd/message/Index.svelte +++ b/frontend/antd/message/Index.svelte @@ -67,6 +67,7 @@ {...bindEvents($mergedProps)} content={$mergedProps.props.content || $mergedProps.content} slots={$slots} + messageKey={$mergedProps.props.key || $mergedProps.restProps.key} visible={$mergedProps.visible} onVisible={(v) => { visible = v; diff --git a/frontend/antd/message/message.tsx b/frontend/antd/message/message.tsx index 0c2b7ee0..bdd49c83 100644 --- a/frontend/antd/message/message.tsx +++ b/frontend/antd/message/message.tsx @@ -11,6 +11,7 @@ export const Message = sveltify< ConfigOptions & { children?: React.ReactNode; visible?: boolean; + messageKey?: string | number; onVisible?: (visible: boolean) => void; }, ['content', 'icon'] @@ -22,6 +23,7 @@ export const Message = sveltify< onVisible, onClose, getContainer, + messageKey, ...props }) => { const getContainerFunction = useFunction(getContainer); @@ -34,6 +36,7 @@ export const Message = sveltify< if (visible) { messageApi.open({ ...props, + key: messageKey, icon: slots.icon ? : props.icon, content: slots.content ? ( @@ -46,14 +49,23 @@ export const Message = sveltify< }, }); } else { - messageApi.destroy(props.key); + messageApi.destroy(messageKey); } return () => { - messageApi.destroy(props.key); + messageApi.destroy(messageKey); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [visible]); + }, [ + visible, + messageKey, + props.content, + props.className, + props.duration, + props.icon, + props.style, + props.type, + ]); return ( <>
{children}
diff --git a/frontend/antd/modal/modal.tsx b/frontend/antd/modal/modal.tsx index a1c3be45..beb3e1b0 100644 --- a/frontend/antd/modal/modal.tsx +++ b/frontend/antd/modal/modal.tsx @@ -36,6 +36,7 @@ export const Modal = sveltify< const afterCloseFunction = useFunction(afterClose); const getContainerFunction = useFunction(getContainer); const modalRenderFunction = useFunction(modalRender); + return ( + + + +{#await AwaitedModalStatic then ModalStatic} + { + visible = v; + }} + > + + +{/await} + + diff --git a/frontend/antd/modal/static/gradio.config.js b/frontend/antd/modal/static/gradio.config.js new file mode 100644 index 00000000..1992403d --- /dev/null +++ b/frontend/antd/modal/static/gradio.config.js @@ -0,0 +1,3 @@ +import config from '../../../defineConfig.js'; + +export default config(); diff --git a/frontend/antd/modal/static/modal.static.tsx b/frontend/antd/modal/static/modal.static.tsx new file mode 100644 index 00000000..48004912 --- /dev/null +++ b/frontend/antd/modal/static/modal.static.tsx @@ -0,0 +1,134 @@ +import { sveltify } from '@svelte-preprocess-react'; +import { ReactSlot } from '@svelte-preprocess-react/react-slot'; +import type { SetSlotParams } from '@svelte-preprocess-react/slot'; +import React, { useEffect, useRef } from 'react'; +import { useFunction } from '@utils/hooks/useFunction'; +import { renderParamsSlot } from '@utils/renderParamsSlot'; +import { Modal as AModal, type ModalFuncProps } from 'antd'; +import type { ModalFuncWithPromise } from 'antd/es/modal/useModal'; + +export const ModalStatic = sveltify< + ModalFuncProps & { + setSlotParams: SetSlotParams; + visible?: boolean; + type?: 'info' | 'success' | 'error' | 'warning' | 'confirm'; + onVisible?: (visible: boolean) => void; + }, + [ + 'cancelButtonProps.icon', + 'cancelText', + 'closable.closeIcon', + 'closeIcon', + 'footer', + 'content', + 'title', + 'okButtonProps.icon', + 'okText', + 'modalRender', + ] +>( + ({ + slots, + afterClose, + afterOpenChange, + getContainer, + children, + modalRender, + setSlotParams, + onVisible, + onCancel, + onOk, + visible, + type, + ...props + }) => { + const afterOpenChangeFunction = useFunction(afterOpenChange); + const afterCloseFunction = useFunction(afterClose); + const getContainerFunction = useFunction(getContainer); + const modalRenderFunction = useFunction(modalRender); + const [modalApi, contextHolder] = AModal.useModal(); + const currentModalRef = useRef | null>( + null + ); + + useEffect(() => { + if (visible) { + currentModalRef.current = modalApi[type || 'info']({ + ...props, + autoFocusButton: + props.autoFocusButton === undefined ? null : props.autoFocusButton, + afterOpenChange: afterOpenChangeFunction, + afterClose: afterCloseFunction, + getContainer: + typeof getContainer === 'string' + ? getContainerFunction + : getContainer, + okText: slots.okText ? ( + + ) : ( + props.okText + ), + okButtonProps: { + ...(props.okButtonProps || {}), + icon: slots['okButtonProps.icon'] ? ( + + ) : ( + props.okButtonProps?.icon + ), + }, + cancelText: slots.cancelText ? ( + + ) : ( + props.cancelText + ), + cancelButtonProps: { + ...(props.cancelButtonProps || {}), + icon: slots['cancelButtonProps.icon'] ? ( + + ) : ( + props.cancelButtonProps?.icon + ), + }, + closable: slots['closable.closeIcon'] + ? { + ...(typeof props.closable === 'object' ? props.closable : {}), + closeIcon: , + } + : props.closable, + closeIcon: slots.closeIcon ? ( + + ) : ( + props.closeIcon + ), + footer: slots.footer + ? renderParamsSlot({ slots, setSlotParams, key: 'footer' }) + : props.footer, + title: slots.title ? : props.title, + modalRender: slots.modalRender + ? renderParamsSlot({ slots, setSlotParams, key: 'modalRender' }) + : modalRenderFunction, + onCancel(...args) { + onCancel?.(...args); + onVisible?.(false); + }, + onOk(...args) { + onOk?.(...args); + onVisible?.(false); + }, + }); + } else { + currentModalRef.current?.destroy(); + currentModalRef.current = null; + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [visible]); + return ( + <> +
{children}
+ {contextHolder} + + ); + } +); + +export default ModalStatic; diff --git a/frontend/antd/modal/static/package.json b/frontend/antd/modal/static/package.json new file mode 100644 index 00000000..80b28455 --- /dev/null +++ b/frontend/antd/modal/static/package.json @@ -0,0 +1,14 @@ +{ + "name": "@modelscope-studio/antd-modal.static", + "type": "module", + "exports": { + ".": { + "default": "./Index.svelte", + "gradio": "./Index.svelte" + }, + "./package.json": { + "default": "./package.json", + "gradio": "./package.json" + } + } +} diff --git a/frontend/antd/notification/Index.svelte b/frontend/antd/notification/Index.svelte index c453d175..b2fb750f 100644 --- a/frontend/antd/notification/Index.svelte +++ b/frontend/antd/notification/Index.svelte @@ -66,6 +66,7 @@ {...$mergedProps.props} {...bindEvents($mergedProps)} message={$mergedProps.props.message || $mergedProps.message} + notificationKey={$mergedProps.props.key || $mergedProps.restProps.key} slots={$slots} visible={$mergedProps.visible} onVisible={(v) => { diff --git a/frontend/antd/notification/notification.tsx b/frontend/antd/notification/notification.tsx index ff06262a..5910b9f5 100644 --- a/frontend/antd/notification/notification.tsx +++ b/frontend/antd/notification/notification.tsx @@ -9,6 +9,7 @@ export const Notification = sveltify< ArgsProps & NotificationConfig & { children?: React.ReactNode; + notificationKey?: string | number; visible?: boolean; onVisible?: (visible: boolean) => void; }, @@ -22,6 +23,7 @@ export const Notification = sveltify< top, children, visible, + notificationKey, onClose, onVisible, ...props @@ -37,6 +39,7 @@ export const Notification = sveltify< if (visible) { notificationApi.open({ ...props, + key: notificationKey, btn: slots.btn ? : props.btn, closeIcon: slots['closeIcon'] ? ( @@ -60,14 +63,30 @@ export const Notification = sveltify< }, }); } else { - notificationApi.destroy(props.key); + notificationApi.destroy(notificationKey); } return () => { - notificationApi.destroy(props.key); + notificationApi.destroy(notificationKey); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [visible]); + }, [ + visible, + notificationKey, + props.btn, + props.closeIcon, + props.className, + props.description, + props.duration, + props.showProgress, + props.pauseOnHover, + props.icon, + props.message, + props.placement, + props.style, + props.role, + props.props, + ]); return ( <> {children}