Bläddra i källkod

Fix event default call (#1031)

Nikhil Rao 2 år sedan
förälder
incheckning
98f1b30735

+ 11 - 6
pynecone/.templates/jinja/web/pages/index.js.jinja2

@@ -19,10 +19,15 @@ export default function Component() {
   const { isReady } = {{const.router}}
   const { isReady } = {{const.router}}
   const { {{const.color_mode}}, {{const.toggle_color_mode}} } = {{const.use_color_mode}}()
   const { {{const.color_mode}}, {{const.toggle_color_mode}} } = {{const.use_color_mode}}()
 
 
-  const Event = events => {{state_name|react_setter}}({
-    ...{{state_name}},
-    events: [...{{state_name}}.events, ...events],
-  })
+  const Event = (events, _e) => {
+      if (_e) {
+        _e.preventDefault();
+      }
+      {{state_name|react_setter}}({
+        ...{{state_name}},
+        events: [...{{state_name}}.events, ...events],
+      })
+  }
 
 
   const File = files => {{state_name|react_setter}}({
   const File = files => {{state_name|react_setter}}({
     ...{{state_name}},
     ...{{state_name}},
@@ -51,8 +56,8 @@ export default function Component() {
       }
       }
 
 
       await updateState({{state_name}}, {{state_name|react_setter}}, {{const.result}}, {{const.result|react_setter}}, {{const.router}}, {{const.socket}}.current)
       await updateState({{state_name}}, {{state_name|react_setter}}, {{const.result}}, {{const.result|react_setter}}, {{const.router}}, {{const.socket}}.current)
-      }
-      update()
+    }
+    update()
   })
   })
   useEffect(() => {
   useEffect(() => {
     const change_complete = () => Event([E('{{state_name}}.{{const.hydrate}}', {})])
     const change_complete = () => Event([E('{{state_name}}.{{const.hydrate}}', {})])

+ 5 - 2
pynecone/.templates/web/utils/state.js

@@ -11,6 +11,9 @@ let token;
 // Key for the token in the session storage.
 // Key for the token in the session storage.
 const TOKEN_KEY = "token";
 const TOKEN_KEY = "token";
 
 
+// Dictionary holding component references.
+export const refs = {};
+
 /**
 /**
  * Generate a UUID (Used for session tokens).
  * Generate a UUID (Used for session tokens).
  * Taken from: https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid
  * Taken from: https://stackoverflow.com/questions/105034/how-do-i-create-a-guid-uuid
@@ -93,8 +96,8 @@ export const applyEvent = async (event, router, socket) => {
   }
   }
 
 
   if (event.name == "_set_value") {
   if (event.name == "_set_value") {
-    event.payload.ref.current.blur();
-    event.payload.ref.current.value = event.payload.value;
+    const ref = event.payload.ref in refs ? refs[event.payload.ref] : event.payload.ref;
+    ref.current.value = event.payload.value;
     return false;
     return false;
   }
   }
 
 

+ 1 - 0
pynecone/compiler/compiler.py

@@ -26,6 +26,7 @@ DEFAULT_IMPORTS: imports.ImportDict = {
         ImportVar(tag="uploadFiles"),
         ImportVar(tag="uploadFiles"),
         ImportVar(tag="E"),
         ImportVar(tag="E"),
         ImportVar(tag="isTrue"),
         ImportVar(tag="isTrue"),
+        ImportVar(tag="refs"),
     },
     },
     "": {ImportVar(tag="focus-visible/dist/focus-visible")},
     "": {ImportVar(tag="focus-visible/dist/focus-visible")},
     "@chakra-ui/react": {ImportVar(tag=constants.USE_COLOR_MODE)},
     "@chakra-ui/react": {ImportVar(tag=constants.USE_COLOR_MODE)},

+ 1 - 1
pynecone/components/component.py

@@ -469,7 +469,7 @@ class Component(Base, ABC):
         """
         """
         ref = self.get_ref()
         ref = self.get_ref()
         if ref is not None:
         if ref is not None:
-            return f"const {ref} = useRef(null);"
+            return f"const {ref} = useRef(null); refs['{ref}'] = {ref};"
         return None
         return None
 
 
     def get_hooks(self) -> Set[str]:
     def get_hooks(self) -> Set[str]:

+ 11 - 3
pynecone/components/tags/tag.py

@@ -64,6 +64,9 @@ class Tag(Base):
 
 
         Returns:
         Returns:
             The formatted prop to display within a tag.
             The formatted prop to display within a tag.
+
+        Raises:
+            TypeError: If the prop is not a valid type.
         """
         """
         # Handle var props.
         # Handle var props.
         if isinstance(prop, Var):
         if isinstance(prop, Var):
@@ -81,8 +84,8 @@ class Tag(Base):
             else:
             else:
                 # All other events.
                 # All other events.
                 chain = ",".join([format.format_event(event) for event in prop.events])
                 chain = ",".join([format.format_event(event) for event in prop.events])
-                event = f"{{{EVENT_ARG}.preventDefault(); Event([{chain}])}}"
-            prop = f"({EVENT_ARG}) => {event}"
+                event = f"Event([{chain}], {EVENT_ARG})"
+            prop = f"{EVENT_ARG} => {event}"
 
 
         # Handle other types.
         # Handle other types.
         elif isinstance(prop, str):
         elif isinstance(prop, str):
@@ -103,7 +106,12 @@ class Tag(Base):
                 }
                 }
 
 
             # Dump the prop as JSON.
             # Dump the prop as JSON.
-            prop = format.json_dumps(prop)
+            try:
+                prop = format.json_dumps(prop)
+            except TypeError as e:
+                raise TypeError(
+                    f"Could not format prop: {prop} of type {type(prop)}"
+                ) from e
 
 
             # This substitution is necessary to unwrap var values.
             # This substitution is necessary to unwrap var values.
             prop = re.sub('"{', "", prop)
             prop = re.sub('"{', "", prop)

+ 2 - 5
pynecone/constants.py

@@ -8,19 +8,16 @@ from types import SimpleNamespace
 import pkg_resources
 import pkg_resources
 
 
 # App names and versions.
 # App names and versions.
-# The name of the Pynecone module.
+# The name of the Pynecone package.
 MODULE_NAME = "pynecone"
 MODULE_NAME = "pynecone"
-# The name of the pip install package.
-PACKAGE_NAME = "pynecone"
 # The current version of Pynecone.
 # The current version of Pynecone.
-VERSION = pkg_resources.get_distribution(PACKAGE_NAME).version
+VERSION = pkg_resources.get_distribution(MODULE_NAME).version
 # Minimum version of Node.js required to run Pynecone.
 # Minimum version of Node.js required to run Pynecone.
 MIN_NODE_VERSION = "16.6.0"
 MIN_NODE_VERSION = "16.6.0"
 
 
 # Valid bun versions.
 # Valid bun versions.
 MIN_BUN_VERSION = "0.5.9"
 MIN_BUN_VERSION = "0.5.9"
 MAX_BUN_VERSION = "0.5.9"
 MAX_BUN_VERSION = "0.5.9"
-INVALID_BUN_VERSIONS = ["0.5.5", "0.5.6", "0.5.7"]
 
 
 # Files and directories used to init a new project.
 # Files and directories used to init a new project.
 # The root directory of the pynecone library.
 # The root directory of the pynecone library.

+ 0 - 1
pynecone/utils/prerequisites.py

@@ -230,7 +230,6 @@ def validate_and_install_bun(initialize=True):
     if bun_version is not None and (
     if bun_version is not None and (
         bun_version < version.parse(constants.MIN_BUN_VERSION)
         bun_version < version.parse(constants.MIN_BUN_VERSION)
         or bun_version > version.parse(constants.MAX_BUN_VERSION)
         or bun_version > version.parse(constants.MAX_BUN_VERSION)
-        or str(bun_version) in constants.INVALID_BUN_VERSIONS
     ):
     ):
         console.print(
         console.print(
             f"""[red]Bun version {bun_version} is not supported by Pynecone. Please change your to bun version to be between {constants.MIN_BUN_VERSION} and {constants.MAX_BUN_VERSION}."""
             f"""[red]Bun version {bun_version} is not supported by Pynecone. Please change your to bun version to be between {constants.MIN_BUN_VERSION} and {constants.MAX_BUN_VERSION}."""

+ 2 - 2
tests/components/test_tag.py

@@ -25,7 +25,7 @@ def mock_event(arg):
         ({"a": 1, "b": 2, "c": 3}, '{{"a": 1, "b": 2, "c": 3}}'),
         ({"a": 1, "b": 2, "c": 3}, '{{"a": 1, "b": 2, "c": 3}}'),
         (
         (
             EventChain(events=[EventSpec(handler=EventHandler(fn=mock_event))]),
             EventChain(events=[EventSpec(handler=EventHandler(fn=mock_event))]),
-            '{(_e) => {_e.preventDefault(); Event([E("mock_event")])}}',
+            '{_e => Event([E("mock_event")], _e)}',
         ),
         ),
         (
         (
             EventChain(
             EventChain(
@@ -36,7 +36,7 @@ def mock_event(arg):
                     )
                     )
                 ]
                 ]
             ),
             ),
-            '{(_e) => {_e.preventDefault(); Event([E("mock_event", {arg:_e.target.value})])}}',
+            '{_e => Event([E("mock_event", {arg:_e.target.value})], _e)}',
         ),
         ),
         ({"a": "red", "b": "blue"}, '{{"a": "red", "b": "blue"}}'),
         ({"a": "red", "b": "blue"}, '{{"a": "red", "b": "blue"}}'),
         (BaseVar(name="var", type_="int"), "{var}"),
         (BaseVar(name="var", type_="int"), "{var}"),