diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..32ad81f35 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "proseWrap": "never", + "trailingComma": "all" +} diff --git a/src/js/README.md b/src/js/README.md deleted file mode 100644 index e99df49c0..000000000 --- a/src/js/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ReactPy Client - -An ES6 Javascript client for ReactPy diff --git a/src/js/bun.lockb b/src/js/bun.lockb index ff28eeb7f..d668a4403 100644 Binary files a/src/js/bun.lockb and b/src/js/bun.lockb differ diff --git a/src/js/eslint.config.mjs b/src/js/eslint.config.mjs index 7509afebe..12494f73d 100644 --- a/src/js/eslint.config.mjs +++ b/src/js/eslint.config.mjs @@ -1,58 +1,25 @@ -import react from "eslint-plugin-react"; -import typescriptEslint from "@typescript-eslint/eslint-plugin"; +import { default as eslint } from "@eslint/js"; import globals from "globals"; -import tsParser from "@typescript-eslint/parser"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import js from "@eslint/js"; -import { FlatCompat } from "@eslint/eslintrc"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); +import tseslint from "typescript-eslint"; export default [ - ...compat.extends( - "eslint:recommended", - "plugin:react/recommended", - "plugin:@typescript-eslint/recommended", - ), - { - ignores: ["**/node_modules/", "**/dist/"], - }, + eslint.configs.recommended, + ...tseslint.configs.recommended, + { ignores: ["**/node_modules/", "**/dist/"] }, { - plugins: { - react, - "@typescript-eslint": typescriptEslint, - }, - languageOptions: { globals: { ...globals.browser, ...globals.node, }, - - parser: tsParser, ecmaVersion: "latest", sourceType: "module", }, - - settings: { - react: { - version: "detect", - }, - }, - rules: { "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-empty-function": "off", - "react/prop-types": "off", }, }, ]; diff --git a/src/js/package.json b/src/js/package.json index 26962b2c6..03f49afa0 100644 --- a/src/js/package.json +++ b/src/js/package.json @@ -1,17 +1,15 @@ { "devDependencies": { - "@eslint/eslintrc": "^3.2.0", - "@eslint/js": "^9.18.0", - "@typescript-eslint/eslint-plugin": "^8.21.0", - "@typescript-eslint/parser": "^8.21.0", + "@eslint/js": "^9.29.0", + "bun-types": "^1.2.16", "eslint": "^9.18.0", - "eslint-plugin-react": "^7.37.4", "globals": "^15.14.0", - "prettier": "^3.4.2" + "prettier": "^3.4.2", + "typescript-eslint": "^8.34.0" }, "license": "MIT", "scripts": { - "lint": "prettier --check . && eslint", - "format": "prettier --write . && eslint --fix" + "format": "prettier --write . && eslint --fix", + "lint": "prettier --check . && eslint" } } diff --git a/src/js/packages/@reactpy/app/bun.lockb b/src/js/packages/@reactpy/app/bun.lockb index bd09c30d6..5c921795b 100644 Binary files a/src/js/packages/@reactpy/app/bun.lockb and b/src/js/packages/@reactpy/app/bun.lockb differ diff --git a/src/js/packages/@reactpy/app/eslint.config.mjs b/src/js/packages/@reactpy/app/eslint.config.mjs deleted file mode 100644 index 7c41582b5..000000000 --- a/src/js/packages/@reactpy/app/eslint.config.mjs +++ /dev/null @@ -1,42 +0,0 @@ -import react from "eslint-plugin-react"; -import typescriptEslint from "@typescript-eslint/eslint-plugin"; -import globals from "globals"; -import tsParser from "@typescript-eslint/parser"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; -import js from "@eslint/js"; -import { FlatCompat } from "@eslint/eslintrc"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); - -export default [ - ...compat.extends( - "eslint:recommended", - "plugin:react/recommended", - "plugin:@typescript-eslint/recommended", - ), - { - plugins: { - react, - "@typescript-eslint": typescriptEslint, - }, - - languageOptions: { - globals: { - ...globals.browser, - }, - - parser: tsParser, - ecmaVersion: "latest", - sourceType: "module", - }, - - rules: {}, - }, -]; diff --git a/src/js/packages/@reactpy/app/package.json b/src/js/packages/@reactpy/app/package.json index ca3a4370d..3239e974e 100644 --- a/src/js/packages/@reactpy/app/package.json +++ b/src/js/packages/@reactpy/app/package.json @@ -1,17 +1,17 @@ { - "name": "@reactpy/app", - "description": "ReactPy's client-side entry point. This is strictly for internal use and is not designed to be distributed.", - "license": "MIT", "dependencies": { "@reactpy/client": "file:../client", "event-to-object": "file:../../event-to-object", "preact": "^10.25.4" }, + "description": "ReactPy's client-side entry point. This is strictly for internal use and is not designed to be distributed.", "devDependencies": { - "typescript": "^5.7.3", "@pyscript/core": "^0.6", - "morphdom": "^2" + "morphdom": "^2", + "typescript": "^5.8.3" }, + "license": "MIT", + "name": "@reactpy/app", "scripts": { "build": "bun build \"src/index.ts\" --outdir=\"../../../../reactpy/static/\" --minify --sourcemap=\"linked\"", "checkTypes": "tsc --noEmit" diff --git a/src/js/packages/@reactpy/app/tsconfig.json b/src/js/packages/@reactpy/app/tsconfig.json index fb7013663..e7c43004b 100644 --- a/src/js/packages/@reactpy/app/tsconfig.json +++ b/src/js/packages/@reactpy/app/tsconfig.json @@ -1,10 +1,10 @@ { - "extends": "../../../tsconfig.json", "compilerOptions": { + "composite": true, "outDir": "dist", - "rootDir": "src", - "composite": true + "rootDir": "src" }, + "extends": "../../../tsconfig.json", "include": ["src"], "references": [ { diff --git a/src/js/packages/@reactpy/client/bun.lockb b/src/js/packages/@reactpy/client/bun.lockb index 35e6ef1c5..10334c0e5 100644 Binary files a/src/js/packages/@reactpy/client/bun.lockb and b/src/js/packages/@reactpy/client/bun.lockb differ diff --git a/src/js/packages/@reactpy/client/package.json b/src/js/packages/@reactpy/client/package.json index 95e545eb4..1016f94f1 100644 --- a/src/js/packages/@reactpy/client/package.json +++ b/src/js/packages/@reactpy/client/package.json @@ -1,12 +1,13 @@ { - "name": "@reactpy/client", - "version": "1.0.0", - "description": "A client for ReactPy implemented in React", "author": "Ryan Morshead", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/reactive-python/reactpy" + "dependencies": { + "json-pointer": "^0.6.2", + "preact": "^10.26.9" + }, + "description": "A client for ReactPy implemented in React", + "devDependencies": { + "@types/json-pointer": "^1.0.34", + "typescript": "^5.8.3" }, "keywords": [ "react", @@ -14,23 +15,20 @@ "python", "reactpy" ], - "type": "module", + "license": "MIT", "main": "dist/index.js", - "dependencies": { - "json-pointer": "^0.6.2", - "preact": "^10.25.4" - }, - "devDependencies": { - "@types/json-pointer": "^1.0.34", - "@types/react": "^17.0", - "@types/react-dom": "^17.0", - "typescript": "^5.7.3" - }, + "name": "@reactpy/client", "peerDependencies": { "event-to-object": "<1.0.0" }, + "repository": { + "type": "git", + "url": "https://github.com/reactive-python/reactpy" + }, "scripts": { "build": "tsc -b", "checkTypes": "tsc --noEmit" - } + }, + "type": "module", + "version": "1.0.0" } diff --git a/src/js/packages/@reactpy/client/src/client.ts b/src/js/packages/@reactpy/client/src/client.ts index ea4e1aed5..8d9333094 100644 --- a/src/js/packages/@reactpy/client/src/client.ts +++ b/src/js/packages/@reactpy/client/src/client.ts @@ -1,5 +1,5 @@ import logger from "./logger"; -import { +import type { ReactPyClientInterface, ReactPyModule, GenericReactPyClientProps, diff --git a/src/js/packages/@reactpy/client/src/components.tsx b/src/js/packages/@reactpy/client/src/components.tsx index 42f303198..a4fa97ce3 100644 --- a/src/js/packages/@reactpy/client/src/components.tsx +++ b/src/js/packages/@reactpy/client/src/components.tsx @@ -1,16 +1,8 @@ import { set as setJsonPointer } from "json-pointer"; -import React, { - ChangeEvent, - createContext, - createElement, - Fragment, - MutableRefObject, - useContext, - useEffect, - useRef, - useState, -} from "preact/compat"; -import { +import type { ChangeEvent, MutableRefObject } from "preact/compat"; +import { createContext, createElement, Fragment, type JSX } from "preact"; +import { useContext, useEffect, useRef, useState } from "preact/hooks"; +import type { ImportSourceBinding, ReactPyComponent, ReactPyVdom, @@ -67,7 +59,7 @@ export function Element({ model }: { model: ReactPyVdom }): JSX.Element | null { } function StandardElement({ model }: { model: ReactPyVdom }) { - const client = React.useContext(ClientContext); + const client = useContext(ClientContext); // Use createElement here to avoid warning about variable numbers of children not // having keys. Warning about this must now be the responsibility of the client // providing the models instead of the client rendering them. @@ -83,10 +75,10 @@ function StandardElement({ model }: { model: ReactPyVdom }) { function UserInputElement({ model }: { model: ReactPyVdom }): JSX.Element { const client = useContext(ClientContext); const props = createAttributes(model, client); - const [value, setValue] = React.useState(props.value); + const [value, setValue] = useState(props.value); // honor changes to value from the client via props - React.useEffect(() => setValue(props.value), [props.value]); + useEffect(() => setValue(props.value), [props.value]); const givenOnChange = props.onChange; if (typeof givenOnChange === "function") { @@ -116,7 +108,7 @@ function UserInputElement({ model }: { model: ReactPyVdom }): JSX.Element { function ScriptElement({ model }: { model: ReactPyVdom }) { const ref = useRef(null); - React.useEffect(() => { + useEffect(() => { // Don't run if the parent element is missing if (!ref.current) { return; @@ -181,10 +173,10 @@ function useImportSource(model: ReactPyVdom): MutableRefObject { const vdomImportSource = model.importSource; const vdomImportSourceJsonString = JSON.stringify(vdomImportSource); const mountPoint = useRef(null); - const client = React.useContext(ClientContext); + const client = useContext(ClientContext); const [binding, setBinding] = useState(null); - React.useEffect(() => { + useEffect(() => { let unmounted = false; if (vdomImportSource) { diff --git a/src/js/packages/@reactpy/client/src/mount.tsx b/src/js/packages/@reactpy/client/src/mount.tsx index 55ba4245e..281f8291e 100644 --- a/src/js/packages/@reactpy/client/src/mount.tsx +++ b/src/js/packages/@reactpy/client/src/mount.tsx @@ -1,7 +1,7 @@ -import { default as React, default as ReactDOM } from "preact/compat"; +import { render } from "preact"; import { ReactPyClient } from "./client"; import { Layout } from "./components"; -import { MountProps } from "./types"; +import type { MountProps } from "./types"; export function mountReactPy(props: MountProps) { // WebSocket route for component rendering @@ -36,6 +36,5 @@ export function mountReactPy(props: MountProps) { }); // Start rendering the component - // eslint-disable-next-line react/no-deprecated - ReactDOM.render(, props.mountElement); + render(, props.mountElement); } diff --git a/src/js/packages/@reactpy/client/src/types.ts b/src/js/packages/@reactpy/client/src/types.ts index 148a3486c..49232e532 100644 --- a/src/js/packages/@reactpy/client/src/types.ts +++ b/src/js/packages/@reactpy/client/src/types.ts @@ -1,4 +1,4 @@ -import { ComponentType } from "react"; +import type { ComponentType } from "preact"; // #### CONNECTION TYPES #### diff --git a/src/js/packages/@reactpy/client/src/vdom.tsx b/src/js/packages/@reactpy/client/src/vdom.tsx index 4bd882ff4..f54111de7 100644 --- a/src/js/packages/@reactpy/client/src/vdom.tsx +++ b/src/js/packages/@reactpy/client/src/vdom.tsx @@ -1,7 +1,6 @@ -import React from "react"; -import { ReactPyClientInterface } from "./types"; +import type { ReactPyClientInterface } from "./types"; import serializeEvent from "event-to-object"; -import { +import type { ReactPyVdom, ReactPyVdomImportSource, ReactPyVdomEventHandler, @@ -112,7 +111,7 @@ function getComponentFromModule( /* Gets the component with the provided name from the provided module. Built specifically to work on inifinitely deep nested components. - For example, component "My.Nested.Component" is accessed from + For example, component "My.Nested.Component" is accessed from ModuleA like so: ModuleA["My"]["Nested"]["Component"]. */ const componentParts: string[] = componentName.split("."); @@ -206,17 +205,14 @@ function createEventHandler( ): [string, () => void] { const eventHandler = function (...args: any[]) { const data = Array.from(args).map((value) => { - if (!(typeof value === "object" && value.nativeEvent)) { - return value; - } - const event = value as React.SyntheticEvent; + const event = value as Event; if (preventDefault) { event.preventDefault(); } if (stopPropagation) { event.stopPropagation(); } - return serializeEvent(event.nativeEvent); + return serializeEvent(event); }); client.sendMessage({ type: "layout-event", data, target }); }; @@ -228,7 +224,7 @@ function createInlineJavaScript( name: string, inlineJavaScript: string, ): [string, () => void] { - /* Function that will execute the string-like InlineJavaScript + /* Function that will execute the string-like InlineJavaScript via eval in the most appropriate way */ const wrappedExecutable = function (...args: any[]) { function handleExecution(...args: any[]) { diff --git a/src/js/packages/@reactpy/client/src/websocket.ts b/src/js/packages/@reactpy/client/src/websocket.ts index ba3fdc09f..4c72620f0 100644 --- a/src/js/packages/@reactpy/client/src/websocket.ts +++ b/src/js/packages/@reactpy/client/src/websocket.ts @@ -1,4 +1,4 @@ -import { CreateReconnectingWebSocketProps } from "./types"; +import type { CreateReconnectingWebSocketProps } from "./types"; import log from "./logger"; export function createReconnectingWebSocket( diff --git a/src/js/packages/@reactpy/client/tsconfig.json b/src/js/packages/@reactpy/client/tsconfig.json index 032152ae8..b6bb436d0 100644 --- a/src/js/packages/@reactpy/client/tsconfig.json +++ b/src/js/packages/@reactpy/client/tsconfig.json @@ -1,10 +1,10 @@ { - "extends": "../../../tsconfig.json", "compilerOptions": { + "composite": true, "outDir": "dist", - "rootDir": "src", - "composite": true + "rootDir": "src" }, + "extends": "../../../tsconfig.json", "include": ["src"], "references": [ { diff --git a/src/js/packages/event-to-object/bun.lockb b/src/js/packages/event-to-object/bun.lockb index d3ca6e7e5..1c6a0e669 100644 Binary files a/src/js/packages/event-to-object/bun.lockb and b/src/js/packages/event-to-object/bun.lockb differ diff --git a/src/js/packages/event-to-object/package.json b/src/js/packages/event-to-object/package.json index 2f3852120..6d2af6dde 100644 --- a/src/js/packages/event-to-object/package.json +++ b/src/js/packages/event-to-object/package.json @@ -1,34 +1,34 @@ { - "name": "event-to-object", - "version": "0.1.2", - "description": "Converts a JavaScript events to JSON serializable objects.", "author": "Ryan Morshead", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/reactive-python/reactpy" - }, - "keywords": [ - "event", - "json", - "object", - "convert" - ], - "type": "module", - "main": "dist/index.js", "dependencies": { "json-pointer": "^0.6.2" }, + "description": "Converts a JavaScript events to JSON serializable objects.", "devDependencies": { "happy-dom": "^8.9.0", "lodash": "^4.17.21", "tsm": "^2.3.0", - "typescript": "^5.7.3", + "typescript": "^5.8.3", "uvu": "^0.5.6" }, + "keywords": [ + "event", + "json", + "object", + "convert" + ], + "license": "MIT", + "main": "dist/index.js", + "name": "event-to-object", + "repository": { + "type": "git", + "url": "https://github.com/reactive-python/reactpy" + }, "scripts": { "build": "tsc -b", "checkTypes": "tsc --noEmit", "test": "uvu -r tsm tests" - } + }, + "type": "module", + "version": "0.1.2" } diff --git a/src/js/packages/event-to-object/src/index.ts b/src/js/packages/event-to-object/src/index.ts index 8790add04..3f263af4d 100644 --- a/src/js/packages/event-to-object/src/index.ts +++ b/src/js/packages/event-to-object/src/index.ts @@ -11,6 +11,7 @@ export default function convert( ? P : never; }[keyof e.EventToObjectMap] + | e.EventObject | null { return event.type in eventConverters ? eventConverters[event.type](event) diff --git a/src/js/packages/event-to-object/tsconfig.json b/src/js/packages/event-to-object/tsconfig.json index 9b0e0b6a5..4fec695a9 100644 --- a/src/js/packages/event-to-object/tsconfig.json +++ b/src/js/packages/event-to-object/tsconfig.json @@ -1,9 +1,9 @@ { - "extends": "../../tsconfig.json", "compilerOptions": { + "composite": true, "outDir": "dist", - "rootDir": "src", - "composite": true + "rootDir": "src" }, + "extends": "../../tsconfig.json", "include": ["src"] } diff --git a/src/js/tsconfig.json b/src/js/tsconfig.json index 9e7fe5f74..aa44c2023 100644 --- a/src/js/tsconfig.json +++ b/src/js/tsconfig.json @@ -1,22 +1,31 @@ { "compilerOptions": { - "allowJs": false, + "allowJs": true, "allowSyntheticDefaultImports": true, "declaration": true, "declarationMap": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "isolatedModules": true, - "jsx": "react", - "lib": ["DOM", "DOM.Iterable", "esnext"], - "module": "esnext", - "moduleResolution": "node", + "jsx": "react-jsx", + "jsxImportSource": "preact", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "module": "Preserve", + "moduleDetection": "force", + "moduleResolution": "bundler", "noEmitOnError": true, "noUnusedLocals": true, + "paths": { + "react": ["./node_modules/preact/compat/"], + "react-dom": ["./node_modules/preact/compat/"], + "react-dom/*": ["./node_modules/preact/compat/*"], + "react/jsx-runtime": ["./node_modules/preact/jsx-runtime"] + }, "resolveJsonModule": true, - "skipLibCheck": false, + "skipLibCheck": true, "sourceMap": true, "strict": true, - "target": "esnext" + "target": "ESNext", + "verbatimModuleSyntax": true } } diff --git a/src/reactpy/executors/utils.py b/src/reactpy/executors/utils.py index e0008df9a..b68d56627 100644 --- a/src/reactpy/executors/utils.py +++ b/src/reactpy/executors/utils.py @@ -43,9 +43,7 @@ def vdom_head_to_html(head: VdomDict) -> str: if isinstance(head, dict) and head.get("tagName") == "head": return reactpy_to_string(head) - raise ValueError( - "Invalid head element! Element must be either `html.head` or a string." - ) + raise ValueError("Head element must be constructed with `html.head`.") def process_settings(settings: ReactPyConfig) -> None: diff --git a/tests/test_asgi/test_utils.py b/tests/test_asgi/test_utils.py index f0ffc5a73..7b65b2d80 100644 --- a/tests/test_asgi/test_utils.py +++ b/tests/test_asgi/test_utils.py @@ -5,7 +5,7 @@ def test_invalid_vdom_head(): - with pytest.raises(ValueError, match="Invalid head element!*"): + with pytest.raises(ValueError): utils.vdom_head_to_html({"tagName": "invalid"}) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy