-
Notifications
You must be signed in to change notification settings - Fork 335
/
Copy path__init__.py
336 lines (277 loc) · 9.82 KB
/
__init__.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
"""
Component definitions.
NOTE: all imports should be "simple" so the namespace of the module is polluted as little as possible.
All CamelCase names in the namespace should be components.
"""
import typing as _t
import pydantic as _p
import typing_extensions as _te
from pydantic_core import core_schema as _core_schema
from .. import class_name as _class_name
from .. import events
from .. import types as _types
from .display import Details, Display
from .forms import (
Form,
FormField,
FormFieldBoolean,
FormFieldFile,
FormFieldInput,
FormFieldRadio,
FormFieldSelect,
FormFieldSelectSearch,
ModelForm,
)
from .tables import Pagination, Table
__all__ = (
# first we include everything from `AnyComponent`
'Text',
'Paragraph',
'PageTitle',
'Div',
'Page',
'Heading',
'Markdown',
'Code',
'Json',
'Button',
'Link',
'LinkList',
'Navbar',
'Modal',
'ServerLoad',
'Image',
'Iframe',
'FireEvent',
'Error',
'Custom',
'Table',
'Pagination',
'Display',
'Details',
'Form',
'FormField',
'ModelForm',
'Footer',
# then `AnyComponent` itself
'AnyComponent',
# then the other form field types which are included in `AnyComponent` via the `FormField` union
'FormFieldBoolean',
'FormFieldFile',
'FormFieldInput',
'FormFieldSelect',
'FormFieldSelectSearch',
'FormFieldRadio',
)
class Text(_p.BaseModel, extra='forbid'):
text: str
type: _t.Literal['Text'] = 'Text'
class Paragraph(_p.BaseModel, extra='forbid'):
text: str
class_name: _class_name.ClassNameField = None
type: _t.Literal['Paragraph'] = 'Paragraph'
class PageTitle(_p.BaseModel, extra='forbid'):
"""
This sets the title of the HTML page via the `document.title` property.
"""
text: str
type: _t.Literal['PageTitle'] = 'PageTitle'
class Div(_p.BaseModel, extra='forbid'):
components: '_t.List[AnyComponent]'
class_name: _class_name.ClassNameField = None
type: _t.Literal['Div'] = 'Div'
class Page(_p.BaseModel, extra='forbid'):
"""
Similar to `container` in many UI frameworks, this should be a reasonable root component for most pages.
"""
components: '_t.List[AnyComponent]'
class_name: _class_name.ClassNameField = None
type: _t.Literal['Page'] = 'Page'
class Heading(_p.BaseModel, extra='forbid'):
text: str
level: _t.Literal[1, 2, 3, 4, 5, 6] = 1
html_id: _t.Union[str, None] = _p.Field(default=None, serialization_alias='htmlId')
class_name: _class_name.ClassNameField = None
type: _t.Literal['Heading'] = 'Heading'
@classmethod
def __get_pydantic_json_schema__(
cls, core_schema: _core_schema.CoreSchema, handler: _p.GetJsonSchemaHandler
) -> _t.Any:
# until https://github.com/pydantic/pydantic/issues/8413 is fixed
json_schema = handler(core_schema)
json_schema['required'].append('level')
return json_schema
# see https://github.com/PrismJS/prism-themes
# and https://cdn.jsdelivr.net/npm/react-syntax-highlighter@15.5.0/dist/esm/styles/prism/index.js
CodeStyle = _te.Annotated[_t.Union[str, None], _p.Field(serialization_alias='codeStyle')]
class Markdown(_p.BaseModel, extra='forbid'):
text: str
code_style: CodeStyle = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['Markdown'] = 'Markdown'
class Code(_p.BaseModel, extra='forbid'):
text: str
language: _t.Union[str, None] = None
code_style: CodeStyle = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['Code'] = 'Code'
class Json(_p.BaseModel, extra='forbid'):
value: _types.JsonData
class_name: _class_name.ClassNameField = None
type: _t.Literal['JSON'] = 'JSON'
class Button(_p.BaseModel, extra='forbid'):
text: str
on_click: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='onClick')
html_type: _t.Union[_t.Literal['button', 'reset', 'submit'], None] = _p.Field(
default=None, serialization_alias='htmlType'
)
named_style: _class_name.NamedStyleField = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['Button'] = 'Button'
class Link(_p.BaseModel, extra='forbid'):
components: '_t.List[AnyComponent]'
on_click: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='onClick')
mode: _t.Union[_t.Literal['navbar', 'footer', 'tabs', 'vertical', 'pagination'], None] = None
active: _t.Union[str, bool, None] = None
locked: _t.Union[bool, None] = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['Link'] = 'Link'
class LinkList(_p.BaseModel, extra='forbid'):
links: _t.List[Link]
mode: _t.Union[_t.Literal['tabs', 'vertical', 'pagination'], None] = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['LinkList'] = 'LinkList'
class Navbar(_p.BaseModel, extra='forbid'):
title: _t.Union[str, None] = None
title_event: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='titleEvent')
links: _t.List[Link] = _p.Field(default=[])
class_name: _class_name.ClassNameField = None
type: _t.Literal['Navbar'] = 'Navbar'
@classmethod
def __get_pydantic_json_schema__(
cls, core_schema: _core_schema.CoreSchema, handler: _p.GetJsonSchemaHandler
) -> _t.Any:
# until https://github.com/pydantic/pydantic/issues/8413 is fixed
json_schema = handler(core_schema)
json_schema.setdefault('required', []).append('links')
return json_schema
class Footer(_p.BaseModel, extra='forbid'):
links: _t.List[Link]
extra_text: _t.Union[str, None] = _p.Field(default=None, serialization_alias='extraText')
class_name: _class_name.ClassNameField = None
type: _t.Literal['Footer'] = 'Footer'
class Modal(_p.BaseModel, extra='forbid'):
title: str
body: '_t.List[AnyComponent]'
footer: '_t.Union[_t.List[AnyComponent], None]' = None
open_trigger: _t.Union[events.PageEvent, None] = _p.Field(default=None, serialization_alias='openTrigger')
open_context: _t.Union[events.ContextType, None] = _p.Field(default=None, serialization_alias='openContext')
class_name: _class_name.ClassNameField = None
type: _t.Literal['Modal'] = 'Modal'
class ServerLoad(_p.BaseModel, extra='forbid'):
"""
A component that will be replaced by the server with the component returned by the given URL.
"""
path: str
load_trigger: _t.Union[events.PageEvent, None] = _p.Field(default=None, serialization_alias='loadTrigger')
components: '_t.Union[_t.List[AnyComponent], None]' = None
sse: _t.Union[bool, None] = None
type: _t.Literal['ServerLoad'] = 'ServerLoad'
class Image(_p.BaseModel, extra='forbid'):
src: str
alt: _t.Union[str, None] = None
width: _t.Union[str, int, None] = None
height: _t.Union[str, int, None] = None
referrer_policy: _t.Union[
_t.Literal[
'no-referrer',
'no-referrer-when-downgrade',
'origin',
'origin-when-cross-origin',
'same-origin',
'strict-origin',
'strict-origin-when-cross-origin',
'unsafe-url',
],
None,
] = _p.Field(None, serialization_alias='referrerPolicy')
loading: _t.Union[_t.Literal['eager', 'lazy'], None] = None
on_click: _t.Union[events.AnyEvent, None] = _p.Field(default=None, serialization_alias='onClick')
class_name: _class_name.ClassNameField = None
type: _t.Literal['Image'] = 'Image'
class Iframe(_p.BaseModel, extra='forbid'):
src: _p.HttpUrl
title: _t.Union[str, None] = None
width: _t.Union[str, int, None] = None
height: _t.Union[str, int, None] = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['Iframe'] = 'Iframe'
class Video(_p.BaseModel, extra='forbid'):
sources: _t.List[_p.AnyUrl]
autoplay: _t.Union[bool, None] = None
controls: _t.Union[bool, None] = None
loop: _t.Union[bool, None] = None
muted: _t.Union[bool, None] = None
poster: _t.Union[_p.AnyUrl, None] = None
width: _t.Union[str, int, None] = None
height: _t.Union[str, int, None] = None
type: _t.Literal['Video'] = 'Video'
class_name: _class_name.ClassNameField = None
class FireEvent(_p.BaseModel, extra='forbid'):
event: events.AnyEvent
message: _t.Union[str, None] = None # defaults to blank
type: _t.Literal['FireEvent'] = 'FireEvent'
class Error(_p.BaseModel, extra='forbid'):
title: str
description: str
status_code: _t.Union[int, None] = _p.Field(None, serialization_alias='statusCode')
class_name: _class_name.ClassNameField = None
type: _t.Literal['Error'] = 'Error'
@classmethod
def __get_pydantic_json_schema__(
cls, core_schema: _core_schema.CoreSchema, handler: _p.GetJsonSchemaHandler
) -> _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'}
return json_schema
class Custom(_p.BaseModel, extra='forbid'):
data: _types.JsonData
sub_type: str = _p.Field(serialization_alias='subType')
library: _t.Union[str, None] = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['Custom'] = 'Custom'
AnyComponent = _te.Annotated[
_t.Union[
Text,
Paragraph,
PageTitle,
Div,
Page,
Heading,
Markdown,
Code,
Json,
Button,
Link,
LinkList,
Navbar,
Footer,
Modal,
ServerLoad,
Image,
Iframe,
Video,
FireEvent,
Error,
Custom,
Table,
Pagination,
Display,
Details,
Form,
FormField,
ModelForm,
],
_p.Field(discriminator='type'),
]