├── projects ├── .gitkeep └── angular-material-rail-drawer │ ├── src │ ├── lib │ │ ├── default.config.ts │ │ ├── drawer-rail.module.ts │ │ ├── animations.settings.ts │ │ └── drawer-rail.directive.ts │ ├── public-api.ts │ └── test-setup.ts │ ├── ng-package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.lib.json │ ├── tsconfig.spec.json │ ├── package.json │ ├── tsconfig.json │ ├── jest.config.ts │ ├── .eslintrc.json │ ├── project.json │ └── README.md ├── .eslintignore ├── .prettierrc ├── examples └── material-rail-drawer │ ├── src │ ├── assets │ │ └── .gitkeep │ ├── app │ │ ├── app.component.scss │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.component.spec.ts │ │ └── app.component.html │ ├── favicon.ico │ ├── main.ts │ ├── test-setup.ts │ ├── index.html │ └── styles.scss │ ├── tsconfig.editor.json │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ ├── jest.config.ts │ ├── tsconfig.json │ ├── .eslintrc.json │ └── project.json ├── .vscode └── settings.json ├── .prettierignore ├── jest.preset.js ├── jest.config.ts ├── .whitesource ├── .editorconfig ├── license ├── tsconfig.base.json ├── .gitignore ├── .eslintrc.json ├── .github └── workflows │ └── npmpublish.yml ├── nx.json ├── package.json └── README.md /projects/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enable": false, 3 | } -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | /dist 3 | /coverage 4 | .angular 5 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | padding: 8px 24px 108px 24px; 3 | } 4 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import { getJestProjects } from '@nx/jest'; 2 | 3 | export default { 4 | projects: getJestProjects(), 5 | }; 6 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jordan-Hall/angular-material-rail-drawer-plugin/HEAD/examples/material-rail-drawer/src/favicon.ico -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "checkRunSettings": { 3 | "vulnerableCheckRunConclusionLevel": "failure" 4 | }, 5 | "issueSettings": { 6 | "minSeverityLevel": "LOW" 7 | } 8 | } -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/src/lib/default.config.ts: -------------------------------------------------------------------------------- 1 | export const miniConfig = { 2 | defaultDuration: '100ms', 3 | defaultMinWidth: '60px', 4 | defaultMaxWidth: '200px', 5 | }; 6 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": [ 4 | "src/**/*.ts" 5 | ], 6 | "compilerOptions": { 7 | "types": [ 8 | "jest", 9 | "node" 10 | ] 11 | } 12 | } -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/angular-material-rail-drawer", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false 5 | }, 6 | "angularCompilerOptions": { 7 | "compilationMode": "partial" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | import { AppModule } from './app/app.module'; 3 | 4 | platformBrowserDynamic() 5 | .bootstrapModule(AppModule) 6 | .catch((err) => console.error(err)); 7 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of angular-material-rail-drawer 3 | */ 4 | export * from './lib/default.config'; 5 | export * from './lib/animations.settings'; 6 | export * from './lib/drawer-rail.directive'; 7 | export * from './lib/drawer-rail.module'; 8 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.scss'], 7 | }) 8 | export class AppComponent { 9 | title = 'angular-material-rail-drawer-example'; 10 | } 11 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 2 | globalThis.ngJest = { 3 | testEnvironmentOptions: { 4 | errorOnUnknownElements: true, 5 | errorOnUnknownProperties: true, 6 | }, 7 | }; 8 | import 'jest-preset-angular/setup-jest'; 9 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 2 | globalThis.ngJest = { 3 | testEnvironmentOptions: { 4 | errorOnUnknownElements: true, 5 | errorOnUnknownProperties: true, 6 | }, 7 | }; 8 | import 'jest-preset-angular/setup-jest'; 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts" 9 | ], 10 | "include": [ 11 | "src/**/*.d.ts" 12 | ], 13 | "exclude": [ 14 | "jest.config.ts", 15 | "src/**/*.test.ts", 16 | "src/**/*.spec.ts" 17 | ] 18 | } -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/src/lib/drawer-rail.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { MatSidenavModule } from '@angular/material/sidenav'; 3 | import { MatDrawerRailDirective } from './drawer-rail.directive'; 4 | 5 | @NgModule({ 6 | imports: [MatSidenavModule], 7 | declarations: [MatDrawerRailDirective], 8 | exports: [MatDrawerRailDirective], 9 | }) 10 | export class DrawerRailModule {} 11 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [] 9 | }, 10 | "exclude": [ 11 | "src/**/*.spec.ts", 12 | "src/test-setup.ts", 13 | "jest.config.ts", 14 | "src/**/*.test.ts" 15 | ], 16 | "include": ["src/**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2022", 7 | "types": [ 8 | "jest", 9 | "node" 10 | ] 11 | }, 12 | "files": [ 13 | "src/test-setup.ts" 14 | ], 15 | "include": [ 16 | "jest.config.ts", 17 | "src/**/*.test.ts", 18 | "src/**/*.spec.ts", 19 | "src/**/*.d.ts" 20 | ] 21 | } -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2022", 7 | "types": [ 8 | "jest", 9 | "node" 10 | ] 11 | }, 12 | "files": [ 13 | "src/test-setup.ts" 14 | ], 15 | "include": [ 16 | "jest.config.ts", 17 | "src/**/*.test.ts", 18 | "src/**/*.spec.ts", 19 | "src/**/*.d.ts" 20 | ] 21 | } -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularMaterialRailDrawerExample 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | #Code FREEDOM 2 | 3 | Code Freedom means, do what the fuck you want with the code. Just remember giving back is caring and it helps you in the future. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 7 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 8 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-material-rail-drawer", 3 | "version": "3.0.2", 4 | "homepage": "https://medium.com/@LostDeveloper/angular-material-navigation-drawer-adding-support-mode-rail-mini-variant-behaviour-8f7b107700b3", 5 | "repository": { 6 | "type": "git", 7 | "url": "https://github.com/Jordan-Hall/angular-material-rail-drawer-plugin" 8 | }, 9 | "dependencies": { 10 | "tslib": "^2.4.0" 11 | }, 12 | "peerDependencies": { 13 | "@angular/common": ">=12.0.0 <17.0.0", 14 | "@angular/core": ">=12.0.0 <17.0.0", 15 | "@angular/animations": ">=12.0.0 <17.0.0", 16 | "@angular/cdk": ">=12.0.0 <17.0.0", 17 | "rxjs": ">=6.5.5" 18 | }, 19 | "sideEffects": false 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2022", 12 | "module": "esnext", 13 | "lib": [ 14 | "es2022", 15 | "dom" 16 | ], 17 | "skipLibCheck": true, 18 | "skipDefaultLibCheck": true, 19 | "baseUrl": ".", 20 | "paths": { 21 | "angular-material-rail-drawer": [ 22 | "projects/angular-material-rail-drawer/src/public-api.ts" 23 | ], 24 | } 25 | }, 26 | "exclude": [ 27 | "node_modules", 28 | "tmp" 29 | ] 30 | } -------------------------------------------------------------------------------- /examples/material-rail-drawer/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'material-rail-drawer', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../coverage/examples/material-rail-drawer', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'angular-material-rail-drawer', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../coverage/projects/angular-material-rail-drawer', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | .angular/ 26 | 27 | # IDE - VSCode 28 | .vscode/* 29 | !.vscode/settings.json 30 | !.vscode/tasks.json 31 | !.vscode/launch.json 32 | !.vscode/extensions.json 33 | .history/* 34 | 35 | # misc 36 | /.angular/cache 37 | /.sass-cache 38 | /connect.lock 39 | /coverage 40 | /libpeerconnection.log 41 | npm-debug.log 42 | yarn-error.log 43 | testem.log 44 | /typings 45 | 46 | # System Files 47 | .DS_Store 48 | Thumbs.db 49 | 50 | .angular 51 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.app.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | }, 21 | { 22 | "path": "./tsconfig.editor.json" 23 | } 24 | ], 25 | "extends": "../../tsconfig.base.json", 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } -------------------------------------------------------------------------------- /examples/material-rail-drawer/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "app", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "app", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "lib", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "lib", 21 | "style": "kebab-case" 22 | } 23 | ] 24 | }, 25 | "extends": [ 26 | "plugin:@nx/angular", 27 | "plugin:@angular-eslint/template/process-inline-templates" 28 | ] 29 | }, 30 | { 31 | "files": ["*.html"], 32 | "extends": ["plugin:@nx/angular-template"], 33 | "rules": {} 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { MatIconModule } from '@angular/material/icon'; 4 | import { MatListModule } from '@angular/material/list'; 5 | import { MatSidenavModule } from '@angular/material/sidenav'; 6 | import { MatButtonModule } from '@angular/material/button'; 7 | import { MatToolbarModule } from '@angular/material/toolbar'; 8 | import { DrawerRailModule } from 'angular-material-rail-drawer'; 9 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 10 | 11 | import { AppComponent } from './app.component'; 12 | 13 | @NgModule({ 14 | declarations: [AppComponent], 15 | imports: [ 16 | BrowserModule, 17 | BrowserAnimationsModule, 18 | MatIconModule, 19 | MatListModule, 20 | MatSidenavModule, 21 | DrawerRailModule, 22 | MatToolbarModule, 23 | MatButtonModule, 24 | ], 25 | providers: [], 26 | bootstrap: [AppComponent], 27 | }) 28 | export class AppModule { } 29 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nx/typescript"], 27 | "rules": {} 28 | }, 29 | { 30 | "files": ["*.js", "*.jsx"], 31 | "extends": ["plugin:@nx/javascript"], 32 | "rules": {} 33 | }, 34 | { 35 | "files": ["*.spec.ts", "*.spec.tsx", "*.spec.js", "*.spec.jsx"], 36 | "env": { 37 | "jest": true 38 | }, 39 | "rules": {} 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, waitForAsync } from '@angular/core/testing'; 2 | import { NoopAnimationsModule } from '@angular/platform-browser/animations'; 3 | import { AppComponent } from './app.component'; 4 | import { AppModule } from './app.module'; 5 | 6 | describe('AppComponent', () => { 7 | beforeEach(waitForAsync(() => { 8 | TestBed.configureTestingModule({ 9 | imports: [AppModule, NoopAnimationsModule], 10 | }).compileComponents(); 11 | })); 12 | 13 | it('should create the app', () => { 14 | const fixture = TestBed.createComponent(AppComponent); 15 | const app = fixture.componentInstance; 16 | expect(app).toBeTruthy(); 17 | }); 18 | 19 | it(`should have as title 'angular-material-rail-drawer-example'`, () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | const app = fixture.componentInstance; 22 | expect(app.title).toEqual('angular-material-rail-drawer-example'); 23 | }); 24 | 25 | it('should render title', () => { 26 | const fixture = TestBed.createComponent(AppComponent); 27 | fixture.detectChanges(); 28 | const compiled = fixture.nativeElement; 29 | expect(compiled.querySelector('.container p').textContent).toContain( 30 | 'Since 2016, the Angular community has been shouting out' 31 | ); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | on: 3 | release: 4 | types: [created] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: actions/setup-node@v1 11 | with: 12 | node-version: 12 13 | - run: npm ci 14 | - run: npm run build angular-material-rail-drawer-example 15 | - run: npm run build angular-material-rail-drawer 16 | 17 | publish-npm: 18 | needs: build 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v2 22 | - uses: actions/setup-node@v1 23 | with: 24 | node-version: 12 25 | registry-url: https://registry.npmjs.org/ 26 | - run: npm ci 27 | - run: cd dist\angular-material-rail-drawer 28 | - run: npm publish 29 | env: 30 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 31 | 32 | publish-gpr: 33 | needs: build 34 | runs-on: ubuntu-latest 35 | steps: 36 | - uses: actions/checkout@v2 37 | - uses: actions/setup-node@v1 38 | with: 39 | node-version: 12 40 | registry-url: https://npm.pkg.github.com/ 41 | - run: npm ci 42 | - run: cd dist\angular-material-rail-drawer 43 | - run: npm publish 44 | env: 45 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 46 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasksRunnerOptions": { 3 | "default": { 4 | "runner": "nx/tasks-runners/default", 5 | "options": { 6 | "cacheableOperations": ["build", "lint", "test", "e2e"] 7 | } 8 | } 9 | }, 10 | "targetDefaults": { 11 | "build": { 12 | "dependsOn": ["^build"], 13 | "inputs": ["production", "^production"] 14 | }, 15 | "test": { 16 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"] 17 | }, 18 | "lint": { 19 | "inputs": [ 20 | "default", 21 | "{workspaceRoot}/.eslintrc.json", 22 | "{workspaceRoot}/.eslintignore" 23 | ] 24 | } 25 | }, 26 | "workspaceLayout": { 27 | "appsDir": "examples", 28 | "libsDir": "projects" 29 | }, 30 | "namedInputs": { 31 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 32 | "sharedGlobals": [], 33 | "production": [ 34 | "default", 35 | "!{projectRoot}/**/*.spec.[jt]s", 36 | "!{projectRoot}/tsconfig.spec.json", 37 | "!{projectRoot}/.eslintrc.json", 38 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", 39 | "!{projectRoot}/jest.config.[jt]s" 40 | ] 41 | }, 42 | "extends": "nx/presets/npm.json", 43 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 44 | "generators": { 45 | "@nx/angular:application": { 46 | "style": "css", 47 | "linter": "eslint", 48 | "unitTestRunner": "jest", 49 | "e2eTestRunner": "none" 50 | }, 51 | "@nx/angular:library": { 52 | "linter": "eslint", 53 | "unitTestRunner": "jest" 54 | }, 55 | "@nx/angular:component": { 56 | "style": "css" 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/src/lib/animations.settings.ts: -------------------------------------------------------------------------------- 1 | import { 2 | group, 3 | query, 4 | animateChild, 5 | animate, 6 | style, 7 | AnimationStyleMetadata, 8 | AnimationGroupMetadata, 9 | } from '@angular/animations'; 10 | import { miniConfig } from './default.config'; 11 | 12 | export function sidebarClose( 13 | minWidth: string = miniConfig.defaultMinWidth 14 | ): AnimationStyleMetadata { 15 | return style({ 16 | width: minWidth, 17 | visibility: 'visible', 18 | transform: 'none', 19 | overflow: 'hidden', 20 | }); 21 | } 22 | 23 | export function sidebarOpen( 24 | maxWidth: string = miniConfig.defaultMaxWidth 25 | ): AnimationStyleMetadata { 26 | return style({ 27 | width: maxWidth, 28 | visibility: 'visible', 29 | }); 30 | } 31 | 32 | export function sidebarAnimationOpenGroup( 33 | animationDuration: string = miniConfig.defaultDuration, 34 | maxWidth: string = miniConfig.defaultMaxWidth 35 | ): AnimationGroupMetadata { 36 | return group([ 37 | query('@iconAnimation', animateChild(), { optional: true }), 38 | query('@labelAnimation', animateChild(), { optional: true }), 39 | animate(`${animationDuration} ease-in-out`, sidebarOpen(maxWidth)), 40 | ]); 41 | } 42 | 43 | export function sidebarAnimationCloseGroup( 44 | animationDuration: string = miniConfig.defaultDuration, 45 | minWidth: string = miniConfig.defaultMinWidth 46 | ): AnimationGroupMetadata { 47 | return group([ 48 | query('@iconAnimation', animateChild(), { optional: true }), 49 | query('@labelAnimation', animateChild(), { optional: true }), 50 | animate(`${animationDuration} ease-in-out`, sidebarClose(minWidth)), 51 | ]); 52 | } 53 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-material-rail-drawer", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "projects/angular-material-rail-drawer/src", 5 | "prefix": "lib", 6 | "tags": [], 7 | "projectType": "library", 8 | "targets": { 9 | "build": { 10 | "executor": "@nx/angular:package", 11 | "outputs": ["{workspaceRoot}/dist/{projectRoot}"], 12 | "options": { 13 | "project": "projects/angular-material-rail-drawer/ng-package.json" 14 | }, 15 | "configurations": { 16 | "production": { 17 | "tsConfig": "projects/angular-material-rail-drawer/tsconfig.lib.prod.json" 18 | }, 19 | "development": { 20 | "tsConfig": "projects/angular-material-rail-drawer/tsconfig.lib.json" 21 | } 22 | }, 23 | "defaultConfiguration": "production" 24 | }, 25 | "test": { 26 | "executor": "@nx/jest:jest", 27 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 28 | "options": { 29 | "jestConfig": "projects/angular-material-rail-drawer/jest.config.ts", 30 | "passWithNoTests": true 31 | }, 32 | "configurations": { 33 | "ci": { 34 | "ci": true, 35 | "codeCoverage": true 36 | } 37 | } 38 | }, 39 | "lint": { 40 | "executor": "@nx/linter:eslint", 41 | "outputs": ["{options.outputFile}"], 42 | "options": { 43 | "lintFilePatterns": [ 44 | "projects/angular-material-rail-drawer/**/*.ts", 45 | "projects/angular-material-rail-drawer/**/*.html" 46 | ] 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/styles.scss: -------------------------------------------------------------------------------- 1 | @use '@angular/material' as mat; 2 | // Plus imports for other components in your app. 3 | 4 | // Include the common styles for Angular Material. We include this here so that you only 5 | // have to load a single css file for Angular Material in your app. 6 | // Be sure that you only ever include this mixin once! 7 | @include mat.core(); 8 | 9 | // Define the palettes for your theme using the Material Design palettes available in palette.scss 10 | // (imported above). For each palette, you can optionally specify a default, lighter, and darker 11 | // hue. Available color palettes: https://material.io/design/color/ 12 | $candy-app-primary: mat.define-palette(mat.$indigo-palette); 13 | $candy-app-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400); 14 | 15 | // The warn palette is optional (defaults to red). 16 | $candy-app-warn: mat.define-palette(mat.$red-palette); 17 | 18 | // Create the theme object (a Sass map containing all of the palettes). 19 | $candy-app-theme: mat.define-light-theme( 20 | ( 21 | color: ( 22 | primary: $candy-app-primary, 23 | accent: $candy-app-accent, 24 | warn: $candy-app-warn, 25 | ), 26 | ) 27 | ); 28 | 29 | // Include theme styles for core and each component used in your app. 30 | // Alternatively, you can import and @include the theme mixins for each component that you are using. 31 | @include mat.all-component-themes($candy-app-theme); 32 | 33 | body { 34 | margin: 0; 35 | height: 100vh; 36 | font-family: Roboto, Arial, sans-serif; 37 | font-size: 16px; 38 | color: #292a1d; 39 | } 40 | a { 41 | text-decoration-color: mat.get-color-from-palette($candy-app-primary); 42 | color: mat.get-color-from-palette($candy-app-primary); 43 | } 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-material-rail-drawer-plugin", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "nx", 6 | "start": "nx serve", 7 | "build": "nx build", 8 | "test": "nx test", 9 | "lint": "nx lint", 10 | "nx": "nx" 11 | }, 12 | "author": { 13 | "name": "Jordan Hall", 14 | "email": "Jordan@libertyware.co.uk" 15 | }, 16 | "homepage": "https://medium.com/@LostDeveloper/angular-material-navigation-drawer-adding-support-mode-rail-mini-variant-behaviour-8f7b107700b3", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/Jordan-Hall/angular-material-rail-drawer-plugin" 20 | }, 21 | "private": true, 22 | "workspaces": [ 23 | "projects/*" 24 | ], 25 | "dependencies": { 26 | "@angular/animations": "~16.0.0", 27 | "@angular/cdk": "~16.1.0", 28 | "@angular/common": "~16.0.0", 29 | "@angular/compiler": "~16.0.0", 30 | "@angular/core": "~16.0.0", 31 | "@angular/forms": "~16.0.0", 32 | "@angular/material": "~16.1.0", 33 | "@angular/platform-browser": "~16.0.0", 34 | "@angular/platform-browser-dynamic": "~16.0.0", 35 | "@angular/router": "~16.0.0", 36 | "rxjs": "~7.8.0", 37 | "tslib": "^2.3.0", 38 | "zone.js": "~0.13.0" 39 | }, 40 | "devDependencies": { 41 | "@angular-devkit/build-angular": "~16.0.0", 42 | "@angular-devkit/core": "~16.0.0", 43 | "@angular-devkit/schematics": "~16.0.0", 44 | "@angular-eslint/eslint-plugin": "~16.0.0", 45 | "@angular-eslint/eslint-plugin-template": "~16.0.0", 46 | "@angular-eslint/template-parser": "~16.0.0", 47 | "@angular/cli": "~16.0.0", 48 | "@angular/compiler-cli": "~16.0.0", 49 | "@angular/language-service": "~16.0.0", 50 | "@angular/material": "^16.1.0", 51 | "@nrwl/angular": "^16.3.2", 52 | "@nx/cypress": "16.3.2", 53 | "@nx/eslint-plugin": "16.3.2", 54 | "@nx/jest": "16.3.2", 55 | "@nx/js": "16.3.2", 56 | "@nx/linter": "16.3.2", 57 | "@nx/web": "16.3.2", 58 | "@schematics/angular": "~16.0.0", 59 | "@types/jest": "^29.4.0", 60 | "@types/node": "16.11.7", 61 | "@typescript-eslint/eslint-plugin": "^5.58.0", 62 | "@typescript-eslint/parser": "^5.58.0", 63 | "cypress": "^12.11.0", 64 | "eslint": "~8.15.0", 65 | "eslint-config-prettier": "8.1.0", 66 | "eslint-plugin-cypress": "^2.10.3", 67 | "jest": "^29.4.1", 68 | "jest-environment-jsdom": "^29.4.1", 69 | "jest-preset-angular": "~13.1.0", 70 | "ng-packagr": "~16.0.0", 71 | "nx": "16.3.2", 72 | "postcss": "^8.4.5", 73 | "postcss-import": "~14.1.0", 74 | "postcss-preset-env": "~7.5.0", 75 | "postcss-url": "~10.1.3", 76 | "prettier": "^2.6.2", 77 | "ts-jest": "^29.1.0", 78 | "ts-node": "10.9.1", 79 | "typescript": "~5.0.2" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ DEPRECATION NOTICE ⚠️ 2 | 3 | **Package Name:** [angular-material-rail-drawer](https://npmjs.com/package/angular-material-rail-drawer) 4 | 5 | --- 6 | 7 | ### 🚫 Reasons for Discontinuation: 8 | 9 | 1. **Legacy Support Only:** This package is designed to work only with Material Legacy (pre-version 17). 10 | 2. **No Support for Angular V17:** There are little to no plans to support Angular V17. The new syntax of Angular V17 is not favored, and it's believed that the changes are detrimental to the framework. 11 | 12 | --- 13 | 14 | ### 📣 Personal Note: 15 | 16 | I personally dislike the new syntax introduced in Angular V17. I believe the direction Angular is taking with this version is not in the best interest of the framework. As a result, I have decided not to continue supporting or maintaining this package. 17 | 18 | --- 19 | 20 | ### 📌 Recommendations: 21 | 22 | - If you are using an older version of Angular (pre-version 17), you may continue using this package. However, be aware that no further updates or support will be provided. 23 | - For projects using Angular V17 and above, it's recommended to look for alternative packages or solutions. 24 | 25 | --- 26 | 27 | # Angular Material Rail Drawer Plugin 28 | 29 | Angular Material Navigation drawer — Adding support mode = “Rail” (mini variant behaviour) 30 | 31 | Since 2016, the Angular community has been shouting out of a mini variant for material design. 32 | 33 | ## How to install 34 | 35 | NPM: 36 | `npm i angular-material-rail-drawer` 37 | Yarn: 38 | `yarn add angular-material-rail-drawer` 39 | 40 | ## How to use 41 | 42 | Read example for more information 43 | 44 | module.ts 45 | `import { DrawerRailModule } from 'angular-material-rail-drawer';` 46 | 47 | component.html 48 | `` 49 | 50 | If `"strictTemplates": true` is activated in _tsconfig.json_, overwriting mode is not possible. In this case you can use the following selector: 51 | 52 | component.html 53 | `` 54 | 55 | This extension adds on an existing `mode` the Material documentation remains the same. 56 | 57 | ## Extra API for rail variant 58 | 59 | On top of all the standard Drawer API from google https://material.angular.io/components/sidenav/api. I've added 4 extra API so you have more control over the animation and size. 60 | 61 | | Input | description | default | 62 | | -------------- | :------------------------------------: | :--------------------: | 63 | | openAnimation | Angular Animation settings for opening | sidebarOpen(maxWidth) | 64 | | closeAnimation | Angular Animation settings for closing | sidebarClose(minWidth) | 65 | | closeWidth | min width (small view) | "60px" | 66 | | expandedWidth | max width for the expanded view | "200px" | 67 | 68 | extra note the default animation time is set to 100ms 69 | 70 | _Notes:_ 71 | Angular material open state 72 | 73 | `Close === mini` & `Opened === expanded` 74 | 75 | ## Useful links 76 | 77 | Blog post: 78 | https://medium.com/@LostDeveloper/angular-material-navigation-drawer-adding-support-mode-rail-mini-variant-behaviour-8f7b107700b3 79 | 80 | Angular material mini variant github issue: 81 | https://github.com/angular/components/issues/1728 82 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ DEPRECATION NOTICE ⚠️ 2 | 3 | **Package Name:** [angular-material-rail-drawer](https://npmjs.com/package/angular-material-rail-drawer) 4 | 5 | --- 6 | 7 | ### 🚫 Reasons for Discontinuation: 8 | 9 | 1. **Legacy Support Only:** This package is designed to work only with Material Legacy (pre-version 17). 10 | 2. **No Support for Angular V17:** There are little to no plans to support Angular V17. The new syntax of Angular V17 is not favored, and it's believed that the changes are detrimental to the framework. 11 | 12 | --- 13 | 14 | ### 📣 Personal Note: 15 | 16 | I personally dislike the new syntax introduced in Angular V17. I believe the direction Angular is taking with this version is not in the best interest of the framework. As a result, I have decided not to continue supporting or maintaining this package. 17 | 18 | --- 19 | 20 | ### 📌 Recommendations: 21 | 22 | - If you are using an older version of Angular (pre-version 17), you may continue using this package. However, be aware that no further updates or support will be provided. 23 | - For projects using Angular V17 and above, it's recommended to look for alternative packages or solutions. 24 | 25 | --- 26 | 27 | # Angular Material Rail Drawer Plugin 28 | 29 | Angular Material Navigation drawer — Adding support mode = “Rail” (mini variant behaviour) 30 | 31 | Since 2016, the Angular community has been shouting out of a mini variant for material design. 32 | 33 | ## How to install 34 | 35 | NPM: 36 | `npm i angular-material-rail-drawer` 37 | Yarn: 38 | `yarn add angular-material-rail-drawer` 39 | 40 | ## How to use 41 | 42 | Read example for more information 43 | 44 | module.ts 45 | `import { DrawerRailModule } from 'angular-material-rail-drawer';` 46 | 47 | component.html 48 | `` 49 | 50 | If `"strictTemplates": true` is activated in _tsconfig.json_, overwriting mode is not possible. In this case you can use the following selector: 51 | 52 | component.html 53 | `` 54 | 55 | This extension adds on an existing `mode` the Material documentation remains the same. 56 | 57 | ## Extra API for rail variant 58 | 59 | On top of all the standard Drawer API from google https://material.angular.io/components/sidenav/api. I've added 4 extra API so you have more control over the animation and size. 60 | 61 | | Input | description | default | 62 | | -------------- | :------------------------------------: | :--------------------: | 63 | | openAnimation | Angular Animation settings for opening | sidebarOpen(maxWidth) | 64 | | closeAnimation | Angular Animation settings for closing | sidebarClose(minWidth) | 65 | | closeWidth | min width (small view) | "60px" | 66 | | expandedWidth | max width for the expanded view | "200px" | 67 | 68 | extra note the default animation time is set to 100ms 69 | 70 | _Notes:_ 71 | Angular material open state 72 | 73 | `Close === mini` & `Opened === expanded` 74 | 75 | ## Useful links 76 | 77 | Blog post: 78 | https://medium.com/@LostDeveloper/angular-material-navigation-drawer-adding-support-mode-rail-mini-variant-behaviour-8f7b107700b3 79 | 80 | Angular material mini variant github issue: 81 | https://github.com/angular/components/issues/1728 82 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "material-rail-drawer", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "prefix": "app", 6 | "sourceRoot": "examples/material-rail-drawer/src", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@angular-devkit/build-angular:browser", 11 | "outputs": ["{options.outputPath}"], 12 | "options": { 13 | "outputPath": "dist/angular-material-rail-drawer-example", 14 | "index": "examples/material-rail-drawer/src/index.html", 15 | "main": "examples/material-rail-drawer/src/main.ts", 16 | "polyfills": ["zone.js"], 17 | "tsConfig": "examples/material-rail-drawer/tsconfig.app.json", 18 | "assets": [ 19 | "examples/material-rail-drawer/src/favicon.ico", 20 | "examples/material-rail-drawer/src/assets" 21 | ], 22 | "styles": ["examples/material-rail-drawer/src/styles.scss"], 23 | "scripts": [] 24 | }, 25 | "configurations": { 26 | "production": { 27 | "budgets": [ 28 | { 29 | "type": "initial", 30 | "maximumWarning": "500kb", 31 | "maximumError": "1mb" 32 | }, 33 | { 34 | "type": "anyComponentStyle", 35 | "maximumWarning": "2kb", 36 | "maximumError": "4kb" 37 | } 38 | ], 39 | "outputHashing": "all" 40 | }, 41 | "development": { 42 | "buildOptimizer": false, 43 | "optimization": false, 44 | "vendorChunk": true, 45 | "extractLicenses": false, 46 | "sourceMap": true, 47 | "namedChunks": true 48 | } 49 | }, 50 | "defaultConfiguration": "production" 51 | }, 52 | "serve": { 53 | "executor": "@angular-devkit/build-angular:dev-server", 54 | "configurations": { 55 | "production": { 56 | "browserTarget": "material-rail-drawer:build:production" 57 | }, 58 | "development": { 59 | "browserTarget": "material-rail-drawer:build:development" 60 | } 61 | }, 62 | "defaultConfiguration": "development" 63 | }, 64 | "extract-i18n": { 65 | "executor": "@angular-devkit/build-angular:extract-i18n", 66 | "options": { 67 | "browserTarget": "material-rail-drawer:build" 68 | } 69 | }, 70 | "lint": { 71 | "executor": "@nx/linter:eslint", 72 | "outputs": ["{options.outputFile}"], 73 | "options": { 74 | "lintFilePatterns": [ 75 | "examples/material-rail-drawer/**/*.ts", 76 | "examples/material-rail-drawer/**/*.html" 77 | ] 78 | } 79 | }, 80 | "test": { 81 | "executor": "@nx/jest:jest", 82 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 83 | "options": { 84 | "jestConfig": "examples/material-rail-drawer/jest.config.ts", 85 | "passWithNoTests": true 86 | }, 87 | "configurations": { 88 | "ci": { 89 | "ci": true, 90 | "codeCoverage": true 91 | } 92 | } 93 | }, 94 | "serve-static": { 95 | "executor": "@nx/web:file-server", 96 | "options": { 97 | "buildTarget": "material-rail-drawer:build" 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /projects/angular-material-rail-drawer/src/lib/drawer-rail.directive.ts: -------------------------------------------------------------------------------- 1 | import { 2 | forwardRef, 3 | Inject, 4 | Directive, 5 | ElementRef, 6 | OnInit, 7 | OnDestroy, 8 | Host, 9 | Self, 10 | Optional, 11 | Renderer2, 12 | Input, 13 | AfterViewInit, 14 | } from '@angular/core'; 15 | import { AnimationMetadata, AnimationBuilder } from '@angular/animations'; 16 | 17 | import { 18 | MatSidenav, 19 | MatDrawer, 20 | MatSidenavContainer, 21 | MatDrawerContainer, 22 | } from '@angular/material/sidenav'; 23 | 24 | import { Subject } from 'rxjs'; 25 | import { takeUntil } from 'rxjs/operators'; 26 | 27 | import { miniConfig } from './default.config'; 28 | import { 29 | sidebarAnimationCloseGroup, 30 | sidebarAnimationOpenGroup, 31 | } from './animations.settings'; 32 | import { Directionality } from '@angular/cdk/bidi'; 33 | 34 | @Directive({ 35 | // eslint-disable-next-line @angular-eslint/directive-selector 36 | selector: 'mat-sidenav[mode="rail"], mat-drawer[mode="rail"], mat-sidenav[rail-mode], mat-drawer[rail-mode]', 37 | // eslint-disable-next-line @angular-eslint/no-host-metadata-property 38 | host: { 39 | '[class.mat-drawer-side]': 'true', 40 | }, 41 | }) 42 | export class MatDrawerRailDirective 43 | implements OnInit, OnDestroy, AfterViewInit 44 | { 45 | public onDestory: Subject = new Subject(); 46 | 47 | private drawer: MatSidenav | MatDrawer; 48 | private container: MatSidenavContainer | MatDrawerContainer; 49 | 50 | private containerContent?: HTMLElement; 51 | 52 | @Input() 53 | public openAnimation?: AnimationMetadata | AnimationMetadata[]; 54 | 55 | @Input() 56 | public closeAnimation?: AnimationMetadata | AnimationMetadata[]; 57 | 58 | @Input() 59 | public closeWidth: string = miniConfig.defaultMinWidth; 60 | 61 | @Input() 62 | public expandedWidth: string = miniConfig.defaultMaxWidth; 63 | 64 | constructor( 65 | private builder: AnimationBuilder, 66 | private el: ElementRef, 67 | private renderer2: Renderer2, 68 | @Host() @Self() @Optional() sidenav: MatSidenav, 69 | @Host() @Self() @Optional() drawer: MatDrawer, 70 | @Inject(forwardRef(() => MatSidenavContainer)) 71 | @Optional() 72 | matSideNavContainer: MatSidenavContainer, 73 | @Inject(forwardRef(() => MatDrawerContainer)) 74 | @Optional() 75 | matDrawerContainer: MatDrawerContainer, 76 | // tslint:disable-next-line: variable-name 77 | @Optional() private _dir: Directionality 78 | ) { 79 | this.container = matSideNavContainer || matDrawerContainer; 80 | this.drawer = sidenav || drawer; 81 | this.container.hasBackdrop = false; 82 | this.drawer.autoFocus = false; 83 | } 84 | 85 | public ngOnInit(): void { 86 | this.closeAnimation = 87 | this.closeAnimation || 88 | sidebarAnimationCloseGroup(miniConfig.defaultDuration, this.closeWidth); 89 | this.openAnimation = 90 | this.openAnimation || 91 | sidebarAnimationOpenGroup(miniConfig.defaultDuration, this.expandedWidth); 92 | this.renderer2.setStyle( 93 | this.el.nativeElement.querySelector('.mat-drawer-inner-container'), 94 | 'overflow', 95 | 'hidden' 96 | ); 97 | this.drawer.closedStart.pipe(takeUntil(this.onDestory)).subscribe(() => { 98 | this.closeMenu(); 99 | }); 100 | 101 | this.drawer._closedStream.pipe(takeUntil(this.onDestory)).subscribe(() => { 102 | this.renderer2.setStyle(this.el.nativeElement, 'visibility', 'visible'); 103 | this.renderer2.setStyle(this.el.nativeElement, 'display', 'block'); 104 | }); 105 | 106 | this.drawer.openedStart.pipe(takeUntil(this.onDestory)).subscribe(() => { 107 | this.correctContentMargin(this.expandedWidth); 108 | const factory = this.builder.build(this.openAnimation ?? []); 109 | const player = factory.create(this.el.nativeElement); 110 | player.play(); 111 | }); 112 | } 113 | 114 | ngAfterViewInit() { 115 | if (this.drawer.opened) { 116 | this.correctContentMargin(this.expandedWidth); 117 | } else { 118 | this.renderer2.setStyle(this.el.nativeElement, 'visibility', 'visible'); 119 | this.renderer2.setStyle(this.el.nativeElement, 'display', 'block'); 120 | this.closeMenu(); 121 | } 122 | } 123 | 124 | private closeMenu() { 125 | this.correctContentMargin(this.closeWidth); 126 | const factory = this.builder.build(this.closeAnimation ?? []); 127 | const player = factory.create(this.el.nativeElement); 128 | player.play(); 129 | } 130 | 131 | private correctContentMargin(width: string) { 132 | this.containerContent = 133 | (this.containerContent 134 | ? this.containerContent 135 | : this.el.nativeElement?.parentElement?.querySelector( 136 | '.mat-drawer-content' 137 | )) ?? undefined; 138 | if ( 139 | (this.drawer.position !== 'end' && 140 | this._dir && 141 | this._dir.value !== 'rtl') || 142 | (this.drawer.position === 'end' && this._dir && this._dir.value === 'rtl') 143 | ) { 144 | this.renderer2.setStyle(this.containerContent, 'marginLeft', width); 145 | } else { 146 | this.renderer2.setStyle(this.containerContent, 'marginRight', width); 147 | } 148 | } 149 | 150 | public ngOnDestroy(): void { 151 | this.onDestory.next(); 152 | this.onDestory.complete(); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /examples/material-rail-drawer/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | Mini Variant 6 | 7 | 8 | 9 | 10 | 11 | account_circle 12 |

Name

13 |
14 | 15 | 16 | 17 | 18 | inbox 19 |

Inbox

20 |
21 | 22 | star 23 |

Starred

24 |
25 | 26 | drafts 27 |

Drafts

28 |
29 |
30 |
31 | 32 | 33 | 36 | Mini Variant 37 | 38 |
39 |

40 | Angular Material Navigation drawer — Adding support mode = “Rail” (mini 41 | variant behaviour) 42 |

43 |

44 | Since 2016, the Angular community has been shouting out of a 45 | mini variant for material design, including this article by 52 | Harkirat Singh 59 | which you can view here: 60 | Angular 6 — Mini-Variant Drawer. Unfortunately every version I’ve seen currently uses some form of 67 | *ngIf 68 |

69 | 70 |
71 |
72 |
73 | 82 |
83 |
84 |
85 | 86 |

87 | Other solutions include using CSS and setting a min with; however, what 88 | all of these solutions are lacking are animation support and straight 89 | forward implantation. In late December a client I was working for, 90 | wanted to use the official 91 | Angular Material design 97 | but also wanted to support a mini variant. At the time, I wrote a 98 | prototype using a customer directive called mat-nav-mini. 99 |

100 | 101 |

My issues with mat-nav-mini Solution

102 | 103 |

104 | The implementation was easy. You pick either the drawer or the sidenav 105 | drawer and add the custom directive. However, the UI was written 106 | abstract and wasn’t using the official 107 | mat-sidenav-container. However, I still didn’t like this 108 | approach; it felt bulky and still not a “realistic” implementation that 109 | the official team my introduce. At the time, I decided to share the 110 | result on 111 | Github 117 | for people to use as a cleaner implementation to *ngIf. 118 |

119 | 120 |

121 | Then the other day, I looked back through the thread on GitHub, and 122 | someone called 123 | Angelfraga 129 | asked to create a working example. 130 |

131 | 132 |
133 |
134 |
135 |
136 |
137 | 158 |
159 |
160 |
161 |
162 |
163 | 164 |

165 | A few more days have passed by, and I decided, I’ll make a working 166 | example. However, for the working example, I wanted to make the right 167 | implementation that meet my strict objectives 168 |

169 | 170 |
    171 |
  • They should be no new directive.
  • 172 |
  • No extra markup to ensure element was hiding
  • 173 |
  • Simple end-user implementation
  • 174 |
  • 175 | Something that should be relatively easy to migrate if Angular 176 | Material get chance to make an official release 177 |
  • 178 |
179 | 180 |

Designing a solution

181 |

182 | Material has long last drawn up specs for 183 | “Navigation rail.” 189 | Inside the Specs they a behaviour usage: “Some apps, such as 190 | Material’s Reply, customize and extend the rail to function as both a rail and a 196 | navigation drawer.” 197 |

198 | 199 |

200 | The goal is now to create a drawer implementation for a new mode setting 201 | mode="rail". Any new implementation should be implementing 202 | the existing material drawer component but with 203 | mode="rail". 204 |

205 | 206 |

207 | The solution meant no extending drawer component, no CSS solution but 208 | somehow adding functionality to “mode” which was an input for both 209 | md-drawer and md-sidenav-drawer 210 |

211 | 212 |

Solving the the problem

213 |

214 | The first step was determining the first issue to overcome. The design 215 | solution requires you to use the mode input with the option of “rail” 216 | this was easy to overcome as every @Input()In angular is a 217 | simple implementation of the custom directive. 218 |

219 | 220 |

221 | The next problem was the SCSS. Looking at the specs for Navigation rail, 222 | the drawer would be the same spec as the “side” drawer; this meant we 223 | didn’t have to write custom scss file that needed to import. That 224 | allowed me to use the “host” property and assign the same class as 225 | “side”. 226 |

227 |

228 | After tackling these two issues, after two hours of work, looking 229 | through angular code file, I managed to come up with a solution. The 230 | solution is a simple directive that needs to include in your module. 231 |

232 | 233 |

234 | Result is the page you are looking at. 235 | View Source 238 |

239 |
240 |
241 |
242 | --------------------------------------------------------------------------------