Implement raw HTML elements
This PR adds raw HTML elements under the pynecone.el namespace that can be used in conjunction with class_name and stylesheets to support Tailwind and other custom workflows. (Support for stylesheets is not included in this PR, I’ll make a separate PR for that.)
The following is now possible:
from pynecone import el
def index():
return el.div(
el.div(
el.h1("Welcome to Pynecone!", style={"font_size": "2em"}),
el.div(
"Get started by editing ",
pc.code(filename, style={"font_size": "1em"}),
),
el.a(
"Check out our docs!",
href=docs_url,
style={
"color": "rgb(107,99,246)",
"border": "0.1em solid",
"padding": "0.5em",
"border_radius": "0.5em",
"display": "inline-block",
},
),
style={
"font_size": "2em",
"display": "flex",
"flex_direction": "column",
"align_items": "center",
},
),
style={
"padding_top": "10%",
"display": "flex",
"justify_content": "center",
},
)
This PR contributes the following files under pynecone/el/:
element.py
Subclasses Component in order to remove the Chakra sx prop from the render. sx has been replaced with the raw style prop, meaning when you say something like
el.div(style={"font_size": "1em"})
It is compiled to:
<div style={{fontSize: '1em'}} />
constants.py
This file contains constants that are used in generating base elements:
1. ELEMENTS: A list of all valid HTML elements (including deprecated and obsolete ones) from MDN.
2. ATTR_TO_ELEMENTS: A dict mapping HTML attributes to all the elements that can possess those attributes. (e.g. "autofocus": ["button", "input", ...])
3. PROP_TO_ELEMENTS (derived from ATTR_TO_ELEMENTS): A dict mapping Pynecone props (e.g. auto_focus) to the elements which can possess them.
4. _POSSIBLE_STANDARD_NAMES: Used internally to go from HTML attribute names to their React versions.
5. ELEMENT_TO_PROPS: This is just PROP_TO_ELEMENTS inverted; maps elements to the props that they can legally possess.
generate.py
This is the main compilation script. It's pretty short, so just read the source code. TL;DR, it uses a simple template to generate a subclass of Element for each element in ELEMENT_TO_PROPS, and outputs all the generated code to elements/__init__.py.
elements/__init__.py
Contains all the generated elements. Should not need manual review, just skim if necessary.
Design Decisions
- The Element subclass for the
<del />element is calledDel, but it's used asel.del_sincedel(lowercase) is a reserved keyword. I could have made the subclass nameDel_, but I don't think that makes sense since reserved keywords are case-sensitive andDelworks fine. This way, as a rule of thumb, you can assume that if something in the API resembles a keyword, you just need to append an underscore (with the exception of theclassprop, which is used asclass_name). -
asyncis a reserved keyword; theasync_prop is used instead. - Code for all elements is output to a single generated file (
pynecone/el/elements/__init__.py) rather than multiple files (pynecone/els/elements/a.py,pynecone/els/elements/abbr.py, etc.) because we don't want to manually edit the generated code. The generated file contains a "Do not edit" warning to this effect.
Misc.
All Submissions:
- [x] Have you followed the guidelines stated in CONTRIBUTING.md file?
- [x] Have you checked to ensure there aren't any other open Pull Requests for the desired changed?
Type of change
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [x] This change requires a documentation update
New Feature Submission:
- [ ] Does your submission pass the tests?
- [ ] Have you linted your code locally prior to submission?
Changes To Core Features:
- [x] Have you added an explanation of what your changes do and why you'd like us to include them?
- [ ] Have you written new tests for your core changes, as applicable?
- [ ] Have you successfully ran tests with your changes locally?