From 31d6c8bbbad0f98d3607cf1936990682599904fc Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:31:08 +0100 Subject: [PATCH 1/7] Rebuild models if necessary --- .../fastui/components/__init__.py | 24 ++++++++++++++----- src/python-fastui/fastui/components/forms.py | 4 ++-- src/python-fastui/fastui/events.py | 4 +++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/python-fastui/fastui/components/__init__.py b/src/python-fastui/fastui/components/__init__.py index f74fafc2..7ffbb85b 100644 --- a/src/python-fastui/fastui/components/__init__.py +++ b/src/python-fastui/fastui/components/__init__.py @@ -15,6 +15,7 @@ from ..base import BaseModel from .display import Details, Display from .forms import ( + BaseForm, Form, FormField, FormFieldBoolean, @@ -103,7 +104,7 @@ class PageTitle(BaseModel, extra='forbid'): """The type of the component. Always 'PageTitle'.""" -class Div(BaseModel, extra='forbid'): +class Div(BaseModel, defer_build=True, extra='forbid'): """A generic container component.""" components: '_t.List[AnyComponent]' @@ -116,7 +117,7 @@ class Div(BaseModel, extra='forbid'): """The type of the component. Always 'Div'.""" -class Page(BaseModel, extra='forbid'): +class Page(BaseModel, defer_build=True, extra='forbid'): """Similar to `container` in many UI frameworks, this acts as a root component for most pages.""" components: '_t.List[AnyComponent]' @@ -240,7 +241,7 @@ class Button(BaseModel, extra='forbid'): """The type of the component. Always 'Button'.""" -class Link(BaseModel, extra='forbid'): +class Link(BaseModel, defer_build=True, extra='forbid'): """Link component.""" components: '_t.List[AnyComponent]' @@ -328,7 +329,7 @@ class Footer(BaseModel, extra='forbid'): """The type of the component. Always 'Footer'.""" -class Modal(BaseModel, extra='forbid'): +class Modal(BaseModel, defer_build=True, extra='forbid'): """Modal component that displays a modal dialog.""" title: str @@ -353,7 +354,7 @@ class Modal(BaseModel, extra='forbid'): """The type of the component. Always 'Modal'.""" -class ServerLoad(BaseModel, extra='forbid'): +class ServerLoad(BaseModel, defer_build=True, extra='forbid'): """A component that will be replaced by the server with the component returned by the given URL.""" path: str @@ -539,7 +540,7 @@ class Spinner(BaseModel, extra='forbid'): """The type of the component. Always 'Spinner'.""" -class Toast(BaseModel, extra='forbid'): +class Toast(BaseModel, defer_build=True, extra='forbid'): """Toast component that displays a toast message (small temporary message).""" title: str @@ -636,3 +637,14 @@ class Custom(BaseModel, extra='forbid'): """Union of all components. Pydantic discriminator field is set to 'type' to allow for efficient serialization and deserialization of the components.""" + +# Rebuild models: +BaseForm.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +Form.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +ModelForm.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +Div.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +Page.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +Link.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +Modal.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +ServerLoad.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) +Toast.model_rebuild(_types_namespace={'AnyComponent': AnyComponent}) diff --git a/src/python-fastui/fastui/components/forms.py b/src/python-fastui/fastui/components/forms.py index b4f2f2d9..17bcb6f6 100644 --- a/src/python-fastui/fastui/components/forms.py +++ b/src/python-fastui/fastui/components/forms.py @@ -200,7 +200,7 @@ def default_footer(self) -> _te.Self: return self -class Form(BaseForm): +class Form(BaseForm, defer_build=True): """Form component.""" form_fields: _t.List[FormField] @@ -213,7 +213,7 @@ class Form(BaseForm): FormFieldsModel = _t.TypeVar('FormFieldsModel', bound=pydantic.BaseModel) -class ModelForm(BaseForm): +class ModelForm(BaseForm, defer_build=True): """Form component generated from a Pydantic model.""" model: _t.Type[pydantic.BaseModel] = pydantic.Field(exclude=True) diff --git a/src/python-fastui/fastui/events.py b/src/python-fastui/fastui/events.py index 9b5970dd..cb443444 100644 --- a/src/python-fastui/fastui/events.py +++ b/src/python-fastui/fastui/events.py @@ -8,7 +8,7 @@ ContextType = TypeAliasType('ContextType', Dict[str, Union[str, int]]) -class PageEvent(BaseModel): +class PageEvent(BaseModel, defer_build=True): name: str push_path: Union[str, None] = None context: Union[ContextType, None] = None @@ -37,3 +37,5 @@ class AuthEvent(BaseModel): AnyEvent = Annotated[Union[PageEvent, GoToEvent, BackEvent, AuthEvent], Field(discriminator='type')] + +PageEvent.model_rebuild(_types_namespace={'AnyEvent': AnyEvent}) From 3e62956e040828e25120c86da857d762773da2c9 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:59:56 +0100 Subject: [PATCH 2/7] More compat --- .../fastui/components/__init__.py | 9 ++- src/python-fastui/fastui/json_schema.py | 55 ++++++++++++------- src/python-fastui/requirements/pyproject.txt | 9 ++- src/python-fastui/tests/test_components.py | 4 +- src/python-fastui/tests/test_forms.py | 1 - 5 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/python-fastui/fastui/components/__init__.py b/src/python-fastui/fastui/components/__init__.py index 7ffbb85b..8c2188d6 100644 --- a/src/python-fastui/fastui/components/__init__.py +++ b/src/python-fastui/fastui/components/__init__.py @@ -154,7 +154,8 @@ def __get_pydantic_json_schema__( ) -> _t.Any: # until https://github.com/pydantic/pydantic/issues/8413 is fixed json_schema = handler(core_schema) - json_schema['required'].append('level') + schema_def = handler.resolve_ref_schema(json_schema) + schema_def['required'].append('level') return json_schema @@ -309,7 +310,8 @@ def __get_pydantic_json_schema__( ) -> _t.Any: # until https://github.com/pydantic/pydantic/issues/8413 is fixed json_schema = handler(core_schema) - json_schema.setdefault('required', []).extend(['startLinks', 'endLinks']) + schema_def = handler.resolve_ref_schema(json_schema) + schema_def.setdefault('required', []).extend(['startLinks', 'endLinks']) return json_schema @@ -523,7 +525,8 @@ def __get_pydantic_json_schema__( ) -> _t.Any: # add `children` to the schema so it can be used in the client json_schema = handler(core_schema) - json_schema['properties']['children'] = {'tsType': 'ReactNode'} + schema_def = handler.resolve_ref_schema(json_schema) + schema_def['properties']['children'] = {'tsType': 'ReactNode'} return json_schema diff --git a/src/python-fastui/fastui/json_schema.py b/src/python-fastui/fastui/json_schema.py index c822f180..3abd1e14 100644 --- a/src/python-fastui/fastui/json_schema.py +++ b/src/python-fastui/fastui/json_schema.py @@ -160,21 +160,26 @@ def json_schema_obj_to_fields( def json_schema_any_to_fields( schema: JsonSchemaAny, loc: SchemeLocation, title: _t.List[str], required: bool, defs: JsonSchemaDefs ) -> _t.Iterable[FormField]: - schema, required = deference_json_schema(schema, defs, required) - title = title + [schema.get('title') or loc_to_title(loc)] - - if schema_is_field(schema): - yield json_schema_field_to_field(schema, loc, title, required) - elif schema_is_array(schema): - yield from json_schema_array_to_fields(schema, loc, title, required, defs) + dereferenced, required = deference_json_schema(schema, defs, required) + title = title + [schema.get('title', dereferenced.get('title', loc_to_title(loc)))] + description = schema.get('description', dereferenced.get('description')) + + if schema_is_field(dereferenced): + yield json_schema_field_to_field(dereferenced, loc, title, description, required) + elif schema_is_array(dereferenced): + yield from json_schema_array_to_fields(dereferenced, loc, title, description, required, defs) else: - assert schema_is_object(schema), f'Unexpected schema type {schema}' + assert schema_is_object(dereferenced), f'Unexpected schema type {dereferenced}' - yield from json_schema_obj_to_fields(schema, loc, title, defs) + yield from json_schema_obj_to_fields(dereferenced, loc, title, defs) def json_schema_field_to_field( - schema: JsonSchemaField, loc: SchemeLocation, title: _t.List[str], required: bool + schema: JsonSchemaField, + loc: SchemeLocation, + title: _t.List[str], + description: _t.Union[str, None], + required: bool, ) -> FormField: name = loc_to_name(loc) if schema['type'] == 'boolean': @@ -183,10 +188,10 @@ def json_schema_field_to_field( title=title, required=required, initial=schema.get('default'), - description=schema.get('description'), + description=description, mode=schema.get('mode', 'checkbox'), ) - elif field := special_string_field(schema, name, title, required, False): + elif field := special_string_field(schema, name, title, description, required, False): return field else: return FormFieldInput( @@ -206,15 +211,20 @@ def loc_to_title(loc: SchemeLocation) -> str: def json_schema_array_to_fields( - schema: JsonSchemaArray, loc: SchemeLocation, title: _t.List[str], required: bool, defs: JsonSchemaDefs + schema: JsonSchemaArray, + loc: SchemeLocation, + title: _t.List[str], + description: _t.Union[str, None], + required: bool, + defs: JsonSchemaDefs, ) -> _t.Iterable[FormField]: items_schema = schema.get('items') if items_schema: items_schema, required = deference_json_schema(items_schema, defs, required) - for field_name in 'search_url', 'placeholder', 'description': + for field_name in 'search_url', 'placeholder': if value := schema.get(field_name): items_schema[field_name] = value # type: ignore - if field := special_string_field(items_schema, loc_to_name(loc), title, required, True): + if field := special_string_field(items_schema, loc_to_name(loc), title, description, required, True): yield field return @@ -236,7 +246,12 @@ def json_schema_array_to_fields( def special_string_field( - schema: JsonSchemaConcrete, name: str, title: _t.List[str], required: bool, multiple: bool + schema: JsonSchemaConcrete, + name: str, + title: _t.List[str], + description: _t.Union[str, None], + required: bool, + multiple: bool, ) -> _t.Union[FormField, None]: if schema['type'] == 'string': if schema.get('format') == 'binary': @@ -246,7 +261,7 @@ def special_string_field( required=required, multiple=multiple, accept=schema.get('accept'), - description=schema.get('description'), + description=description, ) elif schema.get('format') == 'textarea': return FormFieldTextarea( @@ -257,7 +272,7 @@ def special_string_field( cols=schema.get('cols'), placeholder=schema.get('placeholder'), initial=schema.get('initial'), - description=schema.get('description'), + description=description, autocomplete=schema.get('autocomplete'), ) elif enum := schema.get('enum'): @@ -270,7 +285,7 @@ def special_string_field( multiple=multiple, options=[SelectOption(value=v, label=enum_labels.get(v) or as_title(v)) for v in enum], initial=schema.get('default'), - description=schema.get('description'), + description=description, autocomplete=schema.get('autocomplete'), ) elif search_url := schema.get('search_url'): @@ -282,7 +297,7 @@ def special_string_field( required=required, multiple=multiple, initial=schema.get('initial'), - description=schema.get('description'), + description=description, ) diff --git a/src/python-fastui/requirements/pyproject.txt b/src/python-fastui/requirements/pyproject.txt index 71255820..ad1ed563 100644 --- a/src/python-fastui/requirements/pyproject.txt +++ b/src/python-fastui/requirements/pyproject.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile --constraint=src/python-fastui/requirements/lint.txt --extra=fastapi --output-file=src/python-fastui/requirements/pyproject.txt --strip-extras src/python-fastui/pyproject.toml @@ -18,12 +18,11 @@ idna==3.6 # via # anyio # email-validator -pydantic==2.6.1 +pydantic==2.10.6 # via # fastapi # fastui (src/python-fastui/pyproject.toml) - # pydantic -pydantic-core==2.16.2 +pydantic-core==2.27.2 # via pydantic python-multipart==0.0.7 # via fastui (src/python-fastui/pyproject.toml) @@ -31,7 +30,7 @@ sniffio==1.3.0 # via anyio starlette==0.36.3 # via fastapi -typing-extensions==4.9.0 +typing-extensions==4.12.2 # via # fastapi # pydantic diff --git a/src/python-fastui/tests/test_components.py b/src/python-fastui/tests/test_components.py index 6d3c3d17..053d923b 100644 --- a/src/python-fastui/tests/test_components.py +++ b/src/python-fastui/tests/test_components.py @@ -5,7 +5,7 @@ that's just testing pydantic! """ from fastui import FastUI, components -from pydantic_core import Url +from pydantic import HttpUrl def test_div_text(): @@ -56,7 +56,7 @@ def test_root_model_single(): def test_iframe(): iframe = components.Iframe(src='https://www.example.com', srcdoc='

hello world

', sandbox='allow-scripts') assert iframe.model_dump(by_alias=True, exclude_none=True) == { - 'src': Url('https://www.example.com'), + 'src': HttpUrl('https://www.example.com'), 'type': 'Iframe', 'srcdoc': '

hello world

', 'sandbox': 'allow-scripts', diff --git a/src/python-fastui/tests/test_forms.py b/src/python-fastui/tests/test_forms.py index ceaa7a5d..26f86080 100644 --- a/src/python-fastui/tests/test_forms.py +++ b/src/python-fastui/tests/test_forms.py @@ -485,7 +485,6 @@ class FormSelectMultiple(BaseModel): def test_form_description_leakage(): m = components.ModelForm(model=FormSelectMultiple, submit_url='/foobar/') - assert m.model_dump(by_alias=True, exclude_none=True) == { 'formFields': [ { From 5206aecbaabccbd17825506092c6252223e185f9 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Mon, 4 Aug 2025 09:35:52 +0200 Subject: [PATCH 3/7] Trigger CI From 1b3165785121f7d193d3a2f13ccb15ec762876d5 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:08:55 +0200 Subject: [PATCH 4/7] Remove unecessary defer build --- src/python-fastui/fastui/components/display.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python-fastui/fastui/components/display.py b/src/python-fastui/fastui/components/display.py index fdc64979..deff7a41 100644 --- a/src/python-fastui/fastui/components/display.py +++ b/src/python-fastui/fastui/components/display.py @@ -30,7 +30,7 @@ class DisplayMode(str, enum.Enum): currency = 'currency' -class DisplayBase(BaseModel, ABC, defer_build=True): +class DisplayBase(BaseModel, ABC): """Base class for display components.""" mode: _t.Union[DisplayMode, None] = None From 10be66a4db1dbbabce78f5df7f69360243177228 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:58:09 +0200 Subject: [PATCH 5/7] bump json-schema-to-typescript --- package-lock.json | 389 ++++++++++------------------------------------ package.json | 2 +- 2 files changed, 79 insertions(+), 312 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5cc21c61..6264d682 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.4", "eslint-plugin-simple-import-sort": "^10.0.0", - "json-schema-to-typescript": "^13.1.1", + "json-schema-to-typescript": "^15.0.4", "typescript": "^5.0.2" } }, @@ -38,6 +38,24 @@ "node": ">=0.10.0" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz", + "integrity": "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, "node_modules/@babel/code-frame": { "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", @@ -242,24 +260,6 @@ "node": ">=6.9.0" } }, - "node_modules/@bcherny/json-schema-ref-parser": { - "version": "10.0.5-fork", - "resolved": "https://registry.npmjs.org/@bcherny/json-schema-ref-parser/-/json-schema-ref-parser-10.0.5-fork.tgz", - "integrity": "sha512-E/jKbPoca1tfUPj3iSbitDZTGnq6FUFjkH6L8U2oDwSuwK1WhnnVtCG7oFOTg/DDnyoXbQYUiUiGOibHqaGVnw==", - "dev": true, - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/philsturgeon" - } - }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -830,7 +830,8 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@microsoft/fetch-event-source": { "version": "2.0.1", @@ -1328,16 +1329,6 @@ "@types/ms": "*" } }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, "node_modules/@types/hast": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.3.tgz", @@ -1360,10 +1351,11 @@ "peer": true }, "node_modules/@types/lodash": { - "version": "4.14.202", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", - "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", - "dev": true + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/mdast": { "version": "4.0.3", @@ -1373,12 +1365,6 @@ "@types/unist": "*" } }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, "node_modules/@types/ms": { "version": "0.7.34", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", @@ -1398,12 +1384,6 @@ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "node_modules/@types/prop-types": { "version": "15.7.10", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.10.tgz", @@ -1738,12 +1718,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -2026,12 +2000,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2134,22 +2102,6 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" }, - "node_modules/cli-color": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", - "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.61", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2222,16 +2174,6 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2473,54 +2415,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/esbuild": { "version": "0.19.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.5.tgz", @@ -3026,31 +2920,6 @@ "node": ">=0.10.0" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", - "dev": true - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3273,18 +3142,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -3346,25 +3203,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob-promise": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-4.2.2.tgz", - "integrity": "sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.3" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/ahmadnassri" - }, - "peerDependencies": { - "glob": "^7.1.6" - } - }, "node_modules/globals": { "version": "13.23.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", @@ -3996,12 +3834,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4172,46 +4004,27 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-to-typescript": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.1.1.tgz", - "integrity": "sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==", - "dev": true, - "dependencies": { - "@bcherny/json-schema-ref-parser": "10.0.5-fork", - "@types/json-schema": "^7.0.11", - "@types/lodash": "^4.14.182", - "@types/prettier": "^2.6.1", - "cli-color": "^2.0.2", - "get-stdin": "^8.0.0", - "glob": "^7.1.6", - "glob-promise": "^4.2.2", + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.4.tgz", + "integrity": "sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^11.5.5", + "@types/json-schema": "^7.0.15", + "@types/lodash": "^4.17.7", "is-glob": "^4.0.3", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "mz": "^2.7.0", - "prettier": "^2.6.2" + "minimist": "^1.2.8", + "prettier": "^3.2.5", + "tinyglobby": "^0.2.9" }, "bin": { "json2ts": "dist/src/cli.js" }, "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/json-schema-to-typescript/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=16.0.0" } }, "node_modules/json-schema-traverse": { @@ -4358,15 +4171,6 @@ "node": ">=10" } }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", @@ -4604,22 +4408,6 @@ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -5198,34 +4986,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -5250,12 +5015,6 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6373,35 +6132,49 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", "dev": true, + "license": "MIT", "dependencies": { - "any-promise": "^1.0.0" + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" }, - "engines": { - "node": ">=0.8" + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "dependencies": { - "es5-ext": "~0.10.46", - "next-tick": "1" + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/to-fast-properties": { @@ -6471,12 +6244,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7043,7 +6810,7 @@ }, "src/npm-fastui": { "name": "@pydantic/fastui", - "version": "0.0.22", + "version": "0.0.24", "license": "MIT", "dependencies": { "@microsoft/fetch-event-source": "^2.0.1", @@ -7060,7 +6827,7 @@ }, "src/npm-fastui-bootstrap": { "name": "@pydantic/fastui-bootstrap", - "version": "0.0.22", + "version": "0.0.24", "license": "MIT", "dependencies": { "bootstrap": "^5.3.2", @@ -7070,12 +6837,12 @@ "sass": "^1.69.5" }, "peerDependencies": { - "@pydantic/fastui": "0.0.22" + "@pydantic/fastui": "0.0.24" } }, "src/npm-fastui-prebuilt": { "name": "@pydantic/fastui-prebuilt", - "version": "0.0.22", + "version": "0.0.24", "license": "MIT", "devDependencies": { "@vitejs/plugin-react-swc": "^3.3.2", diff --git a/package.json b/package.json index 6036751c..51901872 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.4", "eslint-plugin-simple-import-sort": "^10.0.0", - "json-schema-to-typescript": "^13.1.1", + "json-schema-to-typescript": "^15.0.4", "typescript": "^5.0.2" }, "dependencies": { From 73bee0ab976daf2ff98e264206a0abd4d0ae1a96 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:58:18 +0200 Subject: [PATCH 6/7] Regenerate models --- src/npm-fastui/src/models.d.ts | 306 ++++++++++++++++++++++++++++----- 1 file changed, 262 insertions(+), 44 deletions(-) diff --git a/src/npm-fastui/src/models.d.ts b/src/npm-fastui/src/models.d.ts index 91fc18ad..1df407b7 100644 --- a/src/npm-fastui/src/models.d.ts +++ b/src/npm-fastui/src/models.d.ts @@ -57,7 +57,6 @@ export type JsonData = [k: string]: JsonData } export type AnyEvent = PageEvent | GoToEvent | BackEvent | AuthEvent -export type NamedStyle = 'primary' | 'secondary' | 'warning' /** * Display mode for a value. */ @@ -72,6 +71,20 @@ export type DisplayMode = | 'json' | 'inline_code' | 'currency' +/** + * Display mode for a value. + */ +export type DisplayMode1 = + | 'auto' + | 'plain' + | 'datetime' + | 'date' + | 'duration' + | 'as_title' + | 'markdown' + | 'json' + | 'inline_code' + | 'currency' export type SelectOptions = SelectOption[] | SelectGroup[] /** @@ -86,7 +99,12 @@ export interface Text { */ export interface Paragraph { text: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Paragraph' } /** @@ -101,7 +119,12 @@ export interface PageTitle { */ export interface Div { components: FastProps[] - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Div' } /** @@ -109,7 +132,12 @@ export interface Div { */ export interface Page { components: FastProps[] - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Page' } /** @@ -119,7 +147,12 @@ export interface Heading { text: string level: 1 | 2 | 3 | 4 | 5 | 6 htmlId?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Heading' } /** @@ -128,7 +161,12 @@ export interface Heading { export interface Markdown { text: string codeStyle?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Markdown' } /** @@ -138,7 +176,12 @@ export interface Code { text: string language?: string codeStyle?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Code' } /** @@ -146,7 +189,12 @@ export interface Code { */ export interface Json { value: JsonData - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'JSON' } /** @@ -154,10 +202,15 @@ export interface Json { */ export interface Button { text: string - onClick?: AnyEvent + onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent htmlType?: 'button' | 'reset' | 'submit' - namedStyle?: NamedStyle - className?: ClassName + namedStyle?: 'primary' | 'secondary' | 'warning' + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Button' } export interface PageEvent { @@ -196,7 +249,12 @@ export interface Link { mode?: 'navbar' | 'footer' | 'tabs' | 'vertical' | 'pagination' active?: string | boolean locked?: boolean - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Link' } /** @@ -205,7 +263,12 @@ export interface Link { export interface LinkList { links: Link[] mode?: 'tabs' | 'vertical' | 'pagination' - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'LinkList' } /** @@ -216,7 +279,12 @@ export interface Navbar { titleEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent startLinks: Link[] endLinks: Link[] - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Navbar' } /** @@ -225,7 +293,12 @@ export interface Navbar { export interface Footer { links: Link[] extraText?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Footer' } /** @@ -235,23 +308,47 @@ export interface Modal { title: string body: FastProps[] footer?: FastProps[] - openTrigger?: PageEvent - openContext?: ContextType - className?: ClassName + openTrigger?: PageEvent1 + openContext?: ContextType1 + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Modal' } +export interface PageEvent1 { + name: string + pushPath?: string + context?: ContextType + clear?: boolean + nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent + type: 'page' +} +export interface ContextType1 { + [k: string]: string | number +} /** * A component that will be replaced by the server with the component returned by the given URL. */ export interface ServerLoad { path: string - loadTrigger?: PageEvent + loadTrigger?: PageEvent2 components?: FastProps[] sse?: boolean sseRetry?: number method?: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE' type: 'ServerLoad' } +export interface PageEvent2 { + name: string + pushPath?: string + context?: ContextType + clear?: boolean + nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent + type: 'page' +} /** * Image container component. */ @@ -270,8 +367,13 @@ export interface Image { | 'strict-origin-when-cross-origin' | 'unsafe-url' loading?: 'eager' | 'lazy' - onClick?: AnyEvent - className?: ClassName + onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Image' } /** @@ -282,7 +384,12 @@ export interface Iframe { title?: string width?: string | number height?: string | number - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } srcdoc?: string sandbox?: string type: 'Iframe' @@ -299,7 +406,12 @@ export interface Video { poster?: string width?: string | number height?: string | number - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Video' } /** @@ -317,7 +429,12 @@ export interface Error { title: string description: string statusCode?: number - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Error' children?: ReactNode } @@ -326,7 +443,12 @@ export interface Error { */ export interface Spinner { text?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Spinner' } /** @@ -336,7 +458,12 @@ export interface Custom { data: JsonData subType: string library?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Custom' } /** @@ -346,7 +473,12 @@ export interface Table { data: DataModel[] columns: DisplayLookup[] noDataMessage?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Table' } export interface DataModel { @@ -370,7 +502,12 @@ export interface Pagination { pageSize: number total: number pageQueryParam?: string - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Pagination' pageCount: number } @@ -378,7 +515,7 @@ export interface Pagination { * Description of how to display a value, either in a table or detail view. */ export interface Display { - mode?: DisplayMode + mode?: DisplayMode1 title?: string onClick?: PageEvent | GoToEvent | BackEvent | AuthEvent value: JsonData @@ -390,7 +527,12 @@ export interface Display { export interface Details { data: DataModel fields: (DisplayLookup | Display)[] - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Details' } /** @@ -404,10 +546,15 @@ export interface Form { method?: 'POST' | 'GOTO' | 'GET' displayMode?: 'default' | 'page' | 'inline' submitOnChange?: boolean - submitTrigger?: PageEvent + submitTrigger?: PageEvent3 loading?: FastProps[] footer?: FastProps[] - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } formFields: ( | FormFieldInput | FormFieldTextarea @@ -418,6 +565,14 @@ export interface Form { )[] type: 'Form' } +export interface PageEvent3 { + name: string + pushPath?: string + context?: ContextType + clear?: boolean + nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent + type: 'page' +} /** * Form field for basic input. */ @@ -429,7 +584,12 @@ export interface FormFieldInput { locked?: boolean description?: string displayMode?: 'default' | 'inline' - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } htmlType?: 'text' | 'date' | 'datetime-local' | 'time' | 'email' | 'url' | 'number' | 'password' | 'hidden' initial?: string | number placeholder?: string @@ -447,7 +607,12 @@ export interface FormFieldTextarea { locked?: boolean description?: string displayMode?: 'default' | 'inline' - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } rows?: number cols?: number initial?: string @@ -466,7 +631,12 @@ export interface FormFieldBoolean { locked?: boolean description?: string displayMode?: 'default' | 'inline' - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } initial?: boolean mode?: 'checkbox' | 'switch' type: 'FormFieldBoolean' @@ -482,7 +652,12 @@ export interface FormFieldFile { locked?: boolean description?: string displayMode?: 'default' | 'inline' - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } multiple?: boolean accept?: string type: 'FormFieldFile' @@ -498,7 +673,12 @@ export interface FormFieldSelect { locked?: boolean description?: string displayMode?: 'default' | 'inline' - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } options: SelectOptions multiple?: boolean initial?: string[] | string @@ -526,14 +706,23 @@ export interface FormFieldSelectSearch { locked?: boolean description?: string displayMode?: 'default' | 'inline' - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } searchUrl: string multiple?: boolean - initial?: SelectOption + initial?: SelectOption1 debounce?: number placeholder?: string type: 'FormFieldSelectSearch' } +export interface SelectOption1 { + value: string + label: string +} /** * Form component generated from a Pydantic model. */ @@ -545,10 +734,15 @@ export interface ModelForm { method?: 'POST' | 'GOTO' | 'GET' displayMode?: 'default' | 'page' | 'inline' submitOnChange?: boolean - submitTrigger?: PageEvent + submitTrigger?: PageEvent4 loading?: FastProps[] footer?: FastProps[] - className?: ClassName + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'ModelForm' formFields: ( | FormFieldInput @@ -559,6 +753,14 @@ export interface ModelForm { | FormFieldSelectSearch )[] } +export interface PageEvent4 { + name: string + pushPath?: string + context?: ContextType + clear?: boolean + nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent + type: 'page' +} /** * Toast component that displays a toast message (small temporary message). */ @@ -575,8 +777,24 @@ export interface Toast { | 'bottom-start' | 'bottom-center' | 'bottom-end' - openTrigger?: PageEvent - openContext?: ContextType - className?: ClassName + openTrigger?: PageEvent5 + openContext?: ContextType2 + className?: + | string + | ClassName[] + | { + [k: string]: boolean + } type: 'Toast' } +export interface PageEvent5 { + name: string + pushPath?: string + context?: ContextType + clear?: boolean + nextEvent?: PageEvent | GoToEvent | BackEvent | AuthEvent + type: 'page' +} +export interface ContextType2 { + [k: string]: string | number +} From 1f1dc11ece541a60f8a1049fa0ad5376d2417898 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:05:52 +0200 Subject: [PATCH 7/7] Add note --- src/python-fastui/fastui/generate_typescript.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/python-fastui/fastui/generate_typescript.py b/src/python-fastui/fastui/generate_typescript.py index 13380662..9654ec72 100644 --- a/src/python-fastui/fastui/generate_typescript.py +++ b/src/python-fastui/fastui/generate_typescript.py @@ -15,6 +15,9 @@ def main(python_object_str: str, typescript_output_file: Path): # pragma: no co json_schema = generate_json_schema(root_model) json_schema_file = Path('fastui-json-schema.json') json_schema_file.write_bytes(to_json(json_schema, indent=2)) + # NOTE: `json-schema-to-typescript` generates ugly schemas + # (https://github.com/bcherny/json-schema-to-typescript/issues/193). + # Note sure what the way forward is. json2ts(json_schema_file, typescript_output_file)