mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-04-02 14:41:37 +00:00
Added prettier and tailwindcss class sorter. First pass with the new formatter. This is a huge change, but it is long overdue.
This commit is contained in:
parent
34138ad5fa
commit
48a7707b45
@ -1,95 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"env": {
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"projects/**/*"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.ts"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": [
|
||||
"tsconfig.json"
|
||||
],
|
||||
"createDefaultProgram": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:@angular-eslint/ng-cli-compat",
|
||||
"plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
],
|
||||
"rules": {
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "attribute",
|
||||
"prefix": "",
|
||||
"style": "camelCase"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/dot-notation": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": [
|
||||
"off",
|
||||
{
|
||||
"accessibility": "explicit"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
"arrow-parens": [
|
||||
"error",
|
||||
"as-needed",
|
||||
{
|
||||
"requireForBlockBody": true
|
||||
}
|
||||
],
|
||||
"brace-style": [
|
||||
"off",
|
||||
"off"
|
||||
],
|
||||
"import/order": "off",
|
||||
"max-len": [
|
||||
"error",
|
||||
{
|
||||
"ignorePattern": "^import |^export | implements",
|
||||
"code": 180
|
||||
}
|
||||
],
|
||||
"no-underscore-dangle": "off",
|
||||
"object-shorthand": "off",
|
||||
"quote-props": [
|
||||
"error",
|
||||
"consistent"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.html"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:@angular-eslint/template/recommended"
|
||||
],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
11
.prettierrc
Normal file
11
.prettierrc
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"semi": true,
|
||||
"bracketSameLine": false,
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "always",
|
||||
"plugins": ["prettier-plugin-organize-imports", "prettier-plugin-tailwindcss"]
|
||||
}
|
17
angular.json
17
angular.json
@ -20,9 +20,7 @@
|
||||
"outputPath": "dist/fuse",
|
||||
"index": "src/index.html",
|
||||
"browser": "src/main.ts",
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
],
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"allowedCommonJsDependencies": [
|
||||
@ -44,9 +42,7 @@
|
||||
}
|
||||
],
|
||||
"stylePreprocessorOptions": {
|
||||
"includePaths": [
|
||||
"src/@fuse/styles"
|
||||
]
|
||||
"includePaths": ["src/@fuse/styles"]
|
||||
},
|
||||
"styles": [
|
||||
"src/@fuse/styles/tailwind.scss",
|
||||
@ -100,10 +96,7 @@
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"polyfills": ["zone.js", "zone.js/testing"],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
@ -112,9 +105,7 @@
|
||||
"input": "public"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles/styles.scss"
|
||||
],
|
||||
"styles": ["src/styles/styles.scss"],
|
||||
"scripts": []
|
||||
}
|
||||
}
|
||||
|
116
package-lock.json
generated
116
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "fuse-angular",
|
||||
"version": "19.1.0",
|
||||
"version": "20.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "fuse-angular",
|
||||
"version": "19.1.0",
|
||||
"version": "20.0.0",
|
||||
"license": "https://themeforest.net/licenses/standard",
|
||||
"dependencies": {
|
||||
"@angular/animations": "18.0.0",
|
||||
@ -56,6 +56,9 @@
|
||||
"karma-jasmine-html-reporter": "2.1.0",
|
||||
"lodash": "4.17.21",
|
||||
"postcss": "8.4.38",
|
||||
"prettier": "3.2.5",
|
||||
"prettier-plugin-organize-imports": "3.2.4",
|
||||
"prettier-plugin-tailwindcss": "0.5.14",
|
||||
"tailwindcss": "3.4.3",
|
||||
"typescript": "5.4.5"
|
||||
}
|
||||
@ -11184,6 +11187,115 @@
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.2.5",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
|
||||
"integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-organize-imports": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz",
|
||||
"integrity": "sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@volar/vue-language-plugin-pug": "^1.0.4",
|
||||
"@volar/vue-typescript": "^1.0.4",
|
||||
"prettier": ">=2.0",
|
||||
"typescript": ">=2.9"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@volar/vue-language-plugin-pug": {
|
||||
"optional": true
|
||||
},
|
||||
"@volar/vue-typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-tailwindcss": {
|
||||
"version": "0.5.14",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz",
|
||||
"integrity": "sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=14.21.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@ianvs/prettier-plugin-sort-imports": "*",
|
||||
"@prettier/plugin-pug": "*",
|
||||
"@shopify/prettier-plugin-liquid": "*",
|
||||
"@trivago/prettier-plugin-sort-imports": "*",
|
||||
"@zackad/prettier-plugin-twig-melody": "*",
|
||||
"prettier": "^3.0",
|
||||
"prettier-plugin-astro": "*",
|
||||
"prettier-plugin-css-order": "*",
|
||||
"prettier-plugin-import-sort": "*",
|
||||
"prettier-plugin-jsdoc": "*",
|
||||
"prettier-plugin-marko": "*",
|
||||
"prettier-plugin-organize-attributes": "*",
|
||||
"prettier-plugin-organize-imports": "*",
|
||||
"prettier-plugin-sort-imports": "*",
|
||||
"prettier-plugin-style-order": "*",
|
||||
"prettier-plugin-svelte": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@ianvs/prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"@prettier/plugin-pug": {
|
||||
"optional": true
|
||||
},
|
||||
"@shopify/prettier-plugin-liquid": {
|
||||
"optional": true
|
||||
},
|
||||
"@trivago/prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"@zackad/prettier-plugin-twig-melody": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-astro": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-css-order": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-import-sort": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-jsdoc": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-marko": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-organize-attributes": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-organize-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-sort-imports": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-style-order": {
|
||||
"optional": true
|
||||
},
|
||||
"prettier-plugin-svelte": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/proc-log": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz",
|
||||
|
@ -60,6 +60,9 @@
|
||||
"karma-jasmine-html-reporter": "2.1.0",
|
||||
"lodash": "4.17.21",
|
||||
"postcss": "8.4.38",
|
||||
"prettier": "3.2.5",
|
||||
"prettier-plugin-organize-imports": "3.2.4",
|
||||
"prettier-plugin-tailwindcss": "0.5.14",
|
||||
"tailwindcss": "3.4.3",
|
||||
"typescript": "5.4.5"
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
export class FuseAnimationCurves
|
||||
{
|
||||
export class FuseAnimationCurves {
|
||||
static standard = 'cubic-bezier(0.4, 0.0, 0.2, 1)';
|
||||
static deceleration = 'cubic-bezier(0.0, 0.0, 0.2, 1)';
|
||||
static acceleration = 'cubic-bezier(0.4, 0.0, 1, 1)';
|
||||
static sharp = 'cubic-bezier(0.4, 0.0, 0.6, 1)';
|
||||
}
|
||||
|
||||
export class FuseAnimationDurations
|
||||
{
|
||||
export class FuseAnimationDurations {
|
||||
static complex = '375ms';
|
||||
static entering = '225ms';
|
||||
static exiting = '195ms';
|
||||
|
@ -1,34 +1,37 @@
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
|
||||
import {
|
||||
animate,
|
||||
state,
|
||||
style,
|
||||
transition,
|
||||
trigger,
|
||||
} from '@angular/animations';
|
||||
import {
|
||||
FuseAnimationCurves,
|
||||
FuseAnimationDurations,
|
||||
} from '@fuse/animations/defaults';
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Expand / collapse
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const expandCollapse = trigger('expandCollapse',
|
||||
[
|
||||
state('void, collapsed',
|
||||
style({
|
||||
height: '0',
|
||||
}),
|
||||
),
|
||||
const expandCollapse = trigger('expandCollapse', [
|
||||
state(
|
||||
'void, collapsed',
|
||||
style({
|
||||
height: '0',
|
||||
})
|
||||
),
|
||||
|
||||
state('*, expanded',
|
||||
style('*'),
|
||||
),
|
||||
state('*, expanded', style('*')),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void <=> false, collapsed <=> false, expanded <=> false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void <=> false, collapsed <=> false, expanded <=> false', []),
|
||||
|
||||
// Transition
|
||||
transition('void <=> *, collapsed <=> expanded',
|
||||
animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void <=> *, collapsed <=> expanded', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
export { expandCollapse };
|
||||
|
@ -1,330 +1,330 @@
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
|
||||
import {
|
||||
animate,
|
||||
state,
|
||||
style,
|
||||
transition,
|
||||
trigger,
|
||||
} from '@angular/animations';
|
||||
import {
|
||||
FuseAnimationCurves,
|
||||
FuseAnimationDurations,
|
||||
} from '@fuse/animations/defaults';
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade in
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeIn = trigger('fadeIn',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
opacity: 0,
|
||||
}),
|
||||
),
|
||||
const fadeIn = trigger('fadeIn', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
opacity: 1,
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade in top
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeInTop = trigger('fadeInTop',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeInTop = trigger('fadeInTop', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade in bottom
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeInBottom = trigger('fadeInBottom',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeInBottom = trigger('fadeInBottom', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade in left
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeInLeft = trigger('fadeInLeft',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeInLeft = trigger('fadeInLeft', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade in right
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeInRight = trigger('fadeInRight',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeInRight = trigger('fadeInRight', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade out
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeOut = trigger('fadeOut',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
opacity: 1,
|
||||
}),
|
||||
),
|
||||
const fadeOut = trigger('fadeOut', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
opacity: 0,
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade out top
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeOutTop = trigger('fadeOutTop',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeOutTop = trigger('fadeOutTop', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade out bottom
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeOutBottom = trigger('fadeOutBottom',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeOutBottom = trigger('fadeOutBottom', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade out left
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeOutLeft = trigger('fadeOutLeft',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeOutLeft = trigger('fadeOutLeft', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Fade out right
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const fadeOutRight = trigger('fadeOutRight',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const fadeOutRight = trigger('fadeOutRight', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
export { fadeIn, fadeInTop, fadeInBottom, fadeInLeft, fadeInRight, fadeOut, fadeOutTop, fadeOutBottom, fadeOutLeft, fadeOutRight };
|
||||
export {
|
||||
fadeIn,
|
||||
fadeInBottom,
|
||||
fadeInLeft,
|
||||
fadeInRight,
|
||||
fadeInTop,
|
||||
fadeOut,
|
||||
fadeOutBottom,
|
||||
fadeOutLeft,
|
||||
fadeOutRight,
|
||||
fadeOutTop,
|
||||
};
|
||||
|
@ -1,15 +1,50 @@
|
||||
import { expandCollapse } from '@fuse/animations/expand-collapse';
|
||||
import { fadeIn, fadeInBottom, fadeInLeft, fadeInRight, fadeInTop, fadeOut, fadeOutBottom, fadeOutLeft, fadeOutRight, fadeOutTop } from '@fuse/animations/fade';
|
||||
import {
|
||||
fadeIn,
|
||||
fadeInBottom,
|
||||
fadeInLeft,
|
||||
fadeInRight,
|
||||
fadeInTop,
|
||||
fadeOut,
|
||||
fadeOutBottom,
|
||||
fadeOutLeft,
|
||||
fadeOutRight,
|
||||
fadeOutTop,
|
||||
} from '@fuse/animations/fade';
|
||||
import { shake } from '@fuse/animations/shake';
|
||||
import { slideInBottom, slideInLeft, slideInRight, slideInTop, slideOutBottom, slideOutLeft, slideOutRight, slideOutTop } from '@fuse/animations/slide';
|
||||
import {
|
||||
slideInBottom,
|
||||
slideInLeft,
|
||||
slideInRight,
|
||||
slideInTop,
|
||||
slideOutBottom,
|
||||
slideOutLeft,
|
||||
slideOutRight,
|
||||
slideOutTop,
|
||||
} from '@fuse/animations/slide';
|
||||
import { zoomIn, zoomOut } from '@fuse/animations/zoom';
|
||||
|
||||
export const fuseAnimations = [
|
||||
expandCollapse,
|
||||
fadeIn, fadeInTop, fadeInBottom, fadeInLeft, fadeInRight,
|
||||
fadeOut, fadeOutTop, fadeOutBottom, fadeOutLeft, fadeOutRight,
|
||||
fadeIn,
|
||||
fadeInTop,
|
||||
fadeInBottom,
|
||||
fadeInLeft,
|
||||
fadeInRight,
|
||||
fadeOut,
|
||||
fadeOutTop,
|
||||
fadeOutBottom,
|
||||
fadeOutLeft,
|
||||
fadeOutRight,
|
||||
shake,
|
||||
slideInTop, slideInBottom, slideInLeft, slideInRight,
|
||||
slideOutTop, slideOutBottom, slideOutLeft, slideOutRight,
|
||||
zoomIn, zoomOut,
|
||||
slideInTop,
|
||||
slideInBottom,
|
||||
slideInLeft,
|
||||
slideInRight,
|
||||
slideOutTop,
|
||||
slideOutBottom,
|
||||
slideOutLeft,
|
||||
slideOutRight,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
];
|
||||
|
@ -1,73 +1,78 @@
|
||||
import { animate, keyframes, style, transition, trigger } from '@angular/animations';
|
||||
import {
|
||||
animate,
|
||||
keyframes,
|
||||
style,
|
||||
transition,
|
||||
trigger,
|
||||
} from '@angular/animations';
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Shake
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const shake = trigger('shake',
|
||||
[
|
||||
const shake = trigger('shake', [
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *, * => true',
|
||||
[
|
||||
animate('{{timings}}',
|
||||
keyframes([
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
offset : 0,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset : 0.1,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset : 0.2,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset : 0.3,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset : 0.4,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset : 0.5,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset : 0.6,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset : 0.7,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset : 0.8,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset : 0.9,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
offset : 1,
|
||||
}),
|
||||
]),
|
||||
),
|
||||
],
|
||||
{
|
||||
params: {
|
||||
timings: '0.8s cubic-bezier(0.455, 0.03, 0.515, 0.955)',
|
||||
},
|
||||
// Transition
|
||||
transition(
|
||||
'void => *, * => true',
|
||||
[
|
||||
animate(
|
||||
'{{timings}}',
|
||||
keyframes([
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
offset: 0,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset: 0.1,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset: 0.2,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset: 0.3,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset: 0.4,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset: 0.5,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset: 0.6,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset: 0.7,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(10px, 0, 0)',
|
||||
offset: 0.8,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(-10px, 0, 0)',
|
||||
offset: 0.9,
|
||||
}),
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
offset: 1,
|
||||
}),
|
||||
])
|
||||
),
|
||||
],
|
||||
{
|
||||
params: {
|
||||
timings: '0.8s cubic-bezier(0.455, 0.03, 0.515, 0.955)',
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
),
|
||||
]);
|
||||
|
||||
export { shake };
|
||||
|
@ -1,252 +1,254 @@
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
|
||||
import {
|
||||
animate,
|
||||
state,
|
||||
style,
|
||||
transition,
|
||||
trigger,
|
||||
} from '@angular/animations';
|
||||
import {
|
||||
FuseAnimationCurves,
|
||||
FuseAnimationDurations,
|
||||
} from '@fuse/animations/defaults';
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide in top
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideInTop = trigger('slideInTop',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
}),
|
||||
),
|
||||
const slideInTop = trigger('slideInTop', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide in bottom
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideInBottom = trigger('slideInBottom',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
}),
|
||||
),
|
||||
const slideInBottom = trigger('slideInBottom', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide in left
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideInLeft = trigger('slideInLeft',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const slideInLeft = trigger('slideInLeft', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide in right
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideInRight = trigger('slideInRight',
|
||||
[
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const slideInRight = trigger('slideInRight', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide out top
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideOutTop = trigger('slideOutTop',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const slideOutTop = trigger('slideOutTop', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(0, -100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide out bottom
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideOutBottom = trigger('slideOutBottom',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const slideOutBottom = trigger('slideOutBottom', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(0, 100%, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide out left
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideOutLeft = trigger('slideOutLeft',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const slideOutLeft = trigger('slideOutLeft', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(-100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Slide out right
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const slideOutRight = trigger('slideOutRight',
|
||||
[
|
||||
state('*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
}),
|
||||
),
|
||||
const slideOutRight = trigger('slideOutRight', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
transform: 'translate3d(100%, 0, 0)',
|
||||
})
|
||||
),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
export { slideInTop, slideInBottom, slideInLeft, slideInRight, slideOutTop, slideOutBottom, slideOutLeft, slideOutRight };
|
||||
export {
|
||||
slideInBottom,
|
||||
slideInLeft,
|
||||
slideInRight,
|
||||
slideInTop,
|
||||
slideOutBottom,
|
||||
slideOutLeft,
|
||||
slideOutRight,
|
||||
slideOutTop,
|
||||
};
|
||||
|
@ -1,73 +1,75 @@
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { FuseAnimationCurves, FuseAnimationDurations } from '@fuse/animations/defaults';
|
||||
import {
|
||||
animate,
|
||||
state,
|
||||
style,
|
||||
transition,
|
||||
trigger,
|
||||
} from '@angular/animations';
|
||||
import {
|
||||
FuseAnimationCurves,
|
||||
FuseAnimationDurations,
|
||||
} from '@fuse/animations/defaults';
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Zoom in
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const zoomIn = trigger('zoomIn',
|
||||
[
|
||||
const zoomIn = trigger('zoomIn', [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'scale(0.5)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'scale(0.5)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'scale(1)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'scale(1)',
|
||||
}),
|
||||
),
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('void => false', []),
|
||||
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('void => *', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.entering} ${FuseAnimationCurves.deceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Zoom out
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const zoomOut = trigger('zoomOut',
|
||||
[
|
||||
const zoomOut = trigger('zoomOut', [
|
||||
state(
|
||||
'*',
|
||||
style({
|
||||
opacity: 1,
|
||||
transform: 'scale(1)',
|
||||
})
|
||||
),
|
||||
|
||||
state('*',
|
||||
style({
|
||||
opacity : 1,
|
||||
transform: 'scale(1)',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'scale(0.5)',
|
||||
})
|
||||
),
|
||||
|
||||
state('void',
|
||||
style({
|
||||
opacity : 0,
|
||||
transform: 'scale(0.5)',
|
||||
}),
|
||||
),
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Prevent the transition if the state is false
|
||||
transition('false => void', []),
|
||||
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'),
|
||||
{
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
// Transition
|
||||
transition('* => void', animate('{{timings}}'), {
|
||||
params: {
|
||||
timings: `${FuseAnimationDurations.exiting} ${FuseAnimationCurves.acceleration}`,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
|
||||
export { zoomIn, zoomOut };
|
||||
|
||||
|
@ -1,19 +1,14 @@
|
||||
<div
|
||||
class="fuse-alert-container"
|
||||
*ngIf="!dismissible || dismissible && !dismissed"
|
||||
*ngIf="!dismissible || (dismissible && !dismissed)"
|
||||
[@fadeIn]="!dismissed"
|
||||
[@fadeOut]="!dismissed">
|
||||
|
||||
[@fadeOut]="!dismissed"
|
||||
>
|
||||
<!-- Border -->
|
||||
<div
|
||||
class="fuse-alert-border"
|
||||
*ngIf="appearance === 'border'"></div>
|
||||
<div class="fuse-alert-border" *ngIf="appearance === 'border'"></div>
|
||||
|
||||
<!-- Icon -->
|
||||
<div
|
||||
class="fuse-alert-icon"
|
||||
*ngIf="showIcon">
|
||||
|
||||
<div class="fuse-alert-icon" *ngIf="showIcon">
|
||||
<!-- Custom icon -->
|
||||
<div class="fuse-alert-custom-icon">
|
||||
<ng-content select="[fuseAlertIcon]"></ng-content>
|
||||
@ -21,46 +16,50 @@
|
||||
|
||||
<!-- Default icons -->
|
||||
<div class="fuse-alert-default-icon">
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'primary'"
|
||||
[svgIcon]="'heroicons_solid:check-circle'"></mat-icon>
|
||||
[svgIcon]="'heroicons_solid:check-circle'"
|
||||
></mat-icon>
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'accent'"
|
||||
[svgIcon]="'heroicons_solid:check-circle'"></mat-icon>
|
||||
[svgIcon]="'heroicons_solid:check-circle'"
|
||||
></mat-icon>
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'warn'"
|
||||
[svgIcon]="'heroicons_solid:x-circle'"></mat-icon>
|
||||
[svgIcon]="'heroicons_solid:x-circle'"
|
||||
></mat-icon>
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'basic'"
|
||||
[svgIcon]="'heroicons_solid:check-circle'"></mat-icon>
|
||||
[svgIcon]="'heroicons_solid:check-circle'"
|
||||
></mat-icon>
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'info'"
|
||||
[svgIcon]="'heroicons_solid:information-circle'"></mat-icon>
|
||||
[svgIcon]="'heroicons_solid:information-circle'"
|
||||
></mat-icon>
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'success'"
|
||||
[svgIcon]="'heroicons_solid:check-circle'"></mat-icon>
|
||||
[svgIcon]="'heroicons_solid:check-circle'"
|
||||
></mat-icon>
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'warning'"
|
||||
[svgIcon]="'heroicons_solid:exclamation-triangle'"></mat-icon>
|
||||
[svgIcon]="'heroicons_solid:exclamation-triangle'"
|
||||
></mat-icon>
|
||||
|
||||
<mat-icon
|
||||
*ngIf="type === 'error'"
|
||||
[svgIcon]="'heroicons_solid:x-circle'"></mat-icon>
|
||||
|
||||
[svgIcon]="'heroicons_solid:x-circle'"
|
||||
></mat-icon>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="fuse-alert-content">
|
||||
|
||||
<div class="fuse-alert-title">
|
||||
<ng-content select="[fuseAlertTitle]"></ng-content>
|
||||
</div>
|
||||
@ -68,15 +67,14 @@
|
||||
<div class="fuse-alert-message">
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Dismiss button -->
|
||||
<button
|
||||
class="fuse-alert-dismiss-button"
|
||||
mat-icon-button
|
||||
(click)="dismiss()">
|
||||
(click)="dismiss()"
|
||||
>
|
||||
<mat-icon [svgIcon]="'heroicons_solid:x-mark'"></mat-icon>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
@ -33,7 +33,6 @@ fuse-alert {
|
||||
}
|
||||
|
||||
.fuse-alert-default-icon {
|
||||
|
||||
.mat-icon {
|
||||
@apply icon-size-5;
|
||||
}
|
||||
@ -70,7 +69,6 @@ fuse-alert {
|
||||
|
||||
/* Alert that comes after the title */
|
||||
+ .fuse-alert-message {
|
||||
|
||||
&:not(:empty) {
|
||||
margin-top: 4px;
|
||||
}
|
||||
@ -108,9 +106,7 @@ fuse-alert {
|
||||
|
||||
/* Dismissible */
|
||||
&.fuse-alert-dismissible {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-content {
|
||||
margin-right: 32px;
|
||||
}
|
||||
@ -118,9 +114,7 @@ fuse-alert {
|
||||
}
|
||||
|
||||
&:not(.fuse-alert-dismissible) {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-dismiss-button {
|
||||
display: none !important;
|
||||
}
|
||||
@ -129,12 +123,11 @@ fuse-alert {
|
||||
|
||||
/* Border */
|
||||
&.fuse-alert-appearance-border {
|
||||
|
||||
.fuse-alert-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
@apply shadow-md bg-card;
|
||||
@apply bg-card shadow-md;
|
||||
|
||||
.fuse-alert-border {
|
||||
position: absolute;
|
||||
@ -151,9 +144,7 @@ fuse-alert {
|
||||
|
||||
/* Primary */
|
||||
&.fuse-alert-type-primary {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-primary;
|
||||
}
|
||||
@ -188,9 +179,7 @@ fuse-alert {
|
||||
|
||||
/* Accent */
|
||||
&.fuse-alert-type-accent {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-accent;
|
||||
}
|
||||
@ -225,9 +214,7 @@ fuse-alert {
|
||||
|
||||
/* Warn */
|
||||
&.fuse-alert-type-warn {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-warn;
|
||||
}
|
||||
@ -262,9 +249,7 @@ fuse-alert {
|
||||
|
||||
/* Basic */
|
||||
&.fuse-alert-type-basic {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-gray-600;
|
||||
}
|
||||
@ -299,9 +284,7 @@ fuse-alert {
|
||||
|
||||
/* Info */
|
||||
&.fuse-alert-type-info {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-blue-600;
|
||||
}
|
||||
@ -336,9 +319,7 @@ fuse-alert {
|
||||
|
||||
/* Success */
|
||||
&.fuse-alert-type-success {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-green-500;
|
||||
}
|
||||
@ -373,9 +354,7 @@ fuse-alert {
|
||||
|
||||
/* Warning */
|
||||
&.fuse-alert-type-warning {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-amber-500;
|
||||
}
|
||||
@ -410,9 +389,7 @@ fuse-alert {
|
||||
|
||||
/* Error */
|
||||
&.fuse-alert-type-error {
|
||||
|
||||
.fuse-alert-container {
|
||||
|
||||
.fuse-alert-border {
|
||||
@apply bg-red-600;
|
||||
}
|
||||
@ -448,7 +425,6 @@ fuse-alert {
|
||||
|
||||
/* Fill */
|
||||
&.fuse-alert-appearance-fill {
|
||||
|
||||
.fuse-alert-container {
|
||||
border-radius: 6px;
|
||||
|
||||
@ -459,7 +435,6 @@ fuse-alert {
|
||||
|
||||
/* Primary */
|
||||
&.fuse-alert-type-primary {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-primary-600;
|
||||
|
||||
@ -476,14 +451,13 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-primary-800 bg-primary-200;
|
||||
@apply bg-primary-200 text-primary-800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Accent */
|
||||
&.fuse-alert-type-accent {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-accent-600;
|
||||
|
||||
@ -500,14 +474,13 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-accent-800 bg-accent-200;
|
||||
@apply bg-accent-200 text-accent-800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Warn */
|
||||
&.fuse-alert-type-warn {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-warn-600;
|
||||
|
||||
@ -524,14 +497,13 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-warn-800 bg-warn-200;
|
||||
@apply bg-warn-200 text-warn-800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Basic */
|
||||
&.fuse-alert-type-basic {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-gray-600;
|
||||
|
||||
@ -555,7 +527,6 @@ fuse-alert {
|
||||
|
||||
/* Info */
|
||||
&.fuse-alert-type-info {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-blue-600;
|
||||
|
||||
@ -579,7 +550,6 @@ fuse-alert {
|
||||
|
||||
/* Success */
|
||||
&.fuse-alert-type-success {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-green-600;
|
||||
|
||||
@ -603,7 +573,6 @@ fuse-alert {
|
||||
|
||||
/* Warning */
|
||||
&.fuse-alert-type-warning {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-amber-500;
|
||||
|
||||
@ -627,7 +596,6 @@ fuse-alert {
|
||||
|
||||
/* Error */
|
||||
&.fuse-alert-type-error {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-red-600;
|
||||
|
||||
@ -652,16 +620,14 @@ fuse-alert {
|
||||
|
||||
/* Outline */
|
||||
&.fuse-alert-appearance-outline {
|
||||
|
||||
.fuse-alert-container {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* Primary */
|
||||
&.fuse-alert-type-primary {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-primary-50 ring-1 ring-primary-400 ring-inset;
|
||||
@apply bg-primary-50 ring-1 ring-inset ring-primary-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-primary-600;
|
||||
@ -677,7 +643,7 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-primary-800 bg-primary-200;
|
||||
@apply bg-primary-200 text-primary-800;
|
||||
}
|
||||
|
||||
.dark & {
|
||||
@ -701,9 +667,8 @@ fuse-alert {
|
||||
|
||||
/* Accent */
|
||||
&.fuse-alert-type-accent {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-accent-100 ring-1 ring-accent-400 ring-inset;
|
||||
@apply bg-accent-100 ring-1 ring-inset ring-accent-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-accent-600;
|
||||
@ -719,7 +684,7 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-accent-800 bg-accent-200;
|
||||
@apply bg-accent-200 text-accent-800;
|
||||
}
|
||||
|
||||
.dark & {
|
||||
@ -743,9 +708,8 @@ fuse-alert {
|
||||
|
||||
/* Warn */
|
||||
&.fuse-alert-type-warn {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-warn-50 ring-1 ring-warn-400 ring-inset;
|
||||
@apply bg-warn-50 ring-1 ring-inset ring-warn-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-warn-600;
|
||||
@ -761,7 +725,7 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-warn-800 bg-warn-200;
|
||||
@apply bg-warn-200 text-warn-800;
|
||||
}
|
||||
|
||||
.dark & {
|
||||
@ -785,9 +749,8 @@ fuse-alert {
|
||||
|
||||
/* Basic */
|
||||
&.fuse-alert-type-basic {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-gray-100 ring-1 ring-gray-400 ring-inset;
|
||||
@apply bg-gray-100 ring-1 ring-inset ring-gray-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-gray-600;
|
||||
@ -827,9 +790,8 @@ fuse-alert {
|
||||
|
||||
/* Info */
|
||||
&.fuse-alert-type-info {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-blue-50 ring-1 ring-blue-400 ring-inset;
|
||||
@apply bg-blue-50 ring-1 ring-inset ring-blue-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-blue-600;
|
||||
@ -869,9 +831,8 @@ fuse-alert {
|
||||
|
||||
/* Success */
|
||||
&.fuse-alert-type-success {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-green-50 ring-1 ring-green-400 ring-inset;
|
||||
@apply bg-green-50 ring-1 ring-inset ring-green-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-green-600;
|
||||
@ -911,9 +872,8 @@ fuse-alert {
|
||||
|
||||
/* Warning */
|
||||
&.fuse-alert-type-warning {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-amber-50 ring-1 ring-amber-400 ring-inset;
|
||||
@apply bg-amber-50 ring-1 ring-inset ring-amber-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-amber-600;
|
||||
@ -953,9 +913,8 @@ fuse-alert {
|
||||
|
||||
/* Error */
|
||||
&.fuse-alert-type-error {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-red-50 ring-1 ring-red-400 ring-inset;
|
||||
@apply bg-red-50 ring-1 ring-inset ring-red-400;
|
||||
|
||||
.fuse-alert-icon {
|
||||
@apply text-red-600;
|
||||
@ -996,14 +955,12 @@ fuse-alert {
|
||||
|
||||
/* Soft */
|
||||
&.fuse-alert-appearance-soft {
|
||||
|
||||
.fuse-alert-container {
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
/* Primary */
|
||||
&.fuse-alert-type-primary {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-primary-50;
|
||||
|
||||
@ -1021,7 +978,7 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-primary-800 bg-primary-200;
|
||||
@apply bg-primary-200 text-primary-800;
|
||||
}
|
||||
|
||||
.dark & {
|
||||
@ -1045,7 +1002,6 @@ fuse-alert {
|
||||
|
||||
/* Accent */
|
||||
&.fuse-alert-type-accent {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-accent-100;
|
||||
|
||||
@ -1063,7 +1019,7 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-accent-800 bg-accent-200;
|
||||
@apply bg-accent-200 text-accent-800;
|
||||
}
|
||||
|
||||
.dark & {
|
||||
@ -1087,7 +1043,6 @@ fuse-alert {
|
||||
|
||||
/* Warn */
|
||||
&.fuse-alert-type-warn {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-warn-50;
|
||||
|
||||
@ -1105,7 +1060,7 @@ fuse-alert {
|
||||
}
|
||||
|
||||
code {
|
||||
@apply text-warn-800 bg-warn-200;
|
||||
@apply bg-warn-200 text-warn-800;
|
||||
}
|
||||
|
||||
.dark & {
|
||||
@ -1129,7 +1084,6 @@ fuse-alert {
|
||||
|
||||
/* Basic */
|
||||
&.fuse-alert-type-basic {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-gray-100;
|
||||
|
||||
@ -1171,7 +1125,6 @@ fuse-alert {
|
||||
|
||||
/* Info */
|
||||
&.fuse-alert-type-info {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-blue-50;
|
||||
|
||||
@ -1213,7 +1166,6 @@ fuse-alert {
|
||||
|
||||
/* Success */
|
||||
&.fuse-alert-type-success {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-green-50;
|
||||
|
||||
@ -1255,7 +1207,6 @@ fuse-alert {
|
||||
|
||||
/* Warning */
|
||||
&.fuse-alert-type-warning {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-amber-50;
|
||||
|
||||
@ -1297,7 +1248,6 @@ fuse-alert {
|
||||
|
||||
/* Error */
|
||||
&.fuse-alert-type-error {
|
||||
|
||||
.fuse-alert-container {
|
||||
@apply bg-red-50;
|
||||
|
||||
|
@ -1,27 +1,43 @@
|
||||
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { NgIf } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, inject, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
EventEmitter,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
ViewEncapsulation,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
import { FuseAlertService } from '@fuse/components/alert/alert.service';
|
||||
import { FuseAlertAppearance, FuseAlertType } from '@fuse/components/alert/alert.types';
|
||||
import {
|
||||
FuseAlertAppearance,
|
||||
FuseAlertType,
|
||||
} from '@fuse/components/alert/alert.types';
|
||||
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
import { Subject, filter, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-alert',
|
||||
templateUrl : './alert.component.html',
|
||||
styleUrls : ['./alert.component.scss'],
|
||||
encapsulation : ViewEncapsulation.None,
|
||||
selector: 'fuse-alert',
|
||||
templateUrl: './alert.component.html',
|
||||
styleUrls: ['./alert.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
animations : fuseAnimations,
|
||||
exportAs : 'fuseAlert',
|
||||
standalone : true,
|
||||
imports : [NgIf, MatIconModule, MatButtonModule],
|
||||
animations: fuseAnimations,
|
||||
exportAs: 'fuseAlert',
|
||||
standalone: true,
|
||||
imports: [NgIf, MatIconModule, MatButtonModule],
|
||||
})
|
||||
export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_dismissible: BooleanInput;
|
||||
static ngAcceptInputType_dismissed: BooleanInput;
|
||||
@ -38,7 +54,8 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
@Input() name: string = this._fuseUtilsService.randomId();
|
||||
@Input() showIcon: boolean = true;
|
||||
@Input() type: FuseAlertType = 'primary';
|
||||
@Output() readonly dismissedChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
@Output() readonly dismissedChanged: EventEmitter<boolean> =
|
||||
new EventEmitter<boolean>();
|
||||
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
|
||||
@ -49,25 +66,24 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Host binding for component classes
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
@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',
|
||||
'fuse-alert-appearance-border': this.appearance === 'border',
|
||||
'fuse-alert-appearance-fill': this.appearance === 'fill',
|
||||
'fuse-alert-appearance-outline': this.appearance === 'outline',
|
||||
'fuse-alert-appearance-soft' : this.appearance === 'soft',
|
||||
'fuse-alert-dismissed' : this.dismissed,
|
||||
'fuse-alert-dismissible' : this.dismissible,
|
||||
'fuse-alert-show-icon' : this.showIcon,
|
||||
'fuse-alert-type-primary' : this.type === 'primary',
|
||||
'fuse-alert-type-accent' : this.type === 'accent',
|
||||
'fuse-alert-type-warn' : this.type === 'warn',
|
||||
'fuse-alert-type-basic' : this.type === 'basic',
|
||||
'fuse-alert-type-info' : this.type === 'info',
|
||||
'fuse-alert-type-success' : this.type === 'success',
|
||||
'fuse-alert-type-warning' : this.type === 'warning',
|
||||
'fuse-alert-type-error' : this.type === 'error',
|
||||
'fuse-alert-appearance-soft': this.appearance === 'soft',
|
||||
'fuse-alert-dismissed': this.dismissed,
|
||||
'fuse-alert-dismissible': this.dismissible,
|
||||
'fuse-alert-show-icon': this.showIcon,
|
||||
'fuse-alert-type-primary': this.type === 'primary',
|
||||
'fuse-alert-type-accent': this.type === 'accent',
|
||||
'fuse-alert-type-warn': this.type === 'warn',
|
||||
'fuse-alert-type-basic': this.type === 'basic',
|
||||
'fuse-alert-type-info': this.type === 'info',
|
||||
'fuse-alert-type-success': this.type === 'success',
|
||||
'fuse-alert-type-warning': this.type === 'warning',
|
||||
'fuse-alert-type-error': this.type === 'error',
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
@ -81,46 +97,46 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Dismissed
|
||||
if ( 'dismissed' in changes )
|
||||
{
|
||||
if ('dismissed' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.dismissed = coerceBooleanProperty(changes.dismissed.currentValue);
|
||||
this.dismissed = coerceBooleanProperty(
|
||||
changes.dismissed.currentValue
|
||||
);
|
||||
|
||||
// Dismiss/show the alert
|
||||
this._toggleDismiss(this.dismissed);
|
||||
}
|
||||
|
||||
// Dismissible
|
||||
if ( 'dismissible' in changes )
|
||||
{
|
||||
if ('dismissible' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.dismissible = coerceBooleanProperty(changes.dismissible.currentValue);
|
||||
this.dismissible = coerceBooleanProperty(
|
||||
changes.dismissible.currentValue
|
||||
);
|
||||
}
|
||||
|
||||
// Show icon
|
||||
if ( 'showIcon' in changes )
|
||||
{
|
||||
if ('showIcon' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.showIcon = coerceBooleanProperty(changes.showIcon.currentValue);
|
||||
this.showIcon = coerceBooleanProperty(
|
||||
changes.showIcon.currentValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Subscribe to the dismiss calls
|
||||
this._fuseAlertService.onDismiss
|
||||
.pipe(
|
||||
filter(name => this.name === name),
|
||||
takeUntil(this._unsubscribeAll),
|
||||
filter((name) => this.name === name),
|
||||
takeUntil(this._unsubscribeAll)
|
||||
)
|
||||
.subscribe(() =>
|
||||
{
|
||||
.subscribe(() => {
|
||||
// Dismiss the alert
|
||||
this.dismiss();
|
||||
});
|
||||
@ -128,11 +144,10 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
// Subscribe to the show calls
|
||||
this._fuseAlertService.onShow
|
||||
.pipe(
|
||||
filter(name => this.name === name),
|
||||
takeUntil(this._unsubscribeAll),
|
||||
filter((name) => this.name === name),
|
||||
takeUntil(this._unsubscribeAll)
|
||||
)
|
||||
.subscribe(() =>
|
||||
{
|
||||
.subscribe(() => {
|
||||
// Show the alert
|
||||
this.show();
|
||||
});
|
||||
@ -141,8 +156,7 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
@ -155,11 +169,9 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Dismiss the alert
|
||||
*/
|
||||
dismiss(): void
|
||||
{
|
||||
dismiss(): void {
|
||||
// Return if the alert is already dismissed
|
||||
if ( this.dismissed )
|
||||
{
|
||||
if (this.dismissed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -170,11 +182,9 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Show the dismissed alert
|
||||
*/
|
||||
show(): void
|
||||
{
|
||||
show(): void {
|
||||
// Return if the alert is already showing
|
||||
if ( !this.dismissed )
|
||||
{
|
||||
if (!this.dismissed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -192,11 +202,9 @@ export class FuseAlertComponent implements OnChanges, OnInit, OnDestroy
|
||||
* @param dismissed
|
||||
* @private
|
||||
*/
|
||||
private _toggleDismiss(dismissed: boolean): void
|
||||
{
|
||||
private _toggleDismiss(dismissed: boolean): void {
|
||||
// Return if the alert is not dismissible
|
||||
if ( !this.dismissible )
|
||||
{
|
||||
if (!this.dismissible) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable, ReplaySubject } from 'rxjs';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseAlertService
|
||||
{
|
||||
private readonly _onDismiss: ReplaySubject<string> = new ReplaySubject<string>(1);
|
||||
private readonly _onShow: ReplaySubject<string> = new ReplaySubject<string>(1);
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseAlertService {
|
||||
private readonly _onDismiss: ReplaySubject<string> =
|
||||
new ReplaySubject<string>(1);
|
||||
private readonly _onShow: ReplaySubject<string> = new ReplaySubject<string>(
|
||||
1
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Accessors
|
||||
@ -14,16 +16,14 @@ export class FuseAlertService
|
||||
/**
|
||||
* Getter for onDismiss
|
||||
*/
|
||||
get onDismiss(): Observable<any>
|
||||
{
|
||||
get onDismiss(): Observable<any> {
|
||||
return this._onDismiss.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for onShow
|
||||
*/
|
||||
get onShow(): Observable<any>
|
||||
{
|
||||
get onShow(): Observable<any> {
|
||||
return this._onShow.asObservable();
|
||||
}
|
||||
|
||||
@ -36,11 +36,9 @@ export class FuseAlertService
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
dismiss(name: string): void
|
||||
{
|
||||
dismiss(name: string): void {
|
||||
// Return if the name is not provided
|
||||
if ( !name )
|
||||
{
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -53,16 +51,13 @@ export class FuseAlertService
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
show(name: string): void
|
||||
{
|
||||
show(name: string): void {
|
||||
// Return if the name is not provided
|
||||
if ( !name )
|
||||
{
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute the observable
|
||||
this._onShow.next(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
export type FuseAlertAppearance =
|
||||
| 'border'
|
||||
| 'fill'
|
||||
| 'outline'
|
||||
| 'soft';
|
||||
export type FuseAlertAppearance = 'border' | 'fill' | 'outline' | 'soft';
|
||||
|
||||
export type FuseAlertType =
|
||||
| 'primary'
|
||||
|
@ -1,6 +1,5 @@
|
||||
<!-- Flippable card -->
|
||||
<ng-container *ngIf="flippable">
|
||||
|
||||
<!-- Front -->
|
||||
<div class="fuse-card-front">
|
||||
<ng-content select="[fuseCardFront]"></ng-content>
|
||||
@ -10,21 +9,15 @@
|
||||
<div class="fuse-card-back">
|
||||
<ng-content select="[fuseCardBack]"></ng-content>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<!-- Normal card -->
|
||||
<ng-container *ngIf="!flippable">
|
||||
|
||||
<!-- Content -->
|
||||
<ng-content></ng-content>
|
||||
|
||||
<!-- Expansion -->
|
||||
<div
|
||||
class="fuse-card-expansion"
|
||||
*ngIf="expanded"
|
||||
[@expandCollapse]>
|
||||
<div class="fuse-card-expansion" *ngIf="expanded" [@expandCollapse]>
|
||||
<ng-content select="[fuseCardExpansion]"></ng-content>
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
@ -2,7 +2,7 @@ fuse-card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
@apply rounded-2xl shadow bg-card;
|
||||
@apply bg-card rounded-2xl shadow;
|
||||
|
||||
/* Flippable */
|
||||
&.fuse-card-flippable {
|
||||
@ -15,7 +15,6 @@ fuse-card {
|
||||
@apply shadow-none;
|
||||
|
||||
&.fuse-card-face-back {
|
||||
|
||||
.fuse-card-front {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
@ -35,9 +34,12 @@ fuse-card {
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
z-index: 10;
|
||||
transition: transform 0.5s ease-out 0s, visibility 0s ease-in 0.2s, opacity 0s ease-in 0.2s;
|
||||
transition:
|
||||
transform 0.5s ease-out 0s,
|
||||
visibility 0s ease-in 0.2s,
|
||||
opacity 0s ease-in 0.2s;
|
||||
backface-visibility: hidden;
|
||||
@apply rounded-2xl shadow bg-card;
|
||||
@apply bg-card rounded-2xl shadow;
|
||||
}
|
||||
|
||||
.fuse-card-front {
|
||||
|
@ -1,21 +1,27 @@
|
||||
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { NgIf } from '@angular/common';
|
||||
import { Component, HostBinding, Input, OnChanges, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnChanges,
|
||||
SimpleChanges,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
import { FuseCardFace } from '@fuse/components/card/card.types';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-card',
|
||||
templateUrl : './card.component.html',
|
||||
styleUrls : ['./card.component.scss'],
|
||||
selector: 'fuse-card',
|
||||
templateUrl: './card.component.html',
|
||||
styleUrls: ['./card.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
animations : fuseAnimations,
|
||||
exportAs : 'fuseCard',
|
||||
standalone : true,
|
||||
imports : [NgIf],
|
||||
animations: fuseAnimations,
|
||||
exportAs: 'fuseCard',
|
||||
standalone: true,
|
||||
imports: [NgIf],
|
||||
})
|
||||
export class FuseCardComponent implements OnChanges
|
||||
{
|
||||
export class FuseCardComponent implements OnChanges {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_expanded: BooleanInput;
|
||||
static ngAcceptInputType_flippable: BooleanInput;
|
||||
@ -32,14 +38,13 @@ export class FuseCardComponent implements OnChanges
|
||||
/**
|
||||
* Host binding for component classes
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
@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-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,
|
||||
'fuse-card-flippable': this.flippable,
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
@ -53,20 +58,21 @@ export class FuseCardComponent implements OnChanges
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Expanded
|
||||
if ( 'expanded' in changes )
|
||||
{
|
||||
if ('expanded' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.expanded = coerceBooleanProperty(changes.expanded.currentValue);
|
||||
this.expanded = coerceBooleanProperty(
|
||||
changes.expanded.currentValue
|
||||
);
|
||||
}
|
||||
|
||||
// Flippable
|
||||
if ( 'flippable' in changes )
|
||||
{
|
||||
if ('flippable' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.flippable = coerceBooleanProperty(changes.flippable.currentValue);
|
||||
this.flippable = coerceBooleanProperty(
|
||||
changes.flippable.currentValue
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1 @@
|
||||
export type FuseCardFace =
|
||||
| 'front'
|
||||
| 'back';
|
||||
export type FuseCardFace = 'front' | 'back';
|
||||
|
@ -12,14 +12,15 @@ fuse-drawer {
|
||||
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);
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.35);
|
||||
@apply bg-card;
|
||||
|
||||
/* Animations */
|
||||
&.fuse-drawer-animations-enabled {
|
||||
transition-duration: 400ms;
|
||||
transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
transition-property: visibility, margin-left, margin-right, transform, width, max-width, min-width;
|
||||
transition-property: visibility, margin-left, margin-right, transform,
|
||||
width, max-width, min-width;
|
||||
|
||||
.fuse-drawer-content {
|
||||
transition-duration: 400ms;
|
||||
@ -42,7 +43,6 @@ fuse-drawer {
|
||||
|
||||
/* Left position */
|
||||
&.fuse-drawer-position-left {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-drawer-mode-side {
|
||||
margin-left: calc(var(--fuse-drawer-width) * -1);
|
||||
@ -70,7 +70,6 @@ fuse-drawer {
|
||||
|
||||
/* Right position */
|
||||
&.fuse-drawer-position-right {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-drawer-mode-side {
|
||||
margin-right: calc(var(--fuse-drawer-width) * -1);
|
||||
|
@ -1,20 +1,42 @@
|
||||
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
|
||||
import {
|
||||
animate,
|
||||
AnimationBuilder,
|
||||
AnimationPlayer,
|
||||
style,
|
||||
} from '@angular/animations';
|
||||
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { Component, ElementRef, EventEmitter, HostBinding, HostListener, inject, Input, OnChanges, OnDestroy, OnInit, Output, Renderer2, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
HostBinding,
|
||||
HostListener,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
Renderer2,
|
||||
SimpleChanges,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { FuseDrawerService } from '@fuse/components/drawer/drawer.service';
|
||||
import { FuseDrawerMode, FuseDrawerPosition } from '@fuse/components/drawer/drawer.types';
|
||||
import {
|
||||
FuseDrawerMode,
|
||||
FuseDrawerPosition,
|
||||
} from '@fuse/components/drawer/drawer.types';
|
||||
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-drawer',
|
||||
templateUrl : './drawer.component.html',
|
||||
styleUrls : ['./drawer.component.scss'],
|
||||
selector: 'fuse-drawer',
|
||||
templateUrl: './drawer.component.html',
|
||||
styleUrls: ['./drawer.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
exportAs : 'fuseDrawer',
|
||||
standalone : true,
|
||||
exportAs: 'fuseDrawer',
|
||||
standalone: true,
|
||||
})
|
||||
export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_fixed: BooleanInput;
|
||||
static ngAcceptInputType_opened: BooleanInput;
|
||||
@ -33,10 +55,14 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
@Input() opened: boolean = false;
|
||||
@Input() position: FuseDrawerPosition = 'left';
|
||||
@Input() transparentOverlay: boolean = false;
|
||||
@Output() readonly fixedChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
@Output() readonly modeChanged: EventEmitter<FuseDrawerMode> = new EventEmitter<FuseDrawerMode>();
|
||||
@Output() readonly openedChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
@Output() readonly positionChanged: EventEmitter<FuseDrawerPosition> = new EventEmitter<FuseDrawerPosition>();
|
||||
@Output() readonly fixedChanged: EventEmitter<boolean> =
|
||||
new EventEmitter<boolean>();
|
||||
@Output() readonly modeChanged: EventEmitter<FuseDrawerMode> =
|
||||
new EventEmitter<FuseDrawerMode>();
|
||||
@Output() readonly openedChanged: EventEmitter<boolean> =
|
||||
new EventEmitter<boolean>();
|
||||
@Output() readonly positionChanged: EventEmitter<FuseDrawerPosition> =
|
||||
new EventEmitter<FuseDrawerPosition>();
|
||||
|
||||
private _animationsEnabled: boolean = false;
|
||||
private readonly _handleOverlayClick = (): void => this.close();
|
||||
@ -51,15 +77,14 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Host binding for component classes
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
@HostBinding('class') get classList(): any {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
return {
|
||||
'fuse-drawer-animations-enabled' : this._animationsEnabled,
|
||||
'fuse-drawer-fixed' : this.fixed,
|
||||
'fuse-drawer-hover' : this._hovered,
|
||||
[`fuse-drawer-mode-${this.mode}`] : true,
|
||||
'fuse-drawer-opened' : this.opened,
|
||||
'fuse-drawer-animations-enabled': this._animationsEnabled,
|
||||
'fuse-drawer-fixed': this.fixed,
|
||||
'fuse-drawer-hover': this._hovered,
|
||||
[`fuse-drawer-mode-${this.mode}`]: true,
|
||||
'fuse-drawer-opened': this.opened,
|
||||
[`fuse-drawer-position-${this.position}`]: true,
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
@ -68,10 +93,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Host binding for component inline styles
|
||||
*/
|
||||
@HostBinding('style') get styleList(): any
|
||||
{
|
||||
@HostBinding('style') get styleList(): any {
|
||||
return {
|
||||
'visibility': this.opened ? 'visible' : 'hidden',
|
||||
visibility: this.opened ? 'visible' : 'hidden',
|
||||
};
|
||||
}
|
||||
|
||||
@ -85,8 +109,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
* @private
|
||||
*/
|
||||
@HostListener('mouseenter')
|
||||
private _onMouseenter(): void
|
||||
{
|
||||
private _onMouseenter(): void {
|
||||
// Enable the animations
|
||||
this._enableAnimations();
|
||||
|
||||
@ -100,8 +123,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
* @private
|
||||
*/
|
||||
@HostListener('mouseleave')
|
||||
private _onMouseleave(): void
|
||||
{
|
||||
private _onMouseleave(): void {
|
||||
// Enable the animations
|
||||
this._enableAnimations();
|
||||
|
||||
@ -118,11 +140,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Fixed
|
||||
if ( 'fixed' in changes )
|
||||
{
|
||||
if ('fixed' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.fixed = coerceBooleanProperty(changes.fixed.currentValue);
|
||||
|
||||
@ -131,8 +151,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
}
|
||||
|
||||
// Mode
|
||||
if ( 'mode' in changes )
|
||||
{
|
||||
if ('mode' in changes) {
|
||||
// Get the previous and current values
|
||||
const previousMode = changes.mode.previousValue;
|
||||
const currentMode = changes.mode.currentValue;
|
||||
@ -141,18 +160,15 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
this._disableAnimations();
|
||||
|
||||
// If the mode changes: 'over -> side'
|
||||
if ( previousMode === 'over' && currentMode === 'side' )
|
||||
{
|
||||
if (previousMode === 'over' && currentMode === 'side') {
|
||||
// Hide the overlay
|
||||
this._hideOverlay();
|
||||
}
|
||||
|
||||
// If the mode changes: 'side -> over'
|
||||
if ( previousMode === 'side' && currentMode === 'over' )
|
||||
{
|
||||
if (previousMode === 'side' && currentMode === 'over') {
|
||||
// If the drawer is opened
|
||||
if ( this.opened )
|
||||
{
|
||||
if (this.opened) {
|
||||
// Show the overlay
|
||||
this._showOverlay();
|
||||
}
|
||||
@ -164,15 +180,13 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
// Enable the animations after a delay
|
||||
// The delay must be bigger than the current transition-duration
|
||||
// to make sure nothing will be animated while the mode is changing
|
||||
setTimeout(() =>
|
||||
{
|
||||
setTimeout(() => {
|
||||
this._enableAnimations();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// Opened
|
||||
if ( 'opened' in changes )
|
||||
{
|
||||
if ('opened' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
const open = coerceBooleanProperty(changes.opened.currentValue);
|
||||
|
||||
@ -181,25 +195,24 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
}
|
||||
|
||||
// Position
|
||||
if ( 'position' in changes )
|
||||
{
|
||||
if ('position' in changes) {
|
||||
// Execute the observable
|
||||
this.positionChanged.next(this.position);
|
||||
}
|
||||
|
||||
// Transparent overlay
|
||||
if ( 'transparentOverlay' in changes )
|
||||
{
|
||||
if ('transparentOverlay' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.transparentOverlay = coerceBooleanProperty(changes.transparentOverlay.currentValue);
|
||||
this.transparentOverlay = coerceBooleanProperty(
|
||||
changes.transparentOverlay.currentValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Register the drawer
|
||||
this._fuseDrawerService.registerComponent(this.name, this);
|
||||
}
|
||||
@ -207,11 +220,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Finish the animation
|
||||
if ( this._player )
|
||||
{
|
||||
if (this._player) {
|
||||
this._player.finish();
|
||||
}
|
||||
|
||||
@ -226,11 +237,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Open the drawer
|
||||
*/
|
||||
open(): void
|
||||
{
|
||||
open(): void {
|
||||
// Return if the drawer has already opened
|
||||
if ( this.opened )
|
||||
{
|
||||
if (this.opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -241,11 +250,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Close the drawer
|
||||
*/
|
||||
close(): void
|
||||
{
|
||||
close(): void {
|
||||
// Return if the drawer has already closed
|
||||
if ( !this.opened )
|
||||
{
|
||||
if (!this.opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -256,14 +263,10 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Toggle the drawer
|
||||
*/
|
||||
toggle(): void
|
||||
{
|
||||
if ( this.opened )
|
||||
{
|
||||
toggle(): void {
|
||||
if (this.opened) {
|
||||
this.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
@ -277,11 +280,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _enableAnimations(): void
|
||||
{
|
||||
private _enableAnimations(): void {
|
||||
// Return if the animations are already enabled
|
||||
if ( this._animationsEnabled )
|
||||
{
|
||||
if (this._animationsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -294,11 +295,9 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _disableAnimations(): void
|
||||
{
|
||||
private _disableAnimations(): void {
|
||||
// Return if the animations are already disabled
|
||||
if ( !this._animationsEnabled )
|
||||
{
|
||||
if (!this._animationsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -311,8 +310,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _showOverlay(): void
|
||||
{
|
||||
private _showOverlay(): void {
|
||||
// Create the backdrop element
|
||||
this._overlay = this._renderer2.createElement('div');
|
||||
|
||||
@ -320,25 +318,31 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
this._overlay.classList.add('fuse-drawer-overlay');
|
||||
|
||||
// Add a class depending on the fixed option
|
||||
if ( this.fixed )
|
||||
{
|
||||
if (this.fixed) {
|
||||
this._overlay.classList.add('fuse-drawer-overlay-fixed');
|
||||
}
|
||||
|
||||
// Add a class depending on the transparentOverlay option
|
||||
if ( this.transparentOverlay )
|
||||
{
|
||||
if (this.transparentOverlay) {
|
||||
this._overlay.classList.add('fuse-drawer-overlay-transparent');
|
||||
}
|
||||
|
||||
// Append the backdrop to the parent of the drawer
|
||||
this._renderer2.appendChild(this._elementRef.nativeElement.parentElement, this._overlay);
|
||||
this._renderer2.appendChild(
|
||||
this._elementRef.nativeElement.parentElement,
|
||||
this._overlay
|
||||
);
|
||||
|
||||
// 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);
|
||||
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);
|
||||
|
||||
// Play the animation
|
||||
this._player.play();
|
||||
@ -352,29 +356,33 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _hideOverlay(): void
|
||||
{
|
||||
if ( !this._overlay )
|
||||
{
|
||||
private _hideOverlay(): void {
|
||||
if (!this._overlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the leave animation and attach it to the player
|
||||
this._player = this._animationBuilder.build([
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 0})),
|
||||
]).create(this._overlay);
|
||||
this._player = this._animationBuilder
|
||||
.build([
|
||||
animate(
|
||||
'300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
|
||||
style({ opacity: 0 })
|
||||
),
|
||||
])
|
||||
.create(this._overlay);
|
||||
|
||||
// Play the animation
|
||||
this._player.play();
|
||||
|
||||
// Once the animation is done...
|
||||
this._player.onDone(() =>
|
||||
{
|
||||
this._player.onDone(() => {
|
||||
// If the overlay still exists...
|
||||
if ( this._overlay )
|
||||
{
|
||||
if (this._overlay) {
|
||||
// Remove the event listener
|
||||
this._overlay.removeEventListener('click', this._handleOverlayClick);
|
||||
this._overlay.removeEventListener(
|
||||
'click',
|
||||
this._handleOverlayClick
|
||||
);
|
||||
|
||||
// Remove the overlay
|
||||
this._overlay.parentNode.removeChild(this._overlay);
|
||||
@ -389,8 +397,7 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
* @param open
|
||||
* @private
|
||||
*/
|
||||
private _toggleOpened(open: boolean): void
|
||||
{
|
||||
private _toggleOpened(open: boolean): void {
|
||||
// Set the opened
|
||||
this.opened = open;
|
||||
|
||||
@ -398,16 +405,13 @@ export class FuseDrawerComponent implements OnChanges, OnInit, OnDestroy
|
||||
this._enableAnimations();
|
||||
|
||||
// If the mode is 'over'
|
||||
if ( this.mode === 'over' )
|
||||
{
|
||||
if (this.mode === 'over') {
|
||||
// If the drawer opens, show the overlay
|
||||
if ( open )
|
||||
{
|
||||
if (open) {
|
||||
this._showOverlay();
|
||||
}
|
||||
// Otherwise, close the overlay
|
||||
else
|
||||
{
|
||||
else {
|
||||
this._hideOverlay();
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FuseDrawerComponent } from '@fuse/components/drawer/drawer.component';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseDrawerService
|
||||
{
|
||||
private _componentRegistry: Map<string, FuseDrawerComponent> = new Map<string, FuseDrawerComponent>();
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseDrawerService {
|
||||
private _componentRegistry: Map<string, FuseDrawerComponent> = new Map<
|
||||
string,
|
||||
FuseDrawerComponent
|
||||
>();
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
@ -16,8 +18,7 @@ export class FuseDrawerService
|
||||
* @param name
|
||||
* @param component
|
||||
*/
|
||||
registerComponent(name: string, component: FuseDrawerComponent): void
|
||||
{
|
||||
registerComponent(name: string, component: FuseDrawerComponent): void {
|
||||
this._componentRegistry.set(name, component);
|
||||
}
|
||||
|
||||
@ -26,8 +27,7 @@ export class FuseDrawerService
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
deregisterComponent(name: string): void
|
||||
{
|
||||
deregisterComponent(name: string): void {
|
||||
this._componentRegistry.delete(name);
|
||||
}
|
||||
|
||||
@ -36,8 +36,7 @@ export class FuseDrawerService
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
getComponent(name: string): FuseDrawerComponent | undefined
|
||||
{
|
||||
getComponent(name: string): FuseDrawerComponent | undefined {
|
||||
return this._componentRegistry.get(name);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,3 @@
|
||||
export type FuseDrawerMode =
|
||||
| 'over'
|
||||
| 'side';
|
||||
export type FuseDrawerMode = 'over' | 'side';
|
||||
|
||||
export type FuseDrawerPosition =
|
||||
| 'left'
|
||||
| 'right';
|
||||
export type FuseDrawerPosition = 'left' | 'right';
|
||||
|
@ -2,7 +2,8 @@
|
||||
<button
|
||||
mat-icon-button
|
||||
[matTooltip]="tooltip || 'Toggle Fullscreen'"
|
||||
(click)="toggleFullscreen()">
|
||||
(click)="toggleFullscreen()"
|
||||
>
|
||||
<ng-container [ngTemplateOutlet]="iconTpl || defaultIconTpl"></ng-container>
|
||||
</button>
|
||||
|
||||
|
@ -1,5 +1,12 @@
|
||||
import { DOCUMENT, NgTemplateOutlet } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, inject, Input, TemplateRef, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
TemplateRef,
|
||||
ViewEncapsulation,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
@ -11,10 +18,14 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
exportAs: 'fuseFullscreen',
|
||||
standalone: true,
|
||||
imports: [MatButtonModule, MatTooltipModule, NgTemplateOutlet, MatIconModule],
|
||||
imports: [
|
||||
MatButtonModule,
|
||||
MatTooltipModule,
|
||||
NgTemplateOutlet,
|
||||
MatIconModule,
|
||||
],
|
||||
})
|
||||
export class FuseFullscreenComponent
|
||||
{
|
||||
export class FuseFullscreenComponent {
|
||||
private _document = inject(DOCUMENT);
|
||||
|
||||
@Input() iconTpl: TemplateRef<any>;
|
||||
@ -27,10 +38,8 @@ export class FuseFullscreenComponent
|
||||
/**
|
||||
* Toggle the fullscreen mode
|
||||
*/
|
||||
toggleFullscreen(): void
|
||||
{
|
||||
if (!this._document.fullscreenEnabled)
|
||||
{
|
||||
toggleFullscreen(): void {
|
||||
if (!this._document.fullscreenEnabled) {
|
||||
console.log('Fullscreen is not available in this browser.');
|
||||
return;
|
||||
}
|
||||
@ -39,17 +48,12 @@ export class FuseFullscreenComponent
|
||||
const fullScreen = this._document.fullscreenElement;
|
||||
|
||||
// Toggle the fullscreen
|
||||
if (fullScreen)
|
||||
{
|
||||
if (fullScreen) {
|
||||
this._document.exitFullscreen();
|
||||
}
|
||||
else
|
||||
{
|
||||
this._document.documentElement.requestFullscreen()
|
||||
.catch(() =>
|
||||
{
|
||||
console.error('Entering fullscreen mode failed.');
|
||||
});
|
||||
} else {
|
||||
this._document.documentElement.requestFullscreen().catch(() => {
|
||||
console.error('Entering fullscreen mode failed.');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
<ng-content></ng-content>
|
||||
|
||||
<!-- @formatter:off -->
|
||||
<!-- prettier-ignore -->
|
||||
<ng-template let-highlightedCode="highlightedCode" let-lang="lang">
|
||||
<div class="fuse-highlight fuse-highlight-code-container">
|
||||
<pre [ngClass]="'language-' + lang"><code [ngClass]="'language-' + lang" [innerHTML]="highlightedCode"></code></pre>
|
||||
</div>
|
||||
</ng-template>
|
||||
<!-- @formatter:on -->
|
||||
|
@ -1,20 +1,34 @@
|
||||
import { NgClass } from '@angular/common';
|
||||
import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, EmbeddedViewRef, inject, Input, OnChanges, SecurityContext, SimpleChanges, TemplateRef, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
EmbeddedViewRef,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
SecurityContext,
|
||||
SimpleChanges,
|
||||
TemplateRef,
|
||||
ViewChild,
|
||||
ViewContainerRef,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { FuseHighlightService } from '@fuse/components/highlight/highlight.service';
|
||||
|
||||
@Component({
|
||||
selector : 'textarea[fuse-highlight]',
|
||||
templateUrl : './highlight.component.html',
|
||||
styleUrls : ['./highlight.component.scss'],
|
||||
encapsulation : ViewEncapsulation.None,
|
||||
selector: 'textarea[fuse-highlight]',
|
||||
templateUrl: './highlight.component.html',
|
||||
styleUrls: ['./highlight.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
exportAs : 'fuseHighlight',
|
||||
standalone : true,
|
||||
imports : [NgClass],
|
||||
exportAs: 'fuseHighlight',
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
})
|
||||
export class FuseHighlightComponent implements OnChanges, AfterViewInit
|
||||
{
|
||||
export class FuseHighlightComponent implements OnChanges, AfterViewInit {
|
||||
private _domSanitizer = inject(DomSanitizer);
|
||||
private _elementRef = inject(ElementRef);
|
||||
private _fuseHighlightService = inject(FuseHighlightService);
|
||||
@ -36,14 +50,11 @@ export class FuseHighlightComponent implements OnChanges, AfterViewInit
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Code & Lang
|
||||
if ( 'code' in changes || 'lang' in changes )
|
||||
{
|
||||
if ('code' in changes || 'lang' in changes) {
|
||||
// Return if the viewContainerRef is not available
|
||||
if ( !this._viewContainerRef.length )
|
||||
{
|
||||
if (!this._viewContainerRef.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -55,18 +66,15 @@ export class FuseHighlightComponent implements OnChanges, AfterViewInit
|
||||
/**
|
||||
* After view init
|
||||
*/
|
||||
ngAfterViewInit(): void
|
||||
{
|
||||
ngAfterViewInit(): void {
|
||||
// Return if there is no language set
|
||||
if ( !this.lang )
|
||||
{
|
||||
if (!this.lang) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no code input, get the code from
|
||||
// the textarea
|
||||
if ( !this.code )
|
||||
{
|
||||
if (!this.code) {
|
||||
// Get the code
|
||||
this.code = this._elementRef.nativeElement.value;
|
||||
}
|
||||
@ -84,41 +92,42 @@ export class FuseHighlightComponent implements OnChanges, AfterViewInit
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _highlightAndInsert(): void
|
||||
{
|
||||
private _highlightAndInsert(): void {
|
||||
// Return if the template reference is not available
|
||||
if ( !this.templateRef )
|
||||
{
|
||||
if (!this.templateRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return if the code or language is not defined
|
||||
if ( !this.code || !this.lang )
|
||||
{
|
||||
if (!this.code || !this.lang) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy the component if there is already one
|
||||
if ( this._viewRef )
|
||||
{
|
||||
if (this._viewRef) {
|
||||
this._viewRef.destroy();
|
||||
this._viewRef = null;
|
||||
}
|
||||
|
||||
// Highlight and sanitize the code just in case
|
||||
this.highlightedCode = this._domSanitizer.sanitize(SecurityContext.HTML, this._fuseHighlightService.highlight(this.code, this.lang));
|
||||
this.highlightedCode = this._domSanitizer.sanitize(
|
||||
SecurityContext.HTML,
|
||||
this._fuseHighlightService.highlight(this.code, this.lang)
|
||||
);
|
||||
|
||||
// Return if the highlighted code is null
|
||||
if ( this.highlightedCode === null )
|
||||
{
|
||||
if (this.highlightedCode === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Render and insert the template
|
||||
this._viewRef = this._viewContainerRef.createEmbeddedView(this.templateRef, {
|
||||
highlightedCode: this.highlightedCode,
|
||||
lang : this.lang,
|
||||
});
|
||||
this._viewRef = this._viewContainerRef.createEmbeddedView(
|
||||
this.templateRef,
|
||||
{
|
||||
highlightedCode: this.highlightedCode,
|
||||
lang: this.lang,
|
||||
}
|
||||
);
|
||||
|
||||
// Detect the changes
|
||||
this._viewRef.detectChanges();
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseHighlightService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseHighlightService {
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -11,13 +10,12 @@ export class FuseHighlightService
|
||||
/**
|
||||
* Highlight
|
||||
*/
|
||||
highlight(code: string, language: string): string
|
||||
{
|
||||
highlight(code: string, language: string): string {
|
||||
// Format the code
|
||||
code = this._format(code);
|
||||
|
||||
// Highlight and return the code
|
||||
return hljs.highlight(code, {language}).value;
|
||||
return hljs.highlight(code, { language }).value;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -32,32 +30,28 @@ export class FuseHighlightService
|
||||
* @param code
|
||||
* @private
|
||||
*/
|
||||
private _format(code: string): string
|
||||
{
|
||||
private _format(code: string): string {
|
||||
let indentation = 0;
|
||||
|
||||
// Split the code into lines and store the lines
|
||||
const lines = code.split('\n');
|
||||
|
||||
// Trim the empty lines around the code block
|
||||
while ( lines.length && lines[0].trim() === '' )
|
||||
{
|
||||
while (lines.length && lines[0].trim() === '') {
|
||||
lines.shift();
|
||||
}
|
||||
|
||||
while ( lines.length && lines[lines.length - 1].trim() === '' )
|
||||
{
|
||||
while (lines.length && lines[lines.length - 1].trim() === '') {
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
// Iterate through the lines
|
||||
lines.filter(line => line.length)
|
||||
.forEach((line, index) =>
|
||||
{
|
||||
lines
|
||||
.filter((line) => line.length)
|
||||
.forEach((line, index) => {
|
||||
// Always get the indentation of the first line so we can
|
||||
// have something to compare with
|
||||
if ( index === 0 )
|
||||
{
|
||||
if (index === 0) {
|
||||
indentation = line.search(/\S|$/);
|
||||
return;
|
||||
}
|
||||
@ -68,6 +62,6 @@ export class FuseHighlightService
|
||||
|
||||
// Iterate through the lines one more time, remove the extra
|
||||
// indentation, join them together and return it
|
||||
return lines.map(line => line.substring(indentation)).join('\n');
|
||||
return lines.map((line) => line.substring(indentation)).join('\n');
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
<ng-container *ngIf="show">
|
||||
<mat-progress-bar
|
||||
[mode]="mode"
|
||||
[value]="progress"></mat-progress-bar>
|
||||
<mat-progress-bar [mode]="mode" [value]="progress"></mat-progress-bar>
|
||||
</ng-container>
|
||||
|
@ -1,21 +1,29 @@
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { NgIf } from '@angular/common';
|
||||
import { Component, inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
SimpleChanges,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { FuseLoadingService } from '@fuse/services/loading';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-loading-bar',
|
||||
templateUrl : './loading-bar.component.html',
|
||||
styleUrls : ['./loading-bar.component.scss'],
|
||||
selector: 'fuse-loading-bar',
|
||||
templateUrl: './loading-bar.component.html',
|
||||
styleUrls: ['./loading-bar.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
exportAs : 'fuseLoadingBar',
|
||||
standalone : true,
|
||||
imports : [NgIf, MatProgressBarModule],
|
||||
exportAs: 'fuseLoadingBar',
|
||||
standalone: true,
|
||||
imports: [NgIf, MatProgressBarModule],
|
||||
})
|
||||
export class FuseLoadingBarComponent implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
export class FuseLoadingBarComponent implements OnChanges, OnInit, OnDestroy {
|
||||
private _fuseLoadingService = inject(FuseLoadingService);
|
||||
|
||||
@Input() autoMode: boolean = true;
|
||||
@ -33,50 +41,44 @@ export class FuseLoadingBarComponent implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Auto mode
|
||||
if ( 'autoMode' in changes )
|
||||
{
|
||||
if ('autoMode' in changes) {
|
||||
// Set the auto mode in the service
|
||||
this._fuseLoadingService.setAutoMode(coerceBooleanProperty(changes.autoMode.currentValue));
|
||||
this._fuseLoadingService.setAutoMode(
|
||||
coerceBooleanProperty(changes.autoMode.currentValue)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Subscribe to the service
|
||||
this._fuseLoadingService.mode$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((value) =>
|
||||
{
|
||||
.subscribe((value) => {
|
||||
this.mode = value;
|
||||
});
|
||||
|
||||
this._fuseLoadingService.progress$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((value) =>
|
||||
{
|
||||
.subscribe((value) => {
|
||||
this.progress = value;
|
||||
});
|
||||
|
||||
this._fuseLoadingService.show$
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((value) =>
|
||||
{
|
||||
.subscribe((value) => {
|
||||
this.show = value;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -1,3 +1,8 @@
|
||||
<div class="flex">
|
||||
<ng-container *ngTemplateOutlet="columnsTemplate; context: { $implicit: distributedColumns }"></ng-container>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="
|
||||
columnsTemplate;
|
||||
context: { $implicit: distributedColumns }
|
||||
"
|
||||
></ng-container>
|
||||
</div>
|
||||
|
@ -1,18 +1,25 @@
|
||||
import { NgTemplateOutlet } from '@angular/common';
|
||||
import { AfterViewInit, Component, Input, OnChanges, SimpleChanges, TemplateRef, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
AfterViewInit,
|
||||
Component,
|
||||
Input,
|
||||
OnChanges,
|
||||
SimpleChanges,
|
||||
TemplateRef,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-masonry',
|
||||
templateUrl : './masonry.component.html',
|
||||
selector: 'fuse-masonry',
|
||||
templateUrl: './masonry.component.html',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
animations : fuseAnimations,
|
||||
exportAs : 'fuseMasonry',
|
||||
standalone : true,
|
||||
imports : [NgTemplateOutlet],
|
||||
animations: fuseAnimations,
|
||||
exportAs: 'fuseMasonry',
|
||||
standalone: true,
|
||||
imports: [NgTemplateOutlet],
|
||||
})
|
||||
export class FuseMasonryComponent implements OnChanges, AfterViewInit
|
||||
{
|
||||
export class FuseMasonryComponent implements OnChanges, AfterViewInit {
|
||||
@Input() columnsTemplate: TemplateRef<any>;
|
||||
@Input() columns: number;
|
||||
@Input() items: any[] = [];
|
||||
@ -27,18 +34,15 @@ export class FuseMasonryComponent implements OnChanges, AfterViewInit
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Columns
|
||||
if ( 'columns' in changes )
|
||||
{
|
||||
if ('columns' in changes) {
|
||||
// Distribute the items
|
||||
this._distributeItems();
|
||||
}
|
||||
|
||||
// Items
|
||||
if ( 'items' in changes )
|
||||
{
|
||||
if ('items' in changes) {
|
||||
// Distribute the items
|
||||
this._distributeItems();
|
||||
}
|
||||
@ -47,8 +51,7 @@ export class FuseMasonryComponent implements OnChanges, AfterViewInit
|
||||
/**
|
||||
* After view init
|
||||
*/
|
||||
ngAfterViewInit(): void
|
||||
{
|
||||
ngAfterViewInit(): void {
|
||||
// Distribute the items for the first time
|
||||
this._distributeItems();
|
||||
}
|
||||
@ -60,21 +63,20 @@ export class FuseMasonryComponent implements OnChanges, AfterViewInit
|
||||
/**
|
||||
* Distribute items into columns
|
||||
*/
|
||||
private _distributeItems(): void
|
||||
{
|
||||
private _distributeItems(): void {
|
||||
// Return an empty array if there are no items
|
||||
if ( this.items.length === 0 )
|
||||
{
|
||||
if (this.items.length === 0) {
|
||||
this.distributedColumns = [];
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare the distributed columns array
|
||||
this.distributedColumns = Array.from(Array(this.columns), item => ({items: []}));
|
||||
this.distributedColumns = Array.from(Array(this.columns), (item) => ({
|
||||
items: [],
|
||||
}));
|
||||
|
||||
// Distribute the items to columns
|
||||
for ( let i = 0; i < this.items.length; i++ )
|
||||
{
|
||||
for (let i = 0; i < this.items.length; i++) {
|
||||
this.distributedColumns[i % this.columns].items.push(this.items[i]);
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,19 @@
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-wrapper"
|
||||
[class.fuse-horizontal-navigation-item-has-subtitle]="!!item.subtitle"
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
>
|
||||
<!-- Item with an internal link -->
|
||||
<ng-container *ngIf="item.link && !item.externalLink && !item.function && !item.disabled">
|
||||
<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}"
|
||||
[ngClass]="{
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
@ -16,18 +22,24 @@
|
||||
[queryParamsHandling]="item.queryParamsHandling ?? null"
|
||||
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link -->
|
||||
<ng-container *ngIf="item.link && item.externalLink && !item.function && !item.disabled">
|
||||
<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 || ''">
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
@ -36,18 +48,27 @@
|
||||
<ng-container *ngIf="!item.link && item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[ngClass]="{
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
(click)="item.function(item)"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an internal link and function -->
|
||||
<ng-container *ngIf="item.link && !item.externalLink && item.function && !item.disabled">
|
||||
<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}"
|
||||
[ngClass]="{
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
@ -56,20 +77,26 @@
|
||||
[routerLinkActive]="'fuse-horizontal-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
(click)="item.function(item)"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link and function -->
|
||||
<ng-container *ngIf="item.link && item.externalLink && item.function && !item.disabled">
|
||||
<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>
|
||||
mat-menu-item
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
@ -78,43 +105,47 @@
|
||||
<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 || ''">
|
||||
[ngClass]="{
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item is disabled -->
|
||||
<ng-container *ngIf="item.disabled">
|
||||
<div class="fuse-horizontal-navigation-item fuse-horizontal-navigation-item-disabled">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item fuse-horizontal-navigation-item-disabled"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Item template -->
|
||||
<ng-template #itemTemplate>
|
||||
|
||||
<!-- Icon -->
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-horizontal-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
[svgIcon]="item.icon"
|
||||
></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-horizontal-navigation-item-title-wrapper">
|
||||
<div class="fuse-horizontal-navigation-item-title">
|
||||
<span [ngClass]="item.classes?.title">
|
||||
{{item.title}}
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-horizontal-navigation-item-subtitle text-hint">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
{{ item.subtitle }}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -125,10 +156,10 @@
|
||||
<div class="fuse-horizontal-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
[ngClass]="item.badge.classes"
|
||||
>
|
||||
{{ item.badge.title }}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</ng-template>
|
||||
|
@ -1,9 +1,21 @@
|
||||
import { NgClass, NgIf, NgTemplateOutlet } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { IsActiveMatchOptions, RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import {
|
||||
IsActiveMatchOptions,
|
||||
RouterLink,
|
||||
RouterLinkActive,
|
||||
} from '@angular/router';
|
||||
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';
|
||||
@ -11,13 +23,23 @@ import { FuseUtilsService } from '@fuse/services/utils/utils.service';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-basic-item',
|
||||
templateUrl : './basic.component.html',
|
||||
selector: 'fuse-horizontal-navigation-basic-item',
|
||||
templateUrl: './basic.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass, NgIf, RouterLink, RouterLinkActive, MatTooltipModule, NgTemplateOutlet, MatMenuModule, MatIconModule],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgClass,
|
||||
NgIf,
|
||||
RouterLink,
|
||||
RouterLinkActive,
|
||||
MatTooltipModule,
|
||||
NgTemplateOutlet,
|
||||
MatMenuModule,
|
||||
MatIconModule,
|
||||
],
|
||||
})
|
||||
export class FuseHorizontalNavigationBasicItemComponent implements OnInit, OnDestroy
|
||||
export class FuseHorizontalNavigationBasicItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
private _changeDetectorRef = inject(ChangeDetectorRef);
|
||||
private _fuseNavigationService = inject(FuseNavigationService);
|
||||
@ -30,7 +52,8 @@ export class FuseHorizontalNavigationBasicItemComponent implements OnInit, OnDes
|
||||
// We are not assigning the item.isActiveMatchOptions directly to the
|
||||
// [routerLinkActiveOptions] because if it's "undefined" initially, the router
|
||||
// will throw an error and stop working.
|
||||
isActiveMatchOptions: IsActiveMatchOptions = this._fuseUtilsService.subsetMatchOptions;
|
||||
isActiveMatchOptions: IsActiveMatchOptions =
|
||||
this._fuseUtilsService.subsetMatchOptions;
|
||||
|
||||
private _fuseHorizontalNavigationComponent: FuseHorizontalNavigationComponent;
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
@ -42,8 +65,7 @@ export class FuseHorizontalNavigationBasicItemComponent implements OnInit, OnDes
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Set the "isActiveMatchOptions" either from item's
|
||||
// "isActiveMatchOptions" or the equivalent form of
|
||||
// item's "exactMatch" option
|
||||
@ -53,26 +75,25 @@ export class FuseHorizontalNavigationBasicItemComponent implements OnInit, OnDes
|
||||
: this._fuseUtilsService.subsetMatchOptions;
|
||||
|
||||
// Get the parent navigation component
|
||||
this._fuseHorizontalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseHorizontalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -1,105 +1,123 @@
|
||||
<ng-container *ngIf="!child">
|
||||
<div
|
||||
[ngClass]="{'fuse-horizontal-navigation-menu-active': trigger.menuOpen,
|
||||
'fuse-horizontal-navigation-menu-active-forced': item.active}"
|
||||
[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>
|
||||
#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">
|
||||
|
||||
#matMenu="matMenu"
|
||||
>
|
||||
<ng-container *ngFor="let item of item.children; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<ng-container
|
||||
*ngIf="(item.hidden && !item.hidden(item)) || !item.hidden"
|
||||
>
|
||||
<!-- Basic -->
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
[disabled]="item.disabled"
|
||||
mat-menu-item>
|
||||
mat-menu-item
|
||||
>
|
||||
<fuse-horizontal-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-basic-item>
|
||||
[name]="name"
|
||||
></fuse-horizontal-navigation-basic-item>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Branch: aside, collapsable, group -->
|
||||
<ng-container *ngIf="item.type === 'aside' || item.type === 'collapsable' || item.type === 'group'">
|
||||
<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>
|
||||
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>
|
||||
#branch
|
||||
></fuse-horizontal-navigation-branch-item>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
mat-menu-item>
|
||||
<div class="fuse-horizontal-navigation-menu-item" mat-menu-item>
|
||||
<fuse-horizontal-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-divider-item>
|
||||
[name]="name"
|
||||
></fuse-horizontal-navigation-divider-item>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</mat-menu>
|
||||
|
||||
<!-- Item template -->
|
||||
<ng-template
|
||||
let-item
|
||||
#itemTemplate>
|
||||
|
||||
<ng-template let-item #itemTemplate>
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-wrapper"
|
||||
[class.fuse-horizontal-navigation-item-has-subtitle]="!!item.subtitle"
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
>
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item"
|
||||
[ngClass]="{'fuse-horizontal-navigation-item-disabled': item.disabled,
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active}"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
|
||||
[ngClass]="{
|
||||
'fuse-horizontal-navigation-item-disabled': item.disabled,
|
||||
'fuse-horizontal-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<!-- Icon -->
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-horizontal-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
[svgIcon]="item.icon"
|
||||
></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-horizontal-navigation-item-title-wrapper">
|
||||
<div class="fuse-horizontal-navigation-item-title">
|
||||
<span [ngClass]="item.classes?.title">
|
||||
{{item.title}}
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-horizontal-navigation-item-subtitle text-hint">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-subtitle text-hint"
|
||||
>
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
{{ item.subtitle }}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -110,12 +128,12 @@
|
||||
<div class="fuse-horizontal-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
[ngClass]="item.badge.classes"
|
||||
>
|
||||
{{ item.badge.title }}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</ng-template>
|
||||
|
@ -1,6 +1,16 @@
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { NgClass, NgFor, NgIf, NgTemplateOutlet } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, inject, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
forwardRef,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenu, MatMenuModule } from '@angular/material/menu';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
@ -12,13 +22,25 @@ import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-branch-item',
|
||||
templateUrl : './branch.component.html',
|
||||
selector: 'fuse-horizontal-navigation-branch-item',
|
||||
templateUrl: './branch.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgIf, NgClass, MatMenuModule, NgTemplateOutlet, NgFor, FuseHorizontalNavigationBasicItemComponent, forwardRef(() => FuseHorizontalNavigationBranchItemComponent), FuseHorizontalNavigationDividerItemComponent, MatTooltipModule, MatIconModule],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgIf,
|
||||
NgClass,
|
||||
MatMenuModule,
|
||||
NgTemplateOutlet,
|
||||
NgFor,
|
||||
FuseHorizontalNavigationBasicItemComponent,
|
||||
forwardRef(() => FuseHorizontalNavigationBranchItemComponent),
|
||||
FuseHorizontalNavigationDividerItemComponent,
|
||||
MatTooltipModule,
|
||||
MatIconModule,
|
||||
],
|
||||
})
|
||||
export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDestroy
|
||||
export class FuseHorizontalNavigationBranchItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_child: BooleanInput;
|
||||
@ -30,7 +52,7 @@ export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDe
|
||||
@Input() child: boolean = false;
|
||||
@Input() item: FuseNavigationItem;
|
||||
@Input() name: string;
|
||||
@ViewChild('matMenu', {static: true}) matMenu: MatMenu;
|
||||
@ViewChild('matMenu', { static: true }) matMenu: MatMenu;
|
||||
|
||||
private _fuseHorizontalNavigationComponent: FuseHorizontalNavigationComponent;
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
@ -42,26 +64,24 @@ export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDe
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Get the parent navigation component
|
||||
this._fuseHorizontalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseHorizontalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
@ -74,8 +94,7 @@ export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDe
|
||||
/**
|
||||
* Trigger the change detection
|
||||
*/
|
||||
triggerChangeDetection(): void
|
||||
{
|
||||
triggerChangeDetection(): void {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
@ -86,8 +105,7 @@ export class FuseHorizontalNavigationBranchItemComponent implements OnInit, OnDe
|
||||
* @param index
|
||||
* @param item
|
||||
*/
|
||||
trackByFn(index: number, item: any): any
|
||||
{
|
||||
trackByFn(index: number, item: any): any {
|
||||
return item.id || index;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<!-- Divider -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-wrapper divider"
|
||||
[ngClass]="item.classes?.wrapper"></div>
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
></div>
|
||||
|
@ -1,18 +1,27 @@
|
||||
import { NgClass } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
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';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-divider-item',
|
||||
templateUrl : './divider.component.html',
|
||||
selector: 'fuse-horizontal-navigation-divider-item',
|
||||
templateUrl: './divider.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass],
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
})
|
||||
export class FuseHorizontalNavigationDividerItemComponent implements OnInit, OnDestroy
|
||||
export class FuseHorizontalNavigationDividerItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
private _changeDetectorRef = inject(ChangeDetectorRef);
|
||||
private _fuseNavigationService = inject(FuseNavigationService);
|
||||
@ -30,26 +39,24 @@ export class FuseHorizontalNavigationDividerItemComponent implements OnInit, OnD
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Get the parent navigation component
|
||||
this._fuseHorizontalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseHorizontalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -1,4 +1,5 @@
|
||||
<!-- Spacer -->
|
||||
<div
|
||||
class="fuse-horizontal-navigation-item-wrapper"
|
||||
[ngClass]="item.classes?.wrapper"></div>
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
></div>
|
||||
|
@ -1,18 +1,27 @@
|
||||
import { NgClass } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
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';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation-spacer-item',
|
||||
templateUrl : './spacer.component.html',
|
||||
selector: 'fuse-horizontal-navigation-spacer-item',
|
||||
templateUrl: './spacer.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass],
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
})
|
||||
export class FuseHorizontalNavigationSpacerItemComponent implements OnInit, OnDestroy
|
||||
export class FuseHorizontalNavigationSpacerItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
private _changeDetectorRef = inject(ChangeDetectorRef);
|
||||
private _fuseNavigationService = inject(FuseNavigationService);
|
||||
@ -30,26 +39,24 @@ export class FuseHorizontalNavigationSpacerItemComponent implements OnInit, OnDe
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Get the parent navigation component
|
||||
this._fuseHorizontalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseHorizontalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseHorizontalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -1,24 +1,31 @@
|
||||
<div class="fuse-horizontal-navigation-wrapper">
|
||||
|
||||
<ng-container *ngFor="let item of navigation; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<ng-container
|
||||
*ngIf="(item.hidden && !item.hidden(item)) || !item.hidden"
|
||||
>
|
||||
<!-- Basic -->
|
||||
<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>
|
||||
[name]="name"
|
||||
></fuse-horizontal-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Branch: aside, collapsable, group -->
|
||||
<ng-container *ngIf="item.type === 'aside' || item.type === 'collapsable' || item.type === 'group'">
|
||||
<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>
|
||||
[name]="name"
|
||||
></fuse-horizontal-navigation-branch-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
@ -26,11 +33,9 @@
|
||||
<fuse-horizontal-navigation-spacer-item
|
||||
class="fuse-horizontal-navigation-menu-item"
|
||||
[item]="item"
|
||||
[name]="name"></fuse-horizontal-navigation-spacer-item>
|
||||
[name]="name"
|
||||
></fuse-horizontal-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* Root navigation specific */
|
||||
fuse-horizontal-navigation {
|
||||
|
||||
.fuse-horizontal-navigation-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -8,11 +7,8 @@ fuse-horizontal-navigation {
|
||||
/* Basic, Branch */
|
||||
fuse-horizontal-navigation-basic-item,
|
||||
fuse-horizontal-navigation-branch-item {
|
||||
|
||||
@screen sm {
|
||||
|
||||
&:hover {
|
||||
|
||||
.fuse-horizontal-navigation-item-wrapper {
|
||||
@apply bg-hover;
|
||||
}
|
||||
@ -37,10 +33,8 @@ fuse-horizontal-navigation {
|
||||
|
||||
/* Basic - When item active (current link) */
|
||||
fuse-horizontal-navigation-basic-item {
|
||||
|
||||
.fuse-horizontal-navigation-item-active,
|
||||
.fuse-horizontal-navigation-item-active-forced {
|
||||
|
||||
.fuse-horizontal-navigation-item-title {
|
||||
@apply text-primary #{'!important'};
|
||||
}
|
||||
@ -61,10 +55,8 @@ fuse-horizontal-navigation {
|
||||
|
||||
/* Branch - When menu open */
|
||||
fuse-horizontal-navigation-branch-item {
|
||||
|
||||
.fuse-horizontal-navigation-menu-active,
|
||||
.fuse-horizontal-navigation-menu-active-forced {
|
||||
|
||||
.fuse-horizontal-navigation-item-wrapper {
|
||||
@apply bg-hover;
|
||||
}
|
||||
@ -80,7 +72,6 @@ fuse-horizontal-navigation {
|
||||
|
||||
/* Menu panel specific */
|
||||
.fuse-horizontal-navigation-menu-panel {
|
||||
|
||||
.fuse-horizontal-navigation-menu-item {
|
||||
height: auto;
|
||||
min-height: 0;
|
||||
@ -109,13 +100,10 @@ fuse-horizontal-navigation {
|
||||
|
||||
/* Navigation menu item common */
|
||||
.fuse-horizontal-navigation-menu-item {
|
||||
|
||||
/* Basic - When item active (current link) */
|
||||
fuse-horizontal-navigation-basic-item {
|
||||
|
||||
.fuse-horizontal-navigation-item-active,
|
||||
.fuse-horizontal-navigation-item-active-forced {
|
||||
|
||||
.fuse-horizontal-navigation-item-title {
|
||||
@apply text-primary #{'!important'};
|
||||
}
|
||||
@ -138,7 +126,6 @@ fuse-horizontal-navigation {
|
||||
width: 100%;
|
||||
|
||||
&.fuse-horizontal-navigation-item-has-subtitle {
|
||||
|
||||
.fuse-horizontal-navigation-item {
|
||||
min-height: 56px;
|
||||
}
|
||||
@ -156,7 +143,6 @@ fuse-horizontal-navigation {
|
||||
text-decoration: none;
|
||||
|
||||
.fuse-horizontal-navigation-item-title-wrapper {
|
||||
|
||||
.fuse-horizontal-navigation-item-subtitle {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
@ -1,5 +1,16 @@
|
||||
import { NgFor, NgIf } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewEncapsulation } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
SimpleChanges,
|
||||
ViewEncapsulation,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@ -10,17 +21,24 @@ import { FuseHorizontalNavigationBranchItemComponent } from './components/branch
|
||||
import { FuseHorizontalNavigationSpacerItemComponent } from './components/spacer/spacer.component';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-horizontal-navigation',
|
||||
templateUrl : './horizontal.component.html',
|
||||
styleUrls : ['./horizontal.component.scss'],
|
||||
animations : fuseAnimations,
|
||||
encapsulation : ViewEncapsulation.None,
|
||||
selector: 'fuse-horizontal-navigation',
|
||||
templateUrl: './horizontal.component.html',
|
||||
styleUrls: ['./horizontal.component.scss'],
|
||||
animations: fuseAnimations,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
exportAs : 'fuseHorizontalNavigation',
|
||||
standalone : true,
|
||||
imports : [NgFor, NgIf, FuseHorizontalNavigationBasicItemComponent, FuseHorizontalNavigationBranchItemComponent, FuseHorizontalNavigationSpacerItemComponent],
|
||||
exportAs: 'fuseHorizontalNavigation',
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgFor,
|
||||
NgIf,
|
||||
FuseHorizontalNavigationBasicItemComponent,
|
||||
FuseHorizontalNavigationBranchItemComponent,
|
||||
FuseHorizontalNavigationSpacerItemComponent,
|
||||
],
|
||||
})
|
||||
export class FuseHorizontalNavigationComponent implements OnChanges, OnInit, OnDestroy
|
||||
export class FuseHorizontalNavigationComponent
|
||||
implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
private _changeDetectorRef = inject(ChangeDetectorRef);
|
||||
private _fuseNavigationService = inject(FuseNavigationService);
|
||||
@ -41,11 +59,9 @@ export class FuseHorizontalNavigationComponent implements OnChanges, OnInit, OnD
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Navigation
|
||||
if ( 'navigation' in changes )
|
||||
{
|
||||
if ('navigation' in changes) {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
@ -54,11 +70,9 @@ export class FuseHorizontalNavigationComponent implements OnChanges, OnInit, OnD
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Make sure the name input is not an empty string
|
||||
if ( this.name === '' )
|
||||
{
|
||||
if (this.name === '') {
|
||||
this.name = this._fuseUtilsService.randomId();
|
||||
}
|
||||
|
||||
@ -69,8 +83,7 @@ export class FuseHorizontalNavigationComponent implements OnChanges, OnInit, OnD
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Deregister the navigation component from the registry
|
||||
this._fuseNavigationService.deregisterComponent(this.name);
|
||||
|
||||
@ -86,8 +99,7 @@ export class FuseHorizontalNavigationComponent implements OnChanges, OnInit, OnD
|
||||
/**
|
||||
* Refresh the component to apply the changes
|
||||
*/
|
||||
refresh(): void
|
||||
{
|
||||
refresh(): void {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
|
||||
@ -101,8 +113,7 @@ export class FuseHorizontalNavigationComponent implements OnChanges, OnInit, OnD
|
||||
* @param index
|
||||
* @param item
|
||||
*/
|
||||
trackByFn(index: number, item: any): any
|
||||
{
|
||||
trackByFn(index: number, item: any): any {
|
||||
return item.id || index;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseNavigationService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseNavigationService {
|
||||
private _componentRegistry: Map<string, any> = new Map<string, any>();
|
||||
private _navigationStore: Map<string, FuseNavigationItem[]> = new Map<string, any>();
|
||||
private _navigationStore: Map<string, FuseNavigationItem[]> = new Map<
|
||||
string,
|
||||
any
|
||||
>();
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
@ -17,8 +19,7 @@ export class FuseNavigationService
|
||||
* @param name
|
||||
* @param component
|
||||
*/
|
||||
registerComponent(name: string, component: any): void
|
||||
{
|
||||
registerComponent(name: string, component: any): void {
|
||||
this._componentRegistry.set(name, component);
|
||||
}
|
||||
|
||||
@ -27,8 +28,7 @@ export class FuseNavigationService
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
deregisterComponent(name: string): void
|
||||
{
|
||||
deregisterComponent(name: string): void {
|
||||
this._componentRegistry.delete(name);
|
||||
}
|
||||
|
||||
@ -37,8 +37,7 @@ export class FuseNavigationService
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
getComponent<T>(name: string): T
|
||||
{
|
||||
getComponent<T>(name: string): T {
|
||||
return this._componentRegistry.get(name);
|
||||
}
|
||||
|
||||
@ -48,8 +47,7 @@ export class FuseNavigationService
|
||||
* @param key
|
||||
* @param navigation
|
||||
*/
|
||||
storeNavigation(key: string, navigation: FuseNavigationItem[]): void
|
||||
{
|
||||
storeNavigation(key: string, navigation: FuseNavigationItem[]): void {
|
||||
// Add to the store
|
||||
this._navigationStore.set(key, navigation);
|
||||
}
|
||||
@ -59,8 +57,7 @@ export class FuseNavigationService
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
getNavigation(key: string): FuseNavigationItem[]
|
||||
{
|
||||
getNavigation(key: string): FuseNavigationItem[] {
|
||||
return this._navigationStore.get(key) ?? [];
|
||||
}
|
||||
|
||||
@ -69,12 +66,12 @@ export class FuseNavigationService
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
deleteNavigation(key: string): void
|
||||
{
|
||||
deleteNavigation(key: string): void {
|
||||
// Check if the navigation exists
|
||||
if ( !this._navigationStore.has(key) )
|
||||
{
|
||||
console.warn(`Navigation with the key '${key}' does not exist in the store.`);
|
||||
if (!this._navigationStore.has(key)) {
|
||||
console.warn(
|
||||
`Navigation with the key '${key}' does not exist in the store.`
|
||||
);
|
||||
}
|
||||
|
||||
// Delete from the storage
|
||||
@ -88,20 +85,22 @@ export class FuseNavigationService
|
||||
* @param navigation
|
||||
* @param flatNavigation
|
||||
*/
|
||||
getFlatNavigation(navigation: FuseNavigationItem[], flatNavigation: FuseNavigationItem[] = []): FuseNavigationItem[]
|
||||
{
|
||||
for ( const item of navigation )
|
||||
{
|
||||
if ( item.type === 'basic' )
|
||||
{
|
||||
getFlatNavigation(
|
||||
navigation: FuseNavigationItem[],
|
||||
flatNavigation: FuseNavigationItem[] = []
|
||||
): FuseNavigationItem[] {
|
||||
for (const item of navigation) {
|
||||
if (item.type === 'basic') {
|
||||
flatNavigation.push(item);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( item.type === 'aside' || item.type === 'collapsable' || item.type === 'group' )
|
||||
{
|
||||
if ( item.children )
|
||||
{
|
||||
if (
|
||||
item.type === 'aside' ||
|
||||
item.type === 'collapsable' ||
|
||||
item.type === 'group'
|
||||
) {
|
||||
if (item.children) {
|
||||
this.getFlatNavigation(item.children, flatNavigation);
|
||||
}
|
||||
}
|
||||
@ -117,21 +116,19 @@ export class FuseNavigationService
|
||||
* @param id
|
||||
* @param navigation
|
||||
*/
|
||||
getItem(id: string, navigation: FuseNavigationItem[]): FuseNavigationItem | null
|
||||
{
|
||||
for ( const item of navigation )
|
||||
{
|
||||
if ( item.id === id )
|
||||
{
|
||||
getItem(
|
||||
id: string,
|
||||
navigation: FuseNavigationItem[]
|
||||
): FuseNavigationItem | null {
|
||||
for (const item of navigation) {
|
||||
if (item.id === id) {
|
||||
return item;
|
||||
}
|
||||
|
||||
if ( item.children )
|
||||
{
|
||||
if (item.children) {
|
||||
const childItem = this.getItem(id, item.children);
|
||||
|
||||
if ( childItem )
|
||||
{
|
||||
if (childItem) {
|
||||
return childItem;
|
||||
}
|
||||
}
|
||||
@ -151,22 +148,17 @@ export class FuseNavigationService
|
||||
getItemParent(
|
||||
id: string,
|
||||
navigation: FuseNavigationItem[],
|
||||
parent: FuseNavigationItem[] | FuseNavigationItem,
|
||||
): FuseNavigationItem[] | FuseNavigationItem | null
|
||||
{
|
||||
for ( const item of navigation )
|
||||
{
|
||||
if ( item.id === id )
|
||||
{
|
||||
parent: FuseNavigationItem[] | FuseNavigationItem
|
||||
): FuseNavigationItem[] | FuseNavigationItem | null {
|
||||
for (const item of navigation) {
|
||||
if (item.id === id) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
if ( item.children )
|
||||
{
|
||||
if (item.children) {
|
||||
const childItem = this.getItemParent(id, item.children, item);
|
||||
|
||||
if ( childItem )
|
||||
{
|
||||
if (childItem) {
|
||||
return childItem;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,14 @@
|
||||
import { IsActiveMatchOptions, Params, QueryParamsHandling } from '@angular/router';
|
||||
import {
|
||||
IsActiveMatchOptions,
|
||||
Params,
|
||||
QueryParamsHandling,
|
||||
} from '@angular/router';
|
||||
|
||||
export interface FuseNavigationItem
|
||||
{
|
||||
export interface FuseNavigationItem {
|
||||
id?: string;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
type:
|
||||
| 'aside'
|
||||
| 'basic'
|
||||
| 'collapsable'
|
||||
| 'divider'
|
||||
| 'group'
|
||||
| 'spacer';
|
||||
type: 'aside' | 'basic' | 'collapsable' | 'divider' | 'group' | 'spacer';
|
||||
hidden?: (item: FuseNavigationItem) => boolean;
|
||||
active?: boolean;
|
||||
disabled?: boolean;
|
||||
@ -22,12 +19,7 @@ export interface FuseNavigationItem
|
||||
queryParams?: Params | null;
|
||||
queryParamsHandling?: QueryParamsHandling | null;
|
||||
externalLink?: boolean;
|
||||
target?:
|
||||
| '_blank'
|
||||
| '_self'
|
||||
| '_parent'
|
||||
| '_top'
|
||||
| string;
|
||||
target?: '_blank' | '_self' | '_parent' | '_top' | string;
|
||||
exactMatch?: boolean;
|
||||
isActiveMatchOptions?: IsActiveMatchOptions;
|
||||
function?: (item: FuseNavigationItem) => void;
|
||||
@ -52,10 +44,6 @@ export type FuseVerticalNavigationAppearance =
|
||||
| 'dense'
|
||||
| 'thin';
|
||||
|
||||
export type FuseVerticalNavigationMode =
|
||||
| 'over'
|
||||
| 'side';
|
||||
export type FuseVerticalNavigationMode = 'over' | 'side';
|
||||
|
||||
export type FuseVerticalNavigationPosition =
|
||||
| 'left'
|
||||
| 'right';
|
||||
export type FuseVerticalNavigationPosition = 'left' | 'right';
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from '@fuse/components/navigation/horizontal/horizontal.component';
|
||||
export * from '@fuse/components/navigation/vertical/vertical.component';
|
||||
export * from '@fuse/components/navigation/navigation.service';
|
||||
export * from '@fuse/components/navigation/navigation.types';
|
||||
export * from '@fuse/components/navigation/vertical/vertical.component';
|
||||
|
@ -1,34 +1,37 @@
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-wrapper"
|
||||
[class.fuse-vertical-navigation-item-has-subtitle]="!!item.subtitle"
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
>
|
||||
<div
|
||||
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}"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
|
||||
[ngClass]="{
|
||||
'fuse-vertical-navigation-item-active': active,
|
||||
'fuse-vertical-navigation-item-disabled': item.disabled,
|
||||
'fuse-vertical-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<!-- Icon -->
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
[svgIcon]="item.icon"
|
||||
></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
<div class="fuse-vertical-navigation-item-title">
|
||||
<span [ngClass]="item.classes?.title">
|
||||
{{item.title}}
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
{{ item.subtitle }}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -39,30 +42,28 @@
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
[ngClass]="item.badge.classes"
|
||||
>
|
||||
{{ item.badge.title }}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="!skipChildren">
|
||||
|
||||
<div class="fuse-vertical-navigation-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">
|
||||
|
||||
<ng-container
|
||||
*ngIf="(item.hidden && !item.hidden(item)) || !item.hidden"
|
||||
>
|
||||
<!-- Basic -->
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
@ -70,34 +71,34 @@
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
[autoCollapse]="autoCollapse"
|
||||
></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
<ng-container *ngIf="item.type === 'group'">
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
</ng-container>
|
||||
|
@ -1,6 +1,16 @@
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { NgClass, NgFor, NgIf } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
SimpleChanges,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
@ -12,16 +22,28 @@ import { FuseVerticalNavigationDividerItemComponent } from '@fuse/components/nav
|
||||
import { FuseVerticalNavigationGroupItemComponent } from '@fuse/components/navigation/vertical/components/group/group.component';
|
||||
import { FuseVerticalNavigationSpacerItemComponent } from '@fuse/components/navigation/vertical/components/spacer/spacer.component';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
import { Subject, filter, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-aside-item',
|
||||
templateUrl : './aside.component.html',
|
||||
selector: 'fuse-vertical-navigation-aside-item',
|
||||
templateUrl: './aside.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass, MatTooltipModule, NgIf, MatIconModule, NgFor, FuseVerticalNavigationBasicItemComponent, FuseVerticalNavigationCollapsableItemComponent, FuseVerticalNavigationDividerItemComponent, FuseVerticalNavigationGroupItemComponent, FuseVerticalNavigationSpacerItemComponent],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgClass,
|
||||
MatTooltipModule,
|
||||
NgIf,
|
||||
MatIconModule,
|
||||
NgFor,
|
||||
FuseVerticalNavigationBasicItemComponent,
|
||||
FuseVerticalNavigationCollapsableItemComponent,
|
||||
FuseVerticalNavigationDividerItemComponent,
|
||||
FuseVerticalNavigationGroupItemComponent,
|
||||
FuseVerticalNavigationSpacerItemComponent,
|
||||
],
|
||||
})
|
||||
export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnInit, OnDestroy
|
||||
export class FuseVerticalNavigationAsideItemComponent
|
||||
implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_autoCollapse: BooleanInput;
|
||||
@ -51,11 +73,9 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Active item id
|
||||
if ( 'activeItemId' in changes )
|
||||
{
|
||||
if ('activeItemId' in changes) {
|
||||
// Mark if active
|
||||
this._markIfActive(this._router.url);
|
||||
}
|
||||
@ -64,41 +84,41 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Mark if active
|
||||
this._markIfActive(this._router.url);
|
||||
|
||||
// Attach a listener to the NavigationEnd event
|
||||
this._router.events
|
||||
.pipe(
|
||||
filter((event): event is NavigationEnd => event instanceof NavigationEnd),
|
||||
takeUntil(this._unsubscribeAll),
|
||||
filter(
|
||||
(event): event is NavigationEnd =>
|
||||
event instanceof NavigationEnd
|
||||
),
|
||||
takeUntil(this._unsubscribeAll)
|
||||
)
|
||||
.subscribe((event: NavigationEnd) =>
|
||||
{
|
||||
.subscribe((event: NavigationEnd) => {
|
||||
// Mark if active
|
||||
this._markIfActive(event.urlAfterRedirects);
|
||||
});
|
||||
|
||||
// Get the parent navigation component
|
||||
this._fuseVerticalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseVerticalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseVerticalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseVerticalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
@ -114,8 +134,7 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
|
||||
* @param index
|
||||
* @param item
|
||||
*/
|
||||
trackByFn(index: number, item: any): any
|
||||
{
|
||||
trackByFn(index: number, item: any): any {
|
||||
return item.id || index;
|
||||
}
|
||||
|
||||
@ -131,34 +150,33 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
|
||||
* @param currentUrl
|
||||
* @private
|
||||
*/
|
||||
private _hasActiveChild(item: FuseNavigationItem, currentUrl: string): boolean
|
||||
{
|
||||
private _hasActiveChild(
|
||||
item: FuseNavigationItem,
|
||||
currentUrl: string
|
||||
): boolean {
|
||||
const children = item.children;
|
||||
|
||||
if ( !children )
|
||||
{
|
||||
if (!children) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( const child of children )
|
||||
{
|
||||
if ( child.children )
|
||||
{
|
||||
if ( this._hasActiveChild(child, currentUrl) )
|
||||
{
|
||||
for (const child of children) {
|
||||
if (child.children) {
|
||||
if (this._hasActiveChild(child, currentUrl)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip items other than 'basic'
|
||||
if ( child.type !== 'basic' )
|
||||
{
|
||||
if (child.type !== 'basic') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the child has a link and is active
|
||||
if ( child.link && this._router.isActive(child.link, child.exactMatch || false) )
|
||||
{
|
||||
if (
|
||||
child.link &&
|
||||
this._router.isActive(child.link, child.exactMatch || false)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -171,15 +189,13 @@ export class FuseVerticalNavigationAsideItemComponent implements OnChanges, OnIn
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _markIfActive(currentUrl: string): void
|
||||
{
|
||||
private _markIfActive(currentUrl: string): void {
|
||||
// Check if the activeItemId is equals to this item id
|
||||
this.active = this.activeItemId === this.item.id;
|
||||
|
||||
// If the aside has a children that is active,
|
||||
// always mark it as active
|
||||
if ( this._hasActiveChild(this.item, currentUrl) )
|
||||
{
|
||||
if (this._hasActiveChild(this.item, currentUrl)) {
|
||||
this.active = true;
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,19 @@
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-wrapper"
|
||||
[class.fuse-vertical-navigation-item-has-subtitle]="!!item.subtitle"
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
>
|
||||
<!-- Item with an internal link -->
|
||||
<ng-container *ngIf="item.link && !item.externalLink && !item.function && !item.disabled">
|
||||
<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}"
|
||||
[ngClass]="{
|
||||
'fuse-vertical-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
@ -16,18 +22,24 @@
|
||||
[queryParamsHandling]="item.queryParamsHandling ?? null"
|
||||
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link -->
|
||||
<ng-container *ngIf="item.link && item.externalLink && !item.function && !item.disabled">
|
||||
<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 || ''">
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
@ -36,18 +48,27 @@
|
||||
<ng-container *ngIf="!item.link && item.function && !item.disabled">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-active-forced': item.active}"
|
||||
[ngClass]="{
|
||||
'fuse-vertical-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
(click)="item.function(item)"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an internal link and function -->
|
||||
<ng-container *ngIf="item.link && !item.externalLink && item.function && !item.disabled">
|
||||
<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}"
|
||||
[ngClass]="{
|
||||
'fuse-vertical-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[routerLink]="[item.link]"
|
||||
[fragment]="item.fragment ?? null"
|
||||
[preserveFragment]="item.preserveFragment ?? false"
|
||||
@ -56,19 +77,25 @@
|
||||
[routerLinkActive]="'fuse-vertical-navigation-item-active'"
|
||||
[routerLinkActiveOptions]="isActiveMatchOptions"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="item.function(item)">
|
||||
(click)="item.function(item)"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<!-- Item with an external link and function -->
|
||||
<ng-container *ngIf="item.link && item.externalLink && item.function && !item.disabled">
|
||||
<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)">
|
||||
(click)="item.function(item)"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</a>
|
||||
</ng-container>
|
||||
@ -77,8 +104,11 @@
|
||||
<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 || ''">
|
||||
[ngClass]="{
|
||||
'fuse-vertical-navigation-item-active-forced': item.active
|
||||
}"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -87,35 +117,35 @@
|
||||
<ng-container *ngIf="item.disabled">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item fuse-vertical-navigation-item-disabled"
|
||||
[matTooltip]="item.tooltip || ''">
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="itemTemplate"></ng-container>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Item template -->
|
||||
<ng-template #itemTemplate>
|
||||
|
||||
<!-- Icon -->
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
[svgIcon]="item.icon"
|
||||
></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
<div class="fuse-vertical-navigation-item-title">
|
||||
<span [ngClass]="item.classes?.title">
|
||||
{{item.title}}
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
{{ item.subtitle }}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -126,10 +156,10 @@
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
[ngClass]="item.badge.classes"
|
||||
>
|
||||
{{ item.badge.title }}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</ng-template>
|
||||
|
@ -1,8 +1,20 @@
|
||||
import { NgClass, NgIf, NgTemplateOutlet } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { IsActiveMatchOptions, RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import {
|
||||
IsActiveMatchOptions,
|
||||
RouterLink,
|
||||
RouterLinkActive,
|
||||
} from '@angular/router';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
@ -10,13 +22,22 @@ import { FuseUtilsService } from '@fuse/services/utils/utils.service';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-basic-item',
|
||||
templateUrl : './basic.component.html',
|
||||
selector: 'fuse-vertical-navigation-basic-item',
|
||||
templateUrl: './basic.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass, NgIf, RouterLink, RouterLinkActive, MatTooltipModule, NgTemplateOutlet, MatIconModule],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgClass,
|
||||
NgIf,
|
||||
RouterLink,
|
||||
RouterLinkActive,
|
||||
MatTooltipModule,
|
||||
NgTemplateOutlet,
|
||||
MatIconModule,
|
||||
],
|
||||
})
|
||||
export class FuseVerticalNavigationBasicItemComponent implements OnInit, OnDestroy
|
||||
export class FuseVerticalNavigationBasicItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
private _changeDetectorRef = inject(ChangeDetectorRef);
|
||||
private _fuseNavigationService = inject(FuseNavigationService);
|
||||
@ -29,7 +50,8 @@ export class FuseVerticalNavigationBasicItemComponent implements OnInit, OnDestr
|
||||
// We are not assigning the item.isActiveMatchOptions directly to the
|
||||
// [routerLinkActiveOptions] because if it's "undefined" initially, the router
|
||||
// will throw an error and stop working.
|
||||
isActiveMatchOptions: IsActiveMatchOptions = this._fuseUtilsService.subsetMatchOptions;
|
||||
isActiveMatchOptions: IsActiveMatchOptions =
|
||||
this._fuseUtilsService.subsetMatchOptions;
|
||||
|
||||
private _fuseVerticalNavigationComponent: FuseVerticalNavigationComponent;
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
@ -41,8 +63,7 @@ export class FuseVerticalNavigationBasicItemComponent implements OnInit, OnDestr
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Set the "isActiveMatchOptions" either from item's
|
||||
// "isActiveMatchOptions" or the equivalent form of
|
||||
// item's "exactMatch" option
|
||||
@ -52,26 +73,25 @@ export class FuseVerticalNavigationBasicItemComponent implements OnInit, OnDestr
|
||||
: this._fuseUtilsService.subsetMatchOptions;
|
||||
|
||||
// Get the parent navigation component
|
||||
this._fuseVerticalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseVerticalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseVerticalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseVerticalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -1,33 +1,34 @@
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-wrapper"
|
||||
[class.fuse-vertical-navigation-item-has-subtitle]="!!item.subtitle"
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
>
|
||||
<div
|
||||
class="fuse-vertical-navigation-item"
|
||||
[ngClass]="{'fuse-vertical-navigation-item-disabled': item.disabled}"
|
||||
[ngClass]="{ 'fuse-vertical-navigation-item-disabled': item.disabled }"
|
||||
[matTooltip]="item.tooltip || ''"
|
||||
(click)="toggleCollapsable()">
|
||||
|
||||
(click)="toggleCollapsable()"
|
||||
>
|
||||
<!-- Icon -->
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
[svgIcon]="item.icon"
|
||||
></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
<div class="fuse-vertical-navigation-item-title">
|
||||
<span [ngClass]="item.classes?.title">
|
||||
{{item.title}}
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
{{ item.subtitle }}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -38,8 +39,9 @@
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
[ngClass]="item.badge.classes"
|
||||
>
|
||||
{{ item.badge.title }}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -47,27 +49,27 @@
|
||||
<!-- Arrow -->
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-arrow icon-size-4"
|
||||
[svgIcon]="'heroicons_solid:chevron-right'"></mat-icon>
|
||||
|
||||
[svgIcon]="'heroicons_solid:chevron-right'"
|
||||
></mat-icon>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-children"
|
||||
*ngIf="!isCollapsed"
|
||||
@expandCollapse>
|
||||
|
||||
@expandCollapse
|
||||
>
|
||||
<ng-container *ngFor="let item of item.children; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<ng-container
|
||||
*ngIf="(item.hidden && !item.hidden(item)) || !item.hidden"
|
||||
>
|
||||
<!-- Basic -->
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
@ -75,32 +77,33 @@
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
[autoCollapse]="autoCollapse"
|
||||
></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
<ng-container *ngIf="item.type === 'group'">
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
@ -1,6 +1,16 @@
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { NgClass, NgFor, NgIf } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, HostBinding, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
forwardRef,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
@ -12,17 +22,29 @@ import { FuseVerticalNavigationDividerItemComponent } from '@fuse/components/nav
|
||||
import { FuseVerticalNavigationGroupItemComponent } from '@fuse/components/navigation/vertical/components/group/group.component';
|
||||
import { FuseVerticalNavigationSpacerItemComponent } from '@fuse/components/navigation/vertical/components/spacer/spacer.component';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
import { Subject, filter, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-collapsable-item',
|
||||
templateUrl : './collapsable.component.html',
|
||||
animations : fuseAnimations,
|
||||
selector: 'fuse-vertical-navigation-collapsable-item',
|
||||
templateUrl: './collapsable.component.html',
|
||||
animations: fuseAnimations,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass, MatTooltipModule, NgIf, MatIconModule, NgFor, FuseVerticalNavigationBasicItemComponent, forwardRef(() => FuseVerticalNavigationCollapsableItemComponent), FuseVerticalNavigationDividerItemComponent, FuseVerticalNavigationGroupItemComponent, FuseVerticalNavigationSpacerItemComponent],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgClass,
|
||||
MatTooltipModule,
|
||||
NgIf,
|
||||
MatIconModule,
|
||||
NgFor,
|
||||
FuseVerticalNavigationBasicItemComponent,
|
||||
forwardRef(() => FuseVerticalNavigationCollapsableItemComponent),
|
||||
FuseVerticalNavigationDividerItemComponent,
|
||||
FuseVerticalNavigationGroupItemComponent,
|
||||
FuseVerticalNavigationSpacerItemComponent,
|
||||
],
|
||||
})
|
||||
export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, OnDestroy
|
||||
export class FuseVerticalNavigationCollapsableItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_autoCollapse: BooleanInput;
|
||||
@ -48,12 +70,11 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
/**
|
||||
* Host binding for component classes
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
@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,
|
||||
'fuse-vertical-navigation-item-expanded': this.isExpanded,
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
@ -65,22 +86,19 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Get the parent navigation component
|
||||
this._fuseVerticalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseVerticalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// If the item has a children that has a matching url with the current url, expand...
|
||||
if ( this._hasActiveChild(this.item, this._router.url) )
|
||||
{
|
||||
if (this._hasActiveChild(this.item, this._router.url)) {
|
||||
this.expand();
|
||||
}
|
||||
// Otherwise...
|
||||
else
|
||||
{
|
||||
else {
|
||||
// If the autoCollapse is on, collapse...
|
||||
if ( this.autoCollapse )
|
||||
{
|
||||
if (this.autoCollapse) {
|
||||
this.collapse();
|
||||
}
|
||||
}
|
||||
@ -88,49 +106,40 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
// Listen for the onCollapsableItemCollapsed from the service
|
||||
this._fuseVerticalNavigationComponent.onCollapsableItemCollapsed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((collapsedItem) =>
|
||||
{
|
||||
.subscribe((collapsedItem) => {
|
||||
// Check if the collapsed item is null
|
||||
if ( collapsedItem === null )
|
||||
{
|
||||
if (collapsedItem === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Collapse if this is a children of the collapsed item
|
||||
if ( this._isChildrenOf(collapsedItem, this.item) )
|
||||
{
|
||||
if (this._isChildrenOf(collapsedItem, this.item)) {
|
||||
this.collapse();
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for the onCollapsableItemExpanded from the service if the autoCollapse is on
|
||||
if ( this.autoCollapse )
|
||||
{
|
||||
if (this.autoCollapse) {
|
||||
this._fuseVerticalNavigationComponent.onCollapsableItemExpanded
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe((expandedItem) =>
|
||||
{
|
||||
.subscribe((expandedItem) => {
|
||||
// Check if the expanded item is null
|
||||
if ( expandedItem === null )
|
||||
{
|
||||
if (expandedItem === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is a parent of the expanded item
|
||||
if ( this._isChildrenOf(this.item, expandedItem) )
|
||||
{
|
||||
if (this._isChildrenOf(this.item, expandedItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this has a children with a matching url with the current active url
|
||||
if ( this._hasActiveChild(this.item, this._router.url) )
|
||||
{
|
||||
if (this._hasActiveChild(this.item, this._router.url)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this is the expanded item
|
||||
if ( this.item === expandedItem )
|
||||
{
|
||||
if (this.item === expandedItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -142,42 +151,39 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
// Attach a listener to the NavigationEnd event
|
||||
this._router.events
|
||||
.pipe(
|
||||
filter((event): event is NavigationEnd => event instanceof NavigationEnd),
|
||||
takeUntil(this._unsubscribeAll),
|
||||
filter(
|
||||
(event): event is NavigationEnd =>
|
||||
event instanceof NavigationEnd
|
||||
),
|
||||
takeUntil(this._unsubscribeAll)
|
||||
)
|
||||
.subscribe((event: NavigationEnd) =>
|
||||
{
|
||||
.subscribe((event: NavigationEnd) => {
|
||||
// If the item has a children that has a matching url with the current url, expand...
|
||||
if ( this._hasActiveChild(this.item, event.urlAfterRedirects) )
|
||||
{
|
||||
if (this._hasActiveChild(this.item, event.urlAfterRedirects)) {
|
||||
this.expand();
|
||||
}
|
||||
// Otherwise...
|
||||
else
|
||||
{
|
||||
else {
|
||||
// If the autoCollapse is on, collapse...
|
||||
if ( this.autoCollapse )
|
||||
{
|
||||
if (this.autoCollapse) {
|
||||
this.collapse();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseVerticalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseVerticalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
@ -190,17 +196,14 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
/**
|
||||
* Collapse
|
||||
*/
|
||||
collapse(): void
|
||||
{
|
||||
collapse(): void {
|
||||
// Return if the item is disabled
|
||||
if ( this.item.disabled )
|
||||
{
|
||||
if (this.item.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return if the item is already collapsed
|
||||
if ( this.isCollapsed )
|
||||
{
|
||||
if (this.isCollapsed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -212,23 +215,22 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
this._changeDetectorRef.markForCheck();
|
||||
|
||||
// Execute the observable
|
||||
this._fuseVerticalNavigationComponent.onCollapsableItemCollapsed.next(this.item);
|
||||
this._fuseVerticalNavigationComponent.onCollapsableItemCollapsed.next(
|
||||
this.item
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand
|
||||
*/
|
||||
expand(): void
|
||||
{
|
||||
expand(): void {
|
||||
// Return if the item is disabled
|
||||
if ( this.item.disabled )
|
||||
{
|
||||
if (this.item.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return if the item is already expanded
|
||||
if ( !this.isCollapsed )
|
||||
{
|
||||
if (!this.isCollapsed) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -240,21 +242,19 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
this._changeDetectorRef.markForCheck();
|
||||
|
||||
// Execute the observable
|
||||
this._fuseVerticalNavigationComponent.onCollapsableItemExpanded.next(this.item);
|
||||
this._fuseVerticalNavigationComponent.onCollapsableItemExpanded.next(
|
||||
this.item
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle collapsable
|
||||
*/
|
||||
toggleCollapsable(): void
|
||||
{
|
||||
toggleCollapsable(): void {
|
||||
// Toggle collapse/expand
|
||||
if ( this.isCollapsed )
|
||||
{
|
||||
if (this.isCollapsed) {
|
||||
this.expand();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this.collapse();
|
||||
}
|
||||
}
|
||||
@ -265,8 +265,7 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
* @param index
|
||||
* @param item
|
||||
*/
|
||||
trackByFn(index: number, item: any): any
|
||||
{
|
||||
trackByFn(index: number, item: any): any {
|
||||
return item.id || index;
|
||||
}
|
||||
|
||||
@ -282,28 +281,28 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
* @param currentUrl
|
||||
* @private
|
||||
*/
|
||||
private _hasActiveChild(item: FuseNavigationItem, currentUrl: string): boolean
|
||||
{
|
||||
private _hasActiveChild(
|
||||
item: FuseNavigationItem,
|
||||
currentUrl: string
|
||||
): boolean {
|
||||
const children = item.children;
|
||||
|
||||
if ( !children )
|
||||
{
|
||||
if (!children) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ( const child of children )
|
||||
{
|
||||
if ( child.children )
|
||||
{
|
||||
if ( this._hasActiveChild(child, currentUrl) )
|
||||
{
|
||||
for (const child of children) {
|
||||
if (child.children) {
|
||||
if (this._hasActiveChild(child, currentUrl)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the child has a link and is active
|
||||
if ( child.link && this._router.isActive(child.link, child.exactMatch || false) )
|
||||
{
|
||||
if (
|
||||
child.link &&
|
||||
this._router.isActive(child.link, child.exactMatch || false)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -319,26 +318,23 @@ export class FuseVerticalNavigationCollapsableItemComponent implements OnInit, O
|
||||
* @param item
|
||||
* @private
|
||||
*/
|
||||
private _isChildrenOf(parent: FuseNavigationItem, item: FuseNavigationItem): boolean
|
||||
{
|
||||
private _isChildrenOf(
|
||||
parent: FuseNavigationItem,
|
||||
item: FuseNavigationItem
|
||||
): boolean {
|
||||
const children = parent.children;
|
||||
|
||||
if ( !children )
|
||||
{
|
||||
if (!children) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( children.indexOf(item) > -1 )
|
||||
{
|
||||
if (children.indexOf(item) > -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for ( const child of children )
|
||||
{
|
||||
if ( child.children )
|
||||
{
|
||||
if ( this._isChildrenOf(child, item) )
|
||||
{
|
||||
for (const child of children) {
|
||||
if (child.children) {
|
||||
if (this._isChildrenOf(child, item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<!-- Divider -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-wrapper divider"
|
||||
[ngClass]="item.classes?.wrapper"></div>
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
></div>
|
||||
|
@ -1,18 +1,27 @@
|
||||
import { NgClass } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-divider-item',
|
||||
templateUrl : './divider.component.html',
|
||||
selector: 'fuse-vertical-navigation-divider-item',
|
||||
templateUrl: './divider.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass],
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
})
|
||||
export class FuseVerticalNavigationDividerItemComponent implements OnInit, OnDestroy
|
||||
export class FuseVerticalNavigationDividerItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
private _changeDetectorRef = inject(ChangeDetectorRef);
|
||||
private _fuseNavigationService = inject(FuseNavigationService);
|
||||
@ -30,26 +39,24 @@ export class FuseVerticalNavigationDividerItemComponent implements OnInit, OnDes
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Get the parent navigation component
|
||||
this._fuseVerticalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseVerticalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseVerticalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseVerticalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -2,29 +2,29 @@
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-wrapper"
|
||||
[class.fuse-vertical-navigation-item-has-subtitle]="!!item.subtitle"
|
||||
[ngClass]="item.classes?.wrapper">
|
||||
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
>
|
||||
<div class="fuse-vertical-navigation-item">
|
||||
|
||||
<!-- Icon -->
|
||||
<ng-container *ngIf="item.icon">
|
||||
<mat-icon
|
||||
class="fuse-vertical-navigation-item-icon"
|
||||
[ngClass]="item.classes?.icon"
|
||||
[svgIcon]="item.icon"></mat-icon>
|
||||
[svgIcon]="item.icon"
|
||||
></mat-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title & Subtitle -->
|
||||
<div class="fuse-vertical-navigation-item-title-wrapper">
|
||||
<div class="fuse-vertical-navigation-item-title">
|
||||
<span [ngClass]="item.classes?.title">
|
||||
{{item.title}}
|
||||
{{ item.title }}
|
||||
</span>
|
||||
</div>
|
||||
<ng-container *ngIf="item.subtitle">
|
||||
<div class="fuse-vertical-navigation-item-subtitle">
|
||||
<span [ngClass]="item.classes?.subtitle">
|
||||
{{item.subtitle}}
|
||||
{{ item.subtitle }}
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -35,26 +35,24 @@
|
||||
<div class="fuse-vertical-navigation-item-badge">
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-badge-content"
|
||||
[ngClass]="item.badge.classes">
|
||||
{{item.badge.title}}
|
||||
[ngClass]="item.badge.classes"
|
||||
>
|
||||
{{ item.badge.title }}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<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 -->
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
@ -62,30 +60,32 @@
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
[autoCollapse]="autoCollapse"
|
||||
></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
<ng-container *ngIf="item.type === 'group'">
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-group-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
@ -1,6 +1,15 @@
|
||||
import { BooleanInput } from '@angular/cdk/coercion';
|
||||
import { NgClass, NgFor, NgIf } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, forwardRef, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
forwardRef,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
@ -12,13 +21,24 @@ import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/ver
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-group-item',
|
||||
templateUrl : './group.component.html',
|
||||
selector: 'fuse-vertical-navigation-group-item',
|
||||
templateUrl: './group.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass, NgIf, MatIconModule, NgFor, FuseVerticalNavigationBasicItemComponent, FuseVerticalNavigationCollapsableItemComponent, FuseVerticalNavigationDividerItemComponent, forwardRef(() => FuseVerticalNavigationGroupItemComponent), FuseVerticalNavigationSpacerItemComponent],
|
||||
standalone: true,
|
||||
imports: [
|
||||
NgClass,
|
||||
NgIf,
|
||||
MatIconModule,
|
||||
NgFor,
|
||||
FuseVerticalNavigationBasicItemComponent,
|
||||
FuseVerticalNavigationCollapsableItemComponent,
|
||||
FuseVerticalNavigationDividerItemComponent,
|
||||
forwardRef(() => FuseVerticalNavigationGroupItemComponent),
|
||||
FuseVerticalNavigationSpacerItemComponent,
|
||||
],
|
||||
})
|
||||
export class FuseVerticalNavigationGroupItemComponent implements OnInit, OnDestroy
|
||||
export class FuseVerticalNavigationGroupItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_autoCollapse: BooleanInput;
|
||||
@ -41,26 +61,24 @@ export class FuseVerticalNavigationGroupItemComponent implements OnInit, OnDestr
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Get the parent navigation component
|
||||
this._fuseVerticalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseVerticalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseVerticalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseVerticalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
@ -76,8 +94,7 @@ export class FuseVerticalNavigationGroupItemComponent implements OnInit, OnDestr
|
||||
* @param index
|
||||
* @param item
|
||||
*/
|
||||
trackByFn(index: number, item: any): any
|
||||
{
|
||||
trackByFn(index: number, item: any): any {
|
||||
return item.id || index;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<!-- Spacer -->
|
||||
<div
|
||||
class="fuse-vertical-navigation-item-wrapper"
|
||||
[ngClass]="item.classes?.wrapper"></div>
|
||||
[ngClass]="item.classes?.wrapper"
|
||||
></div>
|
||||
|
@ -1,18 +1,27 @@
|
||||
import { NgClass } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem } from '@fuse/components/navigation/navigation.types';
|
||||
import { FuseVerticalNavigationComponent } from '@fuse/components/navigation/vertical/vertical.component';
|
||||
import { Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation-spacer-item',
|
||||
templateUrl : './spacer.component.html',
|
||||
selector: 'fuse-vertical-navigation-spacer-item',
|
||||
templateUrl: './spacer.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone : true,
|
||||
imports : [NgClass],
|
||||
standalone: true,
|
||||
imports: [NgClass],
|
||||
})
|
||||
export class FuseVerticalNavigationSpacerItemComponent implements OnInit, OnDestroy
|
||||
export class FuseVerticalNavigationSpacerItemComponent
|
||||
implements OnInit, OnDestroy
|
||||
{
|
||||
private _changeDetectorRef = inject(ChangeDetectorRef);
|
||||
private _fuseNavigationService = inject(FuseNavigationService);
|
||||
@ -30,26 +39,24 @@ export class FuseVerticalNavigationSpacerItemComponent implements OnInit, OnDest
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Get the parent navigation component
|
||||
this._fuseVerticalNavigationComponent = this._fuseNavigationService.getComponent(this.name);
|
||||
this._fuseVerticalNavigationComponent =
|
||||
this._fuseNavigationService.getComponent(this.name);
|
||||
|
||||
// Subscribe to onRefreshed on the navigation component
|
||||
this._fuseVerticalNavigationComponent.onRefreshed.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
this._fuseVerticalNavigationComponent.onRefreshed
|
||||
.pipe(takeUntil(this._unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
fuse-vertical-navigation {
|
||||
|
||||
/* Compact appearance overrides */
|
||||
&.fuse-vertical-navigation-appearance-compact {
|
||||
width: var(--fuse-vertical-navigation-compact-width);
|
||||
@ -13,10 +12,11 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Left positioned */
|
||||
&.fuse-vertical-navigation-position-left {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: calc(var(--fuse-vertical-navigation-compact-width) * -1);
|
||||
margin-left: calc(
|
||||
var(--fuse-vertical-navigation-compact-width) * -1
|
||||
);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@ -27,10 +27,11 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Right positioned */
|
||||
&.fuse-vertical-navigation-position-right {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: calc(var(--fuse-vertical-navigation-compact-width) * -1);
|
||||
margin-right: calc(
|
||||
var(--fuse-vertical-navigation-compact-width) * -1
|
||||
);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@ -47,13 +48,10 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Wrapper */
|
||||
.fuse-vertical-navigation-wrapper {
|
||||
|
||||
/* Content */
|
||||
.fuse-vertical-navigation-content {
|
||||
|
||||
> fuse-vertical-navigation-aside-item,
|
||||
> fuse-vertical-navigation-basic-item {
|
||||
|
||||
.fuse-vertical-navigation-item-wrapper {
|
||||
margin: 4px 8px 0 8px;
|
||||
|
||||
@ -91,13 +89,12 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
> fuse-vertical-navigation-collapsable-item {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
|
||||
> fuse-vertical-navigation-group-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ fuse-vertical-navigation {
|
||||
&.fuse-vertical-navigation-animations-enabled {
|
||||
transition-duration: 400ms;
|
||||
transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
transition-property: visibility, margin-left, margin-right, transform, width, max-width, min-width;
|
||||
transition-property: visibility, margin-left, margin-right, transform,
|
||||
width, max-width, min-width;
|
||||
|
||||
/* Wrapper */
|
||||
.fuse-vertical-navigation-wrapper {
|
||||
@ -44,7 +45,6 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Left position */
|
||||
&.fuse-vertical-navigation-position-left {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: calc(#{var(--fuse-vertical-navigation-width)} * -1);
|
||||
@ -72,7 +72,6 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Right position */
|
||||
&.fuse-vertical-navigation-position-right {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: calc(var(--fuse-vertical-navigation-width) * -1);
|
||||
@ -137,7 +136,6 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Header */
|
||||
.fuse-vertical-navigation-header {
|
||||
|
||||
}
|
||||
|
||||
/* Content */
|
||||
@ -160,7 +158,6 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Footer */
|
||||
.fuse-vertical-navigation-footer {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,7 +192,6 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-position-right {
|
||||
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: auto;
|
||||
right: var(--fuse-vertical-navigation-width);
|
||||
@ -219,7 +215,6 @@ fuse-vertical-navigation {
|
||||
user-select: none;
|
||||
|
||||
.fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@ -243,7 +238,6 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
.fuse-vertical-navigation-item-title-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item-subtitle {
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
@ -272,7 +266,6 @@ fuse-vertical-navigation {
|
||||
fuse-vertical-navigation-basic-item,
|
||||
fuse-vertical-navigation-collapsable-item,
|
||||
fuse-vertical-navigation-group-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
margin: 0 12px;
|
||||
}
|
||||
@ -291,23 +284,17 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Aside */
|
||||
fuse-vertical-navigation-aside-item {
|
||||
|
||||
}
|
||||
|
||||
/* Basic */
|
||||
fuse-vertical-navigation-basic-item {
|
||||
|
||||
}
|
||||
|
||||
/* Collapsable */
|
||||
fuse-vertical-navigation-collapsable-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
|
||||
.fuse-vertical-navigation-item-badge {
|
||||
|
||||
+ .fuse-vertical-navigation-item-arrow {
|
||||
margin-left: 8px;
|
||||
}
|
||||
@ -317,18 +304,16 @@ fuse-vertical-navigation {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-left: auto;
|
||||
transition: transform 300ms cubic-bezier(0.25, 0.8, 0.25, 1),
|
||||
color 375ms cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
transition:
|
||||
transform 300ms cubic-bezier(0.25, 0.8, 0.25, 1),
|
||||
color 375ms cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-item-expanded {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
|
||||
.fuse-vertical-navigation-item-arrow {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
@ -337,7 +322,6 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
> .fuse-vertical-navigation-item-children {
|
||||
|
||||
> *:first-child {
|
||||
margin-top: 6px;
|
||||
}
|
||||
@ -346,7 +330,6 @@ fuse-vertical-navigation {
|
||||
padding-bottom: 6px;
|
||||
|
||||
> .fuse-vertical-navigation-item-children {
|
||||
|
||||
> *:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
@ -368,21 +351,18 @@ fuse-vertical-navigation {
|
||||
|
||||
/* 2nd level */
|
||||
.fuse-vertical-navigation-item-children {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
padding-left: 72px;
|
||||
}
|
||||
|
||||
/* 3rd level */
|
||||
.fuse-vertical-navigation-item-children {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
padding-left: 88px;
|
||||
}
|
||||
|
||||
/* 4th level */
|
||||
.fuse-vertical-navigation-item-children {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
padding-left: 104px;
|
||||
}
|
||||
@ -404,18 +384,14 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Group */
|
||||
fuse-vertical-navigation-group-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
|
||||
.fuse-vertical-navigation-item-badge,
|
||||
.fuse-vertical-navigation-item-icon {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.fuse-vertical-navigation-item-title-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item-title {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
@ -474,9 +450,7 @@ fuse-vertical-navigation-aside-item,
|
||||
fuse-vertical-navigation-basic-item,
|
||||
fuse-vertical-navigation-collapsable-item,
|
||||
fuse-vertical-navigation-group-item {
|
||||
|
||||
.fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
color: currentColor;
|
||||
|
||||
@ -485,7 +459,6 @@ fuse-vertical-navigation-group-item {
|
||||
}
|
||||
|
||||
.fuse-vertical-navigation-item-title-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item-title {
|
||||
@apply text-current opacity-80;
|
||||
}
|
||||
@ -502,14 +475,10 @@ fuse-vertical-navigation-group-item {
|
||||
fuse-vertical-navigation-aside-item,
|
||||
fuse-vertical-navigation-basic-item,
|
||||
fuse-vertical-navigation-collapsable-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
|
||||
/* Active state */
|
||||
&:not(.fuse-vertical-navigation-item-disabled) {
|
||||
|
||||
&.fuse-vertical-navigation-item-active,
|
||||
&.fuse-vertical-navigation-item-active-forced {
|
||||
@apply bg-gray-800 bg-opacity-5 dark:bg-white dark:bg-opacity-12;
|
||||
@ -529,8 +498,9 @@ fuse-vertical-navigation-collapsable-item {
|
||||
}
|
||||
|
||||
/* Hover state */
|
||||
&:not(.fuse-vertical-navigation-item-active-forced):not(.fuse-vertical-navigation-item-active):not(.fuse-vertical-navigation-item-disabled) {
|
||||
|
||||
&:not(.fuse-vertical-navigation-item-active-forced):not(
|
||||
.fuse-vertical-navigation-item-active
|
||||
):not(.fuse-vertical-navigation-item-disabled) {
|
||||
&:hover {
|
||||
@apply bg-gray-800 bg-opacity-5 dark:bg-white dark:bg-opacity-12;
|
||||
|
||||
@ -554,14 +524,10 @@ fuse-vertical-navigation-collapsable-item {
|
||||
|
||||
/* Collapsable */
|
||||
fuse-vertical-navigation-collapsable-item {
|
||||
|
||||
/* Expanded state */
|
||||
&.fuse-vertical-navigation-item-expanded {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
|
||||
.fuse-vertical-navigation-item-icon {
|
||||
@apply opacity-100;
|
||||
}
|
||||
@ -581,15 +547,11 @@ fuse-vertical-navigation-collapsable-item {
|
||||
|
||||
/* Group */
|
||||
fuse-vertical-navigation-group-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
|
||||
.fuse-vertical-navigation-item-title-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item-title {
|
||||
@apply opacity-100 text-primary-600 dark:text-primary-400;
|
||||
@apply text-primary-600 opacity-100 dark:text-primary-400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,8 @@
|
||||
}
|
||||
|
||||
fuse-vertical-navigation {
|
||||
|
||||
/* Dense appearance overrides */
|
||||
&.fuse-vertical-navigation-appearance-dense {
|
||||
|
||||
&:not(.fuse-vertical-navigation-mode-over) {
|
||||
width: var(--fuse-vertical-navigation-dense-width);
|
||||
min-width: var(--fuse-vertical-navigation-dense-width);
|
||||
@ -16,10 +14,11 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Left positioned */
|
||||
&.fuse-vertical-navigation-position-left {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: calc(var(--fuse-vertical-navigation-dense-width) * -1);
|
||||
margin-left: calc(
|
||||
var(--fuse-vertical-navigation-dense-width) * -1
|
||||
);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@ -30,10 +29,11 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Right positioned */
|
||||
&.fuse-vertical-navigation-position-right {
|
||||
|
||||
/* Side mode */
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: calc(var(--fuse-vertical-navigation-dense-width) * -1);
|
||||
margin-right: calc(
|
||||
var(--fuse-vertical-navigation-dense-width) * -1
|
||||
);
|
||||
}
|
||||
|
||||
/* Opened */
|
||||
@ -48,7 +48,6 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-hover {
|
||||
|
||||
.fuse-vertical-navigation-aside-wrapper {
|
||||
left: auto;
|
||||
right: var(--fuse-vertical-navigation-width);
|
||||
@ -59,33 +58,38 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Wrapper */
|
||||
.fuse-vertical-navigation-wrapper {
|
||||
|
||||
/* Content */
|
||||
.fuse-vertical-navigation-content {
|
||||
|
||||
fuse-vertical-navigation-aside-item,
|
||||
fuse-vertical-navigation-basic-item,
|
||||
fuse-vertical-navigation-collapsable-item,
|
||||
fuse-vertical-navigation-group-item {
|
||||
|
||||
.fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
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);
|
||||
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,
|
||||
.fuse-vertical-navigation-item-title-wrapper {
|
||||
transition: opacity 400ms cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
transition: opacity 400ms
|
||||
cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fuse-vertical-navigation-group-item {
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
@ -93,16 +97,14 @@ fuse-vertical-navigation {
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.fuse-vertical-navigation-hover):not(.fuse-vertical-navigation-mode-over) {
|
||||
|
||||
&:not(.fuse-vertical-navigation-hover):not(
|
||||
.fuse-vertical-navigation-mode-over
|
||||
) {
|
||||
/* Wrapper */
|
||||
.fuse-vertical-navigation-wrapper {
|
||||
|
||||
/* Content */
|
||||
.fuse-vertical-navigation-content {
|
||||
|
||||
.fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
padding: 10px 16px;
|
||||
|
||||
@ -116,18 +118,14 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
fuse-vertical-navigation-collapsable-item {
|
||||
|
||||
.fuse-vertical-navigation-item-children {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
fuse-vertical-navigation-group-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
|
||||
.fuse-vertical-navigation-item {
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@ -149,24 +147,28 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Hover */
|
||||
&.fuse-vertical-navigation-hover {
|
||||
|
||||
.fuse-vertical-navigation-wrapper {
|
||||
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);
|
||||
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,
|
||||
.fuse-vertical-navigation-item-title-wrapper {
|
||||
white-space: nowrap;
|
||||
animation: removeWhiteSpaceNoWrap 1ms linear 350ms;
|
||||
animation: removeWhiteSpaceNoWrap 1ms linear
|
||||
350ms;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
}
|
||||
@ -183,10 +185,10 @@ fuse-vertical-navigation {
|
||||
|
||||
@keyframes removeWhiteSpaceNoWrap {
|
||||
0% {
|
||||
white-space: nowrap
|
||||
white-space: nowrap;
|
||||
}
|
||||
99% {
|
||||
white-space: nowrap
|
||||
white-space: nowrap;
|
||||
}
|
||||
100% {
|
||||
white-space: normal;
|
||||
|
@ -4,7 +4,6 @@
|
||||
}
|
||||
|
||||
fuse-vertical-navigation {
|
||||
|
||||
/* Thin appearance overrides */
|
||||
&.fuse-vertical-navigation-appearance-thin {
|
||||
width: var(--fuse-vertical-navigation-thin-width);
|
||||
@ -13,9 +12,10 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Left positioned */
|
||||
&.fuse-vertical-navigation-position-left {
|
||||
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-left: calc(var(--fuse-vertical-navigation-thin-width) * -1);
|
||||
margin-left: calc(
|
||||
var(--fuse-vertical-navigation-thin-width) * -1
|
||||
);
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-opened {
|
||||
@ -25,9 +25,10 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Right positioned */
|
||||
&.fuse-vertical-navigation-position-right {
|
||||
|
||||
&.fuse-vertical-navigation-mode-side {
|
||||
margin-right: calc(var(--fuse-vertical-navigation-thin-width) * -1);
|
||||
margin-right: calc(
|
||||
var(--fuse-vertical-navigation-thin-width) * -1
|
||||
);
|
||||
}
|
||||
|
||||
&.fuse-vertical-navigation-opened {
|
||||
@ -42,10 +43,8 @@ fuse-vertical-navigation {
|
||||
|
||||
/* Wrapper */
|
||||
.fuse-vertical-navigation-wrapper {
|
||||
|
||||
/* Content */
|
||||
.fuse-vertical-navigation-content {
|
||||
|
||||
> fuse-vertical-navigation-aside-item,
|
||||
> fuse-vertical-navigation-basic-item {
|
||||
flex-direction: column;
|
||||
@ -79,13 +78,12 @@ fuse-vertical-navigation {
|
||||
}
|
||||
|
||||
> fuse-vertical-navigation-collapsable-item {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
|
||||
> fuse-vertical-navigation-group-item {
|
||||
|
||||
> .fuse-vertical-navigation-item-wrapper {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
<div class="fuse-vertical-navigation-wrapper">
|
||||
|
||||
<!-- Header -->
|
||||
<div class="fuse-vertical-navigation-header">
|
||||
<ng-content select="[fuseVerticalNavigationHeader]"></ng-content>
|
||||
@ -9,20 +8,25 @@
|
||||
<div
|
||||
class="fuse-vertical-navigation-content"
|
||||
fuseScrollbar
|
||||
[fuseScrollbarOptions]="{wheelPropagation: inner, suppressScrollX: true}"
|
||||
#navigationContent>
|
||||
|
||||
[fuseScrollbarOptions]="{
|
||||
wheelPropagation: inner,
|
||||
suppressScrollX: true
|
||||
}"
|
||||
#navigationContent
|
||||
>
|
||||
<!-- Content header -->
|
||||
<div class="fuse-vertical-navigation-content-header">
|
||||
<ng-content select="[fuseVerticalNavigationContentHeader]"></ng-content>
|
||||
<ng-content
|
||||
select="[fuseVerticalNavigationContentHeader]"
|
||||
></ng-content>
|
||||
</div>
|
||||
|
||||
<!-- Items -->
|
||||
<ng-container *ngFor="let item of navigation; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<ng-container
|
||||
*ngIf="(item.hidden && !item.hidden(item)) || !item.hidden"
|
||||
>
|
||||
<!-- Aside -->
|
||||
<ng-container *ngIf="item.type === 'aside'">
|
||||
<fuse-vertical-navigation-aside-item
|
||||
@ -31,14 +35,16 @@
|
||||
[activeItemId]="activeAsideItemId"
|
||||
[autoCollapse]="autoCollapse"
|
||||
[skipChildren]="true"
|
||||
(click)="toggleAside(item)"></fuse-vertical-navigation-aside-item>
|
||||
(click)="toggleAside(item)"
|
||||
></fuse-vertical-navigation-aside-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Basic -->
|
||||
<ng-container *ngIf="item.type === 'basic'">
|
||||
<fuse-vertical-navigation-basic-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-basic-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-basic-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Collapsable -->
|
||||
@ -46,14 +52,16 @@
|
||||
<fuse-vertical-navigation-collapsable-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-collapsable-item>
|
||||
[autoCollapse]="autoCollapse"
|
||||
></fuse-vertical-navigation-collapsable-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Divider -->
|
||||
<ng-container *ngIf="item.type === 'divider'">
|
||||
<fuse-vertical-navigation-divider-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-divider-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-divider-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Group -->
|
||||
@ -61,32 +69,32 @@
|
||||
<fuse-vertical-navigation-group-item
|
||||
[item]="item"
|
||||
[name]="name"
|
||||
[autoCollapse]="autoCollapse"></fuse-vertical-navigation-group-item>
|
||||
[autoCollapse]="autoCollapse"
|
||||
></fuse-vertical-navigation-group-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spacer -->
|
||||
<ng-container *ngIf="item.type === 'spacer'">
|
||||
<fuse-vertical-navigation-spacer-item
|
||||
[item]="item"
|
||||
[name]="name"></fuse-vertical-navigation-spacer-item>
|
||||
[name]="name"
|
||||
></fuse-vertical-navigation-spacer-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
<!-- Content footer -->
|
||||
<div class="fuse-vertical-navigation-content-footer">
|
||||
<ng-content select="[fuseVerticalNavigationContentFooter]"></ng-content>
|
||||
<ng-content
|
||||
select="[fuseVerticalNavigationContentFooter]"
|
||||
></ng-content>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="fuse-vertical-navigation-footer">
|
||||
<ng-content select="[fuseVerticalNavigationFooter]"></ng-content>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Aside -->
|
||||
@ -94,29 +102,34 @@
|
||||
<div
|
||||
class="fuse-vertical-navigation-aside-wrapper"
|
||||
fuseScrollbar
|
||||
[fuseScrollbarOptions]="{wheelPropagation: false, suppressScrollX: true}"
|
||||
[fuseScrollbarOptions]="{
|
||||
wheelPropagation: false,
|
||||
suppressScrollX: true
|
||||
}"
|
||||
[@fadeInLeft]="position === 'left'"
|
||||
[@fadeInRight]="position === 'right'"
|
||||
[@fadeOutLeft]="position === 'left'"
|
||||
[@fadeOutRight]="position === 'right'">
|
||||
|
||||
[@fadeOutRight]="position === 'right'"
|
||||
>
|
||||
<!-- Items -->
|
||||
<ng-container *ngFor="let item of navigation; trackBy: trackByFn">
|
||||
|
||||
<!-- Skip the hidden items -->
|
||||
<ng-container *ngIf="(item.hidden && !item.hidden(item)) || !item.hidden">
|
||||
|
||||
<ng-container
|
||||
*ngIf="(item.hidden && !item.hidden(item)) || !item.hidden"
|
||||
>
|
||||
<!-- Aside -->
|
||||
<ng-container *ngIf="item.type === 'aside' && item.id === activeAsideItemId">
|
||||
<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>
|
||||
[autoCollapse]="autoCollapse"
|
||||
></fuse-vertical-navigation-aside-item>
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -1,12 +1,43 @@
|
||||
import { animate, AnimationBuilder, AnimationPlayer, style } from '@angular/animations';
|
||||
import {
|
||||
animate,
|
||||
AnimationBuilder,
|
||||
AnimationPlayer,
|
||||
style,
|
||||
} from '@angular/animations';
|
||||
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { ScrollStrategy, ScrollStrategyOptions } from '@angular/cdk/overlay';
|
||||
import { DOCUMENT, NgFor, NgIf } from '@angular/common';
|
||||
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 {
|
||||
AfterViewInit,
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
HostBinding,
|
||||
HostListener,
|
||||
inject,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
Output,
|
||||
QueryList,
|
||||
Renderer2,
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
ViewChildren,
|
||||
ViewEncapsulation,
|
||||
} from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { fuseAnimations } from '@fuse/animations';
|
||||
import { FuseNavigationService } from '@fuse/components/navigation/navigation.service';
|
||||
import { FuseNavigationItem, FuseVerticalNavigationAppearance, FuseVerticalNavigationMode, FuseVerticalNavigationPosition } from '@fuse/components/navigation/navigation.types';
|
||||
import {
|
||||
FuseNavigationItem,
|
||||
FuseVerticalNavigationAppearance,
|
||||
FuseVerticalNavigationMode,
|
||||
FuseVerticalNavigationPosition,
|
||||
} from '@fuse/components/navigation/navigation.types';
|
||||
import { FuseVerticalNavigationAsideItemComponent } from '@fuse/components/navigation/vertical/components/aside/aside.component';
|
||||
import { FuseVerticalNavigationBasicItemComponent } from '@fuse/components/navigation/vertical/components/basic/basic.component';
|
||||
import { FuseVerticalNavigationCollapsableItemComponent } from '@fuse/components/navigation/vertical/components/collapsable/collapsable.component';
|
||||
@ -15,20 +46,39 @@ import { FuseVerticalNavigationGroupItemComponent } from '@fuse/components/navig
|
||||
import { FuseVerticalNavigationSpacerItemComponent } from '@fuse/components/navigation/vertical/components/spacer/spacer.component';
|
||||
import { FuseScrollbarDirective } from '@fuse/directives/scrollbar/scrollbar.directive';
|
||||
import { FuseUtilsService } from '@fuse/services/utils/utils.service';
|
||||
import { delay, filter, merge, ReplaySubject, Subject, Subscription, takeUntil } from 'rxjs';
|
||||
import {
|
||||
delay,
|
||||
filter,
|
||||
merge,
|
||||
ReplaySubject,
|
||||
Subject,
|
||||
Subscription,
|
||||
takeUntil,
|
||||
} from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-vertical-navigation',
|
||||
templateUrl : './vertical.component.html',
|
||||
styleUrls : ['./vertical.component.scss'],
|
||||
animations : fuseAnimations,
|
||||
encapsulation : ViewEncapsulation.None,
|
||||
selector: 'fuse-vertical-navigation',
|
||||
templateUrl: './vertical.component.html',
|
||||
styleUrls: ['./vertical.component.scss'],
|
||||
animations: fuseAnimations,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
exportAs : 'fuseVerticalNavigation',
|
||||
standalone : true,
|
||||
imports : [FuseScrollbarDirective, NgFor, NgIf, FuseVerticalNavigationAsideItemComponent, FuseVerticalNavigationBasicItemComponent, FuseVerticalNavigationCollapsableItemComponent, FuseVerticalNavigationDividerItemComponent, FuseVerticalNavigationGroupItemComponent, FuseVerticalNavigationSpacerItemComponent],
|
||||
exportAs: 'fuseVerticalNavigation',
|
||||
standalone: true,
|
||||
imports: [
|
||||
FuseScrollbarDirective,
|
||||
NgFor,
|
||||
NgIf,
|
||||
FuseVerticalNavigationAsideItemComponent,
|
||||
FuseVerticalNavigationBasicItemComponent,
|
||||
FuseVerticalNavigationCollapsableItemComponent,
|
||||
FuseVerticalNavigationDividerItemComponent,
|
||||
FuseVerticalNavigationGroupItemComponent,
|
||||
FuseVerticalNavigationSpacerItemComponent,
|
||||
],
|
||||
})
|
||||
export class FuseVerticalNavigationComponent implements OnChanges, OnInit, AfterViewInit, OnDestroy
|
||||
export class FuseVerticalNavigationComponent
|
||||
implements OnChanges, OnInit, AfterViewInit, OnDestroy
|
||||
{
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_inner: BooleanInput;
|
||||
@ -55,15 +105,23 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
@Input() opened: boolean = true;
|
||||
@Input() position: FuseVerticalNavigationPosition = 'left';
|
||||
@Input() transparentOverlay: boolean = false;
|
||||
@Output() readonly appearanceChanged: EventEmitter<FuseVerticalNavigationAppearance> = new EventEmitter<FuseVerticalNavigationAppearance>();
|
||||
@Output() readonly modeChanged: EventEmitter<FuseVerticalNavigationMode> = new EventEmitter<FuseVerticalNavigationMode>();
|
||||
@Output() readonly openedChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
@Output() readonly positionChanged: EventEmitter<FuseVerticalNavigationPosition> = new EventEmitter<FuseVerticalNavigationPosition>();
|
||||
@Output()
|
||||
readonly appearanceChanged: EventEmitter<FuseVerticalNavigationAppearance> =
|
||||
new EventEmitter<FuseVerticalNavigationAppearance>();
|
||||
@Output() readonly modeChanged: EventEmitter<FuseVerticalNavigationMode> =
|
||||
new EventEmitter<FuseVerticalNavigationMode>();
|
||||
@Output() readonly openedChanged: EventEmitter<boolean> =
|
||||
new EventEmitter<boolean>();
|
||||
@Output()
|
||||
readonly positionChanged: EventEmitter<FuseVerticalNavigationPosition> =
|
||||
new EventEmitter<FuseVerticalNavigationPosition>();
|
||||
@ViewChild('navigationContent') private _navigationContentEl: ElementRef;
|
||||
|
||||
activeAsideItemId: string | null = null;
|
||||
onCollapsableItemCollapsed: ReplaySubject<FuseNavigationItem> = new ReplaySubject<FuseNavigationItem>(1);
|
||||
onCollapsableItemExpanded: ReplaySubject<FuseNavigationItem> = new ReplaySubject<FuseNavigationItem>(1);
|
||||
onCollapsableItemCollapsed: ReplaySubject<FuseNavigationItem> =
|
||||
new ReplaySubject<FuseNavigationItem>(1);
|
||||
onCollapsableItemExpanded: ReplaySubject<FuseNavigationItem> =
|
||||
new ReplaySubject<FuseNavigationItem>(1);
|
||||
onRefreshed: ReplaySubject<boolean> = new ReplaySubject<boolean>(1);
|
||||
private _animationsEnabled: boolean = false;
|
||||
private _asideOverlay: HTMLElement;
|
||||
@ -73,7 +131,8 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
private _mutationObserver: MutationObserver;
|
||||
private _overlay: HTMLElement;
|
||||
private _player: AnimationPlayer;
|
||||
private _scrollStrategy: ScrollStrategy = this._scrollStrategyOptions.block();
|
||||
private _scrollStrategy: ScrollStrategy =
|
||||
this._scrollStrategyOptions.block();
|
||||
private _fuseScrollbarDirectives!: QueryList<FuseScrollbarDirective>;
|
||||
private _fuseScrollbarDirectivesSubscription: Subscription;
|
||||
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||
@ -81,14 +140,11 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor()
|
||||
{
|
||||
this._handleAsideOverlayClick = (): void =>
|
||||
{
|
||||
constructor() {
|
||||
this._handleAsideOverlayClick = (): void => {
|
||||
this.closeAside();
|
||||
};
|
||||
this._handleOverlayClick = (): void =>
|
||||
{
|
||||
this._handleOverlayClick = (): void => {
|
||||
this.close();
|
||||
};
|
||||
}
|
||||
@ -100,19 +156,20 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Host binding for component classes
|
||||
*/
|
||||
@HostBinding('class') get classList(): any
|
||||
{
|
||||
@HostBinding('class') get classList(): any {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
return {
|
||||
'fuse-vertical-navigation-animations-enabled' : this._animationsEnabled,
|
||||
'fuse-vertical-navigation-animations-enabled':
|
||||
this._animationsEnabled,
|
||||
[`fuse-vertical-navigation-appearance-${this.appearance}`]: true,
|
||||
'fuse-vertical-navigation-hover' : this._hovered,
|
||||
'fuse-vertical-navigation-inner' : this.inner,
|
||||
'fuse-vertical-navigation-mode-over' : this.mode === 'over',
|
||||
'fuse-vertical-navigation-mode-side' : this.mode === 'side',
|
||||
'fuse-vertical-navigation-opened' : this.opened,
|
||||
'fuse-vertical-navigation-position-left' : this.position === 'left',
|
||||
'fuse-vertical-navigation-position-right' : this.position === 'right',
|
||||
'fuse-vertical-navigation-hover': this._hovered,
|
||||
'fuse-vertical-navigation-inner': this.inner,
|
||||
'fuse-vertical-navigation-mode-over': this.mode === 'over',
|
||||
'fuse-vertical-navigation-mode-side': this.mode === 'side',
|
||||
'fuse-vertical-navigation-opened': this.opened,
|
||||
'fuse-vertical-navigation-position-left': this.position === 'left',
|
||||
'fuse-vertical-navigation-position-right':
|
||||
this.position === 'right',
|
||||
};
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
}
|
||||
@ -120,10 +177,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Host binding for component inline styles
|
||||
*/
|
||||
@HostBinding('style') get styleList(): any
|
||||
{
|
||||
@HostBinding('style') get styleList(): any {
|
||||
return {
|
||||
'visibility': this.opened ? 'visible' : 'hidden',
|
||||
visibility: this.opened ? 'visible' : 'hidden',
|
||||
};
|
||||
}
|
||||
|
||||
@ -131,41 +187,34 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
* Setter for fuseScrollbarDirectives
|
||||
*/
|
||||
@ViewChildren(FuseScrollbarDirective)
|
||||
set fuseScrollbarDirectives(fuseScrollbarDirectives: QueryList<FuseScrollbarDirective>)
|
||||
{
|
||||
set fuseScrollbarDirectives(
|
||||
fuseScrollbarDirectives: QueryList<FuseScrollbarDirective>
|
||||
) {
|
||||
// Store the directives
|
||||
this._fuseScrollbarDirectives = fuseScrollbarDirectives;
|
||||
|
||||
// Return if there are no directives
|
||||
if ( fuseScrollbarDirectives.length === 0 )
|
||||
{
|
||||
if (fuseScrollbarDirectives.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Unsubscribe the previous subscriptions
|
||||
if ( this._fuseScrollbarDirectivesSubscription )
|
||||
{
|
||||
if (this._fuseScrollbarDirectivesSubscription) {
|
||||
this._fuseScrollbarDirectivesSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
// Update the scrollbars on collapsable items' collapse/expand
|
||||
this._fuseScrollbarDirectivesSubscription =
|
||||
merge(
|
||||
this.onCollapsableItemCollapsed,
|
||||
this.onCollapsableItemExpanded,
|
||||
)
|
||||
.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
delay(250),
|
||||
)
|
||||
.subscribe(() =>
|
||||
{
|
||||
// Loop through the scrollbars and update them
|
||||
fuseScrollbarDirectives.forEach((fuseScrollbarDirective) =>
|
||||
{
|
||||
fuseScrollbarDirective.update();
|
||||
});
|
||||
this._fuseScrollbarDirectivesSubscription = merge(
|
||||
this.onCollapsableItemCollapsed,
|
||||
this.onCollapsableItemExpanded
|
||||
)
|
||||
.pipe(takeUntil(this._unsubscribeAll), delay(250))
|
||||
.subscribe(() => {
|
||||
// Loop through the scrollbars and update them
|
||||
fuseScrollbarDirectives.forEach((fuseScrollbarDirective) => {
|
||||
fuseScrollbarDirective.update();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -178,8 +227,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
* @private
|
||||
*/
|
||||
@HostListener('mouseenter')
|
||||
private _onMouseenter(): void
|
||||
{
|
||||
private _onMouseenter(): void {
|
||||
// Enable the animations
|
||||
this._enableAnimations();
|
||||
|
||||
@ -193,8 +241,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
* @private
|
||||
*/
|
||||
@HostListener('mouseleave')
|
||||
private _onMouseleave(): void
|
||||
{
|
||||
private _onMouseleave(): void {
|
||||
// Enable the animations
|
||||
this._enableAnimations();
|
||||
|
||||
@ -211,25 +258,21 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Appearance
|
||||
if ( 'appearance' in changes )
|
||||
{
|
||||
if ('appearance' in changes) {
|
||||
// Execute the observable
|
||||
this.appearanceChanged.next(changes.appearance.currentValue);
|
||||
}
|
||||
|
||||
// Inner
|
||||
if ( 'inner' in changes )
|
||||
{
|
||||
if ('inner' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.inner = coerceBooleanProperty(changes.inner.currentValue);
|
||||
}
|
||||
|
||||
// Mode
|
||||
if ( 'mode' in changes )
|
||||
{
|
||||
if ('mode' in changes) {
|
||||
// Get the previous and current values
|
||||
const currentMode = changes.mode.currentValue;
|
||||
const previousMode = changes.mode.previousValue;
|
||||
@ -238,21 +281,18 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
this._disableAnimations();
|
||||
|
||||
// If the mode changes: 'over -> side'
|
||||
if ( previousMode === 'over' && currentMode === 'side' )
|
||||
{
|
||||
if (previousMode === 'over' && currentMode === 'side') {
|
||||
// Hide the overlay
|
||||
this._hideOverlay();
|
||||
}
|
||||
|
||||
// If the mode changes: 'side -> over'
|
||||
if ( previousMode === 'side' && currentMode === 'over' )
|
||||
{
|
||||
if (previousMode === 'side' && currentMode === 'over') {
|
||||
// Close the aside
|
||||
this.closeAside();
|
||||
|
||||
// If the navigation is opened
|
||||
if ( this.opened )
|
||||
{
|
||||
if (this.opened) {
|
||||
// Show the overlay
|
||||
this._showOverlay();
|
||||
}
|
||||
@ -264,22 +304,19 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
// Enable the animations after a delay
|
||||
// The delay must be bigger than the current transition-duration
|
||||
// to make sure nothing will be animated while the mode changing
|
||||
setTimeout(() =>
|
||||
{
|
||||
setTimeout(() => {
|
||||
this._enableAnimations();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// Navigation
|
||||
if ( 'navigation' in changes )
|
||||
{
|
||||
if ('navigation' in changes) {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
// Opened
|
||||
if ( 'opened' in changes )
|
||||
{
|
||||
if ('opened' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.opened = coerceBooleanProperty(changes.opened.currentValue);
|
||||
|
||||
@ -288,28 +325,26 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
}
|
||||
|
||||
// Position
|
||||
if ( 'position' in changes )
|
||||
{
|
||||
if ('position' in changes) {
|
||||
// Execute the observable
|
||||
this.positionChanged.next(changes.position.currentValue);
|
||||
}
|
||||
|
||||
// Transparent overlay
|
||||
if ( 'transparentOverlay' in changes )
|
||||
{
|
||||
if ('transparentOverlay' in changes) {
|
||||
// Coerce the value to a boolean
|
||||
this.transparentOverlay = coerceBooleanProperty(changes.transparentOverlay.currentValue);
|
||||
this.transparentOverlay = coerceBooleanProperty(
|
||||
changes.transparentOverlay.currentValue
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Make sure the name input is not an empty string
|
||||
if ( this.name === '' )
|
||||
{
|
||||
if (this.name === '') {
|
||||
this.name = this._fuseUtilsService.randomId();
|
||||
}
|
||||
|
||||
@ -319,21 +354,18 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
// Subscribe to the 'NavigationEnd' event
|
||||
this._router.events
|
||||
.pipe(
|
||||
filter(event => event instanceof NavigationEnd),
|
||||
takeUntil(this._unsubscribeAll),
|
||||
filter((event) => event instanceof NavigationEnd),
|
||||
takeUntil(this._unsubscribeAll)
|
||||
)
|
||||
.subscribe(() =>
|
||||
{
|
||||
.subscribe(() => {
|
||||
// If the mode is 'over' and the navigation is opened...
|
||||
if ( this.mode === 'over' && this.opened )
|
||||
{
|
||||
if (this.mode === 'over' && this.opened) {
|
||||
// Close the navigation
|
||||
this.close();
|
||||
}
|
||||
|
||||
// If the mode is 'side' and the aside is active...
|
||||
if ( this.mode === 'side' && this.activeAsideItemId )
|
||||
{
|
||||
if (this.mode === 'side' && this.activeAsideItemId) {
|
||||
// Close the aside
|
||||
this.closeAside();
|
||||
}
|
||||
@ -343,74 +375,85 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* After view init
|
||||
*/
|
||||
ngAfterViewInit(): void
|
||||
{
|
||||
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) =>
|
||||
{
|
||||
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') )
|
||||
{
|
||||
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._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,
|
||||
attributes: true,
|
||||
attributeFilter: ['class'],
|
||||
});
|
||||
|
||||
setTimeout(() =>
|
||||
{
|
||||
setTimeout(() => {
|
||||
// Return if 'navigation content' element does not exist
|
||||
if ( !this._navigationContentEl )
|
||||
{
|
||||
if (!this._navigationContentEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If 'navigation content' element doesn't have
|
||||
// perfect scrollbar activated on it...
|
||||
if ( !this._navigationContentEl.nativeElement.classList.contains('ps') )
|
||||
{
|
||||
if (
|
||||
!this._navigationContentEl.nativeElement.classList.contains(
|
||||
'ps'
|
||||
)
|
||||
) {
|
||||
// Find the active item
|
||||
const activeItem = this._navigationContentEl.nativeElement.querySelector('.fuse-vertical-navigation-item-active');
|
||||
const activeItem =
|
||||
this._navigationContentEl.nativeElement.querySelector(
|
||||
'.fuse-vertical-navigation-item-active'
|
||||
);
|
||||
|
||||
// If the active item exists, scroll it into view
|
||||
if ( activeItem )
|
||||
{
|
||||
if (activeItem) {
|
||||
activeItem.scrollIntoView();
|
||||
}
|
||||
}
|
||||
// Otherwise
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Go through all the scrollbar directives
|
||||
this._fuseScrollbarDirectives.forEach((fuseScrollbarDirective) =>
|
||||
{
|
||||
// Skip if not enabled
|
||||
if ( !fuseScrollbarDirective.isEnabled() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
this._fuseScrollbarDirectives.forEach(
|
||||
(fuseScrollbarDirective) => {
|
||||
// Skip if not enabled
|
||||
if (!fuseScrollbarDirective.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll to the active element
|
||||
fuseScrollbarDirective.scrollToElement('.fuse-vertical-navigation-item-active', -120, true);
|
||||
});
|
||||
// Scroll to the active element
|
||||
fuseScrollbarDirective.scrollToElement(
|
||||
'.fuse-vertical-navigation-item-active',
|
||||
-120,
|
||||
true
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -418,8 +461,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Disconnect the mutation observer
|
||||
this._mutationObserver.disconnect();
|
||||
|
||||
@ -442,8 +484,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Refresh the component to apply the changes
|
||||
*/
|
||||
refresh(): void
|
||||
{
|
||||
refresh(): void {
|
||||
// Mark for check
|
||||
this._changeDetectorRef.markForCheck();
|
||||
|
||||
@ -454,11 +495,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Open the navigation
|
||||
*/
|
||||
open(): void
|
||||
{
|
||||
open(): void {
|
||||
// Return if the navigation is already open
|
||||
if ( this.opened )
|
||||
{
|
||||
if (this.opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -469,11 +508,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Close the navigation
|
||||
*/
|
||||
close(): void
|
||||
{
|
||||
close(): void {
|
||||
// Return if the navigation is already closed
|
||||
if ( !this.opened )
|
||||
{
|
||||
if (!this.opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -487,15 +524,11 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Toggle the navigation
|
||||
*/
|
||||
toggle(): void
|
||||
{
|
||||
toggle(): void {
|
||||
// Toggle
|
||||
if ( this.opened )
|
||||
{
|
||||
if (this.opened) {
|
||||
this.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
@ -505,11 +538,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
openAside(item: FuseNavigationItem): void
|
||||
{
|
||||
openAside(item: FuseNavigationItem): void {
|
||||
// Return if the item is disabled
|
||||
if ( item.disabled || !item.id )
|
||||
{
|
||||
if (item.disabled || !item.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -526,8 +557,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
/**
|
||||
* Close the aside
|
||||
*/
|
||||
closeAside(): void
|
||||
{
|
||||
closeAside(): void {
|
||||
// Close
|
||||
this.activeAsideItemId = null;
|
||||
|
||||
@ -543,15 +573,11 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @param item
|
||||
*/
|
||||
toggleAside(item: FuseNavigationItem): void
|
||||
{
|
||||
toggleAside(item: FuseNavigationItem): void {
|
||||
// Toggle
|
||||
if ( this.activeAsideItemId === item.id )
|
||||
{
|
||||
if (this.activeAsideItemId === item.id) {
|
||||
this.closeAside();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this.openAside(item);
|
||||
}
|
||||
}
|
||||
@ -562,8 +588,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
* @param index
|
||||
* @param item
|
||||
*/
|
||||
trackByFn(index: number, item: any): any
|
||||
{
|
||||
trackByFn(index: number, item: any): any {
|
||||
return item.id || index;
|
||||
}
|
||||
|
||||
@ -576,11 +601,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _enableAnimations(): void
|
||||
{
|
||||
private _enableAnimations(): void {
|
||||
// Return if the animations are already enabled
|
||||
if ( this._animationsEnabled )
|
||||
{
|
||||
if (this._animationsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -593,11 +616,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _disableAnimations(): void
|
||||
{
|
||||
private _disableAnimations(): void {
|
||||
// Return if the animations are already disabled
|
||||
if ( !this._animationsEnabled )
|
||||
{
|
||||
if (!this._animationsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -610,11 +631,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _showOverlay(): void
|
||||
{
|
||||
private _showOverlay(): void {
|
||||
// Return if there is already an overlay
|
||||
if ( this._asideOverlay )
|
||||
{
|
||||
if (this._asideOverlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -625,21 +644,30 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
this._overlay.classList.add('fuse-vertical-navigation-overlay');
|
||||
|
||||
// Add a class depending on the transparentOverlay option
|
||||
if ( this.transparentOverlay )
|
||||
{
|
||||
this._overlay.classList.add('fuse-vertical-navigation-overlay-transparent');
|
||||
if (this.transparentOverlay) {
|
||||
this._overlay.classList.add(
|
||||
'fuse-vertical-navigation-overlay-transparent'
|
||||
);
|
||||
}
|
||||
|
||||
// Append the overlay to the parent of the navigation
|
||||
this._renderer2.appendChild(this._elementRef.nativeElement.parentElement, this._overlay);
|
||||
this._renderer2.appendChild(
|
||||
this._elementRef.nativeElement.parentElement,
|
||||
this._overlay
|
||||
);
|
||||
|
||||
// Enable block scroll strategy
|
||||
this._scrollStrategy.enable();
|
||||
|
||||
// Create the enter animation and attach it to the player
|
||||
this._player = this._animationBuilder.build([
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 1})),
|
||||
]).create(this._overlay);
|
||||
this._player = this._animationBuilder
|
||||
.build([
|
||||
animate(
|
||||
'300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
|
||||
style({ opacity: 1 })
|
||||
),
|
||||
])
|
||||
.create(this._overlay);
|
||||
|
||||
// Play the animation
|
||||
this._player.play();
|
||||
@ -653,29 +681,33 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _hideOverlay(): void
|
||||
{
|
||||
if ( !this._overlay )
|
||||
{
|
||||
private _hideOverlay(): void {
|
||||
if (!this._overlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the leave animation and attach it to the player
|
||||
this._player = this._animationBuilder.build([
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 0})),
|
||||
]).create(this._overlay);
|
||||
this._player = this._animationBuilder
|
||||
.build([
|
||||
animate(
|
||||
'300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
|
||||
style({ opacity: 0 })
|
||||
),
|
||||
])
|
||||
.create(this._overlay);
|
||||
|
||||
// Play the animation
|
||||
this._player.play();
|
||||
|
||||
// Once the animation is done...
|
||||
this._player.onDone(() =>
|
||||
{
|
||||
this._player.onDone(() => {
|
||||
// If the overlay still exists...
|
||||
if ( this._overlay )
|
||||
{
|
||||
if (this._overlay) {
|
||||
// Remove the event listener
|
||||
this._overlay.removeEventListener('click', this._handleOverlayClick);
|
||||
this._overlay.removeEventListener(
|
||||
'click',
|
||||
this._handleOverlayClick
|
||||
);
|
||||
|
||||
// Remove the overlay
|
||||
this._overlay.parentNode.removeChild(this._overlay);
|
||||
@ -692,11 +724,9 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _showAsideOverlay(): void
|
||||
{
|
||||
private _showAsideOverlay(): void {
|
||||
// Return if there is already an overlay
|
||||
if ( this._asideOverlay )
|
||||
{
|
||||
if (this._asideOverlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -704,23 +734,34 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
this._asideOverlay = this._renderer2.createElement('div');
|
||||
|
||||
// Add a class to the aside overlay element
|
||||
this._asideOverlay.classList.add('fuse-vertical-navigation-aside-overlay');
|
||||
this._asideOverlay.classList.add(
|
||||
'fuse-vertical-navigation-aside-overlay'
|
||||
);
|
||||
|
||||
// Append the aside overlay to the parent of the navigation
|
||||
this._renderer2.appendChild(this._elementRef.nativeElement.parentElement, this._asideOverlay);
|
||||
this._renderer2.appendChild(
|
||||
this._elementRef.nativeElement.parentElement,
|
||||
this._asideOverlay
|
||||
);
|
||||
|
||||
// Create the enter animation and attach it to the player
|
||||
this._player =
|
||||
this._animationBuilder
|
||||
.build([
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 1})),
|
||||
]).create(this._asideOverlay);
|
||||
this._player = this._animationBuilder
|
||||
.build([
|
||||
animate(
|
||||
'300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
|
||||
style({ opacity: 1 })
|
||||
),
|
||||
])
|
||||
.create(this._asideOverlay);
|
||||
|
||||
// Play the animation
|
||||
this._player.play();
|
||||
|
||||
// Add an event listener to the aside overlay
|
||||
this._asideOverlay.addEventListener('click', this._handleAsideOverlayClick);
|
||||
this._asideOverlay.addEventListener(
|
||||
'click',
|
||||
this._handleAsideOverlayClick
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -728,31 +769,33 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _hideAsideOverlay(): void
|
||||
{
|
||||
if ( !this._asideOverlay )
|
||||
{
|
||||
private _hideAsideOverlay(): void {
|
||||
if (!this._asideOverlay) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the leave animation and attach it to the player
|
||||
this._player =
|
||||
this._animationBuilder
|
||||
.build([
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({opacity: 0})),
|
||||
]).create(this._asideOverlay);
|
||||
this._player = this._animationBuilder
|
||||
.build([
|
||||
animate(
|
||||
'300ms cubic-bezier(0.25, 0.8, 0.25, 1)',
|
||||
style({ opacity: 0 })
|
||||
),
|
||||
])
|
||||
.create(this._asideOverlay);
|
||||
|
||||
// Play the animation
|
||||
this._player.play();
|
||||
|
||||
// Once the animation is done...
|
||||
this._player.onDone(() =>
|
||||
{
|
||||
this._player.onDone(() => {
|
||||
// If the aside overlay still exists...
|
||||
if ( this._asideOverlay )
|
||||
{
|
||||
if (this._asideOverlay) {
|
||||
// Remove the event listener
|
||||
this._asideOverlay.removeEventListener('click', this._handleAsideOverlayClick);
|
||||
this._asideOverlay.removeEventListener(
|
||||
'click',
|
||||
this._handleAsideOverlayClick
|
||||
);
|
||||
|
||||
// Remove the aside overlay
|
||||
this._asideOverlay.parentNode.removeChild(this._asideOverlay);
|
||||
@ -767,8 +810,7 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
* @param open
|
||||
* @private
|
||||
*/
|
||||
private _toggleOpened(open: boolean): void
|
||||
{
|
||||
private _toggleOpened(open: boolean): void {
|
||||
// Set the opened
|
||||
this.opened = open;
|
||||
|
||||
@ -777,14 +819,10 @@ export class FuseVerticalNavigationComponent implements OnChanges, OnInit, After
|
||||
|
||||
// If the navigation opened, and the mode
|
||||
// is 'over', show the overlay
|
||||
if ( this.mode === 'over' )
|
||||
{
|
||||
if ( this.opened )
|
||||
{
|
||||
if (this.mode === 'over') {
|
||||
if (this.opened) {
|
||||
this._showOverlay();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this._hideOverlay();
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,19 @@
|
||||
import { Directive, ElementRef, inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
inject,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { filter, Subject, takeUntil } from 'rxjs';
|
||||
|
||||
@Directive({
|
||||
selector : '[fuseScrollReset]',
|
||||
exportAs : 'fuseScrollReset',
|
||||
selector: '[fuseScrollReset]',
|
||||
exportAs: 'fuseScrollReset',
|
||||
standalone: true,
|
||||
})
|
||||
export class FuseScrollResetDirective implements OnInit, OnDestroy
|
||||
{
|
||||
export class FuseScrollResetDirective implements OnInit, OnDestroy {
|
||||
private _elementRef = inject(ElementRef);
|
||||
private _router = inject(Router);
|
||||
|
||||
@ -21,24 +26,23 @@ export class FuseScrollResetDirective implements OnInit, OnDestroy
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Subscribe to NavigationEnd event
|
||||
this._router.events.pipe(
|
||||
filter(event => event instanceof NavigationEnd),
|
||||
takeUntil(this._unsubscribeAll),
|
||||
).subscribe(() =>
|
||||
{
|
||||
// Reset the element's scroll position to the top
|
||||
this._elementRef.nativeElement.scrollTop = 0;
|
||||
});
|
||||
this._router.events
|
||||
.pipe(
|
||||
filter((event) => event instanceof NavigationEnd),
|
||||
takeUntil(this._unsubscribeAll)
|
||||
)
|
||||
.subscribe(() => {
|
||||
// Reset the element's scroll position to the top
|
||||
this._elementRef.nativeElement.scrollTop = 0;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
// Unsubscribe from all subscriptions
|
||||
this._unsubscribeAll.next(null);
|
||||
this._unsubscribeAll.complete();
|
||||
|
@ -1,21 +1,32 @@
|
||||
import { BooleanInput, coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
import { Platform } from '@angular/cdk/platform';
|
||||
import { Directive, ElementRef, inject, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core';
|
||||
import { ScrollbarGeometry, ScrollbarPosition } from '@fuse/directives/scrollbar/scrollbar.types';
|
||||
import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
SimpleChanges,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
ScrollbarGeometry,
|
||||
ScrollbarPosition,
|
||||
} from '@fuse/directives/scrollbar/scrollbar.types';
|
||||
import { merge } from 'lodash-es';
|
||||
import PerfectScrollbar from 'perfect-scrollbar';
|
||||
import { debounceTime, fromEvent, Subject, takeUntil } from 'rxjs';
|
||||
import { Subject, debounceTime, fromEvent, takeUntil } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Wrapper directive for the Perfect Scrollbar: https://github.com/mdbootstrap/perfect-scrollbar
|
||||
*/
|
||||
@Directive({
|
||||
selector : '[fuseScrollbar]',
|
||||
exportAs : 'fuseScrollbar',
|
||||
selector: '[fuseScrollbar]',
|
||||
exportAs: 'fuseScrollbar',
|
||||
standalone: true,
|
||||
})
|
||||
export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
{
|
||||
export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
static ngAcceptInputType_fuseScrollbar: BooleanInput;
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
@ -38,16 +49,14 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Getter for _elementRef
|
||||
*/
|
||||
get elementRef(): ElementRef
|
||||
{
|
||||
get elementRef(): ElementRef {
|
||||
return this._elementRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for _ps
|
||||
*/
|
||||
get ps(): PerfectScrollbar | null
|
||||
{
|
||||
get ps(): PerfectScrollbar | null {
|
||||
return this._ps;
|
||||
}
|
||||
|
||||
@ -60,46 +69,44 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @param changes
|
||||
*/
|
||||
ngOnChanges(changes: SimpleChanges): void
|
||||
{
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
// Enabled
|
||||
if ( 'fuseScrollbar' in changes )
|
||||
{
|
||||
if ('fuseScrollbar' in changes) {
|
||||
// Interpret empty string as 'true'
|
||||
this.fuseScrollbar = coerceBooleanProperty(changes.fuseScrollbar.currentValue);
|
||||
this.fuseScrollbar = coerceBooleanProperty(
|
||||
changes.fuseScrollbar.currentValue
|
||||
);
|
||||
|
||||
// If enabled, init the directive
|
||||
if ( this.fuseScrollbar )
|
||||
{
|
||||
if (this.fuseScrollbar) {
|
||||
this._init();
|
||||
}
|
||||
// Otherwise destroy it
|
||||
else
|
||||
{
|
||||
else {
|
||||
this._destroy();
|
||||
}
|
||||
}
|
||||
|
||||
// Scrollbar options
|
||||
if ( 'fuseScrollbarOptions' in changes )
|
||||
{
|
||||
if ('fuseScrollbarOptions' in changes) {
|
||||
// Merge the options
|
||||
this._options = merge({}, this._options, changes.fuseScrollbarOptions.currentValue);
|
||||
this._options = merge(
|
||||
{},
|
||||
this._options,
|
||||
changes.fuseScrollbarOptions.currentValue
|
||||
);
|
||||
|
||||
// Return if not initialized
|
||||
if ( !this._ps )
|
||||
{
|
||||
if (!this._ps) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy and re-init the PerfectScrollbar to update its options
|
||||
setTimeout(() =>
|
||||
{
|
||||
setTimeout(() => {
|
||||
this._destroy();
|
||||
});
|
||||
|
||||
setTimeout(() =>
|
||||
{
|
||||
setTimeout(() => {
|
||||
this._init();
|
||||
});
|
||||
}
|
||||
@ -108,16 +115,11 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* On init
|
||||
*/
|
||||
ngOnInit(): void
|
||||
{
|
||||
ngOnInit(): void {
|
||||
// Subscribe to window resize event
|
||||
fromEvent(window, 'resize')
|
||||
.pipe(
|
||||
takeUntil(this._unsubscribeAll),
|
||||
debounceTime(150),
|
||||
)
|
||||
.subscribe(() =>
|
||||
{
|
||||
.pipe(takeUntil(this._unsubscribeAll), debounceTime(150))
|
||||
.subscribe(() => {
|
||||
// Update the PerfectScrollbar
|
||||
this.update();
|
||||
});
|
||||
@ -126,8 +128,7 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* On destroy
|
||||
*/
|
||||
ngOnDestroy(): void
|
||||
{
|
||||
ngOnDestroy(): void {
|
||||
this._destroy();
|
||||
|
||||
// Unsubscribe from all subscriptions
|
||||
@ -142,19 +143,16 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Is enabled
|
||||
*/
|
||||
isEnabled(): boolean
|
||||
{
|
||||
isEnabled(): boolean {
|
||||
return this.fuseScrollbar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the scrollbar
|
||||
*/
|
||||
update(): void
|
||||
{
|
||||
update(): void {
|
||||
// Return if not initialized
|
||||
if ( !this._ps )
|
||||
{
|
||||
if (!this._ps) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -165,8 +163,7 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
/**
|
||||
* Destroy the scrollbar
|
||||
*/
|
||||
destroy(): void
|
||||
{
|
||||
destroy(): void {
|
||||
this.ngOnDestroy();
|
||||
}
|
||||
|
||||
@ -175,13 +172,13 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @param prefix
|
||||
*/
|
||||
geometry(prefix: string = 'scroll'): ScrollbarGeometry
|
||||
{
|
||||
geometry(prefix: string = 'scroll'): ScrollbarGeometry {
|
||||
return new ScrollbarGeometry(
|
||||
this._elementRef.nativeElement[prefix + 'Left'],
|
||||
this._elementRef.nativeElement[prefix + 'Top'],
|
||||
this._elementRef.nativeElement[prefix + 'Width'],
|
||||
this._elementRef.nativeElement[prefix + 'Height']);
|
||||
this._elementRef.nativeElement[prefix + 'Height']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,22 +186,18 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @param absolute
|
||||
*/
|
||||
position(absolute: boolean = false): ScrollbarPosition
|
||||
{
|
||||
position(absolute: boolean = false): ScrollbarPosition {
|
||||
let scrollbarPosition;
|
||||
|
||||
if ( !absolute && this._ps )
|
||||
{
|
||||
if (!absolute && this._ps) {
|
||||
scrollbarPosition = new ScrollbarPosition(
|
||||
this._ps.reach.x || 0,
|
||||
this._ps.reach.y || 0,
|
||||
this._ps.reach.y || 0
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
scrollbarPosition = new ScrollbarPosition(
|
||||
this._elementRef.nativeElement.scrollLeft,
|
||||
this._elementRef.nativeElement.scrollTop,
|
||||
this._elementRef.nativeElement.scrollTop
|
||||
);
|
||||
}
|
||||
|
||||
@ -218,21 +211,15 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param y
|
||||
* @param speed
|
||||
*/
|
||||
scrollTo(x: number, y?: number, speed?: number): void
|
||||
{
|
||||
if ( y == null && speed == null )
|
||||
{
|
||||
scrollTo(x: number, y?: number, speed?: number): void {
|
||||
if (y == null && speed == null) {
|
||||
this.animateScrolling('scrollTop', x, speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( x != null )
|
||||
{
|
||||
} else {
|
||||
if (x != null) {
|
||||
this.animateScrolling('scrollLeft', x, speed);
|
||||
}
|
||||
|
||||
if ( y != null )
|
||||
{
|
||||
if (y != null) {
|
||||
this.animateScrolling('scrollTop', y, speed);
|
||||
}
|
||||
}
|
||||
@ -244,8 +231,7 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param x
|
||||
* @param speed
|
||||
*/
|
||||
scrollToX(x: number, speed?: number): void
|
||||
{
|
||||
scrollToX(x: number, speed?: number): void {
|
||||
this.animateScrolling('scrollLeft', x, speed);
|
||||
}
|
||||
|
||||
@ -255,8 +241,7 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param y
|
||||
* @param speed
|
||||
*/
|
||||
scrollToY(y: number, speed?: number): void
|
||||
{
|
||||
scrollToY(y: number, speed?: number): void {
|
||||
this.animateScrolling('scrollTop', y, speed);
|
||||
}
|
||||
|
||||
@ -266,8 +251,7 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param offset
|
||||
* @param speed
|
||||
*/
|
||||
scrollToTop(offset: number = 0, speed?: number): void
|
||||
{
|
||||
scrollToTop(offset: number = 0, speed?: number): void {
|
||||
this.animateScrolling('scrollTop', offset, speed);
|
||||
}
|
||||
|
||||
@ -277,9 +261,10 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param offset
|
||||
* @param speed
|
||||
*/
|
||||
scrollToBottom(offset: number = 0, speed?: number): void
|
||||
{
|
||||
const top = this._elementRef.nativeElement.scrollHeight - this._elementRef.nativeElement.clientHeight;
|
||||
scrollToBottom(offset: number = 0, speed?: number): void {
|
||||
const top =
|
||||
this._elementRef.nativeElement.scrollHeight -
|
||||
this._elementRef.nativeElement.clientHeight;
|
||||
this.animateScrolling('scrollTop', top - offset, speed);
|
||||
}
|
||||
|
||||
@ -289,8 +274,7 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param offset
|
||||
* @param speed
|
||||
*/
|
||||
scrollToLeft(offset: number = 0, speed?: number): void
|
||||
{
|
||||
scrollToLeft(offset: number = 0, speed?: number): void {
|
||||
this.animateScrolling('scrollLeft', offset, speed);
|
||||
}
|
||||
|
||||
@ -300,9 +284,10 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param offset
|
||||
* @param speed
|
||||
*/
|
||||
scrollToRight(offset: number = 0, speed?: number): void
|
||||
{
|
||||
const left = this._elementRef.nativeElement.scrollWidth - this._elementRef.nativeElement.clientWidth;
|
||||
scrollToRight(offset: number = 0, speed?: number): void {
|
||||
const left =
|
||||
this._elementRef.nativeElement.scrollWidth -
|
||||
this._elementRef.nativeElement.clientWidth;
|
||||
this.animateScrolling('scrollLeft', left - offset, speed);
|
||||
}
|
||||
|
||||
@ -314,22 +299,27 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param ignoreVisible If true, scrollToElement won't happen if element is already inside the current viewport
|
||||
* @param speed
|
||||
*/
|
||||
scrollToElement(qs: string, offset: number = 0, ignoreVisible: boolean = false, speed?: number): void
|
||||
{
|
||||
scrollToElement(
|
||||
qs: string,
|
||||
offset: number = 0,
|
||||
ignoreVisible: boolean = false,
|
||||
speed?: number
|
||||
): void {
|
||||
const element = this._elementRef.nativeElement.querySelector(qs);
|
||||
|
||||
if ( !element )
|
||||
{
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
const elementPos = element.getBoundingClientRect();
|
||||
const scrollerPos = this._elementRef.nativeElement.getBoundingClientRect();
|
||||
const scrollerPos =
|
||||
this._elementRef.nativeElement.getBoundingClientRect();
|
||||
|
||||
if ( this._elementRef.nativeElement.classList.contains('ps--active-x') )
|
||||
{
|
||||
if ( ignoreVisible && elementPos.right <= (scrollerPos.right - Math.abs(offset)) )
|
||||
{
|
||||
if (this._elementRef.nativeElement.classList.contains('ps--active-x')) {
|
||||
if (
|
||||
ignoreVisible &&
|
||||
elementPos.right <= scrollerPos.right - Math.abs(offset)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -339,10 +329,11 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
this.animateScrolling('scrollLeft', position + offset, speed);
|
||||
}
|
||||
|
||||
if ( this._elementRef.nativeElement.classList.contains('ps--active-y') )
|
||||
{
|
||||
if ( ignoreVisible && elementPos.bottom <= (scrollerPos.bottom - Math.abs(offset)) )
|
||||
{
|
||||
if (this._elementRef.nativeElement.classList.contains('ps--active-y')) {
|
||||
if (
|
||||
ignoreVisible &&
|
||||
elementPos.bottom <= scrollerPos.bottom - Math.abs(offset)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -360,20 +351,15 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
* @param value
|
||||
* @param speed
|
||||
*/
|
||||
animateScrolling(target: string, value: number, speed?: number): void
|
||||
{
|
||||
if ( this._animation )
|
||||
{
|
||||
animateScrolling(target: string, value: number, speed?: number): void {
|
||||
if (this._animation) {
|
||||
window.cancelAnimationFrame(this._animation);
|
||||
this._animation = null;
|
||||
}
|
||||
|
||||
if ( !speed || typeof window === 'undefined' )
|
||||
{
|
||||
if (!speed || typeof window === 'undefined') {
|
||||
this._elementRef.nativeElement[target] = value;
|
||||
}
|
||||
else if ( value !== this._elementRef.nativeElement[target] )
|
||||
{
|
||||
} else if (value !== this._elementRef.nativeElement[target]) {
|
||||
let newValue = 0;
|
||||
let scrollCount = 0;
|
||||
|
||||
@ -382,20 +368,18 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
|
||||
const cosParameter = (oldValue - value) / 2;
|
||||
|
||||
const step = (newTimestamp: number): void =>
|
||||
{
|
||||
scrollCount += Math.PI / (speed / (newTimestamp - oldTimestamp));
|
||||
newValue = Math.round(value + cosParameter + cosParameter * Math.cos(scrollCount));
|
||||
const step = (newTimestamp: number): void => {
|
||||
scrollCount +=
|
||||
Math.PI / (speed / (newTimestamp - oldTimestamp));
|
||||
newValue = Math.round(
|
||||
value + cosParameter + cosParameter * Math.cos(scrollCount)
|
||||
);
|
||||
|
||||
// Only continue animation if scroll position has not changed
|
||||
if ( this._elementRef.nativeElement[target] === oldValue )
|
||||
{
|
||||
if ( scrollCount >= Math.PI )
|
||||
{
|
||||
if (this._elementRef.nativeElement[target] === oldValue) {
|
||||
if (scrollCount >= Math.PI) {
|
||||
this.animateScrolling(target, value, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
this._elementRef.nativeElement[target] = newValue;
|
||||
|
||||
// On a zoomed out page the resulting offset may differ
|
||||
@ -420,23 +404,26 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _init(): void
|
||||
{
|
||||
private _init(): void {
|
||||
// Return if already initialized
|
||||
if ( this._ps )
|
||||
{
|
||||
if (this._ps) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return if on mobile or not on browser
|
||||
if ( this._platform.ANDROID || this._platform.IOS || !this._platform.isBrowser )
|
||||
{
|
||||
if (
|
||||
this._platform.ANDROID ||
|
||||
this._platform.IOS ||
|
||||
!this._platform.isBrowser
|
||||
) {
|
||||
this.fuseScrollbar = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialize the PerfectScrollbar
|
||||
this._ps = new PerfectScrollbar(this._elementRef.nativeElement, {...this._options});
|
||||
this._ps = new PerfectScrollbar(this._elementRef.nativeElement, {
|
||||
...this._options,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -444,11 +431,9 @@ export class FuseScrollbarDirective implements OnChanges, OnInit, OnDestroy
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
private _destroy(): void
|
||||
{
|
||||
private _destroy(): void {
|
||||
// Return if not initialized
|
||||
if ( !this._ps )
|
||||
{
|
||||
if (!this._ps) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,11 @@
|
||||
export class ScrollbarGeometry
|
||||
{
|
||||
export class ScrollbarGeometry {
|
||||
public x: number;
|
||||
public y: number;
|
||||
|
||||
public w: number;
|
||||
public h: number;
|
||||
|
||||
constructor(x: number, y: number, w: number, h: number)
|
||||
{
|
||||
constructor(x: number, y: number, w: number, h: number) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.w = w;
|
||||
@ -15,13 +13,11 @@ export class ScrollbarGeometry
|
||||
}
|
||||
}
|
||||
|
||||
export class ScrollbarPosition
|
||||
{
|
||||
export class ScrollbarPosition {
|
||||
public x: number | 'start' | 'end';
|
||||
public y: number | 'start' | 'end';
|
||||
|
||||
constructor(x: number | 'start' | 'end', y: number | 'start' | 'end')
|
||||
{
|
||||
constructor(x: number | 'start' | 'end', y: number | 'start' | 'end') {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
@ -1,13 +1,26 @@
|
||||
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
||||
import { APP_INITIALIZER, ENVIRONMENT_INITIALIZER, EnvironmentProviders, importProvidersFrom, inject, Provider } from '@angular/core';
|
||||
import {
|
||||
APP_INITIALIZER,
|
||||
ENVIRONMENT_INITIALIZER,
|
||||
EnvironmentProviders,
|
||||
Provider,
|
||||
importProvidersFrom,
|
||||
inject,
|
||||
} from '@angular/core';
|
||||
import { MATERIAL_SANITY_CHECKS } from '@angular/material/core';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
import { FUSE_MOCK_API_DEFAULT_DELAY, mockApiInterceptor } from '@fuse/lib/mock-api';
|
||||
import {
|
||||
FUSE_MOCK_API_DEFAULT_DELAY,
|
||||
mockApiInterceptor,
|
||||
} from '@fuse/lib/mock-api';
|
||||
import { FuseConfig } from '@fuse/services/config';
|
||||
import { FUSE_CONFIG } from '@fuse/services/config/config.constants';
|
||||
import { FuseConfirmationService } from '@fuse/services/confirmation';
|
||||
import { fuseLoadingInterceptor, FuseLoadingService } from '@fuse/services/loading';
|
||||
import {
|
||||
FuseLoadingService,
|
||||
fuseLoadingInterceptor,
|
||||
} from '@fuse/services/loading';
|
||||
import { FuseMediaWatcherService } from '@fuse/services/media-watcher';
|
||||
import { FusePlatformService } from '@fuse/services/platform';
|
||||
import { FuseSplashScreenService } from '@fuse/services/splash-screen';
|
||||
@ -17,89 +30,89 @@ export type FuseProviderConfig = {
|
||||
mockApi?: {
|
||||
delay?: number;
|
||||
services?: any[];
|
||||
},
|
||||
fuse?: FuseConfig
|
||||
}
|
||||
};
|
||||
fuse?: FuseConfig;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fuse provider
|
||||
*/
|
||||
export const provideFuse = (config: FuseProviderConfig): Array<Provider | EnvironmentProviders> =>
|
||||
{
|
||||
export const provideFuse = (
|
||||
config: FuseProviderConfig
|
||||
): Array<Provider | EnvironmentProviders> => {
|
||||
// Base providers
|
||||
const providers: Array<Provider | EnvironmentProviders> = [
|
||||
{
|
||||
// Disable 'theme' sanity check
|
||||
provide : MATERIAL_SANITY_CHECKS,
|
||||
provide: MATERIAL_SANITY_CHECKS,
|
||||
useValue: {
|
||||
doctype: true,
|
||||
theme : false,
|
||||
theme: false,
|
||||
version: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Use the 'fill' appearance on Angular Material form fields by default
|
||||
provide : MAT_FORM_FIELD_DEFAULT_OPTIONS,
|
||||
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
|
||||
useValue: {
|
||||
appearance: 'fill',
|
||||
},
|
||||
},
|
||||
{
|
||||
provide : FUSE_MOCK_API_DEFAULT_DELAY,
|
||||
provide: FUSE_MOCK_API_DEFAULT_DELAY,
|
||||
useValue: config?.mockApi?.delay ?? 0,
|
||||
},
|
||||
{
|
||||
provide : FUSE_CONFIG,
|
||||
provide: FUSE_CONFIG,
|
||||
useValue: config?.fuse ?? {},
|
||||
},
|
||||
|
||||
importProvidersFrom(MatDialogModule),
|
||||
{
|
||||
provide : ENVIRONMENT_INITIALIZER,
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
useValue: () => inject(FuseConfirmationService),
|
||||
multi : true,
|
||||
multi: true,
|
||||
},
|
||||
|
||||
provideHttpClient(withInterceptors([fuseLoadingInterceptor])),
|
||||
{
|
||||
provide : ENVIRONMENT_INITIALIZER,
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
useValue: () => inject(FuseLoadingService),
|
||||
multi : true,
|
||||
multi: true,
|
||||
},
|
||||
|
||||
{
|
||||
provide : ENVIRONMENT_INITIALIZER,
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
useValue: () => inject(FuseMediaWatcherService),
|
||||
multi : true,
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide : ENVIRONMENT_INITIALIZER,
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
useValue: () => inject(FusePlatformService),
|
||||
multi : true,
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide : ENVIRONMENT_INITIALIZER,
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
useValue: () => inject(FuseSplashScreenService),
|
||||
multi : true,
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide : ENVIRONMENT_INITIALIZER,
|
||||
provide: ENVIRONMENT_INITIALIZER,
|
||||
useValue: () => inject(FuseUtilsService),
|
||||
multi : true,
|
||||
multi: true,
|
||||
},
|
||||
];
|
||||
|
||||
// Mock Api services
|
||||
if ( config?.mockApi?.services )
|
||||
{
|
||||
if (config?.mockApi?.services) {
|
||||
providers.push(
|
||||
provideHttpClient(withInterceptors([mockApiInterceptor])),
|
||||
{
|
||||
provide : APP_INITIALIZER,
|
||||
deps : [...config.mockApi.services],
|
||||
provide: APP_INITIALIZER,
|
||||
deps: [...config.mockApi.services],
|
||||
useFactory: () => (): any => null,
|
||||
multi : true,
|
||||
},
|
||||
multi: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
export const FUSE_MOCK_API_DEFAULT_DELAY = new InjectionToken<number>('FUSE_MOCK_API_DEFAULT_DELAY');
|
||||
export const FUSE_MOCK_API_DEFAULT_DELAY = new InjectionToken<number>(
|
||||
'FUSE_MOCK_API_DEFAULT_DELAY'
|
||||
);
|
||||
|
@ -1,23 +1,30 @@
|
||||
import { HttpErrorResponse, HttpEvent, HttpHandlerFn, HttpRequest, HttpResponse } from '@angular/common/http';
|
||||
import {
|
||||
HttpErrorResponse,
|
||||
HttpEvent,
|
||||
HttpHandlerFn,
|
||||
HttpRequest,
|
||||
HttpResponse,
|
||||
} from '@angular/common/http';
|
||||
import { inject } from '@angular/core';
|
||||
import { FUSE_MOCK_API_DEFAULT_DELAY } from '@fuse/lib/mock-api/mock-api.constants';
|
||||
import { FuseMockApiService } from '@fuse/lib/mock-api/mock-api.service';
|
||||
import { delay, Observable, of, switchMap, throwError } from 'rxjs';
|
||||
import { Observable, delay, of, switchMap, throwError } from 'rxjs';
|
||||
|
||||
export const mockApiInterceptor = (request: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> =>
|
||||
{
|
||||
export const mockApiInterceptor = (
|
||||
request: HttpRequest<unknown>,
|
||||
next: HttpHandlerFn
|
||||
): Observable<HttpEvent<unknown>> => {
|
||||
const defaultDelay = inject(FUSE_MOCK_API_DEFAULT_DELAY);
|
||||
const fuseMockApiService = inject(FuseMockApiService);
|
||||
|
||||
// Try to get the request handler
|
||||
const {
|
||||
handler,
|
||||
urlParams,
|
||||
} = fuseMockApiService.findHandler(request.method.toUpperCase(), request.url);
|
||||
const { handler, urlParams } = fuseMockApiService.findHandler(
|
||||
request.method.toUpperCase(),
|
||||
request.url
|
||||
);
|
||||
|
||||
// Pass through if the request handler does not exist
|
||||
if ( !handler )
|
||||
{
|
||||
if (!handler) {
|
||||
return next(request);
|
||||
}
|
||||
|
||||
@ -30,15 +37,13 @@ export const mockApiInterceptor = (request: HttpRequest<unknown>, next: HttpHand
|
||||
// Subscribe to the response function observable
|
||||
return handler.response.pipe(
|
||||
delay(handler.delay ?? defaultDelay ?? 0),
|
||||
switchMap((response) =>
|
||||
{
|
||||
switchMap((response) => {
|
||||
// If there is no response data,
|
||||
// throw an error response
|
||||
if ( !response )
|
||||
{
|
||||
if (!response) {
|
||||
response = new HttpErrorResponse({
|
||||
error : 'NOT FOUND',
|
||||
status : 404,
|
||||
error: 'NOT FOUND',
|
||||
status: 404,
|
||||
statusText: 'NOT FOUND',
|
||||
});
|
||||
|
||||
@ -48,16 +53,15 @@ export const mockApiInterceptor = (request: HttpRequest<unknown>, next: HttpHand
|
||||
// Parse the response data
|
||||
const data = {
|
||||
status: response[0],
|
||||
body : response[1],
|
||||
body: response[1],
|
||||
};
|
||||
|
||||
// If the status code is in between 200 and 300,
|
||||
// return a success response
|
||||
if ( data.status >= 200 && data.status < 300 )
|
||||
{
|
||||
if (data.status >= 200 && data.status < 300) {
|
||||
response = new HttpResponse({
|
||||
body : data.body,
|
||||
status : data.status,
|
||||
body: data.body,
|
||||
status: data.status,
|
||||
statusText: 'OK',
|
||||
});
|
||||
|
||||
@ -67,11 +71,12 @@ export const mockApiInterceptor = (request: HttpRequest<unknown>, next: HttpHand
|
||||
// For other status codes,
|
||||
// throw an error response
|
||||
response = new HttpErrorResponse({
|
||||
error : data.body.error,
|
||||
status : data.status,
|
||||
error: data.body.error,
|
||||
status: data.status,
|
||||
statusText: 'ERROR',
|
||||
});
|
||||
|
||||
return throwError(response);
|
||||
}));
|
||||
})
|
||||
);
|
||||
};
|
||||
|
@ -2,8 +2,7 @@ import { HttpRequest } from '@angular/common/http';
|
||||
import { FuseMockApiReplyCallback } from '@fuse/lib/mock-api/mock-api.types';
|
||||
import { Observable, of, take, throwError } from 'rxjs';
|
||||
|
||||
export class FuseMockApiHandler
|
||||
{
|
||||
export class FuseMockApiHandler {
|
||||
request!: HttpRequest<any>;
|
||||
urlParams!: { [key: string]: string };
|
||||
|
||||
@ -17,10 +16,8 @@ export class FuseMockApiHandler
|
||||
*/
|
||||
constructor(
|
||||
public url: string,
|
||||
public delay?: number,
|
||||
)
|
||||
{
|
||||
}
|
||||
public delay?: number
|
||||
) {}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Accessors
|
||||
@ -29,23 +26,19 @@ export class FuseMockApiHandler
|
||||
/**
|
||||
* Getter for response callback
|
||||
*/
|
||||
get response(): Observable<any>
|
||||
{
|
||||
get response(): Observable<any> {
|
||||
// If the execution limit has been reached, throw an error
|
||||
if ( this._replyCount > 0 && this._replyCount <= this._replied )
|
||||
{
|
||||
if (this._replyCount > 0 && this._replyCount <= this._replied) {
|
||||
return throwError('Execution limit has been reached!');
|
||||
}
|
||||
|
||||
// If the response callback has not been set, throw an error
|
||||
if ( !this._reply )
|
||||
{
|
||||
if (!this._reply) {
|
||||
return throwError('Response callback function does not exist!');
|
||||
}
|
||||
|
||||
// If the request has not been set, throw an error
|
||||
if ( !this.request )
|
||||
{
|
||||
if (!this.request) {
|
||||
return throwError('Request does not exist!');
|
||||
}
|
||||
|
||||
@ -54,13 +47,12 @@ export class FuseMockApiHandler
|
||||
|
||||
// Execute the reply callback
|
||||
const replyResult = this._reply({
|
||||
request : this.request,
|
||||
request: this.request,
|
||||
urlParams: this.urlParams,
|
||||
});
|
||||
|
||||
// If the result of the reply callback is an observable...
|
||||
if ( replyResult instanceof Observable )
|
||||
{
|
||||
if (replyResult instanceof Observable) {
|
||||
// Return the result as it is
|
||||
return replyResult.pipe(take(1));
|
||||
}
|
||||
@ -78,8 +70,7 @@ export class FuseMockApiHandler
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
reply(callback: FuseMockApiReplyCallback): void
|
||||
{
|
||||
reply(callback: FuseMockApiReplyCallback): void {
|
||||
// Store the reply
|
||||
this._reply = callback;
|
||||
}
|
||||
@ -89,11 +80,8 @@ export class FuseMockApiHandler
|
||||
*
|
||||
* @param count
|
||||
*/
|
||||
replyCount(count: number): void
|
||||
{
|
||||
replyCount(count: number): void {
|
||||
// Store the reply count
|
||||
this._replyCount = count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,18 +3,17 @@ import { FuseMockApiHandler } from '@fuse/lib/mock-api/mock-api.request-handler'
|
||||
import { FuseMockApiMethods } from '@fuse/lib/mock-api/mock-api.types';
|
||||
import { compact, fromPairs } from 'lodash-es';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseMockApiService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseMockApiService {
|
||||
private _handlers: { [key: string]: 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>(),
|
||||
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>(),
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -28,11 +27,19 @@ export class FuseMockApiService
|
||||
* @param method
|
||||
* @param url
|
||||
*/
|
||||
findHandler(method: string, url: string): { handler: FuseMockApiHandler | undefined; urlParams: { [key: string]: string } }
|
||||
{
|
||||
findHandler(
|
||||
method: string,
|
||||
url: string
|
||||
): {
|
||||
handler: FuseMockApiHandler | undefined;
|
||||
urlParams: { [key: string]: string };
|
||||
} {
|
||||
// Prepare the return object
|
||||
const matchingHandler: { handler: FuseMockApiHandler | undefined; urlParams: { [key: string]: string } } = {
|
||||
handler : undefined,
|
||||
const matchingHandler: {
|
||||
handler: FuseMockApiHandler | undefined;
|
||||
urlParams: { [key: string]: string };
|
||||
} = {
|
||||
handler: undefined,
|
||||
urlParams: {},
|
||||
};
|
||||
|
||||
@ -43,11 +50,9 @@ export class FuseMockApiService
|
||||
const handlers = this._handlers[method.toLowerCase()];
|
||||
|
||||
// Iterate through the handlers
|
||||
handlers.forEach((handler, handlerUrl) =>
|
||||
{
|
||||
handlers.forEach((handler, handlerUrl) => {
|
||||
// Skip if there is already a matching handler
|
||||
if ( matchingHandler.handler )
|
||||
{
|
||||
if (matchingHandler.handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -55,24 +60,32 @@ export class FuseMockApiService
|
||||
const handlerUrlParts = handlerUrl.split('/');
|
||||
|
||||
// Skip if the lengths of the urls we are comparing are not the same
|
||||
if ( urlParts.length !== handlerUrlParts.length )
|
||||
{
|
||||
if (urlParts.length !== handlerUrlParts.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Compare
|
||||
const matches = handlerUrlParts.every((handlerUrlPart, index) => handlerUrlPart === urlParts[index] || handlerUrlPart.startsWith(':'));
|
||||
const matches = handlerUrlParts.every(
|
||||
(handlerUrlPart, index) =>
|
||||
handlerUrlPart === urlParts[index] ||
|
||||
handlerUrlPart.startsWith(':')
|
||||
);
|
||||
|
||||
// If there is a match...
|
||||
if ( matches )
|
||||
{
|
||||
if (matches) {
|
||||
// Assign the matching handler
|
||||
matchingHandler.handler = handler;
|
||||
|
||||
// Extract and assign the parameters
|
||||
matchingHandler.urlParams = fromPairs(compact(handlerUrlParts.map((handlerUrlPart, index) =>
|
||||
handlerUrlPart.startsWith(':') ? [handlerUrlPart.substring(1), urlParts[index]] : undefined,
|
||||
)));
|
||||
matchingHandler.urlParams = fromPairs(
|
||||
compact(
|
||||
handlerUrlParts.map((handlerUrlPart, index) =>
|
||||
handlerUrlPart.startsWith(':')
|
||||
? [handlerUrlPart.substring(1), urlParts[index]]
|
||||
: undefined
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@ -85,8 +98,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onGet(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onGet(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('get', url, delay);
|
||||
}
|
||||
|
||||
@ -96,8 +108,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onPost(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onPost(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('post', url, delay);
|
||||
}
|
||||
|
||||
@ -107,8 +118,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onPatch(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onPatch(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('patch', url, delay);
|
||||
}
|
||||
|
||||
@ -118,8 +128,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onDelete(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onDelete(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('delete', url, delay);
|
||||
}
|
||||
|
||||
@ -129,8 +138,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onPut(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onPut(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('put', url, delay);
|
||||
}
|
||||
|
||||
@ -140,8 +148,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onHead(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onHead(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('head', url, delay);
|
||||
}
|
||||
|
||||
@ -151,8 +158,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onJsonp(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onJsonp(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('jsonp', url, delay);
|
||||
}
|
||||
|
||||
@ -162,8 +168,7 @@ export class FuseMockApiService
|
||||
* @param url - URL address of the mocked API endpoint
|
||||
* @param delay - Delay of the response in milliseconds
|
||||
*/
|
||||
onOptions(url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
onOptions(url: string, delay?: number): FuseMockApiHandler {
|
||||
return this._registerHandler('options', url, delay);
|
||||
}
|
||||
|
||||
@ -179,8 +184,11 @@ export class FuseMockApiService
|
||||
* @param delay
|
||||
* @private
|
||||
*/
|
||||
private _registerHandler(method: FuseMockApiMethods, url: string, delay?: number): FuseMockApiHandler
|
||||
{
|
||||
private _registerHandler(
|
||||
method: FuseMockApiMethods,
|
||||
url: string,
|
||||
delay?: number
|
||||
): FuseMockApiHandler {
|
||||
// Create a new instance of FuseMockApiRequestHandler
|
||||
const fuseMockHttp = new FuseMockApiHandler(url, delay);
|
||||
|
||||
|
@ -2,7 +2,10 @@ import { HttpRequest } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
export type FuseMockApiReplyCallback =
|
||||
| ((data: { request: HttpRequest<any>; urlParams: { [key: string]: string } }) => ([number, string | any]) | Observable<any>)
|
||||
| ((data: {
|
||||
request: HttpRequest<any>;
|
||||
urlParams: { [key: string]: string };
|
||||
}) => [number, string | any] | Observable<any>)
|
||||
| undefined;
|
||||
|
||||
export type FuseMockApiMethods =
|
||||
|
@ -1,5 +1,4 @@
|
||||
export class FuseMockApiUtils
|
||||
{
|
||||
export class FuseMockApiUtils {
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -7,23 +6,23 @@ export class FuseMockApiUtils
|
||||
/**
|
||||
* Generate a globally unique id
|
||||
*/
|
||||
static guid(): string
|
||||
{
|
||||
static guid(): string {
|
||||
/* eslint-disable */
|
||||
|
||||
let d = new Date().getTime();
|
||||
|
||||
// Use high-precision timer if available
|
||||
if ( typeof performance !== 'undefined' && typeof performance.now === 'function' )
|
||||
{
|
||||
if (
|
||||
typeof performance !== 'undefined' &&
|
||||
typeof performance.now === 'function'
|
||||
) {
|
||||
d += performance.now();
|
||||
}
|
||||
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) =>
|
||||
{
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||
const r = (d + Math.random() * 16) % 16 | 0;
|
||||
d = Math.floor(d / 16);
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
||||
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
||||
});
|
||||
|
||||
/* eslint-enable */
|
||||
|
@ -4,12 +4,11 @@ import { Pipe, PipeTransform } from '@angular/core';
|
||||
* Finds an object from given source using the given key - value pairs
|
||||
*/
|
||||
@Pipe({
|
||||
name : 'fuseFindByKey',
|
||||
pure : false,
|
||||
name: 'fuseFindByKey',
|
||||
pure: false,
|
||||
standalone: true,
|
||||
})
|
||||
export class FuseFindByKeyPipe implements PipeTransform
|
||||
{
|
||||
export class FuseFindByKeyPipe implements PipeTransform {
|
||||
/**
|
||||
* Transform
|
||||
*
|
||||
@ -17,15 +16,15 @@ export class FuseFindByKeyPipe implements PipeTransform
|
||||
* @param key Key of the object property to look for
|
||||
* @param source Array of objects to find from
|
||||
*/
|
||||
transform(value: string | string[], key: string, source: any[]): any
|
||||
{
|
||||
transform(value: string | string[], key: string, source: any[]): any {
|
||||
// If the given value is an array of strings...
|
||||
if ( Array.isArray(value) )
|
||||
{
|
||||
return value.map(item => source.find(sourceItem => sourceItem[key] === item));
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((item) =>
|
||||
source.find((sourceItem) => sourceItem[key] === item)
|
||||
);
|
||||
}
|
||||
|
||||
// If the value is a string...
|
||||
return source.find(sourceItem => sourceItem[key] === value);
|
||||
return source.find((sourceItem) => sourceItem[key] === value);
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from '@fuse/pipes/find-by-key/find-by-key.pipe';
|
||||
export * from '@fuse/pipes/find-by-key/find-by-key.module';
|
||||
export * from '@fuse/pipes/find-by-key/find-by-key.pipe';
|
||||
|
@ -3,9 +3,8 @@ import { FUSE_CONFIG } from '@fuse/services/config/config.constants';
|
||||
import { merge } from 'lodash-es';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseConfigService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseConfigService {
|
||||
private _config = new BehaviorSubject(inject(FUSE_CONFIG));
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -15,8 +14,7 @@ export class FuseConfigService
|
||||
/**
|
||||
* Setter & getter for config
|
||||
*/
|
||||
set config(value: any)
|
||||
{
|
||||
set config(value: any) {
|
||||
// Merge the new config over to the current config
|
||||
const config = merge({}, this._config.getValue(), value);
|
||||
|
||||
@ -25,8 +23,7 @@ export class FuseConfigService
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/member-ordering
|
||||
get config$(): Observable<any>
|
||||
{
|
||||
get config$(): Observable<any> {
|
||||
return this._config.asObservable();
|
||||
}
|
||||
|
||||
@ -37,8 +34,7 @@ export class FuseConfigService
|
||||
/**
|
||||
* Resets the config to the default
|
||||
*/
|
||||
reset(): void
|
||||
{
|
||||
reset(): void {
|
||||
// Set the config
|
||||
this._config.next(this.config);
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ export type Themes = { id: string; name: string }[];
|
||||
* AppConfig interface. Update this interface to strictly type your config
|
||||
* object.
|
||||
*/
|
||||
export interface FuseConfig
|
||||
{
|
||||
export interface FuseConfig {
|
||||
layout: string;
|
||||
scheme: Scheme;
|
||||
screens: Screens;
|
||||
|
@ -4,26 +4,25 @@ import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation
|
||||
import { FuseConfirmationDialogComponent } from '@fuse/services/confirmation/dialog/dialog.component';
|
||||
import { merge } from 'lodash-es';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseConfirmationService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseConfirmationService {
|
||||
private _matDialog: MatDialog = inject(MatDialog);
|
||||
private _defaultConfig: FuseConfirmationConfig = {
|
||||
title : 'Confirm action',
|
||||
message : 'Are you sure you want to confirm this action?',
|
||||
icon : {
|
||||
show : true,
|
||||
name : 'heroicons_outline:exclamation-triangle',
|
||||
title: 'Confirm action',
|
||||
message: 'Are you sure you want to confirm this action?',
|
||||
icon: {
|
||||
show: true,
|
||||
name: 'heroicons_outline:exclamation-triangle',
|
||||
color: 'warn',
|
||||
},
|
||||
actions : {
|
||||
actions: {
|
||||
confirm: {
|
||||
show : true,
|
||||
show: true,
|
||||
label: 'Confirm',
|
||||
color: 'warn',
|
||||
},
|
||||
cancel : {
|
||||
show : true,
|
||||
cancel: {
|
||||
show: true,
|
||||
label: 'Cancel',
|
||||
},
|
||||
},
|
||||
@ -34,17 +33,18 @@ export class FuseConfirmationService
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
open(config: FuseConfirmationConfig = {}): MatDialogRef<FuseConfirmationDialogComponent>
|
||||
{
|
||||
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,
|
||||
autoFocus: false,
|
||||
disableClose: !userConfig.dismissible,
|
||||
data : userConfig,
|
||||
panelClass : 'fuse-confirmation-dialog-panel',
|
||||
data: userConfig,
|
||||
panelClass: 'fuse-confirmation-dialog-panel',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
export interface FuseConfirmationConfig
|
||||
{
|
||||
export interface FuseConfirmationConfig {
|
||||
title?: string;
|
||||
message?: string;
|
||||
icon?: {
|
||||
show?: boolean;
|
||||
name?: string;
|
||||
color?: 'primary' | 'accent' | 'warn' | 'basic' | 'info' | 'success' | 'warning' | 'error';
|
||||
color?:
|
||||
| 'primary'
|
||||
| 'accent'
|
||||
| 'warn'
|
||||
| 'basic'
|
||||
| 'info'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'error';
|
||||
};
|
||||
actions?: {
|
||||
confirm?: {
|
||||
|
@ -1,71 +1,82 @@
|
||||
<div class="relative flex flex-col w-full h-full">
|
||||
|
||||
<div class="relative flex h-full w-full flex-col">
|
||||
<!-- Dismiss button -->
|
||||
<ng-container *ngIf="data.dismissible">
|
||||
<div class="absolute top-0 right-0 pt-4 pr-4">
|
||||
<button
|
||||
mat-icon-button
|
||||
[matDialogClose]="undefined">
|
||||
<div class="absolute right-0 top-0 pr-4 pt-4">
|
||||
<button mat-icon-button [matDialogClose]="undefined">
|
||||
<mat-icon
|
||||
class="text-secondary"
|
||||
[svgIcon]="'heroicons_outline:x-mark'"></mat-icon>
|
||||
[svgIcon]="'heroicons_outline:x-mark'"
|
||||
></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">
|
||||
|
||||
<div
|
||||
class="flex flex-auto flex-col items-center p-8 pb-6 sm:flex-row sm:items-start 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'
|
||||
}">
|
||||
class="flex h-10 w-10 flex-0 items-center justify-center rounded-full sm:mr-4"
|
||||
[ngClass]="{
|
||||
'bg-primary-100 text-primary-600 dark:bg-primary-600 dark:text-primary-50':
|
||||
data.icon.color === 'primary',
|
||||
'bg-accent-100 text-accent-600 dark:bg-accent-600 dark:text-accent-50':
|
||||
data.icon.color === 'accent',
|
||||
'bg-warn-100 text-warn-600 dark:bg-warn-600 dark:text-warn-50':
|
||||
data.icon.color === 'warn',
|
||||
'bg-gray-100 text-gray-600 dark:bg-gray-600 dark:text-gray-50':
|
||||
data.icon.color === 'basic',
|
||||
'bg-blue-100 text-blue-600 dark:bg-blue-600 dark:text-blue-50':
|
||||
data.icon.color === 'info',
|
||||
'bg-green-100 text-green-500 dark:bg-green-500 dark:text-green-50':
|
||||
data.icon.color === 'success',
|
||||
'bg-amber-100 text-amber-500 dark:bg-amber-500 dark:text-amber-50':
|
||||
data.icon.color === 'warning',
|
||||
'bg-red-100 text-red-600 dark:bg-red-600 dark:text-red-50':
|
||||
data.icon.color === 'error'
|
||||
}"
|
||||
>
|
||||
<mat-icon
|
||||
class="text-current"
|
||||
[svgIcon]="data.icon.name"></mat-icon>
|
||||
[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">
|
||||
|
||||
<div
|
||||
class="mt-4 flex flex-col items-center space-y-1 text-center sm:mt-0 sm:items-start sm:pr-8 sm:text-left"
|
||||
>
|
||||
<!-- Title -->
|
||||
<ng-container *ngIf="data.title">
|
||||
<div
|
||||
class="text-xl leading-6 font-medium"
|
||||
[innerHTML]="data.title"></div>
|
||||
class="text-xl font-medium leading-6"
|
||||
[innerHTML]="data.title"
|
||||
></div>
|
||||
</ng-container>
|
||||
|
||||
<!-- Message -->
|
||||
<ng-container *ngIf="data.message">
|
||||
<div
|
||||
class="text-secondary"
|
||||
[innerHTML]="data.message"></div>
|
||||
[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">
|
||||
|
||||
<div
|
||||
class="flex items-center justify-center space-x-3 bg-gray-50 px-6 py-4 dark:bg-black dark:bg-opacity-10 sm:justify-end"
|
||||
>
|
||||
<!-- Cancel -->
|
||||
<ng-container *ngIf="data.actions.cancel.show">
|
||||
<button
|
||||
mat-stroked-button
|
||||
[matDialogClose]="'cancelled'">
|
||||
{{data.actions.cancel.label}}
|
||||
<button mat-stroked-button [matDialogClose]="'cancelled'">
|
||||
{{ data.actions.cancel.label }}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
@ -74,12 +85,11 @@
|
||||
<button
|
||||
mat-flat-button
|
||||
[color]="data.actions.confirm.color"
|
||||
[matDialogClose]="'confirmed'">
|
||||
{{data.actions.confirm.label}}
|
||||
[matDialogClose]="'confirmed'"
|
||||
>
|
||||
{{ data.actions.confirm.label }}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
</div>
|
||||
|
@ -1,23 +1,21 @@
|
||||
import { NgClass, NgIf } from '@angular/common';
|
||||
import { Component, inject, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, ViewEncapsulation, inject } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation.types';
|
||||
|
||||
@Component({
|
||||
selector : 'fuse-confirmation-dialog',
|
||||
templateUrl : './dialog.component.html',
|
||||
styles : [
|
||||
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;
|
||||
}
|
||||
@ -26,10 +24,9 @@ import { FuseConfirmationConfig } from '@fuse/services/confirmation/confirmation
|
||||
`,
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
standalone : true,
|
||||
imports : [NgIf, MatButtonModule, MatDialogModule, MatIconModule, NgClass],
|
||||
standalone: true,
|
||||
imports: [NgIf, MatButtonModule, MatDialogModule, MatIconModule, NgClass],
|
||||
})
|
||||
export class FuseConfirmationDialogComponent
|
||||
{
|
||||
export class FuseConfirmationDialogComponent {
|
||||
data: FuseConfirmationConfig = inject(MAT_DIALOG_DATA);
|
||||
}
|
||||
|
@ -1,23 +1,21 @@
|
||||
import { HttpEvent, HttpHandlerFn, HttpRequest } from '@angular/common/http';
|
||||
import { inject } from '@angular/core';
|
||||
import { FuseLoadingService } from '@fuse/services/loading/loading.service';
|
||||
import { finalize, Observable, take } from 'rxjs';
|
||||
import { Observable, finalize, take } from 'rxjs';
|
||||
|
||||
export const fuseLoadingInterceptor = (req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> =>
|
||||
{
|
||||
export const fuseLoadingInterceptor = (
|
||||
req: HttpRequest<unknown>,
|
||||
next: HttpHandlerFn
|
||||
): Observable<HttpEvent<unknown>> => {
|
||||
const fuseLoadingService = inject(FuseLoadingService);
|
||||
let handleRequestsAutomatically = false;
|
||||
|
||||
fuseLoadingService.auto$
|
||||
.pipe(take(1))
|
||||
.subscribe((value) =>
|
||||
{
|
||||
handleRequestsAutomatically = value;
|
||||
});
|
||||
fuseLoadingService.auto$.pipe(take(1)).subscribe((value) => {
|
||||
handleRequestsAutomatically = value;
|
||||
});
|
||||
|
||||
// If the Auto mode is turned off, do nothing
|
||||
if ( !handleRequestsAutomatically )
|
||||
{
|
||||
if (!handleRequestsAutomatically) {
|
||||
return next(req);
|
||||
}
|
||||
|
||||
@ -25,9 +23,9 @@ export const fuseLoadingInterceptor = (req: HttpRequest<unknown>, next: HttpHand
|
||||
fuseLoadingService._setLoadingStatus(true, req.url);
|
||||
|
||||
return next(req).pipe(
|
||||
finalize(() =>
|
||||
{
|
||||
finalize(() => {
|
||||
// Set the status to false if there are any errors or the request is completed
|
||||
fuseLoadingService._setLoadingStatus(false, req.url);
|
||||
}));
|
||||
})
|
||||
);
|
||||
};
|
||||
|
@ -1,13 +1,19 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
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);
|
||||
@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>();
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -17,32 +23,28 @@ export class FuseLoadingService
|
||||
/**
|
||||
* Getter for auto mode
|
||||
*/
|
||||
get auto$(): Observable<boolean>
|
||||
{
|
||||
get auto$(): Observable<boolean> {
|
||||
return this._auto$.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for mode
|
||||
*/
|
||||
get mode$(): Observable<'determinate' | 'indeterminate'>
|
||||
{
|
||||
get mode$(): Observable<'determinate' | 'indeterminate'> {
|
||||
return this._mode$.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for progress
|
||||
*/
|
||||
get progress$(): Observable<number>
|
||||
{
|
||||
get progress$(): Observable<number> {
|
||||
return this._progress$.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for show
|
||||
*/
|
||||
get show$(): Observable<boolean>
|
||||
{
|
||||
get show$(): Observable<boolean> {
|
||||
return this._show$.asObservable();
|
||||
}
|
||||
|
||||
@ -53,16 +55,14 @@ export class FuseLoadingService
|
||||
/**
|
||||
* Show the loading bar
|
||||
*/
|
||||
show(): void
|
||||
{
|
||||
show(): void {
|
||||
this._show$.next(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the loading bar
|
||||
*/
|
||||
hide(): void
|
||||
{
|
||||
hide(): void {
|
||||
this._show$.next(false);
|
||||
}
|
||||
|
||||
@ -71,8 +71,7 @@ export class FuseLoadingService
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
setAutoMode(value: boolean): void
|
||||
{
|
||||
setAutoMode(value: boolean): void {
|
||||
this._auto$.next(value);
|
||||
}
|
||||
|
||||
@ -81,8 +80,7 @@ export class FuseLoadingService
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
setMode(value: 'determinate' | 'indeterminate'): void
|
||||
{
|
||||
setMode(value: 'determinate' | 'indeterminate'): void {
|
||||
this._mode$.next(value);
|
||||
}
|
||||
|
||||
@ -91,10 +89,8 @@ export class FuseLoadingService
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
setProgress(value: number): void
|
||||
{
|
||||
if ( value < 0 || value > 100 )
|
||||
{
|
||||
setProgress(value: number): void {
|
||||
if (value < 0 || value > 100) {
|
||||
console.error('Progress value must be between 0 and 100!');
|
||||
return;
|
||||
}
|
||||
@ -108,28 +104,22 @@ export class FuseLoadingService
|
||||
* @param status
|
||||
* @param url
|
||||
*/
|
||||
_setLoadingStatus(status: boolean, url: string): void
|
||||
{
|
||||
_setLoadingStatus(status: boolean, url: string): void {
|
||||
// Return if the url was not provided
|
||||
if ( !url )
|
||||
{
|
||||
if (!url) {
|
||||
console.error('The request URL must be provided!');
|
||||
return;
|
||||
}
|
||||
|
||||
if ( status === true )
|
||||
{
|
||||
if (status === true) {
|
||||
this._urlMap.set(url, status);
|
||||
this._show$.next(true);
|
||||
}
|
||||
else if ( status === false && this._urlMap.has(url) )
|
||||
{
|
||||
} 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 )
|
||||
{
|
||||
if (this._urlMap.size === 0) {
|
||||
this._show$.next(false);
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from '@fuse/services/loading/loading.service';
|
||||
export * from '@fuse/services/loading/loading.interceptor';
|
||||
export * from '@fuse/services/loading/loading.service';
|
||||
|
@ -1,54 +1,74 @@
|
||||
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { FuseConfigService } from '@fuse/services/config';
|
||||
import { fromPairs } from 'lodash-es';
|
||||
import { map, Observable, ReplaySubject, switchMap } from 'rxjs';
|
||||
import { Observable, ReplaySubject, map, switchMap } from 'rxjs';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseMediaWatcherService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseMediaWatcherService {
|
||||
private _breakpointObserver = inject(BreakpointObserver);
|
||||
private _fuseConfigService = inject(FuseConfigService);
|
||||
|
||||
private _onMediaChange: ReplaySubject<{ matchingAliases: string[]; matchingQueries: any }> = new ReplaySubject<{ matchingAliases: string[]; matchingQueries: any }>(1);
|
||||
private _onMediaChange: ReplaySubject<{
|
||||
matchingAliases: string[];
|
||||
matchingQueries: any;
|
||||
}> = new ReplaySubject<{ matchingAliases: string[]; matchingQueries: any }>(
|
||||
1
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor()
|
||||
{
|
||||
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
|
||||
const matchingAliases: string[] = [];
|
||||
const matchingQueries: any = {};
|
||||
constructor() {
|
||||
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
|
||||
const matchingAliases: string[] = [];
|
||||
const matchingQueries: any = {};
|
||||
|
||||
// Get the matching breakpoints and use them to fill the subject
|
||||
const matchingBreakpoints = Object.entries(state.breakpoints).filter(([query, matches]) => matches) ?? [];
|
||||
for ( const [query] of matchingBreakpoints )
|
||||
{
|
||||
// Find the alias of the matching query
|
||||
const matchingAlias = Object.entries(screens).find(([alias, q]) => q === query)[0];
|
||||
// Get the matching breakpoints and use them to fill the subject
|
||||
const matchingBreakpoints =
|
||||
Object.entries(state.breakpoints).filter(
|
||||
([query, matches]) => matches
|
||||
) ?? [];
|
||||
for (const [query] of matchingBreakpoints) {
|
||||
// Find the alias of the matching query
|
||||
const matchingAlias = Object.entries(
|
||||
screens
|
||||
).find(([alias, q]) => q === query)[0];
|
||||
|
||||
// Add the matching query to the observable values
|
||||
if ( matchingAlias )
|
||||
{
|
||||
matchingAliases.push(matchingAlias);
|
||||
matchingQueries[matchingAlias] = query;
|
||||
}
|
||||
}
|
||||
// Add the matching query to the observable values
|
||||
if (matchingAlias) {
|
||||
matchingAliases.push(matchingAlias);
|
||||
matchingQueries[matchingAlias] = query;
|
||||
}
|
||||
}
|
||||
|
||||
// Execute the observable
|
||||
this._onMediaChange.next({
|
||||
matchingAliases,
|
||||
matchingQueries,
|
||||
});
|
||||
}),
|
||||
)),
|
||||
).subscribe();
|
||||
// Execute the observable
|
||||
this._onMediaChange.next({
|
||||
matchingAliases,
|
||||
matchingQueries,
|
||||
});
|
||||
})
|
||||
)
|
||||
)
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -58,8 +78,10 @@ export class FuseMediaWatcherService
|
||||
/**
|
||||
* Getter for _onMediaChange
|
||||
*/
|
||||
get onMediaChange$(): Observable<{ matchingAliases: string[]; matchingQueries: any }>
|
||||
{
|
||||
get onMediaChange$(): Observable<{
|
||||
matchingAliases: string[];
|
||||
matchingQueries: any;
|
||||
}> {
|
||||
return this._onMediaChange.asObservable();
|
||||
}
|
||||
|
||||
@ -72,8 +94,7 @@ export class FuseMediaWatcherService
|
||||
*
|
||||
* @param query
|
||||
*/
|
||||
onMediaQueryChange$(query: string | string[]): Observable<BreakpointState>
|
||||
{
|
||||
onMediaQueryChange$(query: string | string[]): Observable<BreakpointState> {
|
||||
return this._breakpointObserver.observe(query);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Platform } from '@angular/cdk/platform';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FusePlatformService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FusePlatformService {
|
||||
private _platform = inject(Platform);
|
||||
|
||||
osName = 'os-unknown';
|
||||
@ -11,49 +10,40 @@ export class FusePlatformService
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor()
|
||||
{
|
||||
constructor() {
|
||||
// If the platform is not a browser, return immediately
|
||||
if ( !this._platform.isBrowser )
|
||||
{
|
||||
if (!this._platform.isBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Windows
|
||||
if ( navigator.userAgent.includes('Win') )
|
||||
{
|
||||
if (navigator.userAgent.includes('Win')) {
|
||||
this.osName = 'os-windows';
|
||||
}
|
||||
|
||||
// Mac OS
|
||||
if ( navigator.userAgent.includes('Mac') )
|
||||
{
|
||||
if (navigator.userAgent.includes('Mac')) {
|
||||
this.osName = 'os-mac';
|
||||
}
|
||||
|
||||
// Unix
|
||||
if ( navigator.userAgent.includes('X11') )
|
||||
{
|
||||
if (navigator.userAgent.includes('X11')) {
|
||||
this.osName = 'os-unix';
|
||||
}
|
||||
|
||||
// Linux
|
||||
if ( navigator.userAgent.includes('Linux') )
|
||||
{
|
||||
if (navigator.userAgent.includes('Linux')) {
|
||||
this.osName = 'os-linux';
|
||||
}
|
||||
|
||||
// iOS
|
||||
if ( this._platform.IOS )
|
||||
{
|
||||
if (this._platform.IOS) {
|
||||
this.osName = 'os-ios';
|
||||
}
|
||||
|
||||
// Android
|
||||
if ( this._platform.ANDROID )
|
||||
{
|
||||
if (this._platform.ANDROID) {
|
||||
this.osName = 'os-android';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,25 +3,22 @@ import { inject, Injectable } from '@angular/core';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { filter, take } from 'rxjs';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseSplashScreenService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseSplashScreenService {
|
||||
private _document = inject(DOCUMENT);
|
||||
private _router = inject(Router);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor()
|
||||
{
|
||||
constructor() {
|
||||
// Hide it on the first NavigationEnd event
|
||||
this._router.events
|
||||
.pipe(
|
||||
filter(event => event instanceof NavigationEnd),
|
||||
take(1),
|
||||
filter((event) => event instanceof NavigationEnd),
|
||||
take(1)
|
||||
)
|
||||
.subscribe(() =>
|
||||
{
|
||||
.subscribe(() => {
|
||||
this.hide();
|
||||
});
|
||||
}
|
||||
@ -33,16 +30,14 @@ export class FuseSplashScreenService
|
||||
/**
|
||||
* Show the splash screen
|
||||
*/
|
||||
show(): void
|
||||
{
|
||||
show(): void {
|
||||
this._document.body.classList.remove('fuse-splash-screen-hidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the splash screen
|
||||
*/
|
||||
hide(): void
|
||||
{
|
||||
hide(): void {
|
||||
this._document.body.classList.add('fuse-splash-screen-hidden');
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { IsActiveMatchOptions } from '@angular/router';
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class FuseUtilsService
|
||||
{
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FuseUtilsService {
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Accessors
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
@ -11,26 +10,24 @@ export class FuseUtilsService
|
||||
/**
|
||||
* Get the equivalent "IsActiveMatchOptions" options for "exact = true".
|
||||
*/
|
||||
get exactMatchOptions(): IsActiveMatchOptions
|
||||
{
|
||||
get exactMatchOptions(): IsActiveMatchOptions {
|
||||
return {
|
||||
paths : 'exact',
|
||||
fragment : 'ignored',
|
||||
paths: 'exact',
|
||||
fragment: 'ignored',
|
||||
matrixParams: 'ignored',
|
||||
queryParams : 'exact',
|
||||
queryParams: 'exact',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the equivalent "IsActiveMatchOptions" options for "exact = false".
|
||||
*/
|
||||
get subsetMatchOptions(): IsActiveMatchOptions
|
||||
{
|
||||
get subsetMatchOptions(): IsActiveMatchOptions {
|
||||
return {
|
||||
paths : 'subset',
|
||||
fragment : 'ignored',
|
||||
paths: 'subset',
|
||||
fragment: 'ignored',
|
||||
matrixParams: 'ignored',
|
||||
queryParams : 'subset',
|
||||
queryParams: 'subset',
|
||||
};
|
||||
}
|
||||
|
||||
@ -43,13 +40,12 @@ export class FuseUtilsService
|
||||
*
|
||||
* @param length
|
||||
*/
|
||||
randomId(length: number = 10): string
|
||||
{
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
randomId(length: number = 10): string {
|
||||
const chars =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let name = '';
|
||||
|
||||
for ( let i = 0; i < 10; i++ )
|
||||
{
|
||||
for (let i = 0; i < 10; i++) {
|
||||
name += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
flex-direction: column;
|
||||
margin: 32px 0;
|
||||
overflow: hidden;
|
||||
@apply rounded-2xl shadow bg-card;
|
||||
@apply bg-card rounded-2xl shadow;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
@ -32,11 +32,8 @@
|
||||
}
|
||||
|
||||
mat-tab-group {
|
||||
|
||||
.mat-tab-body-content {
|
||||
|
||||
.fuse-highlight {
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
|
@ -8,8 +8,8 @@
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* @ Font smoothing
|
||||
/* -------------------------------------------------------------------------- */
|
||||
*[class*=mat-],
|
||||
*[class*=mat-mdc-] {
|
||||
*[class*='mat-'],
|
||||
*[class*='mat-mdc-'] {
|
||||
-webkit-font-smoothing: auto !important;
|
||||
-moz-osx-font-smoothing: auto !important;
|
||||
|
||||
@ -23,11 +23,10 @@
|
||||
/* @ Accordion
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-accordion {
|
||||
|
||||
.mat-expansion-panel {
|
||||
margin-bottom: 24px;
|
||||
border-radius: 8px !important;
|
||||
transition: box-shadow 225ms cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
transition: box-shadow 225ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||
@apply shadow #{'!important'};
|
||||
|
||||
&:last-child {
|
||||
@ -40,11 +39,8 @@
|
||||
}
|
||||
|
||||
&:not(.mat-expanded) {
|
||||
|
||||
.mat-expansion-panel-header {
|
||||
|
||||
&:not([aria-disabled=true]) {
|
||||
|
||||
&:not([aria-disabled='true']) {
|
||||
&.cdk-keyboard-focused,
|
||||
&.cdk-program-focused,
|
||||
&:hover {
|
||||
@ -57,8 +53,7 @@
|
||||
.mat-expansion-panel-header {
|
||||
font-size: 14px;
|
||||
|
||||
&[aria-disabled=true] {
|
||||
|
||||
&[aria-disabled='true'] {
|
||||
.mat-expansion-panel-header-description {
|
||||
margin-right: 28px;
|
||||
}
|
||||
@ -107,8 +102,7 @@
|
||||
}
|
||||
|
||||
/* Lower the icon opacity on disabled buttons */
|
||||
&[disabled=true] {
|
||||
|
||||
&[disabled='true'] {
|
||||
.mat-icon {
|
||||
opacity: 0.38 !important;
|
||||
}
|
||||
@ -157,13 +151,11 @@
|
||||
border-radius: 9999px !important;
|
||||
}
|
||||
|
||||
|
||||
/* Fix the alignment of icons when used within buttons */
|
||||
.mat-mdc-button,
|
||||
.mat-mdc-raised-button,
|
||||
.mat-mdc-outlined-button,
|
||||
.mat-mdc-unelevated-button {
|
||||
|
||||
& > .mat-icon {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
@ -178,11 +170,8 @@
|
||||
.mat-mdc-icon-button,
|
||||
.mat-mdc-fab,
|
||||
.mat-mdc-mini-fab {
|
||||
|
||||
.mat-mdc-progress-spinner {
|
||||
|
||||
.mdc-circular-progress__indeterminate-container {
|
||||
|
||||
circle {
|
||||
stroke: currentColor !important;
|
||||
animation-duration: 6000ms;
|
||||
@ -196,12 +185,15 @@
|
||||
.mat-mdc-unelevated-button,
|
||||
.mat-mdc-fab,
|
||||
.mat-mdc-mini-fab {
|
||||
|
||||
--mat-mdc-button-persistent-ripple-color: theme('colors.gray[400]') !important;
|
||||
--mat-mdc-button-persistent-ripple-color: theme(
|
||||
'colors.gray[400]'
|
||||
) !important;
|
||||
--mat-mdc-button-ripple-color: rgba(0, 0, 0, 0.1) !important;
|
||||
|
||||
.dark & {
|
||||
--mat-mdc-button-persistent-ripple-color: theme('colors.black') !important;
|
||||
--mat-mdc-button-persistent-ripple-color: theme(
|
||||
'colors.black'
|
||||
) !important;
|
||||
--mat-mdc-button-ripple-color: rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
@ -218,12 +210,9 @@
|
||||
.mat-mdc-button,
|
||||
.mat-mdc-icon-button,
|
||||
.mat-mdc-outlined-button {
|
||||
|
||||
&:not([disabled=true]) {
|
||||
|
||||
&:not([disabled='true']) {
|
||||
/* Apply primary color */
|
||||
&.mat-primary {
|
||||
|
||||
.mat-icon {
|
||||
@apply text-primary #{'!important'};
|
||||
}
|
||||
@ -231,7 +220,6 @@
|
||||
|
||||
/* Apply accent color */
|
||||
&.mat-accent {
|
||||
|
||||
.mat-icon {
|
||||
@apply text-accent #{'!important'};
|
||||
}
|
||||
@ -239,7 +227,6 @@
|
||||
|
||||
/* Apply warn color */
|
||||
&.mat-warn {
|
||||
|
||||
.mat-icon {
|
||||
@apply text-warn #{'!important'};
|
||||
}
|
||||
@ -249,21 +236,19 @@
|
||||
|
||||
/* Adjust the border color of outlined buttons */
|
||||
.mat-mdc-outlined-button {
|
||||
|
||||
/* Not disabled */
|
||||
&:not([disabled=true]) {
|
||||
&:not([disabled='true']) {
|
||||
@apply border-gray-300 dark:border-gray-500 #{'!important'};
|
||||
}
|
||||
|
||||
/* Disabled */
|
||||
&[disabled=true] {
|
||||
&[disabled='true'] {
|
||||
@apply border-gray-300/70 dark:border-gray-600 #{'!important'};
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't wrap the button label text */
|
||||
.mdc-button {
|
||||
|
||||
.mdc-button__label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@ -277,7 +262,6 @@
|
||||
@apply space-x-1;
|
||||
|
||||
&.mat-button-toggle-group-appearance-standard {
|
||||
|
||||
.mat-button-toggle + .mat-button-toggle {
|
||||
background-clip: padding-box;
|
||||
}
|
||||
@ -290,7 +274,6 @@
|
||||
font-weight: 500;
|
||||
|
||||
&.mat-button-toggle-checked {
|
||||
|
||||
.mat-button-toggle-label-content {
|
||||
@apply text-default #{'!important'};
|
||||
}
|
||||
@ -330,7 +313,6 @@
|
||||
/* @ Dialog
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-mdc-dialog-container {
|
||||
|
||||
.mdc-dialog__surface {
|
||||
border-radius: 16px !important;
|
||||
padding: 24px;
|
||||
@ -350,7 +332,6 @@
|
||||
|
||||
/* "fill" appearance */
|
||||
.mat-mdc-form-field.mat-form-field-appearance-fill {
|
||||
|
||||
/* Disabled */
|
||||
&.mat-form-field-disabled {
|
||||
opacity: 0.7 !important;
|
||||
@ -358,7 +339,6 @@
|
||||
|
||||
/* Invalid */
|
||||
&.mat-form-field-invalid {
|
||||
|
||||
/* Border color */
|
||||
.mat-mdc-text-field-wrapper {
|
||||
@apply border-warn dark:border-warn #{'!important'};
|
||||
@ -366,7 +346,6 @@
|
||||
|
||||
/* Select */
|
||||
.mat-mdc-select {
|
||||
|
||||
/* Placeholder color */
|
||||
.mat-mdc-select-placeholder {
|
||||
@apply text-warn #{'!important'};
|
||||
@ -376,7 +355,6 @@
|
||||
|
||||
/* Hover */
|
||||
&:hover {
|
||||
|
||||
.mat-mdc-form-field-focus-overlay {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
@ -384,7 +362,6 @@
|
||||
|
||||
/* Focused */
|
||||
&.mat-focused {
|
||||
|
||||
.mat-mdc-form-field-focus-overlay {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
@ -392,7 +369,6 @@
|
||||
|
||||
/* Focused and valid fields */
|
||||
&.mat-focused:not(.mat-form-field-invalid) {
|
||||
|
||||
/* Border color */
|
||||
.mat-mdc-text-field-wrapper {
|
||||
@apply border-primary dark:border-primary #{'!important'};
|
||||
@ -401,9 +377,7 @@
|
||||
|
||||
/* Remove the default arrow for native select */
|
||||
&.mat-mdc-form-field-type-mat-native-select {
|
||||
|
||||
.mat-mdc-form-field-infix {
|
||||
|
||||
select {
|
||||
top: auto;
|
||||
margin-top: 0;
|
||||
@ -432,7 +406,7 @@
|
||||
border-radius: 6px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
@apply shadow-sm bg-white border-gray-300 dark:bg-black dark:bg-opacity-5 dark:border-gray-500 #{'!important'};
|
||||
@apply border-gray-300 bg-white shadow-sm dark:border-gray-500 dark:bg-black dark:bg-opacity-5 #{'!important'};
|
||||
|
||||
/* Adjust the top spacing and overflow when mat-label present */
|
||||
&:not(.mdc-text-field--no-label) {
|
||||
@ -529,17 +503,16 @@
|
||||
align-items: center;
|
||||
|
||||
&:focus {
|
||||
|
||||
.mat-mdc-select-trigger {
|
||||
|
||||
.mat-mdc-select-value {
|
||||
@apply text-primary #{'!important'};
|
||||
}
|
||||
|
||||
.mat-mdc-select-arrow-wrapper {
|
||||
|
||||
.mat-mdc-select-arrow {
|
||||
border-top-color: var(--fuse-primary) !important;
|
||||
border-top-color: var(
|
||||
--fuse-primary
|
||||
) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -554,7 +527,6 @@
|
||||
max-width: none;
|
||||
|
||||
mat-mdc-select-trigger {
|
||||
|
||||
.mat-icon {
|
||||
margin: 0 !important;
|
||||
}
|
||||
@ -634,11 +606,8 @@
|
||||
|
||||
/* Adds better alignment for textarea inputs */
|
||||
&:has(textarea.mat-mdc-input-element) {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix,
|
||||
.mat-mdc-form-field-icon-suffix,
|
||||
@ -652,18 +621,14 @@
|
||||
|
||||
/* Rounded */
|
||||
&.fuse-mat-rounded {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
/* Emphasized affix */
|
||||
&.fuse-mat-emphasized-affix {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix {
|
||||
border-radius: 24px 0 0 24px;
|
||||
@ -684,7 +649,9 @@
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(.mat-mdc-select):not(.mat-datepicker-toggle) {
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(
|
||||
.mat-mdc-select
|
||||
):not(.mat-datepicker-toggle) {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
@ -709,7 +676,9 @@
|
||||
margin-left: 4px !important;
|
||||
}
|
||||
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(.mat-mdc-select):not(.mat-datepicker-toggle) {
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(
|
||||
.mat-mdc-select
|
||||
):not(.mat-datepicker-toggle) {
|
||||
margin-left: 12px !important;
|
||||
}
|
||||
}
|
||||
@ -720,16 +689,12 @@
|
||||
|
||||
/* Dense */
|
||||
&.fuse-mat-dense {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix,
|
||||
.mat-mdc-form-field-icon-suffix,
|
||||
.mat-mdc-form-field-text-suffix {
|
||||
|
||||
.mat-mdc-icon-button {
|
||||
width: 32px !important;
|
||||
min-width: 32px;
|
||||
@ -740,7 +705,6 @@
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix {
|
||||
|
||||
> .mat-mdc-icon-button {
|
||||
margin-left: -6px;
|
||||
margin-right: 12px;
|
||||
@ -749,7 +713,6 @@
|
||||
|
||||
.mat-mdc-form-field-icon-suffix,
|
||||
.mat-mdc-form-field-text-suffix {
|
||||
|
||||
> .mat-mdc-icon-button {
|
||||
margin-left: 12px;
|
||||
margin-right: -6px;
|
||||
@ -769,11 +732,8 @@
|
||||
|
||||
/* Adds better alignment for textarea inputs */
|
||||
&:has(textarea.mat-mdc-input-element) {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix,
|
||||
.mat-mdc-form-field-icon-suffix,
|
||||
@ -786,18 +746,14 @@
|
||||
|
||||
/* Rounded */
|
||||
&.fuse-mat-rounded {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
/* Emphasized affix */
|
||||
&.fuse-mat-emphasized-affix {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix {
|
||||
border-radius: 20px 0 0 20px !important;
|
||||
@ -815,11 +771,8 @@
|
||||
|
||||
/* Emphasized affix */
|
||||
&.fuse-mat-emphasized-affix {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix {
|
||||
align-self: stretch !important;
|
||||
@ -845,7 +798,9 @@
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(.mat-mdc-select):not(.mat-datepicker-toggle) {
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(
|
||||
.mat-mdc-select
|
||||
):not(.mat-datepicker-toggle) {
|
||||
margin-right: 16px;
|
||||
}
|
||||
}
|
||||
@ -875,7 +830,9 @@
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(.mat-mdc-select):not(.mat-datepicker-toggle) {
|
||||
> *:not(.mat-icon):not(.mat-mdc-icon-button):not(
|
||||
.mat-mdc-select
|
||||
):not(.mat-datepicker-toggle) {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
@ -891,11 +848,8 @@
|
||||
|
||||
/* with Textarea */
|
||||
&:has(textarea.mat-mdc-input-element) {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mat-mdc-form-field-icon-prefix,
|
||||
.mat-mdc-form-field-text-prefix,
|
||||
.mat-mdc-form-field-icon-suffix,
|
||||
@ -909,7 +863,6 @@
|
||||
|
||||
/* Bolder border width */
|
||||
&.fuse-mat-bold {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
border-width: 2px !important;
|
||||
}
|
||||
@ -918,10 +871,8 @@
|
||||
|
||||
/* "outline" appearance */
|
||||
.mat-mdc-form-field.mat-form-field-appearance-outline {
|
||||
|
||||
/* Invalid */
|
||||
&.mat-form-field-invalid {
|
||||
|
||||
.mdc-notched-outline__leading,
|
||||
.mdc-notched-outline__notch,
|
||||
.mdc-notched-outline__trailing {
|
||||
@ -931,10 +882,8 @@
|
||||
|
||||
/* Focused */
|
||||
&.mat-focused:not(.mat-form-field-invalid) {
|
||||
|
||||
/* Primary */
|
||||
&.mat-primary {
|
||||
|
||||
.mdc-notched-outline__leading,
|
||||
.mdc-notched-outline__notch,
|
||||
.mdc-notched-outline__trailing {
|
||||
@ -944,7 +893,6 @@
|
||||
|
||||
/* Accent */
|
||||
&.mat-accent {
|
||||
|
||||
.mdc-notched-outline__leading,
|
||||
.mdc-notched-outline__notch,
|
||||
.mdc-notched-outline__trailing {
|
||||
@ -954,13 +902,9 @@
|
||||
}
|
||||
|
||||
&:not(.mat-focused):not(.mat-form-field-invalid) {
|
||||
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mdc-notched-outline {
|
||||
|
||||
.mdc-notched-outline__leading,
|
||||
.mdc-notched-outline__notch,
|
||||
.mdc-notched-outline__trailing {
|
||||
@ -974,11 +918,8 @@
|
||||
/* Remove the extra border on the right side of the notch */
|
||||
/* Tailwind's global border setter causes this issue */
|
||||
.mat-mdc-text-field-wrapper {
|
||||
|
||||
.mat-mdc-form-field-flex {
|
||||
|
||||
.mdc-notched-outline {
|
||||
|
||||
.mdc-notched-outline__notch {
|
||||
border-right-style: none !important;
|
||||
}
|
||||
@ -991,7 +932,6 @@
|
||||
/* @ Datepicker
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* @ Icon
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -1012,7 +952,6 @@
|
||||
/* @ Inputs
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-mdc-input-element {
|
||||
|
||||
&::placeholder {
|
||||
transition: none !important;
|
||||
@apply text-hint #{'!important'};
|
||||
@ -1036,9 +975,7 @@
|
||||
|
||||
/* Invalid */
|
||||
.mat-form-field-invalid {
|
||||
|
||||
.mat-mdc-input-element {
|
||||
|
||||
/* Placeholder color */
|
||||
&::placeholder {
|
||||
@apply text-warn #{'!important'};
|
||||
@ -1065,7 +1002,6 @@
|
||||
min-width: 144px !important;
|
||||
|
||||
.mat-mdc-menu-content {
|
||||
|
||||
.mat-mdc-menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -1100,7 +1036,6 @@
|
||||
/* @ Paginator
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-mdc-paginator {
|
||||
|
||||
.mat-mdc-paginator-container {
|
||||
padding: 8px 16px;
|
||||
justify-content: space-between;
|
||||
@ -1160,7 +1095,6 @@
|
||||
}
|
||||
|
||||
.mat-mdc-select-trigger {
|
||||
|
||||
.mat-mdc-select-value {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@ -1191,14 +1125,12 @@
|
||||
/* @ Slide Toggle
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* @ Snack bar
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-mdc-snack-bar-container {
|
||||
|
||||
.mat-mdc-button.mat-mdc-snack-bar-action:not(:disabled) {
|
||||
color: #FFFFFF !important;
|
||||
color: #ffffff !important;
|
||||
|
||||
.dark & {
|
||||
color: #000000 !important;
|
||||
@ -1206,12 +1138,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* @ Stepper
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-step-icon {
|
||||
|
||||
/* Do not override the mat-icon color */
|
||||
.mat-icon {
|
||||
color: currentColor !important;
|
||||
@ -1227,7 +1157,6 @@
|
||||
/* @ Table
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-mdc-table {
|
||||
|
||||
.mdc-data-table__row:not(.mdc-data-table__row--selected):hover {
|
||||
background: none !important;
|
||||
}
|
||||
@ -1237,10 +1166,8 @@
|
||||
/* @ Tabs
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-mdc-tab-group {
|
||||
|
||||
/* No header */
|
||||
&.fuse-mat-no-header {
|
||||
|
||||
.mat-mdc-tab-header {
|
||||
height: 0 !important;
|
||||
max-height: 0 !important;
|
||||
@ -1251,9 +1178,7 @@
|
||||
}
|
||||
|
||||
&:not(.mat-background-primary):not(.mat-background-accent) {
|
||||
|
||||
.mat-mdc-tab-header {
|
||||
|
||||
.mat-mdc-tab-label-container {
|
||||
box-shadow: inset 0 -1px var(--fuse-border);
|
||||
}
|
||||
@ -1261,7 +1186,6 @@
|
||||
}
|
||||
|
||||
.mat-mdc-tab-header {
|
||||
|
||||
.mat-mdc-tab-label-container {
|
||||
margin: 0 24px;
|
||||
}
|
||||
@ -1283,10 +1207,8 @@ textarea.mat-mdc-input-element {
|
||||
/* @ Toolbar
|
||||
/* -------------------------------------------------------------------------- */
|
||||
.mat-toolbar {
|
||||
|
||||
/* Apply primary contrast color */
|
||||
&.mat-primary {
|
||||
|
||||
.mat-icon {
|
||||
@apply text-on-primary #{'!important'};
|
||||
}
|
||||
@ -1310,7 +1232,6 @@ textarea.mat-mdc-input-element {
|
||||
|
||||
/* Apply accent contrast color */
|
||||
&.mat-accent {
|
||||
|
||||
.mat-icon {
|
||||
@apply text-on-accent #{'!important'};
|
||||
}
|
||||
@ -1334,7 +1255,6 @@ textarea.mat-mdc-input-element {
|
||||
|
||||
/* Apply warn contrast color */
|
||||
&.mat-warn {
|
||||
|
||||
.mat-icon {
|
||||
@apply text-on-warn #{'!important'};
|
||||
}
|
||||
|
@ -3,36 +3,35 @@
|
||||
/* ----------------------------------------------------------------------------------------------------- */
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'] {
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #8B9FC1;
|
||||
color: #8b9fc1;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-doctag,
|
||||
.hljs-keyword,
|
||||
.hljs-formula {
|
||||
color: #22D3EE;
|
||||
color: #22d3ee;
|
||||
}
|
||||
|
||||
.hljs-name {
|
||||
color: #E879F9;
|
||||
color: #e879f9;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #BAE6FD;
|
||||
color: #bae6fd;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-selector-tag,
|
||||
.hljs-deletion,
|
||||
.hljs-subst {
|
||||
color: #F87F71;
|
||||
color: #f87f71;
|
||||
}
|
||||
|
||||
.hljs-literal {
|
||||
color: #36BEFF;
|
||||
color: #36beff;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
@ -40,12 +39,12 @@ pre[class*='language-'] {
|
||||
.hljs-addition,
|
||||
.hljs-attribute,
|
||||
.hljs-meta-string {
|
||||
color: #BEF264;
|
||||
color: #bef264;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-class .hljs-title {
|
||||
color: #FFD374;
|
||||
color: #ffd374;
|
||||
}
|
||||
|
||||
.hljs-attr,
|
||||
@ -56,7 +55,7 @@ pre[class*='language-'] {
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo,
|
||||
.hljs-number {
|
||||
color: #22D3EE;
|
||||
color: #22d3ee;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
@ -65,7 +64,7 @@ pre[class*='language-'] {
|
||||
.hljs-meta,
|
||||
.hljs-selector-id,
|
||||
.hljs-title {
|
||||
color: #E879F9;
|
||||
color: #e879f9;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
|
@ -8,7 +8,6 @@
|
||||
&.ps--focus,
|
||||
&.ps--scrolling-x,
|
||||
&.ps--scrolling-y {
|
||||
|
||||
> .ps__rail-x,
|
||||
> .ps__rail-y {
|
||||
opacity: 1;
|
||||
|
@ -17,9 +17,7 @@
|
||||
}
|
||||
|
||||
.ql-picker {
|
||||
|
||||
&.ql-expanded {
|
||||
|
||||
.ql-picker-label {
|
||||
@apply border-gray-300;
|
||||
|
||||
@ -30,7 +28,7 @@
|
||||
|
||||
.ql-picker-options {
|
||||
z-index: 10 !important;
|
||||
@apply border-gray-300 bg-card;
|
||||
@apply bg-card border-gray-300;
|
||||
|
||||
.dark & {
|
||||
@apply border-gray-500;
|
||||
@ -43,7 +41,6 @@
|
||||
}
|
||||
|
||||
.ql-picker-options {
|
||||
|
||||
.ql-picker-item {
|
||||
@apply text-default;
|
||||
}
|
||||
@ -103,10 +100,10 @@
|
||||
}
|
||||
|
||||
.ql-tooltip {
|
||||
@apply px-3 py-1 shadow-sm rounded-md bg-gray-100 border-gray-300;
|
||||
@apply rounded-md border-gray-300 bg-gray-100 px-3 py-1 shadow-sm;
|
||||
|
||||
.dark & {
|
||||
@apply shadow-lg bg-gray-700 border-gray-700 #{'!important'};
|
||||
@apply border-gray-700 bg-gray-700 shadow-lg #{'!important'};
|
||||
}
|
||||
|
||||
// Label
|
||||
@ -116,10 +113,10 @@
|
||||
|
||||
.ql-action,
|
||||
.ql-remove {
|
||||
@apply text-primary border-gray-300;
|
||||
@apply border-gray-300 text-primary;
|
||||
|
||||
.dark & {
|
||||
@apply text-primary-400 border-gray-300;
|
||||
@apply border-gray-300 text-primary-400;
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,10 +129,10 @@
|
||||
}
|
||||
|
||||
input {
|
||||
@apply rounded-sm text-default bg-white border-gray-300 #{'!important'};
|
||||
@apply text-default rounded-sm border-gray-300 bg-white #{'!important'};
|
||||
|
||||
.dark & {
|
||||
@apply bg-gray-700 border-gray-500 #{'!important'};
|
||||
@apply border-gray-500 bg-gray-700 #{'!important'};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
/* This injects additional styles into Tailwind's base styles layer. */
|
||||
@layer base {
|
||||
|
||||
* {
|
||||
/* Text rendering */
|
||||
text-rendering: optimizeLegibility;
|
||||
@ -64,7 +63,9 @@
|
||||
}
|
||||
|
||||
/* Set the background and foreground colors */
|
||||
body, .dark, .light {
|
||||
body,
|
||||
.dark,
|
||||
.light {
|
||||
@apply text-default bg-default #{'!important'};
|
||||
}
|
||||
|
||||
@ -82,9 +83,7 @@
|
||||
|
||||
/* 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;
|
||||
@ -127,13 +126,14 @@
|
||||
|
||||
/* Print styles */
|
||||
@media print {
|
||||
|
||||
/* Make the base font size smaller for print so everything is scaled nicely */
|
||||
html {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
body, .dark, .light {
|
||||
body,
|
||||
.dark,
|
||||
.light {
|
||||
background: none !important;
|
||||
}
|
||||
}
|
||||
|
@ -1,154 +1,247 @@
|
||||
@use "sass:map";
|
||||
@use 'sass:map';
|
||||
@use '@angular/material' as mat;
|
||||
@use "user-themes" as userThemes;
|
||||
@use 'user-themes' as userThemes;
|
||||
|
||||
/* 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 */
|
||||
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 */
|
||||
)
|
||||
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 */
|
||||
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 */
|
||||
)
|
||||
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();
|
||||
|
||||
/* Create a base theme without any color to set the density and typography */
|
||||
@include mat.all-component-themes((
|
||||
color: null,
|
||||
density: 0,
|
||||
typography: mat.m2-define-typography-config(
|
||||
$font-family: theme('fontFamily.sans'),
|
||||
$headline-1: mat.m2-define-typography-level(1.875rem, 2.25rem, 800, theme('fontFamily.sans')),
|
||||
$headline-2: mat.m2-define-typography-level(1.25rem, 1.75rem, 700, theme('fontFamily.sans')),
|
||||
$headline-3: mat.m2-define-typography-level(1.125rem, 1.75rem, 600, theme('fontFamily.sans')),
|
||||
$headline-4: mat.m2-define-typography-level(0.875rem, 1.25rem, 600, theme('fontFamily.sans')),
|
||||
$headline-5: mat.m2-define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$headline-6: mat.m2-define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$subtitle-1: mat.m2-define-typography-level(1rem, 1.75rem, 400, theme('fontFamily.sans')),
|
||||
$subtitle-2: mat.m2-define-typography-level(0.875rem, 1.25rem, 600, theme('fontFamily.sans')),
|
||||
$body-1: mat.m2-define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$body-2: mat.m2-define-typography-level(0.875rem, 1.5rem, 400, theme('fontFamily.sans')),
|
||||
$caption: mat.m2-define-typography-level(0.75rem, 1rem, 400, theme('fontFamily.sans')),
|
||||
$button: mat.m2-define-typography-level(0.875rem, 0.875rem, 500, theme('fontFamily.sans')),
|
||||
$overline: mat.m2-define-typography-level(0.75rem, 2rem, 500, theme('fontFamily.sans'))
|
||||
@include mat.all-component-themes(
|
||||
(
|
||||
color: null,
|
||||
density: 0,
|
||||
typography:
|
||||
mat.m2-define-typography-config(
|
||||
$font-family: theme('fontFamily.sans'),
|
||||
$headline-1:
|
||||
mat.m2-define-typography-level(
|
||||
1.875rem,
|
||||
2.25rem,
|
||||
800,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$headline-2:
|
||||
mat.m2-define-typography-level(
|
||||
1.25rem,
|
||||
1.75rem,
|
||||
700,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$headline-3:
|
||||
mat.m2-define-typography-level(
|
||||
1.125rem,
|
||||
1.75rem,
|
||||
600,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$headline-4:
|
||||
mat.m2-define-typography-level(
|
||||
0.875rem,
|
||||
1.25rem,
|
||||
600,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$headline-5:
|
||||
mat.m2-define-typography-level(
|
||||
0.875rem,
|
||||
1.5rem,
|
||||
400,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$headline-6:
|
||||
mat.m2-define-typography-level(
|
||||
0.875rem,
|
||||
1.5rem,
|
||||
400,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$subtitle-1:
|
||||
mat.m2-define-typography-level(
|
||||
1rem,
|
||||
1.75rem,
|
||||
400,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$subtitle-2:
|
||||
mat.m2-define-typography-level(
|
||||
0.875rem,
|
||||
1.25rem,
|
||||
600,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$body-1:
|
||||
mat.m2-define-typography-level(
|
||||
0.875rem,
|
||||
1.5rem,
|
||||
400,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$body-2:
|
||||
mat.m2-define-typography-level(
|
||||
0.875rem,
|
||||
1.5rem,
|
||||
400,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$caption:
|
||||
mat.m2-define-typography-level(
|
||||
0.75rem,
|
||||
1rem,
|
||||
400,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$button:
|
||||
mat.m2-define-typography-level(
|
||||
0.875rem,
|
||||
0.875rem,
|
||||
500,
|
||||
theme('fontFamily.sans')
|
||||
),
|
||||
$overline:
|
||||
mat.m2-define-typography-level(
|
||||
0.75rem,
|
||||
2rem,
|
||||
500,
|
||||
theme('fontFamily.sans')
|
||||
)
|
||||
),
|
||||
)
|
||||
));
|
||||
);
|
||||
|
||||
/* Loop through user themes and generate Angular Material themes */
|
||||
@each $name, $theme in userThemes.$user-themes {
|
||||
|
||||
/* Generate the palettes */
|
||||
$palettes: ();
|
||||
@each $name in (primary, accent, warn) {
|
||||
|
||||
/* Define the Angular Material theme */
|
||||
$palette: mat.m2-define-palette(map.get($theme, $name));
|
||||
|
||||
/* 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)
|
||||
));
|
||||
$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),
|
||||
)
|
||||
);
|
||||
|
||||
$palettes: map.merge($palettes, (#{$name}: $palette));
|
||||
}
|
||||
|
||||
/* Define a light & dark Angular Material theme with the generated palettes */
|
||||
$light-theme: mat.m2-define-light-theme((
|
||||
color: $palettes
|
||||
));
|
||||
$light-theme: mat.m2-define-light-theme(
|
||||
(
|
||||
color: $palettes,
|
||||
)
|
||||
);
|
||||
|
||||
$dark-theme: mat.m2-define-dark-theme((
|
||||
color: $palettes
|
||||
));
|
||||
$dark-theme: mat.m2-define-dark-theme(
|
||||
(
|
||||
color: $palettes,
|
||||
)
|
||||
);
|
||||
|
||||
/* 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
|
||||
(
|
||||
color: $light-theme-colors,
|
||||
),
|
||||
$light-theme-colors
|
||||
);
|
||||
|
||||
$dark-theme-colors: map.merge(map.get($dark-theme, color), $dark-base);
|
||||
$dark-theme: map.merge(
|
||||
(color: $dark-theme-colors),
|
||||
$dark-theme-colors
|
||||
(
|
||||
color: $dark-theme-colors,
|
||||
),
|
||||
$dark-theme-colors
|
||||
);
|
||||
|
||||
/* Generate and encapsulate Angular Material themes */
|
||||
|
@ -1,50 +1,47 @@
|
||||
const plugin = require('tailwindcss/plugin');
|
||||
|
||||
module.exports = plugin(
|
||||
({
|
||||
matchUtilities,
|
||||
theme,
|
||||
}) =>
|
||||
{
|
||||
({ matchUtilities, theme }) => {
|
||||
matchUtilities(
|
||||
{
|
||||
'icon-size': (value) => ({
|
||||
width : value,
|
||||
height : value,
|
||||
minWidth : value,
|
||||
minHeight : value,
|
||||
fontSize : value,
|
||||
width: value,
|
||||
height: value,
|
||||
minWidth: value,
|
||||
minHeight: value,
|
||||
fontSize: value,
|
||||
lineHeight: value,
|
||||
[`svg`] : {
|
||||
width : value,
|
||||
[`svg`]: {
|
||||
width: value,
|
||||
height: value,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
values: theme('iconSize'),
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
{
|
||||
theme: {
|
||||
iconSize: {
|
||||
3 : '0.75rem',
|
||||
3: '0.75rem',
|
||||
3.5: '0.875rem',
|
||||
4 : '1rem',
|
||||
4: '1rem',
|
||||
4.5: '1.125rem',
|
||||
5 : '1.25rem',
|
||||
6 : '1.5rem',
|
||||
7 : '1.75rem',
|
||||
8 : '2rem',
|
||||
10 : '2.5rem',
|
||||
12 : '3rem',
|
||||
14 : '3.5rem',
|
||||
16 : '4rem',
|
||||
18 : '4.5rem',
|
||||
20 : '5rem',
|
||||
22 : '5.5rem',
|
||||
24 : '6rem',
|
||||
5: '1.25rem',
|
||||
6: '1.5rem',
|
||||
7: '1.75rem',
|
||||
8: '2rem',
|
||||
10: '2.5rem',
|
||||
12: '3rem',
|
||||
14: '3.5rem',
|
||||
16: '4rem',
|
||||
18: '4.5rem',
|
||||
20: '5rem',
|
||||
22: '5.5rem',
|
||||
24: '6rem',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -4,9 +4,14 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const colors = require('tailwindcss/colors');
|
||||
const plugin = require('tailwindcss/plugin');
|
||||
const flattenColorPalette = require('tailwindcss/lib/util/flattenColorPalette').default;
|
||||
const generateContrasts = require(path.resolve(__dirname, ('../utils/generate-contrasts')));
|
||||
const jsonToSassMap = require(path.resolve(__dirname, ('../utils/json-to-sass-map')));
|
||||
const flattenColorPalette =
|
||||
require('tailwindcss/lib/util/flattenColorPalette').default;
|
||||
const generateContrasts = require(
|
||||
path.resolve(__dirname, '../utils/generate-contrasts')
|
||||
);
|
||||
const jsonToSassMap = require(
|
||||
path.resolve(__dirname, '../utils/json-to-sass-map')
|
||||
);
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Utilities
|
||||
@ -19,188 +24,277 @@ const jsonToSassMap = require(path.resolve(__dirname, ('../utils/json-to-sass-ma
|
||||
*
|
||||
* @param theme
|
||||
*/
|
||||
const normalizeTheme = (theme) =>
|
||||
{
|
||||
return _.fromPairs(_.map(_.omitBy(theme, (palette, paletteName) => paletteName.startsWith('on') || _.isEmpty(palette)),
|
||||
(palette, paletteName) => [
|
||||
paletteName,
|
||||
{
|
||||
...palette,
|
||||
DEFAULT: palette['DEFAULT'] || palette[500],
|
||||
},
|
||||
],
|
||||
));
|
||||
const normalizeTheme = (theme) => {
|
||||
return _.fromPairs(
|
||||
_.map(
|
||||
_.omitBy(
|
||||
theme,
|
||||
(palette, paletteName) =>
|
||||
paletteName.startsWith('on') || _.isEmpty(palette)
|
||||
),
|
||||
(palette, paletteName) => [
|
||||
paletteName,
|
||||
{
|
||||
...palette,
|
||||
DEFAULT: palette['DEFAULT'] || palette[500],
|
||||
},
|
||||
]
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ FUSE TailwindCSS Main Plugin
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
const theming = plugin.withOptions((options) => ({
|
||||
addComponents,
|
||||
e,
|
||||
theme,
|
||||
}) =>
|
||||
{
|
||||
/**
|
||||
* Create user themes object by going through the provided themes and
|
||||
* merging them with the provided "default" so, we can have a complete
|
||||
* set of color palettes for each user theme.
|
||||
*/
|
||||
const userThemes = _.fromPairs(_.map(options.themes, (theme, themeName) => [
|
||||
themeName,
|
||||
_.defaults({}, theme, options.themes['default']),
|
||||
]));
|
||||
const theming = plugin.withOptions(
|
||||
(options) =>
|
||||
({ addComponents, e, theme }) => {
|
||||
/**
|
||||
* Create user themes object by going through the provided themes and
|
||||
* merging them with the provided "default" so, we can have a complete
|
||||
* set of color palettes for each user theme.
|
||||
*/
|
||||
const userThemes = _.fromPairs(
|
||||
_.map(options.themes, (theme, themeName) => [
|
||||
themeName,
|
||||
_.defaults({}, theme, options.themes['default']),
|
||||
])
|
||||
);
|
||||
|
||||
/**
|
||||
* Normalize the themes and assign it to the themes object. This will
|
||||
* be the final object that we create a SASS map from
|
||||
*/
|
||||
let themes = _.fromPairs(_.map(userThemes, (theme, themeName) => [
|
||||
themeName,
|
||||
normalizeTheme(theme),
|
||||
]));
|
||||
/**
|
||||
* Normalize the themes and assign it to the themes object. This will
|
||||
* be the final object that we create a SASS map from
|
||||
*/
|
||||
let themes = _.fromPairs(
|
||||
_.map(userThemes, (theme, themeName) => [
|
||||
themeName,
|
||||
normalizeTheme(theme),
|
||||
])
|
||||
);
|
||||
|
||||
/**
|
||||
* Go through the themes to generate the contrasts and filter the
|
||||
* palettes to only have "primary", "accent" and "warn" objects.
|
||||
*/
|
||||
themes = _.fromPairs(_.map(themes, (theme, themeName) => [
|
||||
themeName,
|
||||
_.pick(
|
||||
_.fromPairs(_.map(theme, (palette, paletteName) => [
|
||||
paletteName,
|
||||
/**
|
||||
* Go through the themes to generate the contrasts and filter the
|
||||
* palettes to only have "primary", "accent" and "warn" objects.
|
||||
*/
|
||||
themes = _.fromPairs(
|
||||
_.map(themes, (theme, themeName) => [
|
||||
themeName,
|
||||
_.pick(
|
||||
_.fromPairs(
|
||||
_.map(theme, (palette, paletteName) => [
|
||||
paletteName,
|
||||
{
|
||||
...palette,
|
||||
contrast: _.fromPairs(
|
||||
_.map(
|
||||
generateContrasts(palette),
|
||||
(color, hue) => [
|
||||
hue,
|
||||
_.get(userThemes[themeName], [
|
||||
`on-${paletteName}`,
|
||||
hue,
|
||||
]) || color,
|
||||
]
|
||||
)
|
||||
),
|
||||
},
|
||||
])
|
||||
),
|
||||
['primary', 'accent', 'warn']
|
||||
),
|
||||
])
|
||||
);
|
||||
|
||||
/**
|
||||
* Go through the themes and attach appropriate class selectors so,
|
||||
* we can use them to encapsulate each theme.
|
||||
*/
|
||||
themes = _.fromPairs(
|
||||
_.map(themes, (theme, themeName) => [
|
||||
themeName,
|
||||
{
|
||||
...palette,
|
||||
contrast: _.fromPairs(_.map(generateContrasts(palette), (color, hue) => [
|
||||
hue,
|
||||
_.get(userThemes[themeName], [`on-${paletteName}`, hue]) || color,
|
||||
])),
|
||||
selector: `".theme-${themeName}"`,
|
||||
...theme,
|
||||
},
|
||||
])),
|
||||
['primary', 'accent', 'warn'],
|
||||
),
|
||||
]));
|
||||
])
|
||||
);
|
||||
|
||||
/**
|
||||
* Go through the themes and attach appropriate class selectors so,
|
||||
* we can use them to encapsulate each theme.
|
||||
*/
|
||||
themes = _.fromPairs(_.map(themes, (theme, themeName) => [
|
||||
themeName,
|
||||
{
|
||||
selector: `".theme-${themeName}"`,
|
||||
...theme,
|
||||
},
|
||||
]));
|
||||
/* Generate the SASS map using the themes object */
|
||||
const sassMap = jsonToSassMap(
|
||||
JSON.stringify({ 'user-themes': themes })
|
||||
);
|
||||
|
||||
/* Generate the SASS map using the themes object */
|
||||
const sassMap = jsonToSassMap(JSON.stringify({'user-themes': themes}));
|
||||
/* Get the file path */
|
||||
const filename = path.resolve(
|
||||
__dirname,
|
||||
'../../styles/user-themes.scss'
|
||||
);
|
||||
|
||||
/* Get the file path */
|
||||
const filename = path.resolve(__dirname, ('../../styles/user-themes.scss'));
|
||||
|
||||
/* Read the file and get its data */
|
||||
let data;
|
||||
try
|
||||
{
|
||||
data = fs.readFileSync(filename, {encoding: 'utf8'});
|
||||
}
|
||||
catch ( err )
|
||||
{
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
/* Write the file if the map has been changed */
|
||||
if ( data !== sassMap )
|
||||
{
|
||||
try
|
||||
{
|
||||
fs.writeFileSync(filename, sassMap, {encoding: 'utf8'});
|
||||
}
|
||||
catch ( err )
|
||||
{
|
||||
/* Read the file and get its data */
|
||||
let data;
|
||||
try {
|
||||
data = fs.readFileSync(filename, { encoding: 'utf8' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate through the user's themes and build Tailwind components containing
|
||||
* CSS Custom Properties using the colors from them. This allows switching
|
||||
* themes by simply replacing a class name as well as nesting them.
|
||||
*/
|
||||
addComponents(
|
||||
_.fromPairs(_.map(options.themes, (theme, themeName) => [
|
||||
themeName === 'default' ? 'body, .theme-default' : `.theme-${e(themeName)}`,
|
||||
_.fromPairs(_.flatten(_.map(flattenColorPalette(_.fromPairs(_.flatten(_.map(normalizeTheme(theme), (palette, paletteName) => [
|
||||
[
|
||||
e(paletteName),
|
||||
palette,
|
||||
],
|
||||
[
|
||||
`on-${e(paletteName)}`,
|
||||
_.fromPairs(_.map(generateContrasts(palette), (color, hue) => [hue, _.get(theme, [`on-${paletteName}`, hue]) || color])),
|
||||
],
|
||||
]),
|
||||
))), (value, key) => [[`--fuse-${e(key)}`, value], [`--fuse-${e(key)}-rgb`, chroma(value).rgb().join(',')]]))),
|
||||
])),
|
||||
);
|
||||
/* Write the file if the map has been changed */
|
||||
if (data !== sassMap) {
|
||||
try {
|
||||
fs.writeFileSync(filename, sassMap, { encoding: 'utf8' });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate scheme based css custom properties and utility classes
|
||||
*/
|
||||
const schemeCustomProps = _.map(['light', 'dark'], (colorScheme) =>
|
||||
{
|
||||
const isDark = colorScheme === 'dark';
|
||||
const background = theme(`fuse.customProps.background.${colorScheme}`);
|
||||
const foreground = theme(`fuse.customProps.foreground.${colorScheme}`);
|
||||
const lightSchemeSelectors = 'body.light, .light, .dark .light';
|
||||
const darkSchemeSelectors = 'body.dark, .dark, .light .dark';
|
||||
/**
|
||||
* Iterate through the user's themes and build Tailwind components containing
|
||||
* CSS Custom Properties using the colors from them. This allows switching
|
||||
* themes by simply replacing a class name as well as nesting them.
|
||||
*/
|
||||
addComponents(
|
||||
_.fromPairs(
|
||||
_.map(options.themes, (theme, themeName) => [
|
||||
themeName === 'default'
|
||||
? 'body, .theme-default'
|
||||
: `.theme-${e(themeName)}`,
|
||||
_.fromPairs(
|
||||
_.flatten(
|
||||
_.map(
|
||||
flattenColorPalette(
|
||||
_.fromPairs(
|
||||
_.flatten(
|
||||
_.map(
|
||||
normalizeTheme(theme),
|
||||
(palette, paletteName) => [
|
||||
[
|
||||
e(paletteName),
|
||||
palette,
|
||||
],
|
||||
[
|
||||
`on-${e(paletteName)}`,
|
||||
_.fromPairs(
|
||||
_.map(
|
||||
generateContrasts(
|
||||
palette
|
||||
),
|
||||
(
|
||||
color,
|
||||
hue
|
||||
) => [
|
||||
hue,
|
||||
_.get(
|
||||
theme,
|
||||
[
|
||||
`on-${paletteName}`,
|
||||
hue,
|
||||
]
|
||||
) ||
|
||||
color,
|
||||
]
|
||||
)
|
||||
),
|
||||
],
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
(value, key) => [
|
||||
[`--fuse-${e(key)}`, value],
|
||||
[
|
||||
`--fuse-${e(key)}-rgb`,
|
||||
chroma(value).rgb().join(','),
|
||||
],
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
])
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
[(isDark ? darkSchemeSelectors : lightSchemeSelectors)]: {
|
||||
/**
|
||||
* Generate scheme based css custom properties and utility classes
|
||||
*/
|
||||
const schemeCustomProps = _.map(
|
||||
['light', 'dark'],
|
||||
(colorScheme) => {
|
||||
const isDark = colorScheme === 'dark';
|
||||
const background = theme(
|
||||
`fuse.customProps.background.${colorScheme}`
|
||||
);
|
||||
const foreground = theme(
|
||||
`fuse.customProps.foreground.${colorScheme}`
|
||||
);
|
||||
const lightSchemeSelectors =
|
||||
'body.light, .light, .dark .light';
|
||||
const darkSchemeSelectors =
|
||||
'body.dark, .dark, .light .dark';
|
||||
|
||||
/**
|
||||
* If a custom property is not available, browsers will use
|
||||
* the fallback value. In this case, we want to use '--is-dark'
|
||||
* as the indicator of a dark theme so, we can use it like this:
|
||||
* background-color: var(--is-dark, red);
|
||||
*
|
||||
* If we set '--is-dark' as "true" on dark themes, the above rule
|
||||
* won't work because of the said "fallback value" logic. Therefore,
|
||||
* we set the '--is-dark' to "false" on light themes and not set it
|
||||
* at all on dark themes so that the fallback value can be used on
|
||||
* dark themes.
|
||||
*
|
||||
* On light themes, since '--is-dark' exists, the above rule will be
|
||||
* interpolated as:
|
||||
* "background-color: false"
|
||||
*
|
||||
* On dark themes, since '--is-dark' doesn't exist, the fallback value
|
||||
* will be used ('red' in this case) and the rule will be interpolated as:
|
||||
* "background-color: red"
|
||||
*
|
||||
* It's easier to understand and remember like this.
|
||||
*/
|
||||
...(!isDark ? {'--is-dark': 'false'} : {}),
|
||||
return {
|
||||
[isDark ? darkSchemeSelectors : lightSchemeSelectors]: {
|
||||
/**
|
||||
* If a custom property is not available, browsers will use
|
||||
* the fallback value. In this case, we want to use '--is-dark'
|
||||
* as the indicator of a dark theme so, we can use it like this:
|
||||
* background-color: var(--is-dark, red);
|
||||
*
|
||||
* If we set '--is-dark' as "true" on dark themes, the above rule
|
||||
* won't work because of the said "fallback value" logic. Therefore,
|
||||
* we set the '--is-dark' to "false" on light themes and not set it
|
||||
* at all on dark themes so that the fallback value can be used on
|
||||
* dark themes.
|
||||
*
|
||||
* On light themes, since '--is-dark' exists, the above rule will be
|
||||
* interpolated as:
|
||||
* "background-color: false"
|
||||
*
|
||||
* On dark themes, since '--is-dark' doesn't exist, the fallback value
|
||||
* will be used ('red' in this case) and the rule will be interpolated as:
|
||||
* "background-color: red"
|
||||
*
|
||||
* It's easier to understand and remember like this.
|
||||
*/
|
||||
...(!isDark ? { '--is-dark': 'false' } : {}),
|
||||
|
||||
/* Generate custom properties from customProps */
|
||||
..._.fromPairs(_.flatten(_.map(background, (value, key) => [[`--fuse-${e(key)}`, value], [`--fuse-${e(key)}-rgb`, chroma(value).rgb().join(',')]]))),
|
||||
..._.fromPairs(_.flatten(_.map(foreground, (value, key) => [[`--fuse-${e(key)}`, value], [`--fuse-${e(key)}-rgb`, chroma(value).rgb().join(',')]]))),
|
||||
},
|
||||
};
|
||||
});
|
||||
/* Generate custom properties from customProps */
|
||||
..._.fromPairs(
|
||||
_.flatten(
|
||||
_.map(background, (value, key) => [
|
||||
[`--fuse-${e(key)}`, value],
|
||||
[
|
||||
`--fuse-${e(key)}-rgb`,
|
||||
chroma(value).rgb().join(','),
|
||||
],
|
||||
])
|
||||
)
|
||||
),
|
||||
..._.fromPairs(
|
||||
_.flatten(
|
||||
_.map(foreground, (value, key) => [
|
||||
[`--fuse-${e(key)}`, value],
|
||||
[
|
||||
`--fuse-${e(key)}-rgb`,
|
||||
chroma(value).rgb().join(','),
|
||||
],
|
||||
])
|
||||
)
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const schemeUtilities = (() =>
|
||||
{
|
||||
/* Generate general styles & utilities */
|
||||
return {};
|
||||
})();
|
||||
const schemeUtilities = (() => {
|
||||
/* Generate general styles & utilities */
|
||||
return {};
|
||||
})();
|
||||
|
||||
addComponents(schemeCustomProps);
|
||||
addComponents(schemeUtilities);
|
||||
},
|
||||
(options) =>
|
||||
{
|
||||
addComponents(schemeCustomProps);
|
||||
addComponents(schemeUtilities);
|
||||
},
|
||||
(options) => {
|
||||
return {
|
||||
theme: {
|
||||
extend: {
|
||||
@ -209,58 +303,81 @@ const theming = plugin.withOptions((options) => ({
|
||||
* are generated for them; "bg-primary", "text-on-primary", "bg-accent-600" etc.
|
||||
* This will also allow using arbitrary values with them such as opacity and such.
|
||||
*/
|
||||
colors: _.fromPairs(_.flatten(_.map(_.keys(flattenColorPalette(normalizeTheme(options.themes.default))), (name) => [
|
||||
[name, `rgba(var(--fuse-${name}-rgb), <alpha-value>)`],
|
||||
[`on-${name}`, `rgba(var(--fuse-on-${name}-rgb), <alpha-value>)`],
|
||||
]))),
|
||||
colors: _.fromPairs(
|
||||
_.flatten(
|
||||
_.map(
|
||||
_.keys(
|
||||
flattenColorPalette(
|
||||
normalizeTheme(options.themes.default)
|
||||
)
|
||||
),
|
||||
(name) => [
|
||||
[
|
||||
name,
|
||||
`rgba(var(--fuse-${name}-rgb), <alpha-value>)`,
|
||||
],
|
||||
[
|
||||
`on-${name}`,
|
||||
`rgba(var(--fuse-on-${name}-rgb), <alpha-value>)`,
|
||||
],
|
||||
]
|
||||
)
|
||||
)
|
||||
),
|
||||
},
|
||||
fuse : {
|
||||
fuse: {
|
||||
customProps: {
|
||||
background: {
|
||||
light: {
|
||||
'bg-app-bar' : '#FFFFFF',
|
||||
'bg-card' : '#FFFFFF',
|
||||
'bg-default' : colors.slate[100],
|
||||
'bg-dialog' : '#FFFFFF',
|
||||
'bg-hover' : chroma(colors.slate[400]).alpha(0.12).css(),
|
||||
'bg-app-bar': '#FFFFFF',
|
||||
'bg-card': '#FFFFFF',
|
||||
'bg-default': colors.slate[100],
|
||||
'bg-dialog': '#FFFFFF',
|
||||
'bg-hover': chroma(colors.slate[400])
|
||||
.alpha(0.12)
|
||||
.css(),
|
||||
'bg-status-bar': colors.slate[300],
|
||||
},
|
||||
dark : {
|
||||
'bg-app-bar' : colors.slate[900],
|
||||
'bg-card' : colors.slate[800],
|
||||
'bg-default' : colors.slate[900],
|
||||
'bg-dialog' : colors.slate[800],
|
||||
'bg-hover' : 'rgba(255, 255, 255, 0.05)',
|
||||
dark: {
|
||||
'bg-app-bar': colors.slate[900],
|
||||
'bg-card': colors.slate[800],
|
||||
'bg-default': colors.slate[900],
|
||||
'bg-dialog': colors.slate[800],
|
||||
'bg-hover': 'rgba(255, 255, 255, 0.05)',
|
||||
'bg-status-bar': colors.slate[900],
|
||||
},
|
||||
},
|
||||
foreground: {
|
||||
light: {
|
||||
'text-default' : colors.slate[800],
|
||||
'text-default': colors.slate[800],
|
||||
'text-secondary': colors.slate[500],
|
||||
'text-hint' : colors.slate[400],
|
||||
'text-disabled' : colors.slate[400],
|
||||
'border' : colors.slate[200],
|
||||
'divider' : colors.slate[200],
|
||||
'icon' : colors.slate[500],
|
||||
'mat-icon' : colors.slate[500],
|
||||
'text-hint': colors.slate[400],
|
||||
'text-disabled': colors.slate[400],
|
||||
border: colors.slate[200],
|
||||
divider: colors.slate[200],
|
||||
icon: colors.slate[500],
|
||||
'mat-icon': colors.slate[500],
|
||||
},
|
||||
dark : {
|
||||
'text-default' : '#FFFFFF',
|
||||
dark: {
|
||||
'text-default': '#FFFFFF',
|
||||
'text-secondary': colors.slate[400],
|
||||
'text-hint' : colors.slate[500],
|
||||
'text-disabled' : colors.slate[600],
|
||||
'border' : chroma(colors.slate[100]).alpha(0.12).css(),
|
||||
'divider' : chroma(colors.slate[100]).alpha(0.12).css(),
|
||||
'icon' : colors.slate[400],
|
||||
'mat-icon' : colors.slate[400],
|
||||
'text-hint': colors.slate[500],
|
||||
'text-disabled': colors.slate[600],
|
||||
border: chroma(colors.slate[100])
|
||||
.alpha(0.12)
|
||||
.css(),
|
||||
divider: chroma(colors.slate[100])
|
||||
.alpha(0.12)
|
||||
.css(),
|
||||
icon: colors.slate[400],
|
||||
'mat-icon': colors.slate[400],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
module.exports = theming;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user