-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#7670: Simplify creation of isolated widgets (IsolatedComponent
)
#8151
Conversation
"\\.ya?ml$": "yaml-jest-transform", | ||
"\\.txt$": "<rootDir>/src/testUtils/rawJestTransformer.mjs", | ||
// Note: `?param` URLs aren't supported here: https://github.com/jestjs/jest/pull/6282 | ||
// You can only use a mock via `moduleNameMapper` for these. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated these to avoid confusion. See comment/link.
@@ -15,25 +15,22 @@ | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
|
|||
import "primereact/resources/themes/saga-blue/theme.css"; | |||
import "primereact/resources/primereact.min.css"; | |||
import "primeicons/primeicons.css"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just load the stylesheets normally now 🎉
const ShadowRoot = EmotionShadowRoot.div!; | ||
// TODO: Use EmotionShadowRoot["pixiebrix-widget"] to avoid any CSS conflicts. Requires snapshot/test updates |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this in the POC PR, but it affected too many tests. I can try again later.
// Don't inherit the selection color | ||
:host::selection { | ||
background: initial; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A full default stylesheet in a documented CSS file 🎉
|
||
// This cannot be a CSS module or URL because it must live inside the | ||
// shadow DOM and synchronously set the :host element style. | ||
import cssText from "./IsolatedComponent.scss?loadAsText"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the reason why I changed the Jest config
} | ||
|
||
return false; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can find the context in webpack-contrib/mini-css-extract-plugin#1092. In short, webpack injects the stylesheet in the main document, so we need to target and remove it. This is also mentioned in the code below.
whichever website it's rendering on. | ||
To support react-select and any future potential emotion components we used the | ||
emotion variant of the react-shadow library. | ||
*/} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to EmotionShadowRoot
font-weight: 400; | ||
line-height: 1.5; | ||
color: #212529; | ||
letter-spacing: normal; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing lasts longer than quick temporary fixes:
This was resolved by:
I dropped it here because the file is now an actual CSS module so the classes had to change.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #8151 +/- ##
==========================================
- Coverage 73.43% 73.38% -0.05%
==========================================
Files 1317 1315 -2
Lines 40780 40762 -18
Branches 7570 7579 +9
==========================================
- Hits 29947 29915 -32
- Misses 10833 10847 +14 ☔ View full report in Codecov by Sentry. |
style={ | ||
{ | ||
"fontSize": "16px", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🆕 The storybook now works, however the component includes absolute positioning so it's cut. It can be adjusted separately.
<IsolatedComponent | ||
name="PropertyTree" | ||
lazy={async () => | ||
import( | ||
/* webpackChunkName: "isolated/PropertyTree" */ | ||
"./PropertyTree" | ||
) | ||
} | ||
factory={(PropertyTree) => <PropertyTree value={value} />} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the format I ended up with, I think it's compact and readable enough, which is important due to all the restrictions:
name
,isolated/${name}
,"/${name}"
must all match. Unfortunately this cannot use a variable since they're used by webpack. I can add a lint rule though.- the imported package must also appear in the
isolatedComponentList.mjs
file, which is picked up by webpack, by<IsolatedComponent/>
itself for verification, and by ESLint eventually - the lazy/factory attribute names are the best I could come up with. suggestions welcome (one is
React.lazy(LAZY)
and the other one returns the result ofCOMPONENT
inconst COMPONENT = React.lazy(LAZY)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to document some of these requirements all in one place somewhere (e.g. it's not clear just looking at IsolatedComponent.tsx that you'd need to add that component to isolatedComponentList). Either in the docstring directly or in a README that's referenced in the docstring.
If I'm looking to add a new isolated component, what are the steps that need to be taken and out-of-the box behaviors or assumptions that are made?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes definitely it needs some documentation and a lint rule, but:
- the JSDoc includes a full example that is identical every time, where only the name and import path need to be changed, usually
- if it's used incorrectly, either webpack, typescript or the component itself will throw, depending on what part is wrong
I can't think of anything that breaks that isn't already caught but the build.
assumptions that are made
Since "PropertyTree" is now loaded as an isolated component, it needs to import
all the stylesheets it needs, including bootstrap if it needs it (it doesn't in this case). No component should need to use <Stylesheets/>
directly unless it's loading the user's stylesheets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to document some of these requirements all in one place somewhere
I just checked, each prop is already documented and it includes the requirement:
pixiebrix-extension/src/components/IsolatedComponent.tsx
Lines 61 to 70 in 1334a91
/** | |
* It must match the `import()`ed component's filename | |
*/ | |
name: string; | |
/** | |
* It must follow the format `isolated/${name}` specified above | |
* @example () => import(/* webpackChunkName: "isolated/Moon" * /, "@/components/Moon") | |
*/ | |
lazy: LazyFactory<T>; |
Also this:
pixiebrix-extension/src/components/IsolatedComponent.tsx
Lines 108 to 112 in 1334a91
if (!isolatedComponentList.some((url) => url.endsWith("/" + name))) { | |
throw new Error( | |
`Isolated component "${name}" is not listed in isolatedComponentList.mjs. Add it there and restart webpack to create it.`, | |
); | |
} |
IsolatedWidget
)IsolatedWidget
)
"\\.(gif|svg|png)$": "<rootDir>/src/__mocks__/stringMock.js", | ||
|
||
"\\?loadAsUrl$": "<rootDir>/src/__mocks__/stringMock.js", | ||
"\\?loadAsText$": "<rootDir>/src/__mocks__/stringMock.js", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this conflict with the loadAsText
one on line 109 below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that tests and snapshots don't need to be updated, I'm guessing that it's not actually being applied nor needed.
Anyway I think these 4 above should be moved below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just wondered if it's related to the changes to imports in IntegrationConfigEditorModal.test.tsx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sort of. I dropped it from that test file because:
?loadAsText
did not work in that file, as the original comment suggested, so having it there did nothing- this new config made that
import etc?loadAsText
point to thestringMock
file instead of the actual yml file
Since ?loadAsText
cannot "load the import as text" in Jest, it cannot be used if your tests depend on the content of the file.
I cleaned up line 109 as well: 1334a91
No loom links were found in the first post. Please add one there if you'd like to it to appear on Slack. Do not edit this comment manually. |
What does this PR do?
renderWidget
) #8150You can find the implementation details in the POC PR above.
Future work
EmotionShadowRoot
components, some of which might are the reason why this research was necessary (e.g.DocumentView
)<IsolatedComponent>
forDocumentView
,EphemeralFormContent
,CustomFormComponent
#8200Checklist