-
Notifications
You must be signed in to change notification settings - Fork 1k
classMap overloading and parameter spreading #5155
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
base: main
Are you sure you want to change the base?
Conversation
🦋 Changeset detectedLatest commit: 4c97750 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
|
Thanks for the PR @JorisAerts! I worry a bit about the complexity and performance implications of making The recursive object walk can be done with object spread. The nested array support is equivalent to const classInfo = Object.fromEntries(classes.flat(Infinity).map((c) => [c, true]));
...${classMap(classInfo)}and I'm concerned that people would use arrays unnecessarily, when they could just put static classes in the attribute next to the |
|
Thanks for the review @justinfagnani! I based the functionality on how Vue.js handles the class attribute. In Vue.js, it's part of the internals, whereas in Lit you have to use classMap. For performance, I extracted the regex to the module's global scope so it doesn't need recompiling every other time. For the recursion, I made one quite simple function that calls itself so it can get warmed up real quick. Your solution with .flat maybe worth looking into to avoid recursion. The reason this function is rather slow, I'd suspect, is possibly heavy DOM manipulation during update(....), because classes get added and removed one by one in for-loops, which causes a DOM manipulation for each class change upon each update. Complex CSS (using computed units like em, lh, ... for example) may require a lot unnecessary recalculation of the styles that way. Next to that, each classMap-instance also holds reference to two separate Sets for calculating updates. I would also look into how performance is measured. When long lists get rendered that use classMap, they may trigger — as stated above — a lot of separate DOM updates. Combine that with inefficient component updates at the user's side and you'll be running a lot of unnecessary logic. If users want to use nested arrays, they now can at their own responsibility, it's not opinionated. That's the flexibility and responsibility I'd put into users' hands. The benefit is that — in a component framework for example — it's easier to compose class-objects and class-arrays using references that are managed elsewhere / in another scope. It enables composition, which was my goal here. |
Fixes #4149
Fixes #3095
Fixes #2153 (while at it...)
This feature is fully backward compatible, the syntax is just extended to allow more cases, just like in other frameworks.
It also adds support for multi-class keys, like "foo bar".
It also supports passing nothing, which will would be the same a passing undefined, null or false. These negative parameters allow developers to pass object references, which may or not be falsy, depending on the context.
GIGO principle; none-string values which are not falsy or nothing, will get .toString()'ed, because just ignoring them would be like eating exceptions. They will also be split, so "[object Whatever]" will be two classes.
For example:
Adding more parameters does not seem to break anything, because this directive can only be used as the single directive inside a class-attribute.
It would always just have one parameter in the past usage.
I haven't changed any documentation, I'm not sure I'm expected to, but I wouldn't mind either. There's a lot more to say about classMap, although I can't see any newly introduced unexpected behaviour.