From 96c82c1dcc98650e0668f72105f08c09310aa710 Mon Sep 17 00:00:00 2001 From: Dev Aggarwal Date: Tue, 17 Dec 2024 14:46:51 +0530 Subject: [PATCH] load inline js event handlers for inputs --- app/components/CodeEditor.tsx | 14 ++++---------- app/components/GooeySelect.tsx | 1 + app/gooeyInput.tsx | 23 +++++++++++++++++++++++ app/jsonFormInput.tsx | 5 +++++ app/renderer.tsx | 1 + 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/app/components/CodeEditor.tsx b/app/components/CodeEditor.tsx index 22c282a..417a64b 100644 --- a/app/components/CodeEditor.tsx +++ b/app/components/CodeEditor.tsx @@ -41,19 +41,13 @@ export default function CodeEditor({ onChange: OnChange; state: Record; }) { - const { - name, - defaultValue, - height, - label, - help, - tooltipPlacement, - ...restProps - } = props; + const { name, defaultValue, height, label, help, tooltipPlacement, ...args } = + props; const [inputRef, value, setValue] = useGooeyStringInput({ state, name, defaultValue, + args, }); const handleChange = (val: string) => { setValue(val); @@ -98,7 +92,7 @@ export default function CodeEditor({ value={value} onChange={handleChange} extensions={[javascript(), lintGutter(), jsLinter(lintOptions)]} - {...restProps} + {...args} /> ); diff --git a/app/components/GooeySelect.tsx b/app/components/GooeySelect.tsx index 376cc4a..b8d6998 100644 --- a/app/components/GooeySelect.tsx +++ b/app/components/GooeySelect.tsx @@ -25,6 +25,7 @@ export default function GooeySelect({ defaultValue, name, onChange, + args, }); // if the state value is changed by the server code, then update the value diff --git a/app/gooeyInput.tsx b/app/gooeyInput.tsx index b1be7e8..ffe6c1c 100644 --- a/app/gooeyInput.tsx +++ b/app/gooeyInput.tsx @@ -37,6 +37,7 @@ export function GooeyTextarea({ state, name, defaultValue, + args, }); return (
@@ -74,6 +75,7 @@ export function GooeyInput({ state, name, defaultValue, + args, }); return (
@@ -100,10 +102,12 @@ export function useGooeyStringInput< state, name, defaultValue, + args, }: { state: Record; name: string; defaultValue: string; + args?: Record; }): [ inputRef: React.RefObject, value: string, @@ -117,6 +121,8 @@ export function useGooeyStringInput< // but to avoid reloading the page on every change with onChange (gets very annoying when typing), we need to use this extra state variable with a useEffect const [value, setValue] = useState(state[name] || defaultValue); + loadEventHandlers(value, setValue, args); + useEffect(() => { const element = inputRef.current; if ( @@ -234,3 +240,20 @@ export function useGooeyCheckedInput({ return inputRef; } + +export function loadEventHandlers( + value: T, + setValue: (value: T) => void, + args?: Record +) { + if (!args) return; + for (const [attr, body] of Object.entries(args)) { + if (!attr.startsWith("on")) continue; + args[attr] = (event: React.SyntheticEvent) => { + // new Function(...args, body) + const fn = new Function("event", "value", "setValue", body); + // fn.call(thisArg, ...args) + return fn.call(event.currentTarget, event.nativeEvent, value, setValue); + }; + } +} diff --git a/app/jsonFormInput.tsx b/app/jsonFormInput.tsx index 97b1dce..8466cb5 100644 --- a/app/jsonFormInput.tsx +++ b/app/jsonFormInput.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useRef, useState } from "react"; +import { loadEventHandlers } from "./gooeyInput"; export function useJsonFormInput({ defaultValue, @@ -6,16 +7,20 @@ export function useJsonFormInput({ onChange, encode = JSON.stringify, decode = JSON.parse, + args, }: { defaultValue: T; name: string; onChange?: () => void; encode?: (value: T) => string; decode?: (value: string) => T; + args?: Record; }): [React.FunctionComponent, T, (value: T) => void] { const [value, setValue] = useState(defaultValue); const ref = useRef(null); + loadEventHandlers(value, setValue, args); + useEffect(() => { if (!ref.current) return; if (!ref.current.value) { diff --git a/app/renderer.tsx b/app/renderer.tsx index 352a4e2..aabf9a7 100644 --- a/app/renderer.tsx +++ b/app/renderer.tsx @@ -628,6 +628,7 @@ export function GuiExpander({ defaultValue: open, name, onChange, + args: props, }); return (