From 8730d637a2cac4abd2b5ccc63dbd178898316aa5 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 19:21:09 +0000 Subject: [PATCH 01/10] refactor into package --- demo/.eslintrc.cjs => .eslintrc.cjs | 0 .gitignore | 2 ++ .pre-commit-config.yaml | 31 +++++++++++++++++++ demo/src/App.tsx | 4 +-- demo/src/main.tsx | 2 +- demo/tsconfig.json | 5 ++- demo/vite.config.ts | 1 + .../fastui}/DefaultLoading.tsx | 0 .../fastui}/components/FormField.tsx | 0 .../fastui}/components/Json.tsx | 0 .../fastui}/components/button.tsx | 0 .../fastui}/components/display.tsx | 0 .../fastui}/components/div.tsx | 0 .../fastui}/components/heading.tsx | 0 .../fastui}/components/index.tsx | 0 .../fastui}/components/link.tsx | 0 .../fastui}/components/modal.css | 0 .../fastui}/components/modal.tsx | 0 .../fastui}/components/table.tsx | 0 .../fastui}/components/text.tsx | 0 .../FastUI => frontend/fastui}/controller.tsx | 0 .../src/FastUI => frontend/fastui}/display.ts | 0 .../fastui}/hooks/className.ts | 0 .../fastui}/hooks/customRender.ts | 0 .../fastui}/hooks/error.tsx | 0 .../FastUI => frontend/fastui}/hooks/event.ts | 0 .../fastui}/hooks/locationContext.tsx | 0 .../src/FastUI => frontend/fastui}/index.tsx | 0 demo/package-lock.json => package-lock.json | 25 ++++++++++++--- demo/package.json => package.json | 15 ++++----- tsconfig.json | 24 ++++++++++++++ 31 files changed, 94 insertions(+), 15 deletions(-) rename demo/.eslintrc.cjs => .eslintrc.cjs (100%) create mode 100644 .pre-commit-config.yaml rename {demo/src/FastUI => frontend/fastui}/DefaultLoading.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/FormField.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/Json.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/button.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/display.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/div.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/heading.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/index.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/link.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/modal.css (100%) rename {demo/src/FastUI => frontend/fastui}/components/modal.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/table.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/components/text.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/controller.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/display.ts (100%) rename {demo/src/FastUI => frontend/fastui}/hooks/className.ts (100%) rename {demo/src/FastUI => frontend/fastui}/hooks/customRender.ts (100%) rename {demo/src/FastUI => frontend/fastui}/hooks/error.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/hooks/event.ts (100%) rename {demo/src/FastUI => frontend/fastui}/hooks/locationContext.tsx (100%) rename {demo/src/FastUI => frontend/fastui}/index.tsx (100%) rename demo/package-lock.json => package-lock.json (99%) rename demo/package.json => package.json (73%) create mode 100644 tsconfig.json diff --git a/demo/.eslintrc.cjs b/.eslintrc.cjs similarity index 100% rename from demo/.eslintrc.cjs rename to .eslintrc.cjs diff --git a/.gitignore b/.gitignore index 0250f827..d59a676b 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ dist-ssr __pycache__/ /.logfire/ +/frontend-dist/ +/scratch/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..18323275 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,31 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + # - id: no-commit-to-branch + - id: check-yaml + args: ['--unsafe'] + - id: check-toml + - id: end-of-file-fixer + - id: trailing-whitespace + + - repo: local + hooks: + - id: frontend-prettier + name: frontend-prettier + types_or: [javascript, jsx, ts, tsx] + entry: npm run prettier + language: system + pass_filenames: false + - id: frontend-lint + name: frontend-lint + types_or: [javascript, jsx, ts, tsx] + entry: npm run lint-fix + language: system + pass_filenames: false + - id: frontend-typecheck + name: frontend-typecheck + types_or: [javascript, jsx, ts, tsx] + entry: npm run typecheck + language: system + pass_filenames: false diff --git a/demo/src/App.tsx b/demo/src/App.tsx index b306fbf0..fc1d584a 100644 --- a/demo/src/App.tsx +++ b/demo/src/App.tsx @@ -1,6 +1,6 @@ -import { FastUI, ClassNameGenerator, CustomRender } from './FastUI' +import { FastUI, ClassNameGenerator, CustomRender } from 'fastui' -export default function App () { +export default function App() { return (
diff --git a/demo/src/main.tsx b/demo/src/main.tsx index 76528bce..0a75e0ae 100644 --- a/demo/src/main.tsx +++ b/demo/src/main.tsx @@ -7,5 +7,5 @@ import './main.scss' ReactDOM.createRoot(document.getElementById('root')!).render( - + , ) diff --git a/demo/tsconfig.json b/demo/tsconfig.json index d62f6758..2ff3191b 100644 --- a/demo/tsconfig.json +++ b/demo/tsconfig.json @@ -18,7 +18,10 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "paths": { + "fastui": ["../frontend/fastui"] + } }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/demo/vite.config.ts b/demo/vite.config.ts index cac14eee..3be10613 100644 --- a/demo/vite.config.ts +++ b/demo/vite.config.ts @@ -17,6 +17,7 @@ export default () => { resolve: { alias: { '@': path.resolve(__dirname, './src'), + fastui: path.resolve(__dirname, '../frontend/fastui'), }, }, server: serverConfig, diff --git a/demo/src/FastUI/DefaultLoading.tsx b/frontend/fastui/DefaultLoading.tsx similarity index 100% rename from demo/src/FastUI/DefaultLoading.tsx rename to frontend/fastui/DefaultLoading.tsx diff --git a/demo/src/FastUI/components/FormField.tsx b/frontend/fastui/components/FormField.tsx similarity index 100% rename from demo/src/FastUI/components/FormField.tsx rename to frontend/fastui/components/FormField.tsx diff --git a/demo/src/FastUI/components/Json.tsx b/frontend/fastui/components/Json.tsx similarity index 100% rename from demo/src/FastUI/components/Json.tsx rename to frontend/fastui/components/Json.tsx diff --git a/demo/src/FastUI/components/button.tsx b/frontend/fastui/components/button.tsx similarity index 100% rename from demo/src/FastUI/components/button.tsx rename to frontend/fastui/components/button.tsx diff --git a/demo/src/FastUI/components/display.tsx b/frontend/fastui/components/display.tsx similarity index 100% rename from demo/src/FastUI/components/display.tsx rename to frontend/fastui/components/display.tsx diff --git a/demo/src/FastUI/components/div.tsx b/frontend/fastui/components/div.tsx similarity index 100% rename from demo/src/FastUI/components/div.tsx rename to frontend/fastui/components/div.tsx diff --git a/demo/src/FastUI/components/heading.tsx b/frontend/fastui/components/heading.tsx similarity index 100% rename from demo/src/FastUI/components/heading.tsx rename to frontend/fastui/components/heading.tsx diff --git a/demo/src/FastUI/components/index.tsx b/frontend/fastui/components/index.tsx similarity index 100% rename from demo/src/FastUI/components/index.tsx rename to frontend/fastui/components/index.tsx diff --git a/demo/src/FastUI/components/link.tsx b/frontend/fastui/components/link.tsx similarity index 100% rename from demo/src/FastUI/components/link.tsx rename to frontend/fastui/components/link.tsx diff --git a/demo/src/FastUI/components/modal.css b/frontend/fastui/components/modal.css similarity index 100% rename from demo/src/FastUI/components/modal.css rename to frontend/fastui/components/modal.css diff --git a/demo/src/FastUI/components/modal.tsx b/frontend/fastui/components/modal.tsx similarity index 100% rename from demo/src/FastUI/components/modal.tsx rename to frontend/fastui/components/modal.tsx diff --git a/demo/src/FastUI/components/table.tsx b/frontend/fastui/components/table.tsx similarity index 100% rename from demo/src/FastUI/components/table.tsx rename to frontend/fastui/components/table.tsx diff --git a/demo/src/FastUI/components/text.tsx b/frontend/fastui/components/text.tsx similarity index 100% rename from demo/src/FastUI/components/text.tsx rename to frontend/fastui/components/text.tsx diff --git a/demo/src/FastUI/controller.tsx b/frontend/fastui/controller.tsx similarity index 100% rename from demo/src/FastUI/controller.tsx rename to frontend/fastui/controller.tsx diff --git a/demo/src/FastUI/display.ts b/frontend/fastui/display.ts similarity index 100% rename from demo/src/FastUI/display.ts rename to frontend/fastui/display.ts diff --git a/demo/src/FastUI/hooks/className.ts b/frontend/fastui/hooks/className.ts similarity index 100% rename from demo/src/FastUI/hooks/className.ts rename to frontend/fastui/hooks/className.ts diff --git a/demo/src/FastUI/hooks/customRender.ts b/frontend/fastui/hooks/customRender.ts similarity index 100% rename from demo/src/FastUI/hooks/customRender.ts rename to frontend/fastui/hooks/customRender.ts diff --git a/demo/src/FastUI/hooks/error.tsx b/frontend/fastui/hooks/error.tsx similarity index 100% rename from demo/src/FastUI/hooks/error.tsx rename to frontend/fastui/hooks/error.tsx diff --git a/demo/src/FastUI/hooks/event.ts b/frontend/fastui/hooks/event.ts similarity index 100% rename from demo/src/FastUI/hooks/event.ts rename to frontend/fastui/hooks/event.ts diff --git a/demo/src/FastUI/hooks/locationContext.tsx b/frontend/fastui/hooks/locationContext.tsx similarity index 100% rename from demo/src/FastUI/hooks/locationContext.tsx rename to frontend/fastui/hooks/locationContext.tsx diff --git a/demo/src/FastUI/index.tsx b/frontend/fastui/index.tsx similarity index 100% rename from demo/src/FastUI/index.tsx rename to frontend/fastui/index.tsx diff --git a/demo/package-lock.json b/package-lock.json similarity index 99% rename from demo/package-lock.json rename to package-lock.json index c40a8ba8..e0a9d386 100644 --- a/demo/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "fastui-demo", + "name": "fastui", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "fastui-demo", + "name": "fastui", "version": "0.0.0", "dependencies": { "react": "^18.2.0", @@ -26,7 +26,6 @@ "eslint-plugin-react-refresh": "^0.4.4", "eslint-plugin-simple-import-sort": "^10.0.0", "prettier": "^3.0.3", - "sass": "^1.67.0", "typescript": "^5.0.2", "vite": "^4.4.5" } @@ -1054,6 +1053,8 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1231,6 +1232,8 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=8" } @@ -1349,6 +1352,8 @@ "url": "https://paulmillr.com/funding/" } ], + "optional": true, + "peer": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -1370,6 +1375,8 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -2538,7 +2545,9 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", - "dev": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/import-fresh": { "version": "3.3.0", @@ -2641,6 +2650,8 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -3170,6 +3181,8 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -3547,6 +3560,8 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -3729,6 +3744,8 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.67.0.tgz", "integrity": "sha512-SVrO9ZeX/QQyEGtuZYCVxoeAL5vGlYjJ9p4i4HFuekWl8y/LtJ7tJc10Z+ck1c8xOuoBm2MYzcLfTAffD0pl/A==", "dev": true, + "optional": true, + "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", diff --git a/demo/package.json b/package.json similarity index 73% rename from demo/package.json rename to package.json index e13fc338..6bf36c0d 100644 --- a/demo/package.json +++ b/package.json @@ -1,16 +1,18 @@ { - "name": "fastui-demo", + "name": "fastui", "private": true, "version": "0.0.0", "type": "module", + "entry": "src/index.tsx", "scripts": { - "dev": "vite", + "dev": "vite demo", "typecheck": "tsc --noEmit", + "build": "tsc", "typewatch": "tsc --noEmit --watch", - "build": "tsc && vite build", - "lint": "eslint . --ext .ts,.tsx --report-unused-disable-directives --max-warnings 0", - "format": "prettier . --write -- '**/*.{ts,tsx,js,css,json,md}' && npm run lint -- --fix", - "preview": "vite preview" + "lint": "eslint frontend --ext .ts,.tsx --report-unused-disable-directives --max-warnings 0", + "lint-fix": "npm run lint -- --fix", + "prettier": "prettier . --write -- '**/*.{ts,tsx,js,css,json,md}'", + "format": "npm run prettier && npm run lint-fix" }, "prettier": { "singleQuote": true, @@ -39,7 +41,6 @@ "eslint-plugin-react-refresh": "^0.4.4", "eslint-plugin-simple-import-sort": "^10.0.0", "prettier": "^3.0.3", - "sass": "^1.67.0", "typescript": "^5.0.2", "vite": "^4.4.5" } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..58064ef2 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "outDir": "./frontend-dist", + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": false, + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["frontend"] +} From 759a8e36ad81a98b79e55e56ed431061ab92fb4a Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 19:25:07 +0000 Subject: [PATCH 02/10] fix eslint vs. prettier --- .eslintrc.cjs | 3 ++- frontend/fastui/components/heading.tsx | 2 +- frontend/fastui/components/index.tsx | 2 +- frontend/fastui/controller.tsx | 2 +- frontend/fastui/hooks/className.ts | 8 ++++---- frontend/fastui/hooks/error.tsx | 4 ++-- frontend/fastui/hooks/event.ts | 8 ++++---- frontend/fastui/hooks/locationContext.tsx | 10 +++++----- frontend/fastui/index.tsx | 2 +- 9 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index ae920678..91bb695a 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -6,8 +6,9 @@ module.exports = { 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', + 'prettier', ], - ignorePatterns: ['dist', '.eslintrc.cjs', 'vite.config.ts'], + ignorePatterns: ['dist', '.eslintrc.cjs', 'demo/vite.config.ts'], parser: '@typescript-eslint/parser', plugins: ['react', '@typescript-eslint', 'react-refresh', 'simple-import-sort'], rules: { diff --git a/frontend/fastui/components/heading.tsx b/frontend/fastui/components/heading.tsx index 5473fe98..cc68a1e5 100644 --- a/frontend/fastui/components/heading.tsx +++ b/frontend/fastui/components/heading.tsx @@ -15,7 +15,7 @@ export const HeadingComp: FC = (props) => { return } -function getComponent (level: 1 | 2 | 3 | 4 | 5 | 6): FC<{ text: string; className: string }> { +function getComponent(level: 1 | 2 | 3 | 4 | 5 | 6): FC<{ text: string; className: string }> { switch (level) { case 1: return ({ text, className }) =>

{text}

diff --git a/frontend/fastui/components/index.tsx b/frontend/fastui/components/index.tsx index 83d5be15..104ac952 100644 --- a/frontend/fastui/components/index.tsx +++ b/frontend/fastui/components/index.tsx @@ -81,7 +81,7 @@ interface WithChildren { children: FastProps[] } -function renderWithChildren (Component: FC, props: T) { +function renderWithChildren(Component: FC, props: T) { const { children, ...rest } = props // TODO is there a way to make this type safe? return {children} diff --git a/frontend/fastui/controller.tsx b/frontend/fastui/controller.tsx index 98760a15..30ac3740 100644 --- a/frontend/fastui/controller.tsx +++ b/frontend/fastui/controller.tsx @@ -68,7 +68,7 @@ const request = async ({ url, method, headers, body }: Request): Promise(null) const { fullPath } = useContext(LocationContext) diff --git a/frontend/fastui/hooks/className.ts b/frontend/fastui/hooks/className.ts index a24d7eed..49a76513 100644 --- a/frontend/fastui/hooks/className.ts +++ b/frontend/fastui/hooks/className.ts @@ -14,7 +14,7 @@ export const ClassNameContext = createContext(null) * @param props The full props object sent from the backend, this is passed to the class name generator. * @param dft default className to use if the class name generator is not set or returns undefined. */ -export function useClassNameGenerator (classNameProp: ClassName, props: FastProps, dft?: ClassName): string { +export function useClassNameGenerator(classNameProp: ClassName, props: FastProps, dft?: ClassName): string { const classNameGenerator = useContext(ClassNameContext) if (combineClassNameProp(classNameProp)) { if (!dft && classNameGenerator) { @@ -33,7 +33,7 @@ export function useClassNameGenerator (classNameProp: ClassName, props: FastProp * then we generate the default className and append the user's className to it. * @param classNameProp */ -function combineClassNameProp (classNameProp: ClassName): boolean { +function combineClassNameProp(classNameProp: ClassName): boolean { if (Array.isArray(classNameProp)) { // classNameProp is an array, check if it contains `+` return classNameProp.some((c) => c === '+') @@ -49,7 +49,7 @@ function combineClassNameProp (classNameProp: ClassName): boolean { } } -function combine (cn1: ClassName, cn2: ClassName): string { +function combine(cn1: ClassName, cn2: ClassName): string { if (!cn1) { return renderClassName(cn2) } else if (!cn2) { @@ -63,7 +63,7 @@ function combine (cn1: ClassName, cn2: ClassName): string { * Renders the className to a string, removing plus signs. * @param className */ -export function renderClassName (className: ClassName): string { +export function renderClassName(className: ClassName): string { if (typeof className === 'string') { return className.replace(/^\+ /, '') } else if (Array.isArray(className)) { diff --git a/frontend/fastui/hooks/error.tsx b/frontend/fastui/hooks/error.tsx index 97a345bb..32c1fc59 100644 --- a/frontend/fastui/hooks/error.tsx +++ b/frontend/fastui/hooks/error.tsx @@ -30,7 +30,7 @@ const DefaultErrorDisplay: ErrorDisplayType = ({ title, description, children }) export const ErrorContext = createContext({ error: null, setError: () => null, - DisplayError: DefaultErrorDisplay + DisplayError: DefaultErrorDisplay, }) const MaybeError: FC<{ children: ReactNode }> = ({ children }) => { @@ -55,7 +55,7 @@ export const ErrorContextProvider: FC = ({ DisplayError, children }) => { console.warn('setting error:', error) setErrorState(error) }, - [setErrorState] + [setErrorState], ) const contextValue: ErrorContextType = { error, setError, DisplayError: DisplayError ?? DefaultErrorDisplay } diff --git a/frontend/fastui/hooks/event.ts b/frontend/fastui/hooks/event.ts index 3f83d785..2209ae84 100644 --- a/frontend/fastui/hooks/event.ts +++ b/frontend/fastui/hooks/event.ts @@ -12,14 +12,14 @@ export interface GoToEvent { url: string } -function pageEventType (event: PageEvent): string { +function pageEventType(event: PageEvent): string { return `fastui:${event.name}` } -export function useFireEvent (): { fireEvent: (event?: PageEvent | GoToEvent) => void } { +export function useFireEvent(): { fireEvent: (event?: PageEvent | GoToEvent) => void } { const location = useContext(LocationContext) - function fireEvent (event?: PageEvent | GoToEvent) { + function fireEvent(event?: PageEvent | GoToEvent) { if (!event) { return } @@ -38,7 +38,7 @@ export function useFireEvent (): { fireEvent: (event?: PageEvent | GoToEvent) => return { fireEvent } } -export function useEventListenerToggle (event?: PageEvent, initialState = false): [boolean, () => void] { +export function useEventListenerToggle(event?: PageEvent, initialState = false): [boolean, () => void] { const [state, setState] = useState(initialState) const toggle = useCallback(() => setState((state) => !state), []) diff --git a/frontend/fastui/hooks/locationContext.tsx b/frontend/fastui/hooks/locationContext.tsx index 8e81c45a..bc60c354 100644 --- a/frontend/fastui/hooks/locationContext.tsx +++ b/frontend/fastui/hooks/locationContext.tsx @@ -2,7 +2,7 @@ import { createContext, ReactNode, useEffect, useState, useCallback, useContext import { ErrorContext } from './error' -function parseLocation (): string { +function parseLocation(): string { const { href, origin } = window.location // remove origin from the beginning of href return href.slice(origin.length) @@ -17,12 +17,12 @@ const initialPath = parseLocation() const initialState = { fullPath: initialPath, - goto: () => null + goto: () => null, } export const LocationContext = createContext(initialState) -export function LocationProvider ({ children }: { children: ReactNode }) { +export function LocationProvider({ children }: { children: ReactNode }) { const [fullPath, setFullPath] = useState(initialPath) const { setError } = useContext(ErrorContext) @@ -66,8 +66,8 @@ export function LocationProvider ({ children }: { children: ReactNode }) { setError(null) setFullPath(newPath) }, - [setError] - ) + [setError], + ), } return {children} diff --git a/frontend/fastui/index.tsx b/frontend/fastui/index.tsx index 2cdaeb43..d5f2784c 100644 --- a/frontend/fastui/index.tsx +++ b/frontend/fastui/index.tsx @@ -20,7 +20,7 @@ export interface FastUIProps { customRender?: CustomRender } -export function FastUI (props: FastUIProps) { +export function FastUI(props: FastUIProps) { const { classNameGenerator, DisplayError, customRender, ...rest } = props return (
From 9e905332f30762a99cca3f56a41b6f1523abb3c2 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 19:32:17 +0000 Subject: [PATCH 03/10] fix pre-commit prettier --- .pre-commit-config.yaml | 7 +++---- package.json | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 18323275..0dc21828 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,19 +13,18 @@ repos: hooks: - id: frontend-prettier name: frontend-prettier - types_or: [javascript, jsx, ts, tsx] + types_or: [javascript, jsx, ts, tsx, css, json, markdown] entry: npm run prettier language: system - pass_filenames: false - id: frontend-lint name: frontend-lint - types_or: [javascript, jsx, ts, tsx] + types_or: [ts, tsx] entry: npm run lint-fix language: system pass_filenames: false - id: frontend-typecheck name: frontend-typecheck - types_or: [javascript, jsx, ts, tsx] + types_or: [ts, tsx] entry: npm run typecheck language: system pass_filenames: false diff --git a/package.json b/package.json index 6bf36c0d..5eed218a 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "typewatch": "tsc --noEmit --watch", "lint": "eslint frontend --ext .ts,.tsx --report-unused-disable-directives --max-warnings 0", "lint-fix": "npm run lint -- --fix", - "prettier": "prettier . --write -- '**/*.{ts,tsx,js,css,json,md}'", - "format": "npm run prettier && npm run lint-fix" + "prettier": "prettier --write", + "format": "npm run prettier -- . && npm run lint-fix" }, "prettier": { "singleQuote": true, From eb6147512ca8df3c297d3ce192a13872a26e77b4 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 20:15:23 +0000 Subject: [PATCH 04/10] moving python --- .pre-commit-config.yaml | 2 +- LICENSE | 21 ++++++++ README.md | 3 ++ demo/{server/main.py => server.py} | 15 ++---- demo/tsconfig.json | 2 +- demo/vite.config.ts | 2 +- package.json | 2 +- pyproject.toml | 49 +++++++++++++++++++ python/fastui/__init__.py | 8 +++ .../fastui}/components/__init__.py | 0 .../fastui}/components/events.py | 0 .../fastui}/components/extra.py | 0 .../fastui}/components/table.py | 0 {frontend => react}/fastui/DefaultLoading.tsx | 0 .../fastui/components/FormField.tsx | 0 .../fastui/components/Json.tsx | 0 .../fastui/components/button.tsx | 0 .../fastui/components/display.tsx | 0 {frontend => react}/fastui/components/div.tsx | 0 .../fastui/components/heading.tsx | 0 .../fastui/components/index.tsx | 0 .../fastui/components/link.tsx | 0 .../fastui/components/modal.css | 0 .../fastui/components/modal.tsx | 0 .../fastui/components/table.tsx | 0 .../fastui/components/text.tsx | 0 {frontend => react}/fastui/controller.tsx | 0 {frontend => react}/fastui/display.ts | 0 {frontend => react}/fastui/hooks/className.ts | 0 .../fastui/hooks/customRender.ts | 0 {frontend => react}/fastui/hooks/error.tsx | 0 {frontend => react}/fastui/hooks/event.ts | 0 .../fastui/hooks/locationContext.tsx | 0 {frontend => react}/fastui/index.tsx | 0 tsconfig.json | 4 +- 35 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 LICENSE create mode 100644 README.md rename demo/{server/main.py => server.py} (83%) create mode 100644 pyproject.toml create mode 100644 python/fastui/__init__.py rename {demo/server => python/fastui}/components/__init__.py (100%) rename {demo/server => python/fastui}/components/events.py (100%) rename {demo/server => python/fastui}/components/extra.py (100%) rename {demo/server => python/fastui}/components/table.py (100%) rename {frontend => react}/fastui/DefaultLoading.tsx (100%) rename {frontend => react}/fastui/components/FormField.tsx (100%) rename {frontend => react}/fastui/components/Json.tsx (100%) rename {frontend => react}/fastui/components/button.tsx (100%) rename {frontend => react}/fastui/components/display.tsx (100%) rename {frontend => react}/fastui/components/div.tsx (100%) rename {frontend => react}/fastui/components/heading.tsx (100%) rename {frontend => react}/fastui/components/index.tsx (100%) rename {frontend => react}/fastui/components/link.tsx (100%) rename {frontend => react}/fastui/components/modal.css (100%) rename {frontend => react}/fastui/components/modal.tsx (100%) rename {frontend => react}/fastui/components/table.tsx (100%) rename {frontend => react}/fastui/components/text.tsx (100%) rename {frontend => react}/fastui/controller.tsx (100%) rename {frontend => react}/fastui/display.ts (100%) rename {frontend => react}/fastui/hooks/className.ts (100%) rename {frontend => react}/fastui/hooks/customRender.ts (100%) rename {frontend => react}/fastui/hooks/error.tsx (100%) rename {frontend => react}/fastui/hooks/event.ts (100%) rename {frontend => react}/fastui/hooks/locationContext.tsx (100%) rename {frontend => react}/fastui/index.tsx (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0dc21828..2673841e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.3.0 hooks: - # - id: no-commit-to-branch + - id: no-commit-to-branch - id: check-yaml args: ['--unsafe'] - id: check-toml diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..286f4f19 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 to present Samuel Colvin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..d29303f4 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# FastUI + +WIP diff --git a/demo/server/main.py b/demo/server.py similarity index 83% rename from demo/server/main.py rename to demo/server.py index 287ba121..63b7dd1e 100644 --- a/demo/server/main.py +++ b/demo/server.py @@ -3,20 +3,15 @@ from datetime import date from fastapi import FastAPI -from pydantic import RootModel, BaseModel, Field +from pydantic import BaseModel, Field -import components as c -from components import AnyComponent -from components.events import PageEvent, GoToEvent +from fastui import components as c +from fastui import FastUI app = FastAPI() -class FastUi(RootModel): - root: AnyComponent - - -@app.get('/api/', response_model=FastUi, response_model_exclude_none=True) +@app.get('/api/', response_model=FastUI, response_model_exclude_none=True) def read_root() -> AnyComponent: return c.Page( children=[ @@ -44,7 +39,7 @@ class MyTableRow(BaseModel): enabled: bool | None = None -@app.get('/api/table', response_model=FastUi, response_model_exclude_none=True) +@app.get('/api/table', response_model=FastUI, response_model_exclude_none=True) def read_foo() -> AnyComponent: return c.Page( children=[ diff --git a/demo/tsconfig.json b/demo/tsconfig.json index 2ff3191b..170a281f 100644 --- a/demo/tsconfig.json +++ b/demo/tsconfig.json @@ -20,7 +20,7 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "paths": { - "fastui": ["../frontend/fastui"] + "fastui": ["../react/fastui"] } }, "include": ["src"], diff --git a/demo/vite.config.ts b/demo/vite.config.ts index 3be10613..da1827c0 100644 --- a/demo/vite.config.ts +++ b/demo/vite.config.ts @@ -17,7 +17,7 @@ export default () => { resolve: { alias: { '@': path.resolve(__dirname, './src'), - fastui: path.resolve(__dirname, '../frontend/fastui'), + fastui: path.resolve(__dirname, '../react/fastui'), }, }, server: serverConfig, diff --git a/package.json b/package.json index 5eed218a..cf779fce 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "typecheck": "tsc --noEmit", "build": "tsc", "typewatch": "tsc --noEmit --watch", - "lint": "eslint frontend --ext .ts,.tsx --report-unused-disable-directives --max-warnings 0", + "lint": "eslint react --ext .ts,.tsx --report-unused-disable-directives --max-warnings 0", "lint-fix": "npm run lint -- --fix", "prettier": "prettier --write", "format": "npm run prettier -- . && npm run lint-fix" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..33118b79 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,49 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.build.targets.sdist] +include = ["python"] + +[tool.hatch.build.targets.wheel] +packages = ["python/fastui"] + +[tool.hatch.version] +path = "python/fastui/__init__.py" + +[project] +name = "fastui" +description = "Build UIs fast." +authors = [{ name = "Samuel Colvin", email = "s@muelcolvin.com" }] +license = "MIT" +readme = "README.md" +classifiers = [ + "Development Status :: 4 - Beta", + "Topic :: Internet", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + "Intended Audience :: Developers", + "Intended Audience :: Information Technology", +] +requires-python = ">=3.8" +dependencies = [ + "pydantic>=2.5.0b1", + "fastapi>=0.104.0", +] +dynamic = ["version"] + +[project.urls] +Homepage = "https://github.com/samuelcolvin/fastui" + + +[tool.ruff] +line-length = 120 +extend-select = ["Q", "RUF100", "UP", "I"] +flake8-quotes = {inline-quotes = "single", multiline-quotes = "double"} +target-version = "py38" diff --git a/python/fastui/__init__.py b/python/fastui/__init__.py new file mode 100644 index 00000000..a1e2ec06 --- /dev/null +++ b/python/fastui/__init__.py @@ -0,0 +1,8 @@ +__version__ = '0.0.1' + +from pydantic import RootModel +from .components import AnyComponent + + +class FastUI(RootModel): + root: AnyComponent diff --git a/demo/server/components/__init__.py b/python/fastui/components/__init__.py similarity index 100% rename from demo/server/components/__init__.py rename to python/fastui/components/__init__.py diff --git a/demo/server/components/events.py b/python/fastui/components/events.py similarity index 100% rename from demo/server/components/events.py rename to python/fastui/components/events.py diff --git a/demo/server/components/extra.py b/python/fastui/components/extra.py similarity index 100% rename from demo/server/components/extra.py rename to python/fastui/components/extra.py diff --git a/demo/server/components/table.py b/python/fastui/components/table.py similarity index 100% rename from demo/server/components/table.py rename to python/fastui/components/table.py diff --git a/frontend/fastui/DefaultLoading.tsx b/react/fastui/DefaultLoading.tsx similarity index 100% rename from frontend/fastui/DefaultLoading.tsx rename to react/fastui/DefaultLoading.tsx diff --git a/frontend/fastui/components/FormField.tsx b/react/fastui/components/FormField.tsx similarity index 100% rename from frontend/fastui/components/FormField.tsx rename to react/fastui/components/FormField.tsx diff --git a/frontend/fastui/components/Json.tsx b/react/fastui/components/Json.tsx similarity index 100% rename from frontend/fastui/components/Json.tsx rename to react/fastui/components/Json.tsx diff --git a/frontend/fastui/components/button.tsx b/react/fastui/components/button.tsx similarity index 100% rename from frontend/fastui/components/button.tsx rename to react/fastui/components/button.tsx diff --git a/frontend/fastui/components/display.tsx b/react/fastui/components/display.tsx similarity index 100% rename from frontend/fastui/components/display.tsx rename to react/fastui/components/display.tsx diff --git a/frontend/fastui/components/div.tsx b/react/fastui/components/div.tsx similarity index 100% rename from frontend/fastui/components/div.tsx rename to react/fastui/components/div.tsx diff --git a/frontend/fastui/components/heading.tsx b/react/fastui/components/heading.tsx similarity index 100% rename from frontend/fastui/components/heading.tsx rename to react/fastui/components/heading.tsx diff --git a/frontend/fastui/components/index.tsx b/react/fastui/components/index.tsx similarity index 100% rename from frontend/fastui/components/index.tsx rename to react/fastui/components/index.tsx diff --git a/frontend/fastui/components/link.tsx b/react/fastui/components/link.tsx similarity index 100% rename from frontend/fastui/components/link.tsx rename to react/fastui/components/link.tsx diff --git a/frontend/fastui/components/modal.css b/react/fastui/components/modal.css similarity index 100% rename from frontend/fastui/components/modal.css rename to react/fastui/components/modal.css diff --git a/frontend/fastui/components/modal.tsx b/react/fastui/components/modal.tsx similarity index 100% rename from frontend/fastui/components/modal.tsx rename to react/fastui/components/modal.tsx diff --git a/frontend/fastui/components/table.tsx b/react/fastui/components/table.tsx similarity index 100% rename from frontend/fastui/components/table.tsx rename to react/fastui/components/table.tsx diff --git a/frontend/fastui/components/text.tsx b/react/fastui/components/text.tsx similarity index 100% rename from frontend/fastui/components/text.tsx rename to react/fastui/components/text.tsx diff --git a/frontend/fastui/controller.tsx b/react/fastui/controller.tsx similarity index 100% rename from frontend/fastui/controller.tsx rename to react/fastui/controller.tsx diff --git a/frontend/fastui/display.ts b/react/fastui/display.ts similarity index 100% rename from frontend/fastui/display.ts rename to react/fastui/display.ts diff --git a/frontend/fastui/hooks/className.ts b/react/fastui/hooks/className.ts similarity index 100% rename from frontend/fastui/hooks/className.ts rename to react/fastui/hooks/className.ts diff --git a/frontend/fastui/hooks/customRender.ts b/react/fastui/hooks/customRender.ts similarity index 100% rename from frontend/fastui/hooks/customRender.ts rename to react/fastui/hooks/customRender.ts diff --git a/frontend/fastui/hooks/error.tsx b/react/fastui/hooks/error.tsx similarity index 100% rename from frontend/fastui/hooks/error.tsx rename to react/fastui/hooks/error.tsx diff --git a/frontend/fastui/hooks/event.ts b/react/fastui/hooks/event.ts similarity index 100% rename from frontend/fastui/hooks/event.ts rename to react/fastui/hooks/event.ts diff --git a/frontend/fastui/hooks/locationContext.tsx b/react/fastui/hooks/locationContext.tsx similarity index 100% rename from frontend/fastui/hooks/locationContext.tsx rename to react/fastui/hooks/locationContext.tsx diff --git a/frontend/fastui/index.tsx b/react/fastui/index.tsx similarity index 100% rename from frontend/fastui/index.tsx rename to react/fastui/index.tsx diff --git a/tsconfig.json b/tsconfig.json index 58064ef2..daece3bd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "outDir": "./frontend-dist", + "outDir": "./react-dist", "target": "ES2020", "useDefineForClassFields": true, "lib": ["ES2020", "DOM", "DOM.Iterable"], @@ -20,5 +20,5 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["frontend"] + "include": ["react"] } From e4283c2d2ce645cc9fcbc1119bf9c6a27223422a Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 20:34:31 +0000 Subject: [PATCH 05/10] python setup --- .pre-commit-config.yaml | 24 +++++++++++---- Makefile | 44 ++++++++++++++++++++++++++++ pyproject.toml | 1 + python/fastui/__init__.py | 1 + python/fastui/components/__init__.py | 9 +++--- python/fastui/components/events.py | 3 +- python/fastui/components/extra.py | 1 + python/fastui/components/table.py | 6 ++-- python/requirements/all.txt | 3 ++ python/requirements/lint.in | 2 ++ python/requirements/lint.txt | 15 ++++++++++ python/requirements/pyproject.txt | 31 ++++++++++++++++++++ 12 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 Makefile create mode 100644 python/requirements/all.txt create mode 100644 python/requirements/lint.in create mode 100644 python/requirements/lint.txt create mode 100644 python/requirements/pyproject.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2673841e..aca81a28 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,19 +11,31 @@ repos: - repo: local hooks: - - id: frontend-prettier - name: frontend-prettier + - id: python-format + name: python-format + types_or: [python] + entry: make format + language: system + pass_filenames: false + - id: python-typecheck + name: python-typecheck + types_or: [python] + entry: make typecheck + language: system + pass_filenames: false + - id: react-prettier + name: react-prettier types_or: [javascript, jsx, ts, tsx, css, json, markdown] entry: npm run prettier language: system - - id: frontend-lint - name: frontend-lint + - id: react-lint + name: react-lint types_or: [ts, tsx] entry: npm run lint-fix language: system pass_filenames: false - - id: frontend-typecheck - name: frontend-typecheck + - id: react-typecheck + name: react-typecheck types_or: [ts, tsx] entry: npm run typecheck language: system diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..dcb586a7 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +.DEFAULT_GOAL:=all +paths = python + +.PHONY: install +install: + pip install -U pip pre-commit pip-tools + pip install -r python/requirements/all.txt + pre-commit install + +.PHONY: update-lockfiles +update-lockfiles: + @echo "Updating requirements files using pip-compile" + pip-compile -q --strip-extras -o python/requirements/lint.txt python/requirements/lint.in + pip-compile -q --strip-extras -o python/requirements/pyproject.txt pyproject.toml + pip install --dry-run -r python/requirements/all.txt + +.PHONY: format +format: + ruff check --fix-only $(paths) + ruff format $(paths) + +.PHONY: lint +lint: + ruff check $(paths) + ruff format --check $(paths) + +.PHONY: typecheck +typecheck: + pyright python/fastui + +.PHONY: test +test: + coverage run -m pytest tests + +.PHONY: testcov +testcov: test + coverage html + +.PHONY: dev +dev: + uvicorn demo.server:app --reload --reload-dir demo + +.PHONY: all +all: testcov lint diff --git a/pyproject.toml b/pyproject.toml index 33118b79..c1eda901 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,4 +46,5 @@ Homepage = "https://github.com/samuelcolvin/fastui" line-length = 120 extend-select = ["Q", "RUF100", "UP", "I"] flake8-quotes = {inline-quotes = "single", multiline-quotes = "double"} +format.quote-style="single" target-version = "py38" diff --git a/python/fastui/__init__.py b/python/fastui/__init__.py index a1e2ec06..1670536e 100644 --- a/python/fastui/__init__.py +++ b/python/fastui/__init__.py @@ -1,6 +1,7 @@ __version__ = '0.0.1' from pydantic import RootModel + from .components import AnyComponent diff --git a/python/fastui/components/__init__.py b/python/fastui/components/__init__.py index 122cf0f8..45ab785a 100644 --- a/python/fastui/components/__init__.py +++ b/python/fastui/components/__init__.py @@ -8,10 +8,11 @@ from __future__ import annotations as _annotations import typing + import pydantic -from . import extra, events -from .table import Table, Column, Display +from . import events, extra +from .table import Table if typing.TYPE_CHECKING: import pydantic.fields @@ -32,6 +33,7 @@ class Page(pydantic.BaseModel): """ Similar to `container` in many UI frameworks, this should be a reasonable root component for most pages. """ + children: list[AnyComponent] class_name: extra.ClassName | None = None type: typing.Literal['Page'] = 'Page' @@ -77,6 +79,5 @@ class Modal(pydantic.BaseModel): AnyComponent = typing.Annotated[ - Text | Div | Page | Heading | Row | Col | Button | Modal | Table, - pydantic.Field(discriminator='type') + Text | Div | Page | Heading | Row | Col | Button | Modal | Table, pydantic.Field(discriminator='type') ] diff --git a/python/fastui/components/events.py b/python/fastui/components/events.py index 2efd6fc2..82cf5335 100644 --- a/python/fastui/components/events.py +++ b/python/fastui/components/events.py @@ -1,5 +1,6 @@ from typing import Annotated, Literal -from pydantic import Field, BaseModel + +from pydantic import BaseModel, Field class PageEvent(BaseModel): diff --git a/python/fastui/components/extra.py b/python/fastui/components/extra.py index 693b4a60..cf27a1e9 100644 --- a/python/fastui/components/extra.py +++ b/python/fastui/components/extra.py @@ -1,4 +1,5 @@ from typing import Annotated + from pydantic import Field ClassName = Annotated[str | list[str] | dict[str, bool | None], Field(serialization_alias='className')] diff --git a/python/fastui/components/table.py b/python/fastui/components/table.py index 22758d17..99746e05 100644 --- a/python/fastui/components/table.py +++ b/python/fastui/components/table.py @@ -5,7 +5,7 @@ import pydantic -from . import extra, events +from . import events, extra # TODO allow dataclasses and dicts here too DataModel = typing.TypeVar('DataModel', bound=pydantic.BaseModel) @@ -15,6 +15,7 @@ class Display(StrEnum): """ How to a value. """ + auto = 'auto' # default, same as None below plain = 'plain' datetime = 'datetime' @@ -30,10 +31,11 @@ class Column(pydantic.BaseModel): """ Description of a table column. """ + field: str display: Display | None = None title: str | None = None - on_click: events.Event | None = pydantic.Field(None, serialization_alias='onClick') + on_click: typing.Annotated[events.Event | None, pydantic.Field(serialization_alias='onClick')] = None class_name: extra.ClassName | None = None diff --git a/python/requirements/all.txt b/python/requirements/all.txt new file mode 100644 index 00000000..baff7eec --- /dev/null +++ b/python/requirements/all.txt @@ -0,0 +1,3 @@ +-r ./lint.txt +-r ./pyproject.txt +uvicorn[standard] diff --git a/python/requirements/lint.in b/python/requirements/lint.in new file mode 100644 index 00000000..5d158db7 --- /dev/null +++ b/python/requirements/lint.in @@ -0,0 +1,2 @@ +ruff +pyright diff --git a/python/requirements/lint.txt b/python/requirements/lint.txt new file mode 100644 index 00000000..46f44f48 --- /dev/null +++ b/python/requirements/lint.txt @@ -0,0 +1,15 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --output-file=python/requirements/lint.txt --strip-extras python/requirements/lint.in +# +nodeenv==1.8.0 + # via pyright +pyright==1.1.335 + # via -r python/requirements/lint.in +ruff==0.1.5 + # via -r python/requirements/lint.in + +# The following packages are considered to be unsafe in a requirements file: +# setuptools diff --git a/python/requirements/pyproject.txt b/python/requirements/pyproject.txt new file mode 100644 index 00000000..ab59d0b7 --- /dev/null +++ b/python/requirements/pyproject.txt @@ -0,0 +1,31 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --output-file=python/requirements/pyproject.txt --strip-extras pyproject.toml +# +annotated-types==0.6.0 + # via pydantic +anyio==3.7.1 + # via + # fastapi + # starlette +fastapi==0.104.1 + # via fastui (pyproject.toml) +idna==3.4 + # via anyio +pydantic==2.5.0b1 + # via + # fastapi + # fastui (pyproject.toml) +pydantic-core==2.14.1 + # via pydantic +sniffio==1.3.0 + # via anyio +starlette==0.27.0 + # via fastapi +typing-extensions==4.8.0 + # via + # fastapi + # pydantic + # pydantic-core From eb3d809180bb04bbb563a9f900b7ac45c18917f8 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 20:41:25 +0000 Subject: [PATCH 06/10] add CI --- .github/workflows/ci.yml | 71 ++++++++++++++++++++++++++++++++++++++++ README.md | 5 +++ 2 files changed, 76 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..b587f3e7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,71 @@ +name: CI + +on: + push: + branches: + - main + tags: + - '**' + pull_request: + types: [opened, synchronize] + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - run: pip install -r python/requirements/all.txt + + - uses: pre-commit/action@v3.0.0 + with: + extra_args: --all-files + + check: # This job does nothing and is only used for the branch protection + if: always() + needs: [lint] + runs-on: ubuntu-latest + + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + id: all-green + with: + jobs: ${{ toJSON(needs) }} + + release: + needs: [check] + if: "success() && startsWith(github.ref, 'refs/tags/')" + runs-on: ubuntu-latest + environment: release + + permissions: + id-token: write + + steps: + - uses: actions/checkout@v3 + + - name: set up python + uses: actions/setup-python@v4 + with: + python-version: '3.11' + + - name: install + run: pip install -U build + + - name: check version + id: check-version + uses: samuelcolvin/check-python-version@v4.1 + with: + version_file_path: 'python/fastui/__init__.py' + + - name: build + run: python -m build + + - name: Upload package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/README.md b/README.md index d29303f4..48692e5e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # FastUI +[![CI](https://github.com/samuelcolvin/fastui/workflows/CI/badge.svg?event=push)](https://github.com/samuelcolvin/fastui/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) +[![pypi](https://img.shields.io/pypi/v/fastui.svg)](https://pypi.python.org/pypi/fastui) +[![versions](https://img.shields.io/pypi/pyversions/fastui.svg)](https://github.com/samuelcolvin/fastui) +[![license](https://img.shields.io/github/license/samuelcolvin/fastui.svg)](https://github.com/samuelcolvin/fastui/blob/main/LICENSE) + WIP From 22269432e63fe5bb0c4d48f96fe88ee62d2efaeb Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 20:49:37 +0000 Subject: [PATCH 07/10] adding node and "npm install" to ci --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b587f3e7..4cac0bca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,14 @@ jobs: with: python-version: '3.11' + - uses: actions/setup-node@v3 + with: + node-version: 18 + - run: pip install -r python/requirements/all.txt + - run: npm install + - uses: pre-commit/action@v3.0.0 with: extra_args: --all-files From b4591349ed57b5a0532aaba18cd822fd92979459 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 20:54:35 +0000 Subject: [PATCH 08/10] tweak pre-commit and ci --- .github/workflows/ci.yml | 2 ++ .pre-commit-config.yaml | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4cac0bca..fc8f273d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,8 @@ jobs: - uses: pre-commit/action@v3.0.0 with: extra_args: --all-files + env: + SKIP: no-commit-to-branch check: # This job does nothing and is only used for the branch protection if: always() diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aca81a28..dcedbf43 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,6 @@ repos: hooks: - id: no-commit-to-branch - id: check-yaml - args: ['--unsafe'] - id: check-toml - id: end-of-file-fixer - id: trailing-whitespace From dff86b33e414d62f6a737c6154b8629a974503b2 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 21:01:54 +0000 Subject: [PATCH 09/10] fixing development --- Makefile | 2 +- demo/server.py | 4 ++-- python/fastui/__init__.py | 4 ++-- python/fastui/components/__init__.py | 3 ++- python/fastui/components/table.py | 21 +++------------------ python/fastui/display.py | 17 +++++++++++++++++ python/fastui/{components => }/events.py | 0 7 files changed, 27 insertions(+), 24 deletions(-) create mode 100644 python/fastui/display.py rename python/fastui/{components => }/events.py (100%) diff --git a/Makefile b/Makefile index dcb586a7..c51da711 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ testcov: test .PHONY: dev dev: - uvicorn demo.server:app --reload --reload-dir demo + uvicorn demo.server:app --reload .PHONY: all all: testcov lint diff --git a/demo/server.py b/demo/server.py index 63b7dd1e..adc2595f 100644 --- a/demo/server.py +++ b/demo/server.py @@ -6,7 +6,7 @@ from pydantic import BaseModel, Field from fastui import components as c -from fastui import FastUI +from fastui import FastUI, PageEvent, GoToEvent, Display, AnyComponent app = FastAPI() @@ -52,7 +52,7 @@ def read_foo() -> AnyComponent: ], columns=[ c.Column(field='name', on_click=GoToEvent(url='/api/more/{id}/')), - c.Column(field='dob', display=c.Display.date), + c.Column(field='dob', display=Display.date), c.Column(field='enabled'), ] ) diff --git a/python/fastui/__init__.py b/python/fastui/__init__.py index 1670536e..210b34d4 100644 --- a/python/fastui/__init__.py +++ b/python/fastui/__init__.py @@ -1,9 +1,9 @@ __version__ = '0.0.1' -from pydantic import RootModel +import pydantic from .components import AnyComponent -class FastUI(RootModel): +class FastUI(pydantic.RootModel): root: AnyComponent diff --git a/python/fastui/components/__init__.py b/python/fastui/components/__init__.py index 45ab785a..37b9790b 100644 --- a/python/fastui/components/__init__.py +++ b/python/fastui/components/__init__.py @@ -11,7 +11,8 @@ import pydantic -from . import events, extra +from .. import events +from . import extra from .table import Table if typing.TYPE_CHECKING: diff --git a/python/fastui/components/table.py b/python/fastui/components/table.py index 99746e05..bbb38b5a 100644 --- a/python/fastui/components/table.py +++ b/python/fastui/components/table.py @@ -1,32 +1,17 @@ from __future__ import annotations as _annotations import typing -from enum import StrEnum import pydantic -from . import events, extra +from .. import events +from ..display import Display +from . import extra # TODO allow dataclasses and dicts here too DataModel = typing.TypeVar('DataModel', bound=pydantic.BaseModel) -class Display(StrEnum): - """ - How to a value. - """ - - auto = 'auto' # default, same as None below - plain = 'plain' - datetime = 'datetime' - date = 'date' - duration = 'duration' - as_title = 'as_title' - markdown = 'markdown' - json = 'json' - inline_code = 'inline_code' - - class Column(pydantic.BaseModel): """ Description of a table column. diff --git a/python/fastui/display.py b/python/fastui/display.py new file mode 100644 index 00000000..ff42fdf5 --- /dev/null +++ b/python/fastui/display.py @@ -0,0 +1,17 @@ +from enum import StrEnum + + +class Display(StrEnum): + """ + How to a value. + """ + + auto = 'auto' # default, same as None below + plain = 'plain' + datetime = 'datetime' + date = 'date' + duration = 'duration' + as_title = 'as_title' + markdown = 'markdown' + json = 'json' + inline_code = 'inline_code' diff --git a/python/fastui/components/events.py b/python/fastui/events.py similarity index 100% rename from python/fastui/components/events.py rename to python/fastui/events.py From 831967e399311faede4052ab6b2750af458adaef Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Sun, 12 Nov 2023 21:13:20 +0000 Subject: [PATCH 10/10] update repo name --- README.md | 6 +++--- pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 48692e5e..7efc2f70 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # FastUI -[![CI](https://github.com/samuelcolvin/fastui/workflows/CI/badge.svg?event=push)](https://github.com/samuelcolvin/fastui/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) +[![CI](https://github.com/samuelcolvin/FastUI/workflows/CI/badge.svg?event=push)](https://github.com/samuelcolvin/FastUI/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) [![pypi](https://img.shields.io/pypi/v/fastui.svg)](https://pypi.python.org/pypi/fastui) -[![versions](https://img.shields.io/pypi/pyversions/fastui.svg)](https://github.com/samuelcolvin/fastui) -[![license](https://img.shields.io/github/license/samuelcolvin/fastui.svg)](https://github.com/samuelcolvin/fastui/blob/main/LICENSE) +[![versions](https://img.shields.io/pypi/pyversions/fastui.svg)](https://github.com/samuelcolvin/FastUI) +[![license](https://img.shields.io/github/license/samuelcolvin/FastUI.svg)](https://github.com/samuelcolvin/FastUI/blob/main/LICENSE) WIP diff --git a/pyproject.toml b/pyproject.toml index c1eda901..ee84bed1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,7 @@ dependencies = [ dynamic = ["version"] [project.urls] -Homepage = "https://github.com/samuelcolvin/fastui" +Homepage = "https://github.com/samuelcolvin/FastUI" [tool.ruff]