mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-12-23 05:37:08 +00:00
Compare commits
228 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e39ec222d0 | ||
|
|
685e981438 | ||
|
|
ba8689ed0c | ||
|
|
41a1692e01 | ||
|
|
d4736e2c02 | ||
|
|
1968227e19 | ||
|
|
28180c7491 | ||
|
|
de7a598c07 | ||
|
|
8ae3cdfbea | ||
|
|
533e39261b | ||
|
|
7870e312b9 | ||
|
|
1662042e35 | ||
|
|
08266c3e51 | ||
|
|
8000e53bae | ||
|
|
8fbef029c0 | ||
|
|
b7b849ee60 | ||
|
|
872dffe42b | ||
|
|
646b084a12 | ||
|
|
c88d30a4f4 | ||
|
|
f2d5bf3041 | ||
|
|
388456b937 | ||
|
|
127280c040 | ||
|
|
cad7cd43f0 | ||
|
|
41756200ca | ||
|
|
4a5f641c1c | ||
|
|
39ad558455 | ||
|
|
404c4f5c07 | ||
|
|
51ee16ed93 | ||
|
|
607f2afa90 | ||
|
|
baf35619bd | ||
|
|
6599587e31 | ||
|
|
3fa878b3f2 | ||
|
|
a24bc3fc95 | ||
|
|
9b1c0f2541 | ||
|
|
3ba64abf6e | ||
|
|
82ed80e35d | ||
|
|
72a63b30ca | ||
|
|
d2b37efed4 | ||
|
|
6d516a119a | ||
|
|
3adf9bee6e | ||
|
|
bb06bccf91 | ||
|
|
3018c0235f | ||
|
|
a6399c0cf4 | ||
|
|
22d91673ae | ||
|
|
3e303a041a | ||
|
|
714bc49c4e | ||
|
|
3cc4f31238 | ||
|
|
c5aa094230 | ||
|
|
cbd35d57f8 | ||
|
|
11d5dcdb9d | ||
|
|
66e5511402 | ||
|
|
20a03c3689 | ||
|
|
d033470851 | ||
|
|
c374c2c6cf | ||
|
|
30d75c9bd7 | ||
|
|
54cd21f496 | ||
|
|
57d87fa1c4 | ||
|
|
cd8c6ece0f | ||
|
|
1bf4c48cdc | ||
|
|
ea9efc3dc2 | ||
|
|
878a6bf191 | ||
|
|
099e745a36 | ||
|
|
150ddc64d7 | ||
|
|
a6d64b1747 | ||
|
|
6eff4a1898 | ||
|
|
e3630218b5 | ||
|
|
154095da0f | ||
|
|
a32970b7c2 | ||
|
|
2771d3b1ae | ||
|
|
9b44793b64 | ||
|
|
9521257b4d | ||
|
|
5378a6b6ef | ||
|
|
c41e48df7f | ||
|
|
b87173b056 | ||
|
|
6aaa355a48 | ||
|
|
b96dd041d9 | ||
|
|
9786c6baf5 | ||
|
|
f5cc14939c | ||
|
|
8fd434600b | ||
|
|
4c82f6749b | ||
|
|
b0830148a3 | ||
|
|
cdc54ab05e | ||
|
|
e6ad547d27 | ||
|
|
afda4b35c9 | ||
|
|
3b88638dee | ||
|
|
b96182c848 | ||
|
|
443a103d6f | ||
|
|
42241b279d | ||
|
|
e5eaea5013 | ||
|
|
6e85b9ff2a | ||
|
|
6e593b1f1e | ||
|
|
57a3f6ae99 | ||
|
|
700a117654 | ||
|
|
5337c95782 | ||
|
|
964c4b23a9 | ||
|
|
a8337ce617 | ||
|
|
3ceda2cf3f | ||
|
|
805b50707e | ||
|
|
3fd522de31 | ||
|
|
4a2c7560e8 | ||
|
|
46753d5402 | ||
|
|
9d3e971325 | ||
|
|
9d7c015fe7 | ||
|
|
4b5cac11f2 | ||
|
|
6c62d25c35 | ||
|
|
5c46b1aaa4 | ||
|
|
3a1a7d44b6 | ||
|
|
0076b1ee8a | ||
|
|
c69542679d | ||
|
|
e4ebe2fd7e | ||
|
|
f380d8ca16 | ||
|
|
6b14c1db7f | ||
|
|
20901117d1 | ||
|
|
83e3c85448 | ||
|
|
4d4b411f76 | ||
|
|
7b5217d009 | ||
|
|
e671100bc5 | ||
|
|
f910615831 | ||
|
|
778679e136 | ||
|
|
c25610ee4e | ||
|
|
3ddd7e4533 | ||
|
|
c21c362b84 | ||
|
|
9f97d74911 | ||
|
|
08aec7c3db | ||
|
|
0f249f287e | ||
|
|
c7b8a4564b | ||
|
|
b6a3023ebd | ||
|
|
693e44dbaf | ||
|
|
206ef711a4 | ||
|
|
7e0cc1249e | ||
|
|
138a43da59 | ||
|
|
fe7e2514a6 | ||
|
|
b8f0d9f0b2 | ||
|
|
2a4a392153 | ||
|
|
c2fa88f4d4 | ||
|
|
67d25012ec | ||
|
|
6de6a07778 | ||
|
|
e7ab0ea13f | ||
|
|
4b686d86cc | ||
|
|
190395f14b | ||
|
|
4a9b8ee91e | ||
|
|
488fe8a1eb | ||
|
|
db9a2a2433 | ||
|
|
3dda8479cf | ||
|
|
7c402670a1 | ||
|
|
f6bf0fb5d3 | ||
|
|
d44c004d01 | ||
|
|
4ec40271c5 | ||
|
|
b21cdf1655 | ||
|
|
6fff259fe3 | ||
|
|
8fcb0aea03 | ||
|
|
2c90770d9b | ||
|
|
1581ea74cc | ||
|
|
569809aabb | ||
|
|
dde9333120 | ||
|
|
10ec1790ca | ||
|
|
a2ff55d4c1 | ||
|
|
966e2db743 | ||
|
|
49cccde93b | ||
|
|
952b64297b | ||
|
|
9b3ff6a724 | ||
|
|
961b86c8cb | ||
|
|
8b977c0eeb | ||
|
|
35e56cd6af | ||
|
|
c04550b887 | ||
|
|
747b4f44c8 | ||
|
|
c4914c80b3 | ||
|
|
178d09597b | ||
|
|
d206c55e6e | ||
|
|
9abe887df1 | ||
|
|
b87fdc407c | ||
|
|
58440b63a7 | ||
|
|
63f6edee9a | ||
|
|
ca8e422b21 | ||
|
|
cc703081ca | ||
|
|
038c74df50 | ||
|
|
9abbf5fec2 | ||
|
|
0ebc16ec05 | ||
|
|
56c4eb0356 | ||
|
|
a8a4f2b18d | ||
|
|
36c8727616 | ||
|
|
5ea37aed99 | ||
|
|
cbce71f155 | ||
|
|
ed47050232 | ||
|
|
c86a538d41 | ||
|
|
f369206ef8 | ||
|
|
1659d4babd | ||
|
|
fa37f99d33 | ||
|
|
331968ac5b | ||
|
|
27274c84d6 | ||
|
|
4b8a101a3e | ||
|
|
8080a85d40 | ||
|
|
36784c405f | ||
|
|
8f4f7886d5 | ||
|
|
d693a08136 | ||
|
|
0c0ef40de3 | ||
|
|
f4d737d3a3 | ||
|
|
47d9ddb08c | ||
|
|
4da3612d22 | ||
|
|
403a949d4a | ||
|
|
5b78a68116 | ||
|
|
214116e10d | ||
|
|
5962c80e8d | ||
|
|
ff086b1ed0 | ||
|
|
efdfa6418a | ||
|
|
c1c9904b9d | ||
|
|
39650d3cc9 | ||
|
|
bafa9adc01 | ||
|
|
bb9023f9df | ||
|
|
66096718e0 | ||
|
|
945d0a2240 | ||
|
|
9005f08ac7 | ||
|
|
89f5a4ec69 | ||
|
|
ca7b4c7e5d | ||
|
|
bb57ec2324 | ||
|
|
11ad2c89df | ||
|
|
fc1e7b02b0 | ||
|
|
446bfe4139 | ||
|
|
2c5cd60c0a | ||
|
|
decb238f73 | ||
|
|
ab3ad4fd2f | ||
|
|
c2dd77d7a3 | ||
|
|
a78b087a68 | ||
|
|
84d40427a1 | ||
|
|
f295fd9061 | ||
|
|
b98cfc1d37 | ||
|
|
0ba5677c01 | ||
|
|
96ef1281ae |
@@ -1,17 +0,0 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -31,6 +31,7 @@ chrome-profiler-events*.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.angular/cache
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
|
||||
@@ -4,7 +4,7 @@ This project was generated with [Angular CLI](https://github.com/angular/angular
|
||||
|
||||
## Development server
|
||||
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
|
||||
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
|
||||
|
||||
## Code scaffolding
|
||||
|
||||
@@ -12,7 +12,7 @@ Run `ng generate component component-name` to generate a new component. You can
|
||||
|
||||
## Build
|
||||
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
|
||||
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
@@ -20,7 +20,7 @@ Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.
|
||||
|
||||
## Running end-to-end tests
|
||||
|
||||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice.
|
||||
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
|
||||
|
||||
## Further help
|
||||
|
||||
|
||||
56
angular.json
56
angular.json
@@ -20,7 +20,9 @@
|
||||
"outputPath": "dist/fuse",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"allowedCommonJsDependencies": [
|
||||
@@ -28,7 +30,9 @@
|
||||
"highlight.js",
|
||||
"crypto-js/enc-utf8",
|
||||
"crypto-js/hmac-sha256",
|
||||
"crypto-js/enc-base64"
|
||||
"crypto-js/enc-base64",
|
||||
"flat",
|
||||
"quill"
|
||||
],
|
||||
"assets": [
|
||||
"src/favicon-16x16.png",
|
||||
@@ -60,19 +64,13 @@
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "5mb",
|
||||
"maximumError": "8mb"
|
||||
"maximumWarning": "3mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "100kb",
|
||||
"maximumError": "150kb"
|
||||
}
|
||||
],
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
"maximumWarning": "75kb",
|
||||
"maximumError": "90kb"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
@@ -109,10 +107,11 @@
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon-16x16.png",
|
||||
@@ -120,37 +119,12 @@
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
"src/styles/styles.scss"
|
||||
],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "fuse:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "fuse:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "fuse",
|
||||
"cli": {
|
||||
"defaultCollection": "@angular-eslint/schematics"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config)
|
||||
{
|
||||
config.set({
|
||||
basePath : '',
|
||||
frameworks : ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins : [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client : {
|
||||
jasmine : {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
},
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
},
|
||||
coverageReporter : {
|
||||
dir : require('path').join(__dirname, './coverage/angular12'),
|
||||
subdir : '.',
|
||||
reporters: [
|
||||
{type: 'html'},
|
||||
{type: 'text-summary'}
|
||||
]
|
||||
},
|
||||
reporters : ['progress', 'kjhtml'],
|
||||
port : 9876,
|
||||
colors : true,
|
||||
logLevel : config.LOG_INFO,
|
||||
autoWatch : true,
|
||||
browsers : ['Chrome'],
|
||||
singleRun : false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
||||
27421
package-lock.json
generated
27421
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
121
package.json
121
package.json
@@ -1,92 +1,67 @@
|
||||
{
|
||||
"name": "@fuse/demo",
|
||||
"version": "13.0.2",
|
||||
"name": "fuse-angular",
|
||||
"version": "17.1.0",
|
||||
"description": "Fuse - Angular Admin Template and Starter Project",
|
||||
"author": "https://themeforest.net/user/srcn",
|
||||
"license": "https://themeforest.net/licenses/standard",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "12.0.0",
|
||||
"@angular/cdk": "12.0.0",
|
||||
"@angular/common": "12.0.0",
|
||||
"@angular/compiler": "12.0.0",
|
||||
"@angular/core": "12.0.0",
|
||||
"@angular/forms": "12.0.0",
|
||||
"@angular/material": "12.0.0",
|
||||
"@angular/material-moment-adapter": "12.0.0",
|
||||
"@angular/platform-browser": "12.0.0",
|
||||
"@angular/platform-browser-dynamic": "12.0.0",
|
||||
"@angular/router": "12.0.0",
|
||||
"@fullcalendar/angular": "4.4.5-beta",
|
||||
"@fullcalendar/core": "4.4.2",
|
||||
"@fullcalendar/daygrid": "4.4.2",
|
||||
"@fullcalendar/interaction": "4.4.2",
|
||||
"@fullcalendar/list": "4.4.2",
|
||||
"@fullcalendar/moment": "4.4.2",
|
||||
"@fullcalendar/rrule": "4.4.2",
|
||||
"@fullcalendar/timegrid": "4.4.2",
|
||||
"@ngneat/transloco": "2.20.1",
|
||||
"apexcharts": "3.26.3",
|
||||
"@angular/animations": "15.0.3",
|
||||
"@angular/cdk": "15.0.2",
|
||||
"@angular/common": "15.0.3",
|
||||
"@angular/compiler": "15.0.3",
|
||||
"@angular/core": "15.0.3",
|
||||
"@angular/forms": "15.0.3",
|
||||
"@angular/material": "15.0.2",
|
||||
"@angular/material-luxon-adapter": "15.0.2",
|
||||
"@angular/platform-browser": "15.0.3",
|
||||
"@angular/platform-browser-dynamic": "15.0.3",
|
||||
"@angular/router": "15.0.3",
|
||||
"@ngneat/transloco": "4.2.1",
|
||||
"apexcharts": "3.36.3",
|
||||
"crypto-js": "3.3.0",
|
||||
"highlight.js": "10.7.2",
|
||||
"highlight.js": "11.7.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"moment": "2.29.1",
|
||||
"ng-apexcharts": "1.5.10",
|
||||
"ngx-markdown": "12.0.0",
|
||||
"ngx-quill": "14.0.0",
|
||||
"perfect-scrollbar": "1.5.1",
|
||||
"luxon": "3.1.1",
|
||||
"ng-apexcharts": "1.7.4",
|
||||
"ngx-quill": "20.0.1",
|
||||
"perfect-scrollbar": "1.5.5",
|
||||
"quill": "1.3.7",
|
||||
"rrule": "2.6.8",
|
||||
"rxjs": "6.6.7",
|
||||
"tslib": "2.2.0",
|
||||
"web-animations-js": "2.3.2",
|
||||
"zone.js": "0.11.4"
|
||||
"rxjs": "7.5.7",
|
||||
"tslib": "2.4.1",
|
||||
"zone.js": "0.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "12.0.0",
|
||||
"@angular-eslint/builder": "12.0.0",
|
||||
"@angular-eslint/eslint-plugin": "12.0.0",
|
||||
"@angular-eslint/eslint-plugin-template": "12.0.0",
|
||||
"@angular-eslint/schematics": "12.0.0",
|
||||
"@angular-eslint/template-parser": "12.0.0",
|
||||
"@angular/cli": "12.0.0",
|
||||
"@angular/compiler-cli": "12.0.0",
|
||||
"@angular/language-service": "12.0.0",
|
||||
"@tailwindcss/aspect-ratio": "0.2.0",
|
||||
"@tailwindcss/line-clamp": "0.2.0",
|
||||
"@tailwindcss/typography": "0.4.0",
|
||||
"@types/chroma-js": "2.1.3",
|
||||
"@angular-devkit/build-angular": "15.0.3",
|
||||
"@angular/cli": "15.0.3",
|
||||
"@angular/compiler-cli": "15.0.3",
|
||||
"@tailwindcss/line-clamp": "0.4.2",
|
||||
"@tailwindcss/typography": "0.5.8",
|
||||
"@types/chroma-js": "2.1.4",
|
||||
"@types/crypto-js": "3.1.47",
|
||||
"@types/highlight.js": "10.1.0",
|
||||
"@types/jasmine": "3.6.11",
|
||||
"@types/lodash": "4.14.169",
|
||||
"@types/lodash-es": "4.17.4",
|
||||
"@types/node": "12.20.13",
|
||||
"@typescript-eslint/eslint-plugin": "4.24.0",
|
||||
"@typescript-eslint/parser": "4.24.0",
|
||||
"autoprefixer": "10.2.5",
|
||||
"chroma-js": "2.1.2",
|
||||
"eslint": "7.26.0",
|
||||
"eslint-plugin-import": "2.23.2",
|
||||
"eslint-plugin-jsdoc": "34.8.2",
|
||||
"eslint-plugin-prefer-arrow": "1.2.3",
|
||||
"jasmine-core": "3.7.1",
|
||||
"jasmine-spec-reporter": "5.0.2",
|
||||
"karma": "6.3.2",
|
||||
"karma-chrome-launcher": "3.1.0",
|
||||
"karma-coverage": "2.0.3",
|
||||
"karma-jasmine": "4.0.1",
|
||||
"karma-jasmine-html-reporter": "1.6.0",
|
||||
"@types/jasmine": "4.3.1",
|
||||
"@types/lodash": "4.14.191",
|
||||
"@types/lodash-es": "4.17.6",
|
||||
"@types/luxon": "3.1.0",
|
||||
"autoprefixer": "10.4.13",
|
||||
"chroma-js": "2.4.2",
|
||||
"jasmine-core": "4.5.0",
|
||||
"karma": "6.4.1",
|
||||
"karma-chrome-launcher": "3.1.1",
|
||||
"karma-coverage": "2.2.0",
|
||||
"karma-jasmine": "5.1.0",
|
||||
"karma-jasmine-html-reporter": "2.0.0",
|
||||
"lodash": "4.17.21",
|
||||
"postcss": "8.3.0",
|
||||
"protractor": "7.0.0",
|
||||
"tailwindcss": "2.1.2",
|
||||
"typescript": "4.2.4"
|
||||
"postcss": "8.4.20",
|
||||
"tailwindcss": "3.2.4",
|
||||
"typescript": "4.8.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
import { FuseAlertAppearance, FuseAlertType } from '@fuse/components/alert/alert.types';
|
||||
@@ -54,6 +53,7 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
return {
|
||||
'fuse-alert-appearance-border' : this.appearance === 'border',
|
||||
'fuse-alert-appearance-fill' : this.appearance === 'fill',
|
||||
@@ -71,6 +71,7 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
'fuse-alert-type-warning' : this.type === 'warning',
|
||||
'fuse-alert-type-error' : this.type === 'error'
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@@ -145,7 +146,7 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,12 +38,14 @@ export class FuseCardComponent implements OnChanges
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
return {
|
||||
'fuse-card-expanded' : this.expanded,
|
||||
'fuse-card-face-back' : this.flippable && this.face === 'back',
|
||||
'fuse-card-face-front': this.flippable && this.face === 'front',
|
||||
'fuse-card-flippable' : this.flippable
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
<div
|
||||
class="range"
|
||||
(click)="openPickerPanel()"
|
||||
#pickerPanelOrigin>
|
||||
|
||||
<div class="start">
|
||||
<div class="date">{{range.startDate}}</div>
|
||||
<div
|
||||
class="time"
|
||||
*ngIf="range.startTime">{{range.startTime}}</div>
|
||||
</div>
|
||||
|
||||
<div class="separator">-</div>
|
||||
|
||||
<div class="end">
|
||||
<div class="date">{{range.endDate}}</div>
|
||||
<div
|
||||
class="time"
|
||||
*ngIf="range.endTime">{{range.endTime}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<ng-template #pickerPanel>
|
||||
|
||||
<!-- Start -->
|
||||
<div class="start">
|
||||
|
||||
<div class="month">
|
||||
<div class="month-header">
|
||||
<button
|
||||
class="previous-button"
|
||||
mat-icon-button
|
||||
(click)="prev()"
|
||||
tabindex="1">
|
||||
<mat-icon [svgIcon]="'heroicons_outline:chevron-left'"></mat-icon>
|
||||
</button>
|
||||
<div class="month-label">{{getMonthLabel(1)}}</div>
|
||||
</div>
|
||||
<mat-month-view
|
||||
[(activeDate)]="activeDates.month1"
|
||||
[dateFilter]="dateFilter()"
|
||||
[dateClass]="dateClass()"
|
||||
(click)="$event.stopImmediatePropagation()"
|
||||
(selectedChange)="onSelectedDateChange($event)"
|
||||
#matMonthView1>
|
||||
</mat-month-view>
|
||||
</div>
|
||||
|
||||
<mat-form-field
|
||||
class="fuse-mat-no-subscript time start-time"
|
||||
*ngIf="timeRange">
|
||||
<input
|
||||
matInput
|
||||
[autocomplete]="'off'"
|
||||
[formControl]="startTimeFormControl"
|
||||
(blur)="updateStartTime($event)"
|
||||
tabindex="3">
|
||||
<mat-label>Start time</mat-label>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- End -->
|
||||
<div class="end">
|
||||
|
||||
<div class="month">
|
||||
<div class="month-header">
|
||||
<div class="month-label">{{getMonthLabel(2)}}</div>
|
||||
<button
|
||||
class="next-button"
|
||||
mat-icon-button
|
||||
(click)="next()"
|
||||
tabindex="2">
|
||||
<mat-icon [svgIcon]="'heroicons_outline:chevron-right'"></mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
<mat-month-view
|
||||
[(activeDate)]="activeDates.month2"
|
||||
[dateFilter]="dateFilter()"
|
||||
[dateClass]="dateClass()"
|
||||
(click)="$event.stopImmediatePropagation()"
|
||||
(selectedChange)="onSelectedDateChange($event)"
|
||||
#matMonthView2>
|
||||
</mat-month-view>
|
||||
</div>
|
||||
|
||||
<mat-form-field
|
||||
class="fuse-mat-no-subscript time end-time"
|
||||
*ngIf="timeRange">
|
||||
<input
|
||||
matInput
|
||||
[formControl]="endTimeFormControl"
|
||||
(blur)="updateEndTime($event)"
|
||||
tabindex="4">
|
||||
<mat-label>End time</mat-label>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
</ng-template>
|
||||
@@ -1,292 +0,0 @@
|
||||
/* Variables */
|
||||
$body-cell-padding: 2px;
|
||||
|
||||
fuse-date-range {
|
||||
display: flex;
|
||||
|
||||
.range {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 48px;
|
||||
min-height: 48px;
|
||||
max-height: 48px;
|
||||
cursor: pointer;
|
||||
|
||||
.start,
|
||||
.end {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 0 16px;
|
||||
border-radius: 6px;
|
||||
border-width: 1px;
|
||||
line-height: 1;
|
||||
@apply shadow-sm border-gray-300 dark:bg-black dark:bg-opacity-5 dark:border-gray-500;
|
||||
|
||||
.date {
|
||||
white-space: nowrap;
|
||||
|
||||
+ .time {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 0 2px;
|
||||
|
||||
@screen sm {
|
||||
margin: 0 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fuse-date-range-panel {
|
||||
border-radius: 4px;
|
||||
padding: 24px;
|
||||
@apply shadow-2xl bg-card;
|
||||
|
||||
.start,
|
||||
.end {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.month {
|
||||
max-width: 196px;
|
||||
min-width: 196px;
|
||||
width: 196px;
|
||||
|
||||
.month-header {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 32px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.previous-button,
|
||||
.next-button {
|
||||
position: absolute;
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
min-height: 24px !important;
|
||||
max-height: 24px !important;
|
||||
line-height: 24px !important;
|
||||
|
||||
.mat-icon {
|
||||
@apply icon-size-5;
|
||||
}
|
||||
}
|
||||
|
||||
.previous-button {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.next-button {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.month-label {
|
||||
font-weight: 500;
|
||||
@apply text-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
mat-month-view {
|
||||
display: flex;
|
||||
min-height: 188px;
|
||||
|
||||
.mat-calendar-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
tbody {
|
||||
|
||||
tr {
|
||||
|
||||
&[aria-hidden=true] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
|
||||
td:first-child {
|
||||
|
||||
&[aria-hidden=true] {
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td,
|
||||
td:hover {
|
||||
|
||||
&.fuse-date-range {
|
||||
|
||||
&:before {
|
||||
@apply bg-primary-200;
|
||||
}
|
||||
|
||||
.mat-calendar-body-cell-content {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.fuse-date-range-start,
|
||||
&.fuse-date-range-end {
|
||||
|
||||
.mat-calendar-body-cell-content {
|
||||
@apply bg-primary text-on-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-calendar-body-today {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
td.mat-calendar-body-cell {
|
||||
width: 28px !important;
|
||||
height: 28px !important;
|
||||
padding: $body-cell-padding !important;
|
||||
|
||||
&.fuse-date-range {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: $body-cell-padding;
|
||||
right: 0;
|
||||
bottom: $body-cell-padding;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&.fuse-date-range-start {
|
||||
|
||||
&:before {
|
||||
left: $body-cell-padding;
|
||||
border-radius: 999px 0 0 999px;
|
||||
}
|
||||
|
||||
&.fuse-date-range-end,
|
||||
&:last-child {
|
||||
|
||||
&:before {
|
||||
right: $body-cell-padding;
|
||||
border-radius: 999px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.fuse-date-range-end {
|
||||
|
||||
&:before {
|
||||
right: $body-cell-padding;
|
||||
border-radius: 0 999px 999px 0;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
|
||||
&:before {
|
||||
left: $body-cell-padding;
|
||||
border-radius: 999px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
|
||||
&:before {
|
||||
border-radius: 999px 0 0 999px;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
|
||||
&:before {
|
||||
border-radius: 0 999px 999px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-calendar-body-cell-content {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
td.mat-calendar-body-label {
|
||||
|
||||
+ td.mat-calendar-body-cell {
|
||||
|
||||
&.fuse-date-range {
|
||||
|
||||
&:before {
|
||||
border-radius: 999px 0 0 999px;
|
||||
}
|
||||
|
||||
&.fuse-date-range-start {
|
||||
|
||||
&.fuse-date-range-end {
|
||||
border-radius: 999px;
|
||||
}
|
||||
}
|
||||
|
||||
&.fuse-date-range-end {
|
||||
|
||||
&:before {
|
||||
left: $body-cell-padding;
|
||||
border-radius: 999px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 100%;
|
||||
max-width: 196px;
|
||||
}
|
||||
}
|
||||
|
||||
.start {
|
||||
align-items: flex-start;
|
||||
margin-right: 20px;
|
||||
|
||||
.month {
|
||||
|
||||
.month-label {
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.end {
|
||||
align-items: flex-end;
|
||||
margin-left: 20px;
|
||||
|
||||
.month {
|
||||
|
||||
.month-label {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,682 +0,0 @@
|
||||
import { ChangeDetectorRef, Component, ElementRef, EventEmitter, forwardRef, HostBinding, Input, OnDestroy, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
|
||||
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
|
||||
import { Overlay } from '@angular/cdk/overlay';
|
||||
import { TemplatePortal } from '@angular/cdk/portal';
|
||||
import { MatCalendarCellCssClasses, MatMonthView } from '@angular/material/datepicker';
|
||||
import { Subject } from 'rxjs';
|
||||
import * as moment from 'moment';
|
||||
import { Moment } from 'moment';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-date-range',
|
||||
templateUrl : './date-range.component.html',
|
||||
styleUrls : ['./date-range.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
exportAs : 'fuseDateRange',
|
||||
providers : [
|
||||
{
|
||||
provide : NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => FuseDateRangeComponent),
|
||||
multi : true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class FuseDateRangeComponent implements ControlValueAccessor, OnInit, OnDestroy
|
||||
{
|
||||
@Output() readonly rangeChanged: EventEmitter<{ start: string; end: string }> = new EventEmitter<{ start: string; end: string }>();
|
||||
@ViewChild('matMonthView1') private _matMonthView1: MatMonthView<any>;
|
||||
@ViewChild('matMonthView2') private _matMonthView2: MatMonthView<any>;
|
||||
@ViewChild('pickerPanelOrigin', {read: ElementRef}) private _pickerPanelOrigin: ElementRef;
|
||||
@ViewChild('pickerPanel') private _pickerPanel: TemplateRef<any>;
|
||||
@HostBinding('class.fuse-date-range') private _defaultClassNames = true;
|
||||
|
||||
activeDates: { month1: Moment | null; month2: Moment | null } = {
|
||||
month1: null,
|
||||
month2: null
|
||||
};
|
||||
setWhichDate: 'start' | 'end' = 'start';
|
||||
startTimeFormControl: FormControl;
|
||||
endTimeFormControl: FormControl;
|
||||
private _dateFormat: string;
|
||||
private _onChange: (value: any) => void;
|
||||
private _onTouched: (value: any) => void;
|
||||
private _programmaticChange!: boolean;
|
||||
private _range: { start: Moment | null; end: Moment | null } = {
|
||||
start: null,
|
||||
end : null
|
||||
};
|
||||
private _timeFormat: string;
|
||||
private _timeRange: boolean;
|
||||
private readonly _timeRegExp: RegExp = new RegExp('^(0[0-9]|1[0-9]|2[0-4]|[0-9]):([0-5][0-9])(A|(?:AM)|P|(?:PM))?$', 'i');
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
private _elementRef: ElementRef,
|
||||
private _overlay: Overlay,
|
||||
private _renderer2: Renderer2,
|
||||
private _viewContainerRef: ViewContainerRef
|
||||
)
|
||||
{
|
||||
this._onChange = (): void => {
|
||||
};
|
||||
this._onTouched = (): void => {
|
||||
};
|
||||
this.dateFormat = 'DD/MM/YYYY';
|
||||
this.timeFormat = '12';
|
||||
|
||||
// Initialize the component
|
||||
this._init();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Accessors
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Setter & getter for dateFormat input
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
@Input()
|
||||
set dateFormat(value: string)
|
||||
{
|
||||
// Return if the values are the same
|
||||
if ( this._dateFormat === value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the value
|
||||
this._dateFormat = value;
|
||||
}
|
||||
|
||||
get dateFormat(): string
|
||||
{
|
||||
return this._dateFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter & getter for timeFormat input
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
@Input()
|
||||
set timeFormat(value: string)
|
||||
{
|
||||
// Return if the values are the same
|
||||
if ( this._timeFormat === value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set format based on the time format input
|
||||
this._timeFormat = value === '12' ? 'hh:mmA' : 'HH:mm';
|
||||
}
|
||||
|
||||
get timeFormat(): string
|
||||
{
|
||||
return this._timeFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter & getter for timeRange input
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
@Input()
|
||||
set timeRange(value: boolean)
|
||||
{
|
||||
// Return if the values are the same
|
||||
if ( this._timeRange === value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the value
|
||||
this._timeRange = value;
|
||||
|
||||
// If the time range turned off...
|
||||
if ( !value )
|
||||
{
|
||||
this.range = {
|
||||
start: this._range.start.clone().startOf('day'),
|
||||
end : this._range.end.clone().endOf('day')
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
get timeRange(): boolean
|
||||
{
|
||||
return this._timeRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter & getter for range input
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
@Input()
|
||||
set range(value)
|
||||
{
|
||||
if ( !value )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the value is an object and has 'start' and 'end' values
|
||||
if ( !value.start || !value.end )
|
||||
{
|
||||
console.error('Range input must have "start" and "end" properties!');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we are setting an individual date or both of them
|
||||
const whichDate = value.whichDate || null;
|
||||
|
||||
// Get the start and end dates as moment
|
||||
const start = moment(value.start);
|
||||
const end = moment(value.end);
|
||||
|
||||
// If we are only setting the start date...
|
||||
if ( whichDate === 'start' )
|
||||
{
|
||||
// Set the start date
|
||||
this._range.start = start.clone();
|
||||
|
||||
// If the selected start date is after the end date...
|
||||
if ( this._range.start.isAfter(this._range.end) )
|
||||
{
|
||||
// Set the end date to the start date but keep the end date's time
|
||||
const endDate = start.clone().hours(this._range.end.hours()).minutes(this._range.end.minutes()).seconds(this._range.end.seconds());
|
||||
|
||||
// Test this new end date to see if it's ahead of the start date
|
||||
if ( this._range.start.isBefore(endDate) )
|
||||
{
|
||||
// If it's, set the new end date
|
||||
this._range.end = endDate;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, set the end date same as the start date
|
||||
this._range.end = start.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we are only setting the end date...
|
||||
if ( whichDate === 'end' )
|
||||
{
|
||||
// Set the end date
|
||||
this._range.end = end.clone();
|
||||
|
||||
// If the selected end date is before the start date...
|
||||
if ( this._range.start.isAfter(this._range.end) )
|
||||
{
|
||||
// Set the start date to the end date but keep the start date's time
|
||||
const startDate = end.clone().hours(this._range.start.hours()).minutes(this._range.start.minutes()).seconds(this._range.start.seconds());
|
||||
|
||||
// Test this new end date to see if it's ahead of the start date
|
||||
if ( this._range.end.isAfter(startDate) )
|
||||
{
|
||||
// If it's, set the new start date
|
||||
this._range.start = startDate;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, set the start date same as the end date
|
||||
this._range.start = end.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we are setting both dates...
|
||||
if ( !whichDate )
|
||||
{
|
||||
// Set the start date
|
||||
this._range.start = start.clone();
|
||||
|
||||
// If the start date is before the end date, set the end date as normal.
|
||||
// If the start date is after the end date, set the end date same as the start date.
|
||||
this._range.end = start.isBefore(end) ? end.clone() : start.clone();
|
||||
}
|
||||
|
||||
// Prepare another range object that holds the ISO formatted range dates
|
||||
const range = {
|
||||
start: this._range.start.clone().toISOString(),
|
||||
end : this._range.end.clone().toISOString()
|
||||
};
|
||||
|
||||
// Emit the range changed event with the range
|
||||
this.rangeChanged.emit(range);
|
||||
|
||||
// Update the model with the range if the change was not a programmatic change
|
||||
// Because programmatic changes trigger writeValue which triggers onChange and onTouched
|
||||
// internally causing them to trigger twice which breaks the form's pristine and touched
|
||||
// statuses.
|
||||
if ( !this._programmaticChange )
|
||||
{
|
||||
this._onTouched(range);
|
||||
this._onChange(range);
|
||||
}
|
||||
|
||||
// Set the active dates
|
||||
this.activeDates = {
|
||||
month1: this._range.start.clone(),
|
||||
month2: this._range.start.clone().add(1, 'month')
|
||||
};
|
||||
|
||||
// Set the time form controls
|
||||
this.startTimeFormControl.setValue(this._range.start.clone().format(this._timeFormat).toString());
|
||||
this.endTimeFormControl.setValue(this._range.end.clone().format(this._timeFormat).toString());
|
||||
|
||||
// Run ngAfterContentInit on month views to trigger
|
||||
// re-render on month views if they are available
|
||||
if ( this._matMonthView1 && this._matMonthView2 )
|
||||
{
|
||||
this._matMonthView1.ngAfterContentInit();
|
||||
this._matMonthView2.ngAfterContentInit();
|
||||
}
|
||||
|
||||
// Reset the programmatic change status
|
||||
this._programmaticChange = false;
|
||||
}
|
||||
|
||||
get range(): any
|
||||
{
|
||||
// Clone the range start and end
|
||||
const start = this._range.start.clone();
|
||||
const end = this._range.end.clone();
|
||||
|
||||
// Build and return the range object
|
||||
return {
|
||||
startDate: start.clone().format(this.dateFormat),
|
||||
startTime: this.timeRange ? start.clone().format(this.timeFormat) : null,
|
||||
endDate : end.clone().format(this.dateFormat),
|
||||
endTime : this.timeRange ? end.clone().format(this.timeFormat) : null
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Control Value Accessor
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Update the form model on change
|
||||
*
|
||||
* @param fn
|
||||
*/
|
||||
registerOnChange(fn: any): void
|
||||
{
|
||||
this._onChange = fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the form model on blur
|
||||
*
|
||||
* @param fn
|
||||
*/
|
||||
registerOnTouched(fn: any): void
|
||||
{
|
||||
this._onTouched = fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to view from model when the form model changes programmatically
|
||||
*
|
||||
* @param range
|
||||
*/
|
||||
writeValue(range: { start: string; end: string }): void
|
||||
{
|
||||
// Set this change as a programmatic one
|
||||
this._programmaticChange = true;
|
||||
|
||||
// Set the range
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Lifecycle hooks
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.complete();
|
||||
|
||||
// @ TODO: Workaround until "angular/issues/20007" resolved
|
||||
this.writeValue = (): void => {
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Open the picker panel
|
||||
*/
|
||||
openPickerPanel(): void
|
||||
{
|
||||
// Create the overlay
|
||||
const overlayRef = this._overlay.create({
|
||||
panelClass : 'fuse-date-range-panel',
|
||||
backdropClass : '',
|
||||
hasBackdrop : true,
|
||||
scrollStrategy : this._overlay.scrollStrategies.reposition(),
|
||||
positionStrategy: this._overlay.position()
|
||||
.flexibleConnectedTo(this._pickerPanelOrigin)
|
||||
.withPositions([
|
||||
{
|
||||
originX : 'start',
|
||||
originY : 'bottom',
|
||||
overlayX: 'start',
|
||||
overlayY: 'top',
|
||||
offsetY : 8
|
||||
},
|
||||
{
|
||||
originX : 'start',
|
||||
originY : 'top',
|
||||
overlayX: 'start',
|
||||
overlayY: 'bottom',
|
||||
offsetY : -8
|
||||
}
|
||||
])
|
||||
});
|
||||
|
||||
// Create a portal from the template
|
||||
const templatePortal = new TemplatePortal(this._pickerPanel, this._viewContainerRef);
|
||||
|
||||
// On backdrop click
|
||||
overlayRef.backdropClick().subscribe(() => {
|
||||
|
||||
// If template portal exists and attached...
|
||||
if ( templatePortal && templatePortal.isAttached )
|
||||
{
|
||||
// Detach it
|
||||
templatePortal.detach();
|
||||
}
|
||||
|
||||
// If overlay exists and attached...
|
||||
if ( overlayRef && overlayRef.hasAttached() )
|
||||
{
|
||||
// Detach it
|
||||
overlayRef.detach();
|
||||
overlayRef.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
// Attach the portal to the overlay
|
||||
overlayRef.attach(templatePortal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get month label
|
||||
*
|
||||
* @param month
|
||||
*/
|
||||
getMonthLabel(month: number): string
|
||||
{
|
||||
if ( month === 1 )
|
||||
{
|
||||
return this.activeDates.month1.clone().format('MMMM Y');
|
||||
}
|
||||
|
||||
return this.activeDates.month2.clone().format('MMMM Y');
|
||||
}
|
||||
|
||||
/**
|
||||
* Date class function to add/remove class names to calendar days
|
||||
*/
|
||||
dateClass(): any
|
||||
{
|
||||
return (date: Moment): MatCalendarCellCssClasses => {
|
||||
|
||||
// If the date is both start and end date...
|
||||
if ( date.isSame(this._range.start, 'day') && date.isSame(this._range.end, 'day') )
|
||||
{
|
||||
return ['fuse-date-range', 'fuse-date-range-start', 'fuse-date-range-end'];
|
||||
}
|
||||
|
||||
// If the date is the start date...
|
||||
if ( date.isSame(this._range.start, 'day') )
|
||||
{
|
||||
return ['fuse-date-range', 'fuse-date-range-start'];
|
||||
}
|
||||
|
||||
// If the date is the end date...
|
||||
if ( date.isSame(this._range.end, 'day') )
|
||||
{
|
||||
return ['fuse-date-range', 'fuse-date-range-end'];
|
||||
}
|
||||
|
||||
// If the date is in between start and end dates...
|
||||
if ( date.isBetween(this._range.start, this._range.end, 'day') )
|
||||
{
|
||||
return ['fuse-date-range', 'fuse-date-range-mid'];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Date filter to enable/disable calendar days
|
||||
*/
|
||||
dateFilter(): any
|
||||
{
|
||||
// If we are selecting the end date, disable all the dates that comes before the start date
|
||||
return (date: Moment): boolean => !(this.setWhichDate === 'end' && date.isBefore(this._range.start, 'day'));
|
||||
}
|
||||
|
||||
/**
|
||||
* On selected date change
|
||||
*
|
||||
* @param date
|
||||
*/
|
||||
onSelectedDateChange(date: Moment): void
|
||||
{
|
||||
// Create a new range object
|
||||
const newRange = {
|
||||
start : this._range.start.clone().toISOString(),
|
||||
end : this._range.end.clone().toISOString(),
|
||||
whichDate: null
|
||||
};
|
||||
|
||||
// Replace either the start or the end date with the new one
|
||||
// depending on which date we are setting
|
||||
if ( this.setWhichDate === 'start' )
|
||||
{
|
||||
newRange.start = moment(newRange.start).year(date.year()).month(date.month()).date(date.date()).toISOString();
|
||||
}
|
||||
else
|
||||
{
|
||||
newRange.end = moment(newRange.end).year(date.year()).month(date.month()).date(date.date()).toISOString();
|
||||
}
|
||||
|
||||
// Append the which date to the new range object
|
||||
newRange.whichDate = this.setWhichDate;
|
||||
|
||||
// Switch which date to set on the next run
|
||||
this.setWhichDate = this.setWhichDate === 'start' ? 'end' : 'start';
|
||||
|
||||
// Set the range
|
||||
this.range = newRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to previous month on both views
|
||||
*/
|
||||
prev(): void
|
||||
{
|
||||
this.activeDates.month1 = moment(this.activeDates.month1).subtract(1, 'month');
|
||||
this.activeDates.month2 = moment(this.activeDates.month2).subtract(1, 'month');
|
||||
}
|
||||
|
||||
/**
|
||||
* Go to next month on both views
|
||||
*/
|
||||
next(): void
|
||||
{
|
||||
this.activeDates.month1 = moment(this.activeDates.month1).add(1, 'month');
|
||||
this.activeDates.month2 = moment(this.activeDates.month2).add(1, 'month');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the start time
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
updateStartTime(event): void
|
||||
{
|
||||
// Parse the time
|
||||
const parsedTime = this._parseTime(event.target.value);
|
||||
|
||||
// Go back to the previous value if the form control is not valid
|
||||
if ( this.startTimeFormControl.invalid )
|
||||
{
|
||||
// Override the time
|
||||
const time = this._range.start.clone().format(this._timeFormat);
|
||||
|
||||
// Set the time
|
||||
this.startTimeFormControl.setValue(time);
|
||||
|
||||
// Do not update the range
|
||||
return;
|
||||
}
|
||||
|
||||
// Append the new time to the start date
|
||||
const startDate = this._range.start.clone().hours(parsedTime.hours()).minutes(parsedTime.minutes());
|
||||
|
||||
// If the new start date is after the current end date,
|
||||
// use the end date's time and set the start date again
|
||||
if ( startDate.isAfter(this._range.end) )
|
||||
{
|
||||
const endDateHours = this._range.end.hours();
|
||||
const endDateMinutes = this._range.end.minutes();
|
||||
|
||||
// Set the start date
|
||||
startDate.hours(endDateHours).minutes(endDateMinutes);
|
||||
}
|
||||
|
||||
// If everything is okay, set the new date
|
||||
this.range = {
|
||||
start : startDate.toISOString(),
|
||||
end : this._range.end.clone().toISOString(),
|
||||
whichDate: 'start'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the end time
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
updateEndTime(event): void
|
||||
{
|
||||
// Parse the time
|
||||
const parsedTime = this._parseTime(event.target.value);
|
||||
|
||||
// Go back to the previous value if the form control is not valid
|
||||
if ( this.endTimeFormControl.invalid )
|
||||
{
|
||||
// Override the time
|
||||
const time = this._range.end.clone().format(this._timeFormat);
|
||||
|
||||
// Set the time
|
||||
this.endTimeFormControl.setValue(time);
|
||||
|
||||
// Do not update the range
|
||||
return;
|
||||
}
|
||||
|
||||
// Append the new time to the end date
|
||||
const endDate = this._range.end.clone().hours(parsedTime.hours()).minutes(parsedTime.minutes());
|
||||
|
||||
// If the new end date is before the current start date,
|
||||
// use the start date's time and set the end date again
|
||||
if ( endDate.isBefore(this._range.start) )
|
||||
{
|
||||
const startDateHours = this._range.start.hours();
|
||||
const startDateMinutes = this._range.start.minutes();
|
||||
|
||||
// Set the end date
|
||||
endDate.hours(startDateHours).minutes(startDateMinutes);
|
||||
}
|
||||
|
||||
// If everything is okay, set the new date
|
||||
this.range = {
|
||||
start : this._range.start.clone().toISOString(),
|
||||
end : endDate.toISOString(),
|
||||
whichDate: 'end'
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Private methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _init(): void
|
||||
{
|
||||
// Start and end time form controls
|
||||
this.startTimeFormControl = new FormControl('', [Validators.pattern(this._timeRegExp)]);
|
||||
this.endTimeFormControl = new FormControl('', [Validators.pattern(this._timeRegExp)]);
|
||||
|
||||
// Set the default range
|
||||
this._programmaticChange = true;
|
||||
this.range = {
|
||||
start: moment().startOf('day').toISOString(),
|
||||
end : moment().add(1, 'day').endOf('day').toISOString()
|
||||
};
|
||||
|
||||
// Set the default time range
|
||||
this._programmaticChange = true;
|
||||
this.timeRange = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the time from the inputs
|
||||
*
|
||||
* @param value
|
||||
* @private
|
||||
*/
|
||||
private _parseTime(value: string): Moment
|
||||
{
|
||||
// Parse the time using the time regexp
|
||||
const timeArr = value.split(this._timeRegExp).filter(part => part !== '');
|
||||
|
||||
// Get the meridiem
|
||||
const meridiem = timeArr[2] || null;
|
||||
|
||||
// If meridiem exists...
|
||||
if ( meridiem )
|
||||
{
|
||||
// Create a moment using 12-hours format and return it
|
||||
return moment(value, 'hh:mmA').seconds(0);
|
||||
}
|
||||
|
||||
// If meridiem doesn't exist, create a moment using 24-hours format and return in
|
||||
return moment(value, 'HH:mm').seconds(0);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatMomentDateModule } from '@angular/material-moment-adapter';
|
||||
import { FuseDateRangeComponent } from '@fuse/components/date-range/date-range.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
FuseDateRangeComponent
|
||||
],
|
||||
imports : [
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
MatButtonModule,
|
||||
MatDatepickerModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatIconModule,
|
||||
MatMomentDateModule
|
||||
],
|
||||
exports : [
|
||||
FuseDateRangeComponent
|
||||
]
|
||||
})
|
||||
export class FuseDateRangeModule
|
||||
{
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from '@fuse/components/date-range/public-api';
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from '@fuse/components/date-range/date-range.component';
|
||||
export * from '@fuse/components/date-range/date-range.module';
|
||||
@@ -1,14 +1,16 @@
|
||||
/* Variables */
|
||||
$fuse-drawer-width: 320;
|
||||
:root {
|
||||
--fuse-drawer-width: 320px;
|
||||
}
|
||||
|
||||
fuse-drawer {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
width: #{$fuse-drawer-width}px;
|
||||
min-width: #{$fuse-drawer-width}px;
|
||||
max-width: #{$fuse-drawer-width}px;
|
||||
width: var(--fuse-drawer-width);
|
||||
min-width: var(--fuse-drawer-width);
|
||||
max-width: var(--fuse-drawer-width);
|
||||
z-index: 300;
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, .35);
|
||||
@apply bg-card;
|
||||
@@ -43,7 +45,7 @@ fuse-drawer {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-drawer-mode-side {
|
||||
margin-left: -#{$fuse-drawer-width}px;
|
||||
margin-left: calc(var(--fuse-drawer-width) * -1);
|
||||
|
||||
&.fuse-drawer-opened {
|
||||
margin-left: 0;
|
||||
@@ -71,7 +73,7 @@ fuse-drawer {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-drawer-mode-side {
|
||||
margin-right: -#{$fuse-drawer-width}px;
|
||||
margin-right: calc(var(--fuse-drawer-width) * -1);
|
||||
|
||||
&.fuse-drawer-opened {
|
||||
margin-right: 0;
|
||||
@@ -116,7 +118,7 @@ fuse-drawer {
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 299;
|
||||
opacity: 0;
|
||||
opacity: 1;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
|
||||
/* Fixed mode */
|
||||
|
||||
@@ -32,6 +32,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
@Output() readonly positionChanged: EventEmitter<FuseDrawerPosition> = new EventEmitter<FuseDrawerPosition>();
|
||||
|
||||
private _animationsEnabled: boolean = false;
|
||||
private readonly _handleOverlayClick: any;
|
||||
private _hovered: boolean = false;
|
||||
private _overlay: HTMLElement;
|
||||
private _player: AnimationPlayer;
|
||||
@@ -47,6 +48,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
private _fuseUtilsService: FuseUtilsService
|
||||
)
|
||||
{
|
||||
this._handleOverlayClick = (): void => {
|
||||
this.close();
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@@ -58,6 +62,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
return {
|
||||
'fuse-drawer-animations-enabled' : this._animationsEnabled,
|
||||
'fuse-drawer-fixed' : this.fixed,
|
||||
@@ -66,6 +71,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
'fuse-drawer-opened' : this.opened,
|
||||
[`fuse-drawer-position-${this.position}`]: true
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,6 +217,12 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Finish the animation
|
||||
if ( this._player )
|
||||
{
|
||||
this._player.finish();
|
||||
}
|
||||
|
||||
// Deregister the drawer from the registry
|
||||
this._fuseDrawerService.deregisterComponent(this.name);
|
||||
}
|
||||
@@ -312,12 +324,6 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
// Create the backdrop element
|
||||
this._overlay = this._renderer2.createElement('div');
|
||||
|
||||
// Return if overlay couldn't be create for some reason
|
||||
if ( !this._overlay )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a class to the backdrop element
|
||||
this._overlay.classList.add('fuse-drawer-overlay');
|
||||
|
||||
@@ -336,8 +342,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
// Append the backdrop to the parent of the drawer
|
||||
this._renderer2.appendChild(this._elementRef.nativeElement.parentElement, this._overlay);
|
||||
|
||||
// Create the enter animation and attach it to the player
|
||||
// Create enter animation and attach it to the player
|
||||
this._player = this._animationBuilder.build([
|
||||
style({opacity: 0}),
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 1}))
|
||||
]).create(this._overlay);
|
||||
|
||||
@@ -345,9 +352,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
this._player.play();
|
||||
|
||||
// Add an event listener to the overlay
|
||||
this._overlay.addEventListener('click', () => {
|
||||
this.close();
|
||||
});
|
||||
this._overlay.addEventListener('click', this._handleOverlayClick);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,10 +378,13 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
// Once the animation is done...
|
||||
this._player.onDone(() => {
|
||||
|
||||
// If the backdrop still exists...
|
||||
// If the overlay still exists...
|
||||
if ( this._overlay )
|
||||
{
|
||||
// Remove the backdrop
|
||||
// Remove the event listener
|
||||
this._overlay.removeEventListener('click', this._handleOverlayClick);
|
||||
|
||||
// Remove the overlay
|
||||
this._overlay.parentNode.removeChild(this._overlay);
|
||||
this._overlay = null;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<!-- Button -->
|
||||
<button
|
||||
mat-icon-button
|
||||
[matTooltip]="'Toggle Fullscreen'"
|
||||
[matTooltip]="tooltip || 'Toggle Fullscreen'"
|
||||
(click)="toggleFullscreen()">
|
||||
<mat-icon [svgIcon]="'heroicons_outline:arrows-expand'"></mat-icon>
|
||||
<ng-container [ngTemplateOutlet]="iconTpl || defaultIconTpl"></ng-container>
|
||||
</button>
|
||||
|
||||
<!-- Default icon -->
|
||||
<ng-template #defaultIconTpl>
|
||||
<mat-icon [svgIcon]="'heroicons_outline:arrows-expand'"></mat-icon>
|
||||
</ng-template>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Inject, Input, OnInit, TemplateRef, ViewEncapsulation } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { FSDocument, FSDocumentElement } from '@fuse/components/fullscreen/fullscreen.types';
|
||||
|
||||
@@ -11,6 +11,8 @@ import { FSDocument, FSDocumentElement } from '@fuse/components/fullscreen/fulls
|
||||
})
|
||||
export class FuseFullscreenComponent implements OnInit
|
||||
{
|
||||
@Input() iconTpl: TemplateRef<any>;
|
||||
@Input() tooltip: string;
|
||||
private _fsDoc: FSDocument;
|
||||
private _fsDocEl: FSDocumentElement;
|
||||
private _isFullscreen: boolean = false;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { FuseFullscreenComponent } from '@fuse/components/fullscreen/fullscreen.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -11,7 +12,8 @@ import { FuseFullscreenComponent } from '@fuse/components/fullscreen/fullscreen.
|
||||
imports : [
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatTooltipModule
|
||||
MatTooltipModule,
|
||||
CommonModule
|
||||
],
|
||||
exports : [
|
||||
FuseFullscreenComponent
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import * as hljs from 'highlight.js';
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
||||
1
src/@fuse/components/loading-bar/index.ts
Normal file
1
src/@fuse/components/loading-bar/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@fuse/components/loading-bar/public-api';
|
||||
@@ -0,0 +1,5 @@
|
||||
<ng-container *ngIf="show">
|
||||
<mat-progress-bar
|
||||
[mode]="mode"
|
||||
[value]="progress"></mat-progress-bar>
|
||||
</ng-container>
|
||||
@@ -0,0 +1,7 @@
|
||||
fuse-loading-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
}
|
||||
82
src/@fuse/components/loading-bar/loading-bar.component.ts
Normal file
82
src/@fuse/components/loading-bar/loading-bar.component.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseLoadingService } from '@fuse/services/loading';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-loading-bar',
|
||||
templateUrl : './loading-bar.component.html',
|
||||
styleUrls : ['./loading-bar.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
exportAs : 'fuseLoadingBar'
|
||||
})
|
||||
export class FuseLoadingBarComponent implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
@Input() autoMode: boolean = true;
|
||||
mode: 'determinate' | 'indeterminate';
|
||||
progress: number = 0;
|
||||
show: boolean = false;
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(private _fuseLoadingService: FuseLoadingService)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Lifecycle hooks
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* On changes
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
// Auto mode
|
||||
if ( 'autoMode' in changes )
|
||||
{
|
||||
// Set the auto mode in the service
|
||||
this._fuseLoadingService.setAutoMode(coerceBooleanProperty(changes.autoMode.currentValue));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
// Subscribe to the service
|
||||
this._fuseLoadingService.mode$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((value) => {
|
||||
this.mode = value;
|
||||
});
|
||||
|
||||
this._fuseLoadingService.progress$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((value) => {
|
||||
this.progress = value;
|
||||
});
|
||||
|
||||
this._fuseLoadingService.show$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((value) => {
|
||||
this.show = value;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
20
src/@fuse/components/loading-bar/loading-bar.module.ts
Normal file
20
src/@fuse/components/loading-bar/loading-bar.module.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { FuseLoadingBarComponent } from '@fuse/components/loading-bar/loading-bar.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
FuseLoadingBarComponent
|
||||
],
|
||||
imports : [
|
||||
CommonModule,
|
||||
MatProgressBarModule
|
||||
],
|
||||
exports : [
|
||||
FuseLoadingBarComponent
|
||||
]
|
||||
})
|
||||
export class FuseLoadingBarModule
|
||||
{
|
||||
}
|
||||
2
src/@fuse/components/loading-bar/public-api.ts
Normal file
2
src/@fuse/components/loading-bar/public-api.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from '@fuse/components/loading-bar/loading-bar.component';
|
||||
export * from '@fuse/components/loading-bar/loading-bar.module';
|
||||
@@ -5,7 +5,6 @@ import { FuseMediaWatcherService } from '@fuse/services/media-watcher';
|
||||
@Component({
|
||||
selector : 'fuse-masonry',
|
||||
templateUrl : './masonry.component.html',
|
||||
styleUrls : ['./masonry.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
animations : fuseAnimations,
|
||||
exportAs : 'fuseMasonry'
|
||||
|
||||
@@ -5,69 +5,91 @@
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
<!-- Item with an internal link -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
*ngIf="item.link && !item.externalLink && !item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="item.link && !item.externalLink && !item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
[queryParams]="item.queryParams ?? null"
|
||||
[queryParamsHandling]="item.queryParamsHandling ?? null"
|
||||
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link -->
|
||||
<a
|
||||
class="fuse-horizontal-navigation-item"
|
||||
*ngIf="item.link && item.externalLink && !item.function && !item.disabled"
|
||||
[href]="item.link">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
<ng-container *ngIf="item.link && item.externalLink && !item.function && !item.disabled">
|
||||
<a
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[href]="item.link"
|
||||
[target]="item.target || '_self'"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with a function -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
*ngIf="!item.link && item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="!item.link && item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an internal link and function -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
*ngIf="item.link && !item.externalLink && item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="item.link && !item.externalLink && item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
[queryParams]="item.queryParams ?? null"
|
||||
[queryParamsHandling]="item.queryParamsHandling ?? null"
|
||||
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link and function -->
|
||||
<a
|
||||
class="fuse-horizontal-navigation-item"
|
||||
*ngIf="item.link && item.externalLink && item.function && !item.disabled"
|
||||
[href]="item.link"
|
||||
(click)="item.function(item)"
|
||||
mat-menu-item>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
<ng-container *ngIf="item.link && item.externalLink && item.function && !item.disabled">
|
||||
<a
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[href]="item.link"
|
||||
[target]="item.target || '_self'"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)"
|
||||
mat-menu-item>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with a no link and no function -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
*ngIf="!item.link && !item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="!item.link && !item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item is disabled -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item fuse-horizontal-navigation-item-disabled"
|
||||
*ngIf="item.disabled">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="item.disabled">
|
||||
<div class="fuse-horizontal-navigation-item fuse-horizontal-navigation-item-disabled">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -75,11 +97,12 @@
|
||||
<ng-template #itemTemplate>
|
||||
|
||||
<!-- Icon -->
|
||||
<mat-icon
|
||||
class="fuse-horizontal-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
*ngIf="item.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-horizontal-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-horizontal-navigation-item-title-wrapper">
|
||||
@@ -88,24 +111,24 @@
|
||||
{{item.title}}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-subtitle text-hint"
|
||||
*ngIf="item.subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-horizontal-navigation-item-subtitle text-hint">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<!-- Badge -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge"
|
||||
*ngIf="item.badge">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
<ng-container *ngIf="item.badge">
|
||||
<div class="fuse-horizontal-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</ng-template>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { IsActiveMatchOptions } from '@angular/router';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -10,7 +9,6 @@ import { FuseUtilsService } from '@fuse/services/utils/utils.service';
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-basic-item',
|
||||
templateUrl : './basic.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseHorizontalNavigationBasicItemComponent implements OnInit, OnDestroy
|
||||
@@ -77,7 +75,7 @@ export class FuseHorizontalNavigationBasicItemComponent implements OnInit, OnDes
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,63 @@
|
||||
<div
|
||||
*ngIf="!child"
|
||||
[ngClass]="{'fuse-horizontal-navigation-menu-active': trigger.menuOpen,
|
||||
<ng-container *ngIf="!child">
|
||||
<div
|
||||
[ngClass]="{'fuse-horizontal-navigation-menu-active': trigger.menuOpen,
|
||||
'fuse-horizontal-navigation-menu-active-forced': item.active}"
|
||||
[matMenuTriggerFor]="matMenu"
|
||||
(onMenuOpen)="triggerChangeDetection()"
|
||||
(onMenuClose)="triggerChangeDetection()"
|
||||
#trigger="matMenuTrigger">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate; context: {$implicit: item}"></ng-container>
|
||||
</div>
|
||||
[matMenuTriggerFor]="matMenu"
|
||||
(onMenuOpen)="triggerChangeDetection()"
|
||||
(onMenuClose)="triggerChangeDetection()"
|
||||
#trigger="matMenuTrigger">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate; context: {$implicit: item}"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<mat-menu
|
||||
class="fuse-horizontal-navigation-menu-panel"
|
||||
[overlapTrigger]="false"
|
||||
#matMenu="matMenu">
|
||||
|
||||
<ng-container *ngFor="let item of item.children">
|
||||
<ng-container *ngFor="let item of item.children; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<!-- Basic -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
*ngIf="item.type === 'basic'"
|
||||
[disabled]="item.disabled"
|
||||
mat-menu-item>
|
||||
<fuse-horizontal-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-basic-item>
|
||||
</div>
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
[disabled]="item.disabled"
|
||||
mat-menu-item>
|
||||
<fuse-horizontal-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-basic-item>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Branch: aside, collapsable, group -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
*ngIf="item.type === 'aside' || item.type === 'collapsable' || item.type === 'group'"
|
||||
[disabled]="item.disabled"
|
||||
[matMenuTriggerFor]="branch.matMenu"
|
||||
mat-menu-item>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate; context: {$implicit: item}"></ng-container>
|
||||
<fuse-horizontal-navigation-branch-item
|
||||
[child]="true"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
#branch></fuse-horizontal-navigation-branch-item>
|
||||
</div>
|
||||
<ng-container *ngIf="item.type === 'aside' || item.type === 'collapsable' || item.type === 'group'">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
[disabled]="item.disabled"
|
||||
[matMenuTriggerFor]="branch.matMenu"
|
||||
mat-menu-item>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate; context: {$implicit: item}"></ng-container>
|
||||
<fuse-horizontal-navigation-branch-item
|
||||
[child]="true"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
#branch></fuse-horizontal-navigation-branch-item>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
*ngIf="item.type === 'divider'"
|
||||
mat-menu-item>
|
||||
<fuse-horizontal-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-divider-item>
|
||||
</div>
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
mat-menu-item>
|
||||
<fuse-horizontal-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-divider-item>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
@@ -74,14 +78,16 @@
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-disabled': item.disabled,
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active}">
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
|
||||
<!-- Icon -->
|
||||
<mat-icon
|
||||
class="fuse-horizontal-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
*ngIf="item.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-horizontal-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-horizontal-navigation-item-title-wrapper">
|
||||
@@ -90,25 +96,25 @@
|
||||
{{item.title}}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-subtitle text-hint"
|
||||
*ngIf="item.subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-horizontal-navigation-item-subtitle text-hint">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<!-- Badge -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge"
|
||||
*ngIf="item.badge">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
<ng-container *ngIf="item.badge">
|
||||
<div class="fuse-horizontal-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { MatMenu } from '@angular/material/menu';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -10,7 +9,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-branch-item',
|
||||
templateUrl : './branch.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDestroy
|
||||
@@ -65,7 +63,7 @@ export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDe
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
@@ -81,4 +79,15 @@ export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDe
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
/**
|
||||
* Track by function for ngFor loops
|
||||
*
|
||||
* @param index
|
||||
* @param item
|
||||
*/
|
||||
trackByFn(index: number, item: any): any
|
||||
{
|
||||
return item.id || index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -8,7 +7,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-divider-item',
|
||||
templateUrl : './divider.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseHorizontalNavigationDividerItemComponent implements OnInit, OnDestroy
|
||||
@@ -57,7 +55,7 @@ export class FuseHorizontalNavigationDividerItemComponent implements OnInit, OnD
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseHorizontalNavigationComponent } from '@fuse/components/navigation/horizontal/horizontal.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -8,7 +7,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-spacer-item',
|
||||
templateUrl : './spacer.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseHorizontalNavigationSpacerItemComponent implements OnInit, OnDestroy
|
||||
@@ -57,7 +55,7 @@ export class FuseHorizontalNavigationSpacerItemComponent implements OnInit, OnDe
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
<div class="fuse-horizontal-navigation-wrapper">
|
||||
|
||||
<ng-container *ngFor="let item of navigation">
|
||||
<ng-container *ngFor="let item of navigation; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<!-- Basic -->
|
||||
<fuse-horizontal-navigation-basic-item
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
*ngIf="item.type === 'basic'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-basic-item>
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-horizontal-navigation-basic-item
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Branch: aside, collapsable, group -->
|
||||
<fuse-horizontal-navigation-branch-item
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
*ngIf="item.type === 'aside' || item.type === 'collapsable' || item.type === 'group'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-branch-item>
|
||||
<ng-container *ngIf="item.type === 'aside' || item.type === 'collapsable' || item.type === 'group'">
|
||||
<fuse-horizontal-navigation-branch-item
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-branch-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<fuse-horizontal-navigation-spacer-item
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
*ngIf="item.type === 'spacer'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-spacer-item>
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-horizontal-navigation-spacer-item
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ export class FuseHorizontalNavigationComponent implements OnChanges, OnInit, OnD
|
||||
this._fuseNavigationService.deregisterComponent(this.name);
|
||||
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsActiveMatchOptions } from '@angular/router';
|
||||
import { IsActiveMatchOptions, Params, QueryParamsHandling } from '@angular/router';
|
||||
|
||||
export interface FuseNavigationItem
|
||||
{
|
||||
@@ -15,8 +15,19 @@ export interface FuseNavigationItem
|
||||
hidden?: (item: FuseNavigationItem) => boolean;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
tooltip?: string;
|
||||
link?: string;
|
||||
fragment?: string;
|
||||
preserveFragment?: boolean;
|
||||
queryParams?: Params | null;
|
||||
queryParamsHandling?: QueryParamsHandling | null;
|
||||
externalLink?: boolean;
|
||||
target?:
|
||||
| '_blank'
|
||||
| '_self'
|
||||
| '_parent'
|
||||
| '_top'
|
||||
| string;
|
||||
exactMatch?: boolean;
|
||||
isActiveMatchOptions?: IsActiveMatchOptions;
|
||||
function?: (item: FuseNavigationItem) => void;
|
||||
|
||||
@@ -7,14 +7,16 @@
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active': active,
|
||||
'fuse-vertical-navigation-item-disabled': item.disabled,
|
||||
'fuse-vertical-navigation-item-active-forced': item.active}">
|
||||
'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
|
||||
<!-- Icon -->
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
*ngIf="item.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
@@ -23,25 +25,25 @@
|
||||
{{item.title}}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-subtitle"
|
||||
*ngIf="item.subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<!-- Badge -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge"
|
||||
*ngIf="item.badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
<ng-container *ngIf="item.badge">
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -57,35 +59,40 @@
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<!-- Basic -->
|
||||
<fuse-vertical-navigation-basic-item
|
||||
*ngIf="item.type === 'basic'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
*ngIf="item.type === 'collapsable'"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
<ng-container *ngIf="item.type === 'collapsable'">
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<fuse-vertical-navigation-divider-item
|
||||
*ngIf="item.type === 'divider'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
<fuse-vertical-navigation-group-item
|
||||
*ngIf="item.type === 'group'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
<ng-container *ngIf="item.type === 'group'">
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
*ngIf="item.type === 'spacer'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { Subject } from 'rxjs';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -10,7 +9,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-aside-item',
|
||||
templateUrl : './aside.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnInit, OnDestroy
|
||||
@@ -99,7 +97,7 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,68 +5,92 @@
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
<!-- Item with an internal link -->
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
*ngIf="item.link && !item.externalLink && !item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
<ng-container *ngIf="item.link && !item.externalLink && !item.function && !item.disabled">
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
[queryParams]="item.queryParams ?? null"
|
||||
[queryParamsHandling]="item.queryParamsHandling ?? null"
|
||||
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link -->
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
*ngIf="item.link && item.externalLink && !item.function && !item.disabled"
|
||||
[href]="item.link">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
<ng-container *ngIf="item.link && item.externalLink && !item.function && !item.disabled">
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
[href]="item.link"
|
||||
[target]="item.target || '_self'"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with a function -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item"
|
||||
*ngIf="!item.link && item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="!item.link && item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an internal link and function -->
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
*ngIf="item.link && !item.externalLink && item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
<ng-container *ngIf="item.link && !item.externalLink && item.function && !item.disabled">
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
[queryParams]="item.queryParams ?? null"
|
||||
[queryParamsHandling]="item.queryParamsHandling ?? null"
|
||||
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link and function -->
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
*ngIf="item.link && item.externalLink && item.function && !item.disabled"
|
||||
[href]="item.link"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
<ng-container *ngIf="item.link && item.externalLink && item.function && !item.disabled">
|
||||
<a
|
||||
class="fuse-vertical-navigation-item"
|
||||
[href]="item.link"
|
||||
[target]="item.target || '_self'"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with a no link and no function -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item"
|
||||
*ngIf="!item.link && !item.function && !item.disabled"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="!item.link && !item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item is disabled -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item fuse-vertical-navigation-item-disabled"
|
||||
*ngIf="item.disabled">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="item.disabled">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item fuse-vertical-navigation-item-disabled"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -74,11 +98,12 @@
|
||||
<ng-template #itemTemplate>
|
||||
|
||||
<!-- Icon -->
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
*ngIf="item.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
@@ -87,24 +112,24 @@
|
||||
{{item.title}}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-subtitle"
|
||||
*ngIf="item.subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<!-- Badge -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge"
|
||||
*ngIf="item.badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
<ng-container *ngIf="item.badge">
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</ng-template>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { IsActiveMatchOptions } from '@angular/router';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -10,7 +9,6 @@ import { FuseUtilsService } from '@fuse/services/utils/utils.service';
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-basic-item',
|
||||
templateUrl : './basic.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseVerticalNavigationBasicItemComponent implements OnInit, OnDestroy
|
||||
@@ -77,7 +75,7 @@ export class FuseVerticalNavigationBasicItemComponent implements OnInit, OnDestr
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,16 @@
|
||||
<div
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-disabled': item.disabled}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="toggleCollapsable()">
|
||||
|
||||
<!-- Icon -->
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
*ngIf="item.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
@@ -22,25 +24,25 @@
|
||||
{{item.title}}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-subtitle"
|
||||
*ngIf="item.subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<!-- Badge -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge"
|
||||
*ngIf="item.badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
<ng-container *ngIf="item.badge">
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Arrow -->
|
||||
<mat-icon
|
||||
@@ -62,35 +64,40 @@
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<!-- Basic -->
|
||||
<fuse-vertical-navigation-basic-item
|
||||
*ngIf="item.type === 'basic'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
*ngIf="item.type === 'collapsable'"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
<ng-container *ngIf="item.type === 'collapsable'">
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<fuse-vertical-navigation-divider-item
|
||||
*ngIf="item.type === 'divider'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
<fuse-vertical-navigation-group-item
|
||||
*ngIf="item.type === 'group'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
<ng-container *ngIf="item.type === 'group'">
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
*ngIf="item.type === 'spacer'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { Subject } from 'rxjs';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
@@ -11,7 +10,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-collapsable-item',
|
||||
templateUrl : './collapsable.component.html',
|
||||
styles : [],
|
||||
animations : fuseAnimations,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
@@ -50,10 +48,12 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
return {
|
||||
'fuse-vertical-navigation-item-collapsed': this.isCollapsed,
|
||||
'fuse-vertical-navigation-item-expanded' : this.isExpanded
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@@ -177,7 +177,7 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -8,7 +7,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-divider-item',
|
||||
templateUrl : './divider.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseVerticalNavigationDividerItemComponent implements OnInit, OnDestroy
|
||||
@@ -57,7 +55,7 @@ export class FuseVerticalNavigationDividerItemComponent implements OnInit, OnDes
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
<div class="fuse-vertical-navigation-item">
|
||||
|
||||
<!-- Icon -->
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
*ngIf="item.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
@@ -20,25 +21,25 @@
|
||||
{{item.title}}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-subtitle"
|
||||
*ngIf="item.subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<!-- Badge -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge"
|
||||
*ngIf="item.badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
<ng-container *ngIf="item.badge">
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -50,35 +51,40 @@
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<!-- Basic -->
|
||||
<fuse-vertical-navigation-basic-item
|
||||
*ngIf="item.type === 'basic'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
*ngIf="item.type === 'collapsable'"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
<ng-container *ngIf="item.type === 'collapsable'">
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<fuse-vertical-navigation-divider-item
|
||||
*ngIf="item.type === 'divider'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
<fuse-vertical-navigation-group-item
|
||||
*ngIf="item.type === 'group'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
<ng-container *ngIf="item.type === 'group'">
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
*ngIf="item.type === 'spacer'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -9,7 +8,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-group-item',
|
||||
templateUrl : './group.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseVerticalNavigationGroupItemComponent implements OnInit, OnDestroy
|
||||
@@ -63,7 +61,7 @@ export class FuseVerticalNavigationGroupItemComponent implements OnInit, OnDestr
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Subject } from 'rxjs';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@@ -8,7 +7,6 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-spacer-item',
|
||||
templateUrl : './spacer.component.html',
|
||||
styles : [],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class FuseVerticalNavigationSpacerItemComponent implements OnInit, OnDestroy
|
||||
@@ -57,7 +55,7 @@ export class FuseVerticalNavigationSpacerItemComponent implements OnInit, OnDest
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
/* Variables */
|
||||
$fuse-vertical-navigation-compact-width: 112;
|
||||
:root {
|
||||
--fuse-vertical-navigation-compact-width: 112px;
|
||||
}
|
||||
|
||||
fuse-vertical-navigation {
|
||||
|
||||
/* Compact appearance overrides */
|
||||
&.fuse-vertical-navigation-appearance-compact {
|
||||
width: #{$fuse-vertical-navigation-compact-width}px;
|
||||
min-width: #{$fuse-vertical-navigation-compact-width}px;
|
||||
max-width: #{$fuse-vertical-navigation-compact-width}px;
|
||||
width: var(--fuse-vertical-navigation-compact-width);
|
||||
min-width: var(--fuse-vertical-navigation-compact-width);
|
||||
max-width: var(--fuse-vertical-navigation-compact-width);
|
||||
|
||||
/* Left positioned */
|
||||
&.fuse-vertical-navigation-position-left {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: -#{$fuse-vertical-navigation-compact-width}px;
|
||||
margin-left: calc(var(--fuse-vertical-navigation-compact-width) * -1);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@@ -28,7 +30,7 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: -#{$fuse-vertical-navigation-compact-width}px;
|
||||
margin-right: calc(var(--fuse-vertical-navigation-compact-width) * -1);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@@ -39,7 +41,7 @@ fuse-vertical-navigation {
|
||||
/* Aside wrapper */
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: auto;
|
||||
right: #{$fuse-vertical-navigation-compact-width}px;
|
||||
right: var(--fuse-vertical-navigation-compact-width);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +106,7 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Aside wrapper */
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: #{$fuse-vertical-navigation-compact-width}px;
|
||||
left: var(--fuse-vertical-navigation-compact-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/* Variables */
|
||||
$fuse-vertical-navigation-width: 280;
|
||||
:root {
|
||||
--fuse-vertical-navigation-width: 280px;
|
||||
}
|
||||
|
||||
fuse-vertical-navigation {
|
||||
position: sticky;
|
||||
@@ -7,9 +9,9 @@ fuse-vertical-navigation {
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
top: 0;
|
||||
width: #{$fuse-vertical-navigation-width}px;
|
||||
min-width: #{$fuse-vertical-navigation-width}px;
|
||||
max-width: #{$fuse-vertical-navigation-width}px;
|
||||
width: var(--fuse-vertical-navigation-width);
|
||||
min-width: var(--fuse-vertical-navigation-width);
|
||||
max-width: var(--fuse-vertical-navigation-width);
|
||||
height: 100vh;
|
||||
min-height: 100vh;
|
||||
max-height: 100vh;
|
||||
@@ -45,7 +47,7 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: -#{$fuse-vertical-navigation-width}px;
|
||||
margin-left: calc(#{var(--fuse-vertical-navigation-width)} * -1);
|
||||
|
||||
&.fuse-vertical-navigation-opened {
|
||||
margin-left: 0;
|
||||
@@ -73,7 +75,7 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: -#{$fuse-vertical-navigation-width}px;
|
||||
margin-right: calc(var(--fuse-vertical-navigation-width) * -1);
|
||||
|
||||
&.fuse-vertical-navigation-opened {
|
||||
margin-right: 0;
|
||||
@@ -170,8 +172,8 @@ fuse-vertical-navigation {
|
||||
flex-direction: column;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: #{$fuse-vertical-navigation-width}px;
|
||||
width: #{$fuse-vertical-navigation-width}px;
|
||||
left: var(--fuse-vertical-navigation-width);
|
||||
width: var(--fuse-vertical-navigation-width);
|
||||
height: 100%;
|
||||
z-index: 5;
|
||||
overflow-x: hidden;
|
||||
@@ -196,7 +198,7 @@ fuse-vertical-navigation {
|
||||
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: auto;
|
||||
right: #{$fuse-vertical-navigation-width}px;
|
||||
right: var(--fuse-vertical-navigation-width);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,6 +338,10 @@ fuse-vertical-navigation {
|
||||
|
||||
> .fuse-vertical-navigation-item-children {
|
||||
|
||||
> *:first-child {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
> *:last-child {
|
||||
padding-bottom: 6px;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* Variables */
|
||||
$fuse-vertical-navigation-width: 280;
|
||||
$fuse-vertical-navigation-dense-width: 80;
|
||||
:root {
|
||||
--fuse-vertical-navigation-width: 280px;
|
||||
--fuse-vertical-navigation-dense-width: 80px;
|
||||
}
|
||||
|
||||
fuse-vertical-navigation {
|
||||
|
||||
@@ -8,16 +10,16 @@ fuse-vertical-navigation {
|
||||
&.fuse-vertical-navigation-appearance-dense {
|
||||
|
||||
&:not(.fuse-vertical-navigation-mode-over) {
|
||||
width: #{$fuse-vertical-navigation-dense-width}px;
|
||||
min-width: #{$fuse-vertical-navigation-dense-width}px;
|
||||
max-width: #{$fuse-vertical-navigation-dense-width}px;
|
||||
width: var(--fuse-vertical-navigation-dense-width);
|
||||
min-width: var(--fuse-vertical-navigation-dense-width);
|
||||
max-width: var(--fuse-vertical-navigation-dense-width);
|
||||
|
||||
/* Left positioned */
|
||||
&.fuse-vertical-navigation-position-left {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: -#{$fuse-vertical-navigation-dense-width}px;
|
||||
margin-left: calc(var(--fuse-vertical-navigation-dense-width) * -1);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@@ -31,7 +33,7 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: -#{$fuse-vertical-navigation-dense-width}px;
|
||||
margin-right: calc(var(--fuse-vertical-navigation-dense-width) * -1);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@@ -42,14 +44,14 @@ fuse-vertical-navigation {
|
||||
/* Aside wrapper */
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: auto;
|
||||
right: #{$fuse-vertical-navigation-dense-width}px;
|
||||
right: var(--fuse-vertical-navigation-dense-width);
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-hover {
|
||||
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: auto;
|
||||
right: #{$fuse-vertical-navigation-width}px;
|
||||
right: var(--fuse-vertical-navigation-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,9 +71,9 @@ fuse-vertical-navigation {
|
||||
.fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
width: #{$fuse-vertical-navigation-width}px - 24px;
|
||||
min-width: #{$fuse-vertical-navigation-width}px - 24px;
|
||||
max-width: #{$fuse-vertical-navigation-width}px - 24px;
|
||||
width: calc(var(--fuse-vertical-navigation-dense-width) - 24px);
|
||||
min-width: calc(var(--fuse-vertical-navigation-dense-width) - 24px);
|
||||
max-width: calc(var(--fuse-vertical-navigation-dense-width) - 24px);
|
||||
|
||||
.fuse-vertical-navigation-item-arrow,
|
||||
.fuse-vertical-navigation-item-badge,
|
||||
@@ -142,20 +144,23 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Aside wrapper */
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: #{$fuse-vertical-navigation-dense-width}px;
|
||||
left: var(--fuse-vertical-navigation-dense-width);
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
&.fuse-vertical-navigation-hover {
|
||||
|
||||
.fuse-vertical-navigation-wrapper {
|
||||
width: #{$fuse-vertical-navigation-width}px;
|
||||
width: var(--fuse-vertical-navigation-width);
|
||||
|
||||
.fuse-vertical-navigation-content {
|
||||
|
||||
.fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
width: calc(var(--fuse-vertical-navigation-width) - 24px);
|
||||
min-width: calc(var(--fuse-vertical-navigation-width) - 24px);
|
||||
max-width: calc(var(--fuse-vertical-navigation-width) - 24px);
|
||||
|
||||
.fuse-vertical-navigation-item-arrow,
|
||||
.fuse-vertical-navigation-item-badge,
|
||||
@@ -170,7 +175,7 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: #{$fuse-vertical-navigation-width}px;
|
||||
left: var(--fuse-vertical-navigation-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
/* Variables */
|
||||
$fuse-vertical-navigation-thin-width: 80;
|
||||
:root {
|
||||
--fuse-vertical-navigation-thin-width: 80px;
|
||||
}
|
||||
|
||||
fuse-vertical-navigation {
|
||||
|
||||
/* Thin appearance overrides */
|
||||
&.fuse-vertical-navigation-appearance-thin {
|
||||
width: #{$fuse-vertical-navigation-thin-width}px;
|
||||
min-width: #{$fuse-vertical-navigation-thin-width}px;
|
||||
max-width: #{$fuse-vertical-navigation-thin-width}px;
|
||||
width: var(--fuse-vertical-navigation-thin-width);
|
||||
min-width: var(--fuse-vertical-navigation-thin-width);
|
||||
max-width: var(--fuse-vertical-navigation-thin-width);
|
||||
|
||||
/* Left positioned */
|
||||
&.fuse-vertical-navigation-position-left {
|
||||
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: -#{$fuse-vertical-navigation-thin-width}px;
|
||||
margin-left: calc(var(--fuse-vertical-navigation-thin-width) * -1);
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-opened {
|
||||
@@ -25,7 +27,7 @@ fuse-vertical-navigation {
|
||||
&.fuse-vertical-navigation-position-right {
|
||||
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: -#{$fuse-vertical-navigation-thin-width}px;
|
||||
margin-right: calc(var(--fuse-vertical-navigation-thin-width) * -1);
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-opened {
|
||||
@@ -34,7 +36,7 @@ fuse-vertical-navigation {
|
||||
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: auto;
|
||||
right: #{$fuse-vertical-navigation-thin-width}px;
|
||||
right: var(--fuse-vertical-navigation-thin-width);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +93,7 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Aside wrapper */
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: #{$fuse-vertical-navigation-thin-width}px;
|
||||
left: var(--fuse-vertical-navigation-thin-width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,46 +24,52 @@
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<!-- Aside -->
|
||||
<fuse-vertical-navigation-aside-item
|
||||
*ngIf="item.type === 'aside'"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[activeItemId]="activeAsideItemId"
|
||||
[autoCollapse]="autoCollapse"
|
||||
[skipChildren]="true"
|
||||
(click)="toggleAside(item)"></fuse-vertical-navigation-aside-item>
|
||||
<ng-container *ngIf="item.type === 'aside'">
|
||||
<fuse-vertical-navigation-aside-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[activeItemId]="activeAsideItemId"
|
||||
[autoCollapse]="autoCollapse"
|
||||
[skipChildren]="true"
|
||||
(click)="toggleAside(item)"></fuse-vertical-navigation-aside-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Basic -->
|
||||
<fuse-vertical-navigation-basic-item
|
||||
*ngIf="item.type === 'basic'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
*ngIf="item.type === 'collapsable'"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
<ng-container *ngIf="item.type === 'collapsable'">
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<fuse-vertical-navigation-divider-item
|
||||
*ngIf="item.type === 'divider'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
<fuse-vertical-navigation-group-item
|
||||
*ngIf="item.type === 'group'"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-group-item>
|
||||
<ng-container *ngIf="item.type === 'group'">
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
*ngIf="item.type === 'spacer'"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
@@ -84,31 +90,33 @@
|
||||
</div>
|
||||
|
||||
<!-- Aside -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-aside-wrapper"
|
||||
*ngIf="activeAsideItemId"
|
||||
fuseScrollbar
|
||||
[fuseScrollbarOptions]="{wheelPropagation: false, suppressScrollX: true}"
|
||||
[@fadeInLeft]="position === 'left'"
|
||||
[@fadeInRight]="position === 'right'"
|
||||
[@fadeOutLeft]="position === 'left'"
|
||||
[@fadeOutRight]="position === 'right'">
|
||||
<ng-container *ngIf="activeAsideItemId">
|
||||
<div
|
||||
class="fuse-vertical-navigation-aside-wrapper"
|
||||
fuseScrollbar
|
||||
[fuseScrollbarOptions]="{wheelPropagation: false, suppressScrollX: true}"
|
||||
[@fadeInLeft]="position === 'left'"
|
||||
[@fadeInRight]="position === 'right'"
|
||||
[@fadeOutLeft]="position === 'left'"
|
||||
[@fadeOutRight]="position === 'right'">
|
||||
|
||||
<!-- Items -->
|
||||
<ng-container *ngFor="let item of navigation; trackBy: trackByFn">
|
||||
<!-- Items -->
|
||||
<ng-container *ngFor="let item of navigation; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<!-- Aside -->
|
||||
<fuse-vertical-navigation-aside-item
|
||||
*ngIf="item.type === 'aside' && item.id === activeAsideItemId"
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-aside-item>
|
||||
<!-- Aside -->
|
||||
<ng-container *ngIf="item.type === 'aside' && item.id === activeAsideItemId">
|
||||
<fuse-vertical-navigation-aside-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-aside-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@import 'styles/appearances/default';
|
||||
@import 'styles/appearances/compact';
|
||||
@import 'styles/appearances/dense';
|
||||
@import 'styles/appearances/thin';
|
||||
@use 'styles/appearances/default';
|
||||
@use 'styles/appearances/compact';
|
||||
@use 'styles/appearances/dense';
|
||||
@use 'styles/appearances/thin';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, Input, OnChanges, OnDestroy, OnInit, Output, QueryList, Renderer2, SimpleChanges, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, HostListener, Inject, Input, OnChanges, OnDestroy, OnInit, Output, QueryList, Renderer2, SimpleChanges, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
|
||||
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { ScrollStrategy, ScrollStrategyOptions } from '@angular/cdk/overlay';
|
||||
import { merge, ReplaySubject, Subject, Subscription } from 'rxjs';
|
||||
import { delay, filter, takeUntil } from 'rxjs/operators';
|
||||
import { delay, filter, merge, ReplaySubject, Subject, Subscription, takeUntil } from 'rxjs';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
import { FuseNavigationItem, FuseVerticalNavigationAppearance, FuseVerticalNavigationMode, FuseVerticalNavigationPosition } from '@fuse/components/navigation/navigation.types';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
@@ -52,6 +52,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
private readonly _handleAsideOverlayClick: any;
|
||||
private readonly _handleOverlayClick: any;
|
||||
private _hovered: boolean = false;
|
||||
private _mutationObserver: MutationObserver;
|
||||
private _overlay: HTMLElement;
|
||||
private _player: AnimationPlayer;
|
||||
private _scrollStrategy: ScrollStrategy = this._scrollStrategyOptions.block();
|
||||
@@ -65,6 +66,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
constructor(
|
||||
private _animationBuilder: AnimationBuilder,
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
@Inject(DOCUMENT) private _document: Document,
|
||||
private _elementRef: ElementRef,
|
||||
private _renderer2: Renderer2,
|
||||
private _router: Router,
|
||||
@@ -90,6 +92,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
return {
|
||||
'fuse-vertical-navigation-animations-enabled' : this._animationsEnabled,
|
||||
[`fuse-vertical-navigation-appearance-${this.appearance}`]: true,
|
||||
@@ -101,6 +104,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
'fuse-vertical-navigation-position-left' : this.position === 'left',
|
||||
'fuse-vertical-navigation-position-right' : this.position === 'right'
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,6 +333,34 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*/
|
||||
ngAfterViewInit(): void
|
||||
{
|
||||
// Fix for Firefox.
|
||||
//
|
||||
// Because 'position: sticky' doesn't work correctly inside a 'position: fixed' parent,
|
||||
// adding the '.cdk-global-scrollblock' to the html element breaks the navigation's position.
|
||||
// This fixes the problem by reading the 'top' value from the html element and adding it as a
|
||||
// 'marginTop' to the navigation itself.
|
||||
this._mutationObserver = new MutationObserver((mutations) => {
|
||||
mutations.forEach((mutation) => {
|
||||
const mutationTarget = mutation.target as HTMLElement;
|
||||
if ( mutation.attributeName === 'class' )
|
||||
{
|
||||
if ( mutationTarget.classList.contains('cdk-global-scrollblock') )
|
||||
{
|
||||
const top = parseInt(mutationTarget.style.top, 10);
|
||||
this._renderer2.setStyle(this._elementRef.nativeElement, 'margin-top', `${Math.abs(top)}px`);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._renderer2.setStyle(this._elementRef.nativeElement, 'margin-top', null);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
this._mutationObserver.observe(this._document.documentElement, {
|
||||
attributes : true,
|
||||
attributeFilter: ['class']
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
// Return if 'navigation content' element does not exist
|
||||
@@ -374,11 +406,18 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Disconnect the mutation observer
|
||||
this._mutationObserver.disconnect();
|
||||
|
||||
// Forcefully close the navigation and aside in case they are opened
|
||||
this.close();
|
||||
this.closeAside();
|
||||
|
||||
// Deregister the navigation component from the registry
|
||||
this._fuseNavigationService.deregisterComponent(this.name);
|
||||
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
import { ChangeDetectorRef, Directive, ElementRef, HostBinding, HostListener, Input, NgZone, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
@Directive({
|
||||
selector: 'textarea[fuseAutogrow]',
|
||||
exportAs: 'fuseAutogrow'
|
||||
})
|
||||
export class FuseAutogrowDirective implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
// eslint-disable-next-line @angular-eslint/no-input-rename
|
||||
@Input('fuseAutogrowVerticalPadding') padding: number = 8;
|
||||
@HostBinding('rows') private _rows: number = 1;
|
||||
|
||||
private _height: string = 'auto';
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(
|
||||
private _elementRef: ElementRef,
|
||||
private _changeDetectorRef: ChangeDetectorRef,
|
||||
private _ngZone: NgZone
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Accessors
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Host binding for component inline styles
|
||||
*/
|
||||
@HostBinding('style') get styleList(): any
|
||||
{
|
||||
return {
|
||||
'height' : this._height,
|
||||
'overflow': 'hidden',
|
||||
'resize' : 'none'
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Decorated methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Resize on 'input' and 'ngModelChange' events
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
@HostListener('input')
|
||||
@HostListener('ngModelChange')
|
||||
private _resize(): void
|
||||
{
|
||||
// This doesn't need to trigger Angular's change detection by itself
|
||||
this._ngZone.runOutsideAngular(() => {
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
// Set the height to 'auto' so we can correctly read the scrollHeight
|
||||
this._height = 'auto';
|
||||
|
||||
// Detect the changes so the height is applied
|
||||
this._changeDetectorRef.detectChanges();
|
||||
|
||||
// Get the scrollHeight and subtract the vertical padding
|
||||
this._height = `${this._elementRef.nativeElement.scrollHeight - this.padding}px`;
|
||||
|
||||
// Detect the changes one more time to apply the final height
|
||||
this._changeDetectorRef.detectChanges();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Lifecycle hooks
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* On changes
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
// Padding
|
||||
if ( 'fuseAutogrowVerticalPadding' in changes )
|
||||
{
|
||||
// Resize
|
||||
this._resize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
// Resize for the first time
|
||||
this._resize();
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FuseAutogrowDirective } from '@fuse/directives/autogrow/autogrow.directive';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
FuseAutogrowDirective
|
||||
],
|
||||
exports : [
|
||||
FuseAutogrowDirective
|
||||
]
|
||||
})
|
||||
export class FuseAutogrowModule
|
||||
{
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from '@fuse/directives/autogrow/public-api';
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from '@fuse/directives/autogrow/autogrow.directive';
|
||||
export * from '@fuse/directives/autogrow/autogrow.module';
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Directive, ElementRef, OnDestroy, OnInit } from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { Subject } from 'rxjs';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Directive({
|
||||
selector: '[fuseScrollReset]',
|
||||
@@ -47,7 +46,7 @@ export class FuseScrollResetDirective implements OnInit, OnDestroy
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@ import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChang
|
||||
import { Router } from '@angular/router';
|
||||
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { Platform } from '@angular/cdk/platform';
|
||||
import { fromEvent, Subject } from 'rxjs';
|
||||
import { debounceTime, takeUntil } from 'rxjs/operators';
|
||||
import { debounceTime, fromEvent, Subject, takeUntil } from 'rxjs';
|
||||
import PerfectScrollbar from 'perfect-scrollbar';
|
||||
import { merge } from 'lodash-es';
|
||||
import { ScrollbarGeometry, ScrollbarPosition } from '@fuse/directives/scrollbar/scrollbar.types';
|
||||
@@ -138,7 +137,7 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
this._destroy();
|
||||
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next();
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,32 @@
|
||||
import { NgModule, Optional, SkipSelf } from '@angular/core';
|
||||
import { MATERIAL_SANITY_CHECKS } from '@angular/material/core';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
import { FuseConfirmationModule } from '@fuse/services/confirmation';
|
||||
import { FuseLoadingModule } from '@fuse/services/loading';
|
||||
import { FuseMediaWatcherModule } from '@fuse/services/media-watcher/media-watcher.module';
|
||||
import { FusePlatformModule } from '@fuse/services/platform/platform.module';
|
||||
import { FuseSplashScreenModule } from '@fuse/services/splash-screen/splash-screen.module';
|
||||
import { FuseTailwindConfigModule } from '@fuse/services/tailwind/tailwind.module';
|
||||
import { FuseUtilsModule } from '@fuse/services/utils/utils.module';
|
||||
|
||||
@NgModule({
|
||||
imports : [
|
||||
FuseConfirmationModule,
|
||||
FuseLoadingModule,
|
||||
FuseMediaWatcherModule,
|
||||
FusePlatformModule,
|
||||
FuseSplashScreenModule,
|
||||
FuseTailwindConfigModule,
|
||||
FuseUtilsModule
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
// Disable 'theme' sanity check
|
||||
provide : MATERIAL_SANITY_CHECKS,
|
||||
useValue: {
|
||||
doctype: true,
|
||||
theme : false,
|
||||
version: true
|
||||
}
|
||||
},
|
||||
{
|
||||
// Use the 'fill' appearance on Angular Material form fields by default
|
||||
provide : MAT_FORM_FIELD_DEFAULT_OPTIONS,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { delay, switchMap } from 'rxjs/operators';
|
||||
import { delay, Observable, of, switchMap, throwError } from 'rxjs';
|
||||
import { FUSE_MOCK_API_DEFAULT_DELAY } from '@fuse/lib/mock-api/mock-api.constants';
|
||||
import { FuseMockApiService } from '@fuse/lib/mock-api/mock-api.service';
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { HttpRequest } from '@angular/common/http';
|
||||
import { Observable, of, throwError } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { Observable, of, take, throwError } from 'rxjs';
|
||||
import { FuseMockApiReplyCallback } from '@fuse/lib/mock-api/mock-api.types';
|
||||
|
||||
export class FuseMockApiHandler
|
||||
|
||||
@@ -9,11 +9,14 @@ import { FuseMockApiMethods } from '@fuse/lib/mock-api/mock-api.types';
|
||||
export class FuseMockApiService
|
||||
{
|
||||
private _handlers: { [key: string]: Map<string, FuseMockApiHandler> } = {
|
||||
'delete': new Map<string, FuseMockApiHandler>(),
|
||||
'get' : new Map<string, FuseMockApiHandler>(),
|
||||
'patch' : new Map<string, FuseMockApiHandler>(),
|
||||
'post' : new Map<string, FuseMockApiHandler>(),
|
||||
'put' : new Map<string, FuseMockApiHandler>()
|
||||
'get' : new Map<string, FuseMockApiHandler>(),
|
||||
'post' : new Map<string, FuseMockApiHandler>(),
|
||||
'patch' : new Map<string, FuseMockApiHandler>(),
|
||||
'delete' : new Map<string, FuseMockApiHandler>(),
|
||||
'put' : new Map<string, FuseMockApiHandler>(),
|
||||
'head' : new Map<string, FuseMockApiHandler>(),
|
||||
'jsonp' : new Map<string, FuseMockApiHandler>(),
|
||||
'options': new Map<string, FuseMockApiHandler>()
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -86,18 +89,7 @@ export class FuseMockApiService
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a DELETE request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onDelete(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
return this._registerHandler('delete', url, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a GET request handler
|
||||
* Register GET request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
@@ -108,18 +100,7 @@ export class FuseMockApiService
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a PATCH request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onPatch(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
return this._registerHandler('patch', url, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a POST request handler
|
||||
* Register POST request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
@@ -130,7 +111,29 @@ export class FuseMockApiService
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a PUT request handler
|
||||
* Register PATCH request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onPatch(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
return this._registerHandler('patch', url, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register DELETE request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onDelete(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
return this._registerHandler('delete', url, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register PUT request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
@@ -140,6 +143,39 @@ export class FuseMockApiService
|
||||
return this._registerHandler('put', url, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register HEAD request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onHead(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
return this._registerHandler('head', url, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register JSONP request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onJsonp(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
return this._registerHandler('jsonp', url, delay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register OPTIONS request handler
|
||||
*
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onOptions(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
return this._registerHandler('options', url, delay);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Private methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -8,6 +8,9 @@ export type FuseMockApiReplyCallback =
|
||||
export type FuseMockApiMethods =
|
||||
| 'get'
|
||||
| 'post'
|
||||
| 'put'
|
||||
| 'patch'
|
||||
| 'delete';
|
||||
| 'delete'
|
||||
| 'put'
|
||||
| 'head'
|
||||
| 'jsonp'
|
||||
| 'options';
|
||||
|
||||
@@ -35,6 +35,7 @@ export class FuseConfigService
|
||||
this._config.next(config);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/member-ordering
|
||||
get config$(): Observable<any>
|
||||
{
|
||||
return this._config.asObservable();
|
||||
|
||||
31
src/@fuse/services/confirmation/confirmation.module.ts
Normal file
31
src/@fuse/services/confirmation/confirmation.module.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { FuseConfirmationService } from '@fuse/services/confirmation/confirmation.service';
|
||||
import { FuseConfirmationDialogComponent } from '@fuse/services/confirmation/dialog/dialog.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
FuseConfirmationDialogComponent
|
||||
],
|
||||
imports : [
|
||||
MatButtonModule,
|
||||
MatDialogModule,
|
||||
MatIconModule,
|
||||
CommonModule
|
||||
],
|
||||
providers : [
|
||||
FuseConfirmationService
|
||||
]
|
||||
})
|
||||
export class FuseConfirmationModule
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(private _fuseConfirmationService: FuseConfirmationService)
|
||||
{
|
||||
}
|
||||
}
|
||||
58
src/@fuse/services/confirmation/confirmation.service.ts
Normal file
58
src/@fuse/services/confirmation/confirmation.service.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import { merge } from 'lodash-es';
|
||||
import { FuseConfirmationDialogComponent } from '@fuse/services/confirmation/dialog/dialog.component';
|
||||
import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation.types';
|
||||
|
||||
@Injectable()
|
||||
export class FuseConfirmationService
|
||||
{
|
||||
private _defaultConfig: FuseConfirmationConfig = {
|
||||
title : 'Confirm action',
|
||||
message : 'Are you sure you want to confirm this action?',
|
||||
icon : {
|
||||
show : true,
|
||||
name : 'heroicons_outline:exclamation',
|
||||
color: 'warn'
|
||||
},
|
||||
actions : {
|
||||
confirm: {
|
||||
show : true,
|
||||
label: 'Confirm',
|
||||
color: 'warn'
|
||||
},
|
||||
cancel : {
|
||||
show : true,
|
||||
label: 'Cancel'
|
||||
}
|
||||
},
|
||||
dismissible: false
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(
|
||||
private _matDialog: MatDialog
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
open(config: FuseConfirmationConfig = {}): MatDialogRef<FuseConfirmationDialogComponent>
|
||||
{
|
||||
// Merge the user config with the default config
|
||||
const userConfig = merge({}, this._defaultConfig, config);
|
||||
|
||||
// Open the dialog
|
||||
return this._matDialog.open(FuseConfirmationDialogComponent, {
|
||||
autoFocus : false,
|
||||
disableClose: !userConfig.dismissible,
|
||||
data : userConfig,
|
||||
panelClass : 'fuse-confirmation-dialog-panel'
|
||||
});
|
||||
}
|
||||
}
|
||||
22
src/@fuse/services/confirmation/confirmation.types.ts
Normal file
22
src/@fuse/services/confirmation/confirmation.types.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export interface FuseConfirmationConfig
|
||||
{
|
||||
title?: string;
|
||||
message?: string;
|
||||
icon?: {
|
||||
show?: boolean;
|
||||
name?: string;
|
||||
color?: 'primary' | 'accent' | 'warn' | 'basic' | 'info' | 'success' | 'warning' | 'error';
|
||||
};
|
||||
actions?: {
|
||||
confirm?: {
|
||||
show?: boolean;
|
||||
label?: string;
|
||||
color?: 'primary' | 'accent' | 'warn';
|
||||
};
|
||||
cancel?: {
|
||||
show?: boolean;
|
||||
label?: string;
|
||||
};
|
||||
};
|
||||
dismissible?: boolean;
|
||||
}
|
||||
85
src/@fuse/services/confirmation/dialog/dialog.component.html
Normal file
85
src/@fuse/services/confirmation/dialog/dialog.component.html
Normal file
@@ -0,0 +1,85 @@
|
||||
<div class="relative flex flex-col w-full h-full">
|
||||
|
||||
<!-- Dismiss button -->
|
||||
<ng-container *ngIf="data.dismissible">
|
||||
<div class="absolute top-0 right-0 pt-4 pr-4">
|
||||
<button
|
||||
mat-icon-button
|
||||
[matDialogClose]="undefined">
|
||||
<mat-icon
|
||||
class="text-secondary"
|
||||
[svgIcon]="'heroicons_outline:x'"></mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="flex flex-col sm:flex-row flex-auto items-center sm:items-start p-8 pb-6 sm:pb-8">
|
||||
|
||||
<!-- Icon -->
|
||||
<ng-container *ngIf="data.icon.show">
|
||||
<div
|
||||
class="flex flex-0 items-center justify-center w-10 h-10 sm:mr-4 rounded-full"
|
||||
[ngClass]="{'text-primary-600 bg-primary-100 dark:text-primary-50 dark:bg-primary-600': data.icon.color === 'primary',
|
||||
'text-accent-600 bg-accent-100 dark:text-accent-50 dark:bg-accent-600': data.icon.color === 'accent',
|
||||
'text-warn-600 bg-warn-100 dark:text-warn-50 dark:bg-warn-600': data.icon.color === 'warn',
|
||||
'text-gray-600 bg-gray-100 dark:text-gray-50 dark:bg-gray-600': data.icon.color === 'basic',
|
||||
'text-blue-600 bg-blue-100 dark:text-blue-50 dark:bg-blue-600': data.icon.color === 'info',
|
||||
'text-green-500 bg-green-100 dark:text-green-50 dark:bg-green-500': data.icon.color === 'success',
|
||||
'text-amber-500 bg-amber-100 dark:text-amber-50 dark:bg-amber-500': data.icon.color === 'warning',
|
||||
'text-red-600 bg-red-100 dark:text-red-50 dark:bg-red-600': data.icon.color === 'error'
|
||||
}">
|
||||
<mat-icon
|
||||
class="text-current"
|
||||
[svgIcon]="data.icon.name"></mat-icon>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="data.title || data.message">
|
||||
<div class="flex flex-col items-center sm:items-start mt-4 sm:mt-0 sm:pr-8 space-y-1 text-center sm:text-left">
|
||||
|
||||
<!-- Title -->
|
||||
<ng-container *ngIf="data.title">
|
||||
<div
|
||||
class="text-xl leading-6 font-medium"
|
||||
[innerHTML]="data.title"></div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Message -->
|
||||
<ng-container *ngIf="data.message">
|
||||
<div
|
||||
class="text-secondary"
|
||||
[innerHTML]="data.message"></div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<ng-container *ngIf="data.actions.confirm.show || data.actions.cancel.show">
|
||||
<div class="flex items-center justify-center sm:justify-end px-6 py-4 space-x-3 bg-gray-50 dark:bg-black dark:bg-opacity-10">
|
||||
|
||||
<!-- Cancel -->
|
||||
<ng-container *ngIf="data.actions.cancel.show">
|
||||
<button
|
||||
mat-stroked-button
|
||||
[matDialogClose]="'cancelled'">
|
||||
{{data.actions.cancel.label}}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
<!-- Confirm -->
|
||||
<ng-container *ngIf="data.actions.confirm.show">
|
||||
<button
|
||||
mat-flat-button
|
||||
[color]="data.actions.confirm.color"
|
||||
[matDialogClose]="'confirmed'">
|
||||
{{data.actions.confirm.label}}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
36
src/@fuse/services/confirmation/dialog/dialog.component.ts
Normal file
36
src/@fuse/services/confirmation/dialog/dialog.component.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Component, Inject, ViewEncapsulation } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation.types';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-confirmation-dialog',
|
||||
templateUrl : './dialog.component.html',
|
||||
styles : [
|
||||
`
|
||||
.fuse-confirmation-dialog-panel {
|
||||
|
||||
@screen md {
|
||||
@apply w-128;
|
||||
}
|
||||
|
||||
.mat-mdc-dialog-container {
|
||||
|
||||
.mat-mdc-dialog-surface {
|
||||
padding: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FuseConfirmationDialogComponent
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public data: FuseConfirmationConfig)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
1
src/@fuse/services/confirmation/index.ts
Normal file
1
src/@fuse/services/confirmation/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@fuse/services/confirmation/public-api';
|
||||
3
src/@fuse/services/confirmation/public-api.ts
Normal file
3
src/@fuse/services/confirmation/public-api.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from '@fuse/services/confirmation/confirmation.module';
|
||||
export * from '@fuse/services/confirmation/confirmation.service';
|
||||
export * from '@fuse/services/confirmation/confirmation.types';
|
||||
1
src/@fuse/services/loading/index.ts
Normal file
1
src/@fuse/services/loading/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@fuse/services/loading/public-api';
|
||||
48
src/@fuse/services/loading/loading.interceptor.ts
Normal file
48
src/@fuse/services/loading/loading.interceptor.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||
import { finalize, Observable } from 'rxjs';
|
||||
import { FuseLoadingService } from '@fuse/services/loading/loading.service';
|
||||
|
||||
@Injectable()
|
||||
export class FuseLoadingInterceptor implements HttpInterceptor
|
||||
{
|
||||
handleRequestsAutomatically: boolean;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(
|
||||
private _fuseLoadingService: FuseLoadingService
|
||||
)
|
||||
{
|
||||
// Subscribe to the auto
|
||||
this._fuseLoadingService.auto$
|
||||
.subscribe((value) => {
|
||||
this.handleRequestsAutomatically = value;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept
|
||||
*
|
||||
* @param req
|
||||
* @param next
|
||||
*/
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
|
||||
{
|
||||
// If the Auto mode is turned off, do nothing
|
||||
if ( !this.handleRequestsAutomatically )
|
||||
{
|
||||
return next.handle(req);
|
||||
}
|
||||
|
||||
// Set the loading status to true
|
||||
this._fuseLoadingService._setLoadingStatus(true, req.url);
|
||||
|
||||
return next.handle(req).pipe(
|
||||
finalize(() => {
|
||||
// Set the status to false if there are any errors or the request is completed
|
||||
this._fuseLoadingService._setLoadingStatus(false, req.url);
|
||||
}));
|
||||
}
|
||||
}
|
||||
16
src/@fuse/services/loading/loading.module.ts
Normal file
16
src/@fuse/services/loading/loading.module.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { FuseLoadingInterceptor } from '@fuse/services/loading/loading.interceptor';
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{
|
||||
provide : HTTP_INTERCEPTORS,
|
||||
useClass: FuseLoadingInterceptor,
|
||||
multi : true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class FuseLoadingModule
|
||||
{
|
||||
}
|
||||
146
src/@fuse/services/loading/loading.service.ts
Normal file
146
src/@fuse/services/loading/loading.service.ts
Normal file
@@ -0,0 +1,146 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FuseLoadingService
|
||||
{
|
||||
private _auto$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
|
||||
private _mode$: BehaviorSubject<'determinate' | 'indeterminate'> = new BehaviorSubject<'determinate' | 'indeterminate'>('indeterminate');
|
||||
private _progress$: BehaviorSubject<number | null> = new BehaviorSubject<number | null>(0);
|
||||
private _show$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
private _urlMap: Map<string, boolean> = new Map<string, boolean>();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(private _httpClient: HttpClient)
|
||||
{
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Accessors
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Getter for auto mode
|
||||
*/
|
||||
get auto$(): Observable<boolean>
|
||||
{
|
||||
return this._auto$.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for mode
|
||||
*/
|
||||
get mode$(): Observable<'determinate' | 'indeterminate'>
|
||||
{
|
||||
return this._mode$.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for progress
|
||||
*/
|
||||
get progress$(): Observable<number>
|
||||
{
|
||||
return this._progress$.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for show
|
||||
*/
|
||||
get show$(): Observable<boolean>
|
||||
{
|
||||
return this._show$.asObservable();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Show the loading bar
|
||||
*/
|
||||
show(): void
|
||||
{
|
||||
this._show$.next(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the loading bar
|
||||
*/
|
||||
hide(): void
|
||||
{
|
||||
this._show$.next(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the auto mode
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
setAutoMode(value: boolean): void
|
||||
{
|
||||
this._auto$.next(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
setMode(value: 'determinate' | 'indeterminate'): void
|
||||
{
|
||||
this._mode$.next(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the progress of the bar manually
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
setProgress(value: number): void
|
||||
{
|
||||
if ( value < 0 || value > 100 )
|
||||
{
|
||||
console.error('Progress value must be between 0 and 100!');
|
||||
return;
|
||||
}
|
||||
|
||||
this._progress$.next(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the loading status on the given url
|
||||
*
|
||||
* @param status
|
||||
* @param url
|
||||
*/
|
||||
_setLoadingStatus(status: boolean, url: string): void
|
||||
{
|
||||
// Return if the url was not provided
|
||||
if ( !url )
|
||||
{
|
||||
console.error('The request URL must be provided!');
|
||||
return;
|
||||
}
|
||||
|
||||
if ( status === true )
|
||||
{
|
||||
this._urlMap.set(url, status);
|
||||
this._show$.next(true);
|
||||
}
|
||||
else if ( status === false && this._urlMap.has(url) )
|
||||
{
|
||||
this._urlMap.delete(url);
|
||||
}
|
||||
|
||||
// Only set the status to 'false' if all outgoing requests are completed
|
||||
if ( this._urlMap.size === 0 )
|
||||
{
|
||||
this._show$.next(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
src/@fuse/services/loading/public-api.ts
Normal file
2
src/@fuse/services/loading/public-api.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from '@fuse/services/loading/loading.service';
|
||||
export * from '@fuse/services/loading/loading.module';
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
|
||||
import { Observable, ReplaySubject } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { FuseTailwindService } from '@fuse/services/tailwind/tailwind.service';
|
||||
import { map, Observable, ReplaySubject, switchMap } from 'rxjs';
|
||||
import { fromPairs } from 'lodash-es';
|
||||
import { FuseConfigService } from '@fuse/services/config';
|
||||
|
||||
@Injectable()
|
||||
export class FuseMediaWatcherService
|
||||
@@ -14,11 +14,12 @@ export class FuseMediaWatcherService
|
||||
*/
|
||||
constructor(
|
||||
private _breakpointObserver: BreakpointObserver,
|
||||
private _fuseTailwindConfigService: FuseTailwindService
|
||||
private _fuseConfigService: FuseConfigService
|
||||
)
|
||||
{
|
||||
this._fuseTailwindConfigService.tailwindConfig$.pipe(
|
||||
switchMap(config => this._breakpointObserver.observe(Object.values(config.breakpoints)).pipe(
|
||||
this._fuseConfigService.config$.pipe(
|
||||
map(config => fromPairs(Object.entries(config.screens).map(([alias, screen]) => ([alias, `(min-width: ${screen})`])))),
|
||||
switchMap(screens => this._breakpointObserver.observe(Object.values(screens)).pipe(
|
||||
map((state) => {
|
||||
|
||||
// Prepare the observable values and set their defaults
|
||||
@@ -30,7 +31,7 @@ export class FuseMediaWatcherService
|
||||
for ( const [query] of matchingBreakpoints )
|
||||
{
|
||||
// Find the alias of the matching query
|
||||
const matchingAlias = Object.entries(config.breakpoints).find(([alias, q]) => q === query)[0];
|
||||
const matchingAlias = Object.entries(screens).find(([alias, q]) => q === query)[0];
|
||||
|
||||
// Add the matching query to the observable values
|
||||
if ( matchingAlias )
|
||||
|
||||
1
src/@fuse/services/platform/index.ts
Normal file
1
src/@fuse/services/platform/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@fuse/services/platform/public-api';
|
||||
17
src/@fuse/services/platform/platform.module.ts
Normal file
17
src/@fuse/services/platform/platform.module.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FusePlatformService } from '@fuse/services/platform/platform.service';
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
FusePlatformService
|
||||
]
|
||||
})
|
||||
export class FusePlatformModule
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(private _fusePlatformService: FusePlatformService)
|
||||
{
|
||||
}
|
||||
}
|
||||
59
src/@fuse/services/platform/platform.service.ts
Normal file
59
src/@fuse/services/platform/platform.service.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Platform } from '@angular/cdk/platform';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FusePlatformService
|
||||
{
|
||||
osName = 'os-unknown';
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(private _platform: Platform)
|
||||
{
|
||||
// If the platform is not a browser, return immediately
|
||||
if ( !this._platform.isBrowser )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Windows
|
||||
if ( navigator.userAgent.includes('Win') )
|
||||
{
|
||||
this.osName = 'os-windows';
|
||||
}
|
||||
|
||||
// Mac OS
|
||||
if ( navigator.userAgent.includes('Mac') )
|
||||
{
|
||||
this.osName = 'os-mac';
|
||||
}
|
||||
|
||||
// Unix
|
||||
if ( navigator.userAgent.includes('X11') )
|
||||
{
|
||||
this.osName = 'os-unix';
|
||||
}
|
||||
|
||||
// Linux
|
||||
if ( navigator.userAgent.includes('Linux') )
|
||||
{
|
||||
this.osName = 'os-linux';
|
||||
}
|
||||
|
||||
// iOS
|
||||
if ( this._platform.IOS )
|
||||
{
|
||||
this.osName = 'os-ios';
|
||||
}
|
||||
|
||||
// Android
|
||||
if ( this._platform.ANDROID )
|
||||
{
|
||||
this.osName = 'os-android';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
1
src/@fuse/services/platform/public-api.ts
Normal file
1
src/@fuse/services/platform/public-api.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@fuse/services/platform/platform.service';
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { filter, take } from 'rxjs/operators';
|
||||
import { filter, take } from 'rxjs';
|
||||
|
||||
@Injectable()
|
||||
export class FuseSplashScreenService
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export * from '@fuse/services/tailwind/public-api';
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from '@fuse/services/tailwind/tailwind.module';
|
||||
export * from '@fuse/services/tailwind/tailwind.service';
|
||||
@@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FuseTailwindService } from '@fuse/services/tailwind/tailwind.service';
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
FuseTailwindService
|
||||
]
|
||||
})
|
||||
export class FuseTailwindConfigModule
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(private _fuseTailwindConfigService: FuseTailwindService)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, ReplaySubject } from 'rxjs';
|
||||
import { fromPairs, map } from 'lodash-es';
|
||||
import * as extractedTailwindConfigStyle from '@fuse/styles/core/tailwind-config.scss';
|
||||
|
||||
@Injectable()
|
||||
export class FuseTailwindService
|
||||
{
|
||||
private _tailwindConfig: ReplaySubject<any> = new ReplaySubject<any>(1);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor()
|
||||
{
|
||||
// Prepare the config object
|
||||
const config: any = {};
|
||||
|
||||
// Extract the style from the class
|
||||
const regexpForClass = /\.fuse-tailwind-extracted-config\s\{([\s\S]*)\}/g;
|
||||
const style = regexpForClass.exec(extractedTailwindConfigStyle.default)[1].trim();
|
||||
|
||||
// Extract the rules
|
||||
const regexp = /(--[\s\S]*?):'([\s\S]*?)';/g;
|
||||
let rules = regexp.exec(style);
|
||||
|
||||
// Add to the config
|
||||
while ( rules !== null )
|
||||
{
|
||||
const configGroup = /--([\s\S]*?)-/g.exec(rules[1])[1];
|
||||
if ( !config[configGroup] )
|
||||
{
|
||||
config[configGroup] = {};
|
||||
}
|
||||
|
||||
config[configGroup][rules[1].replace(/(--[\s\S]*?-)/g, '')] = rules[2];
|
||||
rules = regexp.exec(style);
|
||||
}
|
||||
|
||||
// Parse the themes objects
|
||||
config.themes = fromPairs(map(config.themes, (value, key) => [key, JSON.parse(value)]));
|
||||
|
||||
// Execute the observable with the config
|
||||
this._tailwindConfig.next(config);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Accessors
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Getter for _tailwindConfig
|
||||
*/
|
||||
get tailwindConfig$(): Observable<any>
|
||||
{
|
||||
return this._tailwindConfig.asObservable();
|
||||
}
|
||||
}
|
||||
@@ -20,22 +20,22 @@ textarea {
|
||||
}
|
||||
|
||||
&:-webkit-autofill {
|
||||
-webkit-transition: 'background-color 9999s ease-out';
|
||||
-webkit-transition-delay: 9999s;
|
||||
transition: background-color 600000s 0s, color 600000s 0s !important;
|
||||
}
|
||||
|
||||
&:-webkit-autofill:hover {
|
||||
-webkit-transition: 'background-color 9999s ease-out';
|
||||
-webkit-transition-delay: 9999s;
|
||||
transition: background-color 600000s 0s, color 600000s 0s !important;
|
||||
}
|
||||
|
||||
&:-webkit-autofill:focus {
|
||||
-webkit-transition: 'background-color 9999s ease-out';
|
||||
-webkit-transition-delay: 9999s;
|
||||
transition: background-color 600000s 0s, color 600000s 0s !important;
|
||||
}
|
||||
|
||||
&:-webkit-autofill:active {
|
||||
-webkit-transition: 'background-color 9999s ease-out';
|
||||
-webkit-transition-delay: 9999s;
|
||||
transition: background-color 600000s 0s, color 600000s 0s !important;
|
||||
}
|
||||
|
||||
[data-autocompleted] {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
/* ----------------------------------------------------------------------------------------------------- */
|
||||
/* @ Any configuration we need from Tailwind's config file will be extracted here so we can import this
|
||||
/* @ file from "config.ts" to access the extracted configuration from TypeScript
|
||||
/* ----------------------------------------------------------------------------------------------------- */
|
||||
@variants fuse-tailwind-extracted-config {
|
||||
}
|
||||
@@ -1,13 +1,9 @@
|
||||
/* 1. Core */
|
||||
@import 'core/tailwind-config';
|
||||
/* 1. Components */
|
||||
@use 'components/example-viewer';
|
||||
@use 'components/input';
|
||||
|
||||
/* 2. Components */
|
||||
@import 'components/example-viewer';
|
||||
@import 'components/input';
|
||||
|
||||
/* 3. Overrides */
|
||||
@import 'overrides/angular-material';
|
||||
@import 'overrides/fullcalendar';
|
||||
@import 'overrides/highlightjs';
|
||||
@import 'overrides/perfect-scrollbar';
|
||||
@import 'overrides/quill';
|
||||
/* 2. Overrides */
|
||||
@use 'overrides/angular-material';
|
||||
@use 'overrides/highlightjs';
|
||||
@use 'overrides/perfect-scrollbar';
|
||||
@use 'overrides/quill';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,680 +0,0 @@
|
||||
/* ----------------------------------------------------------------------------------------------------- */
|
||||
/* @ FullCalendar overrides
|
||||
/* ----------------------------------------------------------------------------------------------------- */
|
||||
.fc {
|
||||
|
||||
.fc-view-container {
|
||||
|
||||
/* Day Grid - Month view */
|
||||
.fc-view.fc-dayGridMonth-view {
|
||||
|
||||
.fc-head {
|
||||
|
||||
> tr > .fc-head-container {
|
||||
border: none;
|
||||
|
||||
.fc-row {
|
||||
|
||||
.fc-day-header {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-top: 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
@apply text-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-body {
|
||||
|
||||
> tr > .fc-widget-content {
|
||||
border: none;
|
||||
|
||||
.fc-day-grid {
|
||||
|
||||
.fc-week {
|
||||
|
||||
.fc-bg {
|
||||
|
||||
.fc-day {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
&.fc-today {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-content-skeleton {
|
||||
|
||||
.fc-day-top {
|
||||
text-align: center;
|
||||
|
||||
&.fc-other-month {
|
||||
opacity: 1;
|
||||
|
||||
.fc-day-number {
|
||||
@apply text-hint;
|
||||
}
|
||||
}
|
||||
|
||||
&.fc-today {
|
||||
|
||||
.fc-day-number {
|
||||
@apply bg-primary text-on-primary;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-day-number {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 21px;
|
||||
margin: 4px 0;
|
||||
font-size: 12px;
|
||||
border-radius: 50%;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-event-container {
|
||||
|
||||
.fc-day-grid-event {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
min-height: 22px;
|
||||
max-height: 22px;
|
||||
margin: 0 6px 4px 6px;
|
||||
padding: 0 5px;
|
||||
font-size: 12px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
@screen sm {
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-more {
|
||||
padding: 0 3px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
@apply text-secondary;
|
||||
|
||||
@screen sm {
|
||||
padding: 0 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-highlight-skeleton {
|
||||
|
||||
.fc-highlight {
|
||||
position: relative;
|
||||
opacity: 1;
|
||||
@apply bg-gray-100;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-popover {
|
||||
@apply bg-card;
|
||||
|
||||
&.fc-more-popover {
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
@apply shadow-2xl;
|
||||
|
||||
.fc-header {
|
||||
height: 32px;
|
||||
min-height: 32px;
|
||||
max-height: 32px;
|
||||
padding: 0 8px;
|
||||
@apply bg-hover;
|
||||
|
||||
.fc-title {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-body {
|
||||
max-height: 160px;
|
||||
overflow: hidden auto;
|
||||
|
||||
.fc-event-container {
|
||||
padding: 8px;
|
||||
|
||||
.fc-day-grid-event {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
min-height: 22px;
|
||||
max-height: 22px;
|
||||
margin: 0 0 6px 0;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Time Grid - Week view */
|
||||
.fc-view.fc-timeGridWeek-view {
|
||||
|
||||
.fc-head {
|
||||
|
||||
> tr > .fc-head-container {
|
||||
border: none;
|
||||
|
||||
.fc-row {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-day-header {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
@apply text-secondary;
|
||||
|
||||
&.fc-weekday {
|
||||
padding-top: 16px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.055em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&.fc-date {
|
||||
padding-bottom: 12px;
|
||||
font-size: 26px;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-body {
|
||||
|
||||
> tr > .fc-widget-content {
|
||||
border: none;
|
||||
|
||||
.fc-day-grid {
|
||||
|
||||
.fc-row {
|
||||
min-height: 0;
|
||||
|
||||
.fc-bg {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-day {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
&.fc-today {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-content-skeleton {
|
||||
padding-bottom: 0;
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
}
|
||||
|
||||
.fc-event-container {
|
||||
|
||||
.fc-day-grid-event {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
min-height: 22px;
|
||||
max-height: 22px;
|
||||
margin: 0 6px 6px 6px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-divider {
|
||||
border: none;
|
||||
background: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-time-grid {
|
||||
|
||||
.fc-bg {
|
||||
|
||||
.fc-axis {
|
||||
border: none;
|
||||
width: 48px !important;
|
||||
|
||||
+ .fc-day {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-day {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
&.fc-today {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-slats {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
height: 48px;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
width: 48px;
|
||||
min-width: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-time {
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-widget-content {
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
}
|
||||
|
||||
.fc-content-skeleton {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
}
|
||||
|
||||
.fc-event-container {
|
||||
margin: 0 12px 0 0;
|
||||
|
||||
.fc-time-grid-event {
|
||||
display: flex;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
.fc-time,
|
||||
.fc-title {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Time Grid - Day view */
|
||||
.fc-view.fc-timeGridDay-view {
|
||||
|
||||
.fc-head {
|
||||
|
||||
> tr > .fc-head-container {
|
||||
border: none;
|
||||
|
||||
.fc-row {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-day-header {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
@apply text-secondary;
|
||||
|
||||
&.fc-weekday {
|
||||
padding-top: 16px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.055em;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
&.fc-date {
|
||||
padding-bottom: 12px;
|
||||
font-size: 26px;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-body {
|
||||
|
||||
> tr > .fc-widget-content {
|
||||
border: none;
|
||||
|
||||
.fc-day-grid {
|
||||
|
||||
.fc-bg {
|
||||
|
||||
.fc-axis {
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-day {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
&.fc-today {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-row {
|
||||
min-height: 0;
|
||||
|
||||
.fc-bg {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-content-skeleton {
|
||||
padding-bottom: 0;
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
}
|
||||
|
||||
.fc-event-container {
|
||||
|
||||
.fc-day-grid-event {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
min-height: 22px;
|
||||
max-height: 22px;
|
||||
margin: 0 6px 6px 6px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-divider {
|
||||
border: none;
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-time-grid {
|
||||
|
||||
.fc-bg {
|
||||
|
||||
.fc-day {
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
&.fc-today {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-axis {
|
||||
border: none;
|
||||
width: 48px !important;
|
||||
|
||||
+ .fc-day {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fc-slats {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
height: 48px;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
font-size: 12px;
|
||||
width: 48px;
|
||||
min-width: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
.fc-time {
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
|
||||
.fc-widget-content {
|
||||
border-color: var(--fuse-divider);
|
||||
}
|
||||
}
|
||||
|
||||
.fc-content-skeleton {
|
||||
|
||||
.fc-axis {
|
||||
width: 48px !important;
|
||||
}
|
||||
|
||||
.fc-event-container {
|
||||
margin: 0 12px 0 0;
|
||||
|
||||
.fc-time-grid-event {
|
||||
display: flex;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
.fc-time,
|
||||
.fc-title {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* List - Year view */
|
||||
.fc-view.fc-listYear-view {
|
||||
border: none;
|
||||
|
||||
.fc-list-table {
|
||||
|
||||
.fc-list-heading {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fc-list-item {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
|
||||
td {
|
||||
@apply bg-hover;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: auto;
|
||||
height: 48px;
|
||||
min-height: 48px;
|
||||
padding: 0 8px;
|
||||
border-width: 0 0 1px 0;
|
||||
border-color: var(--fuse-divider);
|
||||
|
||||
&.fc-list-item-date {
|
||||
order: 1;
|
||||
padding-left: 16px;
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
max-width: 100px;
|
||||
|
||||
@screen sm {
|
||||
width: 120px;
|
||||
min-width: 120px;
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
> span {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
span {
|
||||
|
||||
&:first-child {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-right: 2px;
|
||||
width: 32px;
|
||||
min-width: 32px;
|
||||
max-width: 32px;
|
||||
font-size: 18px;
|
||||
|
||||
@screen sm {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
+ span {
|
||||
display: flex;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.055em;
|
||||
text-transform: uppercase;
|
||||
@apply text-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.fc-list-item-time {
|
||||
flex: 0 0 auto;
|
||||
order: 3;
|
||||
width: 120px;
|
||||
min-width: 120px;
|
||||
max-width: 120px;
|
||||
|
||||
@screen sm {
|
||||
width: 160px;
|
||||
min-width: 160px;
|
||||
max-width: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
&.fc-list-item-marker {
|
||||
flex: 0 0 auto;
|
||||
order: 2;
|
||||
|
||||
.fc-event-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
&.fc-list-item-title {
|
||||
flex: 1 1 auto;
|
||||
order: 4;
|
||||
padding-right: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Day grid event - Dragging */
|
||||
.fc-day-grid-event {
|
||||
|
||||
&.fc-dragging,
|
||||
&.fc-resizing {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
min-height: 22px;
|
||||
max-height: 22px;
|
||||
margin: 0 6px 4px 6px;
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
border-radius: 4px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,12 @@
|
||||
.ql-toolbar {
|
||||
border-radius: 6px 6px 0 0;
|
||||
padding: 0 !important;
|
||||
@apply bg-gray-100 border-gray-300;
|
||||
@apply bg-gray-100;
|
||||
@apply border-gray-300 border-opacity-100 #{'!important'};
|
||||
|
||||
.dark & {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
@apply border-gray-500;
|
||||
@apply border-gray-500 #{'!important'};
|
||||
}
|
||||
|
||||
.ql-formats {
|
||||
@@ -79,30 +80,63 @@
|
||||
}
|
||||
|
||||
.ql-container {
|
||||
overflow: hidden;
|
||||
overflow: auto;
|
||||
min-height: 160px;
|
||||
max-height: 400px;
|
||||
border-radius: 0 0 6px 6px;
|
||||
@apply border-gray-300 shadow-sm;
|
||||
@apply border-gray-300 border-opacity-100 shadow-sm #{'!important'};
|
||||
|
||||
.dark & {
|
||||
@apply border-gray-500;
|
||||
@apply border-gray-500 #{'!important'};
|
||||
}
|
||||
|
||||
.ql-editor {
|
||||
min-height: 160px;
|
||||
max-height: 160px;
|
||||
height: 160px;
|
||||
@apply bg-gray-50;
|
||||
@apply bg-card;
|
||||
|
||||
.dark & {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
@apply bg-card;
|
||||
//background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&.ql-blank::before {
|
||||
@apply text-hint;
|
||||
}
|
||||
}
|
||||
|
||||
.ql-tooltip {
|
||||
@apply px-3 py-1 shadow-sm rounded-md bg-gray-100 border-gray-300;
|
||||
|
||||
.dark & {
|
||||
@apply shadow-lg bg-gray-700 border-gray-700 #{'!important'};
|
||||
}
|
||||
|
||||
// Label
|
||||
&:before {
|
||||
@apply text-secondary;
|
||||
}
|
||||
|
||||
.ql-action,
|
||||
.ql-remove {
|
||||
@apply text-primary border-gray-300;
|
||||
|
||||
.dark & {
|
||||
@apply text-primary-400 border-gray-300;
|
||||
}
|
||||
}
|
||||
|
||||
.ql-action:after {
|
||||
@apply border-r border-r-gray-300 #{'!important'};
|
||||
|
||||
.dark & {
|
||||
@apply border-r-gray-500 #{'!important'};
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
@apply rounded-sm text-default bg-white border-gray-300 #{'!important'};
|
||||
|
||||
.dark & {
|
||||
@apply bg-gray-700 border-gray-500 #{'!important'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,11 +63,15 @@
|
||||
-webkit-text-fill-color: currentColor;
|
||||
}
|
||||
|
||||
/* Set the background and foreground colors */
|
||||
body, .dark, .light {
|
||||
@apply text-default bg-default #{'!important'};
|
||||
}
|
||||
|
||||
*, *::before, *::after {
|
||||
/* Set the border color */
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
--tw-border-opacity: 1 !important;
|
||||
border-color: rgba(var(--fuse-border-rgb), var(--tw-border-opacity));
|
||||
|
||||
@@ -76,6 +80,47 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Style scrollbars on platforms other than MacOS and iOS */
|
||||
@media only screen and (min-width: 960px) {
|
||||
|
||||
body:not(.os-mac) {
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar:hover {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border: 2px solid transparent;
|
||||
border-radius: 20px;
|
||||
box-shadow: inset 0 0 0 20px rgba(0, 0, 0, 0.24);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:active {
|
||||
border-radius: 20px;
|
||||
box-shadow: inset 0 0 0 20px rgba(0, 0, 0, 0.37);
|
||||
}
|
||||
|
||||
&.dark {
|
||||
::-webkit-scrollbar-thumb {
|
||||
box-shadow: inset 0 0 0 20px rgba(255, 255, 255, 0.24);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:active {
|
||||
box-shadow: inset 0 0 0 20px rgba(255, 255, 255, 0.37);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the foreground color for disabled elements */
|
||||
[disabled] * {
|
||||
@apply text-disabled #{'!important'};
|
||||
}
|
||||
|
||||
@@ -1,173 +1,164 @@
|
||||
@use '~@angular/material' as mat;
|
||||
@use "sass:map";
|
||||
@use '@angular/material' as mat;
|
||||
@use "user-themes" as userThemes;
|
||||
|
||||
/** Include the core Angular Material styles */
|
||||
/* Set the base colors for light themes */
|
||||
$light-base: (
|
||||
foreground: (
|
||||
base: #000000,
|
||||
divider: #E2E8F0, /* slate.200 */
|
||||
dividers: #E2E8F0, /* slate.200 */
|
||||
disabled: #94A3B8, /* slate.400 */
|
||||
disabled-button: #94A3B8, /* slate.400 */
|
||||
disabled-text: #94A3B8, /* slate.400 */
|
||||
elevation: #000000,
|
||||
hint-text: #94A3B8, /* slate.400 */
|
||||
secondary-text: #64748B, /* slate.500 */
|
||||
icon: #64748B, /* slate.500 */
|
||||
icons: #64748B, /* slate.500 */
|
||||
mat-icon: #64748B, /* slate.500 */
|
||||
text: #1E293B, /* slate.800 */
|
||||
slider-min: #1E293B, /* slate.800 */
|
||||
slider-off: #CBD5E1, /* slate.300 */
|
||||
slider-off-active: #94A3B8 /* slate.400 */
|
||||
),
|
||||
background: (
|
||||
status-bar: #CBD5E1, /* slate.300 */
|
||||
app-bar: #FFFFFF,
|
||||
background: #F1F5F9, /* slate.100 */
|
||||
hover: rgba(148, 163, 184, 0.12), /* slate.400 + opacity */
|
||||
card: #FFFFFF,
|
||||
dialog: #FFFFFF,
|
||||
disabled-button: rgba(148, 163, 184, 0.38), /* slate.400 + opacity */
|
||||
raised-button: #FFFFFF,
|
||||
focused-button: #64748B, /* slate.500 */
|
||||
selected-button: #E2E8F0, /* slate.200 */
|
||||
selected-disabled-button: #E2E8F0, /* slate.200 */
|
||||
disabled-button-toggle: #CBD5E1, /* slate.300 */
|
||||
unselected-chip: #E2E8F0, /* slate.200 */
|
||||
disabled-list-option: #CBD5E1, /* slate.300 */
|
||||
tooltip: #1E293B /* slate.800 */
|
||||
)
|
||||
);
|
||||
|
||||
/* Set the base colors for dark themes */
|
||||
$dark-base: (
|
||||
foreground: (
|
||||
base: #FFFFFF,
|
||||
divider: rgba(241, 245, 249, 0.12), /* slate.100 + opacity */
|
||||
dividers: rgba(241, 245, 249, 0.12), /* slate.100 + opacity */
|
||||
disabled: #475569, /* slate.600 */
|
||||
disabled-button: #1E293B, /* slate.800 */
|
||||
disabled-text: #475569, /* slate.600 */
|
||||
elevation: #000000,
|
||||
hint-text: #64748B, /* slate.500 */
|
||||
secondary-text: #94A3B8, /* slate.400 */
|
||||
icon: #F1F5F9, /* slate.100 */
|
||||
icons: #F1F5F9, /* slate.100 */
|
||||
mat-icon: #94A3B8, /* slate.400 */
|
||||
text: #FFFFFF,
|
||||
slider-min: #FFFFFF,
|
||||
slider-off: #64748B, /* slate.500 */
|
||||
slider-off-active: #94A3B8 /* slate.400 */
|
||||
),
|
||||
background: (
|
||||
status-bar: #0F172A, /* slate.900 */
|
||||
app-bar: #0F172A, /* slate.900 */
|
||||
background: #0F172A, /* slate.900 */
|
||||
hover: rgba(255, 255, 255, 0.05),
|
||||
card: #1E293B, /* slate.800 */
|
||||
dialog: #1E293B, /* slate.800 */
|
||||
disabled-button: rgba(15, 23, 42, 0.38), /* slate.900 + opacity */
|
||||
raised-button: #0F172A, /* slate.900 */
|
||||
focused-button: #E2E8F0, /* slate.200 */
|
||||
selected-button: rgba(255, 255, 255, 0.05),
|
||||
selected-disabled-button: #1E293B, /* slate.800 */
|
||||
disabled-button-toggle: #0F172A, /* slate.900 */
|
||||
unselected-chip: #475569, /* slate.600 */
|
||||
disabled-list-option: #E2E8F0, /* slate.200 */
|
||||
tooltip: #64748B /* slate.500 */
|
||||
)
|
||||
);
|
||||
|
||||
/* Include the core Angular Material styles */
|
||||
@include mat.core();
|
||||
|
||||
/** Configure the Angular Material typography */
|
||||
@include mat.all-component-typographies(
|
||||
mat.define-typography-config(
|
||||
$font-family: theme('fontFamily.sans'),
|
||||
$title: mat.define-typography-level(1.25rem, 2rem, 600),
|
||||
$body-2: mat.define-typography-level(0.875rem, 1.5rem, 600),
|
||||
$button: mat.define-typography-level(0.875rem, 0.875rem, 500),
|
||||
$input: mat.define-typography-level(0.875rem, 1.2857142857, 400) // line-height: 20px
|
||||
)
|
||||
);
|
||||
/* Create a base theme without any color to set the density and typography */
|
||||
@include mat.all-component-themes((
|
||||
color: null,
|
||||
density: 0,
|
||||
typography: mat.define-typography-config(
|
||||
$font-family: theme('fontFamily.sans'),
|
||||
$headline-1: mat.define-typography-level(1.875rem, 2.25rem, 800, theme('fontFamily.sans')),
|
||||
$headline-2: mat.define-typography-level(1.25rem, 1.75rem, 700, theme('fontFamily.sans')),
|
||||
$headline-3: mat.define-typography-level(1.125rem, 1.75rem, 600, theme('fontFamily.sans')),
|
||||
$headline-4: mat.define-typography-level(0.875rem, 1.25rem, 600, theme('fontFamily.sans')),
|
||||
$headline-5: mat.define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$headline-6: mat.define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$subtitle-1: mat.define-typography-level(1rem, 1.75rem, 400, theme('fontFamily.sans')),
|
||||
$subtitle-2: mat.define-typography-level(0.875rem, 1.25rem, 600, theme('fontFamily.sans')),
|
||||
$body-1: mat.define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$body-2: mat.define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$caption: mat.define-typography-level(0.75rem, 1rem, 400, theme('fontFamily.sans')),
|
||||
$button: mat.define-typography-level(0.875rem, 0.875rem, 500, theme('fontFamily.sans')),
|
||||
$overline: mat.define-typography-level(0.75rem, 2rem, 500, theme('fontFamily.sans'))
|
||||
)
|
||||
));
|
||||
|
||||
/** Prepare the Background and Foreground maps */
|
||||
$background-light: (
|
||||
status-bar: #CBD5E1, /* blueGray.300 */
|
||||
app-bar: #FFFFFF,
|
||||
background: #F1F5F9, /* blueGray.100 */
|
||||
hover: rgba(148, 163, 184, 0.12), /* blueGray.400 + opacity */
|
||||
card: #FFFFFF,
|
||||
dialog: #FFFFFF,
|
||||
disabled-button: rgba(148, 163, 184, 0.38), /* blueGray.400 + opacity */
|
||||
raised-button: #FFFFFF,
|
||||
focused-button: #64748B, /* blueGray.500 */
|
||||
selected-button: #E2E8F0, /* blueGray.200 */
|
||||
selected-disabled-button: #E2E8F0, /* blueGray.200 */
|
||||
disabled-button-toggle: #CBD5E1, /* blueGray.300 */
|
||||
unselected-chip: #E2E8F0, /* blueGray.200 */
|
||||
disabled-list-option: #CBD5E1, /* blueGray.300 */
|
||||
tooltip: #1E293B /* blueGray.800 */
|
||||
);
|
||||
/* Loop through user themes and generate Angular Material themes */
|
||||
@each $name, $theme in userThemes.$user-themes {
|
||||
|
||||
$background-dark: (
|
||||
status-bar: #0F172A, /* blueGray.900 */
|
||||
app-bar: #0F172A, /* blueGray.900 */
|
||||
background: #0F172A, /* blueGray.900 */
|
||||
hover: rgba(255, 255, 255, 0.05),
|
||||
card: #1E293B, /* blueGray.800 */
|
||||
dialog: #1E293B, /* blueGray.800 */
|
||||
disabled-button: rgba(15, 23, 42, 0.38), /* blueGray.900 + opacity */
|
||||
raised-button: #0F172A, /* blueGray.900 */
|
||||
focused-button: #E2E8F0, /* blueGray.200 */
|
||||
selected-button: rgba(255, 255, 255, 0.05),
|
||||
selected-disabled-button: #1E293B, /* blueGray.800 */
|
||||
disabled-button-toggle: #0F172A, /* blueGray.900 */
|
||||
unselected-chip: #475569, /* blueGray.600 */
|
||||
disabled-list-option: #E2E8F0, /* blueGray.200 */
|
||||
tooltip: #64748B /* blueGray.500 */
|
||||
);
|
||||
/* Generate the palettes */
|
||||
$palettes: ();
|
||||
@each $name in (primary, accent, warn) {
|
||||
|
||||
$foreground-light: (
|
||||
base: #000000,
|
||||
divider: #E2E8F0, /* blueGray.200 */
|
||||
dividers: #E2E8F0, /* blueGray.200 */
|
||||
disabled: #94A3B8, /* blueGray.400 */
|
||||
disabled-button: #94A3B8, /* blueGray.400 */
|
||||
disabled-text: #94A3B8, /* blueGray.400 */
|
||||
elevation: #000000,
|
||||
hint-text: #94A3B8, /* blueGray.400 */
|
||||
secondary-text: #64748B, /* blueGray.500 */
|
||||
icon: #64748B, /* blueGray.500 */
|
||||
icons: #64748B, /* blueGray.500 */
|
||||
mat-icon: #64748B, /* blueGray.500 */
|
||||
text: #1E293B, /* blueGray.800 */
|
||||
slider-min: #1E293B, /* blueGray.800 */
|
||||
slider-off: #CBD5E1, /* blueGray.300 */
|
||||
slider-off-active: #94A3B8 /* blueGray.400 */
|
||||
);
|
||||
/* Define the Angular Material theme */
|
||||
$palette: mat.define-palette(map.get($theme, $name));
|
||||
|
||||
$foreground-dark: (
|
||||
base: #FFFFFF,
|
||||
divider: rgba(241, 245, 249, 0.12), /* blueGray.100 + opacity */
|
||||
dividers: rgba(241, 245, 249, 0.12), /* blueGray.100 + opacity */
|
||||
disabled: #475569, /* blueGray.600 */
|
||||
disabled-button: #1E293B, /* blueGray.800 */
|
||||
disabled-text: #475569, /* blueGray.600 */
|
||||
elevation: #000000,
|
||||
hint-text: #64748B, /* blueGray.500 */
|
||||
secondary-text: #94A3B8, /* blueGray.400 */
|
||||
icon: #F1F5F9, /* blueGray.100 */
|
||||
icons: #F1F5F9, /* blueGray.100 */
|
||||
mat-icon: #94A3B8, /* blueGray.400 */
|
||||
text: #FFFFFF,
|
||||
slider-min: #FFFFFF,
|
||||
slider-off: #64748B, /* blueGray.500 */
|
||||
slider-off-active: #94A3B8 /* blueGray.400 */
|
||||
);
|
||||
/* Replace the default colors on the defined Material palette */
|
||||
$palette: map.merge($palette, (
|
||||
default: map.get(map.get($theme, $name), DEFAULT),
|
||||
lighter: map.get(map.get($theme, $name), 100),
|
||||
darker: map.get(map.get($theme, $name), 700),
|
||||
text: map.get(map.get($theme, $name), DEFAULT),
|
||||
default-contrast: map.get(map.get(map.get($theme, $name), contrast), DEFAULT),
|
||||
lighter-contrast: map.get(map.get(map.get($theme, $name), contrast), 100),
|
||||
darker-contrast: map.get(map.get(map.get($theme, $name), contrast), 700)
|
||||
));
|
||||
|
||||
/** Generate Primary, Accent and Warn palettes */
|
||||
$palettes: ();
|
||||
@each $name in (primary, accent, warn) {
|
||||
$palettes: map.merge($palettes, (#{$name}: (
|
||||
50: var(--fuse-#{$name}-50),
|
||||
100: var(--fuse-#{$name}-100),
|
||||
200: var(--fuse-#{$name}-200),
|
||||
300: var(--fuse-#{$name}-300),
|
||||
400: var(--fuse-#{$name}-400),
|
||||
500: var(--fuse-#{$name}-500),
|
||||
600: var(--fuse-#{$name}-600),
|
||||
700: var(--fuse-#{$name}-700),
|
||||
800: var(--fuse-#{$name}-800),
|
||||
900: var(--fuse-#{$name}-900),
|
||||
contrast: (
|
||||
50: var(--fuse-on-#{$name}-50),
|
||||
100: var(--fuse-on-#{$name}-100),
|
||||
200: var(--fuse-on-#{$name}-200),
|
||||
300: var(--fuse-on-#{$name}-300),
|
||||
400: var(--fuse-on-#{$name}-400),
|
||||
500: var(--fuse-on-#{$name}-500),
|
||||
600: var(--fuse-on-#{$name}-600),
|
||||
700: var(--fuse-on-#{$name}-700),
|
||||
800: var(--fuse-on-#{$name}-800),
|
||||
900: var(--fuse-on-#{$name}-900)
|
||||
),
|
||||
default: var(--fuse-#{$name}),
|
||||
lighter: var(--fuse-#{$name}-100),
|
||||
darker: var(--fuse-#{$name}-700),
|
||||
text: var(--fuse-#{$name}),
|
||||
default-contrast: var(--fuse-on-#{$name}),
|
||||
lighter-contrast: var(--fuse-on-#{$name}-100),
|
||||
darker-contrast: var(--fuse-on-#{$name}-700)
|
||||
)));
|
||||
}
|
||||
$palettes: map.merge($palettes, (#{$name}: $palette));
|
||||
}
|
||||
|
||||
/** Generate Angular Material themes. Since we are using CSS Custom Properties,
|
||||
we don't have to generate a separate Angular Material theme for each color
|
||||
set. We can just create one light and one dark theme and then switch the
|
||||
CSS Custom Properties to dynamically switch the colors. */
|
||||
body.light,
|
||||
body .light {
|
||||
$base-light-theme: mat.define-light-theme((
|
||||
color: ($palettes)
|
||||
/* Define a light & dark Angular Material theme with the generated palettes */
|
||||
$light-theme: mat.define-light-theme((
|
||||
color: $palettes
|
||||
));
|
||||
|
||||
$light-theme: (
|
||||
color: (
|
||||
primary: map.get(map.get($base-light-theme, color), primary),
|
||||
accent: map.get(map.get($base-light-theme, color), accent),
|
||||
warn: map.get(map.get($base-light-theme, color), warn),
|
||||
is-dark: map.get(map.get($base-light-theme, color), is-dark),
|
||||
foreground: $foreground-light,
|
||||
background: $background-light
|
||||
),
|
||||
density: -2
|
||||
);
|
||||
|
||||
@include mat.all-component-themes($light-theme);
|
||||
}
|
||||
|
||||
body.dark,
|
||||
body .dark {
|
||||
$base-dark-theme: mat.define-dark-theme((
|
||||
color: ($palettes)
|
||||
$dark-theme: mat.define-dark-theme((
|
||||
color: $palettes
|
||||
));
|
||||
|
||||
$dark-theme: (
|
||||
color: (
|
||||
primary: map.get(map.get($base-dark-theme, color), primary),
|
||||
accent: map.get(map.get($base-dark-theme, color), accent),
|
||||
warn: map.get(map.get($base-dark-theme, color), warn),
|
||||
is-dark: map.get(map.get($base-dark-theme, color), is-dark),
|
||||
foreground: $foreground-dark,
|
||||
background: $background-dark
|
||||
),
|
||||
density: -2
|
||||
/* Merge the custom base colors with the generated themes */
|
||||
$light-theme-colors: map.merge(map.get($light-theme, color), $light-base);
|
||||
$light-theme: map.merge(
|
||||
(color: $light-theme-colors),
|
||||
$light-theme-colors
|
||||
);
|
||||
|
||||
@include mat.all-component-colors($dark-theme);
|
||||
$dark-theme-colors: map.merge(map.get($dark-theme, color), $dark-base);
|
||||
$dark-theme: map.merge(
|
||||
(color: $dark-theme-colors),
|
||||
$dark-theme-colors
|
||||
);
|
||||
|
||||
/* Generate and encapsulate Angular Material themes */
|
||||
#{map.get($theme, selector)} .light,
|
||||
#{map.get($theme, selector)}.light {
|
||||
@include mat.all-component-colors($light-theme);
|
||||
}
|
||||
|
||||
#{map.get($theme, selector)} .dark,
|
||||
#{map.get($theme, selector)}.dark {
|
||||
@include mat.all-component-colors($dark-theme);
|
||||
}
|
||||
}
|
||||
|
||||
1
src/@fuse/styles/user-themes.scss
Normal file
1
src/@fuse/styles/user-themes.scss
Normal file
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user