From d9e4d6d13089f84a72db10c36d85029f62f0bfef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Brand=C3=A9ho?= Date: Fri, 23 Jun 2023 22:01:57 +0200 Subject: [PATCH] add set_clipboard method (#1230) --- pynecone/.templates/web/utils/state.js | 6 +++++ pynecone/__init__.py | 1 + pynecone/components/datadisplay/code.py | 30 +++++++++++++++++++++++-- pynecone/event.py | 16 +++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/pynecone/.templates/web/utils/state.js b/pynecone/.templates/web/utils/state.js index 7657ef305..f53997357 100644 --- a/pynecone/.templates/web/utils/state.js +++ b/pynecone/.templates/web/utils/state.js @@ -125,6 +125,12 @@ export const applyEvent = async (event, router, socket) => { return false; } + if (event.name == "_set_clipboard") { + const content = event.payload.content; + navigator.clipboard.writeText(content); + return false; + } + if (event.name == "_alert") { alert(event.payload.message); return false; diff --git a/pynecone/__init__.py b/pynecone/__init__.py index d2d920807..12939a847 100644 --- a/pynecone/__init__.py +++ b/pynecone/__init__.py @@ -23,6 +23,7 @@ from .event import EventChain as EventChain from .event import FileUpload as upload_files from .event import console_log as console_log from .event import redirect as redirect +from .event import set_clipboard as set_clipboard from .event import set_cookie as set_cookie from .event import set_focus as set_focus from .event import set_local_storage as set_local_storage diff --git a/pynecone/components/datadisplay/code.py b/pynecone/components/datadisplay/code.py index 6a1c11d24..ce157f170 100644 --- a/pynecone/components/datadisplay/code.py +++ b/pynecone/components/datadisplay/code.py @@ -3,7 +3,11 @@ from typing import Dict from pynecone.components.component import Component +from pynecone.components.forms import Button +from pynecone.components.layout import Box from pynecone.components.libs.chakra import ChakraComponent +from pynecone.components.media import Icon +from pynecone.event import set_clipboard from pynecone.style import Style from pynecone.utils import imports from pynecone.vars import ImportVar, Var @@ -49,11 +53,13 @@ class CodeBlock(Component): return merged_imports @classmethod - def create(cls, *children, **props): + def create(cls, *children, can_copy=False, copy_button=None, **props): """Create a text component. Args: *children: The children of the component. + can_copy: Whether a copy button should appears. + copy_button: A custom copy button to override the default one. **props: The props to pass to the component. Returns: @@ -62,18 +68,38 @@ class CodeBlock(Component): # This component handles style in a special prop. custom_style = props.pop("custom_style", {}) + if can_copy: + code = children[0] + copy_button = ( + copy_button + if copy_button is not None + else Button.create( + Icon.create(tag="copy"), + on_click=set_clipboard(code), + style={"position": "absolute", "top": "0.5em", "right": "0"}, + ) + ) + custom_style.update({"padding": "1em 3.2em 1em 1em"}) + else: + copy_button = None + # Transfer style props to the custom style prop. for key, value in props.items(): if key not in cls.get_fields(): custom_style[key] = value # Create the component. - return super().create( + code_block = super().create( *children, **props, custom_style=Style(custom_style), ) + if copy_button: + return Box.create(code_block, copy_button, position="relative") + else: + return code_block + def _add_style(self, style): self.custom_style = self.custom_style or {} self.custom_style.update(style) # type: ignore diff --git a/pynecone/event.py b/pynecone/event.py index 86400ddec..0dd853d6f 100644 --- a/pynecone/event.py +++ b/pynecone/event.py @@ -272,6 +272,22 @@ def set_local_storage(key: str, value: str) -> EventSpec: ) +def set_clipboard(content: str) -> EventSpec: + """Set the text in content in the clipboard. + + Args: + content: The text to add to clipboard. + + Returns: + EventSpec: An event to set some content in the clipboard. + """ + return server_side( + "_set_clipboard", + get_fn_signature(set_clipboard), + content=content, + ) + + def get_event(state, event): """Get the event from the given state.