We need to create an Angular component, big.component.ts
, that is NPM installable and also themeable.
The component makes text
contained by its inner html
bigger and uses the accent
theme color for the text.
Approach
Workspace
We will be using the Angular Package Format for the component and module library, so first create a workspace for the library.
ng new big-workspace --create-application=false
cd big-workspace
Library
Then create the big component library.
ng g library big
And open the project in VSCode.
code .
Delete big.component.spec.ts
, big.service.ts
, and big.service.spec.ts
.
rm projects/big/src/lib/big.component.spec.ts
rm projects/big/src/lib/big.service.ts
rm projects/big/src/lib/big.service.spec.ts
And update public-api.ts
.
export * from './lib/big.component';
export * from './lib/big.module';
Styling
Add big.component.scss
.
touch projects/big/src/lib/big.component.scss
Declare the non theme dependent CSS.
:host {
letter-spacing: 0.05em;
text-transform: uppercase;
font-size: 4rem;
font-family: monospace;
}
Add theming/index.scss
.
mkdir projects/big/src/lib/theming
touch projects/big/src/lib/theming/index.scss
Declare the theme dependent CSS
.
@use '@angular/material' as mat;
@mixin big-component-theme($theme) {
$accent: map-get($theme, accent);
fs-big {
color: mat.get-color-from-palette($accent);
}
}
Note that we are naming the theme file for the component index.scss
such that we can import it like this (Which is symmetric with how Angular Material does it in general).
@use "@fireflysemantics/big-component-example/theming" as theme;
Create a big.component.html
.
touch projects/big/src/lib/big.component.html
Put the template in that.
<p>big works!</p>
Change the implementation of big.component.ts
.
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'fs-big',
templateUrl: './big.component.html',
styleUrls: ['./big.component.scss']
})
export class BigComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
Library Test Build
Build the library project.
ng build big
Library Assets Packaging
Create a src/CHANGELOG.md
for our change log notes.
touch projects/big/src/CHANGELOG.md
In order for ng-packagr
to copy our assets into the distribution when building we need to update the assets section of ng-package.json
.
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/big",
"assets": [
"./src/CHANGELOG.md",
"./src/lib/theming/index.scss"
],
"lib": {
"entryFile": "src/public-api.ts"
}
}
After the update run the build command ng build big
again.
Check the dist
folder. It now contains a src
folder with our assets.
sandbox/big-workspace $ tree dist/big/src/
dist/big/src/
├── CHANGELOG.md
└── lib
└── theming
└── index.scss
2 directories, 2 files
We also need to create an exports
block for index.scss
in the libraries package.json
file.
{
"name": "@fireflysemantics/big-component-example",
"version": "0.0.1",
"exports": {
".": {
"sass": "./src/lib/theming/index.scss"
}
},
"peerDependencies": {
"@angular/common": "^13.3.0",
"@angular/core": "^13.3.0"
},
"dependencies": {
"tslib": "^2.3.0"
}
}
This enables clients of our component to import the theme like this:
@use "@fireflysemantics/big-component-example/theming" as theme;
Note that we also changed the package name.
"name": "@fireflysemantics/big-component-example",
Local Testing
Test the component. To do this we will generate a test application.
ng generate application test --style=scss --routing
And add Angular Material.
ng add @angular/material
Add the big.module.ts
BigModule
to the test application app.module.ts
.
import { BigModule} from 'big'
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BigModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Declare the fs-big
component inside app.component.html
.
<div>
<fs-big></fs-big>
</div>
Declare the CSS for the test rendering within app.component.scss
.
div {
margin-top: 10rem;
display: flex;
justify-content: center;
align-items: center;
font-weight: bolder;
}
Within the test project create a themes.scss
file.
@use '@angular/material' as mat;
$my-theme-primary: mat.define-palette(mat.$indigo-palette, 500, 200, 800);
$my-theme-accent: mat.define-palette(mat.$cyan-palette);
$my-theme-warn: mat.define-palette(mat.$deep-orange-palette, A200);
$light-theme: mat.define-light-theme(
$my-theme-primary,
$my-theme-accent,
$my-theme-warn
);
And add the themes to styles.scss
.
/* You can add global styles to this file, and also import other style files */
@use '@angular/material' as mat;
@use '../../big/src/lib/theming' as theme;
// =====================================
// always include only once per project
// =====================================
@include mat.core();
// =====================================
// import our custom themes
// =====================================
@import 'themes';
// =====================================
// Import the big component theme
// =====================================
// =====================================
// Initialize custom component themes
// =====================================
@mixin custom-components-theme($theme) {
@include theme.big-component-theme($theme);
// ====================================
// If we had more component themes
// we could include them here as well.
// ====================================
}
@include mat.core-theme($light-theme);
@include custom-components-theme($light-theme);
We can now run ng serve -o
and we can see that our custom component is rendered with the accent
color applied.
Packaging
Open package.json
for the library and change the name.
"name": "@fireflysemantics/big-component-example",
Workspace Package Scripts
In order to build and publish the project add the following package.json scripts.
Install Global
This will install @jsdevtools/version-bump-prompt
for semantic versioning.
"ig": "npm install -g @jsdevtools/version-bump-prompt",
Build
"b": "ng build big",
Bump Patch
Bump the package patch version.
"bp": "cd projects/big && bump patch",
Publish
We copy over README.md
over the library README.md
that way we only maintain the big-workspace/README.md
file.
"p": "cp README.md ./projects/big/ && npm run bp && npm run b && cd dist/big/ && npm publish"
Publish to NPM
The first time we publish we need to add --access public
so we will run the p script manually the first time.
cp README.md ./projects/big && npm run b && cd dist/big/ && npm publish --access public
Now we can find @fireflysemantics/big-component-example
on NPM.