Is it possible to build an npm module that uses Angular Material and allows the components it defines to be styled by the consuming app\'s custom theme?
As an example, s
Indeed, it is possible. The question just doesn't relate to Angular, it applies to any other framework out there.
Before that, you need to glace over the concept of dependency inversion. Say you are building your apps App1 and App2 and use an npm module lib which contains your reusable component. Your apps are built on top of lib meaning your apps are higher level module and lib is lower level module.
If you consider your lib
is self-contained then ideally, it should perform same be it used in App1
or App2
. But your requirements are - lib should have different behavior (styling in this case) as per the app. It means that you want the higher level module to make some decisions on how the lower level module should behave. So you are inverting dependency and that is dependency inversion principle. Read more about DIP on wikipedia.
Now to achieve DIP, you will need to expose some sort of port/extension from your library and for styling purpose, the simplest way is to expose SCSS mixins. But if you use any build tool like Webpack, rollup or ng-package, then they will always generate compiled distributions. You will have to write some extra node.js scripts to package your source code (SCSS here) along with the compiled code. These scripts will be executed during compilation/bundling step.
At my work, I am having similar requirements. There are some guidelines you should follow:
We have an enterprise level apps. There are total 5 distinct apps and one privately published npm module that provides commons components to all these five apps. But there are some components which need to be styled differently which as I said, first override classes in our apps, and then once it feels generic enough to put into common module, we then put it in next release.