diff --git a/.env b/.env index 6ec6abb..d21397a 100644 --- a/.env +++ b/.env @@ -3,8 +3,8 @@ PORT=3000 REACT_APP_BASE_LAYOUT_CONFIG_KEY='metronic-react-demo1-8150' REACT_APP_API_URL=https://preview.keenthemes.com/metronic8/laravel/api REACT_APP_VERSION=v8.1.5 -REACT_APP_THEME_NAME=Metornic -REACT_APP_THEME_DEMO=demo1 +REACT_APP_THEME_NAME=WrenchBoard +REACT_APP_THEME_DEMO=dashboard REACT_APP_BOOTSTRAP_DOCS_LINK=https://getbootstrap.com/docs/5.0 REACT_APP_SASS_PATH=src/_metronic/assets/sass/core/components REACT_APP_SASS_VARIABLES_PATH=src/_metronic/assets/sass/core/components/_variables.scss diff --git a/docker-compose.yml b/docker-compose.yml index e3fb988..211f5a5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,12 @@ version: '3' services: - metronic-dash: + wrenchboard-dash: build: context: . dockerfile: docker/Dockerfile restart: unless-stopped ports: - - 3800:3000 + - 3811:3000 # - 3800:3011 extra_hosts: - backend.wrenchboard.api.live:10.10.33.15 @@ -17,5 +17,11 @@ services: - apigateway.wrenchboard.app.lotus.fluxtra.net:172.31.4.19 environment: - CHOKIDAR_USEPOLLING=true + # volumes: + # - ./:/app + # - /app/node_modules + tty: true + stdin_open: true + # working_dir: /app volumes: src: diff --git a/public/index.html b/public/index.html index 07fad54..49fad37 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,7 @@ - Metronic Theme | Keenthemes + WrenchBoard @@ -36,7 +36,7 @@
- Metronic logo + WrenchBoard Loading ...
diff --git a/src/_res/assets/sass/_init.scss b/src/_res/assets/sass/_init.scss new file mode 100644 index 0000000..7ac4710 --- /dev/null +++ b/src/_res/assets/sass/_init.scss @@ -0,0 +1,28 @@ +// +// Main init file of global bootstrap and theme functions, mixins, variables and config +// + + +// Custom functions & mixins +@import "./core/base/functions"; +@import "./core/base/mixins"; +@import "./core/components/mixins"; +@import "./core/vendors/plugins/mixins"; + +// Custom variables +@import "components/variables.custom"; +@import "./core/components/variables"; + +// Bootstrap initializaton +@import "~bootstrap/scss/functions"; +@import "~bootstrap/scss/variables"; +@import "~bootstrap/scss/maps"; +@import "~bootstrap/scss/mixins"; +@import "~bootstrap/scss/utilities"; + +// 3rd-Party plugins variables +@import "./core/vendors/plugins/variables"; + +// Custom layout variables +@import "./core/layout/base/variables"; +@import "layout/variables.custom"; \ No newline at end of file diff --git a/src/_res/assets/sass/components/_landing.scss b/src/_res/assets/sass/components/_landing.scss new file mode 100644 index 0000000..34f3024 --- /dev/null +++ b/src/_res/assets/sass/components/_landing.scss @@ -0,0 +1,136 @@ +// +// Landing elements +// + +// Variables +$landing-dark-color: #13263C; +$landing-header-height: 100px; +$landing-header-height-tablet-and-mobile: 70px; +$landing-header-sticky-height: 70px; +$landing-header-sticky-height-tablet-and-mobile: 70px; + +// Utility classes +.landing-dark-bg { + background-color: $landing-dark-color; +} + +.landing-dark-color { + color: $landing-dark-color; +} + +.landing-dark-border { + border:1px dashed #2C3F5B; +} + +.landing-dark-separator { + border-top:1px dashed #2C3F5B; +} + +.landing-curve { + position: relative; + + svg { + position: relative; + top: 0; + display: block; + } +} + +// Landing header +.landing-header { + display: flex; + align-items: center; + height: $landing-header-height; + + // Logos + .logo-default { + display: block; + } + + .logo-sticky { + display: none; + } + + // Menu + .menu { + // Menu link + .menu-link { + &.active { + color: $white; + } + } + + // Header menu sticky mode + [data-kt-sticky-landing-header="on"] & { + // Menu link + .menu-link { + &.active { + color: $primary; + background-color: rgba(#EFF2F5, 0.4); + } + } + } + } + + // Sticky header modes + [data-kt-sticky-landing-header="on"] & { + padding: 0; + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 100; + background-color: $white; + box-shadow: 0px 10px 30px 0px rgba(82,63,105,0.05); + height: $landing-header-sticky-height; + + // Logos + .logo-sticky { + display: block; + } + + .logo-default { + display: none; + } + } +} + +// Fix body padding top when Landing sticky header is on +body[data-kt-sticky-landing-header="on"] { + padding-top: $landing-header-height; +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Landing header + .landing-header { + height: $landing-header-height-tablet-and-mobile; + + // Menu wrapper + .landing-menu-wrapper { + position: relative; + overflow: auto; + } + + // Sticky header modes + [data-kt-sticky-landing-header="on"] & { + height: $landing-header-sticky-height-tablet-and-mobile; + } + + // Menu + .menu { + // Menu link + .menu-link { + &.active { + color: $primary; + background-color: rgba(#EFF2F5, 0.4); + } + } + } + } + + // Fix body padding top when Landing sticky header is on + body[data-kt-sticky-landing-header="on"] { + padding-top: $landing-header-height-tablet-and-mobile; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/components/_variables.custom.scss b/src/_res/assets/sass/components/_variables.custom.scss new file mode 100644 index 0000000..ae87b9f --- /dev/null +++ b/src/_res/assets/sass/components/_variables.custom.scss @@ -0,0 +1,44 @@ +// +// To make future updates easier consider overriding the global variables from _variables.bootstrap.scss and _variables.custom.scss for current demo in this file. +// Note that this file is included first and variables defined in _variables.bootstrap.scss and _variables.custom.scss +// are not accessible in this file but you can override any global variable as shown below: +// + +// Bootstrap color system +$white: #ffffff; + +// Theme colors +// Primary +$primary: #009ef7; +$primary-active: #0095e8; +$primary-light: #f1faff; +$primary-light-dark: #212e48; +$primary-inverse: $white; + +// Success +$success: #50cd89; +$success-active: #47be7d; +$success-light: #e8fff3; +$success-light-dark: #1c3238; +$success-inverse: $white; + +// Info +$info: #7239ea; +$info-active: #5014d0; +$info-light: #f8f5ff; +$info-light-dark: #2f264f; +$info-inverse: $white; + +// Danger +$danger: #f1416c; +$danger-active: #d9214e; +$danger-light: #fff5f8; +$danger-light-dark: #3a2434; +$danger-inverse: $white; + +// Warning +$warning: #ffc700; +$warning-active: #f1bc00; +$warning-light: #fff8dd; +$warning-light-dark: #392f28; +$warning-inverse: $white; \ No newline at end of file diff --git a/src/_res/assets/sass/components/components.scss b/src/_res/assets/sass/components/components.scss new file mode 100644 index 0000000..aaed781 --- /dev/null +++ b/src/_res/assets/sass/components/components.scss @@ -0,0 +1,7 @@ +// +// Components +// + +// Import Dependencies +@import "stepper/multistep"; +@import "landing"; diff --git a/src/_res/assets/sass/components/stepper/_multistep.scss b/src/_res/assets/sass/components/stepper/_multistep.scss new file mode 100644 index 0000000..0861c78 --- /dev/null +++ b/src/_res/assets/sass/components/stepper/_multistep.scss @@ -0,0 +1,42 @@ +// +// Multistep stepper +// + +// Custom +.stepper.stepper-pills.stepper-multistep { + --kt-stepper-pills-size: 46px; + --kt-stepper-icon-border-radius: 9px; + --kt-stepper-icon-check-size: 1.25rem; + + --kt-stepper-icon-bg-color: rgba(255, 255, 255, 0.03); + --kt-stepper-icon-bg-color-current: var(--kt-success); + --kt-stepper-icon-bg-color-completed: rgba(255, 255, 255, 0.03); + + --kt-stepper-icon-border: 1px dashed rgba(255, 255, 255, 0.3); + --kt-stepper-icon-border-current: 0; + --kt-stepper-icon-border-completed: 1px dashed rgba(255, 255, 255, 0.3); + + --kt-stepper-icon-number-color: var(--kt-white); + --kt-stepper-icon-number-color-current: var(--kt-white); + --kt-stepper-icon-number-color-completed: var(--kt-white); + + --kt-stepper-icon-check-color-completed: var(--kt-success); + + --kt-stepper-label-title-opacity: 0.7; + --kt-stepper-label-title-opacity-current: 1; + --kt-stepper-label-title-opacity-completed: 1; + + --kt-stepper-label-title-color: var(--kt-white); + --kt-stepper-label-title-color-current: var(--kt-white); + --kt-stepper-label-title-color-completed: var(--kt-white); + + --kt-stepper-label-desc-opacity: 0.7; + --kt-stepper-label-desc-opacity-current: 0.7; + --kt-stepper-label-desc-opacity-completed: 0.7; + + --kt-stepper-label-desc-color: var(--kt-white); + --kt-stepper-label-desc-color-current: var(--kt-white); + --kt-stepper-label-desc-color-completed: var(--kt-white); + + --kt-stepper-line-border: 1px dashed rgba(255, 255, 255, 0.3); +} diff --git a/src/_res/assets/sass/core/base/_functions.scss b/src/_res/assets/sass/core/base/_functions.scss new file mode 100644 index 0000000..0551f4b --- /dev/null +++ b/src/_res/assets/sass/core/base/_functions.scss @@ -0,0 +1,10 @@ +// +// Functions +// + +// Import Dependencies +@import "functions/get"; +@import "functions/set"; +@import "functions/math"; +@import "functions/valueif"; +@import "functions/theme-colors"; diff --git a/src/_res/assets/sass/core/base/_mixins.scss b/src/_res/assets/sass/core/base/_mixins.scss new file mode 100644 index 0000000..93acae0 --- /dev/null +++ b/src/_res/assets/sass/core/base/_mixins.scss @@ -0,0 +1,11 @@ +// +// Mixins +// + +// Import Dependencies +@import "mixins/property"; +@import "mixins/browsers"; +@import "mixins/fixes"; +@import "mixins/reset"; +@import "mixins/placeholder"; +@import "mixins/breakpoints"; diff --git a/src/_res/assets/sass/core/base/functions/_get.scss b/src/_res/assets/sass/core/base/functions/_get.scss new file mode 100644 index 0000000..775e4a1 --- /dev/null +++ b/src/_res/assets/sass/core/base/functions/_get.scss @@ -0,0 +1,82 @@ +// +// Get +// + +@function get($map, $keys...) { + @if length($keys) == 1 { + $keys: nth($keys, 1); + } + + @if type-of($map) != 'map' or $map == null { + //@return false; + } + + $warn: "#{nth($keys, 1)}"; + $length: length($keys); + $get: map-get($map, nth($keys, 1)); + + @if $length > 1 { + @for $i from 2 through $length { + @if $get != null and type-of($get) == 'map' { + $warn: $warn + "->#{nth($keys, $i)}"; + $get: map-get($get, nth($keys, $i)); + + @if $get == null { + @return null; + } + } + @else { + @return get-warning($warn, $get, nth($keys, $i)); + } + } + } + + @return $get; +} + +@function has($map, $keys...) { + @if length($keys) == 1 { + $keys: nth($keys, 1); + } + + @if type-of($map) != 'map' or $map == null { + //@return false; + } + + $warn: "#{nth($keys, 1)}"; + $length: length($keys); + $get: map-get($map, nth($keys, 1)); + + @if $length > 1 { + @for $i from 2 through $length { + @if $get != null and type-of($get) == 'map' { + $warn: $warn + "->#{nth($keys, $i)}"; + $get: map-get($get, nth($keys, $i)); + + @if $get == null { + @return false; + } + } + @else { + @return false; + } + } + } + + @if $get != null { + @return true; + } + @else { + @return false; + } +} + +@function get-warning($warn, $get, $key) { + @if $get == null { + @warn "Map has no value for key search `#{$warn}`"; + } + @else if type-of($get) != 'map' { + @warn "Non-map value found for key search `#{$warn}`, cannot search for key `#{$key}`"; + } + @return null; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/base/functions/_math.scss b/src/_res/assets/sass/core/base/functions/_math.scss new file mode 100644 index 0000000..e5766ff --- /dev/null +++ b/src/_res/assets/sass/core/base/functions/_math.scss @@ -0,0 +1,15 @@ +// +// Math +// + +@function sqrt($r) { + $x0: 1; + $x1: $x0; + + @for $i from 1 through 10 { + $x1: $x0 - ($x0 * $x0 - abs($r)) / (2 * $x0); + $x0: $x1; + } + + @return $x1; +} diff --git a/src/_res/assets/sass/core/base/functions/_set.scss b/src/_res/assets/sass/core/base/functions/_set.scss new file mode 100644 index 0000000..91690a8 --- /dev/null +++ b/src/_res/assets/sass/core/base/functions/_set.scss @@ -0,0 +1,43 @@ +/// Deep set function to set a value in nested maps + +@function set($map, $keys, $value) { + $maps: ($map,); + $result: null; + + // If the last key is a map already + // Warn the user we will be overriding it with $value + @if type-of(nth($keys, -1)) == "map" { + @warn "The last key you specified is a map; it will be overrided with `#{$value}`."; + } + + // If $keys is a single key + // Just merge and return + @if length($keys) == 1 { + @return map-merge($map, ($keys: $value)); + } + + // Loop from the first to the second to last key from $keys + // Store the associated map to this key in the $maps list + // If the key doesn't exist, throw an error + @for $i from 1 through length($keys) - 1 { + $current-key: nth($keys, $i); + $current-map: nth($maps, -1); + $current-get: map-get($current-map, $current-key); + @if $current-get == null { + @error "Key `#{$key}` doesn't exist at current level in map."; + } + $maps: append($maps, $current-get); + } + + // Loop from the last map to the first one + // Merge it with the previous one + @for $i from length($maps) through 1 { + $current-map: nth($maps, $i); + $current-key: nth($keys, $i); + $current-val: if($i == length($maps), $value, $result); + $result: map-merge($current-map, ($current-key: $current-val)); + } + + // Return result + @return $result; +} diff --git a/src/_res/assets/sass/core/base/functions/_theme-colors.scss b/src/_res/assets/sass/core/base/functions/_theme-colors.scss new file mode 100644 index 0000000..6c9fd7f --- /dev/null +++ b/src/_res/assets/sass/core/base/functions/_theme-colors.scss @@ -0,0 +1,15 @@ +// +// Bootstrap extended functions +// + +@function theme-inverse-color($key: "primary") { + @return get($theme-inverse-colors, $key); +} + +@function theme-active-color($key: "primary") { + @return get($theme-active-colors, $key); +} + +@function theme-light-color($key: "primary") { + @return get($theme-light-colors, $key); +} diff --git a/src/_res/assets/sass/core/base/functions/_valueif.scss b/src/_res/assets/sass/core/base/functions/_valueif.scss new file mode 100644 index 0000000..ac3de28 --- /dev/null +++ b/src/_res/assets/sass/core/base/functions/_valueif.scss @@ -0,0 +1,13 @@ +// +// valueif +// + +@function valueif($check, $trueValue, $falseValue: null) { + @if $check { + @return $trueValue; + } @else if $falseValue != null { + @return $falseValue; + } @else { + @return null; + } +} diff --git a/src/_res/assets/sass/core/base/mixins/_breakpoints.scss b/src/_res/assets/sass/core/base/mixins/_breakpoints.scss new file mode 100644 index 0000000..d335b9a --- /dev/null +++ b/src/_res/assets/sass/core/base/mixins/_breakpoints.scss @@ -0,0 +1,25 @@ +// Media of at most the maximum and minimum breakpoint widths. No query for the largest breakpoint. +// Makes the @content apply to the given breakpoint. + +@mixin media-breakpoint-direction($direction, $name, $breakpoints: $grid-breakpoints) { + @if $direction == up { + $min: breakpoint-min($name, $breakpoints); + + @if $min { + @media (min-width: $min) { + @content; + } + } @else { + @content; + } + + } @else if $direction == down { + $max: breakpoint-max($name, $breakpoints); + + @if $max { + @media (max-width: $max) { + @content; + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/base/mixins/_browsers.scss b/src/_res/assets/sass/core/base/mixins/_browsers.scss new file mode 100644 index 0000000..123ac81 --- /dev/null +++ b/src/_res/assets/sass/core/base/mixins/_browsers.scss @@ -0,0 +1,10 @@ +// +// Browsers +// + +@mixin for-edge { + // Microsoft Edge + @supports (-ms-ime-align:auto) { + @content; + } +} diff --git a/src/_res/assets/sass/core/base/mixins/_fixes.scss b/src/_res/assets/sass/core/base/mixins/_fixes.scss new file mode 100644 index 0000000..5f07525 --- /dev/null +++ b/src/_res/assets/sass/core/base/mixins/_fixes.scss @@ -0,0 +1,15 @@ +// +// Fixes +// + + +@mixin fix-fixed-position-lags() { + // webkit hack for smooth font view on fixed positioned elements + -webkit-backface-visibility:hidden; + backface-visibility:hidden; +} + +@mixin fix-animation-lags() { + transform: translateZ(0); + -webkit-transform-style: preserve-3d; +} diff --git a/src/_res/assets/sass/core/base/mixins/_placeholder.scss b/src/_res/assets/sass/core/base/mixins/_placeholder.scss new file mode 100644 index 0000000..2119683 --- /dev/null +++ b/src/_res/assets/sass/core/base/mixins/_placeholder.scss @@ -0,0 +1,16 @@ +// +// Input placeholder color +// + +@mixin placeholder($color) { + // Chrome, Firefox, Opera, Safari 10.1+ + &::placeholder { + color: $color; + } + + // Firefox + &::-moz-placeholder { + color: $color; + opacity: 1; + } +} diff --git a/src/_res/assets/sass/core/base/mixins/_property.scss b/src/_res/assets/sass/core/base/mixins/_property.scss new file mode 100644 index 0000000..d93c3ec --- /dev/null +++ b/src/_res/assets/sass/core/base/mixins/_property.scss @@ -0,0 +1,9 @@ +// +// CSS Property +// + +@mixin property($attr, $value, $important: '') { + @if $value != null and $value != false { + #{$attr}: #{$value} #{$important}; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/base/mixins/_reset.scss b/src/_res/assets/sass/core/base/mixins/_reset.scss new file mode 100644 index 0000000..b796a6e --- /dev/null +++ b/src/_res/assets/sass/core/base/mixins/_reset.scss @@ -0,0 +1,23 @@ +// +// Reset +// + +@mixin button-reset() { + appearance: none; + box-shadow: none; + border-radius: 0; + border: none; + cursor: pointer; + background-color: transparent; + outline: none !important; + margin: 0; + padding: 0; +} + +@mixin input-reset() { + border: 0; + background-color: transparent; + outline: none !important; + box-shadow: none; + border-radius: 0; +} diff --git a/src/_res/assets/sass/core/components/_accordion.scss b/src/_res/assets/sass/core/components/_accordion.scss new file mode 100644 index 0000000..c65a239 --- /dev/null +++ b/src/_res/assets/sass/core/components/_accordion.scss @@ -0,0 +1,74 @@ +// +// Accordion +// + +// Base +.accordion { + --#{$prefix}accordion-color: var(--kt-accordion-color); + --#{$prefix}accordion-bg: var(--kt-accordion-bg); + --#{$prefix}accordion-border-color: var(--kt-accordion-border-color); + --#{$prefix}accordion-btn-color: var(--kt-accordion-color); + --#{$prefix}accordion-btn-bg: var(--kt-accordion-button-bg); + --#{$prefix}accordion-btn-icon: var(--kt-accordion-button-icon); + --#{$prefix}accordion-btn-active-icon: var(--kt-accordion-button-active-icon); + --#{$prefix}accordion-btn-focus-border-color: var(--kt-accordion-button-focus-border-color); + --#{$prefix}accordion-btn-focus-box-shadow: var(--kt-accordion-button-focus-box-shadow); + --#{$prefix}accordion-active-color: var(--kt-accordion-button-active-color); + --#{$prefix}accordion-active-bg: var(--kt-accordion-button-active-bg); + + // According heading + .accordion-header { + cursor: pointer; + } + + // Icon toggle mode + &.accordion-icon-toggle { + // Accordion icon expaned mode + .accordion-icon { + display: flex; + flex-shrink: 0; + transition: $transition-base; + transform: rotate(90deg); + align-items: center; + justify-content: center; + + i, + .svg-icon { + color: var(--kt-primary); + } + } + + // Accordion icon collapsed mode + .collapsed { + .accordion-icon { + transition: $transition-base; + transform: rotate(0); + + i, + .svg-icon { + color: var(--kt-text-muted); + } + } + } + } + + // Reset accordion item border + &.accordion-borderless { + // According item + .accordion-item { + border: 0; + } + } + + // Reset accordion item border, border radiues and background color + &.accordion-flush { + // According item + .accordion-item { + background-color: transparent; + border: 0; + border-radius: 0; + padding-left: 0; + padding-right: 0; + } + } +} diff --git a/src/_res/assets/sass/core/components/_alert.scss b/src/_res/assets/sass/core/components/_alert.scss new file mode 100644 index 0000000..8916c2b --- /dev/null +++ b/src/_res/assets/sass/core/components/_alert.scss @@ -0,0 +1,15 @@ +// +// Alert +// + +@each $name, $value in $theme-colors { + .alert-#{$name} { + color: var(--kt-#{$name}); + border-color: var(--kt-#{$name}); + background-color: var(--kt-#{$name}-light); + + .alert-link { + color: var(--kt-#{$name}); + } + } +} diff --git a/src/_res/assets/sass/core/components/_anchor.scss b/src/_res/assets/sass/core/components/_anchor.scss new file mode 100644 index 0000000..453d360 --- /dev/null +++ b/src/_res/assets/sass/core/components/_anchor.scss @@ -0,0 +1,37 @@ +// +// Anchor +// + +.anchor { + display: flex; + align-items: center; + + a { + position: relative; + display: none; + align-items: center; + justify-content:flex-start; + height: 1em; + width: 1.25em; + margin-left: -1.25em; + font-weight: 500; + font-size: 0.8em; + color: var(--kt-text-muted); + transition: $transition-base; + + &:before { + content: '#'; + } + } + + &:hover { + a { + display: flex; + + &:hover { + color: var(--kt-primary); + transition: $transition-base; + } + } + } +} diff --git a/src/_res/assets/sass/core/components/_animation.scss b/src/_res/assets/sass/core/components/_animation.scss new file mode 100644 index 0000000..c008782 --- /dev/null +++ b/src/_res/assets/sass/core/components/_animation.scss @@ -0,0 +1,81 @@ +// +// Animation +// + +// Base +.animation { + animation-duration: 1s; + animation-fill-mode: both; +} + +// Slide In Down +@keyframes animationSlideInDown { + from { + transform: translate3d(0, -100%, 0); + visibility: visible; + } + + to { + transform: translate3d(0, 0, 0); + } +} + +.animation-slide-in-down { + animation-name: animationSlideInDown; +} + +// Slide In Up +@keyframes animationSlideInUp { + from { + transform: translate3d(0, 100%, 0); + visibility: visible; + } + + to { + transform: translate3d(0, 0, 0); + } +} + +.animation-slide-in-up { + animation-name: animationSlideInUp; +} + +// Fade In +@keyframes animationFadeIn { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +.animation-fade-in { + animation-name: animationFadeIn; +} + +// Fade Out +@keyframes animationFadeOut { + from { + opacity: 1; + } + + to { + opacity: 0; + } +} +.animation-fade-out { + animation-name: animationFadeOut; +} + +// Blink +.animation-blink { + animation: animationBlink 1s steps(5, start) infinite; +} + +@keyframes animationBlink { + to { + visibility: hidden; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_badge.scss b/src/_res/assets/sass/core/components/_badge.scss new file mode 100644 index 0000000..03ccd66 --- /dev/null +++ b/src/_res/assets/sass/core/components/_badge.scss @@ -0,0 +1,77 @@ +// +// Badge +// + +.badge { + --#{$prefix}badge-color: var(--kt-badge-color); + + display: inline-flex; + align-items: center; + + // Fixed size + &.badge-circle, + &.badge-square { + display: inline-flex; + align-items: center; + justify-content: center; + height: $badge-size; + min-width: $badge-size; + padding: 0 0.1rem; + line-height: 0; + } + + // Circle + &.badge-circle { + border-radius: 50%; + padding: 0; + min-width: unset; + width: $badge-size; + } + + // Sizes + &.badge-sm { + min-width: $badge-size-sm; + font-size: $badge-font-size-sm; + + &.badge-square { + height: $badge-size-sm; + } + + &.badge-circle { + width: $badge-size-sm; + height: $badge-size-sm; + } + } + + &.badge-lg { + min-width: $badge-size-lg; + font-size: $badge-font-size-lg; + + &.badge-square { + height: $badge-size-lg; + } + + &.badge-circle { + width: $badge-size-lg; + height: $badge-size-lg; + } + } +} + +@each $name, $value in $theme-colors { + .badge-#{$name} { + color: var(--kt-#{$name}-inverse); + background-color: var(--kt-#{$name}); + + &.badge-outline { + border: 1px solid var(--kt-#{$name}); + color: var(--kt-#{$name}); + background-color: transparent; + } + } + + .badge-light-#{$name} { + color: var(--kt-#{$name}); + background-color: var(--kt-#{$name}-light); + } +} diff --git a/src/_res/assets/sass/core/components/_blockui.scss b/src/_res/assets/sass/core/components/_blockui.scss new file mode 100644 index 0000000..879ce91 --- /dev/null +++ b/src/_res/assets/sass/core/components/_blockui.scss @@ -0,0 +1,43 @@ +// +// BlockUI +// + + +.blockui { + position: relative; + + .blockui-overlay { + transition: all 0.3s ease; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + justify-content: center; + align-items: center; + background-color: var(--kt-blockui-overlay-bg); + + .spinner-border { + height: 1.35rem; + width: 1.35rem; + } + } + + .blockui-message { + display: flex; + align-items: center; + @include border-radius($border-radius); + box-shadow: var(--kt-dropdown-box-shadow); + background-color: var(--kt-tooltip-bg); + color: var(--kt-gray-700); + font-weight: $font-weight-bold; + margin: 0 !important; + width: auto; + padding: 0.85rem 1.75rem !important; + + .spinner-border { + margin-right: 0.65rem; + } + } +} diff --git a/src/_res/assets/sass/core/components/_breadcrumb.scss b/src/_res/assets/sass/core/components/_breadcrumb.scss new file mode 100644 index 0000000..e2f16f3 --- /dev/null +++ b/src/_res/assets/sass/core/components/_breadcrumb.scss @@ -0,0 +1,70 @@ +// +// Breadcrumb +// + +// Breadcrumb +.breadcrumb { + --#{$prefix}breadcrumb-bg: var(--kt-breadcrumb-bg); + --#{$prefix}breadcrumb-divider-color: var(--kt-breadcrumb-divider-color); + --#{$prefix}breadcrumb-item-active-color: var(--kt-breadcrumb-item-active-color); + + display: flex; + align-items: center; + background-color: transparent; + padding: 0; + margin: 0; + + // Item breadcrumb + .breadcrumb-item { + display: flex; + align-items: center; + padding-left: 0; + padding-right: $breadcrumb-item-padding-x; + + &:last-child { + padding-right: 0; + } + + &:after { + content: "/"; + //padding-left: $breadcrumb-item-padding-x; + } + + &:before { + display: none; + } + + &:last-child { + &:after { + display: none; + } + } + } +} + +// Breadcrumb line style +.breadcrumb-line { + .breadcrumb-item { + &:after { + content: "-"; + } + } +} + +// Breadcrumb dot style +.breadcrumb-dot { + .breadcrumb-item { + &:after { + content: "\2022"; + } + } +} + +// Breadcrumb separatorless style +.breadcrumb-separatorless { + .breadcrumb-item { + &:after { + display:none; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_bullet.scss b/src/_res/assets/sass/core/components/_bullet.scss new file mode 100644 index 0000000..57d4300 --- /dev/null +++ b/src/_res/assets/sass/core/components/_bullet.scss @@ -0,0 +1,33 @@ +// +// Bullet +// + +// Base +.bullet { + display: inline-block; + background-color: var(--kt-bullet-bg-color); + @include border-radius($bullet-bar-border-radius); + width: $bullet-bar-width; + height: $bullet-bar-height; + flex-shrink: 0; +} + +// Dot bullet +.bullet-dot { + width: $bullet-dot-size; + height: $bullet-dot-size; + border-radius: 100% !important; +} + +// Vertical bullet +.bullet-vertical { + width: $bullet-bar-height; + height: $bullet-bar-width; +} + +// Vertical line +.bullet-line { + width: $bullet-line-width; + height: $bullet-line-height; + border-radius: 0; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_button-group.scss b/src/_res/assets/sass/core/components/_button-group.scss new file mode 100644 index 0000000..f5dae70 --- /dev/null +++ b/src/_res/assets/sass/core/components/_button-group.scss @@ -0,0 +1,7 @@ + + +// The clickable button for toggling the menu +// Set the same inset shadow as the :active state +.btn-group.show .dropdown-toggle { + @include box-shadow(var(--kt-btn-active-box-shadow)); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_buttons.scss b/src/_res/assets/sass/core/components/_buttons.scss new file mode 100644 index 0000000..9ca3257 --- /dev/null +++ b/src/_res/assets/sass/core/components/_buttons.scss @@ -0,0 +1,7 @@ +// +// Buttons +// + +// Import Dependencies +@import "buttons/base"; +@import "buttons/theme"; diff --git a/src/_res/assets/sass/core/components/_card.scss b/src/_res/assets/sass/core/components/_card.scss new file mode 100644 index 0000000..1662e7e --- /dev/null +++ b/src/_res/assets/sass/core/components/_card.scss @@ -0,0 +1,291 @@ +// +// Card +// + +// Base +.card { + @if ($card-border-enabled) { + border: $card-border-width $card-border-style var(--kt-card-border-color); + } @else { + border: 0; + } + + box-shadow: var(--kt-card-box-shadow); + background-color: var(--kt-card-bg); + + // Header + .card-header { + display: flex; + justify-content: space-between; + align-items: stretch; + flex-wrap: wrap; + min-height: $card-header-height; + padding: 0 $card-px; + color: var(--kt-card-cap-color); + background-color: var(--kt-card-cap-bg); + border-bottom: $card-border-width $card-border-style var(--kt-card-border-color); + + // Title + .card-title { + display: flex; + align-items: center; + margin: $card-header-py; + margin-left: 0; + + &.flex-column { + align-items: flex-start; + justify-content: center; + } + + .card-icon { + margin-right: 0.75rem; + line-height: 0; + + i { + font-size: 1.25rem; + color: var(--kt-gray-600); + line-height: 0; + + &:after, + &:before { + line-height: 0; + } + } + + .svg-icon { + color: var(--kt-gray-600); + @include svg-icon-size(24px); + } + } + + &, + .card-label { + font-weight: 500; + font-size: 1.275rem; + color: var(--kt-text-dark); + } + + .card-label { + margin: 0 0.75rem 0 0; + flex-wrap: wrap; + } + + // Description + small { + color: var(--kt-text-muted); + font-size: 1rem; + } + + // Headings + h1, h2, h3, h4, h5, h6 { + margin-bottom: 0; + } + } + + // Toolbar + .card-toolbar { + display: flex; + align-items: center; + margin: $card-header-py 0; + flex-wrap: wrap; + } + } + + // Body + .card-body { + padding: $card-py $card-px; + color: var(--kt-card-color); + } + + // Footer + .card-footer { + padding: $card-py $card-px; + color: var(--kt-card-cap-color); + background-color: var(--kt-card-cap-bg); + border-top: $card-border-width $card-border-style var(--kt-card-border-color); + } + + // Scroll + .card-scroll { + position: relative; + overflow: auto; + } + + // Reset padding x + &.card-px-0 { + .card-header, + .card-body, + .card-footer { + padding-left: 0; + padding-right: 0; + } + } + + &.card-py-0 { + .card-header, + .card-body, + .card-footer { + padding-top: 0; + padding-bottom: 0; + } + } + + &.card-p-0 { + .card-header, + .card-body, + .card-footer { + padding: 0; + } + } + + // Dashed style + &.card-dashed { + box-shadow: none; + border: $card-border-width dashed var(--kt-card-border-dashed-color); + + > .card-header { + border-bottom: 1px dashed var(--kt-card-border-dashed-color); + } + + > .card-footer { + border-top: 1px dashed var(--kt-card-border-dashed-color); + } + } + + // Bordered style + &.card-bordered { + box-shadow: none; + border: $card-border-width $card-border-style var(--kt-card-border-color); + } + + // Flush header and footer borders + &.card-flush { + > .card-header { + border-bottom: 0 !important; + } + + > .card-footer { + border-top: 0 !important; + } + } + + // Enable shadow + &.card-shadow { + box-shadow: var(--kt-card-box-shadow); + border: 0; + } + + // Reset styles + &.card-reset { + border: 0 !important; + box-shadow: none !important; + background-color: transparent !important; + + > .card-header { + border-bottom: 0 !important; + } + + > .card-footer { + border-top: 0 !important; + } + } +} + +// Responsive stretch heights +.card { + @each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + // Stretch + &.card#{$infix}-stretch { + height: calc(100% - var(--bs-gutter-y)); + } + + // Stretch 75 + &.card#{$infix}-stretch-75 { + height: calc(75% - var(--bs-gutter-y)); + } + + // Stretch 50 + &.card#{$infix}-stretch-50 { + height: calc(50% - var(--bs-gutter-y)); + } + + // Stretch 33 + &.card#{$infix}-stretch-33 { + height: calc(33.333% - var(--bs-gutter-y)); + } + + // Stretch 25 + &.card#{$infix}-stretch-25 { + height: calc(25% - var(--bs-gutter-y)); + } + + // Header stretch + .card-header#{$infix}-stretch { + padding-top: 0 !important; + padding-bottom: 0 !important; + align-items: stretch; + + .card-toolbar { + margin: 0; + align-items: stretch; + } + } + } + } +} + +// Utilities +.card-p { + padding: $card-py $card-px !important; +} + +.card-px { + padding-left: $card-px !important; + padding-right: $card-px !important; +} + +.card-shadow { + box-shadow: var(--kt-card-box-shadow); +} + +.card-py { + padding-top: $card-py !important; + padding-bottom: $card-py !important; +} + +.card-rounded { + border-radius: $card-border-radius; +} + +.card-rounded-start { + border-top-left-radius: $card-border-radius; + border-bottom-left-radius: $card-border-radius; +} + +.card-rounded-end { + border-top-right-radius: $card-border-radius; + border-bottom-right-radius: $card-border-radius; +} + +.card-rounded-top { + border-top-left-radius: $card-border-radius; + border-top-right-radius: $card-border-radius; +} + +.card-rounded-bottom { + border-bottom-left-radius: $card-border-radius; + border-bottom-right-radius: $card-border-radius; +} + +// Mobile mode +@include media-breakpoint-down(md) { + .card { + > .card-header:not(.flex-nowrap) { + padding-top: $card-header-py; + padding-bottom: $card-header-py; + } + } +} diff --git a/src/_res/assets/sass/core/components/_carousel.scss b/src/_res/assets/sass/core/components/_carousel.scss new file mode 100644 index 0000000..a4b5beb --- /dev/null +++ b/src/_res/assets/sass/core/components/_carousel.scss @@ -0,0 +1,130 @@ +// +// Carousel +// + + +.carousel-custom { + // Indicators + .carousel-indicators { + align-items: center; + position: static; + z-index: auto; + margin: 0; + padding: 0; + list-style: none; + + li { + transform: none; + opacity: 1; + + &.active { + transform: none; + opacity: 1; + } + } + + // Dots style + &.carousel-indicators-dots { + li { + border-radius: 0; + background-color: transparent; + height: $carousel-custom-dots-indicator-active-size; + width: $carousel-custom-dots-indicator-active-size; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + + &:after { + display: inline-block; + content: " "; + @include border-radius(50%); + transition: all $carousel-custom-indicator-transition-speed ease; + background-color: var(--kt-carousel-custom-indicator-default-bg-color); + height: $carousel-custom-dots-indicator-default-size; + width: $carousel-custom-dots-indicator-default-size; + } + + &.active { + background-color: transparent; + + &:after { + transition: all $carousel-custom-indicator-transition-speed ease; + height: $carousel-custom-dots-indicator-active-size; + width: $carousel-custom-dots-indicator-active-size; + background-color: var(--kt-carousel-custom-indicator-active-bg-color); + } + } + } + } + + // Bullet style + &.carousel-indicators-bullet { + li { + transition: all $carousel-custom-indicator-transition-speed ease; + background-color: transparent; + border-radius: $carousel-custom-bullet-indicator-default-size; + height: $carousel-custom-bullet-indicator-default-size; + width: $carousel-custom-bullet-indicator-default-size; + display: flex; + align-items: center; + justify-content: center; + text-align: center; + + &:after { + display: inline-block; + content: " "; + transition: all $carousel-custom-indicator-transition-speed ease; + background-color: var(--kt-carousel-custom-bullet-indicator-default-bg-color); + border-radius: $carousel-custom-bullet-indicator-default-size; + height: $carousel-custom-bullet-indicator-default-size; + width: $carousel-custom-bullet-indicator-default-size; + } + + &.active { + transition: all $carousel-custom-indicator-transition-speed ease; + background-color: transparent; + height: $carousel-custom-bullet-indicator-default-size; + width: $carousel-custom-bullet-indicator-active-width; + + &:after { + transition: all $carousel-custom-indicator-transition-speed ease; + height: $carousel-custom-bullet-indicator-default-size; + width: $carousel-custom-bullet-indicator-active-width; + background-color: var(--kt-carousel-custom-bullet-indicator-active-bg-color); + } + } + } + } + } + + // Theme colors + @each $name, $value in $theme-colors { + .carousel-indicators-active-#{$name} { + li.active:after { + background-color: $value !important; + } + } + } + + // Stretch mode + &.carousel-stretch { + height: 100%; + display: flex; + flex-direction: column; + + .carousel-inner { + flex-grow: 1; + } + + .carousel-item { + height: 100%; + } + + .carousel-wrapper { + display: flex; + flex-direction: column; + height: 100%; + } + } +} diff --git a/src/_res/assets/sass/core/components/_close.scss b/src/_res/assets/sass/core/components/_close.scss new file mode 100644 index 0000000..6c3e529 --- /dev/null +++ b/src/_res/assets/sass/core/components/_close.scss @@ -0,0 +1,14 @@ +// +// Close +// + +.btn-close { + color: var(--kt-btn-close-color); + background-image: var(--kt-btn-close-bg); + background-position: center; + + + &:hover { + color: var(--kt-btn-close-color); + } +} diff --git a/src/_res/assets/sass/core/components/_code.scss b/src/_res/assets/sass/core/components/_code.scss new file mode 100644 index 0000000..b01d5a2 --- /dev/null +++ b/src/_res/assets/sass/core/components/_code.scss @@ -0,0 +1,15 @@ +// +// Code +// + +code:not([class*="language-"]) { + font-weight: $code-font-weight; + color: var(--kt-code-color); + line-height: inherit; + font-size: inherit; + background-color: var(--kt-code-bg); + padding: $code-padding; + margin: $code-margin; + box-shadow: var(--kt-code-box-shadow); + @include border-radius($code-border-radius); +} diff --git a/src/_res/assets/sass/core/components/_cookiealert.scss b/src/_res/assets/sass/core/components/_cookiealert.scss new file mode 100644 index 0000000..539756e --- /dev/null +++ b/src/_res/assets/sass/core/components/_cookiealert.scss @@ -0,0 +1,8 @@ +// +// Cookie Alert +// + +.cookiealert{ + background: inherit; + color: inherit; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_drawer.scss b/src/_res/assets/sass/core/components/_drawer.scss new file mode 100644 index 0000000..bfb97b8 --- /dev/null +++ b/src/_res/assets/sass/core/components/_drawer.scss @@ -0,0 +1,62 @@ +// +// Drawer +// + +// Drawer +.drawer { + display: flex !important; + overflow: auto; + z-index: $drawer-z-index; + position: fixed; + top: 0; + bottom: 0; + background-color: var(--kt-drawer-bg-color); + transition: transform $drawer-transition-speed ease-in-out !important; + + &.drawer-start { + left: 0; + transform: translateX(-100%); + } + + &.drawer-end { + right: 0; + transform: translateX(100%); + } + + &.drawer-on { + transform: none; + box-shadow: var(--kt-drawer-box-shadow); + transition: transform $drawer-transition-speed ease-in-out !important; + } +} + +// Drawer Overlay +.drawer-overlay { + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + overflow: hidden; + z-index: $drawer-z-index - 1; + background-color: var(--kt-drawer-overlay-bg-color); + animation: animation-drawer-fade-in $drawer-overlay-animation-speed ease-in-out 1; +} + +// Initial state +[data-kt-drawer="true"] { + display: none; +} + +// Animation +@keyframes animation-drawer-fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +// Tablet & Mobile Modes +@include media-breakpoint-down(lg) { + body[data-kt-drawer="on"] { + overflow: hidden; + } +} diff --git a/src/_res/assets/sass/core/components/_dropdown.scss b/src/_res/assets/sass/core/components/_dropdown.scss new file mode 100644 index 0000000..0b307d8 --- /dev/null +++ b/src/_res/assets/sass/core/components/_dropdown.scss @@ -0,0 +1,16 @@ + +// The dropdown menu +.dropdown-menu { + --#{$prefix}dropdown-color: var(--kt-dropdown-color); + --#{$prefix}dropdown-bg: var(--kt-dropdown-bg); + --#{$prefix}dropdown-border-color: var(--kt-dropdown-border-color); + --#{$prefix}dropdown-divider-bg: var(--kt-dropdown-divider-bg); + --#{$prefix}dropdown-box-shadow: var(--kt-dropdown-box-shadow); + --#{$prefix}dropdown-link-color: var(--kt-dropdown-link-color); + --#{$prefix}dropdown-link-hover-color: var(--kt-dropdown-link-hover-color); + --#{$prefix}dropdown-link-hover-bg: var(--kt-dropdown-link-hover-bg); + --#{$prefix}dropdown-link-active-color: var(--kt-dropdown-link-active-color); + --#{$prefix}dropdown-link-active-bg: var(--kt-dropdown-link-active-bg); + --#{$prefix}dropdown-link-disabled-color: var(--kt-dropdown-link-disabled-color); + --#{$prefix}dropdown-header-color: var(--kt-dropdown-header-color); +} diff --git a/src/_res/assets/sass/core/components/_engage.scss b/src/_res/assets/sass/core/components/_engage.scss new file mode 100644 index 0000000..a0290dc --- /dev/null +++ b/src/_res/assets/sass/core/components/_engage.scss @@ -0,0 +1,20 @@ +// +// Engage panel(used for demo product demo) +// + +.engage-btn { + display: flex; + align-items: center; + height: 35px !important; + + @include button-custom-variant( + $color: var(--kt-engage-btn-color), + $icon-color: var(--kt-engage-btn-color), + $border-color: var(--kt-engage-btn-bg), + $bg-color: var(--kt-engage-btn-bg), + $color-active: var(--kt-engage-btn-color-active), + $icon-color-active: var(--kt-engage-btn-color-active), + $border-color-active: var(--kt-engage-btn-bg), + $bg-color-active: var(--kt-engage-btn-bg) + ); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_explore.scss b/src/_res/assets/sass/core/components/_explore.scss new file mode 100644 index 0000000..049ff4c --- /dev/null +++ b/src/_res/assets/sass/core/components/_explore.scss @@ -0,0 +1,104 @@ +// +// Explore(used for demo product demo) +// + +$explore-primary: #00B2FF; +$explore-primary-light: #F1FAFF; +$explore-primary-active: #0098DA; +$explore-primary-inverse: $white; + +$explore-success: #50CD89; +$explore-success-light: #E8FFF3; +$explore-success-active: #47BE7D; +$explore-success-inverse: $white; + +$explore-warning: #FFC700; +$explore-warning-inverse: $white; + +$explore-danger: #F1416C; +$explore-warning-inverse: $white; + +.explore-btn-toggle { + color: var(--kt-gray-600); + background-color: $white; + + &:hover, + &:focus, + &:active { + color: $explore-primary-inverse; + background-color: $explore-primary; + } +} + +.explore-btn-dismiss { + border: 0; + + &:hover { + i, + .svg-icon { + color: $explore-primary; + } + } +} + +.explore-btn-primary { + border: 0; + color: $explore-primary-inverse; + background-color: $explore-primary; + + &:hover { + color: $explore-primary-inverse; + background-color: $explore-primary-active; + } +} + +.explore-btn-secondary { + border: 0; + color: var(--kt-gray-600); + background-color: var(--kt-gray-100); + + &:hover { + color: var(--kt-gray-800); + background-color: var(--kt-gray-200); + } +} + +.explore-btn-outline { + border: 1px dashed var(--kt-gray-300) !important; + + &:hover, + &.active { + border: 1px dashed $explore-success !important; + background-color: $explore-success-light; + } +} + +.explore-link { + color: $explore-primary; + + &:hover { + color: $explore-primary-active; + } +} + +.explore-link-hover:hover { + color: $explore-primary !important; +} + +.explore-icon-success { + color: $explore-success; +} + +.explore-icon-danger { + color: $explore-danger; +} + +.explore-label-free { + color: $explore-warning-inverse; + background-color: $explore-warning; +} + +.explore-label-pro { + color: $explore-success-inverse; + background-color: $explore-success; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_feedback.scss b/src/_res/assets/sass/core/components/_feedback.scss new file mode 100644 index 0000000..5b2844f --- /dev/null +++ b/src/_res/assets/sass/core/components/_feedback.scss @@ -0,0 +1,34 @@ +// +// Loading +// + +.feedback { + display: none; +} + +.feedback-popup { + display: flex; + justify-content: center; + margin: 0 auto; + position: fixed; + z-index: $feedback-popup-z-index; + box-shadow: var(--kt-feedback-popup-box-shadow); + background-color: var(--kt-feedback-popup-background-color); + border-radius: $feedback-popup-border-radius; + padding: $feedback-popup-padding; +} + +// Placement +.feedback-top-center { + display: flex; + transition: top $feedback-popup-transition-speed ease; + left: 50%; + transform: translateX(-50%); + @include border-top-start-radius(0); + @include border-top-end-radius(0); + + &.feedback-shown { + top: 0px; + transition: top $feedback-popup-transition-speed ease; + } +} diff --git a/src/_res/assets/sass/core/components/_fixed.scss b/src/_res/assets/sass/core/components/_fixed.scss new file mode 100644 index 0000000..c4935c4 --- /dev/null +++ b/src/_res/assets/sass/core/components/_fixed.scss @@ -0,0 +1,18 @@ +// +// Fixed +// + +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .fixed-top#{$infix} { + position: fixed; + z-index: $fixed-z-index; + top: 0; + left: 0; + right: 0; + } + } +} + diff --git a/src/_res/assets/sass/core/components/_forms.scss b/src/_res/assets/sass/core/components/_forms.scss new file mode 100644 index 0000000..7e5f3ae --- /dev/null +++ b/src/_res/assets/sass/core/components/_forms.scss @@ -0,0 +1,19 @@ +// +// Forms +// + +// Import Dependencies +@import "forms/labels"; +@import "forms/form-text"; +@import "forms/form-control"; +@import "forms/form-select"; +@import "forms/form-check"; +@import "forms/floating-labels"; +@import "forms/input-group"; + +@import "forms/form-control-solid"; +@import "forms/form-select-solid"; +@import "forms/form-check-solid"; +@import "forms/input-group-solid"; +@import "forms/floating-labels"; +@import "forms/required"; diff --git a/src/_res/assets/sass/core/components/_helpers.scss b/src/_res/assets/sass/core/components/_helpers.scss new file mode 100644 index 0000000..803a272 --- /dev/null +++ b/src/_res/assets/sass/core/components/_helpers.scss @@ -0,0 +1,12 @@ +// +// Helpers +// + +// Import Dependencies +@import "helpers/background"; +@import "helpers/borders"; +@import "helpers/flex"; +@import "helpers/shadow"; +@import "helpers/text"; +@import "helpers/opacity"; +@import "helpers/transform"; diff --git a/src/_res/assets/sass/core/components/_hover.scss b/src/_res/assets/sass/core/components/_hover.scss new file mode 100644 index 0000000..66650db --- /dev/null +++ b/src/_res/assets/sass/core/components/_hover.scss @@ -0,0 +1,48 @@ +// +// Hover effects +// + +.hover-elevate-up { + transition: transform 0.3s ease; + + &:hover { + transform: translateY(-5%); + transition: transform 0.3s ease; + } +} + +.hover-elevate-down { + transition: transform 0.3s ease; + + &:hover { + transform: translateY(5%); + transition: transform 0.3s ease; + } +} + +.hover-scale { + transition: transform 0.3s ease; + + &:hover { + transform: scale(1.1); + transition: transform 0.3s ease; + } +} + +.hover-rotate-end { + transition: transform 0.3s ease; + + &:hover { + transform: rotate(4deg); + transition: transform 0.3s ease; + } +} + +.hover-rotate-start { + transition: transform 0.3s ease; + + &:hover { + transform: rotate(-4deg); + transition: transform 0.3s ease; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_image-input.scss b/src/_res/assets/sass/core/components/_image-input.scss new file mode 100644 index 0000000..c08f0ae --- /dev/null +++ b/src/_res/assets/sass/core/components/_image-input.scss @@ -0,0 +1,111 @@ +// +// Avatar +// + + +// Base +.image-input { + position: relative; + display: inline-block; + @include border-radius($border-radius); + background-repeat: no-repeat; + background-size: cover; + + // Empty state + &:not(.image-input-empty) { + background-image: none !important; + } + + // Wrapper + .image-input-wrapper { + width: 120px; + height: 120px; + @include border-radius($border-radius); + background-repeat: no-repeat; + background-size: cover; + } + + // Actions + [data-kt-image-input-action] { + cursor: pointer; + position: absolute; + transform: translate(-50%,-50%); + } + + // Change Button + [data-kt-image-input-action="change"] { + left: 100%; + top: 0; + + input { + width: 0 !important; + height: 0 !important; + overflow: hidden; + opacity: 0; + } + } + + // Cancel & Remove Buttons + [data-kt-image-input-action="cancel"], + [data-kt-image-input-action="remove"] { + position: absolute; + left: 100%; + top: 100%; + } + + [data-kt-image-input-action="cancel"] { + display: none; + } + + // Input Changed State + &.image-input-changed { + [data-kt-image-input-action="cancel"] { + display: flex; + } + + [data-kt-image-input-action="remove"] { + display: none; + } + } + + // Input Empty State + &.image-input-empty { + [data-kt-image-input-action="remove"], + [data-kt-image-input-action="cancel"] { + display: none; + } + } + + // Circle style + &.image-input-circle { + border-radius: 50%; + + // Wrapper + .image-input-wrapper { + border-radius: 50%; + } + + // Change Control + [data-kt-image-input-action="change"] { + left: 100%; + top: 0; + transform: translate(-100%, 0%); + } + + // Cancel & Remove Buttons + [data-kt-image-input-action="cancel"], + [data-kt-image-input-action="remove"] { + left: 100%; + top: 100%; + transform: translate(-100%,-100%); + } + } + + // Bordered style + &.image-input-outline { + .image-input-wrapper { + border: 3px solid var(--kt-body-bg); + box-shadow: var(--kt-box-shadow); + } + } +} diff --git a/src/_res/assets/sass/core/components/_images.scss b/src/_res/assets/sass/core/components/_images.scss new file mode 100644 index 0000000..b0317f8 --- /dev/null +++ b/src/_res/assets/sass/core/components/_images.scss @@ -0,0 +1,12 @@ + + +// Image thumbnails +.img-thumbnail { + background-color: var(--kt-thumbnail-bg); + border: $thumbnail-border-width solid var(--kt-thumbnail-border-color); + @include box-shadow(var(--kt-thumbnail-box-shadow)); +} + +.figure-caption { + color: var(--kt-figure-caption-color); +} diff --git a/src/_res/assets/sass/core/components/_indicator.scss b/src/_res/assets/sass/core/components/_indicator.scss new file mode 100644 index 0000000..d74a923 --- /dev/null +++ b/src/_res/assets/sass/core/components/_indicator.scss @@ -0,0 +1,17 @@ +// +// Indicator +// + +.indicator-progress { + display: none; + + [data-kt-indicator="on"] > & { + display: inline-block; + } +} + +.indicator-label { + [data-kt-indicator="on"] > & { + display: none; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_list-group.scss b/src/_res/assets/sass/core/components/_list-group.scss new file mode 100644 index 0000000..5562fbd --- /dev/null +++ b/src/_res/assets/sass/core/components/_list-group.scss @@ -0,0 +1,19 @@ +// +// List group +// + +.list-group { + --#{$prefix}list-group-color: var(--kt-list-group-color); + --#{$prefix}list-group-bg: var(--kt-list-group-bg); + --#{$prefix}list-group-border-color: var(--kt-list-group-border-color); + --#{$prefix}list-group-action-color: var(--kt-list-group-action-color); + --#{$prefix}list-group-action-hover-color: var(--kt-list-group-action-hover-color); + --#{$prefix}list-group-action-hover-bg: var(--kt-list-group-hover-bg); + --#{$prefix}list-group-action-active-color: var(--kt-list-group-action-active-color); + --#{$prefix}list-group-action-active-bg: var(--kt-list-group-action-active-bg); + --#{$prefix}list-group-disabled-color: var(--kt-list-group-disabled-color); + --#{$prefix}list-group-disabled-bg: var(--kt-list-group-disabled-bg); + --#{$prefix}list-group-active-color: var(--kt-list-group-active-color); + --#{$prefix}list-group-active-bg: var(--kt-list-group-active-bg); + --#{$prefix}list-group-active-border-color: var(--kt-list-group-active-border-color); +} diff --git a/src/_res/assets/sass/core/components/_menu.scss b/src/_res/assets/sass/core/components/_menu.scss new file mode 100644 index 0000000..8564e7c --- /dev/null +++ b/src/_res/assets/sass/core/components/_menu.scss @@ -0,0 +1,7 @@ +// +// Menu +// + +// Import Dependencies +@import "menu/base"; +@import "menu/theme"; diff --git a/src/_res/assets/sass/core/components/_mixins.scss b/src/_res/assets/sass/core/components/_mixins.scss new file mode 100644 index 0000000..522cbf0 --- /dev/null +++ b/src/_res/assets/sass/core/components/_mixins.scss @@ -0,0 +1,16 @@ +// +// Mixins +// + +// Import Dependencies +@import "mixins/theme-mode"; +@import "mixins/menu"; +@import "mixins/tooltip"; +@import "mixins/popover"; +@import "mixins/buttons"; +@import "mixins/ki"; +@import "mixins/symbol"; +@import "mixins/svg-icon"; +@import "mixins/svg-bg-icon"; +@import "mixins/scroll"; +@import "mixins/shape"; diff --git a/src/_res/assets/sass/core/components/_modal.scss b/src/_res/assets/sass/core/components/_modal.scss new file mode 100644 index 0000000..547fcb5 --- /dev/null +++ b/src/_res/assets/sass/core/components/_modal.scss @@ -0,0 +1,65 @@ +// +// Modal +// + +.modal { + --#{$prefix}modal-color: var(--kt-modal-content-color); + --#{$prefix}modal-bg: var(--kt-modal-content-bg); + --#{$prefix}modal-border-color: var(--kt-modal-content-border-color); + --#{$prefix}modal-box-shadow: var(--kt-modal-content-box-shadow-xs); + --#{$prefix}modal-header-border-color: var(--kt-modal-header-border-color); + --#{$prefix}modal-footer-bg: var(--kt-modal-footer-bg); + --#{$prefix}modal-footer-border-color: var(--kt-modal-footer-border-color); +} + + // Mobile dialog +.modal-dialog { + outline: none !important; +} + +// Modal header +.modal-header { + align-items: center; + justify-content: space-between; + @include border-top-radius($modal-content-border-radius); + border-bottom: $modal-header-border-width solid var(--kt-modal-header-border-color); + + // Headings + h1,h2,h3,h4,h5,h6 { + margin-bottom: 0; + } +} + +// Modal content +.modal-content { + color: var(--kt-modal-color); + background-color: var(--kt-modal-bg); + border: $modal-content-border-width solid var(--kt-modal-border-color); + @include box-shadow(var(--kt-modal-box-shadow)); +} + +// Modal footer +.modal-footer { + background-color: var(--kt-modal-footer-bg); + border-top: $modal-footer-border-width solid var(--#{$prefix}modal-footer-border-color); +} + +// Modal background +.modal-backdrop { + --#{$prefix}backdrop-bg: var(--kt-modal-backdrop-bg); + --#{$prefix}backdrop-opacity: var(--kt-modal-backdrop-opacity); +} + +// Scale up the modal +@include media-breakpoint-up(sm) { + .modal-content { + @include box-shadow(var(--kt-modal-box-shadow-sm-up)); + } +} + +// Utilities +.modal-rounded { + @if $enable-rounded { + border-radius: $modal-content-border-radius !important; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_nav-line-tabs.scss b/src/_res/assets/sass/core/components/_nav-line-tabs.scss new file mode 100644 index 0000000..e821c67 --- /dev/null +++ b/src/_res/assets/sass/core/components/_nav-line-tabs.scss @@ -0,0 +1,68 @@ +// +// Nav +// + +// Line tabs +.nav-line-tabs { + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: var(--kt-border-color); + + .nav-item { + margin-bottom: -1px; + + // Base link + .nav-link { + color: var(--kt-gray-500); + border: 0; + border-bottom: 1px solid transparent; + transition: $transition-link; + padding: 0.5rem 0; + margin: 0 1rem; + } + + // First Item + &:first-child { + .nav-link { + margin-left: 0; + } + } + + // Last Item + &:last-child { + .nav-link { + margin-right: 0; + } + } + } + + // Active & Hover States + .nav-item .nav-link.active, + .nav-item.show .nav-link, + .nav-item .nav-link:hover:not(.disabled) { + background-color: transparent; + border: 0; + border-bottom: 1px solid var(--kt-primary); + transition: $transition-link; + } + + // 2x Line + &.nav-line-tabs-2x { + border-bottom-width: 2px; + + .nav-item { + margin-bottom: -2px; + + .nav-link { + border-bottom-width: 2px; + } + } + + // Active & Hover States + .nav-item .nav-link.active, + .nav-item.show .nav-link, + .nav-item .nav-link:hover:not(.disabled) { + border-bottom-width: 2px; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_nav-pills-custom.scss b/src/_res/assets/sass/core/components/_nav-pills-custom.scss new file mode 100644 index 0000000..f9821f5 --- /dev/null +++ b/src/_res/assets/sass/core/components/_nav-pills-custom.scss @@ -0,0 +1,91 @@ +// +// Custom Nav Pills +// + +.nav.nav-pills.nav-pills-custom { + // States + .show > .nav-link, + .nav-link{ + border: 1px dashed var(--kt-border-dashed-color); + @include border-radius($border-radius-lg); + + &.nav-link-border-solid { + border: 3px solid var(--kt-border-dashed-color); + + &.active { + border: 3px solid var(--kt-primary); + } + } + + .nav-icon { + img { + width: 30px; + transition: $transition-link; + + &.default { + display: inline-block; + } + + &.active { + display: none; + } + } + } + + &.active { + background-color: transparent; + border: 1px solid var(--kt-border-dashed-color); + transition-duration: 1ms; + position: relative; + + .nav-text { + color: var(--kt-gray-800) !important; + transition: $transition-link; + } + + .bullet-custom { + display: block; + } + } + + .bullet-custom { + display: none; + } + } + + &.nav-pills-active-custom { + .nav-item { + .nav-link { + &:not(:active) { + span:nth-child(1) { + color: #B5B5C3; + } + + span:nth-child(2) { + color: #3F4254; + } + } + + &:hover { + span:nth-child(1) { + color: $white !important; + } + + span:nth-child(2) { + color: $white !important; + } + } + + &.active { + span:nth-child(1) { + color: $white !important; + } + + span:nth-child(2) { + color: $white !important; + } + } + } + } + } +} diff --git a/src/_res/assets/sass/core/components/_nav.scss b/src/_res/assets/sass/core/components/_nav.scss new file mode 100644 index 0000000..5a0fe51 --- /dev/null +++ b/src/_res/assets/sass/core/components/_nav.scss @@ -0,0 +1,93 @@ +// +// Nav +// + +// Basic +.nav { + --#{$prefix}nav-link-color: var(--kt-nav-link-color); + --#{$prefix}nav-link-hover-color: var(--kt-nav-link-hover-color); + --#{$prefix}nav-link-disabled-color: var(--kt-nav-link-disabled-color); +} + +// Tabs +.nav-tabs { + --#{$prefix}nav-tabs-border-color: var(--kt-nav-tabs-border-color); + --#{$prefix}nav-tabs-link-hover-border-color: var(--kt-nav-tabs-link-hover-border-color); + --#{$prefix}nav-tabs-link-active-color: var(--kt-nav-tabs-link-active-color); + --#{$prefix}nav-tabs-link-active-bg: var(--kt-nav-tabs-link-active-bg); + --#{$prefix}nav-tabs-link-active-border-color: var(--kt-nav-tabs-link-active-border-color); +} + +// Pills +.nav-pills { + --#{$prefix}nav-pills-link-active-color: var(--kt-nav-pills-link-active-color); + --#{$prefix}nav-pills-link-active-bg: var(--kt-nav-pills-link-active-bg); +} + +// Nav pills +.nav-pills { + .nav-item { + margin-right: 0.5rem; + + &:last-child { + margin-right: 0; + } + } +} + +// Stretch items +.nav-stretch { + align-items: stretch; + padding-top: 0 !important; + padding-bottom: 0 !important; + + .nav-item { + display: flex; + align-items: stretch; + padding-top: 0 !important; + padding-bottom: 0 !important; + } + + .nav-link { + display: flex; + align-items: center; + } +} + +// Nav group +.nav-group { + padding: 0.35rem; + @include border-radius($border-radius); + background-color: var(--kt-gray-100); + + // Outline nav group + &.nav-group-outline { + background-color: transparent; + border: 1px solid var(--kt-border-color); + } + + // Fluid option + &.nav-group-fluid { + display: flex; + + > label, + > .btn { + position: relative; + flex-shrink: 0; + flex-grow: 1; + flex-basis: 0; + } + + > label { + margin-right: 0.1rem; + + > .btn { + width: 100%; + } + + &:last-child { + margin-right: 0; + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_offcanvas.scss b/src/_res/assets/sass/core/components/_offcanvas.scss new file mode 100644 index 0000000..1da1c90 --- /dev/null +++ b/src/_res/assets/sass/core/components/_offcanvas.scss @@ -0,0 +1,6 @@ +%offcanvas-css-vars { + --#{$prefix}offcanvas-color: var(--kt-offcanvas-color); + --#{$prefix}offcanvas-bg: var(--kt-offcanvas-bg-color); + --#{$prefix}offcanvas-border-color: var(--kt-offcanvas-border-color); + --#{$prefix}offcanvas-box-shadow: var(--kt-offcanvas-box-shadow); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_overlay.scss b/src/_res/assets/sass/core/components/_overlay.scss new file mode 100644 index 0000000..75ffa69 --- /dev/null +++ b/src/_res/assets/sass/core/components/_overlay.scss @@ -0,0 +1,35 @@ +// +// Demo +// + + +.overlay { + position: relative; + + .overlay-layer { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + justify-content: center; + align-items: center; + background-color: var(--kt-overlay-bg); + transition: all 0.3s ease; + opacity: 0; + } + + &.overlay-show, + &.overlay-block, + &:hover { + .overlay-layer { + transition: all 0.3s ease; + opacity: 1; + } + } + + &.overlay-block { + cursor: wait; + } +} diff --git a/src/_res/assets/sass/core/components/_page-loader.scss b/src/_res/assets/sass/core/components/_page-loader.scss new file mode 100644 index 0000000..5497dd8 --- /dev/null +++ b/src/_res/assets/sass/core/components/_page-loader.scss @@ -0,0 +1,28 @@ +// +// Page loader(used by the previous layout system) +// + +// CSS3 Transitions only after page load(.page-loading class added to body tag and remove with JS on page load) +[data-kt-app-page-loading="on"] *, +.page-loading * { + transition: none !important; +} + +// Base +.page-loader { + background: var(--kt-body-bg); + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 1000; + display: none; + + [data-kt-app-page-loading="on"] &, + .page-loading & { + display: flex; + justify-content: center; + align-items: center; + } +} diff --git a/src/_res/assets/sass/core/components/_pagination.scss b/src/_res/assets/sass/core/components/_pagination.scss new file mode 100644 index 0000000..7aa3538 --- /dev/null +++ b/src/_res/assets/sass/core/components/_pagination.scss @@ -0,0 +1,193 @@ +// +// Pagination +// + +.pagination { + --#{$prefix}pagination-color: var(--kt-pagination-color); + --#{$prefix}pagination-bg: var(--kt-pagination-bg); + --#{$prefix}pagination-border-color: var(--kt-pagination-border-color); + --#{$prefix}pagination-hover-color: var(--kt-pagination-hover-color); + --#{$prefix}pagination-hover-bg: var(--kt-pagination-hover-bg); + --#{$prefix}pagination-hover-border-color: var(--kt-pagination-hover-border-color); + --#{$prefix}pagination-focus-color: var(--kt-pagination-focus-color); + --#{$prefix}pagination-focus-bg: var(--kt-pagination-focus-bg); + --#{$prefix}pagination-focus-box-shadow: var(--kt-pagination-focus-box-shadow); + --#{$prefix}pagination-active-color: var(--kt-pagination-active-color); + --#{$prefix}pagination-active-bg: var(--kt-pagination-active-bg); + --#{$prefix}pagination-active-border-color: var(--kt-pagination-active-border-color); + --#{$prefix}pagination-disabled-color: var(--kt-pagination-disabled-color); + --#{$prefix}pagination-disabled-bg: var(--kt-pagination-disabled-bg); + --#{$prefix}pagination-disabled-border-color: var(--kt-pagination-disabled-border-color); + + display:flex; + flex-wrap: wrap; + justify-content: center; + margin: 0; + + // Pagination circle + &.pagination-circle { + .page-link { + border-radius: 50%; + } + } + + // Pagination outline + &.pagination-outline { + .page-link { + border: 1px solid var(--kt-border-color); + } + + .page-item { + &:hover:not(.disabled), + &.active { + .page-link { + border-color: var(--kt-primary-light); + } + } + } + } +} + +.page-item { + margin-right: $pagination-item-space; + + &:last-child { + margin-right: 0; + } + + .page-link { + display:flex; + justify-content: center; + align-items: center; + border-radius: $btn-border-radius; + height: $pagination-item-height; + min-width: $pagination-item-height; + font-weight: $pagination-font-weight; + font-size: $pagination-font-size; + + i { + font-size: $pagination-icon-font-size; + } + + /*rtl:options:{"autoRename":false}*/ + .previous, + .next { + display: block; + height: $pagination-icon-height; + width: $pagination-icon-height; + + /*rtl:raw:transform: rotateZ(-180deg);*/ + } + /*rtl:end:ignore*/ + + .previous { + @include svg-bg-icon(arrow-start, $pagination-color); + } + + /*rtl:options:{"autoRename":false}*/ + .next { + @include svg-bg-icon(arrow-end, $pagination-color); + } + } + + &:focus { + .page-link { + color: var(--kt-pagination-focus-color); + + .svg-icon, + i { + color: var(--kt-pagination-focus-color); + } + + .previous { + @include svg-bg-icon(arrow-start, var(--kt-pagination-focus-color)); + } + + /*rtl:options:{"autoRename":false}*/ + .next { + @include svg-bg-icon(arrow-end, var(--kt-pagination-focus-color)); + } + } + } + + &:hover:not(.active):not(.offset):not(.disabled) { + .page-link { + color: var(--kt-pagination-hover-color); + + &.page-text { + background-color: transparent; + } + + .svg-icon, + i { + color: var(--kt-pagination-hover-color); + } + + .previous { + @include svg-bg-icon(arrow-start, var(--kt-pagination-hover-color)); + } + + /*rtl:options:{"autoRename":false}*/ + .next { + @include svg-bg-icon(arrow-end, var(--kt-pagination-hover-color)); + } + } + } + + &.active { + .page-link { + color: var(--kt-pagination-active-color); + + &.page-text { + background-color: transparent; + } + + .svg-icon, + i { + color: var(--kt-pagination-active-color);; + } + + .previous { + @include svg-bg-icon(arrow-start, var(--kt-pagination-active-color)); + } + + /*rtl:options:{"autoRename":false}*/ + .next { + @include svg-bg-icon(arrow-end, var(--kt-pagination-active-color)); + } + } + } + + &.disabled { + .page-link { + color: var(--kt-pagination-disabled-color); + + .svg-icon, + i { + color: var(--kt-pagination-disabled-color); + } + + .previous { + @include svg-bg-icon(arrow-start, var(--kt-pagination-disabled-color)); + } + + /*rtl:options:{"autoRename":false}*/ + .next { + @include svg-bg-icon(arrow-end, var(--kt-pagination-disabled-color)); + } + } + } + /*rtl:end:ignore*/ +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .page-item { + margin-right: $pagination-item-space-tablet-and-mobile; + + &:last-child { + margin-right: 0; + } + } +} + diff --git a/src/_res/assets/sass/core/components/_popover.scss b/src/_res/assets/sass/core/components/_popover.scss new file mode 100644 index 0000000..c7de66e --- /dev/null +++ b/src/_res/assets/sass/core/components/_popover.scss @@ -0,0 +1,53 @@ +// +// Popover +// + + +// Base +.popover { + --#{$prefix}popover-bg: var(--kt-popover-bg); + --#{$prefix}popover-border-color: var(--kt-popover-border-color); + --#{$prefix}popover-box-shadow: var(--kt-popover-box-shadow); + --#{$prefix}popover-header-color: var(--kt-popover-header-color); + --#{$prefix}popover-header-bg: var(--kt-popover-header-bg); + --#{$prefix}popover-body-color: var(--kt-popover-body-color); + --#{$prefix}popover-arrow-border: var(--kt-popover-bg); + + .popover-header { + font-size: $popover-header-font-size; + font-weight: $popover-header-font-weight; + border-bottom: 1px solid var(--kt-popover-header-border-color); + } + + .popover-dismiss { + position: absolute; + top: $popover-dissmis-btn-top; + right: $popover-dissmis-btn-end; + height: $popover-dissmis-btn-height; + width: $popover-dissmis-btn-height; + @include svg-bg-icon(close, var(--kt-gray-500)); // todo: revise + mask-size: 50%; + -webkit-mask-size: 50%; + + &:hover { + background-color: var(--kt-primary); + } + + & + .popover-header { + padding-right: $popover-body-padding-x + $popover-dissmis-btn-height; + } + } +} + +// Inverse +.popover-inverse { + @include popover-theme( + $bg-color: var(--kt-gray-900), + $border-color: var(--kt-gray-800), + $header-bg-color: var(--kt-gray-900), + $header-color: var(--kt-gray-200), + $body-color: var(--kt-gray-400), + $arrow-outer-color: var(--kt-gray-100), + $arrow-color: var(--kt-gray-900) + ); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_print.scss b/src/_res/assets/sass/core/components/_print.scss new file mode 100644 index 0000000..ab7854b --- /dev/null +++ b/src/_res/assets/sass/core/components/_print.scss @@ -0,0 +1,34 @@ +// +// Print Mode +// + +// Add .print-content-only class to body element in order to allow printing only the content area +@media print { + .print-content-only { + padding: 0 !important; + background: none !important; + + .wrapper, + .page, + .page-title + .content, + .container, + .container-xxl, + .container-fluid { + background: none !important; + padding: 0 !important; + margin: 0 !important; + } + + .aside, + .sidebar, + .scrolltop, + .header, + .footer, + .toolbar, + .drawer, + .btn { + display: none !important; + } + } +} diff --git a/src/_res/assets/sass/core/components/_progress.scss b/src/_res/assets/sass/core/components/_progress.scss new file mode 100644 index 0000000..e085f1f --- /dev/null +++ b/src/_res/assets/sass/core/components/_progress.scss @@ -0,0 +1,35 @@ +// +// Progress +// + +// Base +.progress { + --#{$prefix}progress-bg: var(--kt-progress-bg); + --#{$prefix}progress-box-shadow: var(--kt-progress-box-shadow); + --#{$prefix}progress-bar-color: var(--kt-progress-bar-color); + --#{$prefix}progress-bar-bg: var(--kt-progress-bar-bg); +} + +// Vertical Position +.progress-vertical { + display: flex; + align-items: stretch; + justify-content: space-between; + + .progress { + height: 100%; + @include border-radius($border-radius); + display: flex; + align-items: flex-end; + margin-right: 1rem; + + &:last-child { + margin-right: 0; + } + + .progress-bar { + width: 8px; + @include border-radius($border-radius); + } + } +} diff --git a/src/_res/assets/sass/core/components/_pulse.scss b/src/_res/assets/sass/core/components/_pulse.scss new file mode 100644 index 0000000..24b612c --- /dev/null +++ b/src/_res/assets/sass/core/components/_pulse.scss @@ -0,0 +1,39 @@ +// +// Pulse +// + + +// Base +.pulse { + position: relative; + + // Theme Colors + @each $name, $color in $theme-colors { + &.pulse-#{$name} { + .pulse-ring { + border-color: $color; + } + } + } +} + +.pulse-ring { + display: block; + border-radius: 40px; + height: 40px; + width: 40px; + position: absolute; + animation: animation-pulse 3.5s ease-out; + animation-iteration-count: infinite; + opacity: 0; + border-width: 3px; + border-style: solid; + border-color: var(--kt-gray-500); +} + +@keyframes animation-pulse { + 0% {-webkit-transform: scale(0.1, 0.1); opacity: 0.0;} + 60% {-webkit-transform: scale(0.1, 0.1); opacity: 0.0;} + 65% {opacity: 1;} + 100% {-webkit-transform: scale(1.2, 1.2); opacity: 0.0;} +} diff --git a/src/_res/assets/sass/core/components/_rating.scss b/src/_res/assets/sass/core/components/_rating.scss new file mode 100644 index 0000000..b24eb76 --- /dev/null +++ b/src/_res/assets/sass/core/components/_rating.scss @@ -0,0 +1,62 @@ +// +// Rating +// + +.rating { + display: flex; + align-items: center; +} + +.rating-input { + position: absolute !important; + left: -9999px !important; + + &[disabled] { + display: none; + } +} + +.rating-label { + padding: 0; + margin: 0; + + & > i, + & > .svg-icon { + line-height: 1; + color: var(--kt-rating-color-default); + } +} + +label.rating-label { + cursor: pointer; +} + +div.rating-label.checked, +label.rating-label { + & > i, + & > .svg-icon { + color: var(--kt-rating-color-active); + } +} + +.rating-input:checked ~ .rating-label { + & > i, + & > .svg-icon { + color: var(--kt-rating-color-default); + } +} + +.rating:hover label.rating-label { + & > i, + & > .svg-icon { + color: var(--kt-rating-color-active); + } +} + +label.rating-label:hover ~ .rating-label { + & > i, + & > .svg-icon { + color: var(--kt-rating-color-default); + } + color: var(--kt-rating-color-default); +} diff --git a/src/_res/assets/sass/core/components/_reboot.scss b/src/_res/assets/sass/core/components/_reboot.scss new file mode 100644 index 0000000..9f94268 --- /dev/null +++ b/src/_res/assets/sass/core/components/_reboot.scss @@ -0,0 +1,8 @@ +// +// Reboot +// + +h1, h2, h3, h4, h5, h6 { + color: var(--kt-headings-color); + outline: 0; +} diff --git a/src/_res/assets/sass/core/components/_ribbon.scss b/src/_res/assets/sass/core/components/_ribbon.scss new file mode 100644 index 0000000..c9bf53a --- /dev/null +++ b/src/_res/assets/sass/core/components/_ribbon.scss @@ -0,0 +1,195 @@ +// +// Ribbon +// + +// Base +.ribbon { + position: relative; + + // Ribbon target + .ribbon-label { + display: flex; + justify-content: center; + align-items: center; + padding: 5px 10px; + position: absolute; + z-index: 1; + background-color: var(--kt-ribbon-label-bg); + box-shadow: var(--kt-ribbon-label-box-shadow); + color: var(--kt-primary-inverse); + top: 50%; + right: 0; + transform: translateX(5px) translateY(-50%); + + > .ribbon-inner { + z-index: -1; + position: absolute; + padding: 0; + width: 100%; + height: 100%; + top: 0; + left: 0; + } + + &:after { + border-color: var(--kt-ribbon-label-border-color); + } + } + + // Vertical aligment + &-vertical { + .ribbon-label { + padding: 5px 10px; + min-width: 36px; + min-height: 46px; + text-align: center; + } + } + + &.ribbon-top { + .ribbon-label { + top: 0; + transform: translateX(-15px) translateY(-4px); + border-bottom-right-radius: $border-radius; + border-bottom-left-radius: $border-radius; + } + } + + &.ribbon-bottom { + .ribbon-label { + border-top-right-radius: $border-radius; + border-top-left-radius: $border-radius; + } + } + + &.ribbon-start { + .ribbon-label { + top: 50%; + left: 0; + right: auto; + transform: translateX(-5px) translateY(-50%); + border-top-right-radius: $border-radius; + border-bottom-right-radius: $border-radius; + } + } + + &.ribbon-end { + .ribbon-label { + border-top-left-radius: $border-radius; + border-bottom-left-radius: $border-radius; + } + } +} + +// Clip style +.ribbon.ribbon-clip { + &.ribbon-start { + .ribbon-label { + left: -5px; + + .ribbon-inner { + border-top-right-radius: $border-radius; + border-bottom-right-radius: $border-radius; + + &:before, + &:after { + content: ""; + position: absolute; + border-style: solid; + border-color: transparent !important; + bottom: -10px; + } + + &:before { + border-width: 0 10px 10px 0; + border-right-color: var(--kt-ribbon-clip-bg) !important; + left: 0; + } + } + } + } + + &.ribbon-end { + .ribbon-label { + right: -5px; + + .ribbon-inner { + border-top-left-radius: $border-radius; + border-bottom-left-radius: $border-radius; + + &:before, + &:after { + content: ""; + position: absolute; + border-style: solid; + border-color: transparent !important; + bottom: -10px; + } + + &:before { + border-width: 0 0 10px 10px; + border-left-color: var(--kt-ribbon-clip-bg) !important; + right: 0; + } + } + } + } +} + +// Triangle style +.ribbon.ribbon-triangle { + position: absolute; + z-index: 1; + display: flex; + align-items: flex-start; + justify-content: flex-start; + + // Top start position + &.ribbon-top-start { + top: 0; + left: 0; + width: 4rem; + height: 4rem; + border-bottom: solid 2rem transparent !important; + border-left: solid 2rem transparent; + border-right: solid 2rem transparent !important; + border-top: solid 2rem transparent; + } + + // Top end position + &.ribbon-top-end { + top: 0; + right: 0; + width: 4rem; + height: 4rem; + border-bottom: solid 2rem transparent !important; + border-left: solid 2rem transparent !important; + border-right: solid 2rem transparent; + border-top: solid 2rem transparent; + } + + // Botton start position + &.ribbon-bottom-start { + bottom: 0; + left: 0; + width: 4rem; + height: 4rem; + border-bottom: solid 2rem transparent; + border-left: solid 2rem transparent; + border-right: solid 2rem transparent !important; + border-top: solid 2rem transparent !important; + } + + // Botton end position + &.ribbon-bottom-end { + bottom: 0; + right: 0; + width: 4rem; + height: 4rem; + border-bottom: solid 2rem transparent; + border-right: solid 2rem transparent; + border-left: solid 2rem transparent !important; + border-top: solid 2rem transparent !important; + } +} + diff --git a/src/_res/assets/sass/core/components/_root-bs.scss b/src/_res/assets/sass/core/components/_root-bs.scss new file mode 100644 index 0000000..eb43e43 --- /dev/null +++ b/src/_res/assets/sass/core/components/_root-bs.scss @@ -0,0 +1,27 @@ +// +// CSS Variables +// + +[data-theme="dark"] { + @each $color, $value in $grays-dark { + --#{$prefix}gray-#{$color}: #{$value}; + } + + @each $color, $value in $theme-colors-dark { + --#{$prefix}#{$color}: #{$value}; + } + + --#{$prefix}body-color-rgb: #{to-rgb($body-color-dark)}; + --#{$prefix}body-bg-rgb: #{to-rgb($body-bg-dark)}; + + --#{$prefix}body-color: #{$body-color-dark}; + --#{$prefix}body-bg: #{$body-bg-dark}; + + --#{$prefix}border-color: #{$border-color-dark}; + + --#{$prefix}heading-color: #{$headings-color-dark}; + --#{$prefix}link-color: #{$link-color-dark}; + --#{$prefix}link-hover-color: #{$link-hover-color-dark}; + + --#{$prefix}code-color: #{$code-color-dark}; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_root.scss b/src/_res/assets/sass/core/components/_root.scss new file mode 100644 index 0000000..a7d3b2a --- /dev/null +++ b/src/_res/assets/sass/core/components/_root.scss @@ -0,0 +1,868 @@ +// +// CSS Variables +// + +:root, +[data-theme="light"] { + // Breakpoints + @each $breakpoint, $value in $grid-breakpoints { + --kt-#{$breakpoint}:#{$value}; + } + + // Bootstrap color system + --kt-white: #{$white}; + --kt-white-bg-rgb: #{to-rgb($white)}; + --kt-black: #{$black}; + --kt-black-bg-rgb: #{to-rgb($black)}; + + // Bootstrap muted color + --kt-text-muted: #{$text-muted}; + + // Grey colors + @each $name, $value in $grays { + --kt-gray-#{$name}: #{$value}; + } + + // Grey rgba colors + @each $name, $value in $grays { + --kt-gray-#{$name}-rgb: #{to-rgb($value)}; + } + + // Contextual colors + @each $name, $value in $theme-colors { + --kt-#{$name}: #{$value}; + } + + // Contextual active state colors + @each $name, $value in $theme-active-colors { + --kt-#{$name}-active: #{$value}; + } + + // Contextual light state colors + @each $name, $value in $theme-light-colors { + --kt-#{$name}-light: #{$value}; + } + + // Contextual inverse state colors + @each $name, $value in $theme-inverse-colors { + --kt-#{$name}-inverse: #{$value}; + } + + // Contextual rbg colors + @each $name, $value in $theme-colors { + --kt-#{$name}-rgb: #{to-rgb($value)}; + } + + // Text colors + @each $name, $value in $theme-text-colors { + --kt-text-#{$name}: #{$value}; + } + + // Body + --kt-body-bg: #{$body-bg}; + --kt-body-bg-rgb: #{to-rgb($body-bg)}; + --kt-body-color: #{$body-color}; + + // Links + --kt-link-color: #{$link-color}; + --kt-link-hover-color: #{$link-hover-color}; + + // Components + --kt-border-color: #{$border-color}; + --kt-border-dashed-color: #{$border-dashed-color}; + + --kt-component-active-color: #{$component-active-color}; + --kt-component-active-bg: #{$component-active-bg}; + --kt-component-hover-color: #{$component-hover-color}; + --kt-component-hover-bg: #{$component-hover-bg}; + --kt-component-checked-color: #{$component-checked-color}; + --kt-component-checked-bg: #{$component-checked-bg}; + + // Box shadow + --kt-box-shadow-xs: #{$box-shadow-xs}; + --kt-box-shadow-sm: #{$box-shadow-sm}; + --kt-box-shadow: #{$box-shadow}; + --kt-box-shadow-lg: #{$box-shadow-lg}; + + // Typography + --kt-headings-color: #{$headings-color}; + + // Tables + --kt-table-color: #{$table-color}; + --kt-table-bg: #{$table-bg}; + --kt-table-striped-color: #{$table-striped-color}; + --kt-table-striped-bg: #{$table-striped-bg}; + --kt-table-accent-bg: #{$table-accent-bg}; + --kt-table-active-color: #{$table-active-color}; + --kt-table-active-bg: #{$table-active-bg}; + --kt-table-hover-colorr: #{$table-hover-color}; + --kt-table-hover-bg: #{$table-hover-bg}; + --kt-table-border-color: #{$table-border-color}; + --kt-table-caption-color: #{$table-caption-color}; + + --kt-table-loading-message-box-shadow: #{$table-loading-message-box-shadow}; + --kt-table-loading-message-bg: #{$table-loading-message-bg}; + --kt-table-loading-message-color: #{$table-loading-message-color}; + + // Buttons + Forms + --kt-input-btn-focus-color: #{$input-btn-focus-color}; + --kt-input-btn-focus-box-shadow: #{$input-btn-focus-box-shadow}; + --kt-input-btn-focus-color-opacity: #{$input-btn-focus-color-opacity}; + + --kt-input-color: #{$input-color}; + --kt-input-placeholder-color: #{$input-placeholder-color}; + --kt-input-plaintext-color: #{$input-plaintext-color}; + + // Buttons + --kt-btn-box-shadow: #{$btn-box-shadow}; + --kt-btn-focus-box-shadow: #{$btn-focus-box-shadow}; + --kt-btn-active-box-shadow: #{$btn-active-box-shadow}; + --kt-btn-disabled-opacity: #{$btn-disabled-opacity}; + + --kt-btn-link-color: #{$btn-link-color}; + --kt-btn-link-hover-color: #{$btn-link-hover-color}; + --kt-btn-link-disabled-color: #{$btn-link-disabled-color}; + + // Forms + --kt-form-label-color: #{$form-label-color}; + --kt-form-text-color: #{$form-text-color}; + + --kt-input-bg: #{$input-bg}; + --kt-input-disabled-bg: #{$input-disabled-bg}; + --kt-input-disabled-color: #{$input-disabled-color}; + --kt-input-disabled-border-color: #{$input-disabled-border-color}; + + --kt-input-color: #{$input-color}; + --kt-input-border-color: #{$input-border-color}; + + --kt-input-focus-bg: #{$input-focus-bg}; + --kt-input-focus-border-color: #{$input-focus-border-color}; + --kt-input-focus-color: #{$input-focus-color}; + + // Keenthemes solid input style + --kt-input-solid-bg: #{$input-solid-bg}; + --kt-input-solid-bg-focus: #{$input-solid-bg-focus}; + --kt-input-solid-placeholder-color: #{$input-solid-placeholder-color}; + --kt-input-solid-color: #{$input-solid-color}; + + // Form checks + --kt-form-check-label-color: #{$form-check-label-color}; + --kt-form-check-label-color-checked: #{$form-check-label-color-checked}; + --kt-form-check-input-active-filter: #{$form-check-input-active-filter}; + + --kt-form-check-input-bg: #{$form-check-input-bg}; + --kt-form-check-input-bg-solid: #{$form-check-input-bg-solid}; + --kt-form-check-input-border: #{$form-check-input-border}; + --kt-form-check-input-focus-border: #{$form-check-input-focus-border}; + --kt-form-check-input-focus-box-shadow: #{$form-check-input-focus-box-shadow}; + + --kt-form-check-input-checked-color: #{$form-check-input-checked-color}; + --kt-form-check-input-checked-bg-color: #{$form-check-input-checked-bg-color}; + --kt-form-check-input-checked-bg-color-solid: #{$form-check-input-checked-bg-color-solid}; + --kt-form-check-input-checked-border-color: #{$form-check-input-checked-border-color}; + --kt-form-check-input-checked-bg-image: #{escape-svg($form-check-input-checked-bg-image)}; + --kt-form-check-radio-checked-bg-image: #{escape-svg($form-check-radio-checked-bg-image)}; + + --kt-form-check-input-indeterminate-color: #{$form-check-input-indeterminate-color}; + --kt-form-check-input-indeterminate-bg-color: #{$form-check-input-indeterminate-bg-color}; + --kt-form-check-input-indeterminate-border-color: #{$form-check-input-indeterminate-border-color}; + --kt-form-check-input-indeterminate-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image)}; + + --kt-form-check-input-disabled-opacity: #{$form-check-input-disabled-opacity}; + --kt-form-check-label-disabled-opacity: #{$form-check-label-disabled-opacity}; + --kt-form-check-btn-check-disabled-opacity: #{$form-check-btn-check-disabled-opacity}; + + --kt-form-switch-color: #{$form-switch-color}; + --kt-form-switch-color-solid: #{$form-switch-color-solid}; + --kt-form-switch-bg-image: #{escape-svg($form-switch-bg-image)}; + --kt-form-switch-bg-image-solid: #{escape-svg($form-switch-bg-image-solid)}; + --kt-form-switch-focus-color: #{$form-switch-focus-color}; + --kt-form-switch-focus-bg-image: #{escape-svg($form-switch-focus-bg-image)}; + --kt-form-switch-checked-color: #{$form-switch-checked-color}; + --kt-form-switch-checked-bg-image: #{escape-svg($form-switch-checked-bg-image)}; + + // Input groups + --kt-input-group-addon-color: #{$input-group-addon-color}; + --kt-input-group-addon-bg: #{$input-group-addon-bg}; + --kt-input-group-addon-border-color: #{$input-group-addon-border-color}; + + // Form select + --kt-form-select-color: #{$form-select-color}; + --kt-form-select-bg: #{$form-select-bg}; + --kt-form-select-disabled-color: #{$form-select-disabled-color}; + --kt-form-select-disabled-bg: #{$form-select-disabled-bg}; + --kt-form-select-disabled-border-color: #{$form-select-disabled-border-color}; + --kt-form-select-indicator-color: #{$form-select-indicator-color}; + --kt-form-select-indicator: #{escape-svg($form-select-indicator)}; + --kt-form-select-border-color: #{$form-select-border-color}; + --kt-form-select-box-shadow: #{$form-select-box-shadow}; + --kt-form-select-focus-border-color: #{$form-select-focus-border-color}; + --kt-form-select-focus-box-shadow: #{$form-select-focus-box-shadow}; + + // Form file button + --kt-form-file-button-color: #{$form-file-button-color}; + --kt-form-file-button-bg: #{$form-file-button-bg}; + --kt-form-file-button-hover-bg: #{$form-file-button-hover-bg}; + + // Navs + --kt-nav-tabs-border-color: #{$nav-tabs-border-color}; + --kt-nav-tabs-link-hover-border-color: #{$nav-tabs-link-hover-border-color}; + --kt-nav-tabs-link-active-color: #{$nav-tabs-link-active-color}; + --kt-nav-tabs-link-active-bg: #{$nav-tabs-link-active-bg}; + --kt-nav-tabs-link-active-border-color: #{$nav-tabs-link-active-border-color}; + + --kt-nav-pills-link-active-color: #{$nav-pills-link-active-color}; + --kt-nav-pills-link-active-bg: #{$nav-pills-link-active-bg}; + + // Dropdowns + --kt-dropdown-color: #{$dropdown-color}; + --kt-dropdown-bg: #{$dropdown-bg}; + --kt-dropdown-divider-bg: #{$dropdown-divider-bg}; + --kt-dropdown-box-shadow: #{$dropdown-box-shadow}; + --kt-dropdown-link-color: #{$dropdown-link-color}; + --kt-dropdown-link-hover-color: #{$dropdown-link-hover-color}; + --kt-dropdown-link-hover-bg: #{$dropdown-link-hover-bg}; + --kt-dropdown-link-active-color: #{$dropdown-link-active-color}; + --kt-dropdown-link-active-bg: #{$dropdown-link-active-bg}; + --kt-dropdown-link-disabled-color: #{$dropdown-link-disabled-color}; + --kt-dropdown-header-color: #{$dropdown-header-color}; + + // Pagination + --kt-pagination-item-bg: #{$pagination-item-bg}; + --kt-pagination-color: #{$pagination-color}; + --kt-pagination-bg: #{$pagination-bg}; + --kt-pagination-border-color: #{$pagination-border-color}; + --kt-pagination-focus-color: #{$pagination-focus-color}; + --kt-pagination-focus-bg: #{$pagination-focus-bg}; + --kt-pagination-focus-box-shadow: #{$pagination-focus-box-shadow}; + --kt-pagination-focus-outline: #{$pagination-focus-outline}; + --kt-pagination-hover-color: #{$pagination-hover-color}; + --kt-pagination-hover-bg: #{$pagination-hover-bg}; + --kt-pagination-hover-border-color: #{$pagination-hover-border-color}; + --kt-pagination-active-color: #{$pagination-active-color}; + --kt-pagination-active-bg: #{$pagination-active-bg}; + --kt-pagination-active-border-color: #{$pagination-active-border-color}; + --kt-pagination-disabled-color: #{$pagination-disabled-color}; + --kt-pagination-disabled-bg: #{$pagination-disabled-bg}; + + // Card + --kt-card-color: #{$card-color-dark}; + --kt-card-bg: #{$card-bg}; + --kt-card-box-shadow: #{$card-box-shadow}; + --kt-card-border-color: #{$card-border-color}; + --kt-card-border-dashed-color: #{$card-border-dashed-color}; + --kt-card-cap-bg: #{$card-cap-bg}; + + // Accordion + --kt-accordion-color: #{$accordion-color}; + --kt-accordion-bg: #{$accordion-bg}; + --kt-accordion-border-color: #{$accordion-border-color}; + --kt-accordion-button-bg: #{$accordion-button-bg}; + --kt-accordion-button-color: #{$accordion-button-color}; + --kt-accordion-button-active-bg: #{$accordion-button-active-bg}; + --kt-accordion-button-active-color: #{$accordion-button-active-color}; + --kt-accordion-button-focus-border-color: #{$accordion-button-focus-border-color}; + --kt-accordion-button-focus-box-shadow: #{$accordion-button-focus-box-shadow}; + + --kt-accordion-icon-color: #{$accordion-icon-color}; + --kt-accordion-icon-active-color: #{$accordion-icon-active-color}; + --kt-accordion-button-icon: #{escape-svg($accordion-button-icon)}; + --kt-accordion-button-active-icon: #{escape-svg($accordion-button-active-icon)}; + + // Tooltips + --kt-tooltip-color: #{$tooltip-color}; + --kt-tooltip-bg: #{$tooltip-bg}; + --kt-tooltip-opacity: #{$tooltip-opacity}; + --kt-tooltip-box-shadow: #{$tooltip-box-shadow}; + + // Popovers + --kt-popover-bg: #{$popover-bg}; + --kt-popover-border-color: #{$popover-border-color}; + --kt-popover-box-shadow: #{$popover-box-shadow}; + --kt-popover-header-bg: #{$popover-header-bg}; + --kt-popover-header-color: #{$popover-header-color}; + --kt-popover-header-border-color: #{$popover-header-border-color}; + --kt-popover-body-color: #{$popover-body-color}; + + // Dropdowns + --kt-dropdown-box-shadow: #{$dropdown-box-shadow}; + --kt-dropdown-bg: #{$dropdown-bg}; + + // Toasts + --kt-toast-color: #{$toast-color}; + --kt-toast-background-color: #{$toast-background-color}; + --kt-toast-box-shadow: #{$toast-box-shadow}; + --kt-toast-header-color: #{$toast-header-color}; + --kt-toast-header-background-color: #{$toast-header-background-color}; + --kt-toast-header-border-color: #{$toast-header-border-color}; + + // Badges + --kt-badge-color: #{$badge-color}; + + // Modals + --kt-modal-bg: #{$modal-content-bg}; + --kt-modal-color: #{$modal-content-color}; + --kt-modal-border-color: #{$modal-content-border-color}; + --kt-modal-box-shadow: #{$modal-content-box-shadow}; + --kt-modal-content-color: #{$modal-content-color}; + --kt-modal-content-bg: #{$modal-content-bg}; + --kt-modal-content-border-color: #{$modal-content-border-color}; + --kt-modal-content-box-shadow: #{$modal-content-box-shadow}; + --kt-modal-content-box-shadow-xs: #{$modal-content-box-shadow-xs}; + --kt-modal-content-box-shadow-sm-up: #{$modal-content-box-shadow-sm-up}; + --kt-modal-header-border-color: #{$modal-header-border-color}; + --kt-modal-footer-border-color: #{$modal-footer-border-color}; + --kt-modal-backdrop-bg: #{$modal-backdrop-bg}; + --kt-modal-backdrop-opacity: #{$modal-backdrop-opacity}; + + // Progress bars + --kt-progress-bg: #{$progress-bg}; + --kt-progress-box-shadow: #{$progress-box-shadow}; + + // List group + --kt-list-group-color: #{$list-group-color}; + --kt-list-group-bg: #{$list-group-bg}; + --kt-list-group-border-color: #{$list-group-border-color}; + --kt-list-group-hover-bg: #{$list-group-hover-bg}; + --kt-list-group-active-color: #{$list-group-active-color}; + --kt-list-group-active-bg: #{$list-group-active-bg}; + --kt-list-group-active-border-colorg: #{$list-group-active-border-color}; + --kt-list-group-disabled-color: #{$list-group-disabled-color}; + --kt-list-group-disabled-bg: #{$list-group-disabled-bg}; + --kt-list-group-action-colorg: #{$list-group-action-color}; + --kt-list-group-action-hover-color: #{$list-group-action-hover-color}; + --kt-list-group-action-active-color: #{$list-group-action-active-color}; + --kt-list-group-action-active-bg: #{$list-group-action-active-bg}; + + // Image thumbnails + --kt-thumbnail-bg: #{$thumbnail-bg}; + --kt-thumbnail-border-color: #{$thumbnail-border-color}; + --kt-thumbnail-box-shadow: #{$thumbnail-box-shadow}; + + // Figures + --kt-figure-caption-color: #{$figure-caption-color}; + + // Breadcrumbs + --kt-breadcrumb-bg: #{$breadcrumb-bg}; + --kt-breadcrumb-divider-color: #{$breadcrumb-divider-color}; + --kt-breadcrumb-active-color: #{$breadcrumb-active-color}; + + // Carousel + --kt-carousel-custom-indicator-default-bg-color: #{$carousel-custom-indicator-default-bg-color}; + --kt-carousel-custom-indicator-active-bg-color: #{$carousel-custom-indicator-active-bg-color}; + --kt-carousel-custom-bullet-indicator-default-bg-color: #{$carousel-custom-bullet-indicator-default-bg-color}; + --kt-carousel-custom-bullet-indicator-active-bg-color: #{$carousel-custom-bullet-indicator-active-bg-color}; + + // Code + --kt-code-bg: #{$code-bg}; + --kt-code-box-shadow: #{$code-box-shadow}; + --kt-code-color: #{$code-color}; + + // Close + --kt-btn-close-color: #{$btn-close-color}; + --kt-btn-close-bg: #{escape-svg($btn-close-bg)}; + + // Offcanvas + --kt-offcanvas-border-color: #{$offcanvas-border-color}; + --kt-offcanvas-bg-color: #{$offcanvas-bg-color}; + --kt-offcanvas-color: #{$offcanvas-color}; + --kt-offcanvas-box-shadow: #{$offcanvas-box-shadow}; + --kt-offcanvas-backdrop-bg: #{$offcanvas-backdrop-bg}; + --kt-offcanvas-backdrop-opacity: #{$offcanvas-backdrop-opacity}; + + // Symbol + --kt-symbol-label-color: #{$symbol-label-color}; + --kt-symbol-label-bg: #{$symbol-label-bg}; + --kt-symbol-border-color: #{$symbol-border-color}; + + // Bullet + --kt-bullet-bg-color: #{$bullet-bg-color}; + + // Scrolltop + --kt-scrolltop-opacity: #{$scrolltop-opacity}; + --kt-scrolltop-opacity-on: #{$scrolltop-opacity-on}; + --kt-scrolltop-opacity-hover: #{$scrolltop-opacity-hover}; + --kt-scrolltop-box-shadow: #{$scrolltop-box-shadow}; + --kt-scrolltop-bg-color: #{$scrolltop-bg-color}; + --kt-scrolltop-bg-color-hover: #{$scrolltop-bg-color-hover}; + --kt-scrolltop-icon-color: #{$scrolltop-icon-color}; + --kt-scrolltop-icon-color-hover: #{$scrolltop-icon-color-hover}; + + // Keenthemes drawer component + --kt-drawer-box-shadow: #{$drawer-box-shadow}; + --kt-drawer-bg-color: #{$drawer-bg-color}; + --kt-drawer-overlay-bg-color: #{$drawer-overlay-bg-color}; + + // Keenthemes menu component + --kt-menu-dropdown-box-shadow: #{$menu-dropdown-box-shadow}; + --kt-menu-dropdown-bg-color: #{$menu-dropdown-bg-color}; + --kt-menu-heading-color: #{$menu-heading-color}; + --kt-menu-link-color-hover: #{$menu-link-color-hover}; + --kt-menu-link-color-show: #{$menu-link-color-show}; + --kt-menu-link-color-here: #{$menu-link-color-here}; + --kt-menu-link-color-active: #{$menu-link-color-active}; + --kt-menu-link-bg-color-hover: #{$menu-link-bg-color-hover}; + --kt-menu-link-bg-color-show: #{$menu-link-bg-color-show}; + --kt-menu-link-bg-color-here: #{$menu-link-bg-color-here}; + --kt-menu-link-bg-color-active: #{$menu-link-bg-color-active}; + + // Keenthemes feedback component + --kt-feedback-popup-box-shadow: #{$feedback-popup-box-shadow}; + --kt-feedback-popup-background-color: #{$feedback-popup-background-color}; + + // Keenthemes scrollbar component + --kt-scrollbar-color: #{$scrollbar-color}; + --kt-scrollbar-hover-color: #{$scrollbar-hover-color}; + --kt-scrollbar-width: #{$scrollbar-width}; + --kt-scrollbar-height: #{$scrollbar-height}; + --kt-scrollbar-space: #{$scrollbar-space}; + + // Keenthemes overlay component + --kt-overlay-bg: #{$overlay-bg}; + + // Keenthemes blockui component + --kt-blockui-overlay-bg: #{$blockui-overlay-bg}; + + // Keenthemes rating component + --kt-rating-color-default: #{$rating-color-default}; + --kt-rating-color-active: #{$rating-color-active}; + + // Keenthemes ribbon component + --kt-ribbon-label-box-shadow: #{$ribbon-label-box-shadow}; + --kt-ribbon-label-bg: #{$ribbon-label-bg}; + --kt-ribbon-label-border-color: #{$ribbon-label-border-color}; + --kt-ribbon-clip-bg: #{$ribbon-clip-bg}; + + // Engage panel + --kt-engage-btn-bg: #{$engage-btn-bg}; + --kt-engage-btn-color: #{$engage-btn-color}; + --kt-engage-btn-color-active: #{$engage-btn-color-active}; +} + +[data-theme="dark"] { + // Bootstrap muted color + --kt-text-muted: #{$text-muted-dark}; + + // Grey colors + @each $name, $value in $grays-dark { + --kt-gray-#{$name}: #{$value}; + } + + // Grey rgba colors + @each $name, $value in $grays-dark { + --kt-gray-#{$name}-rgb: #{to-rgb($value)}; + } + + // Contextual colors + @each $name, $value in $theme-colors-dark { + --kt-#{$name}: #{$value}; + } + + // Contextual active state colors + @each $name, $value in $theme-active-colors-dark { + --kt-#{$name}-active: #{$value}; + } + + // Contextual light state colors + @each $name, $value in $theme-light-colors-dark { + --kt-#{$name}-light: #{$value}; + } + + // Contextual inverse state colors + @each $name, $value in $theme-inverse-colors-dark { + --kt-#{$name}-inverse: #{$value}; + } + + // Contextual rbg colors + @each $name, $value in $theme-colors-dark { + --kt-#{$name}-rgb: #{to-rgb($value)}; + } + + // Text colors + @each $name, $value in $theme-text-colors-dark { + --kt-text-#{$name}: #{$value}; + } + + // Body + --kt-body-bg: #{$body-bg-dark}; + --kt-body-bg-rgb: #{to-rgb($body-bg-dark)}; + --kt-body-color: #{$body-color-dark}; + + // Links + --kt-link-color: #{$link-color-dark}; + --kt-link-hover-color: #{$link-hover-color-dark}; + + // Components + --kt-border-color: #{$border-color-dark}; + --kt-border-dashed-color: #{$border-dashed-color-dark}; + + --kt-component-active-color: #{$component-active-color-dark}; + --kt-component-active-bg: #{$component-active-bg-dark}; + --kt-component-hover-color: #{$component-hover-color-dark}; + --kt-component-hover-bg: #{$component-hover-bg-dark}; + --kt-component-checked-color: #{$component-checked-color-dark}; + --kt-component-checked-bg: #{$component-checked-bg-dark}; + + // Box shadow + --kt-box-shadow-xs: #{$box-shadow-xs-dark}; + --kt-box-shadow-sm: #{$box-shadow-sm-dark}; + --kt-box-shadow: #{$box-shadow-dark}; + --kt-box-shadow-lg: #{$box-shadow-lg-dark}; + + // Typography + --kt-headings-color: #{$headings-color-dark}; + + // Tables + --kt-table-color: #{$table-color-dark}; + --kt-table-bg: #{$table-bg-dark}; + --kt-table-striped-color: #{$table-striped-color-dark}; + --kt-table-striped-bg: #{$table-striped-bg-dark}; + --kt-table-accent-bg: #{$table-accent-bg-dark}; + --kt-table-active-color: #{$table-active-color-dark}; + --kt-table-active-bg: #{$table-active-bg-dark}; + --kt-table-hover-colorr: #{$table-hover-color-dark}; + --kt-table-hover-bg: #{$table-hover-bg-dark}; + --kt-table-border-color: #{$table-border-color-dark}; + --kt-table-caption-color: #{$table-caption-color-dark}; + + --kt-table-loading-message-box-shadow: #{$table-loading-message-box-shadow-dark}; + --kt-table-loading-message-bg: #{$table-loading-message-bg-dark}; + --kt-table-loading-message-color: #{$table-loading-message-color-dark}; + + // Buttons + Forms + --kt-input-btn-focus-color: #{$input-btn-focus-color-dark}; + --kt-input-btn-focus-box-shadow: #{$input-btn-focus-box-shadow-dark}; + --kt-input-btn-focus-color-opacity: #{$input-btn-focus-color-opacity-dark}; + + --kt-input-color: #{$input-color-dark}; + --kt-input-placeholder-color: #{$input-placeholder-color-dark}; + --kt-input-plaintext-color: #{$input-plaintext-color-dark}; + + // Buttons + --kt-btn-box-shadow: #{$btn-box-shadow-dark}; + --kt-btn-focus-box-shadow: #{$btn-focus-box-shadow-dark}; + --kt-btn-active-box-shadow: #{$btn-active-box-shadow-dark}; + --kt-btn-disabled-opacity: #{$btn-disabled-opacity-dark}; + + --kt-btn-link-color: #{$btn-link-color-dark}; + --kt-btn-link-hover-color: #{$btn-link-hover-color-dark}; + --kt-btn-link-disabled-color: #{$btn-link-disabled-color-dark}; + + // Forms + --kt-form-label-color: #{$form-label-color-dark}; + --kt-form-text-color: #{$form-text-color-dark}; + + --kt-input-bg: #{$input-bg-dark}; + --kt-input-disabled-bg: #{$input-disabled-bg-dark}; + --kt-input-disabled-color: #{$input-disabled-color-dark}; + --kt-input-disabled-border-color: #{$input-disabled-border-color-dark}; + + --kt-input-color: #{$input-color-dark}; + --kt-input-border-color: #{$input-border-color-dark}; + + --kt-input-focus-bg: #{$input-focus-bg-dark}; + --kt-input-focus-border-color: #{$input-focus-border-color-dark}; + --kt-input-focus-color: #{$input-focus-color-dark}; + + // Keenthemes solid input style + --kt-input-solid-bg: #{$input-solid-bg-dark}; + --kt-input-solid-bg-focus: #{$input-solid-bg-focus-dark}; + --kt-input-solid-placeholder-color: #{$input-solid-placeholder-color-dark}; + --kt-input-solid-color: #{$input-solid-color-dark}; + + // Form checks + --kt-form-check-label-color: #{$form-check-label-color-dark}; + --kt-form-check-label-color-checked: #{$form-check-label-color-checked-dark}; + --kt-form-check-input-active-filter: #{$form-check-input-active-filter-dark}; + + --kt-form-check-input-bg: #{$form-check-input-bg-dark}; + --kt-form-check-input-bg-solid: #{$form-check-input-bg-solid-dark}; + --kt-form-check-input-border: #{$form-check-input-border-dark}; + --kt-form-check-input-focus-border: #{$form-check-input-focus-border-dark}; + --kt-form-check-input-focus-box-shadow: #{$form-check-input-focus-box-shadow-dark}; + + --kt-form-check-input-checked-color: #{$form-check-input-checked-color-dark}; + --kt-form-check-input-checked-bg-color: #{$form-check-input-checked-bg-color-dark}; + --kt-form-check-input-checked-border-color: #{$form-check-input-checked-border-color-dark}; + --kt-form-check-input-checked-bg-image: #{escape-svg($form-check-input-checked-bg-image-dark)}; + --kt-form-check-radio-checked-bg-image: #{escape-svg($form-check-radio-checked-bg-image-dark)}; + + --kt-form-check-input-indeterminate-color: #{$form-check-input-indeterminate-color-dark}; + --kt-form-check-input-indeterminate-bg-color: #{$form-check-input-indeterminate-bg-color-dark}; + --kt-form-check-input-indeterminate-border-color: #{$form-check-input-indeterminate-border-color-dark}; + --kt-form-check-input-indeterminate-bg-image: #{escape-svg($form-check-input-indeterminate-bg-image-dark)}; + + --kt-form-check-input-disabled-opacity: #{$form-check-input-disabled-opacity-dark}; + --kt-form-check-label-disabled-opacity: #{$form-check-label-disabled-opacity-dark}; + --kt-form-check-btn-check-disabled-opacity: #{$form-check-btn-check-disabled-opacity-dark}; + + --kt-form-switch-color: #{$form-switch-color-dark}; + --kt-form-switch-color-solid: #{$form-switch-color-solid-dark}; + --kt-form-switch-bg-image: #{escape-svg($form-switch-bg-image-dark)}; + --kt-form-switch-bg-image-solid: #{escape-svg($form-switch-bg-image-solid-dark)}; + --kt-form-switch-focus-color: #{$form-switch-focus-color-dark}; + --kt-form-switch-focus-bg-image: #{escape-svg($form-switch-focus-bg-image-dark)}; + --kt-form-switch-checked-color: #{$form-switch-checked-color-dark}; + --kt-form-switch-checked-bg-image: #{escape-svg($form-switch-checked-bg-image-dark)}; + + // Input groups + --kt-input-group-addon-color: #{$input-group-addon-color-dark}; + --kt-input-group-addon-bg: #{$input-group-addon-bg-dark}; + --kt-input-group-addon-border-color: #{$input-group-addon-border-color-dark}; + + // Form select + --kt-form-select-color: #{$form-select-color-dark}; + --kt-form-select-bg: #{$form-select-bg-dark}; + --kt-form-select-disabled-color: #{$form-select-disabled-color-dark}; + --kt-form-select-disabled-bg: #{$form-select-disabled-bg-dark}; + --kt-form-select-disabled-border-color: #{$form-select-disabled-border-color-dark}; + --kt-form-select-indicator-color: #{$form-select-indicator-color-dark}; + --kt-form-select-indicator: #{escape-svg($form-select-indicator-dark)}; + --kt-form-select-border-color: #{$form-select-border-color-dark}; + --kt-form-select-box-shadow: #{$form-select-box-shadow-dark}; + --kt-form-select-focus-border-color: #{$form-select-focus-border-color-dark}; + --kt-form-select-focus-box-shadow: #{$form-select-focus-box-shadow-dark}; + + // Form file button + --kt-form-file-button-color: #{$form-file-button-color-dark}; + --kt-form-file-button-bg: #{$form-file-button-bg-dark}; + --kt-form-file-button-hover-bg: #{$form-file-button-hover-bg-dark}; + + // Navs + --kt-nav-tabs-border-color: #{$nav-tabs-border-color-dark}; + --kt-nav-tabs-link-hover-border-color: #{$nav-tabs-link-hover-border-color-dark}; + --kt-nav-tabs-link-active-color: #{$nav-tabs-link-active-color-dark}; + --kt-nav-tabs-link-active-bg: #{$nav-tabs-link-active-bg-dark}; + --kt-nav-tabs-link-active-border-color: #{$nav-tabs-link-active-border-color-dark}; + + --kt-nav-pills-link-active-color: #{$nav-pills-link-active-color-dark}; + --kt-nav-pills-link-active-bg: #{$nav-pills-link-active-bg-dark}; + + // Dropdowns + --kt-dropdown-color: #{$dropdown-color-dark}; + --kt-dropdown-bg: #{$dropdown-bg-dark}; + --kt-dropdown-divider-bg: #{$dropdown-divider-bg-dark}; + --kt-dropdown-box-shadow: #{$dropdown-box-shadow-dark}; + --kt-dropdown-link-color: #{$dropdown-link-color-dark}; + --kt-dropdown-link-hover-color: #{$dropdown-link-hover-color-dark}; + --kt-dropdown-link-hover-bg: #{$dropdown-link-hover-bg-dark}; + --kt-dropdown-link-active-color: #{$dropdown-link-active-color-dark}; + --kt-dropdown-link-active-bg: #{$dropdown-link-active-bg-dark}; + --kt-dropdown-link-disabled-color: #{$dropdown-link-disabled-color-dark}; + --kt-dropdown-header-color: #{$dropdown-header-color-dark}; + + // Pagination + --kt-pagination-item-bg: #{$pagination-item-bg-dark}; + --kt-pagination-color: #{$pagination-color-dark}; + --kt-pagination-bg: #{$pagination-bg-dark}; + --kt-pagination-border-color: #{$pagination-border-color-dark}; + --kt-pagination-focus-color: #{$pagination-focus-color-dark}; + --kt-pagination-focus-bg: #{$pagination-focus-bg-dark}; + --kt-pagination-focus-box-shadow: #{$pagination-focus-box-shadow-dark}; + --kt-pagination-focus-outline: #{$pagination-focus-outline-dark}; + --kt-pagination-hover-color: #{$pagination-hover-color-dark}; + --kt-pagination-hover-bg: #{$pagination-hover-bg-dark}; + --kt-pagination-hover-border-color: #{$pagination-hover-border-color-dark}; + --kt-pagination-active-color: #{$pagination-active-color-dark}; + --kt-pagination-active-bg: #{$pagination-active-bg-dark}; + --kt-pagination-active-border-color: #{$pagination-active-border-color-dark}; + --kt-pagination-disabled-color: #{$pagination-disabled-color-dark}; + --kt-pagination-disabled-bg: #{$pagination-disabled-bg-dark}; + + // Card + --kt-card-bg: #{$card-bg-dark}; + --kt-card-color: #{$card-color-dark}; + --kt-card-box-shadow: #{$card-box-shadow-dark}; + --kt-card-border-color: #{$card-border-color-dark}; + --kt-card-border-dashed-color: #{$card-border-dashed-color-dark}; + --kt-card-cap-bg: #{$card-cap-bg-dark}; + + // Accordion + --kt-accordion-color: #{$accordion-color-dark}; + --kt-accordion-bg: #{$accordion-bg-dark}; + --kt-accordion-border-color: #{$accordion-border-color-dark}; + --kt-accordion-button-color: #{$accordion-button-color-dark}; + --kt-accordion-button-bg: #{$accordion-button-bg-dark}; + --kt-accordion-button-active-bg: #{$accordion-button-active-bg-dark}; + --kt-accordion-button-active-color: #{$accordion-button-active-color-dark}; + --kt-accordion-button-focus-border-color: #{$accordion-button-focus-border-color-dark}; + --kt-accordion-button-focus-box-shadow: #{$accordion-button-focus-box-shadow-dark}; + + --kt-accordion-icon-color: #{$accordion-icon-color-dark}; + --kt-accordion-icon-active-color: #{$accordion-icon-active-color-dark}; + --kt-accordion-button-icon: #{escape-svg($accordion-button-icon-dark)}; + --kt-accordion-button-active-icon: #{escape-svg($accordion-button-active-icon-dark)}; + + // Tooltips + --kt-tooltip-color: #{$tooltip-color-dark}; + --kt-tooltip-bg: #{$tooltip-bg-dark}; + --kt-tooltip-opacity: #{$tooltip-opacity-dark}; + --kt-tooltip-box-shadow: #{$tooltip-box-shadow-dark}; + + // Popovers + --kt-popover-bg: #{$popover-bg-dark}; + --kt-popover-border-color: #{$popover-border-color-dark}; + --kt-popover-box-shadow: #{$popover-box-shadow-dark}; + --kt-popover-header-bg: #{$popover-header-bg-dark}; + --kt-popover-header-color: #{$popover-header-color-dark}; + --kt-popover-header-border-color: #{$popover-header-border-color-dark}; + --kt-popover-body-color: #{$popover-body-color-dark}; + + // Dropdowns + --kt-dropdown-box-shadow: #{$dropdown-box-shadow-dark}; + --kt-dropdown-bg: #{$dropdown-bg-dark}; + + // Toasts + --kt-toast-color: #{$toast-color-dark}; + --kt-toast-background-color: #{$toast-background-color-dark}; + --kt-toast-box-shadow: #{$toast-box-shadow-dark}; + --kt-toast-header-color: #{$toast-header-color-dark}; + --kt-toast-header-background-color: #{$toast-header-background-color-dark}; + --kt-toast-header-border-color: #{$toast-header-border-color-dark}; + + // Badges + --kt-badge-color: #{$badge-color-dark}; + + // Modals + --kt-modal-bg: #{$modal-content-bg-dark}; + --kt-modal-color: #{$modal-content-color-dark}; + --kt-modal-border-color: #{$modal-content-border-color-dark}; + --kt-modal-box-shadow: #{$modal-content-box-shadow-dark}; + --kt-modal-content-color: #{$modal-content-color-dark}; + --kt-modal-content-bg: #{$modal-content-bg-dark}; + --kt-modal-content-border-color: #{$modal-content-border-color-dark}; + --kt-modal-content-box-shadow: #{$modal-content-box-shadow-dark}; + --kt-modal-content-box-shadow-xs: #{$modal-content-box-shadow-xs-dark}; + --kt-modal-content-box-shadow-sm-up: #{$modal-content-box-shadow-sm-up-dark}; + --kt-modal-header-border-color: #{$modal-header-border-color-dark}; + --kt-modal-footer-border-color: #{$modal-footer-border-color-dark}; + --kt-modal-backdrop-bg: #{$modal-backdrop-bg-dark}; + --kt-modal-backdrop-opacity: #{$modal-backdrop-opacity-dark}; + + // Progress bars + --kt-progress-bg: #{$progress-bg-dark}; + --kt-progress-box-shadow: #{$progress-box-shadow-dark}; + + // List group + --kt-list-group-color: #{$list-group-color-dark}; + --kt-list-group-bg: #{$list-group-bg-dark}; + --kt-list-group-border-color: #{$list-group-border-color-dark}; + --kt-list-group-hover-bg: #{$list-group-hover-bg-dark}; + --kt-list-group-active-color: #{$list-group-active-color-dark}; + --kt-list-group-active-bg: #{$list-group-active-bg-dark}; + --kt-list-group-active-border-colorg: #{$list-group-active-border-color-dark}; + --kt-list-group-disabled-color: #{$list-group-disabled-color-dark}; + --kt-list-group-disabled-bg: #{$list-group-disabled-bg-dark}; + --kt-list-group-action-colorg: #{$list-group-action-color-dark}; + --kt-list-group-action-hover-color: #{$list-group-action-hover-color-dark}; + --kt-list-group-action-active-color: #{$list-group-action-active-color-dark}; + --kt-list-group-action-active-bg: #{$list-group-action-active-bg-dark}; + + // Image thumbnails + --kt-thumbnail-bg: #{$thumbnail-bg-dark}; + --kt-thumbnail-border-color: #{$thumbnail-border-color-dark}; + --kt-thumbnail-box-shadow: #{$thumbnail-box-shadow-dark}; + + // Figures + --kt-figure-caption-color: #{$figure-caption-color-dark}; + + // Breadcrumbs + --kt-breadcrumb-bg: #{$breadcrumb-bg-dark}; + --kt-breadcrumb-divider-color: #{$breadcrumb-divider-color-dark}; + --kt-breadcrumb-active-color: #{$breadcrumb-active-color-dark}; + + // Carousel + --kt-carousel-custom-indicator-default-bg-color: #{$carousel-custom-indicator-default-bg-color-dark}; + --kt-carousel-custom-indicator-active-bg-color: #{$carousel-custom-indicator-active-bg-color-dark}; + --kt-arousel-custom-bullet-indicator-default-bg-color: #{$carousel-custom-bullet-indicator-default-bg-color-dark}; + --kt-carousel-custom-bullet-indicator-active-bg-color: #{$carousel-custom-bullet-indicator-active-bg-color-dark}; + + // Close + --kt-btn-close-color: #{$btn-close-color-dark}; + --kt-btn-close-bg: #{escape-svg($btn-close-bg-dark)}; + + // Offcanvas + --kt-code-bg: #{$code-bg-dark}; + --kt-code-box-shadow: #{$code-box-shadow-dark}; + --kt-code-color: #{$code-color-dark}; + + // Offcanvas + --kt-offcanvas-border-color: #{$offcanvas-border-color-dark}; + --kt-offcanvas-bg-color: #{$offcanvas-bg-color-dark}; + --kt-offcanvas-color: #{$offcanvas-color-dark}; + --kt-offcanvas-box-shadow: #{$offcanvas-box-shadow-dark}; + --kt-offcanvas-backdrop-bg: #{$offcanvas-backdrop-bg-dark}; + --kt-offcanvas-backdrop-opacity: #{$offcanvas-backdrop-opacity-dark}; + + // Code + --kt-code-bg: #{$code-bg-dark}; + --kt-code-box-shadow: #{$code-box-shadow-dark}; + --kt-code-color: #{$code-color-dark}; + + // Symbol + --kt-symbol-label-color: #{$symbol-label-color-dark}; + --kt-symbol-label-bg: #{$symbol-label-bg-dark}; + --kt-symbol-border-color: #{$symbol-border-color-dark}; + + // Bullet + --kt-bullet-bg-color: #{$bullet-bg-color-dark}; + + // Scrolltop + --kt-scrolltop-opacity: #{$scrolltop-opacity-dark}; + --kt-scrolltop-opacity-on: #{$scrolltop-opacity-on-dark}; + --kt-scrolltop-opacity-hover: #{$scrolltop-opacity-hover-dark}; + --kt-scrolltop-box-shadow: #{$scrolltop-box-shadow-dark}; + --kt-scrolltop-bg-color: #{$scrolltop-bg-color-dark}; + --kt-scrolltop-bg-color-hover: #{$scrolltop-bg-color-hover-dark}; + --kt-scrolltop-icon-color: #{$scrolltop-icon-color-dark}; + --kt-scrolltop-icon-color-hover: #{$scrolltop-icon-color-hover-dark}; + + // Keenthemes drawer component + --kt-drawer-box-shadow: #{$drawer-box-shadow-dark}; + --kt-drawer-bg-color: #{$drawer-bg-color-dark}; + --kt-drawer-overlay-bg-color: #{$drawer-overlay-bg-color-dark}; + + // Keenthemes menu component + --kt-menu-dropdown-box-shadow: #{$menu-dropdown-box-shadow-dark}; + --kt-menu-dropdown-bg-color: #{$menu-dropdown-bg-color-dark}; + --kt-menu-heading-color: #{$menu-heading-color-dark}; + + --kt-menu-link-color-hover: #{$menu-link-color-hover-dark}; + --kt-menu-link-color-show: #{$menu-link-color-show-dark}; + --kt-menu-link-color-here: #{$menu-link-color-here-dark}; + --kt-menu-link-color-active: #{$menu-link-color-active-dark}; + --kt-menu-link-bg-color-hover: #{$menu-link-bg-color-hover-dark}; + --kt-menu-link-bg-color-show: #{$menu-link-bg-color-show-dark}; + --kt-menu-link-bg-color-here: #{$menu-link-bg-color-here-dark}; + --kt-menu-link-bg-color-active: #{$menu-link-bg-color-active-dark}; + + + // Keenthemes feedback component + --kt-feedback-popup-box-shadow: #{$feedback-popup-box-shadow-dark}; + --kt-feedback-popup-background-color: #{$feedback-popup-background-color-dark}; + + // Keenthemes scrollbar component + --kt-scrollbar-color: #{$scrollbar-color-dark}; + --kt-scrollbar-hover-color: #{$scrollbar-hover-color-dark}; + + // Keenthemes overlay component + --kt-overlay-bg: #{$overlay-bg-dark}; + + // Keenthemes blockui component + --kt-blockui-overlay-bg: #{$blockui-overlay-bg-dark}; + + // Keenthemes rating component + --kt-rating-color-default: #{$rating-color-default-dark}; + --kt-rating-color-active: #{$rating-color-active-dark}; + + // Keenthemes ribbon component + --kt-ribbon-label-box-shadow: #{$ribbon-label-box-shadow-dark}; + --kt-ribbon-label-bg: #{$ribbon-label-bg-dark}; + --kt-ribbon-label-border-color: #{$ribbon-label-border-color-dark}; + --kt-ribbon-clip-bg: #{$ribbon-clip-bg-dark}; + + // Engage panel + --kt-engage-btn-bg: #{$engage-btn-bg-dark}; + --kt-engage-btn-color: #{$engage-btn-color-dark}; + --kt-engage-btn-color-active: #{$engage-btn-color-active-dark}; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_rotate.scss b/src/_res/assets/sass/core/components/_rotate.scss new file mode 100644 index 0000000..80ece20 --- /dev/null +++ b/src/_res/assets/sass/core/components/_rotate.scss @@ -0,0 +1,47 @@ +// +// Rotate +// + + +$rotate-transition: transform 0.3s ease; + +.rotate { + display: inline-flex; + align-items: center; +} + +@each $value in (90, 180, 270) { + .rotate-#{$value} { + transition: $rotate-transition; + backface-visibility: hidden; + will-change: transform; + + .collapsible:not(.collapsed)> & , + .show > &, + .active > & { + transform: rotateZ(#{$value}deg); + transition: $rotate-transition; + + [direction="rtl"] & { + transform: rotateZ(-#{$value}deg); + } + } + } + + .rotate-n#{$value} { + transition: $rotate-transition; + backface-visibility: hidden; + will-change: transform; + + .collapsible:not(.collapsed)> &, + .show > &, + .active > & { + transform: rotateZ(-#{$value}deg); + transition: $rotate-transition; + + [direction="rtl"] & { + transform: rotateZ(#{$value}deg); + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_scroll.scss b/src/_res/assets/sass/core/components/_scroll.scss new file mode 100644 index 0000000..e61ca0b --- /dev/null +++ b/src/_res/assets/sass/core/components/_scroll.scss @@ -0,0 +1,309 @@ +// +// Scroll +// + + +// Customize native scrollbars only for desktop mode +@include media-breakpoint-up(lg) { + main, + span, + ol, + ul, + pre, + div { + // Firefox + scrollbar-width: thin; + + // Webkit + &::-webkit-scrollbar { + width: var(--kt-scrollbar-width); + height: var(--kt-scrollbar-height); + } + + ::-webkit-scrollbar-track { + @include border-radius($scrollbar-border-radius); + } + + ::-webkit-scrollbar-thumb { + @include border-radius($scrollbar-border-radius); + } + + // Default color + @include scrollbar-color(var(--kt-scrollbar-color), var(--kt-scrollbar-hover-color)); + } +} + +// Overflow scroll +.scroll { + overflow: scroll; + position: relative; + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow: auto; + } +} + +.scroll-x { + overflow-x: scroll; + position: relative; + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow-x: auto; + } +} + +.scroll-y { + overflow-y: scroll; + position: relative; + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow-y: auto; + } +} + +// Hover overflow scroll +.hover-scroll { + position: relative; + + // Desktop mode + @include media-breakpoint-up(lg) { + overflow: hidden; + + border-right: var(--kt-scrollbar-width) solid transparent; + border-bottom: var(--kt-scrollbar-height) transparent; + margin-right: calc( -1 * var(--kt-scrollbar-width)); + margin-bottom: calc( -1 * var(--kt-scrollbar-height)); + + &:hover { + overflow: scroll; + border-right: 0; + border-bottom: 0; + } + + // Firefox hack + @-moz-document url-prefix() { + overflow: scroll; + position: relative; + border-right: 0; + border-bottom: 0; + } + } + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow: auto; + } +} + +// Hover overflow scroll y +.hover-scroll-y { + position: relative; + + // Desktop mode + @include media-breakpoint-up(lg) { + overflow-y: hidden; + border-right: var(--kt-scrollbar-width) solid transparent; + margin-right: calc( -1 * var(--kt-scrollbar-width)); + + &:hover { + overflow-y: scroll; + border-right: 0; + } + + // Firefox hack + @-moz-document url-prefix() { + overflow-y: scroll; + position: relative; + border-right: 0; + } + } + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow-y: auto; + } +} + +// Hover overflow scroll x +.hover-scroll-x { + position: relative; + + // Desktop mode + @include media-breakpoint-up(lg) { + overflow-x: hidden; + border-bottom: var(--kt-scrollbar-height) solid transparent; + + &:hover { + overflow-x: scroll; + border-bottom: 0; + } + + // Firefox hack + @-moz-document url-prefix() { + overflow-x: scroll; + position: relative; + border-bottom: 0; + } + } + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow-x: auto; + } +} + +// Hover overflow overlay +.hover-scroll-overlay { + position: relative; + + // Desktop mode + @include media-breakpoint-up(lg) { + overflow: hidden; + + // Webkit + &::-webkit-scrollbar { + width: calc( var(--kt-scrollbar-width) + var(--kt-scrollbar-width) ); + height: calc( var(--kt-scrollbar-width) + var(--kt-scrollbar-width) ); + } + + &::-webkit-scrollbar-track { + border-radius: 0; + } + + &::-webkit-scrollbar-thumb { + border-radius: 0; + background-clip: content-box; + border-right: var(--kt-scrollbar-space) solid transparent; + border-bottom: var(--kt-scrollbar-space) solid transparent; + } + + &:hover { + overflow: overlay; + } + + // Firefox hack + @-moz-document url-prefix() { + overflow: scroll; + position: relative; + } + } + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow: auto; + } +} + +// Hover overflow overlay y +.hover-scroll-overlay-y { + position: relative; + + // Desktop mode + @include media-breakpoint-up(lg) { + overflow-y: hidden; + + // Webkit + &::-webkit-scrollbar { + width: calc( var(--kt-scrollbar-width) + var(--kt-scrollbar-space)); + } + + &::-webkit-scrollbar-track { + border-radius: 0; + } + + &::-webkit-scrollbar-thumb { + border-radius: 0; + background-clip: content-box; + border-right: var(--kt-scrollbar-space) solid transparent; + } + + &:hover { + overflow-y: overlay; + } + + // Firefox hack + @-moz-document url-prefix() { + overflow-y: scroll; + position: relative; + } + } + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow-y: auto; + } +} + +// Hover overflow overlay x +.hover-scroll-overlay-x { + position: relative; + + // Desktop mode + @include media-breakpoint-up(lg) { + overflow-x: hidden; + + // Webkit + &::-webkit-scrollbar { + height: calc( var(--kt-scrollbar-width) + var(--kt-scrollbar-space) ); + } + + &::-webkit-scrollbar-track { + border-radius: 0; + } + + &::-webkit-scrollbar-thumb { + border-radius: 0; + background-clip: content-box; + border-bottom: var(--kt-scrollbar-space) solid transparent; + } + + &:hover { + overflow-x: overlay; + } + + // Firefox hack + @-moz-document url-prefix() { + overflow-x: scroll; + position: relative; + } + } + + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + overflow-x: auto; + } +} + +// Utility classes +.scroll-ps { + padding-left: var(--kt-scrollbar-width) !important; +} + +.scroll-ms { + margin-left: var(--kt-scrollbar-width) !important; +} + +.scroll-mb { + margin-bottom: var(--kt-scrollbar-height) !important; +} + +.scroll-pe { + padding-right: var(--kt-scrollbar-width) !important; +} + +.scroll-me { + margin-right: var(--kt-scrollbar-width) !important; +} + +.scroll-px { + padding-left: var(--kt-scrollbar-width) !important; + padding-right: var(--kt-scrollbar-width) !important; +} + +.scroll-mx { + margin-left: var(--kt-scrollbar-width) !important; + margin-right: var(--kt-scrollbar-width) !important; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_scrolltop.scss b/src/_res/assets/sass/core/components/_scrolltop.scss new file mode 100644 index 0000000..b4571bf --- /dev/null +++ b/src/_res/assets/sass/core/components/_scrolltop.scss @@ -0,0 +1,69 @@ +// +// Scrolltop +// + +.scrolltop { + position: fixed; + display: none; + cursor: pointer; + z-index: $scrolltop-z-index; + justify-content: center; + align-items: center; + width: $scrolltop-size; + height: $scrolltop-size; + bottom: $scrolltop-bottom; + right: $scrolltop-end; + background-color: var(--kt-scrolltop-bg-color); + box-shadow: var(--kt-scrolltop-box-shadow); + opacity: $scrolltop-opacity; + transition: $transition-link; + @include border-radius($border-radius); + + .svg-icon { + @include svg-icon-size(24px); + color: var(--kt-scrolltop-icon-color); + } + + > i { + font-size: 1.3rem; + color: var(--kt-scrolltop-icon-color); + } + + &:hover { + background-color: var(--kt-scrolltop-bg-color-hover); + + .svg-icon, + i { + color: var(--kt-scrolltop-icon-color-hover); + } + } + + [data-kt-scrolltop="on"] & { + opacity: var(--kt-scrolltop-opacity-on); + animation: animation-scrolltop .4s ease-out 1; + display: flex; + + &:hover { + transition: $transition-link; + opacity: var(--kt-scrolltop-opacity-hover); + } + } + + +} + +// Tablet & Mobile Modess +@include media-breakpoint-down(lg) { + .scrolltop { + bottom: $scrolltop-bottom-mobile; + right: $scrolltop-end-mobile; + width: $scrolltop-size-mobile; + height: $scrolltop-size-mobile; + } +} + +// Animations +@keyframes animation-scrolltop { + from { margin-bottom: -15px; } + to { margin-bottom: 0; } +} diff --git a/src/_res/assets/sass/core/components/_separator.scss b/src/_res/assets/sass/core/components/_separator.scss new file mode 100644 index 0000000..4417e1d --- /dev/null +++ b/src/_res/assets/sass/core/components/_separator.scss @@ -0,0 +1,66 @@ +// +// Separator +// + +.separator { + display: block; + height: 0; + border-bottom: 1px solid var(--kt-border-color); + + &.separator-dotted { + border-bottom-style: dotted; + border-bottom-color: var(--kt-border-dashed-color); + } + + &.separator-dashed { + border-bottom-style: dashed; + border-bottom-color: var(--kt-border-dashed-color); + } + + &.separator-content { + display: flex; + align-items: center; + border-bottom: 0; + text-align: center; + + &::before, + &::after { + content: " "; + width: 50%; + border-bottom: 1px solid var(--kt-border-color); + } + + &::before{ + margin-right: 1.25rem; + } + + &::after{ + margin-left: 1.25rem; + } + + &.separator-dotted { + &::before, + &::after { + border-bottom-style: dotted; + border-bottom-color: var(--kt-border-dashed-color); + } + } + + &.separator-dashed { + &::before, + &::after { + border-bottom-style: dashed; + border-bottom-color: var(--kt-border-dashed-color); + } + } + + @each $color, $value in $theme-colors { + &.border-#{$color}{ + &::before, + &::after { + border-color: $value !important; + } + } + } + } +} diff --git a/src/_res/assets/sass/core/components/_shape.scss b/src/_res/assets/sass/core/components/_shape.scss new file mode 100644 index 0000000..e540908 --- /dev/null +++ b/src/_res/assets/sass/core/components/_shape.scss @@ -0,0 +1,13 @@ +// +// Shape +// + +.xehagon { + //$edges-number: 6, $main-radius: 30%, $rounding-radius: 10%, $rotated: true, $precision: 20 + @include shape(6); +} + +.octagon { + //$edges-number: 6, $main-radius: 30%, $rounding-radius: 10%, $rotated: true, $precision: 20 + @include shape(8); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_stepper.scss b/src/_res/assets/sass/core/components/_stepper.scss new file mode 100644 index 0000000..eff128c --- /dev/null +++ b/src/_res/assets/sass/core/components/_stepper.scss @@ -0,0 +1,8 @@ +// +// Stepper +// + +// Import Dependencies +@import "stepper/base"; +@import "stepper/pills"; +@import "stepper/links"; diff --git a/src/_res/assets/sass/core/components/_svg-icon.scss b/src/_res/assets/sass/core/components/_svg-icon.scss new file mode 100644 index 0000000..7147ab8 --- /dev/null +++ b/src/_res/assets/sass/core/components/_svg-icon.scss @@ -0,0 +1,30 @@ +// +// SVG Icon +// + +.svg-icon { + line-height: 1; + color: var(--kt-text-muted); + @include svg-icon-size(get($font-sizes, 5)); + + // Theme colors + @each $name, $color in $theme-text-colors { + &.svg-icon-#{$name} { + color: var(--kt-text-#{$name}); + } + } + + // Responsive icon sizes + @each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + // Sizes + @each $name, $value in $font-sizes { + &.svg-icon#{$infix}-#{$name} { + @include svg-icon-size($value, true); + } + } + } + } +} diff --git a/src/_res/assets/sass/core/components/_symbol.scss b/src/_res/assets/sass/core/components/_symbol.scss new file mode 100644 index 0000000..5b49557 --- /dev/null +++ b/src/_res/assets/sass/core/components/_symbol.scss @@ -0,0 +1,133 @@ +// +// symbol +// + +// Base +.symbol { + display: inline-block;; + flex-shrink: 0; + position: relative; + @include border-radius($border-radius); + + // Label + .symbol-label { + display: flex; + align-items: center; + justify-content: center; + font-weight: 500; + color: var(--kt-symbol-label-color); + background-color: var(--kt-symbol-label-bg); + background-repeat: no-repeat; + background-position: center center; + background-size: cover; + @include border-radius($border-radius); + + &:after { + @include border-radius($border-radius); + } + } + + // Badge + .symbol-badge { + position: absolute; + border-radius: 100%; + top: 0; + left: 50%; + transform: translateX(-50%) translateY(-50%) !important; + } + + // Image + > img { + width: 100%; + flex-shrink: 0; + display: inline-block; + @include border-radius($border-radius); + } + + // Square + &.symbol-square { + &, + > img, + .symbol-label { + border-radius: 0 !important; + } + } + + // Circle + &.symbol-circle { + &, + > img, + .symbol-label { + border-radius: 50%; + + &:after { + border-radius: 50%; + } + } + } + + // Sizes + @include symbol-size(get($symbol-sizes, default)); + + @each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + @each $name, $value in $symbol-sizes { + @if ($name != 'default') { + &.symbol#{$infix}-#{$name} { + @include symbol-size($value); + } + } + } + } + } +} + +// Group +.symbol-group { + display: flex; + flex-wrap: wrap; + align-items: center; + margin-left: 10px; + + .symbol { + position: relative; + z-index: 0; + margin-left: -10px; + transition: all 0.3s ease; + + &:hover { + transition: all 0.3s ease; + z-index: 1; + } + } + + .symbol-badge { + border: 2px solid var(--kt-body-bg); + } + + .symbol-label { + position: relative; + + &:after { + display: block; + content: " "; + border-radius: inherit; + position: absolute; + top: 0; + right: 0; + left: 0; + bottom: 0; + border: 2px solid var(--kt-symbol-border-color); + -webkit-background-clip: padding-box; /* for Safari */ + background-clip: padding-box; /* for IE9+, Firefox 4+, Opera, Chrome */ + } + } + + &.symbol-hover { + .symbol { + cursor: pointer; + } + } +} diff --git a/src/_res/assets/sass/core/components/_tables.scss b/src/_res/assets/sass/core/components/_tables.scss new file mode 100644 index 0000000..1ff0772 --- /dev/null +++ b/src/_res/assets/sass/core/components/_tables.scss @@ -0,0 +1,243 @@ +// +// Table +// + +// Table +.table { + --#{$prefix}table-color: var(--kt-table-color); + --#{$prefix}table-bg: var(--kt-table-bg); + --#{$prefix}table-border-color: var(--kt-table-border-color); + --#{$prefix}table-accent-bg: var(--kt-table-accent-bg); + --#{$prefix}table-striped-color: var(--kt-table-striped-color); + --#{$prefix}table-striped-bg: var(--kt-table-striped-bg); + --#{$prefix}table-active-color: var(--kt-table-active-color); + --#{$prefix}table-active-bg: var(--kt-table-active-bg); + --#{$prefix}table-hover-color: var(--kt-table-hover-color); + --#{$prefix}table-hover-bg: var(--kt-table-hover-bg); + + // Fix for BS 5.1.2 update + & > :not(:first-child) { + border-color: transparent; + border-width: 0; + border-style: none; + } + + >:not(:last-child)>:last-child>* { + border-bottom-color: inherit; + } + + tr, th, td { + border-color: inherit; + border-width: inherit; + border-style: inherit; + text-transform: inherit; + font-weight: inherit; + font-size: inherit; + color: inherit; + height: inherit; + min-height: inherit; + + &:first-child { + padding-left: 0; + } + + &:last-child { + padding-right: 0; + } + } + + tfoot, + tbody { + tr:last-child { + border-bottom: 0 !important; + + th, td { + border-bottom: 0 !important; + } + } + } + + tfoot { + th, td { + border-top: inherit; + } + } + + // Rounded + &.table-rounded { + border-radius: $border-radius; + border-spacing: 0; + border-collapse: separate; + } + + // Flush + &.table-flush { + tr, th, td { + padding: inherit; + } + } + + // Row bordered + &.table-row-bordered { + tr { + border-bottom-width: 1px; + border-bottom-style: solid; + border-bottom-color: var(--kt-border-color); + } + + tfoot { + th, td { + border-top-width: 1px !important; + } + } + } + + // Row dashed + &.table-row-dashed { + tr { + border-bottom-width: 1px; + border-bottom-style: dashed; + border-bottom-color: var(--kt-border-color); + } + + tfoot { + th, td { + border-top-width: 1px !important; + } + } + } + + // Row border colors + @each $name, $value in $grays { + &.table-row-gray-#{$name} { + tr { + border-bottom-color: var(--kt-gray-#{$name}); + } + } + } +} + +// Layout fixed +.table-layout-fixed { + table-layout: fixed; +} + +// Sorting +.table-sort { + &:after { + opacity: 0; + } +} + +.table-sort, +.table-sort-asc, +.table-sort-desc { + vertical-align: middle; + + &:after { + position: relative; + display: inline-block; + width: 0.75rem; + height: 0.75rem; + content: " "; + bottom: auto; + right: auto; + left: auto; + margin-left: 0.5rem; + } +} + +.table-sort-asc { + &:after { + opacity: 1; + @include svg-bg-icon(arrow-top, var(--kt-text-muted)); + } +} + +.table-sort-desc { + &:after { + opacity: 1; + @include svg-bg-icon(arrow-bottom, var(--kt-text-muted)); + } +} + +// Loading +.table-loading-message { + display: none; + position: absolute; + top: 50%; + left: 50%; + @include border-radius($border-radius); + box-shadow: var(--kt-table-loading-message-box-shadow); + background-color: var(--kt-table-loading-message-bg); + color: var(--kt-table-loading-message-color); + font-weight: $font-weight-bold; + margin: 0 !important; + width: auto; + padding: 0.85rem 2rem !important; + transform: translateX(-50%) translateY(-50%); +} + +.table-loading { + position: relative; + + .table-loading-message { + display: block; + } +} + +// Cell gutters +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + @each $name, $value in $gutters { + .table.g#{$infix}-#{$name} { + th, td { + padding: $value; + + // Datatables responsive mode fix + &.dtr-control { + padding-left: $value !important; + } + } + } + + .table.gy#{$infix}-#{$name} { + th, td { + padding-top: $value; + padding-bottom: $value; + } + } + + .table.gx#{$infix}-#{$name} { + th, td { + padding-left: $value; + padding-right: $value; + + // Datatables responsive mode fix + &.dtr-control { + padding-left: $value !important; + } + } + } + + .table.gs#{$infix}-#{$name} { + th, td { + &:first-child { + padding-left: $value; + } + + &:last-child { + padding-right: $value; + } + + // Datatables responsive mode fix + &.dtr-control:first-child { + padding-left: $value !important; + } + } + } + } + } +} diff --git a/src/_res/assets/sass/core/components/_theme-mode.scss b/src/_res/assets/sass/core/components/_theme-mode.scss new file mode 100644 index 0000000..40e99ee --- /dev/null +++ b/src/_res/assets/sass/core/components/_theme-mode.scss @@ -0,0 +1,38 @@ +// +// Theme Modes +// + +// Used for theme mode switching via JS +[data-kt-theme-mode-switching="true"] * { + transition: none !important; +} + +// Light mode +@include theme-light() { + .theme-dark-show { + display: none !important; + } + + .theme-light-bg-transparent { + background-color: transparent !important; + } + + .theme-light-bg-body { + background-color: var(--kt-body-bg) !important; + } +} + +// Dark mode +@include theme-dark() { + .theme-light-show { + display: none !important; + } + + .theme-dark-bg-transparent { + background-color: transparent !important; + } + + .theme-dark-bg-body { + background-color: var(--kt-body-bg) !important; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_timeline-label.scss b/src/_res/assets/sass/core/components/_timeline-label.scss new file mode 100644 index 0000000..edbcab7 --- /dev/null +++ b/src/_res/assets/sass/core/components/_timeline-label.scss @@ -0,0 +1,68 @@ +// +// Timeline Label +// + + +.timeline-label { + position: relative; + + $label-width: 50px; + + &:before { + content: ''; + position: absolute; + left: $label-width + 1px; + width: 3px; + top: 0; + bottom: 0; + background-color: var(--kt-gray-200); + } + + // + .timeline-item { + display: flex; + align-items: flex-start; + position: relative; + margin-bottom: 1.7rem; + + &:last-child { + margin-bottom: 0; + } + } + + .timeline-label { + width: $label-width; + flex-shrink: 0; + position: relative; + color: var(--kt-gray-800); + } + + .timeline-badge { + flex-shrink: 0; + background-color: var(--kt-body-bg); + width: 1rem; + height: 1rem; + border-radius: 100%; + display: flex; + justify-content: center; + align-items: center; + z-index: 1; + position: relative; + margin-top: 1px; + margin-left: -0.5rem; + padding: 3px !important; + border: 6px solid var(--kt-body-bg) !important; + + span { + display: block; + border-radius: 100%; + width: 6px; + height: 6px; + background-color: var(--kt-gray-200); + } + } + + .timeline-content { + flex-grow: 1; + } +} diff --git a/src/_res/assets/sass/core/components/_timeline.scss b/src/_res/assets/sass/core/components/_timeline.scss new file mode 100644 index 0000000..4813245 --- /dev/null +++ b/src/_res/assets/sass/core/components/_timeline.scss @@ -0,0 +1,70 @@ +// +// Timeline +// + +// Base +.timeline { + // Item + .timeline-item { + position: relative; + padding: 0; + margin: 0; + display: flex; + align-items: flex-start; + + &:last-child { + .timeline-line { + bottom: 100%; + } + } + } + + // Line + .timeline-line { + display: block; + content: " "; + justify-content: center; + position: absolute; + z-index: 0; + left: 0; + top:0; + bottom: 0; + transform: translate(50%); + border-left-width: 1px; + border-left-style: dashed; + border-left-color: var(--kt-gray-300); + } + + // Icon + .timeline-icon { + z-index: 1; + flex-shrink: 0; + margin-right: 1rem; + } + + // Content + .timeline-content { + width: 100%; + overflow: auto; + margin-bottom: 1.5rem; + } + + // Vertical center + &.timeline-center { + .timeline-item { + align-items: center; + + &:first-child { + .timeline-line { + top: 50%; + } + } + + &:last-child { + .timeline-line { + bottom: 50%; + } + } + } + } +} diff --git a/src/_res/assets/sass/core/components/_toasts.scss b/src/_res/assets/sass/core/components/_toasts.scss new file mode 100644 index 0000000..4612c77 --- /dev/null +++ b/src/_res/assets/sass/core/components/_toasts.scss @@ -0,0 +1,15 @@ +.toast { + --#{$prefix}toast-color: var(--kt-toast-color); + --#{$prefix}toast-bg: var(--kt-toast-background-color); + --#{$prefix}toast-border-color: var(--kt-toast-border-color); + --#{$prefix}toast-box-shadow: var(--kt-toast-box-shadow); + --#{$prefix}toast-header-color: var(--kt-toast-header-color); + --#{$prefix}toast-header-bg: var(--kt-toast-header-background-color); + --#{$prefix}toast-header-border-color: var(--kt-toast-header-border-color); + + .toast-header { + .btn-close { + margin-right: 0; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_toggle.scss b/src/_res/assets/sass/core/components/_toggle.scss new file mode 100644 index 0000000..9f97ee2 --- /dev/null +++ b/src/_res/assets/sass/core/components/_toggle.scss @@ -0,0 +1,19 @@ +// +// Toggle +// + +.toggle { + &.collapsible:not(.collapsed), // Integration with Bootstrap Collapse + &.active { + .toggle-off { + display: none; + } + } + + &.collapsible.collapsed, // Integration with Bootstrap Collapse + &:not(.collapsible):not(.active) { + .toggle-on { + display: none; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/_tooltip.scss b/src/_res/assets/sass/core/components/_tooltip.scss new file mode 100644 index 0000000..94725b4 --- /dev/null +++ b/src/_res/assets/sass/core/components/_tooltip.scss @@ -0,0 +1,31 @@ +// +// Tooltip +// + + +// Base +.tooltip { + --#{$prefix}tooltip-color: var(--kt-tooltip-color); + --#{$prefix}tooltip-bg: var(--kt-tooltip-bg); + --#{$prefix}tooltip-opacity: var(--kt-tooltip-opacity); + + .tooltip-inner { + box-shadow: var(--kt-tooltip-box-shadow); + } + + &.tooltop-auto-width { + .tooltip-inner { + white-space: nowrap; + max-width: none; + } + } + + // Inverse + &.tooltip-inverse { + @include tooltip-theme( + $bg-color: var(--kt-dark), + $color: var(--kt-dark-inverse), + $arrow-color: var(--kt-dark), + ); + } +} diff --git a/src/_res/assets/sass/core/components/_type.scss b/src/_res/assets/sass/core/components/_type.scss new file mode 100644 index 0000000..01819b7 --- /dev/null +++ b/src/_res/assets/sass/core/components/_type.scss @@ -0,0 +1,5 @@ + + +.blockquote-footer { + color: var(--kt-blockquote-footer-color); +} diff --git a/src/_res/assets/sass/core/components/_utilities.scss b/src/_res/assets/sass/core/components/_utilities.scss new file mode 100644 index 0000000..0874a6c --- /dev/null +++ b/src/_res/assets/sass/core/components/_utilities.scss @@ -0,0 +1,125 @@ +// +// Custom utilities +// + +$utilities: map-merge( + $utilities, + ( + "position": ( + property: position, + responsive: true, + values: static relative absolute fixed sticky + ), + "opacity": ( + property: opacity, + class: opacity, + values: $opacity-values + ), + "opacity-hover": ( + property: opacity, + state: hover, + class: opacity, + values: $opacity-values + ), + "font-size": ( + rfs: true, + responsive: true, + property: font-size, + class: fs, + values: $font-sizes + ), + "width": ( + responsive: true, + property: width, + class: w, + values: $custom-sizes + ), + "max-width": ( + responsive: true, + property: max-width, + class: mw, + values: $custom-sizes + ), + "min-width": ( + responsive: true, + property: min-width, + class: min-w, + values: $custom-sizes + ), + "height": ( + responsive: true, + property: height, + class: h, + values: $custom-sizes + ), + "max-height": ( + responsive: true, + property: max-height, + class: mh, + values: $custom-sizes + ), + "min-height": ( + responsive: true, + property: min-height, + class: min-h, + values: $custom-sizes + ), + "z-index": ( + property: z-index, + class: z-index, + values: $zindex-values + ), + "border-top-width": ( + property: border-top-width, + class: border-top, + values: $border-widths + ), + "border-bottom-width": ( + property: border-bottom-width, + class: border-bottom, + values: $border-widths + ), + "border-right-width": ( + property: border-right-width, + class: border-right, + values: $border-widths + ), + "border-left-width": ( + property: border-left-width, + class: border-left, + values: $border-widths + ), + "line-height": ( + property: line-height, + class: lh, + values: ( + 0: 0, + 1: 1, + sm: $line-height-sm, + base: $line-height-base, + lg: $line-height-lg, + xl: $line-height-xl, + xxl: $line-height-xxl + ) + ), + "letter-spacing": ( + property: letter-spacing, + class: ls, + values: $letter-spacing-values + ), + "rounded": ( + property: border-radius, + class: rounded, + values: ( + null: $border-radius, + 0: 0, + 1: $border-radius-sm, + 2: $border-radius, + 3: $border-radius-lg, + 4: $border-radius-xl, + circle: 50%, + pill: $border-radius-pill + ) + ) + ) +); diff --git a/src/_res/assets/sass/core/components/_variables.scss b/src/_res/assets/sass/core/components/_variables.scss new file mode 100644 index 0000000..e20e542 --- /dev/null +++ b/src/_res/assets/sass/core/components/_variables.scss @@ -0,0 +1,1587 @@ +// +// Bootstrap & Custom Variables +// Safely override any variable in _variables.custom.scss +// + + +// Bootstrap color system +$white: #ffffff !default; +$black:#000000 !default; + +// Bootstrap grey colors +$gray-100: #f5f8fa !default; +$gray-200: #eff2f5 !default; +$gray-300: #E4E6EF !default; +$gray-400: #B5B5C3 !default; +$gray-500: #A1A5B7 !default; +$gray-600: #7E8299 !default; +$gray-700: #5E6278 !default; +$gray-800: #3F4254 !default; +$gray-900: #181C32 !default; + +$gray-100-dark: #1b1b29 !default; +$gray-200-dark: #2B2B40 !default; +$gray-300-dark: #323248 !default; +$gray-400-dark: #474761 !default; +$gray-500-dark: #565674 !default; +$gray-600-dark: #6D6D80 !default; +$gray-700-dark: #92929F !default; +$gray-800-dark: #CDCDDE !default; +$gray-900-dark: #FFFFFF !default; + +// Bootstrap muted color +$text-muted: $gray-500 !default; +$text-muted-dark: $gray-500-dark !default; + +// Bootstrap gray colors map +$grays: ( + "100": $gray-100, + "200": $gray-200, + "300": $gray-300, + "400": $gray-400, + "500": $gray-500, + "600": $gray-600, + "700": $gray-700, + "800": $gray-800, + "900": $gray-900 +) !default; + +$grays-dark: ( + "100": $gray-100-dark, + "200": $gray-200-dark, + "300": $gray-300-dark, + "400": $gray-400-dark, + "500": $gray-500-dark, + "600": $gray-600-dark, + "700": $gray-700-dark, + "800": $gray-800-dark, + "900": $gray-900-dark +) !default; + +// Bootstrap contextual colors +// Primary colors +$primary: #3699FF !default; +$primary-active: #187DE4 !default; +$primary-light: #F1FAFF !default; +$primary-light-dark: #212E48 !default; +$primary-inverse: $white !default; + +// Secondary colors +$secondary: $gray-300 !default; +$secondary-dark: $gray-300-dark !default; +$secondary-active: $gray-400 !default; +$secondary-active-dark: $gray-400-dark !default; +$secondary-light: $gray-100 !default; +$secondary-light-dark: $gray-100-dark !default; +$secondary-inverse: $gray-800 !default; +$secondary-inverse-dark: $gray-800-dark !default; + +// Light colors +$light: $gray-100 !default; +$light-dark: $gray-200-dark !default; +$light-active: $gray-200 !default; +$light-active-dark: $gray-300-dark !default; +$light-light: gba($gray-100, 0.75) !default; +$light-inverse: $gray-600 !default; +$light-inverse-dark: $gray-600-dark !default; + +// Success colors +$success: #1BC5BD !default; +$success-active: #0BB7AF !default; +$success-light: #C9F7F5 !default; +$success-light-dark: #1C3833 !default; +$success-inverse: $white !default; + +// Info colors +$info: #8950FC !default; +$info-active: #7337EE !default; +$info-light: #EEE5FF !default; +$info-light-dark: #2F264F !default; +$info-inverse: $white !default; + +// Warning colors +$warning: #FFA800 !default; +$warning-active: #EE9D01 !default; +$warning-light: #FFF4DE !default; +$warning-light-dark: #392F28 !default; +$warning-inverse: $white !default; + +// Danger colors +$danger: #F64E60 !default; +$danger-active: #EE2D41 !default; +$danger-light: #FFE2E5 !default; +$danger-light-dark: #3A2434 !default; +$danger-inverse: $white !default; + +// Dark colors +$dark: $gray-900 !default; +$dark-dark: $gray-900-dark !default; +$dark-active: darken($gray-900, 3%) !default; +$dark-active-dark: lighten($gray-900-dark, 3%) !default; +$dark-light: $gray-200 !default; +$dark-light-dark: $gray-200-dark !default; +$dark-inverse: $white !default; +$dark-inverse-dark: $gray-100-dark !default; + +// Contextual colors +$theme-colors: ( + "white": $white, // custom color type + "light": $light, + "primary": $primary, + "secondary": $secondary, + "success": $success, + "info": $info, + "warning": $warning, + "danger": $danger, + "dark": $dark +) !default; + +$theme-colors-dark: ( + "dark": $dark-dark, + "light": $light-dark, + "secondary": $secondary-dark, +) !default; + +// Contextual active state colors +$theme-active-colors: ( + "primary": $primary-active, + "secondary": $secondary-active, + "light": $light-active, + "success": $success-active, + "info": $info-active, + "warning": $warning-active, + "danger": $danger-active, + "dark": $dark-active +) !default; + +$theme-active-colors-dark: ( + "dark": $dark-active-dark, + "light": $light-active-dark, + "secondary": $secondary-active-dark, +) !default; + +// Contextual inverse state colors +$theme-inverse-colors: ( + "primary": $primary-inverse, + "secondary": $secondary-inverse, + "light": $light-inverse, + "success": $success-inverse, + "info": $info-inverse, + "warning": $warning-inverse, + "danger": $danger-inverse, + "dark": $dark-inverse +) !default; + +$theme-inverse-colors-dark: ( + "dark": $dark-inverse-dark, + "light": $light-inverse-dark, + "secondary": $secondary-inverse-dark, +) !default; + +// Contextual light state colors +$theme-light-colors: ( + "primary": $primary-light, + "secondary": $secondary-light, + "success": $success-light, + "info": $info-light, + "warning": $warning-light, + "danger": $danger-light, + "dark": $dark-light +) !default; + +$theme-light-colors-dark: ( + "primary": $primary-light-dark, + "success": $success-light-dark, + "info": $info-light-dark, + "warning": $warning-light-dark, + "danger": $danger-light-dark, + "dark": $dark-light-dark, + "secondary": $secondary-light-dark +) !default; + +// Text colors +$theme-text-colors: ( + "white": $white, + "primary": $primary, + "secondary": $secondary, + "light": $light, + "success": $success, + "info": $info, + "warning": $warning, + "danger": $danger, + "dark": $dark, + "muted": $text-muted, + "gray-100": $gray-100, + "gray-200": $gray-200, + "gray-300": $gray-300, + "gray-400": $gray-400, + "gray-500": $gray-500, + "gray-600": $gray-600, + "gray-700": $gray-700, + "gray-800": $gray-800, + "gray-900": $gray-900 +) !default; + +$theme-text-colors-dark: ( + "dark": $dark-dark, + "muted": $text-muted-dark, + "secondary": $secondary-dark, + "gray-100": $gray-100-dark, + "gray-200": $gray-200-dark, + "gray-300": $gray-300-dark, + "gray-400": $gray-400-dark, + "gray-500": $gray-500-dark, + "gray-600": $gray-600-dark, + "gray-700": $gray-700-dark, + "gray-800": $gray-800-dark, + "gray-900": $gray-900-dark +) !default; + + +// Options +// +// Quickly modify global styling by enabling or disabling optional features. +$enable-rounded: true !default; +$enable-shadows: true !default; +$enable-negative-margins: true !default; +$enable-smooth-scroll: false !default; + +// Spacing +// +// Control the default styling of most Bootstrap elements by modifying these +// variables. Mostly focused on spacing. +// You can add more entries to the $spacers map, should you need more variation. +$spacer: 1rem !default; + +$spacers: ( + 0: 0, + 1: ($spacer * .25), // 3.5px + 2: ($spacer * .5), // 7px; + 3: ($spacer * .75), // 10.5px + 4: ($spacer * 1), // 14px + 5: ($spacer * 1.25), // 17.5px + 6: ($spacer * 1.5), // 21px + 7: ($spacer * 1.75), // 24.5px + 8: ($spacer * 2), // 28px + 9: ($spacer * 2.25), // 31.5px + 10: ($spacer * 2.5), // 35px + 11: ($spacer * 2.75), // 38.5px + 12: ($spacer * 3), // 42px + 13: ($spacer * 3.25), // 45.5px + 14: ($spacer * 3.5), // 49px + 15: ($spacer * 3.75), // 52.5px + 16: ($spacer * 4), // 55px + 17: ($spacer * 4.25), // 58.5px + 18: ($spacer * 4.5), // 62px + 19: ($spacer * 4.75), // 65.5px + 20: ($spacer * 5), // 69px +); + + +// Position +// +// Define the edge positioning anchors of the position utilities. +$position-values: ( + 0: 0, + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100% +) !default; + + +// Body +// +// Settings for the `` element. +$body-bg: $white !default; +$body-bg-rgb: to-rgb($body-bg) !default; +$body-bg-dark: #1e1e2d !default; +$body-bg-rgb-dark: to-rgb($body-bg-dark) !default; +$body-color: $gray-900 !default; +$body-color-dark: $gray-900-dark !default; +$body-text-align: null !default; + + +// Links +// +// Style anchor elements. +$link-color: $primary !default; +$link-color-dark: $primary !default; +$link-decoration: none !default; +$link-shade-percentage: 20% !default; +$link-hover-color: $primary-active !default; +$link-hover-color-dark: $primary-active !default; +$link-hover-decoration: none !default; + + +// Paragraphs +// +// Style p element. +$paragraph-margin-bottom: 1rem !default; + + +// Grid breakpoints +// +// Define the minimum dimensions at which your layout will change, +// adapting to different screen sizes, for use in media queries. +// scss-docs-start grid-breakpoints +$grid-breakpoints: ( + xs: 0, + sm: 576px, + md: 768px, + lg: 992px, + xl: 1200px, + xxl: 1400px +) !default; +// scss-docs-end grid-breakpoints + + +// Grid containers +// +// Define the maximum width of `.container` for different screen sizes. +$container-max-widths: ( + sm: 540px, + md: 720px, + lg: 960px, + xl: 1140px, + xxl: 1320px +) !default; + + +// Components +// +// Define common padding and border radius sizes and more. +$border-width: 1px !default; +$border-color: $gray-200 !default; +$border-color-dark: $gray-200-dark !default; +$border-dashed-color: $gray-300 !default; +$border-dashed-color-dark: $gray-300-dark !default; + +$border-widths: ( + 0: 0, + 1: 1px, + 2: 2px, + 3: 3px, + 4: 4px, + 5: 5px +) !default; + +// Border Radiues +$border-radius: .475rem !default; +$border-radius-sm: .425rem !default; +$border-radius-lg: .625rem !default; +$border-radius-xl: 1rem !default; +$border-radius-2xl: 2rem !default; +$border-radius-pill: 50rem !default; + +// Keenthemes hover states +$component-hover-color: $primary !default; +$component-hover-color-dark: $primary !default; +$component-hover-bg: #F4F6FA !default; +$component-hover-bg-dark: $gray-200-dark !default; + +// Keenthemes active states +$component-active-color: $primary-inverse !default; +$component-active-color-dark: $primary-inverse !default; +$component-active-bg: $primary !default; +$component-active-bg-dark: $primary !default; + +// Keenthemes checked states +$component-checked-color: $primary-inverse !default; +$component-checked-color-dark: $primary-inverse !default; +$component-checked-bg: $primary !default; +$component-checked-bg-dark: $primary !default; + +// Keenthemes custom transition settings +$transition-link: color .2s ease !default; +$transition-input: color .2s ease !default; + +// Box shadow +$box-shadow-xs: 0 .1rem 0.75rem 0.25rem rgba($black, 0.05) !default; +$box-shadow-xs-dark: 0 .1rem 0.75rem 0.25rem rgba($black, 0.05) !default; +$box-shadow-sm: 0 .1rem 1rem 0.25rem rgba($black, .05) !default; +$box-shadow-sm-dark: 0 .1rem 1rem 0.25rem rgba($black, .05) !default; +$box-shadow: 0 .5rem 1.5rem 0.5rem rgba($black, .075) !default; +$box-shadow-dark: 0 .5rem 1.5rem 0.5rem rgba($black, .075) !default; +$box-shadow-lg: 0 1rem 2rem 1rem rgba($black, .1) !default; +$box-shadow-lg-dark: 0 1rem 2rem 1rem rgba($black, .1) !default; +$box-shadow-inset: inset 0 1px 2px rgba($black, .075) !default; +$box-shadow-inset-dark: inset 0 1px 2px rgba($black, .075) !default; + +// Keenthemes custom gutter sizes +$gutters: ( + 0: 0rem, + 1: ($spacer * .25), // 3.5px + 2: ($spacer * .5), // 7px; + 3: ($spacer * .75), // 10.5px + 4: ($spacer * 1), // 14px + 5: ($spacer * 1.25), // 17.5px + 6: ($spacer * 1.5), // 21px + 7: ($spacer * 1.75), // 24.5px + 8: ($spacer * 2), // 28px + 9: ($spacer * 2.25), // 31.5px + 10: ($spacer * 2.5), // 35px +) !default; + + +// Typography +// +// Font, line-height, and color for body text, headings, and more. +// Font family +$font-family-sans-serif: Inter, Helvetica, "sans-serif" !default; + +$font-size-base: 1rem !default; // Assumes the browser default, typically `13px` +$font-size-lg: $font-size-base * 1.075 !default; // 14.04px +$font-size-sm: $font-size-base * .925 !default; // 12.025px + +$font-weight-lighter: lighter !default; +$font-weight-light: 300 !default; +$font-weight-normal: 400 !default; +$font-weight-semibold: 500 !default; +$font-weight-bold: 600 !default; +$font-weight-bolder: 700 !default; + +$font-weight-base: $font-weight-normal !default; + +// Line heights +$line-height-base: 1.5 !default; +$line-height-sm: 1.25 !default; +$line-height-lg: 1.75 !default; + +// Keenthemes custom line heights +$line-height-xl: 2 !default; +$line-height-xxl: 2.25 !default; + +// Heading sizes +$h1-font-size: $font-size-base * 1.75 !default; // 22.75px +$h2-font-size: $font-size-base * 1.5 !default; // 19.50px +$h3-font-size: $font-size-base * 1.35 !default; // 17.55px +$h4-font-size: $font-size-base * 1.25 !default; // 16.25px +$h5-font-size: $font-size-base * 1.15 !default; // 14.95px +$h6-font-size: $font-size-base * 1.075 !default; // 13.97px + +// Font Sizes +$font-sizes: ( + 1: $h1-font-size, // 22.75px + 2: $h2-font-size, // 19.50px + 3: $h3-font-size, // 17.55px + 4: $h4-font-size, // 16.25px + 5: $h5-font-size, // 14.95px + 6: $h6-font-size, // 13.95px + + 7: $font-size-base * 0.95, // 12.35px + 8: $font-size-base * 0.85, // 11.05px + 9: $font-size-base * 0.75, // 9.75px + 10: $font-size-base * 0.5, // 6.50px + + base: $font-size-base, // 13px + fluid: 100%, // 100% + + 2x: $font-size-base * 2, // 26px + 2qx: $font-size-base * 2.25, // 29.25px + 2hx: $font-size-base * 2.5, // 32.5px + 2tx: $font-size-base * 2.75, // 35.75px + + 3x: $font-size-base * 3, // 39px + 3qx: $font-size-base * 3.25, // 42.25px + 3hx: $font-size-base * 3.5, // 45.5px + 3tx: $font-size-base * 3.75, // 48.75px + + 4x: $font-size-base * 4, // 52px + 4qx: $font-size-base * 4.25, // 55.25px + 4hx: $font-size-base * 4.5, // 58.5px + 4tx: $font-size-base * 4.75, // 61.75px + + 5x: $font-size-base * 5, // 65px + 5qx: $font-size-base * 5.25, // 68.25px + 5hx: $font-size-base * 5.5, // 71.5px + 5tx: $font-size-base * 5.75 // 74.75px +) !default; + +$headings-font-weight: 600 !default; +$headings-color: $gray-900 !default; +$headings-color-dark: $gray-900-dark !default; +$headings-line-height: 1.2 !default; + +$display-font-sizes: ( + 1: 5rem, + 2: 4.5rem, + 3: 4rem, + 4: 3.5rem, + 5: 3rem, + 6: 2.5rem +) !default; + +$display-font-weight: $font-weight-bolder !default; +$display-line-height: $headings-line-height !default; + +$blockquote-footer-color: $gray-600 !default; +$blockquote-footer-color: $gray-600-dark !default; + + +// Tables +// +// Customizes the `.table` component with basic values, each used across all table variations. + +$table-cell-padding-y: .75rem !default; +$table-cell-padding-x: .75rem !default; +$table-cell-padding-y-sm: .5rem !default; +$table-cell-padding-x-sm: .5rem !default; + +$table-color: $body-color !default; +$table-color-dark: $body-color-dark !default; +$table-bg: transparent !default; +$table-bg-dark: transparent !default; +$table-accent-bg: transparent !default; +$table-accent-bg-dark: transparent !default; +$table-striped-color: $table-color !default; +$table-striped-color-dark: $table-color-dark !default; +$table-striped-bg: rgba($gray-100, 0.75) !default; +$table-striped-bg-dark: rgba($gray-100-dark, 0.75) !default; + +$table-active-color: $table-color !default; +$table-active-color-dark: $table-color-dark !default; +$table-active-bg: $gray-100 !default; +$table-active-bg-dark: $gray-100-dark !default; + +$table-hover-color: $table-color !default; +$table-hover-color-dark: $table-color-dark !default; +$table-hover-bg: $gray-100 !default; +$table-hover-bg-dark: $gray-100-dark !default; + +$table-border-factor: .1 !default; +$table-border-width: $border-width !default; +$table-border-color: $border-color !default; +$table-border-color-dark: $border-color-dark !default; + +$table-caption-color: $text-muted !default; +$table-caption-color-dark: $text-muted-dark !default; + +$table-loading-message-box-shadow: 0px 0px 50px 0px rgba(82,63,105, 0.15) !default; +$table-loading-message-box-shadow-dark: 0px 0px 30px rgba(0, 0, 0, 0.3) !default; +$table-loading-message-bg: $body-bg !default; +$table-loading-message-bg-dark: $gray-200-dark !default; +$table-loading-message-color: $gray-700 !default; +$table-loading-message-color-dark: $gray-700-dark !default; + + +// Buttons + Forms +// +// Shared variables that are reassigned to `$input-` and `$btn-` specific variables. +$input-btn-padding-y: .775rem !default; +$input-btn-padding-x: 1rem !default; +$input-btn-font-family: null !default; +$input-btn-font-size: $font-size-base * 1.1 !default; +$input-btn-line-height: $line-height-base !default; + +$input-btn-focus-width: .25rem !default; +$input-btn-focus-color-opacity: .25 !default; +$input-btn-focus-color-opacity-dark: .25 !default; +$input-btn-focus-color: rgba($component-active-bg, $input-btn-focus-color-opacity) !default; +$input-btn-focus-color-dark: rgba($component-active-bg-dark, $input-btn-focus-color-opacity-dark) !default; +$input-btn-focus-box-shadow: null !default; +$input-btn-focus-box-shadow-dark: null !default; + +$input-btn-padding-y-sm: .55rem !default; +$input-btn-padding-x-sm: .75rem !default; +$input-btn-font-size-sm: $font-size-sm !default; + +$input-btn-padding-y-lg: .825rem !default; +$input-btn-padding-x-lg: 1.5rem !default; +$input-btn-font-size-lg: $font-size-base * 1.15 !default; + +$input-btn-border-width: $border-width !default; + +// Buttons +// +// For each of Bootstrap's buttons, define text, background, and border color. +$btn-padding-y: $input-btn-padding-y !default; +$btn-padding-x: 1.5rem !default; +$btn-font-family: $input-btn-font-family !default; +$btn-font-size: $input-btn-font-size !default; +$btn-line-height: $input-btn-line-height !default; +$btn-white-space: null !default; // Set to `nowrap` to prevent text wrapping + +$btn-padding-y-sm: $input-btn-padding-y-sm !default; +$btn-padding-x-sm: 1.25rem !default; +$btn-font-size-sm: $input-btn-font-size-sm !default; + +$btn-padding-y-lg: $input-btn-padding-y-lg !default; +$btn-padding-x-lg: 1.75rem !default; +$btn-font-size-lg: $input-btn-font-size-lg !default; + +$btn-border-width: $input-btn-border-width !default; + +$btn-font-weight: $font-weight-semibold !default; +$btn-box-shadow: null !default; +$btn-box-shadow-dark: null !default; +$btn-focus-width: $input-btn-focus-width !default; +$btn-focus-box-shadow: null !default; +$btn-focus-box-shadow-dark: null !default; +$btn-disabled-opacity: .65 !default; +$btn-disabled-opacity-dark: .65 !default; +$btn-active-box-shadow: null !default; +$btn-active-box-shadow-dark: null !default; + +$btn-link-color: $link-color !default; +$btn-link-color-dark: $link-color !default; +$btn-link-hover-color: $link-hover-color !default; +$btn-link-hover-color-dark: $link-hover-color !default; +$btn-link-disabled-color: $gray-600 !default; +$btn-link-disabled-color-dark: $gray-600-dark !default; + +// Allows for customizing button radius independently from global border radius +$btn-border-radius: $border-radius !default; +$btn-border-radius-sm: $border-radius-sm !default; +$btn-border-radius-lg: $border-radius-lg !default; + + +// Forms +$form-text-margin-top: .5rem !default; +$form-text-font-size: $font-size-sm !default; +$form-text-color: $text-muted !default; +$form-text-color-dark: $text-muted-dark !default; + +$form-label-margin-bottom: .5rem !default; +$form-label-font-size: 1.05rem !default; +$form-label-font-weight: 500 !default; +$form-label-color: $gray-800 !default; +$form-label-color-dark: $gray-800-dark !default; + +$input-padding-y: $input-btn-padding-y !default; +$input-padding-x: $input-btn-padding-x !default; +$input-font-family: $input-btn-font-family !default; +$input-font-size: $input-btn-font-size !default; +$input-font-weight: $font-weight-semibold !default; +$input-line-height: $input-btn-line-height !default; + +$input-bg: $body-bg !default; +$input-bg-dark: $body-bg-dark !default; + +$input-border-width: $input-btn-border-width !default; +$input-color: $gray-700 !default; +$input-color-dark: $gray-700-dark !default; +$input-border-color: $gray-300 !default; +$input-border-color-dark: $gray-300-dark !default; +//$input-box-shadow: none !default; +//$input-box-shadow-dark: none !default; + +$input-border-radius: $btn-border-radius !default; +$input-border-radius-sm: $btn-border-radius-sm !default; +$input-border-radius-lg: $btn-border-radius-lg !default; + +$input-focus-bg: $input-bg !default; +$input-focus-bg-dark: $input-bg-dark !default; +$input-focus-border-color: $gray-400 !default; +$input-focus-border-color-dark: $gray-400-dark !default; +$input-btn-focus-width: .25rem !default; +$input-focus-color: $input-color !default; +$input-focus-color-dark: $input-color-dark !default; +$input-focus-width: $input-btn-focus-width !default; +//$input-focus-box-shadow: none !default; +//$input-focus-box-shadow-dark: none !default; + +$input-disabled-color: null !default; +$input-disabled-color-dark: null !default; +$input-disabled-bg: $gray-200 !default; +$input-disabled-bg-dark: $gray-200-dark !default; +$input-disabled-border-color: $input-border-color !default; +$input-disabled-border-color-dark: $input-border-color-dark !default; + +$input-placeholder-color: $gray-500 !default; +$input-placeholder-color-dark: $gray-500-dark !default; +$input-plaintext-color: $gray-700 !default; +$input-plaintext-color-dark: $gray-700-dark !default; + +// Keenthemes solid input style +$input-solid-bg: $gray-100 !default; +$input-solid-bg-dark: $gray-100-dark !default; +$input-solid-bg-focus: darken($gray-100, 2%) !default; +$input-solid-bg-focus-dark: lighten($gray-100-dark, 2%) !default; +$input-solid-placeholder-color: $input-placeholder-color !default; +$input-solid-placeholder-color-dark: $input-placeholder-color-dark !default; +$input-solid-color: $gray-700 !default; +$input-solid-color-dark: $gray-700-dark !default; + +// Form checks +$form-check-input-width: 1.75rem !default; +$form-check-input-width-sm: 1.55rem !default; +$form-check-input-width-lg: 2.25rem !default; +$form-check-input-bg-size: 60% 60% !default; +$form-check-min-height: $font-size-base * $line-height-base !default; +$form-check-padding-start: $form-check-input-width + .5rem !default; +$form-check-padding-left: $form-check-input-width + .5rem !default; +$form-check-margin-bottom: .125rem !default; +$form-check-label-color: $gray-500 !default; +$form-check-label-color-dark: $gray-500-dark !default; +$form-check-label-color-checked: $gray-700 !default; +$form-check-label-color-checked-dark: $gray-700-dark !default; +$form-check-label-cursor: null !default; +$form-check-transition: null !default; +$form-check-inline-margin-right: 1rem !default; + +$form-check-input-active-filter: brightness(90%) !default; +$form-check-input-active-filter-dark: brightness(90%) !default; + +$form-check-input-bg: transparent !default; +$form-check-input-bg-dark: transparent !default; +$form-check-input-bg-solid: $gray-200 !default; +$form-check-input-bg-solid-dark: $gray-200-dark !default; +$form-check-input-bg-solid: $gray-200 !default; +$form-check-input-bg-solid-dark: $gray-200-dark !default; +$form-check-input-border: 1px solid $input-border-color !default; +$form-check-input-border-dark: 1px solid $input-border-color-dark !default; +$form-check-input-border-radius: .45em !default; +$form-check-radio-border-radius: 50% !default; +$form-check-input-focus-border: $input-focus-border-color !default; +$form-check-input-focus-border-dark: $input-focus-border-color-dark !default; +$form-check-input-focus-box-shadow: none !default; +$form-check-input-focus-box-shadow-dark: none !default; + +$form-check-input-checked-color: $component-checked-color !default; +$form-check-input-checked-color-dark: $component-checked-color-dark !default; +$form-check-input-checked-bg-color: $component-checked-bg !default; +$form-check-input-checked-bg-color-solid: $component-checked-bg !default; +$form-check-input-checked-bg-color-dark: $component-checked-bg-dark !default; +$form-check-input-checked-bg-color-solid-dark: $component-checked-bg-dark !default; +$form-check-input-checked-border-color: $component-checked-bg !default; +$form-check-input-checked-border-color-dark: $component-checked-bg-dark !default; +$form-check-input-checked-bg-image: url("data:image/svg+xml,") !default; +$form-check-input-checked-bg-image-dark: url("data:image/svg+xml,") !default; +$form-check-radio-checked-bg-image: url("data:image/svg+xml,") !default; +$form-check-radio-checked-bg-image-dark: url("data:image/svg+xml,") !default; + +$form-check-input-indeterminate-color: $component-checked-color !default; +$form-check-input-indeterminate-color-dark: $component-checked-color-dark !default; +$form-check-input-indeterminate-bg-color: $component-checked-bg !default; +$form-check-input-indeterminate-bg-color-dark: $component-checked-bg-dark !default; +$form-check-input-indeterminate-border-color: $component-checked-bg !default; +$form-check-input-indeterminate-border-color-dark: $component-checked-bg-dark !default; +$form-check-input-indeterminate-bg-image: url("data:image/svg+xml,") !default; +$form-check-input-indeterminate-bg-image-dark: url("data:image/svg+xml,") !default; + +$form-check-input-disabled-opacity: .5 !default; +$form-check-input-disabled-opacity-dark: .5 !default; +$form-check-label-disabled-opacity: $form-check-input-disabled-opacity !default; +$form-check-label-disabled-opacity-dark: $form-check-input-disabled-opacity-dark !default; +$form-check-btn-check-disabled-opacity: $btn-disabled-opacity !default; +$form-check-btn-check-disabled-opacity-dark: $btn-disabled-opacity-dark !default; + +$form-switch-color: rgba(0, 0, 0, .25) !default; +$form-switch-color-dark: rgba(255, 255, 255, .25) !default; +$form-switch-color-solid: $white !default; +$form-switch-color-solid-dark: $gray-500 !default; +$form-switch-width: 3.25rem !default; +$form-switch-height: 2.25rem !default; +$form-switch-width-sm: 2.5rem !default; +$form-switch-height-sm: 1.5rem !default; +$form-switch-width-lg: 3.75rem !default; +$form-switch-height-lg: 2.75rem !default; + +$form-switch-padding-start: $form-switch-width + .5rem !default; +$form-switch-padding-left: $form-switch-width + .5rem !default; +$form-switch-bg-image: url("data:image/svg+xml,") !default; +$form-switch-bg-image-dark: url("data:image/svg+xml,") !default; +$form-switch-bg-image-solid: url("data:image/svg+xml,") !default; +$form-switch-bg-image-solid-dark: url("data:image/svg+xml,") !default; +$form-switch-border-radius: $form-switch-width !default; + +$form-switch-focus-color: $input-focus-border-color !default; +$form-switch-focus-color-dark: $input-focus-border-color-dark !default; +$form-switch-focus-bg-image: url("data:image/svg+xml,") !default; +$form-switch-focus-bg-image-dark: url("data:image/svg+xml,") !default; + +$form-switch-checked-color: $component-checked-color !default; +$form-switch-checked-color-dark: $component-checked-color-dark !default; +$form-switch-checked-bg-image: url("data:image/svg+xml,") !default; +$form-switch-checked-bg-image-dark: url("data:image/svg+xml,") !default; +$form-switch-checked-bg-position: right center !default; + + +// Input groups +$input-group-addon-bg: $gray-100 !default; +$input-group-addon-bg-dark: $gray-100-dark !default; +$input-group-addon-color: $gray-700 !default; +$input-group-addon-color-dark: $gray-700-dark !default; +$input-group-addon-border-color: $input-border-color !default; +$input-group-addon-border-color-dark: $input-border-color-dark !default; + + +// Form select +$form-select-color: $input-color !default; +$form-select-color-dark: $input-color-dark !default; +$form-select-bg: $input-bg !default; +$form-select-bg-dark: $input-bg-dark !default; +$form-select-disabled-color: null !default; +$form-select-disabled-color-dark: null !default; +$form-select-disabled-bg: $gray-200 !default; +$form-select-disabled-bg-dark: $gray-200-dark !default; +$form-select-disabled-border-color: $input-disabled-border-color !default; +$form-select-disabled-border-color-dark: $input-disabled-border-color-dark !default; +$form-select-indicator-color: $gray-600 !default; +$form-select-indicator-color-dark: $gray-600-dark !default; +$form-select-indicator: url("data:image/svg+xml,") !default; +$form-select-indicator-dark: url("data:image/svg+xml,") !default; +$form-select-border-color: $input-border-color !default; +$form-select-border-color-dark: $input-border-color-dark !default; +$form-select-box-shadow: $box-shadow-inset !default; +$form-select-box-shadow-dark: $box-shadow-inset-dark !default; +$form-select-focus-border-color: $input-focus-border-color !default; +$form-select-focus-border-color-dark: $input-focus-border-color-dark !default; +$form-select-focus-width: $input-focus-width !default; +$form-select-focus-box-shadow: 0 0 0 $form-select-focus-width $input-btn-focus-color !default; +$form-select-focus-box-shadow-dark: 0 0 0 $form-select-focus-width $input-btn-focus-color-dark !default; + + +// Form range +$form-range-track-border-radius: $border-radius !default; +$form-range-track-bg: var(--kt-gray-300) !default; +$form-range-thumb-disabled-bg: var(--kt-gray-500) !default; + + +// Form file button +$form-file-button-color: $input-color !default; +$form-file-button-color-dark: $input-color-dark !default; +$form-file-button-bg: $input-group-addon-bg !default; +$form-file-button-bg-dark: $input-group-addon-bg-dark !default; +$form-file-button-hover-bg: shade-color($form-file-button-bg, 5%) !default; +$form-file-button-hover-bg-dark: shade-color($form-file-button-bg-dark, 5%) !default; + + +// Form floating +$input-height-border: $input-border-width * 2 !default; +$form-floating-height: calc(3.75rem + #{$input-height-border}) !default; +$form-floating-input-padding-t: 1.85rem !default; + + +// Navs +$nav-link-transition: color .15s ease-in-out !default; + +$nav-tabs-border-color: $border-color !default; +$nav-tabs-border-color-dark: $border-color-dark !default; +$nav-tabs-border-width: $border-width !default; +$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default; +$nav-tabs-link-hover-border-color-dark: $gray-200-dark $gray-200-dark $nav-tabs-border-color-dark !default; +$nav-tabs-link-active-color: $gray-700 !default; +$nav-tabs-link-active-color-dark: $gray-700-dark !default; +$nav-tabs-link-active-bg: $body-bg !default; +$nav-tabs-link-active-bg-dark: $body-bg-dark !default; +$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default; +$nav-tabs-link-active-border-color-dark: $gray-300-dark $gray-300-dark $nav-tabs-link-active-bg-dark !default; + +$nav-pills-link-active-color: $component-active-color !default; +$nav-pills-link-active-color-dark: $component-active-color-dark !default; +$nav-pills-link-active-bg: $component-active-bg !default; +$nav-pills-link-active-bg-dark: $component-active-bg-dark !default; + + +// Dropdowns +// Dropdown menu container and contents. +$dropdown-color: $body-color !default; +$dropdown-color-dark: $body-color-dark !default; +$dropdown-bg: $body-bg !default; +$dropdown-bg-dark: $body-bg-dark !default; +$dropdown-divider-bg: $gray-100 !default; +$dropdown-divider-bg-dark: $gray-100-dark !default; +$dropdown-box-shadow: 0px 0px 50px 0px rgba(82,63,105, 0.15) !default; +$dropdown-box-shadow-dark: 0px 0px 30px rgba(0, 0, 0, 0.3) !default; +$dropdown-border-radius: $border-radius !default; +$dropdown-border-width: 0 !default; +$dropdown-link-color: $gray-900 !default; +$dropdown-link-color-dark: $gray-900-dark !default; +$dropdown-link-hover-color: shade-color($dropdown-link-color, 10%) !default; +$dropdown-link-hover-color-dark: shade-color($dropdown-link-color-dark, 10%) !default; +$dropdown-link-hover-bg: $gray-200 !default; +$dropdown-link-hover-bg-dark: $gray-200-dark !default; +$dropdown-link-active-color: $component-active-color !default; +$dropdown-link-active-color-dark: $component-active-color-dark !default; +$dropdown-link-active-bg: $component-active-bg !default; +$dropdown-link-active-bg-dark: $component-active-bg-dark !default; +$dropdown-link-disabled-color: $gray-500 !default; +$dropdown-link-disabled-color-dark: $gray-500-dark !default; +$dropdown-header-color: $gray-600 !default; +$dropdown-header-color-dark: $gray-600-dark !default; + + +// Pagination +$pagination-item-height: 2.5rem !default; +$pagination-item-bg: $body-bg !default; +$pagination-item-bg-dark: $body-bg-dark !default; +$pagination-item-space: 0.5rem !default; +$pagination-item-space-tablet-and-mobile: 0.25rem !default; +$pagination-font-weight: $font-weight-semibold !default; +$pagination-font-size: $font-size-lg !default; +$pagination-icon-font-size: 0.85rem !default; +$pagination-icon-height: $pagination-item-height * 0.35 !default; + +$pagination-padding-y: .375rem !default; +$pagination-padding-x: .75rem !default; +$pagination-padding-y-sm: .25rem !default; +$pagination-padding-x-sm: .5rem !default; +$pagination-padding-y-lg: .75rem !default; +$pagination-padding-x-lg: 1.5rem !default; + +$pagination-color: $gray-700 !default; +$pagination-color-dark: $gray-700-dark !default; +$pagination-bg: transparent !default; +$pagination-bg-dark: transparent !default; +$pagination-border-width: 0 !default; +$pagination-border-radius: $btn-border-radius !default; +$pagination-margin-left: 0 !default; +$pagination-border-color: transparent !default; +$pagination-border-color-dark: transparent !default; + +$pagination-focus-color: $component-hover-color !default; +$pagination-focus-color-dark: $component-hover-color-dark !default; +$pagination-focus-bg: $component-hover-bg !default; +$pagination-focus-bg-dark: $component-hover-bg-dark !default; +$pagination-focus-box-shadow: none !default; +$pagination-focus-box-shadow-dark: none !default; +$pagination-focus-outline: 0 !default; +$pagination-focus-outline-dark: 0 !default; + +$pagination-hover-color: $component-hover-color !default; +$pagination-hover-color-dark: $component-hover-color-dark !default; +$pagination-hover-bg: $component-hover-bg !default; +$pagination-hover-bg-dark: $component-hover-bg-dark !default; +$pagination-hover-border-color: transparent !default; +$pagination-hover-border-color-dark: transparent !default; + +$pagination-active-color: $component-active-color !default; +$pagination-active-color-dark: $component-active-color-dark !default; +$pagination-active-bg: $component-active-bg !default; +$pagination-active-bg-dark: $component-active-bg-dark !default; +$pagination-active-border-color: transparent !default; +$pagination-active-border-color-dark: transparent !default; + +$pagination-disabled-color: $gray-400 !default; +$pagination-disabled-color-dark: $gray-400-dark !default; +$pagination-disabled-bg: transparent !default; +$pagination-disabled-bg-dark: transparent !default; +$pagination-disabled-border-color: transparent !default; +$pagination-disabled-border-color-dark: transparent !default; + + +// Card +$card-bg: $body-bg !default; +$card-bg-dark: $body-bg-dark !default; +$card-box-shadow: 0px 0px 20px 0px rgba(76,87,125,0.02) !default; +$card-box-shadow-dark: none !default; +$card-border-color: $border-color !default; +$card-border-color-dark: $border-color-dark !default; +$card-border-style: solid !default; +$card-border-dashed-color: $border-dashed-color !default; +$card-border-dashed-color-dark: $border-dashed-color-dark !default; +$card-color: null !default; +$card-color-dark: null !default; +$card-cap-bg: transparent !default; +$card-cap-bg-dark: transparent !default; +$card-py: 2rem !default; +$card-px: 2.25rem !default; +$card-border-radius: $border-radius-lg !default; +$card-header-py: 0.5rem !default; +$card-header-height: 70px !default; +$card-border-enabled: false !default; + + +// Accordion +$accordion-color: $body-color !default; +$accordion-color-dark: $body-color-dark !default; +$accordion-bg: $body-bg !default; +$accordion-bg-dark: $body-bg-dark !default; +$accordion-padding-y: 1.5rem !default; +$accordion-padding-x: 1.5rem !default; +$accordion-border-color: $border-color !default; +$accordion-border-color-dark: $border-color-dark !default; +$accordion-border-radius: $border-radius !default; +$accordion-button-color: $accordion-color !default; +$accordion-button-color-dark: $accordion-color-dark !default; +$accordion-button-bg: $accordion-bg !default; +$accordion-button-bg-dark: $accordion-bg-dark !default; +$accordion-button-active-bg: $gray-100 !default; +$accordion-button-active-bg-dark: $gray-100-dark !default; +$accordion-button-active-color: $primary !default; +$accordion-button-active-color-dark: $primary !default; + +$accordion-button-focus-border-color: $border-color !default; +$accordion-button-focus-border-color-dark: $border-color-dark !default; +$accordion-button-focus-box-shadow: none !default; +$accordion-button-focus-box-shadow-dark: none !default; + +$accordion-icon-width: 1.15rem !default; +$accordion-icon-color: $accordion-button-color !default; +$accordion-icon-color-dark: $accordion-button-color-dark !default; +$accordion-icon-active-color: $accordion-button-active-color !default; +$accordion-icon-active-color-dark: $accordion-button-active-color-dark !default; +$accordion-button-icon: url("data:image/svg+xml,") !default; +$accordion-button-icon-dark: url("data:image/svg+xml,") !default; +$accordion-button-active-icon: url("data:image/svg+xml,") !default; +$accordion-button-active-icon-dark: url("data:image/svg+xml,") !default; + + +// Tooltips +$tooltip-font-size: $font-size-sm !default; +$tooltip-max-width: 200px !default; +$tooltip-color: $gray-800 !default; +$tooltip-color-dark: $gray-800-dark !default; +$tooltip-bg: $body-bg !default; +$tooltip-bg-dark: $gray-200-dark !default; +$tooltip-border-radius: $btn-border-radius !default; +$tooltip-opacity: 1 !default; +$tooltip-opacity-dark: 1 !default; +$tooltip-box-shadow: $dropdown-box-shadow !default; +$tooltip-box-shadow-dark: $dropdown-box-shadow-dark !default; +$tooltip-padding-y: .75rem !default; +$tooltip-padding-x: 1rem !default; +$tooltip-margin: 0 !default; + + +// Popovers +$popover-bg: $body-bg !default; +$popover-bg-dark: $gray-200-dark !default; +$popover-font-size: $font-size-base !default; +$popover-border-color: $popover-bg !default; +$popover-border-color-dark: $popover-bg-dark !default; +$popover-border-radius: $border-radius !default; +$popover-box-shadow: $dropdown-box-shadow !default; +$popover-box-shadow-dark: $dropdown-box-shadow-dark !default; +$popover-header-bg: $popover-bg !default; +$popover-header-bg-dark: $popover-bg-dark !default; +$popover-header-color: $gray-800 !default; +$popover-header-color-dark: $gray-800-dark !default; +$popover-header-font-weight: 500 !default; +$popover-header-font-size: 1rem !default; +$popover-header-padding-y: 1rem !default; +$popover-header-padding-x: 1.25rem !default; +$popover-header-border-color: $gray-200 !default; +$popover-header-border-color-dark: $gray-300-dark !default; +$popover-body-color: $gray-800 !default; +$popover-body-color-dark: $gray-800-dark !default; +$popover-body-padding-y: 1.25rem !default; +$popover-body-padding-x: 1.25rem !default; + +$popover-dissmis-btn-height: 1.5rem !default; +$popover-dissmis-btn-top: 0.85rem !default; +$popover-dissmis-btn-end: 0.85rem !default; + + +// Toasts +$toast-color: null !default; +$toast-color-dark: null !default; +$toast-background-color: rgba($white, .85) !default; +$toast-background-color-dark: rgba($black, .85) !default; +$toast-box-shadow: $box-shadow !default; +$toast-box-shadow-dark: $box-shadow-dark !default; +$toast-header-color: $gray-600 !default; +$toast-header-color-dark: $gray-600-dark !default; +$toast-header-background-color: rgba($white, .85) !default; +$toast-header-background-color-dark: rgba($black, .85) !default; +$toast-header-border-color: rgba($black, .05) !default; +$toast-header-border-color-dark: rgba($white, .05) !default; + + +// Badges +$badge-font-size: 0.85rem !default; +$badge-font-size-sm: 0.8rem !default; +$badge-font-size-lg: 1rem !default; +$badge-font-weight: $font-weight-bold !default; +$badge-color: $body-bg !default; +$badge-color-dark: $body-bg-dark !default; +$badge-padding-y: .325rem !default; +$badge-padding-x: .5rem !default; +$badge-border-radius: $border-radius-sm !default; +$badge-size: 1.75rem !default; +$badge-size-sm: 1.5rem !default; +$badge-size-lg: 2rem !default; + + +// Modals +// Padding applied to the modal body +$modal-inner-padding: 1.75rem !default; + +// Margin between elements in footer, must be lower than or equal to 2 * $modal-inner-padding +$modal-footer-margin-between: .5rem !default; + +$modal-dialog-margin: .5rem !default; +$modal-dialog-margin-y-sm-up: 1.75rem !default; + +$modal-content-color: null !default; +$modal-content-color-dark: null !default; +$modal-content-bg: $body-bg !default; +$modal-content-bg-dark: $body-bg-dark !default; +$modal-content-border-color: null !default; +$modal-content-border-color-dark: null !default; +$modal-content-border-width: 0 !default; +$modal-content-border-radius: $border-radius !default; +$modal-content-inner-border-radius: $border-radius !default; +$modal-content-box-shadow: 0 .25rem .5rem rgba($black, .05) !default; +$modal-content-box-shadow-dark: 0 .25rem .5rem rgba($white, .05) !default; +$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .1) !default; +$modal-content-box-shadow-xs-dark: 0 .25rem .5rem rgba($white, .1) !default; +$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .1) !default; +$modal-content-box-shadow-sm-up-dark: 0 .5rem 1rem rgba($white, .1) !default; + +$modal-backdrop-bg: $black !default; +$modal-backdrop-bg-dark: $black !default; +$modal-backdrop-opacity: 0.3 !default; +$modal-backdrop-opacity-dark: 0.4 !default; + +$modal-header-border-color: $border-color !default; +$modal-header-border-color-dark: $border-color-dark !default; +$modal-footer-border-color: $modal-header-border-color !default; +$modal-footer-border-color-dark: $modal-header-border-color-dark !default; +$modal-header-border-width: 1px !default; + + +// Progress bars +$progress-height: 1rem !default; +$progress-font-size: $font-size-base * .75 !default; +$progress-bg: $gray-100 !default; +$progress-bg-dark: $gray-100-dark !default; +$progress-border-radius: 6px !default; +$progress-box-shadow: none !default; +$progress-box-shadow-dark: none !default; + + +// List group +$list-group-color: $gray-900 !default; +$list-group-color-dark: $gray-900-dark !default; +$list-group-bg: $white !default; +$list-group-bg-dark: $black !default; +$list-group-border-color: rgba($black, .125) !default; +$list-group-border-color-dark: rgba($white, .125) !default; + +$list-group-hover-bg: $gray-100 !default; +$list-group-hover-bg-dark: $gray-100 !default; +$list-group-active-color: $component-active-color !default; +$list-group-active-color-dark: $component-active-color-dark !default; +$list-group-active-bg: $component-active-bg !default; +$list-group-active-bg-dark: $component-active-bg-dark !default; +$list-group-active-border-color: $list-group-active-bg !default; +$list-group-active-border-color-dark: $list-group-active-bg-dark !default; + +$list-group-disabled-color: $gray-600 !default; +$list-group-disabled-color-dark: $gray-600-dark !default; +$list-group-disabled-bg: $list-group-bg !default; +$list-group-disabled-bg-dark: $list-group-bg-dark !default; + +$list-group-action-color: $gray-700 !default; +$list-group-action-color-dark: $gray-700-dark !default; +$list-group-action-hover-color: $list-group-action-color !default; +$list-group-action-hover-color-dark: $list-group-action-color-dark !default; + +$list-group-action-active-color: $body-color !default; +$list-group-action-active-color-dark: $body-color-dark !default; +$list-group-action-active-bg: $gray-200 !default; +$list-group-action-active-bg-dark: $gray-200-dark !default; + + +// Image thumbnails +$thumbnail-bg: $body-bg !default; +$thumbnail-bg-dark: $body-bg-dark !default; +$thumbnail-border-color: $border-color !default; +$thumbnail-border-color-dark: $border-color-dark !default; +$thumbnail-box-shadow: $box-shadow-sm !default; +$thumbnail-box-shadow-dark: $box-shadow-sm-dark !default; + + +// Figures +$figure-caption-color: $gray-600 !default; +$figure-caption-color-dark: $gray-600-dark !default; + + +// Breadcrumbs +$breadcrumb-bg: null !default; +$breadcrumb-bg-dark: null !default; +$breadcrumb-divider-color: $gray-600 !default; +$breadcrumb-divider-color-dark: $gray-600-dark !default; +$breadcrumb-active-color: $primary !default; +$breadcrumb-active-color-dark: $primary !default; +$breadcrumb-item-padding-x: .5rem !default; + + +// Carousel +$carousel-custom-indicator-transition-speed: 0.3s !default; +$carousel-custom-indicator-default-bg-color: $gray-200 !default; +$carousel-custom-indicator-default-bg-color-dark: $gray-200-dark !default; +$carousel-custom-indicator-active-bg-color: $gray-400 !default; +$carousel-custom-indicator-active-bg-color-dark: $gray-400-dark !default; + +$carousel-custom-dots-indicator-default-size: 9px !default; +$carousel-custom-dots-indicator-active-size: 13px !default; + +$carousel-custom-bullet-indicator-default-size: 6px !default; +$carousel-custom-bullet-indicator-active-width: 16px !default; +$carousel-custom-bullet-indicator-default-bg-color: $gray-400 !default; +$carousel-custom-bullet-indicator-default-bg-color-dark: $gray-400-dark !default; +$carousel-custom-bullet-indicator-active-bg-color: $gray-600 !default; +$carousel-custom-bullet-indicator-active-bg-color-dark: $gray-600-dark !default; + + +// Spinners +$spinner-border-width: .185rem !default; +$spinner-animation-speed: .65s !default; +$spinner-border-width-sm: .145em !default; + + +// Close +$btn-close-width: 0.75rem !default; +$btn-close-height: $btn-close-width !default; +$btn-close-color: $black !default; +$btn-close-color-dark: $white !default; +$btn-close-bg: url("data:image/svg+xml,") !default; +$btn-close-bg-dark: url("data:image/svg+xml,") !default; +$btn-close-focus-shadow: none !default; + + +// Offcanvas +$offcanvas-border-color: $modal-content-border-color !default; +$offcanvas-border-color-dark: $modal-content-border-color-dark !default; +$offcanvas-bg-color: $modal-content-bg !default; +$offcanvas-bg-color-dark: $modal-content-bg-dark !default; +$offcanvas-color: $modal-content-color !default; +$offcanvas-color-dark: $modal-content-color-dark !default; +$offcanvas-box-shadow: $modal-content-box-shadow-xs !default; +$offcanvas-box-shadow-dark: $modal-content-box-shadow-xs-dark !default; +$offcanvas-backdrop-bg: $modal-backdrop-bg !default; +$offcanvas-backdrop-bg-dark: $modal-backdrop-bg-dark !default; +$offcanvas-backdrop-opacity: $modal-backdrop-opacity !default; +$offcanvas-backdrop-opacity-dark: $modal-backdrop-opacity-dark !default; + + +// Code +$code-bg: #F1F3F8 !default; +$code-bg-dark: $gray-200-dark !default; +$code-box-shadow: 0px 3px 9px rgba(0, 0, 0, 0.08) !default; +$code-box-shadow-dark: 0px 3px 9px rgba(0, 0, 0, 0.08) !default; +$code-padding: 0.1rem 0.4rem !default; +$code-margin: 0 0.5rem !default; +$code-font-weight: 400 !default; +$code-border-radius: 0.3rem !default; +$code-color: #b93993 !default; +$code-color-dark: #b93993 !default; +$code-space: 0.25rem !default; + +// Opacity +$opacity-values: ( + 0: 0, + 5: .05, + 10: .1, + 15: .15, + 20: .20, + 25: .25, + 50: .5, + 75: .75, + 100: 1, + ) !default; + +// Zindex +$zindex-values: ( + n1: -1, + n2: -2, + 0: 0, + 1: 1, + 2: 2, + 3: 3 +) !default; + +// Letter spacing +$letter-spacing-values: ( + 1: 0.1rem, + 2: 0.115rem, + 3: 0.125rem, + 4: 0.25rem, + 5: 0.5rem, + n1: -0.1rem, + n2: -0.115rem, + n3: -0.125rem, + n4: -0.25rem, + n5: -0.5rem, +) !default; + +// Keenthemes hight and width sizes +$custom-sizes: ( + unset: unset, + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100%, + auto: auto, + 1px: 1px, + 2px: 2px, + 3px: 3px, + 4px: 4px, + 5px: 5px, + 6px: 6px, + 7px: 7px, + 8px: 8px, + 9px: 9px, + 10px: 10px, + 15px: 15px, + 20px: 20px, + 25px: 25px, + 30px: 30px, + 35px: 35px, + 40px: 40px, + 45px: 45px, + 50px: 50px, + 55px: 55px, + 60px: 60px, + 65px: 65px, + 70px: 70px, + 75px: 75px, + 80px: 80px, + 85px: 85px, + 90px: 90px, + 95px: 95px, + 100px: 100px, + 125px: 125px, + 150px: 150px, + 175px: 175px, + 200px: 200px, + 225px: 225px, + 250px: 250px, + 275px: 275px, + 300px: 300px, + 325px: 325px, + 350px: 350px, + 375px: 375px, + 400px: 400px, + 425px: 425px, + 450px: 450px, + 475px: 475px, + 500px: 500px, + 550px: 550px, + 600px: 600px, + 650px: 650px, + 700px: 700px, + 750px: 750px, + 800px: 800px, + 850px: 850px, + 900px: 900px, + 950px: 950px, + 1000px: 1000px +) !default; + + +// Keenthemes symbol component +$symbol-sizes: ( + 20px: 20px, + 25px: 25px, + 30px: 30px, + 35px: 35px, + 40px: 40px, + 45px: 45px, + default: 50px, + 50px: 50px, + 55px: 55px, + 60px: 60px, + 65px: 65px, + 70px: 70px, + 75px: 75px, + 90px: 90px, + 100px:100px, + 125px:125px, + 150px:150px, + 160px:160px, + 175px:175px, + 200px:200px +) !default; + +$symbol-border-color: rgba($body-bg, 0.5); +$symbol-border-color-dark: rgba($body-bg, 0.5); +$symbol-label-color: $gray-800; +$symbol-label-color-dark: $gray-800-dark; +$symbol-label-bg: $gray-100; +$symbol-label-bg-dark: $gray-100-dark; + + +// Keenthemes bullet component +$bullet-bg-color: $gray-400 !default; +$bullet-bg-color-dark: $gray-400-dark !default; +$bullet-dot-size: 4px !default; +$bullet-bar-height: 4px !default; +$bullet-bar-width: 8px !default; +$bullet-bar-border-radius: 6px !default; +$bullet-line-height: 1px !default; +$bullet-line-width: 5px !default; + + +// Keenthemes scrolltop component +$scrolltop-z-index: 105 !default; +$scrolltop-opacity: 0 !default; +$scrolltop-opacity-dark: 0 !default; +$scrolltop-opacity-on: 0.3 !default; +$scrolltop-opacity-on-dark: 0.3 !default; +$scrolltop-opacity-hover: 1 !default; +$scrolltop-opacity-hover-dark: 1 !default; +$scrolltop-bottom: 40px !default; +$scrolltop-bottom-mobile: 30px !default; +$scrolltop-end: 20px !default; +$scrolltop-end-mobile: 15px !default; +$scrolltop-size: 36px !default; +$scrolltop-size-mobile: 30px !default; +$scrolltop-box-shadow: $box-shadow !default; +$scrolltop-box-shadow-dark: $box-shadow-dark !default; +$scrolltop-bg-color: $primary !default; +$scrolltop-bg-color-dark: $primary !default; +$scrolltop-bg-color-hover: $primary !default; +$scrolltop-bg-color-hover-dark: $primary !default; +$scrolltop-icon-color: $primary-inverse !default; +$scrolltop-icon-color-dark: $primary-inverse !default; +$scrolltop-icon-color-hover: $primary-inverse !default; +$scrolltop-icon-color-hover-dark: $primary-inverse !default; + + +// Keenthemes sticky toolbar component +$sticky-toolbar-z-index: 95 !default; + + +// Keenthemes drawer component +$drawer-z-index: 110 !default; +$drawer-box-shadow: 0px 1px 9px -3px rgba(0,0,0, 0.05) !default; +$drawer-box-shadow-dark: 0px 0px 30px rgba(0, 0, 0, 0.1) !default; +$drawer-bg-color: $body-bg !default; +$drawer-bg-color-dark: $body-bg-dark !default; +$drawer-transition-speed: 0.3s !default; +$drawer-overlay-bg-color: rgba($black, 0.2) !default; +$drawer-overlay-bg-color-dark: rgba($black, 0.4) !default; +$drawer-overlay-animation-speed: 0.3s !default; + +// Keenthemes menu component +$menu-dropdown-box-shadow: $dropdown-box-shadow !default; +$menu-dropdown-box-shadow-dark: $dropdown-box-shadow-dark !default; +$menu-dropdown-z-index: 107 !default; +$menu-dropdown-bg-color: $dropdown-bg !default; +$menu-dropdown-bg-color-dark: $dropdown-bg-dark !default; +$menu-dropdown-border-radius: $dropdown-border-radius !default; +$menu-dropdown-animation: true !default; +$menu-dropdown-animation-speed: 0.3s !default; +$menu-dropdown-animation-move-offset: 0.75rem !default; +$menu-accordion-indention: 1rem !default; +$menu-accordion-arrow-transition: transform 0.3s ease !default; +$menu-item-padding-y: 0.15rem !default; +$menu-item-padding-x: 0 !default; +$menu-link-padding-y: 0.65rem !default; +$menu-link-padding-x: 1rem !default; +$menu-link-border-radius: $border-radius !default; +$menu-link-color-hover: $component-hover-color !default; +$menu-link-color-hover-dark: $component-hover-color-dark !default; +$menu-link-color-show: $component-hover-color !default; +$menu-link-color-show-dark: $component-hover-color-dark !default; +$menu-link-color-here: $component-hover-color !default; +$menu-link-color-here-dark: $component-hover-color-dark !default; +$menu-link-color-active: $component-hover-color !default; +$menu-link-color-active-dark: $component-hover-color-dark !default; +$menu-link-bg-color-hover: $component-hover-bg !default; +$menu-link-bg-color-hover-dark: $component-hover-bg-dark !default; +$menu-link-bg-color-show: $component-hover-bg !default; +$menu-link-bg-color-show-dark: $component-hover-bg-dark !default; +$menu-link-bg-color-here: $component-hover-bg !default; +$menu-link-bg-color-here-dark: $component-hover-bg-dark !default; +$menu-link-bg-color-active: $component-hover-bg !default; +$menu-link-bg-color-active-dark: $component-hover-bg-dark !default; +$menu-icon-size: 2rem !default; +$menu-icon-space: 0.5rem !default; +$menu-bullet-size: 1.25rem !default; +$menu-bullet-space: 0.5rem !default; +$menu-badge-space: 0.5rem !default; +$menu-arrow-size: 9px !default; +$menu-arrow-space: 5px !default; +$menu-heading-color: $text-muted !default; +$menu-heading-color-dark: $text-muted-dark !default; + +// Keenthemes feedback component +$feedback-popup-z-index: 1000 !default; +$feedback-popup-box-shadow: $dropdown-box-shadow !default; +$feedback-popup-box-shadow-dark: $dropdown-box-shadow-dark !default; +$feedback-popup-background-color: $body-bg !default; +$feedback-popup-background-color-dark: $body-bg-dark !default; +$feedback-popup-border-radius: $border-radius !default; +$feedback-popup-transition-speed: 0.6s !default; +$feedback-popup-padding: 1rem 1.25rem !default; + +// Keenthemes scrollbar component +$scrollbar-space: 0.5rem !default; +$scrollbar-border-radius: 0.5rem !default; +$scrollbar-width: 0.4rem !default; +$scrollbar-height: 0.4rem !default; +$scrollbar-color: $gray-200 !default; +$scrollbar-color-dark: $gray-200-dark !default; +$scrollbar-hover-color: darken($gray-200, 2%) !default; +$scrollbar-hover-color-dark: darken($gray-200-dark, 2%) !default; + +// Keenthemes overlay component +$overlay-bg: rgba($black, 0.05) !default; +$overlay-bg-dark: rgba($white, 0.05) !default; + +// Keenthemes blockui component +$blockui-overlay-bg: rgba($black, 0.05) !default; +$blockui-overlay-bg-dark: rgba($white, 0.05) !default; + +// Keenthemes rating component +$rating-color-default: $gray-400 !default; +$rating-color-default-dark: $gray-400-dark !default; +$rating-color-active: #FFAD0F !default; +$rating-color-active-dark: #FFAD0F !default; + +// Keenthemes ribbon component +$ribbon-label-box-shadow: 0px -1px 5px 0px rgba($dark, 0.1) !default; +$ribbon-label-box-shadow-dark: 0px -1px 5px 0px rgba($white, 0.1) !default; +$ribbon-label-bg: $primary !default; +$ribbon-label-bg-dark: $primary !default; +$ribbon-label-border-color: darken($primary, 20%) !default; +$ribbon-label-border-color-dark: darken($primary, 20%) !default; +$ribbon-clip-bg: $dark !default; +$ribbon-clip-bg-dark: $light !default; + +// Keenthemes fixed component +$fixed-z-index: 101 !default; + +// Engage panel +$engage-btn-bg: $body-bg; +$engage-btn-bg-dark: $gray-200-dark; +$engage-btn-color: $gray-600; +$engage-btn-color-dark: $gray-600-dark; +$engage-btn-color-active: $gray-800; +$engage-btn-color-active-dark: $gray-800-dark; + +// Social Network Colors Used With Boostrap Buttons(see: https://brandcolors.net) +$social-colors: ( + facebook: ( + base: #3b5998, + inverse: #ffffff, + light: rgba(#3b5998, 0.1), + active: darken(#3b5998, 7.5%) + ), + google: ( + base: #dd4b39, + inverse: #ffffff, + light: rgba(#dd4b39, 0.1), + active: darken(#dd4b39, 7.5%) + ), + twitter: ( + base: #1da1f2, + inverse: #ffffff, + light: rgba(#1da1f2, 0.1), + active: darken(#1da1f2, 7.5%) + ), + instagram: ( + base: #e1306c, + inverse: #ffffff, + light: rgba(#e1306c, 0.1), + active: darken(#e1306c, 7.5%) + ), + youtube: ( + base: #ff0000, + inverse: #ffffff, + light: rgba(#ff0000, 0.1), + active: darken(#ff0000, 7.5%) + ), + linkedin: ( + base: #0077b5, + inverse: #ffffff, + light: rgba(#0077b5, 0.1), + active: darken(#0077b5, 7.5%) + ) +) !default; \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/buttons/_base.scss b/src/_res/assets/sass/core/components/buttons/_base.scss new file mode 100644 index 0000000..30479d7 --- /dev/null +++ b/src/_res/assets/sass/core/components/buttons/_base.scss @@ -0,0 +1,132 @@ +// +// Buttons Base +// + +// Button +.btn { + --#{$prefix}btn-color: var(--kt-body-color); + --#{$prefix}btn-bg: transparent; + --#{$prefix}btn-border-color: transparent; + + // Reset outline + outline: none !important; + + // Reset focus shadow + &:not(.btn-shadow):not(.shadow):not(.shadow-sm):not(.shadow-lg):not(.shadow-xs) { + box-shadow: none !important; + } + + // Remove border + &:not(.btn-outline):not(.btn-dashed):not(.border-hover):not(.border-active):not(.btn-flush):not(.btn-icon) { + border: 0; + padding: calc(#{$btn-padding-y} + #{$btn-border-width}) calc(#{$btn-padding-x} + #{$btn-border-width}); + + &.btn-lg { + padding: calc(#{$btn-padding-y-lg} + #{$btn-border-width}) calc(#{$btn-padding-x-lg} + #{$btn-border-width}); + } + + &.btn-sm { + padding: calc(#{$btn-padding-y-sm} + #{$btn-border-width}) calc(#{$btn-padding-x-sm} + #{$btn-border-width}); + } + } + + // Link + &.btn-link { + border: 0; + border-radius: 0; + padding-left: 0 !important; + padding-right: 0 !important; + text-decoration: none; + font-weight: $btn-font-weight; + } + + // Outline + &.btn-outline:not(.btn-outline-dashed) { + border: 1px solid var(--kt-input-border-color); + } + + // Outline dashed + &.btn-outline-dashed { + border: 1px dashed var(--kt-input-border-color); + } + + // Flush + &.btn-flush { + @include button-reset(); + } + + // Flex + &.btn-flex { + display: inline-flex; + align-items: center; + } + + // Align start + &.btn-trim-start { + justify-content: flex-start !important; + padding-left: 0 !important; + } + + // Align start + &.btn-trim-end { + justify-content: flex-end !important; + padding-right: 0 !important; + } +} + +// Icons +.btn { + // Font icon + i { + display: inline-flex; + font-size: $font-size-base; + padding-right: 0.35rem; + vertical-align: middle; + line-height: 0; + } + + // Svg icon + .svg-icon { + flex-shrink: 0; + line-height: 0; + margin-right: 0.5rem; + } + + // Icon only button + &.btn-icon { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0; + height: $input-height; + width: $input-height; + + // Remove border + &:not(.btn-outline):not(.btn-dashed):not(.border-hover):not(.border-active):not(.btn-flush) { + border: 0; + } + + // Sizes + &.btn-sm { + height: $input-height-sm; + width: $input-height-sm; + + } + + &.btn-lg { + height: $input-height-lg; + width: $input-height-lg; + } + + &.btn-circle { + border-radius: 50%; + } + + i, + .svg-icon { + padding: 0; + margin: 0; + line-height: 1; + } + } +} diff --git a/src/_res/assets/sass/core/components/buttons/_theme.scss b/src/_res/assets/sass/core/components/buttons/_theme.scss new file mode 100644 index 0000000..3f1d75a --- /dev/null +++ b/src/_res/assets/sass/core/components/buttons/_theme.scss @@ -0,0 +1,244 @@ +// +// Buttons Theme +// + +// Outline dashed basic style +.btn.btn-outline.btn-outline-dashed { + border-width: 1px; + border-style: dashed; + + $color: null; + $icon-color: null; + $border-color: null; + $bg-color: null;; + + $color-active: null; + $icon-color-active: null; + $border-color-active: var(--kt-primary); + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); +} + +// Theme colors +@each $name, $value in $theme-colors { + // Base + .btn.btn-#{$name} { + $color: var(--kt-#{$name}-inverse); + $icon-color: var(--kt-#{$name}-inverse); + $border-color: var(--kt-#{$name}); + $bg-color: var(--kt-#{$name}); + + $color-active: var(--kt-#{$name}-inverse); + $icon-color-active: var(--kt-#{$name}-inverse); + $border-color-active: var(--kt-#{$name}-active); + $bg-color-active: var(--kt-#{$name}-active); + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Light + @if ( theme-light-color($name) ) { + .btn.btn-light-#{$name} { + $color: var(--kt-#{$name}); + $icon-color: var(--kt-#{$name}); + $border-color: var(--kt-#{$name}-light); + $bg-color: var(--kt-#{$name}-light); + + $color-active: var(--kt-#{$name}-inverse); + $icon-color-active: var(--kt-#{$name}-inverse); + $border-color-active: var(--kt-#{$name}); + $bg-color-active: var(--kt-#{$name}); + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + } + + // Background + .btn.btn-bg-#{$name} { + $color: null; + $icon-color: null; + $border-color: var(--kt-#{$name}); + $bg-color: var(--kt-#{$name}); + + $color-active: null; + $icon-color-active: null; + $border-color-active: null; + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Active + .btn.btn-active-#{$name} { + $color: null; + $icon-color: null; + $border-color: null; + $bg-color: null; + + $color-active: var(--kt-#{$name}-inverse); + $icon-color-active: var(--kt-#{$name}-inverse); + $border-color-active: var(--kt-#{$name}); + $bg-color-active: var(--kt-#{$name}); + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Light + @if ( theme-light-color($name) ) { + .btn.btn-active-light-#{$name} { + $color: null; + $icon-color: null; + $border-color: null; + $bg-color: null; + + $color-active: var(--kt-#{$name}); + $icon-color-active: var(--kt-#{$name}); + $border-color-active: var(--kt-#{$name}-light); + $bg-color-active: var(--kt-#{$name}-light); + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + } + + // Outline + .btn.btn-outline.btn-outline-#{$name} { + $color: var(--kt-#{$name}); + $icon-color: var(--kt-#{$name}); + $border-color: var(--kt-#{$name}); + $bg-color: transparent; + + $color-active: var(--kt-#{$name}-active); + $icon-color-active: var(--kt-#{$name}-active); + $border-color-active: var(--kt-#{$name}); + $bg-color-active: var(--kt-#{$name}-light); + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } +} + +// Theme text colors +@each $name, $value in $theme-text-colors { + // Text and icon colors + .btn.btn-color-#{$name} { + $color: var(--kt-text-#{$name}); + $icon-color: var(--kt-text-#{$name}); + $bg-color: null; + $border-color: null; + + $color-active: null; + $icon-color-active: null; + $border-color-active: null; + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Text and icon colors active state + .btn.btn-active-color-#{$name} { + $color: null; + $icon-color: null; + $border-color: null; + $bg-color: null; + + $color-active: var(--kt-text-#{$name}); + $icon-color-active: var(--kt-text-#{$name}); + $border-color-active: null; + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Icon colors + .btn.btn-icon-#{$name} { + $color: null; + $icon-color: var(--kt-text-#{$name}); + $bg-color: null; + $border-color: null; + + $color-active: null; + $icon-color-active: null; + $border-color-active: null; + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Icon colors active state + .btn.btn-active-icon-#{$name} { + $color: null; + $icon-color: null; + $bg-color: null; + $border-color: null; + + $color-active: null; + $icon-color-active: var(--kt-text-#{$name}); + $border-color-active: null; + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Text colors + .btn.btn-text-#{$name} { + $color: var(--kt-text-#{$name}); + $icon-color: null; + $bg-color: null; + $border-color: null; + + $color-active: null; + $icon-color-active: null; + $border-color-active: null; + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Text colors active state + .btn.btn-active-text-#{$name} { + $color: null; + $icon-color: null; + $bg-color: null; + $border-color: null; + + $color-active: var(--kt-text-#{$name}); + $icon-color-active: null; + $border-color-active: null; + $bg-color-active: null; + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } +} + +// Social colors +@each $name, $value in $social-colors { + // Base + .btn.btn-#{$name} { + $color: get($value, inverse); + $icon-color: get($value, inverse); + $border-color: get($value, base); + $bg-color: get($value, base); + + $color-active: null; + $icon-color-active: null; + $border-color-active: get($value, active); + $bg-color-active: get($value, active); + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } + + // Light + .btn.btn-light-#{$name} { + $color: get($value, base); + $icon-color: get($value, base); + $bg-color: get($value, light); + $border-color: get($value, light); + + $color-active: get($value, inverse); + $icon-color-active: get($value, inverse); + $bg-color-active: get($value, base); + $border-color-active: get($value, base); + + @include button-custom-variant($color, $icon-color, $border-color, $bg-color, $color-active, $icon-color-active, $border-color-active, $bg-color-active); + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/components.scss b/src/_res/assets/sass/core/components/components.scss new file mode 100644 index 0000000..64e382f --- /dev/null +++ b/src/_res/assets/sass/core/components/components.scss @@ -0,0 +1,107 @@ +// +// Components +// + +// Bootstrap components +@import "~bootstrap/scss/root"; +@import "~bootstrap/scss/reboot"; +@import "~bootstrap/scss/type"; +@import "~bootstrap/scss/images"; +@import "~bootstrap/scss/containers"; +@import "~bootstrap/scss/grid"; +@import "~bootstrap/scss/tables"; +@import "~bootstrap/scss/forms"; +@import "~bootstrap/scss/buttons"; +@import "~bootstrap/scss/transitions"; +@import "~bootstrap/scss/dropdown"; +@import "~bootstrap/scss/button-group"; +@import "~bootstrap/scss/nav"; +@import "~bootstrap/scss/navbar"; +@import "~bootstrap/scss/card"; +@import "~bootstrap/scss/accordion"; +@import "~bootstrap/scss/breadcrumb"; +@import "~bootstrap/scss/pagination"; +@import "~bootstrap/scss/badge"; +@import "~bootstrap/scss/alert"; +@import "~bootstrap/scss/progress"; +@import "~bootstrap/scss/list-group"; +@import "~bootstrap/scss/close"; +@import "~bootstrap/scss/toasts"; +@import "~bootstrap/scss/modal"; +@import "~bootstrap/scss/tooltip"; +@import "~bootstrap/scss/popover"; +@import "~bootstrap/scss/carousel"; +@import "~bootstrap/scss/spinners"; +@import "~bootstrap/scss/offcanvas"; +@import "~bootstrap/scss/placeholders"; + +// Bootstrap helpers +@import "~bootstrap/scss/helpers"; + +// Bootstrap utilities +@import "utilities"; +@import "~bootstrap/scss/utilities/api"; + +// Custom components +@import "root"; +@import "root-bs"; +@import "reboot"; +@import "type"; +@import "theme-mode"; +@import "animation"; +@import "alert"; +@import "list-group"; +@import "images"; +@import "button-group"; +@import "dropdown"; +@import "toasts"; +@import "close"; +@import "offcanvas"; +@import "nav"; +@import "nav-line-tabs"; +@import "nav-pills-custom"; +@import "pagination"; +@import "separator"; +@import "carousel"; +@import "menu"; +@import "anchor"; +@import "card"; +@import "breadcrumb"; +@import "buttons"; +@import "code"; +@import "forms"; +@import "modal"; +@import "progress"; +@import "tables"; +@import "popover"; +@import "tooltip"; +@import "accordion"; +@import "feedback"; +@import "image-input"; +@import "symbol"; +@import "pulse"; +@import "page-loader"; +@import "scrolltop"; +@import "svg-icon"; +@import "fixed"; +@import "timeline"; +@import "timeline-label"; +@import "overlay"; +@import "bullet"; +@import "drawer"; +@import "badge"; +@import "indicator"; +@import "hover"; +@import "rotate"; +@import "scroll"; +@import "rating"; +@import "stepper"; +@import "toggle"; +@import "shape"; +@import "ribbon"; +@import "blockui"; +@import "explore"; +@import "engage"; +@import "cookiealert"; +@import "print"; +@import "helpers"; \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/forms/_floating-labels.scss b/src/_res/assets/sass/core/components/forms/_floating-labels.scss new file mode 100644 index 0000000..3c9d596 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_floating-labels.scss @@ -0,0 +1,12 @@ +// +// Floating label +// + +.form-floating { + .form-control.form-control-solid { + &::placeholder { + color: transparent; + } + } +} + \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/forms/_form-check-solid.scss b/src/_res/assets/sass/core/components/forms/_form-check-solid.scss new file mode 100644 index 0000000..c5d7088 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_form-check-solid.scss @@ -0,0 +1,239 @@ +// +// Form Check +// + +// Check input +.form-check:not(.form-switch) { + .form-check-input { + &[type="checkbox"] { + background-size: $form-check-input-bg-size; + } + } +} + +// Custom checkbox and radio +.form-check-custom { + display: flex; + align-items: center; + padding-left: 0; + margin: 0; + + // Input + .form-check-input { + margin: 0; + float: none; + flex-shrink: 0; + } + + // Label + .form-check-label { + margin-left: 0.55rem; + } + + // Sizing + &.form-check-sm { + .form-check-input { + height: $form-check-input-width-sm; + width: $form-check-input-width-sm; + } + } + + &.form-check-lg { + .form-check-input { + height: $form-check-input-width-lg; + width: $form-check-input-width-lg; + } + } + + // Solid + &.form-check-solid { + .form-check-input { + border: 0; + background-color: var(--kt-form-check-input-bg-solid); + + &:active, + &:focus { + filter: none; + background-color: var(--kt-form-check-input-bg-solid); + } + + &:checked { + background-color: var(--kt-form-check-input-checked-bg-color-solid); + } + } + } + + // States + // Success state + &.form-check-success { + .form-check-input { + &:checked { + background-color: var(--kt-success); + } + } + } + + // Danger state + &.form-check-danger { + .form-check-input { + &:checked { + background-color: var(--kt-danger); + } + } + } + + // Warning state + &.form-check-warning { + .form-check-input { + &:checked { + background-color: var(--kt-warning); + } + } + } +} + +// Custom switch +.form-switch.form-check-solid { + .form-check-input { + height: $form-switch-height; + background-image: var(--kt-form-switch-bg-image-solid); + border-radius: $form-switch-border-radius; + + &:checked { + filter: none; + background-image: var(--kt-form-switch-checked-bg-image); + } + } + + &.form-switch-sm { + .form-check-input { + height: $form-switch-height-sm; + width: $form-switch-width-sm; + } + } + + &.form-switch-lg { + .form-check-input { + height: $form-switch-height-lg; + width: $form-switch-width-lg; + } + } +} + +// Clip +.form-check-clip { + position: relative; + overflow: hidden; + + .form-check-label { + padding-top: 0.5rem; + font-size: $form-label-font-size; + color: var(--kt-form-label-color); + font-weight: $form-label-font-weight; + } + + .form-check-wrapper { + @include border-radius($border-radius-lg); + border: 2px solid transparent; + transition: $transition-base; + cursor: pointer; + overflow: hidden; + } + + .form-check-indicator { + transition: $transition-base; + position: absolute; + top: 0; + right: 0; + opacity: 0; + width: $form-check-input-width; + height: $form-check-input-width; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + background-size: 50%; + background-image: var(--kt-form-check-input-checked-bg-image); + background-color: var(--kt-component-checked-bg); + @include border-bottom-start-radius($border-radius-lg); + @include border-top-end-radius($border-radius-lg); + + &.form-check-indicator-sm { + width: $form-check-input-width-sm; + height: $form-check-input-width-sm; + } + + &.form-check-indicator-lg { + width: $form-check-input-width-lg; + height: $form-check-input-width-lg; + } + } + + .form-check-content { + width: 100%; + } + + .btn-check:checked + div { + border: 2px solid var(--kt-component-checked-bg); + transition: $transition-base; + + .form-check-indicator { + transition: $transition-base; + opacity: 1; + } + } + + .btn-check:disabled + div { + transition: $transition-base; + opacity: var(--kt-form-check-btn-check-disabled-opacity); + } +} + +// Image +.form-check-image { + position: relative; + overflow: hidden; + + img { + max-width: 100%; + } + + .form-check-wrapper { + @include border-radius($border-radius-lg); + border: 2px solid transparent; + transition: $transition-base; + cursor: pointer; + overflow: hidden; + margin-bottom: 0.75rem; + } + + .form-check-rounded { + @include border-radius($border-radius-lg); + } + + .form-check-label { + font-weight: $font-weight-bold; + margin-left: 0.5rem; + } + + &.active { + .form-check-wrapper { + border-color: var(--kt-primary); + } + } + + &.form-check-success.active { + .form-check-wrapper { + border-color: var(--kt-success); + } + } + + &.form-check-danger.active { + .form-check-wrapper { + border-color: var(--kt-danger); + } + } + + &.disabled { + opacity: var(--kt-form-check-btn-check-disabled-opacity); + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/forms/_form-check.scss b/src/_res/assets/sass/core/components/forms/_form-check.scss new file mode 100644 index 0000000..191fbd7 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_form-check.scss @@ -0,0 +1,106 @@ +// +// Check/radio +// + +.form-check-input { + background-color: var(--kt-form-check-input-bg); + border: var(--kt-form-check-input-border); + + &:active { + filter: var(--kt-form-check-input-active-filter); + } + + &:focus { + border-color: var(--kt-form-check-input-focus-border); + box-shadow: var(--kt-form-check-input-focus-box-shadow); + } + + &:checked { + background-color: var(--kt-form-check-input-checked-bg-color); + border-color: var(--kt-form-check-input-checked-border-color); + + &[type="checkbox"] { + @if $enable-gradients { + background-image: var(--kt-form-check-input-checked-bg-image), var(--#{$prefix}gradient); + } @else { + background-image: var(--kt-form-check-input-checked-bg-image); + } + } + + &[type="radio"] { + @if $enable-gradients { + background-image: var(--kt-form-check-radio-checked-bg-image), var(--#{$prefix}gradient); + } @else { + background-image: var(--kt-form-check-radio-checked-bg-image); + } + } + } + + &[type="checkbox"]:indeterminate { + background-color: var(--kt-form-check-input-indeterminate-bg-color); + border-color: var(--kt-form-check-input-indeterminate-border-color); + + @if $enable-gradients { + background-image: var(--kt-form-check-input-indeterminate-bg-image), var(--#{$prefix}gradient); + } @else { + background-image:var(--kt-form-check-input-indeterminate-bg-image); + } + } + + &:disabled { + opacity: var(--kt-form-check-input-disabled-opacity); + } + + // Use disabled attribute in addition of :disabled pseudo-class + // See: https://github.com/twbs/bootstrap/issues/28247 + &[disabled], + &:disabled { + ~ .form-check-label { + opacity: var(--kt-form-check-label-disabled-opacity); + } + } +} + +.form-check-label { + color: var(--kt-form-check-label-color); +} + +.form-check-input { + &:checked { + & + span, + & + label { + color: var(--kt-form-check-label-color-checked); + } + } +} + +// +// Switch +// + +.form-switch { + .form-check-input { + background-image: var(--kt-form-switch-bg-image); + + &:focus { + background-image: var(--kt-form-switch-focus-bg-image); + } + + &:checked { + @if $enable-gradients { + background-image: var(--kt-form-switch-checked-bg-image), var(--#{$prefix}gradient); + } @else { + background-image: var(--kt-form-switch-checked-bg-image); + } + } + } +} + +.btn-check { + &[disabled], + &:disabled { + + .btn { + opacity: var(--kt-form-check-btn-check-disabled-opacity); + } + } +} diff --git a/src/_res/assets/sass/core/components/forms/_form-control-solid.scss b/src/_res/assets/sass/core/components/forms/_form-control-solid.scss new file mode 100644 index 0000000..84b021a --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_form-control-solid.scss @@ -0,0 +1,78 @@ +// +// Form Control +// + + +// Form control +.form-control { + // Dropdown shown state + .dropdown.show > & { + color: var(--kt-input-focus-color); + background-color: var(--kt-input-focus-bg); + border-color: var(--kt-input-focus-border-color); + } + + // Readonly state + &[readonly] { + background-color: var(--kt-input-readonly-bg); + } + + // Solid style + &.form-control-solid { + background-color: var(--kt-input-solid-bg); + border-color: var(--kt-input-solid-bg); + color: var(--kt-input-solid-color); + @include placeholder(var(--kt-input-solid-placeholder-color)); + transition: $transition-input; + + .dropdown.show > &, + &:active, + &.active, + &:focus, + &.focus { + background-color: var(--kt-input-solid-bg-focus); + border-color: var(--kt-input-solid-bg-focus); + color: var(--kt-input-solid-color); + transition: $transition-input; + } + } + + // Transparent style + &.form-control-transparent { + background-color: transparent; + border-color: transparent; + + .dropdown.show > &, + &:active, + &.active, + &:focus, + &.focus { + background-color: transparent; + border-color: transparent; + } + } + + // Flush + &.form-control-flush { + @include input-reset(); + } +} + +// Placeholder colors +.placeholder-gray-500 { + @include placeholder(var(--kt-gray-500)); +} + +.placeholder-white { + @include placeholder($white); +} + +// Textarea reset resize +.resize-none { + resize: none; +} + +// Form control solid bg +.form-control-solid-bg { + background-color: var(--kt-input-solid-bg); +} diff --git a/src/_res/assets/sass/core/components/forms/_form-control.scss b/src/_res/assets/sass/core/components/forms/_form-control.scss new file mode 100644 index 0000000..9ae50d4 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_form-control.scss @@ -0,0 +1,46 @@ +// +// Form controls +// + +.form-control { + color: var(--kt-input-color); + background-color: var(--kt-input-bg); + border: $input-border-width solid var(--kt-input-border-color); + box-shadow: none !important; + //@include box-shadow(var(--kt-input-box-shadow)); + + &:focus { + color: var(--kt-input-focus-color); + background-color: var(--kt-input-focus-bg); + border-color: var(--kt-input-focus-border-color); + //box-shadow: var(--kt-input-focus-box-shadow); + } + + // Placeholder + &::placeholder { + color: var(--kt-input-placeholder-color); + } + + // Disabled and read-only inputs + &:disabled, + &[readonly] { + color: var(--kt-input-disabled-color); + background-color: var(--kt-input-disabled-bg); + border-color: var(--kt-input-disabled-border-color); + } + + // File input buttons theming + &::file-selector-button { + color: var(--kt-form-file-button-color); + @include gradient-bg(var(--kt-form-file-button-bg)); + } + + &:hover:not(:disabled):not([readonly])::file-selector-button { + background-color: var(--kt-form-file-button-hover-bg); + } +} + +// Readonly controls as plain text +.form-control-plaintext { + color: var(--kt-input-plaintext-color); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/forms/_form-select-solid.scss b/src/_res/assets/sass/core/components/forms/_form-select-solid.scss new file mode 100644 index 0000000..f53bb93 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_form-select-solid.scss @@ -0,0 +1,45 @@ +// +// Form Select +// + +.form-select { + box-shadow: none !important; + + // Solid style + &.form-select-solid { + @include placeholder(var(--kt-input-solid-placeholder-color)); + background-color: var(--kt-input-solid-bg); + border-color: var(--kt-input-solid-bg); + color: var(--kt-input-solid-color); + transition: $transition-input; + + .dropdown.show > &, + &:active, + &.active, + &:focus, + &.focus { + background-color: var(--kt-input-solid-bg-focus); + border-color: var(--kt-input-solid-bg-focus) !important; + color: var(--kt-input-solid-color); + transition: $transition-input; + } + } + + // Transparent style + &.form-select-transparent { + @include placeholder(var(--kt-input-placeholder-color)); + background-color: transparent; + border-color: transparent; + color: $input-color; + + .dropdown.show > &, + &:active, + &.active, + &:focus, + &.focus { + background-color: transparent; + border-color: transparent !important; + color: $input-color; + } + } +} diff --git a/src/_res/assets/sass/core/components/forms/_form-select.scss b/src/_res/assets/sass/core/components/forms/_form-select.scss new file mode 100644 index 0000000..07a2e10 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_form-select.scss @@ -0,0 +1,35 @@ +// Select +// +// Replaces the browser default select with a custom one, mostly pulled from +// https://primer.github.io/. + +.form-select { + color: var(--kt-form-select-color); + background-color: var(--kt-form-select-bg); + background-image: var(--kt-form-select-indicator); + border: $form-select-border-width solid var(--kt-form-select-border-color); + @include box-shadow(var(--kt-form-select-box-shadow)); + appearance: none; + + &:focus { + border-color: var(--kt-form-select-focus-border-color); + @if $enable-shadows { + @include box-shadow(var(--kt-form-select-box-shadow), var(--kt-form-select-focus-box-shadow)); + } @else { + // Avoid using mixin so we can pass custom focus shadow properly + box-shadow: var(--kt-form-select-focus-box-shadow); + } + } + + + &:disabled { + color: var(--kt-form-select-disabled-color); + background-color: var(--kt-form-select-disabled-bg); + border-color: var(--kt-form-select-disabled-border-color); + } + + // Remove outline from select box in FF + &:-moz-focusring { + text-shadow: 0 0 0 var(--kt-form-select-color); + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/forms/_form-text.scss b/src/_res/assets/sass/core/components/forms/_form-text.scss new file mode 100644 index 0000000..94cd819 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_form-text.scss @@ -0,0 +1,7 @@ +// +// Form text +// + +.form-text { + color: var(--kt-form-text-color); +} diff --git a/src/_res/assets/sass/core/components/forms/_input-group-solid.scss b/src/_res/assets/sass/core/components/forms/_input-group-solid.scss new file mode 100644 index 0000000..46d6e32 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_input-group-solid.scss @@ -0,0 +1,36 @@ +// +// Input Group +// + +// Form control +.input-group { + &.input-group-solid { + @include border-radius($input-border-radius); + + &.input-group-sm { + @include border-radius($input-border-radius-sm); + } + + &.input-group-lg { + @include border-radius($input-border-radius-lg); + } + + .input-group-text { + background-color: var(--kt-input-solid-bg); + border-color: var(--kt-input-solid-bg); + + & + .form-control { + border-left-color: var(--kt-input-border-color); + } + } + + .form-control { + background-color: var(--kt-input-solid-bg); + border-color: var(--kt-input-solid-bg); + + & + .input-group-text { + border-left-color: var(--kt-input-border-color); + } + } + } +} diff --git a/src/_res/assets/sass/core/components/forms/_input-group.scss b/src/_res/assets/sass/core/components/forms/_input-group.scss new file mode 100644 index 0000000..ee05d35 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_input-group.scss @@ -0,0 +1,9 @@ +// +// Input group +// + +.input-group-text { + color: var(--kt-input-group-addon-color); + background-color: var(--kt-input-group-addon-bg); + border: $input-border-width solid var(--kt-input-group-addon-border-color); +} diff --git a/src/_res/assets/sass/core/components/forms/_labels.scss b/src/_res/assets/sass/core/components/forms/_labels.scss new file mode 100644 index 0000000..c6091c6 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_labels.scss @@ -0,0 +1,13 @@ +// +// Labels +// + +.form-label { + color: var(--kt-form-label-color); +} + +// For use with horizontal and inline forms, when you need the label (or legend) +// text to align with the form controls. +.col-form-label { + color: var(--kt-form-label-color); +} diff --git a/src/_res/assets/sass/core/components/forms/_required.scss b/src/_res/assets/sass/core/components/forms/_required.scss new file mode 100644 index 0000000..effaf53 --- /dev/null +++ b/src/_res/assets/sass/core/components/forms/_required.scss @@ -0,0 +1,14 @@ +// +// Required Label +// + +.required { + &:after { + content: "*"; + position: relative; + font-size: inherit; + color: var(--kt-danger); + padding-left: 0.25rem; + font-weight: $font-weight-bold; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/helpers/_background.scss b/src/_res/assets/sass/core/components/helpers/_background.scss new file mode 100644 index 0000000..c526de6 --- /dev/null +++ b/src/_res/assets/sass/core/components/helpers/_background.scss @@ -0,0 +1,208 @@ +// +// Custom background helpers +// + +// Background white color +.bg-white { + --kt-bg-rgb-color: var(--kt-white-bg-rgb); + background-color: $black !important; +} + +// Background black color +.bg-black { + --kt-bg-rgb-color: var(--kt-black-bg-rgb); + background-color: $black !important; +} + +// Background body color +.bg-body { + --kt-bg-rgb-color: var(--kt-body-bg-rgb); + background-color: var(--kt-body-bg) !important; +} + +.bg-hover-body { + cursor: pointer; + + &:hover { + background-color: var(--kt-body-bg) !important; + } +} + +.bg-active-body { + &.active { + background-color: var(--kt-body-bg) !important; + } +} + +.bg-state-body { + cursor: pointer; + + &.active, + &:hover { + background-color: var(--kt-body-bg) !important; + } +} + +// Background theme light colors +@each $name, $value in $theme-colors { + @if (theme-light-color($name)) { + .bg-light-#{$name} { + background-color: var(--kt-#{$name}-light) !important; + } + } + + .bg-#{$name} { + --kt-bg-rgb-color: var(--kt-#{$name}-rgb); + background-color: var(--kt-#{$name}) !important; + } + + @if (theme-light-color($name)) { + .bg-hover-light-#{$name} { + cursor: pointer; + + &:hover { + background-color: var(--kt-#{$name}-light) !important; + } + } + + .bg-state-light-#{$name} { + cursor: pointer; + + &.active, + &:hover { + background-color: var(--kt-#{$name}-light) !important; + } + } + } + + .bg-hover-#{$name} { + cursor: pointer; + + &:hover { + background-color: var(--kt-#{$name}) !important; + } + } + + .bg-active-#{$name} { + &.active { + background-color: var(--kt-#{$name}) !important; + } + } + + .bg-state-#{$name} { + cursor: pointer; + + &.active, + &:hover { + background-color: var(--kt-#{$name}) !important; + } + } +} + +// Background gray colors +@each $name, $value in $grays { + .bg-gray-#{$name} { + background-color: var(--kt-gray-#{$name}); + } + + .bg-gray-#{$name}i { + background-color: var(--kt-gray-#{$name}) !important; + } +} + +// Opacity +@each $name, $value in $opacity-values { + .bg-opacity-#{$name} { + background-color: rgba(var(--kt-bg-rgb-color), #{$value}) !important; + } + + .bg-hover-opacity-#{$name}:hover { + background-color: rgba(var(--kt-bg-rgb-color), #{$value}) !important; + } + + .bg-active-opacity-#{$name}.active { + background-color: rgba(var(--kt-bg-rgb-color), #{$value}) !important; + } + + .bg-state-opacity-#{$name} { + .active, + &:hover { + background-color: rgba(var(--kt-bg-rgb-color), #{$value}) !important; + } + } +} + +// Background image helpers +// Background repeat +.bgi-no-repeat { + background-repeat: no-repeat; +} + +// Background positions +.bgi-position-y-top { + background-position-y: top; +} + +.bgi-position-y-bottom { + background-position-y: bottom; +} + +.bgi-position-y-center { + background-position-y: center; +} + +.bgi-position-x-start { + background-position-x: left; +} + +.bgi-position-x-end { + background-position-x: right; +} + +.bgi-position-x-center { + background-position-x: center; +} + +.bgi-position-top { + background-position: 0 top; +} + +.bgi-position-bottom { + background-position: 0 bottom; +} + +.bgi-position-center { + background-position: center; +} + +// Responsive helpers +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + // Background sizes + .bgi-size#{$infix}-auto { + background-size: auto; + } + + .bgi-size#{$infix}-cover { + background-size: cover; + } + + .bgi-size#{$infix}-contain { + background-size: contain; + } + + // Background attachment + .bgi-attachment#{$infix}-fixed { + background-attachment: fixed; + } + + .bgi-attachment#{$infix}-scroll { + background-attachment: scroll; + } + } +} + + + diff --git a/src/_res/assets/sass/core/components/helpers/_borders.scss b/src/_res/assets/sass/core/components/helpers/_borders.scss new file mode 100644 index 0000000..892c1fe --- /dev/null +++ b/src/_res/assets/sass/core/components/helpers/_borders.scss @@ -0,0 +1,114 @@ +// +// Border +// + +.border-active:not(.active):not(:active):not(:hover):not(:focus) { + border-color: transparent !important; +} + +.border-hover:not(:hover):not(:focus):not(.active):not(:active) { + cursor: pointer; + border-color: transparent !important; +} + +// Gray border colors +@each $name, $value in $grays { + // Initial + .border-gray-#{$name} { + border-color: var(--kt-gray-#{$name}) !important; + } +} + +// Hover border colors +@each $name, $value in $theme-colors { + .border-hover-#{$name}:hover { + border-color: var(--kt-#{$name}) !important; + } + + .border-active-#{$name}.active { + border-color: var(--kt-#{$name}) !important; + } +} + +// Hover transparent +.border-hover-transparent:hover { + border-color: transparent !important; +} + +// Dashed style +.border-dashed { + border-style: dashed !important; + border-color: var(--kt-border-dashed-color); +} + +.border-top-dashed { + border-top-style: dashed !important; +} + +.border-bottom-dashed { + border-bottom-style: dashed !important; +} + +.border-start-dashed { + border-left-style: dashed !important; +} + +.border-end-dashed { + border-right-style: dashed !important; +} + +// Dotted style +.border-dotted { + border-style: dotted !important; +} + +.border-top-dotted { + border-top-style: dotted !important; +} + +.border-bottom-dotted { + border-bottom-style: dotted !important; +} + +.border-start-dotted { + border-left-style: dotted !important; +} + +.border-end-dotted { + border-right-style: dotted !important; +} + +// Border transparent +.border-transparent { + border-color: transparent !important; +} + +// Border body +.border-body { + border-color: var(--kt-body-bg) !important; +} + +// Border radiuses +.rounded-top-0 { + border-top-left-radius: 0 !important; + border-top-right-radius: 0 !important; +} + +.rounded-bottom-0 { + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +.rounded-start-0 { + border-top-left-radius: 0 !important; + border-bottom-left-radius: 0 !important; +} + +.rounded-end-0 { + border-top-right-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} + +.rounded-circle { + border-radius: 50% !important; +} diff --git a/src/_res/assets/sass/core/components/helpers/_flex.scss b/src/_res/assets/sass/core/components/helpers/_flex.scss new file mode 100644 index 0000000..d3f2b31 --- /dev/null +++ b/src/_res/assets/sass/core/components/helpers/_flex.scss @@ -0,0 +1,57 @@ +// +// Flex Utilities +// + + +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .flex#{$infix}-root { + flex: 1; + } + + .flex#{$infix}-column-auto { + flex: none; + } + + .flex#{$infix}-column-fluid { + flex: 1 0 auto; + } + + .flex#{$infix}-row-auto { + flex: 0 0 auto; + } + + .flex#{$infix}-row-fluid { + flex: 1 auto; + min-width: 0; + } + + .flex#{$infix}-center { + justify-content: center; + align-items: center; + } + + .flex#{$infix}-start { + justify-content: start; + align-items: start; + } + + .flex#{$infix}-end { + justify-content: end; + align-items: end; + } + + .flex#{$infix}-stack { + justify-content: space-between; + align-items: center; + } + } +} + +.flex-equal { + flex-grow: 1; + flex-basis: 0; + flex-shrink: 0; +} diff --git a/src/_res/assets/sass/core/components/helpers/_opacity.scss b/src/_res/assets/sass/core/components/helpers/_opacity.scss new file mode 100644 index 0000000..80e26c8 --- /dev/null +++ b/src/_res/assets/sass/core/components/helpers/_opacity.scss @@ -0,0 +1,18 @@ +// +// Opacity +// + +@each $name, $value in $opacity-values { + // Active state + .opacity-active-#{$name}.active { + opacity: #{$value} !important; + } + + // Active and hover states + .opacity-state-#{$name} { + &:hover, + &.active { + opacity: #{$value} !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/helpers/_shadow.scss b/src/_res/assets/sass/core/components/helpers/_shadow.scss new file mode 100644 index 0000000..ff50ae1 --- /dev/null +++ b/src/_res/assets/sass/core/components/helpers/_shadow.scss @@ -0,0 +1,19 @@ +// +// Shadow +// + +.shadow-xs { + box-shadow: var(--kt-box-shadow-xs); +} + +.shadow-sm { + box-shadow: var(--kt-box-shadow-sm); +} + +.shadow { + box-shadow: var(--kt-box-shadow); +} + +.shadow-lg { + box-shadow: var(--kt-box-shadow-lg); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/helpers/_text.scss b/src/_res/assets/sass/core/components/helpers/_text.scss new file mode 100644 index 0000000..f147cae --- /dev/null +++ b/src/_res/assets/sass/core/components/helpers/_text.scss @@ -0,0 +1,114 @@ +// +// Text +// + +// Text colors +@each $name, $color in $theme-text-colors { + // Base color + .text-#{$name} { + color: var(--kt-text-#{$name}) !important; + } + + // Inverse color + @if (theme-inverse-color($name)) { + .text-inverse-#{$name} { + color: var(--kt-#{$name}-inverse) !important; + } + } + + @if (theme-light-color($name)) { + // Light colors + .text-light-#{$name} { + color: var(--kt-#{$name}-light) !important; + } + } + + // Hover + .text-hover-#{$name} { + transition: $transition-link; + + i { + transition: $transition-link; + } + + &:hover { + transition: $transition-link; + color: var(--kt-text-#{$name}) !important; + + i { + transition: $transition-link; + color: var(--kt-text-#{$name}) !important; + } + + .svg-icon { + color: var(--kt-text-#{$name}) !important; + } + } + } + + // Active + .text-active-#{$name} { + transition: $transition-link; + + i { + transition: $transition-link; + } + + &.active { + transition: $transition-link; + color: var(--kt-text-#{$name}) !important; + + i { + transition: $transition-link; + color: var(--kt-text-#{$name}) !important; + } + + .svg-icon { + color: var(--kt-text-#{$name}) !important; + } + } + } +} + +// Text transparent +.text-transparent { + color: transparent; +} + +// Cursor pointer +.cursor-pointer { + cursor: pointer; +} + +// Cursor default +.cursor-default { + cursor: default; +} +// Cursor move +.cursor-move { + cursor: move; +} + +// Icons +i { + &.bi, + &[class^="fonticon-"], + &[class*=" fonticon-"], + &[class^="fa-"], + &[class*=" fa-"], + &[class^="la-"], + &[class*=" la-"] { + line-height: 1; + font-size: 1rem; + color: var(--kt-text-muted); + } +} + +// Link transition +a { + transition: $transition-link; + + &:hover { + transition:$transition-link; + } +} diff --git a/src/_res/assets/sass/core/components/helpers/_transform.scss b/src/_res/assets/sass/core/components/helpers/_transform.scss new file mode 100644 index 0000000..0c8616f --- /dev/null +++ b/src/_res/assets/sass/core/components/helpers/_transform.scss @@ -0,0 +1,8 @@ +// +// Transform +// + +.transform-90 { + transform: rotate(90deg); + transform-origin: right top; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/menu/_base.scss b/src/_res/assets/sass/core/components/menu/_base.scss new file mode 100644 index 0000000..dc50228 --- /dev/null +++ b/src/_res/assets/sass/core/components/menu/_base.scss @@ -0,0 +1,306 @@ +// +// Menu Base +// + +// Menu group +.menu-group { + display: flex; +} + +// Menu & wrapper +.menu, +.menu-wrapper { + display: flex; + padding: 0; + margin: 0; + list-style: none; +} + +// Sub inner +.menu-inner { + padding: 0; + margin: 0; + list-style: none; +} + +// Sub menu +.menu-sub { + display: none; + padding: 0; + margin: 0; + list-style: none; + flex-direction: column; +} + +// Menu item +.menu-item { + display: block; + padding: $menu-item-padding-y $menu-item-padding-x; + + // Menu Link + .menu-link { + cursor: pointer; + display: flex; + align-items: center; + padding: 0; + flex: 0 0 100%; + padding: $menu-link-padding-y $menu-link-padding-x; + transition: none; + outline: none !important; + + .menu-icon { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: $menu-icon-size; + margin-right: $menu-icon-space; + + .svg-icon { + line-height: 1; + } + } + + .menu-bullet { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: $menu-bullet-size; + margin-right: $menu-bullet-space; + } + + .menu-title { + display: flex; + align-items: center; + flex-grow: 1; + } + + .menu-badge { + display: flex; + align-items: center; + flex-shrink: 0; + margin-left: $menu-badge-space; + } + + .menu-arrow { + display: flex; + align-items: stretch; + position: relative; + overflow: hidden; + flex-shrink: 0; + margin-left: $menu-arrow-space; + width: $menu-arrow-size; + height: $menu-arrow-size; + + &:after { + display: block; + width: 100%; + content: " "; + will-change: transform; + background-size: 100% 100%; + @include svg-bg-icon(arrow-start, var(--kt-text-muted)); + /*rtl:begin:remove*/ + @include svg-bg-icon(arrow-end, var(--kt-text-muted)); + /*rtl:end:remove*/ + } + } + } + + // Menu Content + .menu-content { + padding: $menu-link-padding-y $menu-link-padding-x; + } +} + +// Accordion arrows +.menu-item { + &.show { + .menu-link { + .menu-arrow:after { + backface-visibility: hidden; + transition: $menu-accordion-arrow-transition; + } + } + } +} + +// Center alignment +.menu-center { + justify-content: center; +} + +// Heading +.menu-heading { + color: var(--kt-menu-heading-color); +} + +// Responsive +@each $direction in (up, down) { + @each $breakpoint in map-keys($grid-breakpoints) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + @if $infix and $direction == down { + $infix: $infix + "-" + $direction; + } + + @include media-breakpoint-direction($direction, $breakpoint) { + // Accordion arrow + .menu-item.menu#{$infix}-accordion { + .menu-arrow:after { + @include menu-link-arrow-rotate(90deg, -90deg); + } + + &.showing:not(.menu-dropdown), + &.show:not(.hiding):not(.menu-dropdown) { + > .menu-link { + .menu-arrow:after { + @include menu-link-arrow-rotate(-90deg, 90deg); + } + } + } + } + + // Sub dropdown + .menu-sub#{$infix}-dropdown { + display: none; + border-radius: $menu-dropdown-border-radius; + background-color: var(--kt-menu-dropdown-bg-color); + box-shadow: var(--kt-menu-dropdown-box-shadow); + z-index: $menu-dropdown-z-index; + + // Dropdown show + .show.menu-dropdown > &, + &.menu.show, + &.show[data-popper-placement] { + display: flex; + will-change: transform; + + // Animation + @if ($menu-dropdown-animation == true) { + // Move up + animation: menu-sub-dropdown-animation-fade-in #{$menu-dropdown-animation-speed} ease 1, menu-sub-dropdown-animation-move-up #{$menu-dropdown-animation-speed} ease 1; + } + } + } + + // Sub accordion + .menu-sub#{$infix}-accordion { + display: none; + + .show:not(.menu-dropdown) > &, + &.show { + display: flex; + } + } + + // Sub indention + .menu-sub#{$infix}-indention { + @include menu-sub-indention($menu-accordion-indention); + + // Active link + .menu-item .menu-item .menu-link.active { + margin-right: $menu-link-padding-x; + } + } + + // Inline + .menu#{$infix}-inline { + display: flex; + } + + // Reset link left & right paddings of level 1 menu links + .menu#{$infix}-fit { + > .menu-item { + > .menu-content, + > .menu-link { + padding-left: 0 !important; + padding-right: 0 !important; + } + } + } + + .menu#{$infix}-column { + flex-direction: column; + width: 100%; + } + + .menu#{$infix}-row { + flex-direction: row; + + > .menu-item { + display: flex; + align-items: center; + + > .menu-link { + .menu-arrow:after { + @include menu-link-arrow-rotate(90deg, -90deg); + } + } + } + } + + // Border radiuses + .menu#{$infix}-rounded { + .menu-link { + @include border-radius($menu-link-border-radius); + } + } + + // Border radiuses + .menu#{$infix}-pill { + .menu-link { + border-radius: 50px; + } + } + + // Reset border radiuses + .menu#{$infix}-rounded-0 { + .menu-link { + border-radius: 0 !important; + } + } + } + } +} + +// Link indention +.menu-link-indention { + .menu-item { + padding-top: 0; + padding-bottom: 0; + } + + @include menu-link-indention($menu-accordion-indention, $menu-link-padding-x); +} + +// Menu animations +@keyframes menu-sub-dropdown-animation-fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +@keyframes menu-sub-dropdown-animation-move-up { + from { + margin-top: #{$menu-dropdown-animation-move-offset}; + } + + to { + margin-top: 0; + } +} + +@keyframes menu-sub-dropdown-animation-move-down { + from { + margin-bottom: #{$menu-dropdown-animation-move-offset}; + } + + to { + margin-bottom: 0; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/menu/_theme.scss b/src/_res/assets/sass/core/components/menu/_theme.scss new file mode 100644 index 0000000..f8e4730 --- /dev/null +++ b/src/_res/assets/sass/core/components/menu/_theme.scss @@ -0,0 +1,510 @@ +// +// Menu Theme +// + +// Theme text colors +@each $name, $color in $theme-text-colors { + .menu-#{$name} { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-default-state( var(--kt-#{$name}), var(--kt-#{$name}), var(--kt-#{$name}), var(--kt-#{$name}), null ); + } + } + + .menu-title-#{$name} { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-default-state( var(--kt-text-#{$name}), null, null, null, null ); + } + } + + .menu-icon-#{$name} { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-default-state( null, var(--kt-text-#{$name}), null, null, null ); + } + } + + .menu-bullet-#{$name} { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-default-state( null, null, var(--kt-text-#{$name}), null, null ); + } + } + + .menu-arrow-#{$name} { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-default-state( null, null, null, var(--kt-text-#{$name}), null ); + } + } +} + +// Default background states +.menu-hover-bg { + .menu-item { + @include menu-link-hover-state( + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-bg-color-hover) + ); + } +} + +.menu-here-bg { + .menu-item { + @include menu-link-here-state( + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-bg-color-here) + ); + } +} + +.menu-root-here-bg { + > .menu-item { + @include menu-link-here-state( + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-bg-color-here) + ); + } +} + +// Desktop mode +@include media-breakpoint-up(lg) { + .menu-root-here-bg-desktop { + > .menu-item { + @include menu-link-here-state( + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-bg-color-here) + ); + } + } +} + +.menu-show-bg { + .menu-item { + @include menu-link-show-state( + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-bg-color-show) + ); + } +} + +.menu-active-bg { + .menu-item { + @include menu-link-active-state( + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-bg-color-active) + ); + } +} + +.menu-state-bg { + .menu-item { + @include menu-link-hover-state( + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-bg-color-hover) + ); + + @include menu-link-here-state( + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-bg-color-here) + ); + + @include menu-link-show-state( + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-bg-color-show) + ); + + @include menu-link-active-state( + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-bg-color-active) + ); + } +} + +.menu-state-color { + .menu-item { + @include menu-link-hover-state( + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + var(--kt-menu-link-color-hover), + null + ); + + @include menu-link-here-state( + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + var(--kt-menu-link-color-here), + null + ); + + @include menu-link-show-state( + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + var(--kt-menu-link-color-show), + null + ); + + @include menu-link-active-state( + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + var(--kt-menu-link-color-active), + null + ); + } +} + +// Primary background states +.menu-hover-bg-primary { + .menu-item { + @include menu-link-hover-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + } +} + +.menu-show-bg-primary { + .menu-item { + @include menu-link-show-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + } +} + +.menu-here-bg-primary { + .menu-item { + @include menu-link-here-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + } +} + +.menu-active-bg-primary { + .menu-item { + @include menu-link-active-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + } +} + +.menu-state-bg-primary { + .menu-item { + @include menu-link-hover-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + + @include menu-link-show-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + + @include menu-link-here-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + + @include menu-link-active-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + + @include menu-link-show-state( + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary-inverse), + var(--kt-primary) + ); + } +} + +// Light primary background states +.menu-show-bg-light-primary { + .menu-item { + @include menu-link-show-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + } +} + +.menu-here-bg-light-primary { + .menu-item { + @include menu-link-here-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + } +} + +.menu-hover-bg-light-primary { + .menu-item { + @include menu-link-hover-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + } +} + +.menu-active-bg-light-primary { + .menu-item { + @include menu-link-active-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + } +} + +.menu-state-bg-light-primary { + .menu-item { + @include menu-link-show-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + @include menu-link-here-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + @include menu-link-hover-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + @include menu-link-active-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary-light) ); + } +} + +// Primary color states +.menu-hover-primary { + .menu-item { + @include menu-link-hover-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + } +} + +.menu-show-primary { + .menu-item { + @include menu-link-show-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + } +} + +.menu-here-primary { + .menu-item { + @include menu-link-here-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + } +} + +.menu-active-primary { + .menu-item { + @include menu-link-active-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + } +} + +.menu-state-primary { + .menu-item { + @include menu-link-hover-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + @include menu-link-show-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + @include menu-link-here-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + @include menu-link-active-state( var(--kt-primary), var(--kt-primary), var(--kt-primary), var(--kt-primary), null ); + } +} + +.menu-state-dark { + .menu-item { + @include menu-link-hover-state( var(--kt-dark), var(--kt-dark), var(--kt-dark), var(--kt-dark), null ); + @include menu-link-show-state( var(--kt-dark), var(--kt-dark), var(--kt-dark), var(--kt-dark), null ); + @include menu-link-here-state( var(--kt-dark), var(--kt-dark), var(--kt-dark), var(--kt-dark), null ); + @include menu-link-active-state( var(--kt-dark), var(--kt-dark), var(--kt-dark), var(--kt-dark), null ); + } +} + +// Primary title color states +.menu-hover-title-primary { + .menu-item { + @include menu-link-hover-state( var(--kt-primary), null, null, null, null ); + } +} + +.menu-here-title-primary { + .menu-item { + @include menu-link-here-state( var(--kt-primary), null, null, null, null ); + } +} + +.menu-show-title-primary { + .menu-item { + @include menu-link-show-state( var(--kt-primary), null, null, null, null ); + } +} + +.menu-active-title-primary { + .menu-item { + @include menu-link-active-state( var(--kt-primary), null, null, null, null ); + } +} + +.menu-state-title-primary { + .menu-item { + @include menu-link-hover-state( var(--kt-primary), null, null, null, null ); + @include menu-link-here-state( var(--kt-primary), null, null, null, null ); + @include menu-link-show-state( var(--kt-primary), null, null, null, null ); + @include menu-link-active-state( var(--kt-primary), null, null, null, null ); + } +} + +// Primary icon color states +.menu-hover-icon-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-hover-state( null, var(--kt-primary), null, null, null ); + } +} + +.menu-here-icon-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-here-state( null, var(--kt-primary), null, null, null ); + } +} + +.menu-show-icon-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-show-state( null, var(--kt-primary), null, null, null ); + } +} + +.menu-active-icon-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-active-state( null, var(--kt-primary), null, null, null ); + } +} + +.menu-state-icon-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-hover-state( null, var(--kt-primary), null, null, null ); + @include menu-link-here-state( null, var(--kt-primary), null, null, null ); + @include menu-link-show-state( null, var(--kt-primary), null, null, null ); + @include menu-link-active-state( null, var(--kt-primary), null, null, null ); + } +} + +// Primary bullet color states +.menu-hover-bullet-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-hover-state( null, null, var(--kt-primary), null, null ); + } +} + +.menu-show-bullet-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-show-state( null, null, var(--kt-primary), null, null ); + } +} + +.menu-here-bullet-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-here-state( null, null, var(--kt-primary), null, null ); + } +} + +.menu-active-bullet-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-active-state( null, null, var(--kt-primary), null, null ); + } +} + +.menu-state-bullet-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-hover-state( null, null, var(--kt-primary), null, null ); + @include menu-link-here-state( null, null, var(--kt-primary), null, null ); + @include menu-link-show-state( null, null, var(--kt-primary), null, null ); + @include menu-link-active-state( null, null, var(--kt-primary), null, null ); + } +} + +// Primary arrow color states +.menu-hover-arrow-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-hover-state( null, null, null, var(--kt-primary), null ); + } +} + +.menu-here-arrow-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-here-state( null, null, null, var(--kt-primary), null ); + } +} + +.menu-show-arrow-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-show-state( null, null, null, var(--kt-primary), null ); + } +} + +.menu-active-arrow-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-active-state( null, null, null, var(--kt-primary), null ); + } +} + +.menu-state-arrow-primary { + .menu-item { + //$title-color, $icon-color, $bullet-color, $arrow-color, $bg-color + @include menu-link-hover-state( null, null, null, var(--kt-primary), null ); + @include menu-link-here-state( null, null, null, var(--kt-primary), null ); + @include menu-link-show-state( null, null, null, var(--kt-primary), null ); + @include menu-link-active-state( null, null, null, var(--kt-primary), null ); + } +} diff --git a/src/_res/assets/sass/core/components/mixins/_buttons.scss b/src/_res/assets/sass/core/components/mixins/_buttons.scss new file mode 100644 index 0000000..fd8ee49 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_buttons.scss @@ -0,0 +1,84 @@ +// +// Button Mixins +// + +// Custom variant +@mixin button-custom-variant( + $color, + $icon-color, + $border-color, + $bg-color, + $color-active, + $icon-color-active, + $border-color-active, + $bg-color-active +) { + + @if ( $color != null ) { + color: $color; + } + + @if ( $icon-color != null ) { + i, + .svg-icon { + color: $icon-color; + } + + &.dropdown-toggle:after { + color: $icon-color; + } + } + + @if ( $border-color != null ) { + border-color: $border-color; + } + + @if ( $bg-color != null ) { + background-color: $bg-color; + } + + .btn-check:checked + &, + .btn-check:active + &, + &:focus:not(.btn-active), + &:hover:not(.btn-active), + &:active:not(.btn-active), + &.active, + &.show, + .show > & { + @if ( $color-active != null ) { + color: $color-active; + } + + @if ( $icon-color-active != null ) { + i, + .svg-icon { + color: $icon-color-active; + } + + &.dropdown-toggle:after { + color: $icon-color-active; + } + } + + @if ( $border-color-active != null ) { + border-color: $border-color-active; + } + + @if ( $bg-color-active != null ) { + background-color: $bg-color-active !important; + } + } +} + +@mixin button-active-state() { + .btn-check:checked + &, + .btn-check:active + &, + &:focus:not(.btn-active), + &:hover:not(.btn-active), + &:active:not(.btn-active), + &.active, + &.show, + .show > & { + @content; + } +} diff --git a/src/_res/assets/sass/core/components/mixins/_ki.scss b/src/_res/assets/sass/core/components/mixins/_ki.scss new file mode 100644 index 0000000..c83273a --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_ki.scss @@ -0,0 +1,18 @@ +// +// Keenthemes Icons +// + +@mixin ki($icon) { + font-family: Ki; + font-style: normal; + font-weight: normal; + font-variant: normal; + line-height: 1; + text-decoration: inherit; + text-rendering: optimizeLegibility; + text-transform: none; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-smoothing: antialiased; + content: "#{$icon}"; +} diff --git a/src/_res/assets/sass/core/components/mixins/_menu.scss b/src/_res/assets/sass/core/components/mixins/_menu.scss new file mode 100644 index 0000000..f407618 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_menu.scss @@ -0,0 +1,301 @@ +// +// Label +// + +// Set arrow direction +@mixin menu-link-arrow-rotate($angle, $angleRtl) { + /*rtl:ignore*/ + transform: rotateZ($angleRtl); + /*rtl:remove*/ + transform: rotateZ($angle); + transition: $menu-accordion-arrow-transition; +} + +// Set menu link padding x +@mixin menu-link-padding-x($value) { + // Menu item + .menu-item { + .menu-link, + .menu-content { + padding-left: $value; + padding-right: $value; + } + } +} + +// Set menu link padding y +@mixin menu-link-padding-y($value) { + // Menu item + .menu-item { + .menu-link, + .menu-content { + padding-top: $value; + padding-bottom: $value; + } + } +} + +// Set link indention +@mixin menu-link-indention($value, $offset) { + .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: calc(#{1 * $value} + #{$offset}); + } + + > .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: calc(#{2 * $value} + #{$offset}); + } + + > .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: calc(#{3 * $value} + #{$offset}); + } + + > .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: calc(#{4 * $value} + #{$offset}); + } + } + } + } + } + } + } + } + } + + &.menu-fit { + .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: #{$value}; + padding-right: 0; + } + + > .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: calc(#{2 * $value}); + padding-right: 0; + } + + > .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: calc(#{3 * $value}); + padding-right: 0; + } + + > .menu-sub:not([data-popper-placement]) { + > .menu-item, + > .menu-inner > .menu-item { + > .menu-content, + > .menu-link { + padding-left: calc(#{4 * $value}); + padding-right: 0; + } + } + } + } + } + } + } + } + } + } +} + +// Set sub indention +@mixin menu-sub-indention($value) { + .menu-sub:not([data-popper-placement]) { + margin-left: $value; + } +} + +// Set menu link theme +@mixin menu-link-theme($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color: null) { + @if ( $bg-color != null ) { + background-color: $bg-color; + } + + @if ( $title-color != null ) { + color: $title-color; + + .menu-title { + color: $title-color; + } + } + + @if ( $icon-color != null ) { + .menu-icon { + &, + .svg-icon, + i { + color: $icon-color; + } + } + } + + @if ( $bullet-color != null ) { + .menu-bullet { + .bullet { + background-color: $bullet-color; + } + } + } + + @if ( $arrow-color != null ) { + // Arrow + .menu-arrow:after { + @include svg-bg-icon(arrow-start, $arrow-color); + /*rtl:begin:remove*/ + @include svg-bg-icon(arrow-end, $arrow-color); + /*rtl:end:remove*/ + } + } +} + +// Set menu link default state +@mixin menu-link-default-state($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color: null, $all-links: true) { + $sel: ''; + + @if ($all-links == false) { + $sel: '& > '; + } + + #{$sel}.menu-link { + @include menu-link-theme($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color); + } +} + +// Set menu link hover state +@mixin menu-link-hover-state($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color: null, $all-links: true) { + $sel: '&:not(.here) '; + + @if ($all-links == false) { + $sel: '&:not(.here) > '; + } + + &.hover:not(.here) > .menu-link:not(.disabled):not(.active):not(.here), + #{$sel}.menu-link:hover:not(.disabled):not(.active):not(.here) { + transition: $transition-link; + + @include menu-link-theme($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color); + } +} + +// Set menu link active state +@mixin menu-link-active-state($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color: null, $all-links: true) { + $sel: ''; + + @if ($all-links == false) { + $sel: '& > '; + } + + #{$sel}.menu-link.active { + transition: $transition-link; + + @include menu-link-theme($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color); + } +} + +// Set menu link show state +@mixin menu-link-show-state($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color: null, $all-links: true) { + //&.here > .menu-link, + &.show > .menu-link { + transition: $transition-link; + + @include menu-link-theme($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color); + } +} + +// Set menu link here state +@mixin menu-link-here-state($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color: null, $all-links: true) { + &.here > .menu-link { + transition: $transition-link; + + @include menu-link-theme($title-color, $icon-color, $bullet-color, $arrow-color, $bg-color); + } +} + +// Set menu link default +@mixin menu-link-default($all-links: true) { + $sel: ''; + + @if ($all-links == false) { + $sel: '& > '; + } + + #{$sel}.menu-link { + @content; + } +} + +// Set menu link hover +@mixin menu-link-hover($all-links: true) { + $sel: '&:not(.here) '; + + @if ($all-links == false) { + $sel: '&:not(.here) > '; + } + + &.hover:not(.here) > .menu-link:not(.disabled):not(.active):not(.here), + #{$sel}.menu-link:hover:not(.disabled):not(.active):not(.here) { + transition: $transition-link; + + @content; + } +} + +// Set menu link active +@mixin menu-link-active($all-links: true) { + $sel: ''; + + @if ($all-links == false) { + $sel: '& > '; + } + + #{$sel}.menu-link.active { + transition: $transition-link; + + @content; + } +} + +// Set menu link show +@mixin menu-link-show($all-links: true) { + //&.here > .menu-link, + &.show > .menu-link { + transition: $transition-link; + + @content; + } +} + +// Set menu link here +@mixin menu-link-here($all-links: true) { + &.here > .menu-link { + transition: $transition-link; + + @content; + } +} diff --git a/src/_res/assets/sass/core/components/mixins/_popover.scss b/src/_res/assets/sass/core/components/mixins/_popover.scss new file mode 100644 index 0000000..d9f9b0d --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_popover.scss @@ -0,0 +1,74 @@ +// +// Popover Mixin +// + +@mixin popover-theme($bg-color, $border-color, $header-bg-color, $header-color, $body-color, $arrow-outer-color, $arrow-color) { + background-color: $bg-color; + border: 0; + + // Header + .popover-header { + background-color: $header-bg-color; + color: $header-color; + border-bottom-color: $border-color; + } + + // Body + .popover-body { + color: $body-color; + } + + // Arrows + &.bs-popover-top { + > .popover-arrow { + &::before { + border-top-color: $arrow-outer-color; + } + + &::after { + border-top-color: $arrow-color; + } + } + } + + &.bs-popover-end { + > .popover-arrow { + &::before { + border-right-color: $arrow-outer-color; + } + + &::after { + border-right-color: $arrow-color; + } + } + } + + &.bs-popover-bottom { + > .popover-arrow { + &::before { + border-bottom-color: $arrow-outer-color; + } + + &::after { + border-bottom-color: $arrow-color; + } + } + + // This will remove the popover-header's border just below the arrow + .popover-header::before { + border-bottom-color: $header-bg-color; + } + } + + &.bs-popover-start { + > .popover-arrow { + &::before { + border-left-color: $arrow-outer-color; + } + + &::after { + border-left-color: $arrow-color; + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/mixins/_scroll.scss b/src/_res/assets/sass/core/components/mixins/_scroll.scss new file mode 100644 index 0000000..e1bd6f7 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_scroll.scss @@ -0,0 +1,34 @@ +// +// Scroll mixins +// + +@mixin scrollbar-color($color, $hover-color: null) { + // Firefox + scrollbar-color: $color transparent; + + // Webkit + &::-webkit-scrollbar-thumb { + background-color: $color; + } + + &::-webkit-scrollbar-corner { + background-color: transparent; + } + + @if ($hover-color != null) { + // Hover state + &:hover { + // Firefox + scrollbar-color: $hover-color transparent; + + // Webkit + &::-webkit-scrollbar-thumb { + background-color: $hover-color; + } + + &::-webkit-scrollbar-corner { + background-color: transparent; + } + } + } +} diff --git a/src/_res/assets/sass/core/components/mixins/_shape.scss b/src/_res/assets/sass/core/components/mixins/_shape.scss new file mode 100644 index 0000000..3395df0 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_shape.scss @@ -0,0 +1,29 @@ + +@use 'sass:math'; + +@mixin shape($edges-number: 6, $main-radius: 30%, $rounding-radius: 10%, $rotated: true, $precision: 20) { + $central-angle: divide(360deg, $edges-number); + $angle: ($edges-number - 2) * divide(180deg, $edges-number); + $max-var-angle: 2 * (90deg - divide($angle, 2)); + $precision: 6; + $unit-var-angle: divide($max-var-angle, $precision); + $r-diff: $main-radius + $rounding-radius; + + $points: (); + + @for $i from 0 to $edges-number { + $vertex-angle: $i * $central-angle + if($rotated, -90deg, 0deg); + $vertex-x: 50% + $r-diff * math.cos($vertex-angle); + $vertex-y: 50% + $r-diff * math.sin($vertex-angle); + + @for $j from 0 through $precision { + $curr-angle: $vertex-angle + ($j - 0.5 * $precision) * $unit-var-angle; + $x: $vertex-x + $rounding-radius * math.cos($curr-angle); + $y: $vertex-y + $rounding-radius * math.sin($curr-angle); + + $points: $points, $x $y; + } + } + + clip-path: polygon($points); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/mixins/_svg-bg-icon.scss b/src/_res/assets/sass/core/components/mixins/_svg-bg-icon.scss new file mode 100644 index 0000000..48ee125 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_svg-bg-icon.scss @@ -0,0 +1,68 @@ +// +// SVG Bg Icons +// + +@mixin svg-bg-icon($type, $color: none, $update: false) { + $bg-image: ''; + + // Icon type; + @if ($type == close) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == check) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == arrow-top) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == arrow-bottom) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == arrow-start) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == arrow-end) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == sort) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == sort-asc) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == sort-desc) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == expand) { + $bg-image: url("data:image/svg+xml,"); + } + + @if ($type == collapse) { + $bg-image: url("data:image/svg+xml,"); + } + + // Icon style + @if $update == false { + mask-repeat: no-repeat; + mask-position: center; + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center; + } + + @if $color != none { + background-color: $color; + } + + -webkit-mask-image: escape-svg($bg-image); + mask-image: escape-svg($bg-image); +} + diff --git a/src/_res/assets/sass/core/components/mixins/_svg-icon.scss b/src/_res/assets/sass/core/components/mixins/_svg-icon.scss new file mode 100644 index 0000000..35da08c --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_svg-icon.scss @@ -0,0 +1,11 @@ +// +// SVG Icon +// + + +@mixin svg-icon-size($size, $important: false) { + svg { + height: $size valueif($important, !important, null); + width: $size valueif($important, !important, null); + } +} diff --git a/src/_res/assets/sass/core/components/mixins/_symbol.scss b/src/_res/assets/sass/core/components/mixins/_symbol.scss new file mode 100644 index 0000000..904f394 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_symbol.scss @@ -0,0 +1,42 @@ +// +// Symbol +// + +@mixin symbol-size($size) { + > img { + width: $size; + height: $size; + } + + .symbol-label { + width: $size; + height: $size; + } + + &.symbol-fixed { + .symbol-label { + width: $size; + height: $size; + } + + > img { + width: $size; + height: $size; + max-width: none; + } + } + + // Ratios + &.symbol-2by3 { + .symbol-label { + height: $size; + width: $size * divide(3, 2); + } + + > img { + height: $size; + width: $size * divide(3, 2); + max-width: none; + } + } +} diff --git a/src/_res/assets/sass/core/components/mixins/_theme-mode.scss b/src/_res/assets/sass/core/components/mixins/_theme-mode.scss new file mode 100644 index 0000000..02eee57 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_theme-mode.scss @@ -0,0 +1,15 @@ +// +// Theme Mode +// + +@mixin theme-light() { + html:not([data-theme="dark"]) { + @content; + } +} + +@mixin theme-dark() { + [data-theme="dark"] { + @content; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/mixins/_tooltip.scss b/src/_res/assets/sass/core/components/mixins/_tooltip.scss new file mode 100644 index 0000000..63269a2 --- /dev/null +++ b/src/_res/assets/sass/core/components/mixins/_tooltip.scss @@ -0,0 +1,43 @@ +// +// Tooltip Mixin +// + +@mixin tooltip-theme($bg-color, $color, $arrow-color) { + .tooltip-inner { + color: $color; + background-color: $bg-color; + } + + // Arrows + &.bs-tooltip-top { + .tooltip-arrow { + &::before { + border-top-color: $arrow-color; + } + } + } + + &.bs-tooltip-end { + .tooltip-arrow { + &::before { + border-right-color: $arrow-color; + } + } + } + + &.bs-tooltip-bottom { + .tooltip-arrow { + &::before { + border-bottom-color: $arrow-color; + } + } + } + + &.bs-tooltip-start { + .tooltip-arrow { + &::before { + border-left-color: $arrow-color; + } + } + } +} diff --git a/src/_res/assets/sass/core/components/stepper/_base.scss b/src/_res/assets/sass/core/components/stepper/_base.scss new file mode 100644 index 0000000..9e23710 --- /dev/null +++ b/src/_res/assets/sass/core/components/stepper/_base.scss @@ -0,0 +1,102 @@ +// +// Stepper +// + +// Base +.stepper { + // Content + [data-kt-stepper-element="info"], + [data-kt-stepper-element="content"] { + display: none; + + &.current { + display: flex; + } + } + + // Enable cursor pointer on clickable steppers + .stepper-item[data-kt-stepper-action="step"] { + cursor: pointer; + } + + // States + & { + [data-kt-stepper-action="final"] { + display: none; + } + + [data-kt-stepper-action="previous"] { + display: none; + } + + [data-kt-stepper-action="next"] { + display: inline-block; + } + + [data-kt-stepper-action="submit"] { + display: none; + } + } + + &.first { + [data-kt-stepper-action="previous"] { + display: none; + } + + [data-kt-stepper-action="next"] { + display: inline-block; + } + + [data-kt-stepper-action="submit"] { + display: none; + } + } + + &.between { + [data-kt-stepper-action="previous"] { + display: inline-block; + } + + [data-kt-stepper-action="next"] { + display: inline-block; + } + + [data-kt-stepper-action="submit"] { + display: none; + } + } + + &.last { + [data-kt-stepper-action="final"] { + display: inline-block; + } + + [data-kt-stepper-action="final"].btn-flex { + display: flex; + } + + [data-kt-stepper-action="previous"] { + display: inline-block; + } + + [data-kt-stepper-action="previous"].btn-flex { + display: flex; + } + + [data-kt-stepper-action="next"] { + display: none; + } + + [data-kt-stepper-action="next"].btn-flex { + display: flex; + } + + [data-kt-stepper-action="submit"] { + display: inline-block; + } + + [data-kt-stepper-action="submit"].btn-flex { + display: flex; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/stepper/_links.scss b/src/_res/assets/sass/core/components/stepper/_links.scss new file mode 100644 index 0000000..048ec51 --- /dev/null +++ b/src/_res/assets/sass/core/components/stepper/_links.scss @@ -0,0 +1,57 @@ +// +// Stepper Links +// + +// Base +.stepper.stepper-links { + .stepper-nav { + display: flex; + margin: 0 auto; + justify-content: center; + align-items: center; + flex-wrap: wrap; + + .stepper-item { + position: relative; + flex-shrink: 0; + margin: 1rem 1.5rem; + + &:after { + content: " "; + position: absolute; + top: 2.3rem; + left: 0; + height: 2px; + width: 100%; + background-color: transparent; + transition: $transition-link; + } + + .stepper-title { + color: var(--kt-dark); + font-weight: 600; + font-size: 1.25rem; + } + + // Current + &.current { + transition: $transition-link; + + .stepper-title { + color: var(--kt-primary); + } + + &:after { + background-color: var(--kt-primary); + } + } + + &.current.mark-completed:last-child, + &.completed { + .stepper-title { + color: var(--kt-gray-400); + } + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/components/stepper/_pills.scss b/src/_res/assets/sass/core/components/stepper/_pills.scss new file mode 100644 index 0000000..9f1c222 --- /dev/null +++ b/src/_res/assets/sass/core/components/stepper/_pills.scss @@ -0,0 +1,201 @@ +// +// Stepper Pills +// + +// Base +.stepper.stepper-pills { + --kt-stepper-pills-size: 40px; + --kt-stepper-icon-border-radius: 9px; + --kt-stepper-icon-check-size: 1rem; + + --kt-stepper-icon-bg-color: var(--kt-primary-light); + --kt-stepper-icon-bg-color-current: var(--kt-primary); + --kt-stepper-icon-bg-color-completed: var(--kt-primary-light); + + --kt-stepper-icon-border: 0; + --kt-stepper-icon-border-current: 0; + --kt-stepper-icon-border-completed: 0; + + --kt-stepper-icon-number-color: var(--kt-primary); + --kt-stepper-icon-number-color-current: var(--kt-white); + + --kt-stepper-icon-check-color-completed: var(--kt-primary); + + --kt-stepper-label-title-opacity: 1; + --kt-stepper-label-title-opacity-current: 1; + --kt-stepper-label-title-opacity-completed: 1; + + --kt-stepper-label-title-color: var(--kt-gray-800); + --kt-stepper-label-title-color-current: var(--kt-gray-600); + --kt-stepper-label-title-color-completed: var(--kt-text-muted); + + --kt-stepper-label-desc-opacity: 1; + --kt-stepper-label-desc-opacity-current: 1; + --kt-stepper-label-desc-opacity-completed: 1; + + --kt-stepper-label-desc-color: var(--kt-text-muted); + --kt-stepper-label-desc-color-current: var(--kt-text-400); + --kt-stepper-label-desc-color-completed: var(--kt-gray-400); + + --kt-stepper-line-border: 1px dashed var(--kt-gray-300); + + // Nav + .stepper-nav { + display: flex; + } + + // Item + .stepper-item { + display: flex; + align-items: center; + transition: $transition-link; + + // Icon + .stepper-icon { + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + transition: $transition-link; + width: var(--kt-stepper-pills-size); + height: var(--kt-stepper-pills-size); + border-radius: var(--kt-stepper-icon-border-radius); + background-color: var(--kt-stepper-icon-bg-color); + border: var(--kt-stepper-icon-border); + margin-right: 1.5rem; + + .stepper-check { + display: none; + font-size: var(--kt-stepper-icon-check-size); + } + + .stepper-number { + font-weight: $font-weight-bold; + color: var(--kt-stepper-icon-number-color); + font-size: 1.25rem; + } + } + + // Label + .stepper-label { + display: flex; + flex-direction: column; + justify-content: center; + + .stepper-title { + color: var(--kt-stepper-label-title-color); + opacity: var(--kt-stepper-label-title-opacity); + font-weight: 600; + font-size: 1.25rem; + margin-bottom: .3rem; + } + + .stepper-desc { + opacity: var(--kt-stepper-label-desc-opacity); + color: var(--kt-stepper-label-desc-color); + } + } + + // Current + &.current { + transition: $transition-link; + + .stepper-icon { + transition: $transition-link; + background-color: var(--kt-stepper-icon-bg-color-current); + border: var(--kt-stepper-icon-border-current); + + .stepper-check { + display: none; + } + + .stepper-number { + color: var(--kt-stepper-icon-number-color-current); + font-size: 1.35rem; + } + } + + .stepper-label { + .stepper-title { + opacity: var(--kt-stepper-label-title-opacity-current); + color: var(--kt-stepper-label-title-color-current); + } + + .stepper-desc { + opacity: var(--kt-stepper-label-desc-opacity-current); + color: var(--kt-stepper-label-desc-color-current); + } + } + } + + // Completed + &.current.mark-completed:last-child, + &.completed { + .stepper-icon { + transition: $transition-link; + background-color: var(--kt-stepper-icon-bg-color-completed); + border: var(--kt-stepper-icon-border-completed); + + .stepper-check { + color: var(--kt-stepper-icon-check-color-completed); + display: inline-block; + } + + .stepper-number { + display: none; + } + } + + .stepper-label { + .stepper-title { + opacity: var(--kt-stepper-label-title-opacity-completed); + color: var(--kt-stepper-label-title-color-completed); + } + + .stepper-desc { + opacity: var(--kt-stepper-label-desc-opacity-completed); + color: var(--kt-stepper-label-desc-color-completed); + } + } + } + } + + // Column + &.stepper-column { + // Nav + .stepper-nav { + flex-direction: column; + align-items: start; + } + + // Item + .stepper-item { + flex-direction: column; + justify-content: start; + align-items: stretch; + padding: 0; + margin: 0; + } + + // Wrapper + .stepper-wrapper { + display: flex; + align-items: center; + } + + // Icon + .stepper-icon { + z-index: 1; + } + + // Line + .stepper-line { + display: block; + flex-grow: 1; + margin-left: calc(var(--kt-stepper-pills-size) / 2); + border-left: var(--kt-stepper-line-border); + margin-top: 2px; + margin-bottom: 2px; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/_base.scss b/src/_res/assets/sass/core/layout/_base.scss new file mode 100644 index 0000000..a2d8e61 --- /dev/null +++ b/src/_res/assets/sass/core/layout/_base.scss @@ -0,0 +1,50 @@ +// +// Root +// + +html { + font-family: sans-serif; + text-size-adjust: 100%; +} + +html, +body { + height: 100%; + margin: 0px; + padding: 0px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: $root-font-size !important; + font-weight: $font-weight-base; + font-family: $font-family-sans-serif; + + // Tablet mode + @include media-breakpoint-down(lg) { + font-size: $root-font-size-lg !important; + } + + // Mobile mode + @include media-breakpoint-down(md) { + font-size: $root-font-size-md !important; + } +} + +body { + display: flex; + flex-direction: column; + + a:hover, + a:active, + a:focus { + text-decoration: none !important; + } +} + +canvas { + user-select: none; +} + +// Angular integration +router-outlet { + display: none; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_container.scss b/src/_res/assets/sass/core/layout/base/_container.scss new file mode 100644 index 0000000..8e19b06 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_container.scss @@ -0,0 +1,30 @@ +// +// Container +// + +// Desktop mode +@include media-breakpoint-up(lg) { + .app-container { + padding-left: $app-container-padding-x !important; + padding-right: $app-container-padding-x !important; + } + + .app-container-fit-desktop { + padding-left: 0 !important; + padding-right: 0 !important; + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .app-container { + max-width: none; + padding-left: $app-container-padding-x-mobile !important; + padding-right: $app-container-padding-x-mobile !important; + } + + .app-container-fit-mobile { + padding-left: 0 !important; + padding-right: 0 !important; + } +} diff --git a/src/_res/assets/sass/core/layout/base/_content.scss b/src/_res/assets/sass/core/layout/base/_content.scss new file mode 100644 index 0000000..6f9992e --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_content.scss @@ -0,0 +1,24 @@ +// +// Content +// + +// Desktop mode +@include media-breakpoint-up(lg) { + .app-content { + padding-top: $app-content-padding-y; + padding-bottom: $app-content-padding-y; + padding-left: $app-content-padding-x; + padding-right: $app-content-padding-x; + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .app-content { + max-width: none; + padding-top: $app-content-padding-y-mobile; + padding-bottom: $app-content-padding-y-mobile; + padding-left: $app-content-padding-x-mobile; + padding-right: $app-content-padding-x-mobile; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_footer.scss b/src/_res/assets/sass/core/layout/base/_footer.scss new file mode 100644 index 0000000..015a185 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_footer.scss @@ -0,0 +1,103 @@ +// +// Footer +// + +// General mode +.app-footer { + transition: $app-footer-transition; + display: flex; + align-items: stretch; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-footer { + @include property( z-index, $app-footer-z-index); + + background-color: var(--kt-app-footer-bg-color); + box-shadow: var(--kt-app-footer-box-shadow); + border-top: var(--kt-app-footer-border-top); + } + + // Vars + :root { + --kt-app-footer-height: #{$app-footer-height}; + } + + // States + .app-footer { + height: var(--kt-app-footer-height); + + [data-kt-app-footer-fixed="true"] & { + @include property( z-index, $app-footer-fixed-z-index); + position: fixed; + left: 0; + right: 0; + bottom: 0; + } + } + + // Integration + .app-footer { + // Sidebar + [data-kt-app-sidebar-fixed="true"][data-kt-app-sidebar-push-footer="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + // Sidebar Panel + [data-kt-app-sidebar-panel-fixed="true"][data-kt-app-sidebar-panel-push-footer="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + + // Aside + [data-kt-app-aside-fixed="true"][data-kt-app-aside-push-footer="true"] & { + right: calc( + var(--kt-app-aside-width) + + var(--kt-app-aside-gap-start, 0px) + + var(--kt-app-aside-gap-end, 0px) + ); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-footer { + @include property( z-index, $app-footer-z-index-mobile); + + background-color: var(--kt-app-footer-bg-color-mobile); + box-shadow: var(--kt-app-footer-box-shadow-mobile); + border-top: var(--kt-app-footer-border-top-mobile); + } + + // Vars + body { + --kt-app-footer-height: #{$app-footer-height-mobile}; + } + + // States + .app-footer { + height: var(--kt-app-footer-height); + + [data-kt-app-footer-fixed-mobile="true"] & { + @include property( z-index, $app-footer-fixed-z-index-mobile); + position: fixed; + left: 0; + right: 0; + bottom: 0; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_hero.scss b/src/_res/assets/sass/core/layout/base/_hero.scss new file mode 100644 index 0000000..7f843f2 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_hero.scss @@ -0,0 +1,13 @@ +// +// Hero +// + +// General mode +.app-hero { + display: flex; + align-items: stretch; + background-color: var(--kt-app-hero-bg-color); + box-shadow: var(--kt-app-hero-box-shadow); + border-top: var(--kt-app-hero-border-top); + border-bottom: var(--kt-app-hero-border-bottom); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_layout-builder.scss b/src/_res/assets/sass/core/layout/base/_layout-builder.scss new file mode 100644 index 0000000..513db2a --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_layout-builder.scss @@ -0,0 +1,19 @@ +// +// Layout builder +// + +// General mode +.app-layout-builder-toggle { + position: fixed; + z-index: $app-layout-builder-toggle-z-index; + bottom: $app-layout-builder-toggle-bottom; + right: $app-layout-builder-toggle-end; +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .app-layout-builder-toggle { + bottom: $app-layout-builder-toggle-bottom-mobile; + right: $app-layout-builder-toggle-end-mobile; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_layout.scss b/src/_res/assets/sass/core/layout/base/_layout.scss new file mode 100644 index 0000000..e5e3c96 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_layout.scss @@ -0,0 +1,28 @@ +// +// App Layout +// + +@import "mixins/layout-minimize"; +@import "mixins/layout-transition"; +@import "root"; +@import "reboot"; +@import "page"; +@import "page-loader"; +@import "container"; +@import "print"; +@import "navbar"; +@import "header/header"; +@import "header/header-primary"; +@import "header/header-secondary"; +@import "toolbar"; +@import "hero"; +@import "sidebar/sidebar"; +@import "sidebar/sidebar-primary"; +@import "sidebar/sidebar-secondary"; +@import "sidebar/sidebar-panel"; +@import "aside/aside"; +@import "wrapper"; +@import "main"; +@import "content"; +@import "footer"; +@import "layout-builder"; \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_main.scss b/src/_res/assets/sass/core/layout/base/_main.scss new file mode 100644 index 0000000..1d25756 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_main.scss @@ -0,0 +1,75 @@ +// +// Main +// + +// General mode +.app-main { + display: flex; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-main { + transition: $app-main-transition; + + @include property( padding-left, $app-main-padding-x ); + @include property( padding-right, $app-main-padding-x ); + @include property( padding-top, $app-main-padding-y ); + @include property( padding-bottom, $app-main-padding-y ); + + @include property( margin-left, $app-main-margin-x ); + @include property( margin-right, $app-main-margin-x ); + @include property( margin-top, $app-main-margin-y ); + @include property( margin-bottom, $app-main-margin-y ); + } + + // Integration + .app-main { + // Sidebar + [data-kt-app-sidebar-sticky="true"] & { + margin-left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + // Sidebar Panel + [data-kt-app-sidebar-panel-sticky="true"] & { + margin-left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + + // Aside + [data-kt-app-aside-sticky="true"] & { + margin-right: calc( + var(--kt-app-aside-width) + + var(--kt-app-aside-gap-start, 0px) + + var(--kt-app-aside-gap-end, 0px) + ); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-main { + @include property( padding-left, $app-main-padding-x-mobile ); + @include property( padding-right, $app-main-padding-x-mobile ); + @include property( padding-top, $app-main-padding-y-mobile ); + @include property( padding-bottom, $app-main-padding-y-mobile ); + + @include property( margin-left, $app-main-margin-x-mobile ); + @include property( margin-right, $app-main-margin-x-mobile ); + @include property( margin-top, $app-main-margin-y-mobile ); + @include property( margin-bottom, $app-main-margin-y-mobile ); + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_navbar.scss b/src/_res/assets/sass/core/layout/base/_navbar.scss new file mode 100644 index 0000000..a6d329c --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_navbar.scss @@ -0,0 +1,19 @@ +// +// App Navbar +// + +.app-navbar { + display: flex; + align-items: stretch; + + .app-navbar-item { + display: flex; + align-items: center; + } + + &.app-navbar-stretch { + .app-navbar-item { + align-items: stretch; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_page-loader.scss b/src/_res/assets/sass/core/layout/base/_page-loader.scss new file mode 100644 index 0000000..8ed8bfd --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_page-loader.scss @@ -0,0 +1,31 @@ +// +// Page loader +// + +// CSS3 Transitions only after page load(data-kt-app-page-loading="on" attribute added to body tag and removed with JS on page loaded) +[data-kt-app-page-loading="on"] { + overflow: hidden; +} + +[data-kt-app-page-loading="on"] * { + transition: none !important; +} + +// Base +.app-page-loader { + background: var(--kt-body-bg); + color: var(--kt-body-color); + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + z-index: 10000; + display: none; + + [data-kt-app-page-loading="on"] & { + display: flex; + justify-content: center; + align-items: center; + } +} diff --git a/src/_res/assets/sass/core/layout/base/_page.scss b/src/_res/assets/sass/core/layout/base/_page.scss new file mode 100644 index 0000000..78ec216 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_page.scss @@ -0,0 +1,7 @@ +// +// Page +// + +.app-page { + display: flex; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_print.scss b/src/_res/assets/sass/core/layout/base/_print.scss new file mode 100644 index 0000000..c4c76cb --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_print.scss @@ -0,0 +1,34 @@ +// +// Print +// + +// Add .app-print-content-only class to body element in order to allow printing only the content area +@media print { + .app-print-content-only { + padding: 0 !important; + background: none !important; + + .app-wrapper, + .app-page, + .app-page-title, + .app-content, + .app-container { + background: none !important; + padding: 0 !important; + margin: 0 !important; + } + + .app-aside, + .app-aside-panel, + .app-sidebar, + .app-sidebar-panel, + .app-header, + .app-footer, + .app-toolbar, + .drawer, + .scrolltop, + .btn { + display: none !important; + } + } +} diff --git a/src/_res/assets/sass/core/layout/base/_reboot.scss b/src/_res/assets/sass/core/layout/base/_reboot.scss new file mode 100644 index 0000000..eaa8c5f --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_reboot.scss @@ -0,0 +1,65 @@ +// +// Reboot +// + +html { + font-family: sans-serif; + text-size-adjust: 100%; +} + +html, +body { + height: 100%; + margin: 0px; + padding: 0px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: $app-general-root-font-size-desktop !important; + font-weight: $font-weight-base; + font-family: $font-family-sans-serif; + + // Tablet mode + @include media-breakpoint-down(lg) { + font-size: $app-general-root-font-size-tablet !important; + } + + // Mobile mode + @include media-breakpoint-down(md) { + font-size: $app-general-root-font-size-mobile !important; + } +} + +body { + display: flex; + flex-direction: column; + + a:hover, + a:active, + a:focus { + text-decoration: none !important; + } +} + +canvas { + user-select: none; +} + +// Angular integration +router-outlet { + display: none; +} + +// Layouts +body, +.app-default { + background-color: var(--kt-app-bg-color); +} + +.app-blank { + background-color: var(--kt-app-blank-bg-color); +} + +// Reset CSS3 Transitions for child elements +[data-kt-app-reset-transition="true"] * { + transition: none !important; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_root.scss b/src/_res/assets/sass/core/layout/base/_root.scss new file mode 100644 index 0000000..f1c7ccd --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_root.scss @@ -0,0 +1,496 @@ +// +// Root +// + +:root, +[data-theme="light"] { + // Layouts + @include property(--kt-app-bg-color, $app-bg-color); + @include property(--kt-app-blank-bg-color, $app-blank-bg-color); + + // Header base + @include property(--kt-app-header-base-bg-color, $app-header-base-bg-color); + @include property(--kt-app-header-base-bg-color-mobile, $app-header-base-bg-color-mobile); + @include property(--kt-app-header-base-box-shadow, $app-header-base-box-shadow); + @include property(--kt-app-header-base-box-shadow-mobile, $app-header-base-box-shadow-mobile); + @include property(--kt-app-header-base-border-bottom, $app-header-base-border-bottom); + @include property(--kt-app-header-base-border-bottom-mobile, $app-header-base-border-bottom-mobile); + + // Header minimize + @include property(--kt-app-header-minimize-bg-color, $app-header-minimize-bg-color); + @include property(--kt-app-header-minimize-bg-color-mobile, $app-header-minimize-bg-color-mobile); + @include property(--kt-app-header-minimize-box-shadow, $app-header-minimize-box-shadow); + @include property(--kt-app-header-minimize-box-shadow-mobile, $app-header-minimize-box-shadow-mobile); + @include property(--kt-app-header-minimize-border-bottom, $app-header-minimize-border-bottom); + @include property(--kt-app-header-minimize-border-bottom-mobile, $app-header-minimize-border-bottom-mobile); + + // Header sticky + @include property(--kt-app-header-sticky-bg-color, $app-header-sticky-bg-color); + @include property(--kt-app-header-sticky-bg-color-mobile, $app-header-sticky-bg-color-mobile); + @include property(--kt-app-header-sticky-box-shadow, $app-header-sticky-box-shadow); + @include property(--kt-app-header-sticky-box-shadow-mobile, $app-header-sticky-box-shadow-mobile); + @include property(--kt-app-header-sticky-border-bottom, $app-header-sticky-border-bottom); + @include property(--kt-app-header-sticky-border-bottom-mobile, $app-header-sticky-border-bottom-mobile); + + // Header primary + @include property(--kt-app-header-primary-base-bg-color, $app-header-primary-base-bg-color); + @include property(--kt-app-header-primary-base-bg-color-mobile, $app-header-primary-base-bg-color-mobile); + @include property(--kt-app-header-primary-base-box-shadow, $app-header-primary-base-box-shadow); + @include property(--kt-app-header-primary-base-box-shadow-mobile, $app-header-primary-base-box-shadow-mobile); + @include property(--kt-app-header-primary-base-border-bottom, $app-header-primary-base-border-bottom); + @include property(--kt-app-header-primary-base-border-bottom-mobile, $app-header-primary-base-border-bottom-mobile); + + @include property(--kt-app-header-primary-minimize-bg-color, $app-header-primary-minimize-bg-color); + @include property(--kt-app-header-primary-minimize-box-shadow, $app-header-primary-minimize-box-shadow); + @include property(--kt-app-header-primary-minimize-border-top, $app-header-primary-minimize-border-top); + @include property(--kt-app-header-primary-minimize-border-bottom, $app-header-primary-minimize-border-bottom); + + @include property(--kt-app-header-primary-sticky-bg-color, $app-header-primary-sticky-bg-color); + @include property(--kt-app-header-primary-sticky-box-shadow, $app-header-primary-sticky-box-shadow); + @include property(--kt-app-header-primary-sticky-border-top, $app-header-primary-sticky-border-top); + @include property(--kt-app-header-primary-sticky-border-bottom, $app-header-primary-sticky-border-bottom); + + // Header secondary + @include property(--kt-app-header-secondary-base-bg-color, $app-header-secondary-base-bg-color); + @include property(--kt-app-header-secondary-base-bg-color-mobile, $app-header-secondary-base-bg-color-mobile); + @include property(--kt-app-header-secondary-base-box-shadow, $app-header-secondary-base-box-shadow); + @include property(--kt-app-header-secondary-base-box-shadow-mobile, $app-header-secondary-base-box-shadow-mobile); + @include property(--kt-app-header-secondary-base-border-top, $app-header-secondary-base-border-top); + @include property(--kt-app-header-secondary-base-border-bottom, $app-header-secondary-base-border-bottom); + @include property(--kt-app-header-secondary-base-border-start-mobile, $app-header-secondary-base-border-bottom); + @include property(--kt-app-header-secondary-base-border-end-mobile, $app-header-secondary-base-border-end-mobile); + + // Header secondary minimize + @include property(--kt-app-header-secondary-minimize-bg-color, $app-header-secondary-minimize-bg-color); + @include property(--kt-app-header-secondary-minimize-box-shadow, $app-header-secondary-minimize-box-shadow); + @include property(--kt-app-header-secondary-minimize-border-top, $app-header-secondary-minimize-border-top); + @include property(--kt-app-header-secondary-minimize-border-bottom, $app-header-secondary-minimize-border-bottom); + + // Header secondary sticky + @include property(--kt-app-header-secondary-sticky-bg-color, $app-header-secondary-sticky-bg-color); + @include property(--kt-app-header-secondary-sticky-box-shadow, $app-header-secondary-sticky-box-shadow); + @include property(--kt-app-header-secondary-sticky-border-top, $app-header-secondary-sticky-border-top); + @include property(--kt-app-header-secondary-sticky-border-bottom, $app-header-secondary-sticky-border-bottom); + + // Toolbar base + @include property(--kt-app-toolbar-base-bg-color, $app-toolbar-base-bg-color); + @include property(--kt-app-toolbar-base-bg-color-mobile, $app-toolbar-base-bg-color-mobile); + @include property(--kt-app-toolbar-base-box-shadow, $app-toolbar-base-box-shadow); + @include property(--kt-app-toolbar-base-box-shadow-mobile, $app-toolbar-base-box-shadow-mobile); + @include property(--kt-app-toolbar-base-border-top, $app-toolbar-base-border-top); + @include property(--kt-app-toolbar-base-border-top-mobile, $app-toolbar-base-border-top-mobile); + @include property(--kt-app-toolbar-base-border-bottom, $app-toolbar-base-border-bottom); + @include property(--kt-app-toolbar-base-border-bottom-mobile, $app-toolbar-base-border-bottom); + + // Toolbar minimize + @include property(--kt-app-toolbar-minimize-bg-color, $app-toolbar-minimize-bg-color); + @include property(--kt-app-toolbar-minimize-bg-color-mobile, $app-toolbar-minimize-bg-color-mobile); + @include property(--kt-app-toolbar-minimize-box-shadow, $app-toolbar-minimize-box-shadow); + @include property(--kt-app-toolbar-minimize-box-shadow-mobile, $app-toolbar-minimize-box-shadow-mobile); + @include property(--kt-app-toolbar-minimize-border-top, $app-toolbar-minimize-border-top); + @include property(--kt-app-toolbar-minimize-border-top-mobile, $app-toolbar-minimize-border-top-mobile); + @include property(--kt-app-toolbar-minimize-border-bottom, $app-toolbar-minimize-border-bottom); + @include property(--kt-app-toolbar-minimize-border-bottom-mobile, $app-toolbar-minimize-border-bottom-mobile); + + // Toolbar sticky + @include property(--kt-app-toolbar-sticky-bg-color, $app-toolbar-sticky-bg-color); + @include property(--kt-app-toolbar-sticky-bg-color-mobile, $app-toolbar-sticky-bg-color-mobile); + @include property(--kt-app-toolbar-sticky-box-shadow, $app-toolbar-sticky-box-shadow); + @include property(--kt-app-toolbar-sticky-box-shadow-mobile, $app-toolbar-sticky-box-shadow-mobile); + @include property(--kt-app-toolbar-sticky-border-top, $app-toolbar-sticky-border-top); + @include property(--kt-app-toolbar-sticky-border-top-mobile, $app-toolbar-sticky-border-top-mobile); + @include property(--kt-app-toolbar-sticky-border-bottom, $app-toolbar-sticky-border-bottom); + @include property(--kt-app-toolbar-sticky-border-bottom-mobile, $app-toolbar-sticky-border-bottom-mobile); + + // Sidebar base + @include property(--kt-app-sidebar-base-bg-color, $app-sidebar-base-bg-color); + @include property(--kt-app-sidebar-base-bg-color-mobile, $app-sidebar-base-bg-color-mobile); + @include property(--kt-app-sidebar-base-box-shadow, $app-sidebar-base-box-shadow); + @include property(--kt-app-sidebar-base-box-shadow-mobile, $app-sidebar-base-box-shadow-mobile); + @include property(--kt-app-sidebar-base-border-start, $app-sidebar-base-border-start); + @include property(--kt-app-sidebar-base-border-start-mobile, $app-sidebar-base-border-start-mobile); + @include property(--kt-app-sidebar-base-border-end, $app-sidebar-base-border-end); + @include property(--kt-app-sidebar-base-border-end-mobile, $app-sidebar-base-border-end-mobile); + + // Hero + @include property(--kt-app-hero-bg-color, $app-hero-bg-color); + @include property(--kt-app-hero-box-shadow, $app-hero-box-shadow); + @include property(--kt-app-hero-border-top, $app-hero-border-top); + @include property(--kt-app-hero-border-bottom, $app-hero-border-bottom); + + // Sidebar sticky + @include property(--kt-app-sidebar-sticky-bg-color, $app-sidebar-sticky-bg-color); + @include property(--kt-app-sidebar-sticky-box-shadow, $app-sidebar-sticky-box-shadow); + @include property(--kt-app-sidebar-sticky-border-start, $app-sidebar-sticky-border-start); + @include property(--kt-app-sidebar-sticky-border-end, $app-sidebar-sticky-border-end); + + // Sidebar minimize + @include property(--kt-app-sidebar-minimize-bg-color, $app-sidebar-minimize-bg-color); + @include property(--kt-app-sidebar-minimize-bg-color-mobile, $app-sidebar-minimize-bg-color-mobile); + @include property(--kt-app-sidebar-minimize-box-shadow, $app-sidebar-minimize-box-shadow); + @include property(--kt-app-sidebar-minimize-box-shadow-mobile, $app-sidebar-minimize-box-shadow-mobile); + @include property(--kt-app-sidebar-minimize-hover-box-shadow, $app-sidebar-minimize-hover-box-shadow); + @include property(--kt-app-sidebar-minimize-hover-box-shadow-mobile, $app-sidebar-minimize-hover-box-shadow-mobile); + @include property(--kt-app-sidebar-minimize-border-start, $app-sidebar-minimize-border-start); + @include property(--kt-app-sidebar-minimize-border-start-mobile, $app-sidebar-minimize-border-start-mobile); + @include property(--kt-app-sidebar-minimize-border-end, $app-sidebar-minimize-border-end); + @include property(--kt-app-sidebar-minimize-border-end-mobile, $app-sidebar-minimize-border-end-mobile); + + // Sidebar primary + @include property(--kt-app-sidebar-primary-base-bg-color, $app-sidebar-primary-base-bg-color); + @include property(--kt-app-sidebar-primary-base-bg-color-mobile, $app-sidebar-primary-base-bg-color-mobile); + @include property(--kt-app-sidebar-primary-base-box-shadow, $app-sidebar-primary-base-box-shadow); + @include property(--kt-app-sidebar-primary-base-box-shadow-mobile, $app-sidebar-primary-base-box-shadow-mobile); + @include property(--kt-app-sidebar-primary-base-border-start, $app-sidebar-primary-base-border-start); + @include property(--kt-app-sidebar-primary-base-border-start-mobile, $app-sidebar-primary-base-border-start-mobile); + @include property(--kt-app-sidebar-primary-base-border-end, $app-sidebar-primary-base-border-end); + @include property(--kt-app-sidebar-primary-base-border-end-mobile, $app-sidebar-primary-base-border-end-mobile); + + // Sidebar primary minimize + @include property(--kt-app-sidebar-primary-minimize-bg-color, $app-sidebar-primary-base-border-end-mobile); + @include property(--kt-app-sidebar-primary-minimize-bg-color-mobile, $app-sidebar-primary-minimize-bg-color-mobile); + @include property(--kt-app-sidebar-primary-minimize-box-shadow, $app-sidebar-primary-minimize-box-shadow); + @include property(--kt-app-sidebar-primary-minimize-box-shadow-mobile, $app-sidebar-primary-minimize-box-shadow-mobile); + @include property(--kt-app-sidebar-primary-minimize-hover-box-shadow, $app-sidebar-primary-minimize-hover-box-shadow); + @include property(--kt-app-sidebar-primary-minimize-hover-box-shadow-mobile, $app-sidebar-primary-minimize-hover-box-shadow-mobile); + @include property(--kt-app-sidebar-primary-minimize-border-start, $app-sidebar-primary-minimize-border-start); + @include property(--kt-app-sidebar-primary-minimize-border-start-mobile, $app-sidebar-primary-minimize-border-start-mobile); + @include property(--kt-app-sidebar-primary-minimize-border-end, $app-sidebar-primary-minimize-border-end); + @include property(--kt-app-sidebar-primary-minimize-border-end-mobile, $app-sidebar-primary-minimize-border-end-mobile); + + // Sidebar secondary base + @include property(--kt-app-sidebar-secondary-base-bg-color, $app-sidebar-secondary-base-bg-color); + @include property(--kt-app-sidebar-secondary-base-bg-color-mobile, $app-sidebar-secondary-base-bg-color-mobile); + @include property(--kt-app-sidebar-secondary-base-box-shadow, $app-sidebar-secondary-base-box-shadow); + @include property(--kt-app-sidebar-secondary-base-box-shadow-mobile, $app-sidebar-secondary-base-box-shadow-mobile); + @include property(--kt-app-sidebar-secondary-base-border-start, $app-sidebar-secondary-base-border-start); + @include property(--kt-app-sidebar-secondary-base-border-start-mobile, $app-sidebar-secondary-base-border-start-mobile); + @include property(--kt-app-sidebar-secondary-base-border-end, $app-sidebar-secondary-base-border-end); + @include property(--kt-app-sidebar-secondary-base-border-end-mobile, $app-sidebar-secondary-base-border-end-mobile); + + // Sidebar secondary minimize + @include property(--kt-app-sidebar-secondary-minimize-bg-color, $app-sidebar-secondary-minimize-bg-color); + @include property(--kt-app-sidebar-secondary-minimize-bg-color-mobile, $app-sidebar-secondary-minimize-bg-color-mobile); + @include property(--kt-app-sidebar-secondary-minimize-box-shadow, $app-sidebar-secondary-minimize-box-shadow); + @include property(--kt-app-sidebar-secondary-minimize-box-shadow-mobile, $app-sidebar-secondary-minimize-box-shadow-mobile); + @include property(--kt-app-sidebar-secondary-minimize-hover-box-shadow, $app-sidebar-secondary-minimize-hover-box-shadow); + @include property(--kt-app-sidebar-secondary-minimize-hover-box-shadow-mobile, $app-sidebar-secondary-minimize-hover-box-shadow-mobile); + @include property(--kt-app-sidebar-secondary-minimize-border-start, $app-sidebar-secondary-minimize-border-start); + @include property(--kt-app-sidebar-secondary-minimize-border-start-mobile, $app-sidebar-secondary-minimize-border-start-mobile); + @include property(--kt-app-sidebar-secondary-minimize-border-end, $app-sidebar-secondary-minimize-border-end); + @include property(--kt-app-sidebar-secondary-minimize-border-end-mobile, $app-sidebar-secondary-minimize-border-end-mobile); + + // Sidebar panel base + @include property(--kt-app-sidebar-panel-base-bg-color, $app-sidebar-panel-base-bg-color); + @include property(--kt-app-sidebar-panel-base-bg-color-mobile, $app-sidebar-panel-base-bg-color-mobile); + @include property(--kt-app-sidebar-panel-base-box-shadow, $app-sidebar-panel-base-box-shadow); + @include property(--kt-app-sidebar-panel-base-box-shadow-mobile, $app-sidebar-panel-base-box-shadow-mobile); + @include property(--kt-app-sidebar-panel-base-border-start, $app-sidebar-panel-base-border-start); + @include property(--kt-app-sidebar-panel-base-border-start-mobile, $app-sidebar-panel-base-border-start-mobile); + @include property(--kt-app-sidebar-panel-base-border-end, $app-sidebar-panel-base-border-end); + @include property(--kt-app-sidebar-panel-base-border-end-mobile, $app-sidebar-panel-base-border-end-mobile); + + // Sidebar panel sticky + @include property(--kt-app-sidebar-panel-sticky-bg-color, $app-sidebar-panel-sticky-bg-color); + @include property(--kt-app-sidebar-panel-sticky-box-shadow, $app-sidebar-panel-sticky-box-shadow); + @include property(--kt-app-sidebar-panel-sticky-border-start, $app-sidebar-panel-sticky-border-start); + @include property(--kt-app-sidebar-panel-sticky-border-end, $app-sidebar-panel-sticky-border-end); + + // Sidebar panel minimize + @include property(--kt-app-sidebar-panel-minimize-bg-color, $app-sidebar-panel-minimize-bg-color); + @include property(--kt-app-sidebar-panel-minimize-bg-color-mobile, $app-sidebar-panel-minimize-bg-color-mobile); + @include property(--kt-app-sidebar-panel-minimize-box-shadow, $app-sidebar-panel-minimize-box-shadow); + @include property(--kt-app-sidebar-panel-minimize-box-shadow-mobile, $app-sidebar-panel-minimize-box-shadow-mobile); + @include property(--kt-app-sidebar-panel-minimize-hover-box-shadow, $app-sidebar-panel-minimize-hover-box-shadow); + @include property(--kt-app-sidebar-panel-minimize-hover-box-shadow-mobile, $app-sidebar-panel-minimize-hover-box-shadow-mobile); + @include property(--kt-app-sidebar-panel-minimize-border-start, $app-sidebar-panel-minimize-border-start); + @include property(--kt-app-sidebar-panel-minimize-border-start-mobile, $app-sidebar-panel-minimize-border-start-mobile); + @include property(--kt-app-sidebar-panel-minimize-border-end, $app-sidebar-panel-minimize-border-end); + @include property(--kt-app-sidebar-panel-minimize-border-end-mobile, $app-sidebar-panel-minimize-border-end-mobile); + + // Aside base + @include property(--kt-app-aside-base-bg-color, $app-aside-base-bg-color); + @include property(--kt-app-aside-base-bg-color-mobile, $app-aside-base-bg-color-mobile); + @include property(--kt-app-aside-base-box-shadow, $app-aside-base-box-shadow); + @include property(--kt-app-aside-base-box-shadow-mobile, $app-aside-base-box-shadow-mobile); + @include property(--kt-app-aside-base-border-start, $app-aside-base-border-start); + @include property(--kt-app-aside-base-border-start-mobile, $app-aside-base-border-start-mobile); + @include property(--kt-app-aside-base-border-end, $app-aside-base-border-end); + @include property(--kt-app-aside-base-border-end-mobile, $app-aside-base-border-end-mobile); + + // Aside sticky + @include property(--kt-app-aside-sticky-bg-color, $app-aside-sticky-bg-color); + @include property(--kt-app-aside-sticky-box-shadow, $app-aside-sticky-box-shadow); + @include property(--kt-app-aside-sticky-border-start, $app-aside-sticky-border-start); + @include property(--kt-app-aside-sticky-border-end, $app-aside-sticky-border-end); + + // Aside minimize + @include property(--kt-app-aside-minimize-bg-color, $app-aside-minimize-bg-color); + @include property(--kt-app-aside-minimize-bg-color-mobile, $app-aside-minimize-bg-color-mobile); + @include property(--kt-app-aside-minimize-box-shadow, $app-aside-minimize-box-shadow); + @include property(--kt-app-aside-minimize-box-shadow-mobile, $app-aside-minimize-box-shadow-mobile); + @include property(--kt-app-aside-minimize-hover-box-shadow, $app-aside-minimize-hover-box-shadow); + @include property(--kt-app-aside-minimize-hover-box-shadow-mobile, $app-aside-minimize-hover-box-shadow-mobile); + @include property(--kt-app-aside-minimize-border-start, $app-aside-minimize-border-start); + @include property(--kt-app-aside-minimize-border-start-mobile, $app-aside-minimize-border-start-mobile); + @include property(--kt-app-aside-minimize-border-end, $app-aside-minimize-border-end); + @include property(--kt-app-aside-minimize-border-end-mobile, $app-aside-minimize-border-end-mobile); + + // Page + @include property(--kt-app-page-bg-color, $app-page-bg-color); + + // Wrapper + @include property(--kt-app-wrapper-bg-color, $app-wrapper-bg-color); + + // Footer + @include property(--kt-app-footer-bg-color, $app-footer-bg-color); + @include property(--kt-app-footer-bg-color-mobile, $app-footer-bg-color-mobile); + @include property(--kt-app-footer-box-shadow, $app-footer-box-shadow); + @include property(--kt-app-footer-box-shadow-mobile, $app-footer-box-shadow-mobile); + @include property(--kt-app-footer-border-top, $app-footer-border-top); + @include property(--kt-app-footer-border-top-mobile, $app-footer-border-top-mobile); +} + +[data-theme="dark"] { + // Layouts + @include property(--kt-app-bg-color, $app-bg-color-dark); + @include property(--kt-app-blank-bg-color, $app-blank-bg-color-dark); + + // Header base + @include property(--kt-app-header-base-bg-color, $app-header-base-bg-color-dark); + @include property(--kt-app-header-base-bg-color-mobile, $app-header-base-bg-color-mobile-dark); + @include property(--kt-app-header-base-box-shadow, $app-header-base-box-shadow-dark); + @include property(--kt-app-header-base-box-shadow-mobile, $app-header-base-box-shadow-mobile-dark); + @include property(--kt-app-header-base-border-bottom, $app-header-base-border-bottom-dark); + @include property(--kt-app-header-base-border-bottom-mobile, $app-header-base-border-bottom-mobile-dark); + + // Header minimize + @include property(--kt-app-header-minimize-bg-color, $app-header-minimize-bg-color-dark); + @include property(--kt-app-header-minimize-bg-color-mobile, $app-header-minimize-bg-color-mobile-dark); + @include property(--kt-app-header-minimize-box-shadow, $app-header-minimize-box-shadow-dark); + @include property(--kt-app-header-minimize-box-shadow-mobile, $app-header-minimize-box-shadow-mobile-dark); + @include property(--kt-app-header-minimize-border-bottom, $app-header-minimize-border-bottom-dark); + @include property(--kt-app-header-minimize-border-bottom-mobile, $app-header-minimize-border-bottom-mobile-dark); + + // Header sticky + @include property(--kt-app-header-sticky-bg-color, $app-header-sticky-bg-color-dark); + @include property(--kt-app-header-sticky-bg-color-mobile, $app-header-sticky-bg-color-mobile-dark); + @include property(--kt-app-header-sticky-box-shadow, $app-header-sticky-box-shadow-dark); + @include property(--kt-app-header-sticky-box-shadow-mobile, $app-header-sticky-box-shadow-mobile-dark); + @include property(--kt-app-header-sticky-border-bottom, $app-header-sticky-border-bottom-dark); + @include property(--kt-app-header-sticky-border-bottom-mobile, $app-header-sticky-border-bottom-mobile-dark); + + // Header primary + @include property(--kt-app-header-primary-base-bg-color, $app-header-primary-base-bg-color-dark); + @include property(--kt-app-header-primary-base-bg-color-mobile, $app-header-primary-base-bg-color-mobile-dark); + @include property(--kt-app-header-primary-base-box-shadow, $app-header-primary-base-box-shadow-dark); + @include property(--kt-app-header-primary-base-box-shadow-mobile, $app-header-primary-base-box-shadow-mobile-dark); + @include property(--kt-app-header-primary-base-border-bottom, $app-header-primary-base-border-bottom-dark); + @include property(--kt-app-header-primary-base-border-bottom-mobile, $app-header-primary-base-border-bottom-mobile-dark); + + @include property(--kt-app-header-primary-minimize-bg-color, $app-header-primary-minimize-bg-color-dark); + @include property(--kt-app-header-primary-minimize-box-shadow, $app-header-primary-minimize-box-shadow-dark); + @include property(--kt-app-header-primary-minimize-border-top, $app-header-primary-minimize-border-top-dark); + @include property(--kt-app-header-primary-minimize-border-bottom, $app-header-primary-minimize-border-bottom-dark); + + @include property(--kt-app-header-primary-sticky-bg-color, $app-header-primary-sticky-bg-color-dark); + @include property(--kt-app-header-primary-sticky-box-shadow, $app-header-primary-sticky-box-shadow-dark); + @include property(--kt-app-header-primary-sticky-border-top, $app-header-primary-sticky-border-top-dark); + @include property(--kt-app-header-primary-sticky-border-bottom, $app-header-primary-sticky-border-bottom-dark); + + // Header secondary + @include property(--kt-app-header-secondary-base-bg-color, $app-header-secondary-base-bg-color-dark); + @include property(--kt-app-header-secondary-base-bg-color-mobile, $app-header-secondary-base-bg-color-mobile-dark); + @include property(--kt-app-header-secondary-base-box-shadow, $app-header-secondary-base-box-shadow-dark); + @include property(--kt-app-header-secondary-base-box-shadow-mobile, $app-header-secondary-base-box-shadow-mobile-dark); + @include property(--kt-app-header-secondary-base-border-top, $app-header-secondary-base-border-top-dark); + @include property(--kt-app-header-secondary-base-border-bottom, $app-header-secondary-base-border-bottom-dark); + @include property(--kt-app-header-secondary-base-border-start-mobile, $app-header-secondary-base-border-bottom-dark); + @include property(--kt-app-header-secondary-base-border-end-mobile, $app-header-secondary-base-border-end-mobile-dark); + + @include property(--kt-app-header-secondary-minimize-bg-color, $app-header-secondary-minimize-bg-color-dark); + @include property(--kt-app-header-secondary-minimize-box-shadow, $app-header-secondary-minimize-box-shadow-dark); + @include property(--kt-app-header-secondary-minimize-border-top, $app-header-secondary-minimize-border-top-dark); + @include property(--kt-app-header-secondary-minimize-border-bottom, $app-header-secondary-minimize-border-bottom-dark); + + @include property(--kt-app-header-secondary-sticky-bg-color, $app-header-secondary-sticky-bg-color-dark); + @include property(--kt-app-header-secondary-sticky-box-shadow, $app-header-secondary-sticky-box-shadow-dark); + @include property(--kt-app-header-secondary-sticky-border-top, $app-header-secondary-sticky-border-top-dark); + @include property(--kt-app-header-secondary-sticky-border-bottom, $app-header-secondary-sticky-border-bottom-dark); + + // Toolbar base + @include property(--kt-app-toolbar-base-bg-color, $app-toolbar-base-bg-color-dark); + @include property(--kt-app-toolbar-base-bg-color-mobile, $app-toolbar-base-bg-color-mobile-dark); + @include property(--kt-app-toolbar-base-box-shadow, $app-toolbar-base-box-shadow-dark); + @include property(--kt-app-toolbar-base-box-shadow-mobile, $app-toolbar-base-box-shadow-mobile-dark); + @include property(--kt-app-toolbar-base-border-top, $app-toolbar-base-border-top-dark); + @include property(--kt-app-toolbar-base-border-top-mobile, $app-toolbar-base-border-top-mobile-dark); + @include property(--kt-app-toolbar-base-border-bottom, $app-toolbar-base-border-bottom-dark); + @include property(--kt-app-toolbar-base-border-bottom-mobile, $app-toolbar-base-border-bottom-dark); + + // Toolbar minimize + @include property(--kt-app-toolbar-minimize-bg-color, $app-toolbar-minimize-bg-color-dark); + @include property(--kt-app-toolbar-minimize-bg-color-mobile, $app-toolbar-minimize-bg-color-mobile-dark); + @include property(--kt-app-toolbar-minimize-box-shadow, $app-toolbar-minimize-box-shadow-dark); + @include property(--kt-app-toolbar-minimize-box-shadow-mobile, $app-toolbar-minimize-box-shadow-mobile-dark); + @include property(--kt-app-toolbar-minimize-border-top, $app-toolbar-minimize-border-top-dark); + @include property(--kt-app-toolbar-minimize-border-top-mobile, $app-toolbar-minimize-border-top-mobile-dark); + @include property(--kt-app-toolbar-minimize-border-bottom, $app-toolbar-minimize-border-bottom-dark); + @include property(--kt-app-toolbar-minimize-border-bottom-mobile, $app-toolbar-minimize-border-bottom-mobile-dark); + + // Toolbar sticky + @include property(--kt-app-toolbar-sticky-bg-color, $app-toolbar-sticky-bg-color-dark); + @include property(--kt-app-toolbar-sticky-bg-color-mobile, $app-toolbar-sticky-bg-color-mobile-dark); + @include property(--kt-app-toolbar-sticky-box-shadow, $app-toolbar-sticky-box-shadow-dark); + @include property(--kt-app-toolbar-sticky-box-shadow-mobile, $app-toolbar-sticky-box-shadow-mobile-dark); + @include property(--kt-app-toolbar-sticky-border-top, $app-toolbar-sticky-border-top-dark); + @include property(--kt-app-toolbar-sticky-border-top-mobile, $app-toolbar-sticky-border-top-mobile-dark); + @include property(--kt-app-toolbar-sticky-border-bottom, $app-toolbar-sticky-border-bottom-dark); + @include property(--kt-app-toolbar-sticky-border-bottom-mobile, $app-toolbar-sticky-border-bottom-mobile-dark); + + // Hero + @include property(--kt-app-hero-bg-color, $app-hero-bg-color-dark); + @include property(--kt-app-hero-box-shadow, $app-hero-box-shadow-dark); + @include property(--kt-app-hero-border-top, $app-hero-border-top-dark); + @include property(--kt-app-hero-border-bottom, $app-hero-border-bottom-dark); + + // Sidebar base + @include property(--kt-app-sidebar-base-bg-color, $app-sidebar-base-bg-color-dark); + @include property(--kt-app-sidebar-base-bg-color-mobile, $app-sidebar-base-bg-color-mobile-dark); + @include property(--kt-app-sidebar-base-box-shadow, $app-sidebar-base-box-shadow-dark); + @include property(--kt-app-sidebar-base-box-shadow-mobile, $app-sidebar-base-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-base-border-start, $app-sidebar-base-border-start-dark); + @include property(--kt-app-sidebar-base-border-start-mobile, $app-sidebar-base-border-start-mobile-dark); + @include property(--kt-app-sidebar-base-border-end, $app-sidebar-base-border-end-dark); + @include property(--kt-app-sidebar-base-border-end-mobile, $app-sidebar-base-border-end-mobile-dark); + + // Sidebar sticky + @include property(--kt-app-sidebar-sticky-bg-color, $app-sidebar-sticky-bg-color-dark); + @include property(--kt-app-sidebar-sticky-box-shadow, $app-sidebar-sticky-box-shadow-dark); + @include property(--kt-app-sidebar-sticky-border-start, $app-sidebar-sticky-border-start-dark); + @include property(--kt-app-sidebar-sticky-border-end, $app-sidebar-sticky-border-end-dark); + + // Sidebar minimize + @include property(--kt-app-sidebar-minimize-bg-color, $app-sidebar-minimize-bg-color-dark); + @include property(--kt-app-sidebar-minimize-bg-color-mobile, $app-sidebar-minimize-bg-color-mobile-dark); + @include property(--kt-app-sidebar-minimize-box-shadow, $app-sidebar-minimize-box-shadow-dark); + @include property(--kt-app-sidebar-minimize-box-shadow-mobile, $app-sidebar-minimize-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-minimize-hover-box-shadow, $app-sidebar-minimize-hover-box-shadow-dark); + @include property(--kt-app-sidebar-minimize-hover-box-shadow-mobile, $app-sidebar-minimize-hover-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-minimize-border-start, $app-sidebar-minimize-border-start-dark); + @include property(--kt-app-sidebar-minimize-border-start-mobile, $app-sidebar-minimize-border-start-mobile-dark); + @include property(--kt-app-sidebar-minimize-border-end, $app-sidebar-minimize-border-end-dark); + @include property(--kt-app-sidebar-minimize-border-end-mobile, $app-sidebar-minimize-border-end-mobile-dark); + + // Sidebar primary + @include property(--kt-app-sidebar-primary-base-bg-color, $app-sidebar-primary-base-bg-color-dark); + @include property(--kt-app-sidebar-primary-base-bg-color-mobile, $app-sidebar-primary-base-bg-color-mobile-dark); + @include property(--kt-app-sidebar-primary-base-box-shadow, $app-sidebar-primary-base-box-shadow-dark); + @include property(--kt-app-sidebar-primary-base-box-shadow-mobile, $app-sidebar-primary-base-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-primary-base-border-start, $app-sidebar-primary-base-border-start-dark); + @include property(--kt-app-sidebar-primary-base-border-start-mobile, $app-sidebar-primary-base-border-start-mobile-dark); + @include property(--kt-app-sidebar-primary-base-border-end, $app-sidebar-primary-base-border-end-dark); + @include property(--kt-app-sidebar-primary-base-border-end-mobile, $app-sidebar-primary-base-border-end-mobile-dark); + + @include property(--kt-app-sidebar-primary-minimize-bg-color, $app-sidebar-primary-base-border-end-mobile-dark); + @include property(--kt-app-sidebar-primary-minimize-bg-color-mobile, $app-sidebar-primary-minimize-bg-color-mobile-dark); + @include property(--kt-app-sidebar-primary-minimize-box-shadow, $app-sidebar-primary-minimize-box-shadow-dark); + @include property(--kt-app-sidebar-primary-minimize-box-shadow-mobile, $app-sidebar-primary-minimize-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-primary-minimize-hover-box-shadow, $app-sidebar-primary-minimize-hover-box-shadow-dark); + @include property(--kt-app-sidebar-primary-minimize-hover-box-shadow-mobile, $app-sidebar-primary-minimize-hover-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-primary-minimize-border-start, $app-sidebar-primary-minimize-border-start-dark); + @include property(--kt-app-sidebar-primary-minimize-border-start-mobile, $app-sidebar-primary-minimize-border-start-mobile-dark); + @include property(--kt-app-sidebar-primary-minimize-border-end, $app-sidebar-primary-minimize-border-end-dark); + @include property(--kt-app-sidebar-primary-minimize-border-end-mobile, $app-sidebar-primary-minimize-border-end-mobile-dark); + + // Sidebar secondary + @include property(--kt-app-sidebar-secondary-base-bg-color, $app-sidebar-secondary-base-bg-color-dark); + @include property(--kt-app-sidebar-secondary-base-bg-color-mobile, $app-sidebar-secondary-base-bg-color-mobile-dark); + @include property(--kt-app-sidebar-secondary-base-box-shadow, $app-sidebar-secondary-base-box-shadow-dark); + @include property(--kt-app-sidebar-secondary-base-box-shadow-mobile, $app-sidebar-secondary-base-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-secondary-base-border-start, $app-sidebar-secondary-base-border-start-dark); + @include property(--kt-app-sidebar-secondary-base-border-start-mobile, $app-sidebar-secondary-base-border-start-mobile-dark); + @include property(--kt-app-sidebar-secondary-base-border-end, $app-sidebar-secondary-base-border-end-dark); + @include property(--kt-app-sidebar-secondary-base-border-end-mobile, $app-sidebar-secondary-base-border-end-mobile-dark); + + @include property(--kt-app-sidebar-secondary-minimize-bg-color, $app-sidebar-secondary-minimize-bg-color-dark); + @include property(--kt-app-sidebar-secondary-minimize-bg-color-mobile, $app-sidebar-secondary-minimize-bg-color-mobile-dark); + @include property(--kt-app-sidebar-secondary-minimize-box-shadow, $app-sidebar-secondary-minimize-box-shadow-dark); + @include property(--kt-app-sidebar-secondary-minimize-box-shadow-mobile, $app-sidebar-secondary-minimize-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-secondary-minimize-hover-box-shadow, $app-sidebar-secondary-minimize-hover-box-shadow-dark); + @include property(--kt-app-sidebar-secondary-minimize-hover-box-shadow-mobile, $app-sidebar-secondary-minimize-hover-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-secondary-minimize-border-start, $app-sidebar-secondary-minimize-border-start-dark); + @include property(--kt-app-sidebar-secondary-minimize-border-start-mobile, $app-sidebar-secondary-minimize-border-start-mobile-dark); + @include property(--kt-app-sidebar-secondary-minimize-border-end, $app-sidebar-secondary-minimize-border-end-dark); + @include property(--kt-app-sidebar-secondary-minimize-border-end-mobile, $app-sidebar-secondary-minimize-border-end-mobile-dark); + + // Sidebar panel base + @include property(--kt-app-sidebar-panel-base-bg-color, $app-sidebar-panel-base-bg-color-dark); + @include property(--kt-app-sidebar-panel-base-bg-color-mobile, $app-sidebar-panel-base-bg-color-mobile-dark); + @include property(--kt-app-sidebar-panel-base-box-shadow, $app-sidebar-panel-base-box-shadow-dark); + @include property(--kt-app-sidebar-panel-base-box-shadow-mobile, $app-sidebar-panel-base-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-panel-base-border-start, $app-sidebar-panel-base-border-start-dark); + @include property(--kt-app-sidebar-panel-base-border-start-mobile, $app-sidebar-panel-base-border-start-mobile-dark); + @include property(--kt-app-sidebar-panel-base-border-end, $app-sidebar-panel-base-border-end-dark); + @include property(--kt-app-sidebar-panel-base-border-end-mobile, $app-sidebar-panel-base-border-end-mobile-dark); + + // Sidebar panel sticky + @include property(--kt-app-sidebar-panel-sticky-bg-color, $app-sidebar-panel-sticky-bg-color-dark); + @include property(--kt-app-sidebar-panel-sticky-box-shadow, $app-sidebar-panel-sticky-box-shadow-dark); + @include property(--kt-app-sidebar-panel-sticky-border-start, $app-sidebar-panel-sticky-border-start-dark); + @include property(--kt-app-sidebar-panel-sticky-border-end, $app-sidebar-panel-sticky-border-end-dark); + + // Sidebar panel minimize + @include property(--kt-app-sidebar-panel-minimize-bg-color, $app-sidebar-panel-minimize-bg-color-dark); + @include property(--kt-app-sidebar-panel-minimize-bg-color-mobile, $app-sidebar-panel-minimize-bg-color-mobile-dark); + @include property(--kt-app-sidebar-panel-minimize-box-shadow, $app-sidebar-panel-minimize-box-shadow-dark); + @include property(--kt-app-sidebar-panel-minimize-box-shadow-mobile, $app-sidebar-panel-minimize-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-panel-minimize-hover-box-shadow, $app-sidebar-panel-minimize-hover-box-shadow-dark); + @include property(--kt-app-sidebar-panel-minimize-hover-box-shadow-mobile, $app-sidebar-panel-minimize-hover-box-shadow-mobile-dark); + @include property(--kt-app-sidebar-panel-minimize-border-start, $app-sidebar-panel-minimize-border-start-dark); + @include property(--kt-app-sidebar-panel-minimize-border-start-mobile, $app-sidebar-panel-minimize-border-start-mobile-dark); + @include property(--kt-app-sidebar-panel-minimize-border-end, $app-sidebar-panel-minimize-border-end-dark); + @include property(--kt-app-sidebar-panel-minimize-border-end-mobile, $app-sidebar-panel-minimize-border-end-mobile-dark); + + // Aside base + @include property(--kt-app-aside-base-bg-color, $app-aside-base-bg-color-dark); + @include property(--kt-app-aside-base-bg-color-mobile, $app-aside-base-bg-color-mobile-dark); + @include property(--kt-app-aside-base-box-shadow, $app-aside-base-box-shadow-dark); + @include property(--kt-app-aside-base-box-shadow-mobile, $app-aside-base-box-shadow-mobile-dark); + @include property(--kt-app-aside-base-border-start, $app-aside-base-border-start-dark); + @include property(--kt-app-aside-base-border-start-mobile, $app-aside-base-border-start-mobile-dark); + @include property(--kt-app-aside-base-border-end, $app-aside-base-border-end-dark); + @include property(--kt-app-aside-base-border-end-mobile, $app-aside-base-border-end-mobile-dark); + + // Aside sticky + @include property(--kt-app-aside-sticky-bg-color, $app-aside-sticky-bg-color-dark); + @include property(--kt-app-aside-sticky-box-shadow, $app-aside-sticky-box-shadow-dark); + @include property(--kt-app-aside-sticky-border-start, $app-aside-sticky-border-start-dark); + @include property(--kt-app-aside-sticky-border-end, $app-aside-sticky-border-end-dark); + + // Aside minimize + @include property(--kt-app-aside-minimize-bg-color, $app-aside-minimize-bg-color-dark); + @include property(--kt-app-aside-minimize-bg-color-mobile, $app-aside-minimize-bg-color-mobile-dark); + @include property(--kt-app-aside-minimize-box-shadow, $app-aside-minimize-box-shadow-dark); + @include property(--kt-app-aside-minimize-box-shadow-mobile, $app-aside-minimize-box-shadow-mobile-dark); + @include property(--kt-app-aside-minimize-hover-box-shadow, $app-aside-minimize-hover-box-shadow-dark); + @include property(--kt-app-aside-minimize-hover-box-shadow-mobile, $app-aside-minimize-hover-box-shadow-mobile-dark); + @include property(--kt-app-aside-minimize-border-start, $app-aside-minimize-border-start-dark); + @include property(--kt-app-aside-minimize-border-start-mobile, $app-aside-minimize-border-start-mobile-dark); + @include property(--kt-app-aside-minimize-border-end, $app-aside-minimize-border-end-dark); + @include property(--kt-app-aside-minimize-border-end-mobile, $app-aside-minimize-border-end-mobile-dark); + + // Page + @include property(--kt-app-page-bg-color, $app-page-bg-color-dark); + + // Wrapper + @include property(--kt-app-wrapper-bg-color, $app-wrapper-bg-color-dark); + + // Footer + @include property(--kt-app-footer-bg-color, $app-footer-bg-color-dark); + @include property(--kt-app-footer-bg-color-mobile, $app-footer-bg-color-mobile-dark); + @include property(--kt-app-footer-box-shadow, $app-footer-box-shadow-dark); + @include property(--kt-app-footer-box-shadow-mobile, $app-footer-box-shadow-mobile-dark); + @include property(--kt-app-footer-border-top, $app-footer-border-top-dark); + @include property(--kt-app-footer-border-top-mobile, $app-footer-border-top-mobile-dark); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_toolbar.scss b/src/_res/assets/sass/core/layout/base/_toolbar.scss new file mode 100644 index 0000000..e80f74c --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_toolbar.scss @@ -0,0 +1,183 @@ +// +// Toolbar +// + +// General mode +.app-toolbar { + display: flex; + align-items: stretch; + + &.app-toolbar-minimize { + transition: $app-toolbar-base-transition; + } +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-toolbar { + background-color: var(--kt-app-toolbar-base-bg-color); + box-shadow: var(--kt-app-toolbar-base-box-shadow); + border-top: var(--kt-app-toolbar-base-border-top); + border-bottom: var(--kt-app-toolbar-base-border-bottom); + } + + // Vars + :root { + --kt-app-toolbar-height: #{$app-toolbar-base-height}; + --kt-app-toolbar-height-actual: #{$app-toolbar-base-height}; + } + + [data-kt-app-toolbar-sticky="on"] { + --kt-app-toolbar-height: #{$app-toolbar-sticky-height}; + } + + [data-kt-app-toolbar-minimize="on"] { + --kt-app-toolbar-height: #{$app-toolbar-minimize-height}; + } + + // States + .app-toolbar { + height: var(--kt-app-toolbar-height); + + [data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"] & { + @include property( z-index, $app-toolbar-base-z-index); + position: fixed; + left: 0; + right: 0; + top: 0; + } + + [data-kt-app-toolbar-sticky="on"] & { + position: fixed; + left: 0; + right: 0; + top: 0; + @include property( z-index, $app-toolbar-sticky-z-index); + @include property( backdrop-filter, $app-toolbar-sticky-backdrop-filter); + + box-shadow: var(--kt-app-toolbar-sticky-box-shadow); + background-color: var(--kt-app-toolbar-sticky-bg-color); + border-top: var(--kt-app-toolbar-sticky-border-top); + border-bottom: var(--kt-app-toolbar-sticky-border-bottom); + } + + [data-kt-app-toolbar-minimize="on"] & { + transition: $app-toolbar-base-transition; + @include property( z-index, $app-toolbar-minimize-z-index); + @include property( backdrop-filter, $app-toolbar-minimize-backdrop-filter); + + box-shadow: var(--kt-app-toolbar-minimize-box-shadow); + background-color: var(--kt-app-toolbar-minimize-bg-color); + border-top: var(--kt-app-toolbar-minimize-border-top); + border-bottom: var(--kt-app-toolbar-minimize-border-bottom); + } + } + + // Integration + .app-toolbar { + // Header + [data-kt-app-toolbar-fixed="true"][data-kt-app-header-fixed="true"] & { + top: var(--kt-app-header-height); + } + + // Sidebar + [data-kt-app-toolbar-sticky="on"][data-kt-app-sidebar-fixed="true"][data-kt-app-sidebar-push-toolbar="true"] &, + [data-kt-app-toolbar-fixed="true"][data-kt-app-sidebar-fixed="true"][data-kt-app-sidebar-push-toolbar="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + // Sidebar panel + [data-kt-app-toolbar-sticky="on"][data-kt-app-sidebar-panel-fixed="true"][data-kt-app-sidebar-panel-push-toolbar="true"] &, + [data-kt-app-toolbar-fixed="true"][data-kt-app-sidebar-panel-fixed="true"][data-kt-app-sidebar-panel-push-toolbar="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + + // Aside + [data-kt-app-toolbar-sticky="on"][data-kt-app-aside-fixed="true"][data-kt-app-aside-push-toolbar="true"] &, + [data-kt-app-toolbar-fixed="true"][data-kt-app-aside-fixed="true"][data-kt-app-aside-push-toolbar="true"] & { + right: calc( + var(--kt-app-aside-width) + + var(--kt-app-aside-gap-start, 0px) + + var(--kt-app-aside-gap-end, 0px) + ); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-toolbar { + @include property( z-index, $app-toolbar-base-z-index-mobile); + + box-shadow: var(--kt-app-toolbar-base-box-shadow-mobile); + background-color: var(--kt-app-toolbar-base-bg-color-mobile); + border-top: var(--kt-app-toolbar-base-border-top-mobile); + border-bottom: var(--kt-app-toolbar-base-border-bottom-mobile); + } + + // Vars + :root { + --kt-app-toolbar-height: #{$app-toolbar-base-height-mobile}; + } + + [data-kt-app-toolbar-sticky="on"] { + --kt-app-toolbar-height: #{$app-toolbar-sticky-height-mobile}; + } + + [data-kt-app-toolbar-minimize="on"] { + --kt-app-toolbar-height: #{$app-toolbar-minimize-height-mobile}; + } + + // States + .app-toolbar { + height: var(--kt-app-toolbar-height); + + [data-kt-app-header-fixed-mobile="true"][data-kt-app-toolbar-fixed-mobile="true"] & { + @include property( z-index, $app-toolbar-base-z-index-mobile); + position: fixed; + top: calc(var(--kt-app-header-height, 0px) + var(--kt-app-header-mobile-height, 0px)); + left: 0; + right: 0; + } + + [data-kt-app-toolbar-sticky="on"] & { + position: fixed; + left: 0; + right: 0; + top: var(--kt-app-header-height, 0px); + + box-shadow: var(--kt-app-toolbar-sticky-box-shadow-mobile); + background-color: var(--kt-app-toolbar-sticky-bg-color-mobile); + border-top: var(--kt-app-toolbar-sticky-border-top-mobile); + border-bottom: var(--kt-app-toolbar-sticky-border-bottom-mobile); + + @include property( z-index, $app-toolbar-sticky-z-index-mobile); + @include property( backdrop-filter, $app-toolbar-sticky-backdrop-filter-mobile); + } + + [data-kt-app-toolbar-minimize="on"] & { + transition: $app-toolbar-base-transition; + + box-shadow: var(--kt-app-toolbar-minimize-box-shadow-mobile); + background-color: var(--kt-app-toolbar-minimize-bg-color-mobile); + border-top: var(--kt-app-toolbar-minimize-border-top-mobile); + border-bottom: var(--kt-app-toolbar-minimize-border-bottom-mobile); + + @include property( z-index, $app-toolbar-minimize-z-index-mobile); + @include property( backdrop-filter, $app-toolbar-minimize-backdrop-filter-mobile); + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_variables.scss b/src/_res/assets/sass/core/layout/base/_variables.scss new file mode 100644 index 0000000..2a95a9f --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_variables.scss @@ -0,0 +1,696 @@ +// +// Variables +// + +// Reboot +$app-bg-color: #f5f8fa !default; +$app-bg-color-dark: #151521 !default; +$app-blank-bg-color: $white; +$app-blank-bg-color-dark: $app-bg-color-dark; + +// General +$app-general-transition-duration: .3s !default; +$app-general-transition-timing: ease !default; +$app-general-root-font-size-desktop: 13px !default; +$app-general-root-font-size-tablet: 12px !default; +$app-general-root-font-size-mobile: 12px !default; + +// Container +$app-container-padding-x: 30px !default; +$app-container-padding-x-mobile: 20px !default; + +// Page +$app-page-bg-color: null !default; +$app-page-bg-color-dark: null !default; + +// Main +$app-main-transition: margin $app-general-transition-duration $app-general-transition-timing; +$app-main-padding-y: null !default; +$app-main-padding-y-mobile: null !default; +$app-main-padding-x: null !default; +$app-main-padding-x-mobile: 0 !default; +$app-main-margin-y: null !default; +$app-main-margin-y-mobile: null !default; +$app-main-margin-x: null !default; +$app-main-margin-x-mobile: null !default; + +// Wrapper +$app-wrapper-transition: margin-left $app-general-transition-duration $app-general-transition-timing, margin-right $app-general-transition-duration $app-general-transition-timing; +$app-wrapper-bg-color: null !default; +$app-wrapper-bg-color-dark: null !default; + +// Content +$app-content-padding-y: 30px !default; +$app-content-padding-y-mobile: 20px !default; +$app-content-padding-x: 0 !default; +$app-content-padding-x-mobile: 0 !default; + +// Header base +$app-header-base-transition: none !default; +$app-header-base-height: 70px !default; +$app-header-base-height-mobile: 70px !default; +$app-header-base-z-index: null !default; +$app-header-base-z-index-mobile: null !default; +$app-header-base-bg-color: null !default; +$app-header-base-bg-color-dark: null !default; +$app-header-base-bg-color-mobile: null !default; +$app-header-base-bg-color-mobile-dark: null !default; +$app-header-base-box-shadow: null !default; +$app-header-base-box-shadow-dark: null !default; +$app-header-base-box-shadow-mobile: null !default; +$app-header-base-box-shadow-mobile-dark: null !default; +$app-header-base-border-bottom: null !default; +$app-header-base-border-bottom-dark: null !default; +$app-header-base-border-bottom-mobile: null !default; +$app-header-base-border-bottom-mobile-dark: null !default; + +// Header fixed +$app-header-fixed-z-index: 100 !default; +$app-header-fixed-z-index-mobile: 100 !default; + +// Header minimize +$app-header-minimize-height: 70px !default; +$app-header-minimize-height-mobile: 70px !default; +$app-header-minimize-z-index: 100 !default; +$app-header-minimize-z-index-mobile: 100 !default; +$app-header-minimize-backdrop-filter: null !default; +$app-header-minimize-backdrop-filter-mobile: null !default; +$app-header-minimize-bg-color: null !default; +$app-header-minimize-bg-color-dark: null !default; +$app-header-minimize-bg-color-mobile: null !default; +$app-header-minimize-bg-color-mobile-dark: null !default; +$app-header-minimize-box-shadow: null !default; +$app-header-minimize-box-shadow-dark: null !default; +$app-header-minimize-box-shadow-mobile: null !default; +$app-header-minimize-box-shadow-mobile-dark: null !default; +$app-header-minimize-border-bottom: null !default; +$app-header-minimize-border-bottom-dark: null !default; +$app-header-minimize-border-bottom-mobile: null !default; +$app-header-minimize-border-bottom-mobile-dark: null !default; + +// Header sticky +$app-header-sticky-height: 70px !default; +$app-header-sticky-height-mobile: 70px !default; +$app-header-sticky-z-index: 100 !default; +$app-header-sticky-z-index-mobile: 100 !default; +$app-header-sticky-backdrop-filter: null !default; +$app-header-sticky-backdrop-filter-mobile: null !default; +$app-header-sticky-bg-color: null !default; +$app-header-sticky-bg-color-dark: null !default; +$app-header-sticky-bg-color-mobile: null !default; +$app-header-sticky-bg-color-mobile-dark: null !default; +$app-header-sticky-box-shadow: null !default; +$app-header-sticky-box-shadow-dark: null !default; +$app-header-sticky-box-shadow-mobile: null !default; +$app-header-sticky-box-shadow-mobile-dark: null !default; +$app-header-sticky-border-bottom: null !default; +$app-header-sticky-border-bottom-dark: null !default; +$app-header-sticky-border-bottom-mobile: null !default; +$app-header-sticky-border-bottom-mobile-dark: null !default; + +// Header primary +$app-header-primary-base-transition: none !default; +$app-header-primary-base-height: 70px !default; +$app-header-primary-base-z-index: null !default; +$app-header-primary-base-z-index-mobile: null !default; +$app-header-primary-base-bg-color: null !default; +$app-header-primary-base-bg-color-dark: null !default; +$app-header-primary-base-bg-color-mobile: null !default; +$app-header-primary-base-bg-color-mobile-dark: null !default; +$app-header-primary-base-box-shadow: null !default; +$app-header-primary-base-box-shadow-dark: null !default; +$app-header-primary-base-box-shadow-mobile: null !default; +$app-header-primary-base-box-shadow-mobile-dark: null !default; +$app-header-primary-base-border-bottom: null !default; +$app-header-primary-base-border-bottom-dark: null !default; +$app-header-primary-base-border-bottom-mobile: null !default; +$app-header-primary-base-border-bottom-mobile-dark: null !default; + +$app-header-primary-fixed-z-index: 100 !default; + +$app-header-primary-minimize-height: 70px !default; +$app-header-primary-minimize-z-index: 100 !default; +$app-header-primary-minimize-bg-color: null !default; +$app-header-primary-minimize-bg-color-dark: null !default; +$app-header-primary-minimize-box-shadow: null !default; +$app-header-primary-minimize-box-shadow-dark: null !default; +$app-header-primary-minimize-border-top: null !default; +$app-header-primary-minimize-border-top-dark: null !default; +$app-header-primary-minimize-border-bottom: null !default; +$app-header-primary-minimize-border-bottom-dark: null !default; + +$app-header-primary-sticky-height: 70px !default; +$app-header-primary-sticky-z-index: 100 !default; +$app-header-primary-sticky-bg-color: null !default; +$app-header-primary-sticky-bg-color-dark: null !default; +$app-header-primary-sticky-box-shadow: null !default; +$app-header-primary-sticky-box-shadow-dark: null !default; +$app-header-primary-sticky-border-top: null !default; +$app-header-primary-sticky-border-top-dark: null !default; +$app-header-primary-sticky-border-bottom: null !default; +$app-header-primary-sticky-border-bottom-dark: null !default; + +// Header secondary +$app-header-secondary-base-transition: none !default; +$app-header-secondary-base-height: 70px !default; +$app-header-secondary-base-z-index: null !default; +$app-header-secondary-base-bg-color: null !default; +$app-header-secondary-base-bg-color-dark: null !default; +$app-header-secondary-base-bg-color-mobile: null !default; +$app-header-secondary-base-bg-color-mobile-dark: null !default; +$app-header-secondary-base-box-shadow: null !default; +$app-header-secondary-base-box-shadow-dark: null !default; +$app-header-secondary-base-box-shadow-mobile: null !default; +$app-header-secondary-base-box-shadow-mobile-dark: null !default; +$app-header-secondary-base-border-top: null !default; +$app-header-secondary-base-border-top-dark: null !default; +$app-header-secondary-base-border-bottom: null !default; +$app-header-secondary-base-border-bottom-dark: null !default; +$app-header-secondary-base-border-start-mobile: null !default; +$app-header-secondary-base-border-start-mobile-dark: null !default; +$app-header-secondary-base-border-end-mobile: null !default; +$app-header-secondary-base-border-end-mobile-dark: null !default; + +$app-header-secondary-fixed-z-index: 100 !default; + +$app-header-secondary-minimize-height: 70px !default; +$app-header-secondary-minimize-z-index: 100 !default; +$app-header-secondary-minimize-bg-color: null !default; +$app-header-secondary-minimize-bg-color-dark: null !default; +$app-header-secondary-minimize-box-shadow: null !default; +$app-header-secondary-minimize-box-shadow-dark: null !default; +$app-header-secondary-minimize-border-top: null !default; +$app-header-secondary-minimize-border-top-dark: null !default; +$app-header-secondary-minimize-border-bottom: null !default; +$app-header-secondary-minimize-border-bottom-dark: null !default; + +$app-header-secondary-sticky-height: 70px !default; +$app-header-secondary-sticky-z-index: 100 !default; +$app-header-secondary-sticky-bg-color: null !default; +$app-header-secondary-sticky-bg-color-dark: null !default; +$app-header-secondary-sticky-box-shadow: null !default; +$app-header-secondary-sticky-box-shadow-dark: null !default; +$app-header-secondary-sticky-border-top: null !default; +$app-header-secondary-sticky-border-top-dark: null !default; +$app-header-secondary-sticky-border-bottom: null !default; +$app-header-secondary-sticky-border-bottom-dark: null !default; + +// Toolbar base +$app-toolbar-base-transition: none !default; +$app-toolbar-base-height: null !default; +$app-toolbar-base-height-mobile: null !default; +$app-toolbar-base-z-index: 99 !default; +$app-toolbar-base-z-index-mobile: 99 !default; +$app-toolbar-base-bg-color: null !default; +$app-toolbar-base-bg-color-dark: null !default; +$app-toolbar-base-bg-color-mobile: null !default; +$app-toolbar-base-bg-color-mobile-dark: null !default; +$app-toolbar-base-box-shadow: null !default; +$app-toolbar-base-box-shadow-dark: null !default; +$app-toolbar-base-box-shadow-mobile: null !default; +$app-toolbar-base-box-shadow-mobile-dark: null !default; +$app-toolbar-base-border-top: null !default; +$app-toolbar-base-border-top-dark: null !default; +$app-toolbar-base-border-top-mobile: null !default; +$app-toolbar-base-border-top-mobile-dark: null !default; +$app-toolbar-base-border-bottom: null !default; +$app-toolbar-base-border-bottom-dark: null !default; +$app-toolbar-base-border-bottom-mobile: null !default; +$app-toolbar-base-border-bottom-mobile-dark: null !default; + +// Toolbar minimize +$app-toolbar-minimize-height: 70px !default; +$app-toolbar-minimize-height-mobile: 70px !default; +$app-toolbar-minimize-z-index: 99 !default; +$app-toolbar-minimize-z-index-mobile: 99 !default; +$app-toolbar-minimize-backdrop-filter: null !default; +$app-toolbar-minimize-backdrop-filter-mobile: null !default; +$app-toolbar-minimize-bg-color: null !default; +$app-toolbar-minimize-bg-color-dark: null !default; +$app-toolbar-minimize-bg-color-mobile: null !default; +$app-toolbar-minimize-bg-color-mobile-dark: null !default; +$app-toolbar-minimize-box-shadow: null !default; +$app-toolbar-minimize-box-shadow-dark: null !default; +$app-toolbar-minimize-box-shadow-mobile: null !default; +$app-toolbar-minimize-box-shadow-mobile-dark: null !default; +$app-toolbar-minimize-border-top: null !default; +$app-toolbar-minimize-border-top-dark: null !default; +$app-toolbar-minimize-border-top-mobile: null !default; +$app-toolbar-minimize-border-top-mobile-dark: null !default; +$app-toolbar-minimize-border-bottom: null !default; +$app-toolbar-minimize-border-bottom-dark: null !default; +$app-toolbar-minimize-border-bottom-mobile: null !default; +$app-toolbar-minimize-border-bottom-mobile-dark: null !default; + +// Toolbar sticky +$app-toolbar-sticky-height: 70px !default; +$app-toolbar-sticky-height-mobile: 70px !default; +$app-toolbar-sticky-z-index: 99 !default; +$app-toolbar-sticky-z-index-mobile: 99 !default; +$app-toolbar-sticky-backdrop-filter: null !default; +$app-toolbar-sticky-backdrop-filter-mobile: null !default; +$app-toolbar-sticky-bg-color: null !default; +$app-toolbar-sticky-bg-color-dark: null !default; +$app-toolbar-sticky-bg-color-mobile: null !default; +$app-toolbar-sticky-bg-color-mobile-dark: null !default; +$app-toolbar-sticky-box-shadow: null !default; +$app-toolbar-sticky-box-shadow-dark: null !default; +$app-toolbar-sticky-box-shadow-mobile: null !default; +$app-toolbar-sticky-box-shadow-mobile-dark: null !default; +$app-toolbar-sticky-border-top: null !default; +$app-toolbar-sticky-border-top-dark: null !default; +$app-toolbar-sticky-border-top-mobile: null !default; +$app-toolbar-sticky-border-top-mobile-dark: null !default; +$app-toolbar-sticky-border-bottom: null !default; +$app-toolbar-sticky-border-bottom-dark: null !default; +$app-toolbar-sticky-border-bottom-mobile: null !default; +$app-toolbar-sticky-border-bottom-mobile-dark: null !default; + +// Hero +$app-hero-bg-color: null !default; +$app-hero-bg-color-dark: null !default; +$app-hero-box-shadow: null !default; +$app-hero-box-shadow-dark: null !default; +$app-hero-border-top: null !default; +$app-hero-border-top-dark: null !default; +$app-hero-border-bottom: null !default; +$app-hero-border-bottom-dark: null !default; + +// Sidebar base +$app-sidebar-base-transition: width $app-general-transition-duration $app-general-transition-timing !default; +$app-sidebar-base-width: 300px !default; +$app-sidebar-base-width-mobile: 275px !default; +$app-sidebar-base-z-index: null !default; +$app-sidebar-base-z-index-mobile: 106 !default; +$app-sidebar-base-bg-color: null !default; +$app-sidebar-base-bg-color-dark: null !default; +$app-sidebar-base-bg-color-mobile: null !default; +$app-sidebar-base-bg-color-mobile-dark: null !default; +$app-sidebar-base-box-shadow: null !default; +$app-sidebar-base-box-shadow-dark: null !default; +$app-sidebar-base-box-shadow-mobile: null !default; +$app-sidebar-base-box-shadow-mobile-dark: null !default; +$app-sidebar-base-border-start: null !default; +$app-sidebar-base-border-start-dark: null !default; +$app-sidebar-base-border-start-mobile: null !default; +$app-sidebar-base-border-start-mobile-dark: null !default; +$app-sidebar-base-border-end: null !default; +$app-sidebar-base-border-end-dark: null !default; +$app-sidebar-base-border-end-mobile: null !default; +$app-sidebar-base-border-end-mobile-dark: null !default; +$app-sidebar-base-gap-start: 0px !default; +$app-sidebar-base-gap-start-mobile: 0px !default; +$app-sidebar-base-gap-end: 0px !default; +$app-sidebar-base-gap-end-mobile: 0px !default; +$app-sidebar-base-gap-top: 0px !default; +$app-sidebar-base-gap-top-mobile: 0px !default; +$app-sidebar-base-gap-bottom: 0px !default; +$app-sidebar-base-gap-bottom-mobile: 0px !default; + +// Sidebar fixed +$app-sidebar-fixed-z-index: 105 !default; +$app-sidebar-fixed-left: 0 !default; +$app-sidebar-fixed-top: 0 !default; +$app-sidebar-fixed-bottom: 0 !default; + +// Sidebar sticky +$app-sidebar-sticky-top: auto !default; +$app-sidebar-sticky-bottom: auto !default; +$app-sidebar-sticky-left: auto !default; +$app-sidebar-sticky-width: 300px !default; +$app-sidebar-sticky-z-index: 105 !default; +$app-sidebar-sticky-bg-color: null !default; +$app-sidebar-sticky-bg-color-dark: null !default; +$app-sidebar-sticky-box-shadow: null !default; +$app-sidebar-sticky-box-shadow-dark: null !default; +$app-sidebar-sticky-border-start: null !default; +$app-sidebar-sticky-border-start-dark: null !default; +$app-sidebar-sticky-border-end: null !default; +$app-sidebar-sticky-border-end-dark: null !default; +$app-sidebar-sticky-gap-start: 0px !default; +$app-sidebar-sticky-gap-end: 0px !default; +$app-sidebar-sticky-gap-top: 0px !default; +$app-sidebar-sticky-gap-bottom: 0px !default; + +// Sidebar minimize +$app-sidebar-minimize-width: 75px !default; +$app-sidebar-minimize-width-mobile: 75px !default; +$app-sidebar-minimize-bg-color: null !default; +$app-sidebar-minimize-bg-color-dark: null !default; +$app-sidebar-minimize-bg-color-mobile: null !default; +$app-sidebar-minimize-bg-color-mobile-dark: null !default; +$app-sidebar-minimize-box-shadow: null !default; +$app-sidebar-minimize-box-shadow-dark: null !default; +$app-sidebar-minimize-box-shadow-mobile: null !default; +$app-sidebar-minimize-box-shadow-mobile-dark: null !default; +$app-sidebar-minimize-hover-box-shadow: null !default; +$app-sidebar-minimize-hover-box-shadow-dark: null !default; +$app-sidebar-minimize-hover-box-shadow-mobile: null !default; +$app-sidebar-minimize-hover-box-shadow-mobile-dark: null !default; +$app-sidebar-minimize-border-start: null !default; +$app-sidebar-minimize-border-start-dark: null !default; +$app-sidebar-minimize-border-start-mobile: null !default; +$app-sidebar-minimize-border-start-mobile-dark: null !default; +$app-sidebar-minimize-border-end: null !default; +$app-sidebar-minimize-border-end-dark: null !default; +$app-sidebar-minimize-border-end-mobile: null !default; +$app-sidebar-minimize-border-end-mobile-dark: null !default; +$app-sidebar-minimize-gap-start: 0px !default; +$app-sidebar-minimize-gap-start-mobile: 0px !default; +$app-sidebar-minimize-gap-end: 0px !default; +$app-sidebar-minimize-gap-end-mobile: 0px !default; +$app-sidebar-minimize-gap-top: 0px !default; +$app-sidebar-minimize-gap-top-mobile: 0px !default; +$app-sidebar-minimize-gap-bottom: 0px !default; +$app-sidebar-minimize-gap-bottom-mobile: 0px !default; + +// Sidebar primary +$app-sidebar-primary-base-transition: none !default; +$app-sidebar-primary-base-width: 100px !default; +$app-sidebar-primary-base-width-mobile: 100px !default; +$app-sidebar-primary-base-z-index: 1 !default; +$app-sidebar-primary-base-z-index-mobile: 1 !default; +$app-sidebar-primary-base-bg-color: null !default; +$app-sidebar-primary-base-bg-color-dark: null !default; +$app-sidebar-primary-base-bg-color-mobile: null !default; +$app-sidebar-primary-base-bg-color-mobile-dark: null !default; +$app-sidebar-primary-base-box-shadow: null !default; +$app-sidebar-primary-base-box-shadow-dark: null !default; +$app-sidebar-primary-base-box-shadow-mobile: null !default; +$app-sidebar-primary-base-box-shadow-mobile-dark: null !default; +$app-sidebar-primary-base-border-start: null !default; +$app-sidebar-primary-base-border-start-dark: null !default; +$app-sidebar-primary-base-border-start-mobile: null !default; +$app-sidebar-primary-base-border-start-mobile-dark: null !default; +$app-sidebar-primary-base-border-end: null !default; +$app-sidebar-primary-base-border-end-dark: null !default; +$app-sidebar-primary-base-border-end-mobile: null !default; +$app-sidebar-primary-base-border-end-mobile-dark: null !default; +$app-sidebar-primary-base-gap-start: 0px !default; +$app-sidebar-primary-base-gap-start-mobile: 0px !default; +$app-sidebar-primary-base-gap-end: 0px !default; +$app-sidebar-primary-base-gap-end-mobile: 0px !default; +$app-sidebar-primary-base-gap-top: 0px !default; +$app-sidebar-primary-base-gap-top-mobile: 0px !default; +$app-sidebar-primary-base-gap-bottom: 0px !default; +$app-sidebar-primary-base-gap-bottom-mobile: 0px !default; + +$app-sidebar-primary-minimize-width: 75px !default; +$app-sidebar-primary-minimize-width-mobile: 75px !default; +$app-sidebar-primary-minimize-z-index: null !default; +$app-sidebar-primary-minimize-bg-color: null !default; +$app-sidebar-primary-minimize-bg-color-dark: null !default; +$app-sidebar-primary-minimize-bg-color-mobile: null !default; +$app-sidebar-primary-minimize-bg-color-mobile-dark: null !default; +$app-sidebar-primary-minimize-box-shadow: null !default; +$app-sidebar-primary-minimize-box-shadow-dark: null !default; +$app-sidebar-primary-minimize-box-shadow-mobile: null !default; +$app-sidebar-primary-minimize-box-shadow-mobile-dark: null !default; +$app-sidebar-primary-minimize-hover-box-shadow: null !default; +$app-sidebar-primary-minimize-hover-box-shadow-dark: null !default; +$app-sidebar-primary-minimize-hover-box-shadow-mobile: null !default; +$app-sidebar-primary-minimize-hover-box-shadow-mobile-dark: null !default; +$app-sidebar-primary-minimize-border-start: null !default; +$app-sidebar-primary-minimize-border-start-dark: null !default; +$app-sidebar-primary-minimize-border-start-mobile: null !default; +$app-sidebar-primary-minimize-border-start-mobile-dark: null !default; +$app-sidebar-primary-minimize-border-end: null !default; +$app-sidebar-primary-minimize-border-end-dark: null !default; +$app-sidebar-primary-minimize-border-end-mobile: null !default; +$app-sidebar-primary-minimize-border-end-mobile-dark: null !default; +$app-sidebar-primary-minimize-gap-start: 0px !default; +$app-sidebar-primary-minimize-gap-start-mobile: 0px !default; +$app-sidebar-primary-minimize-gap-end: 0px !default; +$app-sidebar-primary-minimize-gap-end-mobile: 0px !default; +$app-sidebar-primary-minimize-gap-top: 0px !default; +$app-sidebar-primary-minimize-gap-top-mobile: 0px !default; +$app-sidebar-primary-minimize-gap-bottom: 0px !default; +$app-sidebar-primary-minimize-gap-bottom-mobile: 0px !default; + +// Sidebar secondary +$app-sidebar-secondary-base-transition: none !default; +$app-sidebar-secondary-base-z-index: null !default; +$app-sidebar-secondary-base-z-index-mobile: null !default; +$app-sidebar-secondary-base-bg-color: null !default; +$app-sidebar-secondary-base-bg-color-dark: null !default; +$app-sidebar-secondary-base-bg-color-mobile: null !default; +$app-sidebar-secondary-base-bg-color-mobile-dark: null !default; +$app-sidebar-secondary-base-box-shadow: null !default; +$app-sidebar-secondary-base-box-shadow-dark: null !default; +$app-sidebar-secondary-base-box-shadow-mobile: null !default; +$app-sidebar-secondary-base-box-shadow-mobile-dark: null !default; +$app-sidebar-secondary-base-border-start: null !default; +$app-sidebar-secondary-base-border-start-dark: null !default; +$app-sidebar-secondary-base-border-start-mobile: null !default; +$app-sidebar-secondary-base-border-start-mobile-dark: null !default; +$app-sidebar-secondary-base-border-end: null !default; +$app-sidebar-secondary-base-border-end-dark: null !default; +$app-sidebar-secondary-base-border-end-mobile: null !default; +$app-sidebar-secondary-base-border-end-mobile-dark: null !default; +$app-sidebar-secondary-base-gap-start: 0px !default; +$app-sidebar-secondary-base-gap-start-mobile: 0px !default; +$app-sidebar-secondary-base-gap-end: 0px !default; +$app-sidebar-secondary-base-gap-end-mobile: 0px !default; +$app-sidebar-secondary-base-gap-top: 0px !default; +$app-sidebar-secondary-base-gap-top-mobile: 0px !default; +$app-sidebar-secondary-base-gap-bottom: 0px !default; +$app-sidebar-secondary-base-gap-bottom-mobile: 0px !default; + +$app-sidebar-secondary-minimize-width: 75px !default; +$app-sidebar-secondary-minimize-width-mobile: 75px !default; +$app-sidebar-secondary-minimize-z-index: null !default; +$app-sidebar-secondary-minimize-bg-color: null !default; +$app-sidebar-secondary-minimize-bg-color-dark: null !default; +$app-sidebar-secondary-minimize-bg-color-mobile: null !default; +$app-sidebar-secondary-minimize-bg-color-mobile-dark: null !default; +$app-sidebar-secondary-minimize-box-shadow: null !default; +$app-sidebar-secondary-minimize-box-shadow-dark: null !default; +$app-sidebar-secondary-minimize-box-shadow-mobile: null !default; +$app-sidebar-secondary-minimize-box-shadow-mobile-dark: null !default; +$app-sidebar-secondary-minimize-hover-box-shadow: null !default; +$app-sidebar-secondary-minimize-hover-box-shadow-dark: null !default; +$app-sidebar-secondary-minimize-hover-box-shadow-mobile: null !default; +$app-sidebar-secondary-minimize-hover-box-shadow-mobile-dark: null !default; +$app-sidebar-secondary-minimize-border-start: null !default; +$app-sidebar-secondary-minimize-border-start-dark: null !default; +$app-sidebar-secondary-minimize-border-start-mobile: null !default; +$app-sidebar-secondary-minimize-border-start-mobile-dark: null !default; +$app-sidebar-secondary-minimize-border-end: null !default; +$app-sidebar-secondary-minimize-border-end-dark: null !default; +$app-sidebar-secondary-minimize-border-end-mobile: null !default; +$app-sidebar-secondary-minimize-border-end-mobile-dark: null !default; +$app-sidebar-secondary-minimize-gap-start: 0px !default; +$app-sidebar-secondary-minimize-gap-start-mobile: 0px !default; +$app-sidebar-secondary-minimize-gap-end: 0px !default; +$app-sidebar-secondary-minimize-gap-end-mobile: 0px !default; +$app-sidebar-secondary-minimize-gap-top: 0px !default; +$app-sidebar-secondary-minimize-gap-top-mobile: 0px !default; +$app-sidebar-secondary-minimize-gap-bottom: 0px !default; +$app-sidebar-secondary-minimize-gap-bottom-mobile: 0px !default; + +// Sidebar panel base +$app-sidebar-panel-base-transition: none !default; +$app-sidebar-panel-base-width: 300px !default; +$app-sidebar-panel-base-width-mobile: 300px !default; +$app-sidebar-panel-base-z-index: null !default; +$app-sidebar-panel-base-z-index-mobile: null !default; +$app-sidebar-panel-base-bg-color: null !default; +$app-sidebar-panel-base-bg-color-dark: null !default; +$app-sidebar-panel-base-bg-color-mobile: null !default; +$app-sidebar-panel-base-bg-color-mobile-dark: null !default; +$app-sidebar-panel-base-box-shadow: null !default; +$app-sidebar-panel-base-box-shadow-dark: null !default; +$app-sidebar-panel-base-box-shadow-mobile: null !default; +$app-sidebar-panel-base-box-shadow-mobile-dark: null !default; +$app-sidebar-panel-base-border-start: null !default; +$app-sidebar-panel-base-border-start-dark: null !default; +$app-sidebar-panel-base-border-start-mobile: null !default; +$app-sidebar-panel-base-border-start-mobile-dark: null !default; +$app-sidebar-panel-base-border-end: null !default; +$app-sidebar-panel-base-border-end-dark: null !default; +$app-sidebar-panel-base-border-end-mobile: null !default; +$app-sidebar-panel-base-border-end-mobile-dark: null !default; +$app-sidebar-panel-base-gap-start: 0px !default; +$app-sidebar-panel-base-gap-start-mobile: 0px !default; +$app-sidebar-panel-base-gap-end: 0px !default; +$app-sidebar-panel-base-gap-end-mobile: 0px !default; +$app-sidebar-panel-base-gap-top: 0px !default; +$app-sidebar-panel-base-gap-top-mobile: 0px !default; +$app-sidebar-panel-base-gap-bottom: 0px !default; +$app-sidebar-panel-base-gap-bottom-mobile: 0px !default; + +// Sidebar panel fixed +$app-sidebar-panel-fixed-z-index: 104 !default; +$app-sidebar-panel-fixed-z-index-mobile: 105 !default; + +// Sidebar panel sticky +$app-sidebar-panel-sticky-top: auto !default; +$app-sidebar-panel-sticky-bottom: auto !default; +$app-sidebar-panel-sticky-width: 300px !default; +$app-sidebar-panel-sticky-z-index: 104 !default; +$app-sidebar-panel-sticky-bg-color: null !default; +$app-sidebar-panel-sticky-bg-color-dark: null !default; +$app-sidebar-panel-sticky-box-shadow: null !default; +$app-sidebar-panel-sticky-box-shadow-dark: null !default; +$app-sidebar-panel-sticky-border-start: null !default; +$app-sidebar-panel-sticky-border-start-dark: null !default; +$app-sidebar-panel-sticky-border-end: null !default; +$app-sidebar-panel-sticky-border-end-dark: null !default; +$app-sidebar-panel-sticky-gap-start: 0px !default; +$app-sidebar-panel-sticky-gap-start-mobile: 0px !default; +$app-sidebar-panel-sticky-gap-end: 0px !default; +$app-sidebar-panel-sticky-gap-end-mobile: 0px !default; +$app-sidebar-panel-sticky-gap-top: 0px !default; +$app-sidebar-panel-sticky-gap-top-mobile: 0px !default; +$app-sidebar-panel-sticky-gap-bottom: 0px !default; +$app-sidebar-panel-sticky-gap-bottom-mobile: 0px !default; + +// Sidebar panel minimize +$app-sidebar-panel-minimize-width: 75px !default; +$app-sidebar-panel-minimize-width-mobile: 75px !default; +$app-sidebar-panel-minimize-bg-color: null !default; +$app-sidebar-panel-minimize-bg-color-dark: null !default; +$app-sidebar-panel-minimize-bg-color-mobile: null !default; +$app-sidebar-panel-minimize-bg-color-mobile-dark: null !default; +$app-sidebar-panel-minimize-box-shadow: null !default; +$app-sidebar-panel-minimize-box-shadow-dark: null !default; +$app-sidebar-panel-minimize-box-shadow-mobile: null !default; +$app-sidebar-panel-minimize-box-shadow-mobile-dark: null !default; +$app-sidebar-panel-minimize-hover-box-shadow: null !default; +$app-sidebar-panel-minimize-hover-box-shadow-dark: null !default; +$app-sidebar-panel-minimize-hover-box-shadow-mobile: null !default; +$app-sidebar-panel-minimize-hover-box-shadow-mobile-dark: null !default; +$app-sidebar-panel-minimize-border-start: null !default; +$app-sidebar-panel-minimize-border-start-dark: null !default; +$app-sidebar-panel-minimize-border-start-mobile: null !default; +$app-sidebar-panel-minimize-border-start-mobile-dark: null !default; +$app-sidebar-panel-minimize-border-end: null !default; +$app-sidebar-panel-minimize-border-end-dark: null !default; +$app-sidebar-panel-minimize-border-end-mobile: null !default; +$app-sidebar-panel-minimize-border-end-mobile-dark: null !default; +$app-sidebar-panel-minimize-gap-start: 0px !default; +$app-sidebar-panel-minimize-gap-start-mobile: 0px !default; +$app-sidebar-panel-minimize-gap-end: 0px !default; +$app-sidebar-panel-minimize-gap-end-mobile: 0px !default; +$app-sidebar-panel-minimize-gap-top: 0px !default; +$app-sidebar-panel-minimize-gap-top-mobile: 0px !default; +$app-sidebar-panel-minimize-gap-bottom: 0px !default; +$app-sidebar-panel-minimize-gap-bottom-mobile: 0px !default; + +// Aside base +$app-aside-base-transition: none; +$app-aside-base-width: 300px !default; +$app-aside-base-width-mobile: 275px !default; +$app-aside-base-z-index: null !default; +$app-aside-base-z-index-mobile: 106 !default; +$app-aside-base-bg-color: null !default; +$app-aside-base-bg-color-dark: null !default; +$app-aside-base-bg-color-mobile: null !default; +$app-aside-base-bg-color-mobile-dark: null !default; +$app-aside-base-box-shadow: null !default; +$app-aside-base-box-shadow-dark: null !default; +$app-aside-base-box-shadow-mobile: null !default; +$app-aside-base-box-shadow-mobile-dark: null !default; +$app-aside-base-border-start: null !default; +$app-aside-base-border-start-dark: null !default; +$app-aside-base-border-start-mobile: null !default; +$app-aside-base-border-start-mobile-dark: null !default; +$app-aside-base-border-end: null !default; +$app-aside-base-border-end-dark: null !default; +$app-aside-base-border-end-mobile: null !default; +$app-aside-base-border-end-mobile-dark: null !default; +$app-aside-base-gap-start: 0px !default; +$app-aside-base-gap-start-mobile: 0px !default; +$app-aside-base-gap-end: 0px !default; +$app-aside-base-gap-end-mobile: 0px !default; +$app-aside-base-gap-top: 0px !default; +$app-aside-base-gap-top-mobile: 0px !default; +$app-aside-base-gap-bottom: 0px !default; +$app-aside-base-gap-bottom-mobile: 0px !default; + +// Aside fixed +$app-aside-fixed-z-index: 105 !default; +$app-aside-fixed-right: 0 !default; +$app-aside-fixed-top: 0 !default; +$app-aside-fixed-bottom: 0 !default; + +// Aside sticky +$app-aside-sticky-top: auto !default; +$app-aside-sticky-bottom: auto !default; +$app-aside-sticky-left: auto !default; +$app-aside-sticky-width: 300px !default; +$app-aside-sticky-z-index: 105 !default; +$app-aside-sticky-bg-color: null !default; +$app-aside-sticky-bg-color-dark: null !default; +$app-aside-sticky-box-shadow: null !default; +$app-aside-sticky-box-shadow-dark: null !default; +$app-aside-sticky-border-start: null !default; +$app-aside-sticky-border-start-dark: null !default; +$app-aside-sticky-border-end: null !default; +$app-aside-sticky-border-end-dark: null !default; +$app-aside-sticky-gap-start: 0px !default; +$app-aside-sticky-gap-end: 0px !default; +$app-aside-sticky-gap-top: 0px !default; +$app-aside-sticky-gap-bottom: 0px !default; + +// Aside minimize +$app-aside-minimize-width: 75px !default; +$app-aside-minimize-width-mobile: 75px !default; +$app-aside-minimize-bg-color: null !default; +$app-aside-minimize-bg-color-dark: null !default; +$app-aside-minimize-bg-color-mobile: null !default; +$app-aside-minimize-bg-color-mobile-dark: null !default; +$app-aside-minimize-box-shadow: null !default; +$app-aside-minimize-box-shadow-dark: null !default; +$app-aside-minimize-box-shadow-mobile: null !default; +$app-aside-minimize-box-shadow-mobile-dark: null !default; +$app-aside-minimize-hover-box-shadow: null !default; +$app-aside-minimize-hover-box-shadow-dark: null !default; +$app-aside-minimize-hover-box-shadow-mobile: null !default; +$app-aside-minimize-hover-box-shadow-mobile-dark: null !default; +$app-aside-minimize-border-start: null !default; +$app-aside-minimize-border-start-dark: null !default; +$app-aside-minimize-border-start-mobile: null !default; +$app-aside-minimize-border-start-mobile-dark: null !default; +$app-aside-minimize-border-end: null !default; +$app-aside-minimize-border-end-dark: null !default; +$app-aside-minimize-border-end-mobile: null !default; +$app-aside-minimize-border-end-mobile-dark: null !default; +$app-aside-minimize-gap-start: 0px !default; +$app-aside-minimize-gap-start-mobile: 0px !default; +$app-aside-minimize-gap-end: 0px !default; +$app-aside-minimize-gap-end-mobile: 0px !default; +$app-aside-minimize-gap-top: 0px !default; +$app-aside-minimize-gap-top-mobile: 0px !default; +$app-aside-minimize-gap-bottom: 0px !default; +$app-aside-minimize-gap-bottom-mobile: 0px !default; + +// Footer +$app-footer-transition: left $app-general-transition-duration $app-general-transition-timing, right $app-general-transition-duration $app-general-transition-timing; +$app-footer-height: 70px !default; +$app-footer-height-mobile: 70px !default; +$app-footer-z-index: null !default; +$app-footer-z-index-mobile: null !default; +$app-footer-bg-color: null !default; +$app-footer-bg-color-dark: null !default; +$app-footer-bg-color-mobile: null !default; +$app-footer-bg-color-mobile-dark: null !default; +$app-footer-box-shadow: null !default; +$app-footer-box-shadow-dark: null !default; +$app-footer-box-shadow-mobile: null !default; +$app-footer-box-shadow-mobile-dark: null !default; +$app-footer-border-top: null !default; +$app-footer-border-top-dark: null !default; +$app-footer-border-top-mobile: null !default; +$app-footer-border-top-mobile-dark: null !default; + +// Footer fixed +$app-footer-fixed-z-index: 100 !default; +$app-footer-fixed-z-index-mobile: 100 !default; + +// Layout Builder +$app-layout-builder-toggle-z-index: 105 !default; +$app-layout-builder-toggle-bottom: 40px !default; +$app-layout-builder-toggle-bottom-mobile: 15px !default; +$app-layout-builder-toggle-end: 40px !default; +$app-layout-builder-toggle-end-mobile: 15px !default; \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/_wrapper.scss b/src/_res/assets/sass/core/layout/base/_wrapper.scss new file mode 100644 index 0000000..a8734b1 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/_wrapper.scss @@ -0,0 +1,100 @@ +// +// Wrapper +// + +// General mode +.app-wrapper { + display: flex; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Integration + .app-wrapper { + transition: $app-wrapper-transition; + + // Header + [data-kt-app-header-sticky="on"] & { + margin-top: var(--kt-app-header-height-actual); + } + + [data-kt-app-header-fixed="true"] & { + margin-top: var(--kt-app-header-height); + } + + // Toolbar + [data-kt-app-toolbar-sticky="on"] & { + margin-top: var(--kt-app-toolbar-height); + } + + [data-kt-app-header-fixed="true"][data-kt-app-toolbar-sticky="on"] & { + margin-top: calc(var(--kt-app-header-height-actual) + var(--kt-app-toolbar-height-actual)); + } + + [data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"] & { + margin-top: calc(var(--kt-app-header-height) + var(--kt-app-toolbar-height)); + } + + // Sidebar + [data-kt-app-sidebar-fixed="true"] & { + margin-left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + // Sidebar Panel + [data-kt-app-sidebar-panel-fixed="true"] & { + margin-left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + + // Aside + [data-kt-app-aside-fixed="true"] & { + margin-right: calc( + var(--kt-app-aside-width) + + var(--kt-app-aside-gap-start, 0px) + + var(--kt-app-aside-gap-end, 0px) + ); + } + + // Footer + [data-kt-app-footer-fixed="true"] & { + margin-bottom: var(--kt-app-footer-height); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Integration + .app-wrapper { + transition: $app-wrapper-transition; + + // Header + [data-kt-app-header-sticky="on"] & { + margin-top: var(--kt-app-header-height-actual); + } + + [data-kt-app-header-fixed-mobile="true"] & { + margin-top: var(--kt-app-header-height); + } + + // Toolbar + [data-kt-app-header-fixed-mobile="true"][data-kt-app-toolbar-sticky="on"] & { + margin-top: calc(var(--kt-app-header-height-actual) + var(--kt-app-toolbar-height-actual)); + } + + // Footer + [data-kt-app-footer-fixed-mobile="true"] & { + margin-bottom: var(--kt-app-footer-height); + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/aside/_aside.scss b/src/_res/assets/sass/core/layout/base/aside/_aside.scss new file mode 100644 index 0000000..71f38c3 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/aside/_aside.scss @@ -0,0 +1,294 @@ +// +// Aside +// + +// General mode +.app-aside { + transition: $app-aside-base-transition; +} + +// Utilities +.app-aside-minimize-d-flex, +.app-aside-sticky-d-flex, +.app-aside-collapse-d-flex, +.app-aside-minimize-mobile-d-flex, +.app-aside-collapse-mobile-d-flex { + display: none; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-aside { + display: flex; + flex-shrink: 0; + width: var(--kt-app-aside-width); + background-color: var(--kt-app-aside-base-bg-color); + box-shadow: var(--kt-app-aside-base-box-shadow); + border-left: var(--kt-app-aside-base-border-left); + border-right: var(--kt-app-aside-base-border-right); + + @include property( margin-left, $app-aside-base-gap-start); + @include property( margin-right, $app-aside-base-gap-end); + @include property( margin-top, $app-aside-base-gap-top); + @include property( margin-bottom, $app-aside-base-gap-bottom); + @include property( z-index, $app-aside-base-z-index); + } + + // Vars + :root { + --kt-app-aside-width: #{$app-aside-base-width}; + --kt-app-aside-width-actual: #{$app-aside-base-width}; + + --kt-app-aside-gap-start: #{$app-aside-base-gap-start}; + --kt-app-aside-gap-end: #{$app-aside-base-gap-end}; + --kt-app-aside-gap-top: #{$app-aside-base-gap-top}; + --kt-app-aside-gap-bottom: #{$app-aside-base-gap-bottom}; + } + + [data-kt-app-aside-stacked="true"] { + --kt-app-aside-width: calc(var(--kt-app-aside-primary-width) + var(--kt-app-aside-secondary-width)); + } + + [data-kt-app-aside-minimize="on"] { + --kt-app-aside-width: #{$app-aside-minimize-width}; + + --kt-app-aside-gap-start: #{$app-aside-minimize-gap-start}; + --kt-app-aside-gap-end: #{$app-aside-minimize-gap-end}; + --kt-app-aside-gap-top: #{$app-aside-minimize-gap-top}; + --kt-app-aside-gap-bottom: #{$app-aside-minimize-gap-bottom}; + } + + [data-kt-app-aside-sticky="on"] { + --kt-app-aside-width: #{$app-aside-sticky-width}; + + --kt-app-aside-gap-start: #{$app-aside-sticky-gap-start}; + --kt-app-aside-gap-end: #{$app-aside-sticky-gap-end}; + --kt-app-aside-gap-top: #{$app-aside-sticky-gap-top}; + --kt-app-aside-gap-bottom: #{$app-aside-sticky-gap-bottom}; + } + + [data-kt-app-aside-collapse="on"] { + --kt-app-aside-width: 0px; + } + + // States + .app-aside { + [data-kt-app-aside-static="true"] & { + position: relative; + } + + [data-kt-app-aside-offcanvas="true"] & { + display: none; + } + + [data-kt-app-aside-fixed="true"] & { + position: fixed; + @include property( z-index, $app-aside-fixed-z-index); + @include property( top, $app-aside-fixed-top); + @include property( bottom, $app-aside-fixed-bottom); + @include property( right, $app-aside-fixed-right); + } + + [data-kt-app-aside-stacked="true"] & { + align-items: stretch; + } + + [data-kt-app-aside-sticky="on"] & { + position: fixed; + transition: $app-aside-base-transition; + + box-shadow: var(--kt-app-aside-sticky-box-shadow); + border-left: var(--kt-aside-sticky-border-start); + border-right: var(--kt-app-aside-sticky-border-end); + + @include property( top, $app-aside-sticky-top); + @include property( bottom, $app-aside-sticky-bottom); + @include property( left, $app-aside-sticky-left); + @include property( z-index, $app-aside-sticky-z-index); + @include property( margin-left, $app-aside-sticky-gap-start); + @include property( margin-right, $app-aside-sticky-gap-end); + @include property( margin-top, $app-aside-sticky-gap-top); + @include property( margin-bottom, $app-aside-sticky-gap-bottom); + } + + [data-kt-app-aside-minimize="on"] & { + transition: $app-aside-base-transition; + + background-color: var(--kt-app-aside-minimize-bg-color); + box-shadow: var(--kt-app-aside-minimize-box-shadow); + border-start: var(--kt-app-aside-minimize-border-start); + border-end: var(--kt-app-aside-minimize-border-end); + + @include property( margin-left, $app-aside-minimize-gap-start); + @include property( margin-right, $app-aside-minimize-gap-end); + @include property( margin-top, $app-aside-minimize-gap-top); + @include property( margin-bottom, $app-aside-minimize-gap-bottom); + } + + [data-kt-app-aside-hoverable="true"] & { + .app-aside-wrapper { + width: var(--kt-app-aside-width-actual); + } + } + + [data-kt-app-aside-hoverable="true"][data-kt-app-aside-minimize="on"] &:hover:not(.animating) { + transition: $app-aside-base-transition; + width: var(--kt-app-aside-width-actual); + box-shadow: var(--kt-app-aside-minimize-hover-box-shadow); + } + + [data-kt-app-aside-collapse="on"] & { + transition: $app-aside-base-transition; + width: var(--kt-app-aside-width-actual); + margin-right: calc( -1 * var(--kt-app-aside-width-actual)); + } + } + + // Utilities + [data-kt-app-aside-minimize="on"] { + .app-aside-minimize-d-none { + display: none !important; + } + + .app-aside-minimize-d-flex { + display: flex !important; + } + } + + [data-kt-app-aside-sticky="on"] { + .app-aside-sticky-d-none { + display: none !important; + } + + .app-aside-sticky-d-flex { + display: flex !important; + } + } + + [data-kt-app-aside-collapse="on"] { + .app-aside-collapse-d-none { + display: none !important; + } + + .app-aside-collapse-d-flex { + display: flex !important; + } + } + + // Integration + .app-aside { + // Header + [data-kt-app-aside-fixed="true"][data-kt-app-header-fixed="true"]:not([data-kt-app-aside-push-header="true"]) & { + top: var(--kt-app-header-height); + } + + // Toolbar + [data-kt-app-aside-fixed="true"][data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"]:not([data-kt-app-aside-push-toolbar="true"]) & { + top: calc(var(--kt-app-header-height) + var(--kt-app-toolbar-height, 0px)); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-aside { + display: none; + width: var(--kt-app-aside-width); + @include property( z-index, $app-aside-base-z-index-mobile); + + background-color: var(--kt-app-aside-base-bg-color-mobile); + box-shadow: var(--kt-app-aside-base-box-shadow-mobile); + border-left: var(--kt-app-aside-base-border-start-mobile); + order-right: var(--kt-app-aside-base-border-end-mobile); + + @include property( margin-left, $app-aside-base-gap-start-mobile); + @include property( margin-right, $app-aside-base-gap-end-mobile); + @include property( margin-top, $app-aside-base-gap-top-mobile); + @include property( margin-bottom, $app-aside-base-gap-bottom-mobile); + } + + // Vars + :root { + --kt-app-aside-width: #{$app-aside-base-width-mobile}; + --kt-app-aside-width-actual: #{$app-aside-base-width-mobile}; + + --kt-app-aside-gap-start: #{$app-aside-base-gap-start-mobile}; + --kt-app-aside-gap-end: #{$app-aside-base-gap-end-mobile}; + --kt-app-aside-gap-top: #{$app-aside-base-gap-top-mobile}; + --kt-app-aside-gap-bottom: #{$app-aside-base-gap-bottom-mobile}; + } + + [data-kt-app-aside-minimize-mobile="on"] { + --kt-app-aside-width: #{$app-aside-minimize-width-mobile}; + + --kt-app-aside-gap-start: #{$app-aside-minimize-gap-start-mobile}; + --kt-app-aside-gap-end: #{$app-aside-minimize-gap-end-mobile}; + --kt-app-aside-gap-top: #{$app-aside-minimize-gap-top-mobile}; + --kt-app-aside-gap-bottom: #{$app-aside-minimize-gap-bottom-mobile}; + } + + [data-kt-app-aside-collapse-mobile="on"] { + --kt-app-aside-width: 0px; + } + + // States + .app-aside { + [data-kt-app-aside-stacked="true"] & { + align-items: stretch; + } + + [data-kt-app-aside-minimize-mobile="on"] & { + transition: $app-aside-base-transition; + background-color: var(--kt-app-aside-minimize-bg-color-mobile); + box-shadow: var(--kt-app-aside-minimize-box-shadow-mobile); + border-left: var(--kt-app-aside-minimize-border-start-mobile); + border-right: var(--kt-app-aside-minimize-border-end-mobile); + + @include property( margin-left, $app-aside-minimize-gap-start-mobile); + @include property( margin-right, $app-aside-minimize-gap-end-mobile); + @include property( margin-top, $app-aside-minimize-gap-top-mobile); + @include property( margin-bottom, $app-aside-minimize-gap-bottom-mobile); + } + + [data-kt-app-aside-hoverable-mobile="true"] & { + .app-aside-wrapper { + width: var(--kt-app-aside-width-actual); + } + } + + [data-kt-app-aside-hoverable-mobile="true"][data-kt-app-aside-minimize-mobile="on"] &:hover:not(.animating) { + transition: $app-aside-base-transition; + width: var(--kt-app-aside-width-actual); + box-shadow: var(--kt-app-aside-minimize-hover-box-shadow-mobile); + } + + [data-kt-app-aside-collapse-mobile="on"] & { + transition: $app-aside-base-transition; + width: var(--kt-app-aside-width-actual); + margin-right: calc( -1 * var(--kt-app-aside-width-actual)); + } + } + + // Utilities + [data-kt-app-aside-minimize-mobile="on"] { + .app-aside-minimize-mobile-d-none { + display: none !important; + } + + .app-aside-minimize-mobile-d-flex { + display: flex !important; + } + } + + [data-kt-app-aside-collapse-mobile="on"] { + .app-aside-collapse-mobile-d-none { + display: none !important; + } + + .app-aside-collapse-mobile-d-flex { + display: flex !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/header/_header-primary.scss b/src/_res/assets/sass/core/layout/base/header/_header-primary.scss new file mode 100644 index 0000000..4456c2a --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/header/_header-primary.scss @@ -0,0 +1,120 @@ +// +// Header primary +// + +// General mode +.app-header-primary { + transition: $app-header-primary-base-transition; + display: flex; + align-items: stretch; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-header-primary { + @include property( z-index, $app-header-primary-base-z-index); + + background-color: var(--kt-app-header-primary-base-bg-color); + box-shadow: var(--kt-app-header-primary-base-box-shadow); + border-bottom: var(--kt-app-header-primary-base-border-bottom); + } + + // Vars + :root { + --kt-app-header-primary-height: #{$app-header-primary-base-height}; + } + + [data-kt-app-header-sticky="on"] { + --kt-app-header-primary-height: #{$app-header-primary-sticky-height}; + } + + [data-kt-app-header-minimize="on"] { + --kt-app-header-primary-height: #{$app-header-primary-minimize-height}; + } + + [data-kt-app-header-sticky="on"][data-kt-app-header-primary-sticky-hide="true"] { + --kt-app-header-primary-height: 0; + } + + // States + .app-header-primary { + height: var(--kt-app-header-primary-height); + + [data-kt-app-header-primary-fixed="true"] & { + @include property( z-index, $app-header-primary-fixed-z-index); + position: fixed; + left: 0; + right: 0; + top: 0; + } + + [data-kt-app-header-primary-static="true"] & { + position: relative; + } + + [data-kt-app-header-primary-sticky="on"] & { + position: fixed; + left: 0; + right: 0; + top: 0; + @include property( height, $app-header-primary-sticky-height); + @include property( z-index, $app-header-primary-sticky-z-index); + + background-color: var(--kt-app-header-primary-sticky-bg-color); + box-shadow: var(--kt-app-header-primary-sticky-box-shadow); + border-bottom: var(--kt-app-header-primary-sticky-border-bottom); + } + + [data-kt-app-header-primary-minimize="on"] & { + transition: $app-header-primary-base-transition; + @include property( height, $app-header-primary-minimize-height); + @include property( z-index, $app-header-primary-minimize-z-index); + + background-color: var(--kt-app-header-primary-minimize-bg-color); + box-shadow: var(--kt-app-header-primary-minimize-box-shadow); + border-bottom: var(--kt-app-header-primary-minimize-border-bottom); + } + + [data-kt-app-header-sticky="on"][data-kt-app-header-primary-sticky-hide="true"] & { + display: none !important; + } + } + + // Integration + .app-header-primary { + // Sidebar + [data-kt-app-sidebar-fixed="true"][data-kt-app-sidebar-push-header="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + // Sidebar Panel + [data-kt-app-sidebar-panel-fixed="true"][data-kt-app-sidebar-panel-push-header="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-header-primary { + flex-grow: 1; + @include property( z-index, $app-header-primary-base-z-index-mobile); + + background-color: var(--kt-app-header-primary-base-bg-color-mobile); + box-shadow: var(--kt-app-header-primary-base-box-shadow-mobile); + border-bottom: var(--kt-app-header-primary-base-border-bottom-mobile); + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/header/_header-secondary.scss b/src/_res/assets/sass/core/layout/base/header/_header-secondary.scss new file mode 100644 index 0000000..8549f76 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/header/_header-secondary.scss @@ -0,0 +1,120 @@ +// +// Header secondary +// + +// General mode +.app-header-secondary { + transition: $app-header-secondary-base-transition; + display: flex; + align-items: stretch; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-header-secondary { + @include property( z-index, $app-header-secondary-base-z-index); + + background-color: var(--kt-app-header-secondary-base-bg-color); + box-shadow: var(--kt-app-header-secondary-base-box-shadow); + border-bottom: var(--kt-app-header-secondary-base-border-bottom); + } + + // Vars + :root { + --kt-app-header-secondary-height: #{$app-header-secondary-base-height}; + } + + [data-kt-app-header-sticky="on"] { + --kt-app-header-secondary-height: #{$app-header-secondary-sticky-height}; + } + + [data-kt-app-header-minimize="on"] { + --kt-app-header-secondary-height: #{$app-header-secondary-minimize-height}; + } + + [data-kt-app-header-sticky="on"][data-kt-app-header-secondary-sticky-hide="true"] { + --kt-app-header-secondary-height: 0; + } + + // States + .app-header-secondary { + height: var(--kt-app-header-secondary-height); + + [data-kt-app-header-secondary-fixed="true"] & { + @include property( z-index, $app-header-secondary-fixed-z-index); + position: fixed; + left: 0; + right: 0; + top: 0; + } + + [data-kt-app-header-secondary-static="true"] & { + position: static; + } + + [data-kt-app-header-secondary-sticky="on"] & { + transition: $app-header-secondary-base-transition; + position: fixed; + left: 0; + right: 0; + top: 0; + @include property( height, $app-header-secondary-sticky-height); + @include property( z-index, $app-header-secondary-sticky-z-index); + + background-color: var(--kt-app-header-secondary-sticky-bg-color); + box-shadow: var(--kt-app-header-secondary-sticky-box-shadow); + border-bottom: var(--kt-app-header-secondary-sticky-border-bottom); + } + + [data-kt-app-header-secondary-minimize="on"] & { + transition: $app-header-secondary-base-transition; + @include property( height, $app-header-secondary-minimize-height); + @include property( z-index, $app-header-secondary-minimize-z-index); + + background-color: var(--kt-app-header-secondary-minimize-bg-color); + box-shadow: var(--kt-app-header-secondary-minimize-box-shadow); + border-bottom: var(--kt-app-header-secondary-minimize-border-bottom); + } + + [data-kt-app-header-sticky="on"][data-kt-app-header-secondary-sticky-hide="true"] & { + display: none !important; + } + } + + // Integration + .app-header-secondary { + // Sidebar + [data-kt-app-sidebar-fixed="true"][data-kt-app-sidebar-push-header="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + // Sidebar Panel + [data-kt-app-sidebar-panel-fixed="true"][data-kt-app-sidebar-panel-push-header="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-header-secondary { + flex-grow: 1; + background-color: var(--kt-app-header-secondary-base-bg-color-mobile); + box-shadow: var(--kt-app-header-secondary-base-box-shadow-mobile); + border-left: var(--kt-app-header-secondary-base-border-start-mobile); + border-right: var(--kt-app-header-secondary-base-border-end-mobile); + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/header/_header.scss b/src/_res/assets/sass/core/layout/base/header/_header.scss new file mode 100644 index 0000000..5283b2c --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/header/_header.scss @@ -0,0 +1,228 @@ +// +// sidebar +// + +// General mode +.app-header { + transition: $app-header-base-transition; + display: flex; + align-items: stretch; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-header { + @include property( z-index, $app-header-base-z-index); + + background-color: var(--kt-app-header-base-bg-color); + box-shadow: var(--kt-app-header-base-box-shadow); + border-bottom: var(--kt-app-header-base-border-bottom); + } + + // Vars + :root { + --kt-app-header-height: #{$app-header-base-height}; + --kt-app-header-height-actual: #{$app-header-base-height}; + } + + [data-kt-app-header-sticky="on"] { + --kt-app-header-height: #{$app-header-sticky-height}; + --kt-app-header-height-actual: #{$app-header-base-height}; + } + + [data-kt-app-header-sticky="on"][data-kt-app-header-stacked="true"] { + --kt-app-header-height: calc(var(--kt-app-header-primary-height, 0px) + var(--kt-app-header-secondary-height, 0px)); + --kt-app-header-height-actual: calc(#{$app-header-primary-base-height} + #{$app-header-secondary-base-height}); + } + + [data-kt-app-header-minimize="on"] { + --kt-app-header-height: #{$app-header-minimize-height}; + } + + // States + .app-header { + height: var(--kt-app-header-height); + + [data-kt-app-header-fixed="true"] & { + @include property( z-index, $app-header-fixed-z-index); + position: fixed; + left: 0; + right: 0; + top: 0; + } + + [data-kt-app-header-static="true"] & { + position: relative; + } + + [data-kt-app-header-stacked="true"] & { + flex-direction: column; + height: calc(var(--kt-app-header-primary-height) + var(--kt-app-header-secondary-height, 0px)); + } + + [data-kt-app-header-sticky="on"] & { + position: fixed; + left: 0; + right: 0; + top: 0; + @include property( z-index, $app-header-sticky-z-index); + @include property( backdrop-filter, $app-header-sticky-backdrop-filter); + + background-color: var(--kt-app-header-sticky-bg-color); + box-shadow: var(--kt-app-header-sticky-box-shadow); + border-bottom: var(--kt-app-header-sticky-border-bottom); + } + + [data-kt-app-header-minimize="on"] & { + transition: $app-header-base-transition; + @include property( z-index, $app-header-minimize-z-index); + @include property( backdrop-filter, $app-header-minimize-backdrop-filter); + + background-color: var(--kt-app-header-minimize-bg-color); + box-shadow: var(--kt-app-header-minimize-box-shadow); + border-bottom: var(--kt-app-header-minimize-border-bottom); + } + + .app-header-mobile-drawer { + display: flex; + } + } + + // Integration + .app-header { + // Sidebar + [data-kt-app-header-fixed="true"][data-kt-app-sidebar-fixed="true"][data-kt-app-sidebar-push-header="true"] &, + [data-kt-app-header-fixed="true"][data-kt-app-sidebar-sticky="on"][data-kt-app-sidebar-push-header="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + body:not([data-kt-app-header-fixed="true"])[data-kt-app-sidebar-fixed="true"][data-kt-app-sidebar-push-header="true"] &, + body:not([data-kt-app-header-fixed="true"])[data-kt-app-sidebar-sticky="on"][data-kt-app-sidebar-push-header="true"] & { + margin-left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + ); + } + + // Sidebar Panel + [data-kt-app-header-fixed="true"][data-kt-app-sidebar-panel-fixed="true"][data-kt-app-sidebar-panel-push-header="true"] &, + [data-kt-app-header-fixed="true"][data-kt-app-sidebar-panel-sticky="on"][data-kt-app-sidebar-panel-push-header="true"] & { + left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + + body:not([data-kt-app-header-fixed="true"])[data-kt-app-sidebar-panel-fixed="true"][data-kt-app-sidebar-panel-push-header="true"] &, + body:not([data-kt-app-header-fixed="true"])[data-kt-app-sidebar-panel-sticky="on"][data-kt-app-sidebar-panel-push-header="true"] & { + margin-left: calc( + var(--kt-app-sidebar-width) + + var(--kt-app-sidebar-gap-start, 0px) + + var(--kt-app-sidebar-gap-end, 0px) + + var(--kt-app-sidebar-panel-width) + + var(--kt-app-sidebar-panel-gap-start, 0px) + + var(--kt-app-sidebar-panel-gap-end, 0px) + ); + } + + // Toolbar + [data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"] & { + box-shadow: none; + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-header { + @include property( z-index, $app-header-base-z-index-mobile); + + background-color: var(--kt-app-header-base-bg-color-mobile); + box-shadow: var(--kt-app-header-base-box-shadow-mobile); + border-bottom: var(--kt-app-header-base-border-bottom-mobile); + } + + // Vars + :root { + --kt-app-header-height: #{$app-header-base-height-mobile}; + } + + [data-kt-app-header-sticky="on"] { + --kt-app-header-height: #{$app-header-sticky-height-mobile}; + --kt-app-header-height-actual: #{$app-header-sticky-height-mobile}; + } + + [data-kt-app-header-minimize="on"] { + --kt-app-header-height: #{$app-header-minimize-height-mobile}; + --kt-app-header-height-actual: #{$app-header-minimize-height-mobile}; + } + + // States + .app-header { + height: var(--kt-app-header-height); + align-items: stretch; + + .app-header-mobile-drawer { + display: none; + } + + [data-kt-app-header-stacked="true"] & { + flex-direction: column; + } + + [data-kt-app-header-fixed-mobile="true"] & { + @include property( z-index, $app-header-fixed-z-index-mobile); + transition: $app-header-base-transition; + position: fixed; + left: 0; + right: 0; + top: 0; + } + + [data-kt-app-header-sticky="on"] & { + position: fixed; + left: 0; + right: 0; + top: 0; + @include property( z-index, $app-header-sticky-z-index-mobile); + @include property( backdrop-filter, $app-header-sticky-backdrop-filter-mobile); + + background-color: var(--kt-app-header-sticky-bg-color-mobile); + box-shadow: var(--kt-app-header-sticky-box-shadow-mobile); + border-bottom: var(--kt-app-header-sticky-border-bottom-mobile); + } + + [data-kt-app-header-minimize="on"] & { + @include property( z-index, $app-header-minimize-z-index-mobile); + @include property( backdrop-filter, $app-header-minimize-backdrop-filter-mobile); + + transition: $app-header-base-transition; + background-color: var(--kt-app-header-minimize-bg-color-mobile); + box-shadow: var(--kt-app-header-minimize-box-shadow-mobile); + border-bottom: var(--kt-app-header-minimize-border-bottom-mobile); + } + } + + // Integration + .app-header { + // Toolbar + [data-kt-app-header-fixed-mobile="true"][data-kt-app-toolbar-fixed-mobile="true"] & { + box-shadow: none; + } + + [data-kt-app-header-fixed-mobile="true"][data-kt-app-toolbar-sticky="on"] & { + box-shadow: none; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/mixins/_layout-minimize.scss b/src/_res/assets/sass/core/layout/base/mixins/_layout-minimize.scss new file mode 100644 index 0000000..31b88d0 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/mixins/_layout-minimize.scss @@ -0,0 +1,41 @@ +// +// Hoverable +// + +@mixin app-layout-minimize($class) { + // Desktop mode + @include media-breakpoint-up(lg) { + [data-kt-#{$class}-minimize="on"]:not([data-kt-#{$class}-hoverable="true"]) { + .#{$class} { + @content; + } + } + + [data-kt-#{$class}-minimize="on"][data-kt-#{$class}-hoverable="true"] { + .#{$class} { + &:not(:hover) { + @content; + } + } + } + } +} + +@mixin app-layout-minimize-mobile($class) { + // Tablet & mobile modes + @include media-breakpoint-down(lg) { + [data-kt-#{$class}-minimize-mobile="on"]:not[data-kt-#{$class}-hoverable-mobile="true"] { + .#{$class} { + @content; + } + } + + [data-kt-#{$class}-minimize-mobile="on"][data-kt-#{$class}-hoverable-mobile="true"] { + .#{$class} { + &:not(:hover) { + @content; + } + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/mixins/_layout-transition.scss b/src/_res/assets/sass/core/layout/base/mixins/_layout-transition.scss new file mode 100644 index 0000000..4e0a84d --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/mixins/_layout-transition.scss @@ -0,0 +1,7 @@ +// +// Layout Transition Mixin +// + +@mixin app-layout-transition($properties: all) { + transition: $properties $app-general-transition-duration $app-general-transition-timing !important; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-panel.scss b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-panel.scss new file mode 100644 index 0000000..9f2735b --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-panel.scss @@ -0,0 +1,283 @@ +// +// sidebar +// + +// General mode +.app-sidebar-panel { + transition: $app-sidebar-panel-base-transition; +} + +// Utilities +.app-sidebar-panel-minimize-d-flex, +.app-sidebar-panel-sticky-d-flex, +.app-sidebar-panel-collapse-d-flex, +.app-sidebar-panel-minimize-mobile-d-flex, +.app-sidebar-panel-collapse-mobile-d-flex { + display: none; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-sidebar-panel { + display: flex; + flex-shrink: 0; + width: var(--kt-app-sidebar-panel-width); + background-color: var(--kt-app-sidebar-panel-base-bg-color); + box-shadow: var(--kt-app-sidebar-panel-base-box-shadow); + border-left: var(--kt-app-sidebar-panel-base-border-start); + border-right: var(--kt-app-sidebar-panel-base-border-end); + + @include property( z-index, $app-sidebar-panel-base-z-index); + @include property( margin-left, $app-sidebar-panel-base-gap-start); + @include property( margin-right, $app-sidebar-panel-base-gap-end); + @include property( margin-top, $app-sidebar-panel-base-gap-top); + @include property( margin-bottom, $app-sidebar-panel-base-gap-bottom); + } + + // Vars + :root { + --kt-app-sidebar-panel-width: #{$app-sidebar-panel-base-width}; + --kt-app-sidebar-panel-width-actual: #{$app-sidebar-panel-base-width}; + + --kt-app-sidebar-panel-gap-start: #{$app-sidebar-panel-base-gap-start}; + --kt-app-sidebar-panel-gap-end: #{$app-sidebar-panel-base-gap-end}; + --kt-app-sidebar-panel-gap-top: #{$app-sidebar-panel-base-gap-top}; + --kt-app-sidebar-panel-gap-bottom: #{$app-sidebar-panel-base-gap-bottom}; + } + + [data-kt-app-sidebar-panel-minimize="on"] { + --kt-app-sidebar-panel-width: #{$app-sidebar-panel-minimize-width}; + + --kt-app-sidebar-panel-gap-start: #{$app-sidebar-panel-minimize-gap-start}; + --kt-app-sidebar-panel-gap-end: #{$app-sidebar-panel-minimize-gap-end}; + --kt-app-sidebar-panel-gap-top: #{$app-sidebar-panel-minimize-gap-top}; + --kt-app-sidebar-panel-gap-bottom: #{$app-sidebar-panel-minimize-gap-bottom}; + } + + [data-kt-app-sidebar-panel-sticky="on"] { + --kt-app-sidebar-panel-width: #{$app-sidebar-panel-sticky-width}; + + --kt-app-sidebar-panel-gap-start: #{$app-sidebar-panel-sticky-gap-start}; + --kt-app-sidebar-panel-gap-end: #{$app-sidebar-panel-sticky-gap-end}; + --kt-app-sidebar-panel-gap-top: #{$app-sidebar-panel-sticky-gap-top}; + --kt-app-sidebar-panel-gap-bottom: #{$app-sidebar-panel-sticky-gap-bottom}; + } + + [data-kt-app-sidebar-panel-collapse="on"] { + --kt-app-sidebar-panel-width-actual: #{$app-sidebar-panel-base-width}; + --kt-app-sidebar-panel-width: 0px; + } + + // States + .app-sidebar-panel { + [data-kt-app-sidebar-panel-static="true"] & { + position: relative; + } + + [data-kt-app-sidebar-panel-offcanvas="true"] & { + display: none; + } + + [data-kt-app-sidebar-panel-fixed="true"] & { + @include property( z-index, $app-sidebar-panel-fixed-z-index); + position: fixed; + left: calc(var(--kt-app-sidebar-width) + var(--kt-app-sidebar-gap-start, 0px) + var(--kt-app-sidebar-gap-end, 0px)); + top: 0; + bottom: 0; + } + + [data-kt-app-sidebar-panel-sticky="on"] & { + position: fixed; + left: calc(var(--kt-app-sidebar-width) + var(--kt-app-sidebar-gap-start, 0px) + var(--kt-app-sidebar-gap-end, 0px)); + top: 0; + bottom: 0; + transition: $app-sidebar-panel-base-transition; + + box-shadow: var(--kt-app-sidebar-panel-sticky-box-shadow); + border-left: var(--kt-app-sidebar-panel-sticky-border-start); + border-right: var(--kt-app-sidebar-panel-sticky-border-end); + + @include property( z-index, $app-sidebar-panel-sticky-z-index); + @include property( margin-left, $app-sidebar-panel-sticky-gap-start); + @include property( margin-right, $app-sidebar-panel-sticky-gap-end); + @include property( margin-top, $app-sidebar-panel-sticky-gap-top); + @include property( margin-bottom, $app-sidebar-panel-sticky-gap-bottom); + } + + [data-kt-app-sidebar-panel-minimize="on"] & { + transition: $app-sidebar-panel-base-transition; + background-color: var(--kt-app-sidebar-panel-minimize-bg-color); + box-shadow: var(--kt-app-sidebar-panel-minimize-box-shadow); + border-left: var(--kt-app-sidebar-panel-minimize-border-start); + border-right: var(--kt-app-sidebar-panel-minimize-border-end); + + + @include property( margin-left, $app-sidebar-panel-minimize-gap-start); + @include property( margin-right, $app-sidebar-panel-minimize-gap-end); + @include property( margin-top, $app-sidebar-panel-minimize-gap-top); + @include property( margin-bottom, $app-sidebar-panel-minimize-gap-bottom); + } + + [data-kt-app-sidebar-panel-hoverable="true"] & { + .app-sidebar-panel-hoverable { + width: var(--kt-app-sidebar-panel-width-actual); + } + } + + [data-kt-app-sidebar-panel-hoverable="true"][data-kt-app-sidebar-panel-minimize="on"] &:hover:not(.animating) { + transition: $app-sidebar-panel-base-transition; + width: var(--kt-app-sidebar-panel-width-actual); + box-shadow: var(--kt-app-sidebar-panel-minimize-hover-box-shadow); + } + + [data-kt-app-sidebar-panel-collapse="on"] & { + transition: $app-sidebar-panel-base-transition; + width: var(--kt-app-sidebar-panel-width-actual); + margin-left: calc( -1 * (var(--kt-app-sidebar-panel-width-actual) + var(--kt-app-sidebar-gap-start, 0px) + var(--kt-app-sidebar-gap-end, 0px))); + } + } + + // Integration + .app-sidebar-panel { + // Header + [data-kt-app-sidebar-panel-fixed="true"][data-kt-app-header-fixed="true"]:not([data-kt-app-sidebar-panel-push-header="true"]) & { + top: var(--kt-app-header-height); + } + + // Toolbar + [data-kt-app-sidebar-panel-fixed="true"][data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"]:not([data-kt-app-sidebar-panel-push-toolbar="true"]) & { + top: calc(var(--kt-app-header-height) + var(--kt-app-toolbar-height, 0)); + } + } + + // Utilities + [data-kt-app-sidebar-panel-minimize="on"] { + .app-sidebar-panel-minimize-d-none { + display: none !important; + } + + .app-sidebar-panel-minimize-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-panel-sticky="on"] { + .app-sidebar-panel-sticky-d-none { + display: none !important; + } + + .app-sidebar-panel-sticky-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-panel-collapse="on"] { + .app-sidebar-panel-collapse-d-none { + display: none !important; + } + + .app-sidebar-panel-collapse-d-flex { + display: flex !important; + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-sidebar-panel { + display: none; + width: var(--kt-app-sidebar-panel-width); + + background-color: var(--kt-app-sidebar-panel-base-bg-color-mobile); + box-shadow: var(--kt-app-sidebar-panel-base-box-shadow-mobile); + border-left: var(--kt-app-sidebar-panel-base-border-start-mobile); + border-right: var(--kt-app-sidebar-panel-base-border-end-mobile); + + @include property( z-index, $app-sidebar-panel-base-z-index-mobile); + @include property( margin-left, $app-sidebar-panel-base-gap-start-mobile); + @include property( margin-right, $app-sidebar-panel-base-gap-end-mobile); + @include property( margin-top, $app-sidebar-panel-base-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-panel-base-gap-bottom-mobile); + } + + // Vars + :root { + --kt-app-sidebar-panel-gap-start: #{$app-sidebar-panel-base-gap-start-mobile}; + --kt-app-sidebar-panel-gap-end: #{$app-sidebar-panel-base-gap-end-mobile}; + --kt-app-sidebar-panel-gap-top: #{$app-sidebar-panel-base-gap-top-mobile}; + --kt-app-sidebar-panel-gap-bottom: #{$app-sidebar-panel-base-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-panel-minimize-mobile="on"] { + --kt-app-sidebar-panel-width: #{$app-sidebar-panel-minimize-width-mobile}; + + --kt-app-sidebar-panel-gap-start: #{$app-sidebar-panel-minimize-gap-start-mobile}; + --kt-app-sidebar-panel-gap-end: #{$app-sidebar-panel-minimize-gap-end-mobile}; + --kt-app-sidebar-panel-gap-top: #{$app-sidebar-panel-minimize-gap-top-mobile}; + --kt-app-sidebar-panel-gap-bottom: #{$app-sidebar-panel-minimize-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-panel-collapse-mobile="on"] { + --kt-app-sidebar-panel-width-actual: #{$app-sidebar-panel-base-width-mobile}; + --kt-app-sidebar-panel-width: 0px; + } + + // States + .app-sidebar-panel { + [data-kt-app-sidebar-panel-minimize-mobile="on"] & { + transition: $app-sidebar-panel-base-transition; + + background-color: var(--kt-app-sidebar-panel-minimize-bg-color-mobile); + box-shadow: var(--kt-app-sidebar-panel-minimize-box-shadow-mobile); + border-left: var(--kt-app-sidebar-panel-minimize-border-start-mobile); + border-right: var(--kt-app-sidebar-panel-minimize-border-end-mobile); + + @include property( margin-left, $app-sidebar-panel-minimize-gap-start-mobile); + @include property( margin-right, $app-sidebar-panel-minimize-gap-end-mobile); + @include property( margin-top, $app-sidebar-panel-minimize-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-panel-minimize-gap-bottom-mobile); + } + + [data-kt-app-sidebar-panel-hoverable-mobile="true"] & { + .app-sidebar-panel-hoverable { + width: var(--kt-app-sidebar-panel-width-actual); + } + } + + [data-kt-app-sidebar-panel-hoverable-mobile="true"][data-kt-app-sidebar-panel-minimize-mobile="on"] &:hover:not(.animating) { + transition: $app-sidebar-panel-base-transition; + width: var(--kt-app-sidebar-panel-width-actual); + + box-shadow: var(--kt-app-sidebar-panel-minimize-hover-box-shadow-mobile); + } + + [data-kt-app-sidebar-panel-collapse-mobile="on"] & { + transition: $app-sidebar-panel-base-transition; + width: var(--kt-app-sidebar-panel-width-actual); + margin-left: calc( -1 * var(--kt-app-sidebar-panel-width-actual)); + } + } + + // Utilities + [data-kt-app-sidebar-panel-minimize-mobile="on"] { + .app-sidebar-panel-minimize-mobile-d-none { + display: none !important; + } + + .app-sidebar-panel-minimize-mobile-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-panel-collapse-mobile="on"] { + .app-sidebar-panel-collapse-mobile-d-none { + display: none !important; + } + + .app-sidebar-panel-collapse-mobile-d-flex { + display: flex !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-primary.scss b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-primary.scss new file mode 100644 index 0000000..9db9167 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-primary.scss @@ -0,0 +1,236 @@ +// +// sidebar Primary +// + +// General mode +.app-sidebar-primary { + transition: $app-sidebar-primary-base-transition; + position: relative; + flex-shrink: 0; +} + +// Utilities +.app-sidebar-primary-collapse-d-flex, +.app-sidebar-primary-minimize-d-flex, +.app-sidebar-primary-collapse-mobile-d-flex, +.app-sidebar-primary-minimize-mobile-d-flex { + display: none; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-sidebar-primary { + background-color: var(--kt-app-sidebar-primary-base-bg-color); + box-shadow: var(--kt-app-sidebar-primary-base-box-shadow); + border-left: var(--kt-app-sidebar-primary-base-border-start); + border-right: var(--kt-app-sidebar-primary-base-border-end); + + @include property( z-index, $app-sidebar-primary-base-z-index); + @include property( margin-left, $app-sidebar-primary-base-gap-start); + @include property( margin-right, $app-sidebar-primary-base-gap-end); + @include property( margin-top, $app-sidebar-primary-base-gap-top); + @include property( margin-bottom, $app-sidebar-primary-base-gap-bottom); + } + + // Vars + :root { + --kt-app-sidebar-primary-width-actual: #{$app-sidebar-primary-base-width}; + } + + [data-kt-app-sidebar-stacked="true"] { + --kt-app-sidebar-primary-width: #{$app-sidebar-primary-base-width}; + + --kt-app-sidebar-primary-gap-start: #{$app-sidebar-primary-base-gap-start}; + --kt-app-sidebar-primary-gap-end: #{$app-sidebar-primary-base-gap-end}; + --kt-app-sidebar-primary-gap-top: #{$app-sidebar-primary-base-gap-top}; + --kt-app-sidebar-primary-gap-bottom: #{$app-sidebar-primary-base-gap-bottom}; + } + + [data-kt-app-sidebar-primary-minimize="on"] { + --kt-app-sidebar-primary-width: #{$app-sidebar-primary-minimize-width}; + + --kt-app-sidebar-primary-gap-start: #{$app-sidebar-primary-minimize-gap-start}; + --kt-app-sidebar-primary-gap-end: #{$app-sidebar-primary-minimize-gap-end}; + --kt-app-sidebar-primary-gap-top: #{$app-sidebar-primary-minimize-gap-top}; + --kt-app-sidebar-primary-gap-bottom: #{$app-sidebar-primary-minimize-gap-bottom}; + } + + [data-kt-app-sidebar-primary-collapse="on"] { + --kt-app-sidebar-primary-width: 0px; + } + + // States + .app-sidebar-primary { + width: var(--kt-app-sidebar-primary-width); + + [data-kt-app-sidebar-primary-collapse="on"] & { + transition: $app-sidebar-primary-base-transition; + width: var(--kt-app-sidebar-primary-width-actual); + margin-left: calc( -1 * var(--kt-app-sidebar-primary-width-actual)); + } + + [data-kt-app-sidebar-primary-minimize="on"] & { + transition: $app-sidebar-primary-base-transition; + + background-color: var(--kt-app-sidebar-primary-minimize-bg-color); + box-shadow: var(--kt-app-sidebar-primary-minimize-box-shadow); + border-left: var(--kt-app-sidebar-primary-minimize-border-start); + border-right: var(--kt-app-sidebar-primary-minimize-border-end); + + @include property( margin-left, $app-sidebar-primary-minimize-gap-start); + @include property( margin-right, $app-sidebar-primary-minimize-gap-end); + @include property( margin-top, $app-sidebar-primary-minimize-gap-top); + @include property( margin-bottom, $app-sidebar-primary-minimize-gap-bottom); + } + + [data-kt-app-sidebar-primary-hoverable="true"] & { + .app-sidebar-primary-hoverable { + width: var(--kt-app-sidebar-primary-width-actual); + } + } + + // Hover minimized + [data-kt-app-sidebar-primary-hoverable="true"][data-kt-app-sidebar-primary-minimize="on"] &:hover:not(.animating) { + transition: $app-sidebar-primary-base-transition; + width: var(--kt-app-sidebar-primary-width-actual); + box-shadow: var(--kt-app-sidebar-primary-minimize-hover-box-shadow); + } + } + + // Integration + .app-sidebar-primary { + // Header + [data-kt-app-sidebar-fixed="true"][data-kt-app-header-fixed="true"][data-kt-app-sidebar-primary-below-header="true"] & { + top: var(--kt-app-header-height); + } + + // Toolbar + [data-kt-app-sidebar-fixed="true"][data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"][data-kt-app-sidebar-primary-below-toolbar="true"] & { + top: calc(var(--kt-app-header-height) + var(--kt-app-toolbar-height, 0)); + } + } + + // Utilities + [data-kt-app-sidebar-primary-minimize="on"] { + .app-sidebar-primary-minimize-d-none { + display: none !important; + } + + .app-sidebar-primary-minimize-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-primary-collapse="on"] { + .app-sidebar-primary-collapse-d-none { + display: none !important; + } + + .app-sidebar-primary-collapse-d-flex { + display: flex !important; + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-sidebar-primary { + @include property( z-index, $app-sidebar-primary-base-z-index-mobile); + + background-color: var(--kt-app-sidebar-primary-base-bg-color-mobile); + box-shadow: var(--kt-app-sidebar-primary-base-box-shadow-mobile); + border-left: var(--kt-app-sidebar-primary-base-border-start-mobile); + border-right: var(--kt-app-sidebar-primary-base-border-end-mobile); + + @include property( margin-left, $app-sidebar-primary-base-gap-start-mobile); + @include property( margin-right, $app-sidebar-primary-base-gap-end-mobile); + @include property( margin-top, $app-sidebar-primary-base-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-primary-base-gap-bottom-mobile); + } + + // Vars + :root { + --kt-app-sidebar-primary-width-actual: #{$app-sidebar-primary-base-width-mobile}; + } + + [data-kt-app-sidebar-stacked="true"] { + --kt-app-sidebar-primary-width: #{$app-sidebar-primary-base-width-mobile}; + + --kt-app-sidebar-primary-gap-start: #{$app-sidebar-primary-base-gap-start-mobile}; + --kt-app-sidebar-primary-gap-end: #{$app-sidebar-primary-base-gap-end-mobile}; + --kt-app-sidebar-primary-gap-top: #{$app-sidebar-primary-base-gap-top-mobile}; + --kt-app-sidebar-primary-gap-bottom: #{$app-sidebar-primary-base-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-primary-minimize-mobile="on"] { + --kt-app-sidebar-primary-width: #{$app-sidebar-primary-minimize-width-mobile}; + + --kt-app-sidebar-primary-gap-start: #{$app-sidebar-primary-minimize-gap-start-mobile}; + --kt-app-sidebar-primary-gap-end: #{$app-sidebar-primary-minimize-gap-end-mobile}; + --kt-app-sidebar-primary-gap-top: #{$app-sidebar-primary-minimize-gap-top-mobile}; + --kt-app-sidebar-primary-gap-bottom: #{$app-sidebar-primary-minimize-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-primary-collapse-mobile="on"] { + --kt-app-sidebar-primary-width: 0px; + } + + // States + .app-sidebar-primary { + width: var(--kt-app-sidebar-primary-width); + + [data-kt-app-sidebar-primary-collapse-mobile="on"] & { + transition: $app-sidebar-primary-base-transition; + width: var(--kt-app-sidebar-primary-width-actual); + margin-left: calc( -1 * var(--kt-app-sidebar-primary-width-actual)); + } + + [data-kt-app-sidebar-primary-minimize-mobile="on"] & { + transition: $app-sidebar-primary-base-transition; + background-color: var(--kt-app-sidebar-primary-minimize-bg-color-mobile); + box-shadow: var(--kt-app-sidebar-primary-base-box-shadow-mobile); + border-left: var(--kt-app-sidebar-primary-minimize-border-start-mobile); + border-left: var(--kt-app-sidebar-primary-minimize-border-end-mobile); + + @include property( margin-left, $app-sidebar-primary-minimize-gap-start-mobile); + @include property( margin-right, $app-sidebar-primary-minimize-gap-end-mobile); + @include property( margin-top, $app-sidebar-primary-minimize-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-primary-minimize-gap-bottom-mobile); + } + + [data-kt-app-sidebar-primary-hoverable-mobile="true"] & { + .app-sidebar-primary-hoverable { + width: var(--kt-app-sidebar-primary-width-actual); + } + } + + [data-kt-app-sidebar-primary-hoverable-mobile="true"][data-kt-app-sidebar-primary-minimize-mobile="on"] &:hover:not(.animating) { + transition: $app-sidebar-primary-base-transition; + width: var(--kt-app-sidebar-primary-width-actual); + box-shadow: var(--kt-app-sidebar-primary-minimize-hover-box-shadow-mobile); + } + } + + // Utilities + [data-kt-app-sidebar-primary-minimize-mobile="on"] { + .app-sidebar-primary-minimize-mobile-d-none { + display: none !important; + } + + .app-sidebar-primary-minimize-mobile-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-primary-collapse-mobile="on"] { + .app-sidebar-primary-collapse-mobile-d-none { + display: none !important; + } + + .app-sidebar-primary-collapse-mobile-d-flex { + display: flex !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-secondary.scss b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-secondary.scss new file mode 100644 index 0000000..0641268 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar-secondary.scss @@ -0,0 +1,282 @@ +// +// sidebar Secondary +// + +// General mode +.app-sidebar-secondary { + transition: $app-sidebar-secondary-base-transition; + position: relative; + flex-shrink: 0; +} + +// Utilities +.app-sidebar-secondary-collapse-d-flex, +.app-sidebar-secondary-minimize-d-flex, +.app-sidebar-secondary-collapse-mobile-d-flex, +.app-sidebar-secondary-minimize-mobile-d-flex { + display: none; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-sidebar-secondary { + @include property( z-index, $app-sidebar-secondary-base-z-index); + + background-color: var(--kt-app-sidebar-secondary-base-bg-color); + box-shadow: var(--kt-app-sidebar-secondary-base-box-shadow); + border-left: var(--kt-app-sidebar-secondary-base-border-start); + border-right: var(--kt-app-sidebar-secondary-base-border-end); + + @include property( margin-left, $app-sidebar-secondary-base-gap-start-mobile); + @include property( margin-right, $app-sidebar-secondary-base-gap-end-mobile); + @include property( margin-top, $app-sidebar-secondary-base-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-secondary-base-gap-bottom-mobile); + } + + // Vars + :root { + --kt-app-sidebar-secondary-width-actual: calc( + #{$app-sidebar-base-width} - + #{$app-sidebar-primary-base-width} - + #{$app-sidebar-primary-base-gap-start} - + #{$app-sidebar-primary-base-gap-end} - + #{$app-sidebar-secondary-base-gap-start} - + #{$app-sidebar-secondary-base-gap-end} + ); + } + + [data-kt-app-sidebar-stacked="true"] { + --kt-app-sidebar-secondary-width: calc( + #{$app-sidebar-base-width} - + #{$app-sidebar-primary-base-width} - + #{$app-sidebar-primary-base-gap-start} - + #{$app-sidebar-primary-base-gap-end} - + #{$app-sidebar-secondary-base-gap-start} - + #{$app-sidebar-secondary-base-gap-end} + ); + + --kt-app-sidebar-secondary-gap-start: #{$app-sidebar-secondary-base-gap-start}; + --kt-app-sidebar-secondary-gap-end: #{$app-sidebar-secondary-base-gap-end}; + --kt-app-sidebar-secondary-gap-top: #{$app-sidebar-secondary-base-gap-top}; + --kt-app-sidebar-secondary-gap-bottom: #{$app-sidebar-secondary-base-gap-bottom}; + } + + [data-kt-app-sidebar-secondary-minimize="on"] { + --kt-app-sidebar-secondary-width: #{$app-sidebar-secondary-minimize-width}; + + --kt-app-sidebar-secondary-gap-start: #{$app-sidebar-secondary-minimize-gap-start}; + --kt-app-sidebar-secondary-gap-end: #{$app-sidebar-secondary-minimize-gap-end}; + --kt-app-sidebar-secondary-gap-top: #{$app-sidebar-secondary-minimize-gap-top}; + --kt-app-sidebar-secondary-gap-bottom: #{$app-sidebar-secondary-minimize-gap-bottom}; + } + + [data-kt-app-sidebar-secondary-collapse="on"] { + --kt-app-sidebar-secondary-width-actual: calc( + #{$app-sidebar-base-width} - + #{$app-sidebar-primary-base-width} - + #{$app-sidebar-primary-base-gap-start} - + #{$app-sidebar-primary-base-gap-end} - + #{$app-sidebar-secondary-base-gap-start} - + #{$app-sidebar-secondary-base-gap-end} + ); + + --kt-app-sidebar-secondary-width: 0px; + } + + // States + .app-sidebar-secondary { + width: var(--kt-app-sidebar-secondary-width); + + [data-kt-app-sidebar-secondary-collapse="on"] & { + transition: $app-sidebar-secondary-base-transition; + width: var(--kt-app-sidebar-secondary-width-actual); + margin-left: calc( -1 * var(--kt-app-sidebar-secondary-width-actual)); + } + + [data-kt-app-sidebar-secondary-minimize="on"] & { + transition: $app-sidebar-secondary-base-transition; + + background-color: var(--kt-app-sidebar-secondary-minimize-bg-color); + box-shadow: var(--kt-app-sidebar-secondary-minimize-box-shadow); + border-left: var(--kt-app-sidebar-secondary-minimize-border-start); + border-right: var(--kt-app-sidebar-secondary-minimize-border-end); + + @include property( margin-left, $app-sidebar-secondary-minimize-gap-start-mobile); + @include property( margin-right, $app-sidebar-secondary-minimize-gap-end-mobile); + @include property( margin-top, $app-sidebar-secondary-minimize-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-secondary-minimize-gap-bottom-mobile); + } + + [data-kt-app-sidebar-secondary-hoverable="true"] & { + .app-sidebar-secondary-hoverable { + width: var(--kt-app-sidebar-secondary-width-actual); + } + } + + [data-kt-app-sidebar-secondary-hoverable="true"][data-kt-app-sidebar-secondary-minimize="on"] &:hover:not(.animating) { + transition: $app-sidebar-secondary-base-transition; + width: var(--kt-app-sidebar-secondary-width-actual); + box-shadow: var(--kt-app-sidebar-secondary-minimize-hover-box-shadow); + } + } + + // Integration + .app-sidebar-secondary { + // Header + [data-kt-app-sidebar-fixed="true"][data-kt-app-header-fixed="true"][data-kt-app-sidebar-secondary-below-header="true"] & { + top: var(--kt-app-header-height); + } + + // Toolbar + [data-kt-app-sidebar-fixed="true"][data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"][data-kt-app-sidebar-secondary-below-toolbar="true"] & { + top: calc(var(--kt-app-header-height) + var(--kt-app-toolbar-height, 0)); + } + } + + // Utilities + [data-kt-app-sidebar-secondary-minimize="on"] { + .app-sidebar-secondary-minimize-d-none { + display: none !important; + } + + .app-sidebar-secondary-minimize-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-secondary-collapse="on"] { + .app-sidebar-secondary-collapse-d-none { + display: none !important; + } + + .app-sidebar-secondary-collapse-d-flex { + display: flex !important; + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-sidebar-secondary { + @include property( z-index, $app-sidebar-secondary-base-z-index-mobile); + + background-color: var(--kt-app-sidebar-secondary-base-bg-color-mobile); + box-shadow: var(--kt-app-sidebar-secondary-base-box-shadow-mobile); + border-left: var(--kt-app-sidebar-secondary-base-border-start-mobile); + border-right: var(--kt-app-sidebar-secondary-base-border-end-mobile); + + @include property( margin-left, $app-sidebar-secondary-base-gap-start-mobile); + @include property( margin-right, $app-sidebar-secondary-base-gap-end-mobile); + @include property( margin-top, $app-sidebar-secondary-base-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-secondary-base-gap-bottom-mobile); + } + + // Vars + :root { + --kt-app-sidebar-secondary-width-actual: calc( + #{$app-sidebar-base-width-mobile} - + #{$app-sidebar-primary-base-width-mobile} - + #{$app-sidebar-primary-base-gap-start-mobile} - + #{$app-sidebar-primary-base-gap-end-mobile} - + #{$app-sidebar-secondary-base-gap-start-mobile} - + #{$app-sidebar-secondary-base-gap-end-mobile} + ); + } + + [data-kt-app-sidebar-stacked="true"] { + --kt-app-sidebar-secondary-width: calc( + #{$app-sidebar-base-width-mobile} - + #{$app-sidebar-primary-base-width-mobile} - + #{$app-sidebar-primary-base-gap-start-mobile} - + #{$app-sidebar-primary-base-gap-end-mobile} - + #{$app-sidebar-secondary-base-gap-start-mobile} - + #{$app-sidebar-secondary-base-gap-end-mobile} + ); + + --kt-app-sidebar-secondary-gap-start: #{$app-sidebar-secondary-base-gap-start-mobile}; + --kt-app-sidebar-secondary-gap-end: #{$app-sidebar-secondary-base-gap-end-mobile}; + --kt-app-sidebar-secondary-gap-top: #{$app-sidebar-secondary-base-gap-top-mobile}; + --kt-app-sidebar-secondary-gap-bottom: #{$app-sidebar-secondary-base-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-secondary-minimize-mobile="on"] { + --kt-app-sidebar-secondary-width: #{$app-sidebar-secondary-minimize-width-mobile}; + + --kt-app-sidebar-secondary-gap-start: #{$app-sidebar-secondary-minimize-gap-start-mobile}; + --kt-app-sidebar-secondary-gap-end: #{$app-sidebar-secondary-minimize-gap-end-mobile}; + --kt-app-sidebar-secondary-gap-top: #{$app-sidebar-secondary-minimize-gap-top-mobile}; + --kt-app-sidebar-secondary-gap-bottom: #{$app-sidebar-secondary-minimize-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-secondary-collapse-mobile="on"] { + --kt-app-sidebar-secondary-width-actual: calc( + #{$app-sidebar-base-width-mobile} - + #{$app-sidebar-primary-base-width-mobile} - + #{$app-sidebar-primary-base-gap-start-mobile} - + #{$app-sidebar-primary-base-gap-end-mobile} - + #{$app-sidebar-secondary-base-gap-start-mobile} - + #{$app-sidebar-secondary-base-gap-end-mobile} + ); + + --kt-app-sidebar-secondary-width: 0px; + } + + // States + .app-sidebar-secondary { + width: var(--kt-app-sidebar-secondary-width); + + [data-kt-app-sidebar-secondary-collapse-mobile="on"] & { + transition: $app-sidebar-secondary-base-transition; + width: var(--kt-app-sidebar-secondary-width-actual); + margin-left: calc( -1 * var(--kt-app-sidebar-secondary-width-actual)); + } + + [data-kt-app-sidebar-secondary-minimize-mobile="on"] & { + transition: $app-sidebar-secondary-base-transition; + background-color: var(--kt-app-sidebar-secondary-minimize-bg-color-mobile); + box-shadow: var(--kt-app-sidebar-secondary-minimize-box-shadow-mobile); + border-left: var(--kt-app-sidebar-secondary-minimize-border-start-mobile); + border-right: var(--kt-app-sidebar-secondary-minimize-border-end-mobile); + + @include property( margin-left, $app-sidebar-secondary-minimize-gap-start-mobile); + @include property( margin-right, $app-sidebar-secondary-minimize-gap-end-mobile); + @include property( margin-top, $app-sidebar-secondary-minimize-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-secondary-minimize-gap-bottom-mobile); + } + + [data-kt-app-sidebar-secondary-hoverable-mobile="true"] & { + .app-sidebar-secondary-hoverable { + width: var(--kt-app-sidebar-secondary-width-actual); + } + } + + [data-kt-app-sidebar-secondary-hoverable-mobile="true"][data-kt-app-sidebar-secondary-minimize-mobile="on"] &:hover:not(.animating) { + transition: $app-sidebar-secondary-base-transition; + width: var(--kt-app-sidebar-secondary-width-actual); + box-shadow: var(--kt-app-sidebar-secondary-minimize-hover-box-shadow-mobile); + } + } + + // Utilities + [data-kt-app-sidebar-secondary-minimize-mobile="on"] { + .app-sidebar-secondary-minimize-mobile-d-none { + display: none !important; + } + + .app-sidebar-secondary-minimize-mobile-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-secondary-collapse="on"] { + .app-sidebar-secondary-collapse-mobile-d-none { + display: none !important; + } + + .app-sidebar-secondary-collapse-mobile-d-flex { + display: flex !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/layout/base/sidebar/_sidebar.scss b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar.scss new file mode 100644 index 0000000..097b6b3 --- /dev/null +++ b/src/_res/assets/sass/core/layout/base/sidebar/_sidebar.scss @@ -0,0 +1,296 @@ +// +// sidebar +// + +// General mode +.app-sidebar { + transition: $app-sidebar-base-transition; +} + +// Utilities +.app-sidebar-minimize-d-flex, +.app-sidebar-sticky-d-flex, +.app-sidebar-collapse-d-flex, +.app-sidebar-minimize-mobile-d-flex, +.app-sidebar-collapse-mobile-d-flex { + display: none; +} + +// Desktop mode +@include media-breakpoint-up(lg) { + // Base + .app-sidebar { + display: flex; + flex-shrink: 0; + width: var(--kt-app-sidebar-width); + + background-color: var(--kt-app-sidebar-base-bg-color); + box-shadow: var(--kt-app-sidebar-base-box-shadow); + border-left: var(--kt-app-sidebar-base-border-start); + border-right: var(--kt-app-sidebar-base-border-end); + + @include property( z-index, $app-sidebar-base-z-index); + @include property( margin-left, $app-sidebar-base-gap-start); + @include property( margin-right, $app-sidebar-base-gap-end); + @include property( margin-top, $app-sidebar-base-gap-top); + @include property( margin-bottom, $app-sidebar-base-gap-bottom); + } + + // Vars + :root { + --kt-app-sidebar-width: #{$app-sidebar-base-width}; + --kt-app-sidebar-width-actual: #{$app-sidebar-base-width}; + + --kt-app-sidebar-gap-start: #{$app-sidebar-base-gap-start}; + --kt-app-sidebar-gap-end: #{$app-sidebar-base-gap-end}; + --kt-app-sidebar-gap-top: #{$app-sidebar-base-gap-top}; + --kt-app-sidebar-gap-bottom: #{$app-sidebar-base-gap-bottom}; + } + + [data-kt-app-sidebar-stacked="true"] { + --kt-app-sidebar-width: calc(var(--kt-app-sidebar-primary-width) + var(--kt-app-sidebar-secondary-width)); + } + + [data-kt-app-sidebar-minimize="on"] { + --kt-app-sidebar-width: #{$app-sidebar-minimize-width}; + + --kt-app-sidebar-gap-start: #{$app-sidebar-minimize-gap-start}; + --kt-app-sidebar-gap-end: #{$app-sidebar-minimize-gap-end}; + --kt-app-sidebar-gap-top: #{$app-sidebar-minimize-gap-top}; + --kt-app-sidebar-gap-bottom: #{$app-sidebar-minimize-gap-bottom}; + } + + [data-kt-app-sidebar-sticky="on"] { + --kt-app-sidebar-width: #{$app-sidebar-sticky-width}; + + --kt-app-sidebar-gap-start: #{$app-sidebar-sticky-gap-start}; + --kt-app-sidebar-gap-end: #{$app-sidebar-sticky-gap-end}; + --kt-app-sidebar-gap-top: #{$app-sidebar-sticky-gap-top}; + --kt-app-sidebar-gap-bottom: #{$app-sidebar-sticky-gap-bottom}; + } + + [data-kt-app-sidebar-collapse="on"] { + --kt-app-sidebar-width: 0px; + } + + // States + .app-sidebar { + [data-kt-app-sidebar-static="true"] & { + position: relative; + } + + [data-kt-app-sidebar-offcanvas="true"] & { + display: none; + } + + [data-kt-app-sidebar-fixed="true"] & { + position: fixed; + @include property( z-index, $app-sidebar-fixed-z-index); + @include property( top, $app-sidebar-fixed-top); + @include property( bottom, $app-sidebar-fixed-bottom); + @include property( left, $app-sidebar-fixed-left); + } + + [data-kt-app-sidebar-stacked="true"] & { + align-items: stretch; + } + + [data-kt-app-sidebar-sticky="on"] & { + position: fixed; + transition: $app-sidebar-base-transition; + @include property( top, $app-sidebar-sticky-top); + @include property( bottom, $app-sidebar-sticky-bottom); + @include property( left, $app-sidebar-sticky-left); + @include property( z-index, $app-sidebar-sticky-z-index); + + box-shadow: var(--kt-app-sidebar-sticky-box-shadow); + border-left: var(--kt-app-sidebar-sticky-border-start); + border-right: var(--kt-app-sidebar-sticky-border-end); + + @include property( margin-left, $app-sidebar-sticky-gap-start); + @include property( margin-right, $app-sidebar-sticky-gap-end); + @include property( margin-top, $app-sidebar-sticky-gap-top); + @include property( margin-bottom, $app-sidebar-sticky-gap-bottom); + } + + [data-kt-app-sidebar-minimize="on"] & { + transition: $app-sidebar-base-transition; + + background-color: var(--kt-app-sidebar-minimize-bg-color); + box-shadow: var(--kt-app-sidebar-minimize-box-shadow); + border-left: var(--kt-app-sidebar-minimize-border-start); + border-right: var(--kt-app-sidebar-minimize-border-end); + + @include property( margin-left, $app-sidebar-minimize-gap-start); + @include property( margin-right, $app-sidebar-minimize-gap-end); + @include property( margin-top, $app-sidebar-minimize-gap-top); + @include property( margin-bottom, $app-sidebar-minimize-gap-bottom); + } + + [data-kt-app-sidebar-hoverable="true"] & { + .app-sidebar-wrapper { + width: var(--kt-app-sidebar-width-actual); + } + } + + [data-kt-app-sidebar-hoverable="true"][data-kt-app-sidebar-minimize="on"] &:hover:not(.animating) { + transition: $app-sidebar-base-transition; + width: var(--kt-app-sidebar-width-actual); + @include property( box-shadow, $app-sidebar-minimize-hover-box-shadow); + } + + [data-kt-app-sidebar-collapse="on"] & { + transition: $app-sidebar-base-transition; + width: var(--kt-app-sidebar-width-actual); + margin-left: calc( -1 * var(--kt-app-sidebar-width-actual)); + } + } + + // Utilities + [data-kt-app-sidebar-minimize="on"] { + .app-sidebar-minimize-d-none { + display: none !important; + } + + .app-sidebar-minimize-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-sticky="on"] { + .app-sidebar-sticky-d-none { + display: none !important; + } + + .app-sidebar-sticky-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-collapse="on"] { + .app-sidebar-collapse-d-none { + display: none !important; + } + + .app-sidebar-collapse-d-flex { + display: flex !important; + } + } + + // Integration + .app-sidebar { + // Header + [data-kt-app-sidebar-fixed="true"][data-kt-app-header-fixed="true"]:not([data-kt-app-sidebar-push-header="true"]) & { + top: var(--kt-app-header-height); + } + + // Toolbar + [data-kt-app-sidebar-fixed="true"][data-kt-app-header-fixed="true"][data-kt-app-toolbar-fixed="true"]:not([data-kt-app-sidebar-push-toolbar="true"]) & { + top: calc(var(--kt-app-header-height) + var(--kt-app-toolbar-height, 0px)); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + // Base + .app-sidebar { + display: none; + width: var(--kt-app-sidebar-width); + + background-color: var(--kt-app-sidebar-base-bg-color-mobile); + box-shadow: var(--kt-app-sidebar-base-box-shadow-mobile); + border-left: var(--kt-app-sidebar-base-border-start-mobile); + border-right: var(--kt-app-sidebar-base-border-end-mobile); + + @include property( z-index, $app-sidebar-base-z-index-mobile); + @include property( margin-left, $app-sidebar-base-gap-start-mobile); + @include property( margin-right, $app-sidebar-base-gap-end-mobile); + @include property( margin-top, $app-sidebar-base-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-base-gap-bottom-mobile); + } + + // Vars + :root { + --kt-app-sidebar-width: #{$app-sidebar-base-width-mobile}; + --kt-app-sidebar-width-actual: #{$app-sidebar-base-width-mobile}; + + --kt-app-sidebar-gap-start: #{$app-sidebar-base-gap-start-mobile}; + --kt-app-sidebar-gap-end: #{$app-sidebar-base-gap-end-mobile}; + --kt-app-sidebar-gap-top: #{$app-sidebar-base-gap-top-mobile}; + --kt-app-sidebar-gap-bottom: #{$app-sidebar-base-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-minimize-mobile="on"] { + --kt-app-sidebar-width: #{$app-sidebar-minimize-width-mobile}; + + --kt-app-sidebar-gap-start: #{$app-sidebar-minimize-gap-start-mobile}; + --kt-app-sidebar-gap-end: #{$app-sidebar-minimize-gap-end-mobile}; + --kt-app-sidebar-gap-top: #{$app-sidebar-minimize-gap-top-mobile}; + --kt-app-sidebar-gap-bottom: #{$app-sidebar-minimize-gap-bottom-mobile}; + } + + [data-kt-app-sidebar-collapse-mobile="on"] { + --kt-app-sidebar-width: 0px; + } + + // States + .app-sidebar { + [data-kt-app-sidebar-stacked="true"] & { + align-items: stretch; + } + + [data-kt-app-sidebar-minimize-mobile="on"] & { + transition: $app-sidebar-base-transition; + + background-color: var(--kt-app-sidebar-minimize-bg-color-mobilee); + box-shadow: var(--kt-app-sidebar-minimize-box-shadow-mobile); + border-left: var(--kt-app-sidebar-minimize-border-start-mobile); + border-right: var(--kt-app-sidebar-minimize-border-end-mobile); + + @include property( margin-left, $app-sidebar-minimize-gap-start-mobile); + @include property( margin-right, $app-sidebar-minimize-gap-end-mobile); + @include property( margin-top, $app-sidebar-minimize-gap-top-mobile); + @include property( margin-bottom, $app-sidebar-minimize-gap-bottom-mobile); + } + + [data-kt-app-sidebar-hoverable-mobile="true"] & { + .app-sidebar-wrapper { + width: var(--kt-app-sidebar-width-actual); + } + } + + [data-kt-app-sidebar-hoverable-mobile="true"][data-kt-app-sidebar-minimize-mobile="on"] &:hover:not(.animating) { + transition: $app-sidebar-base-transition; + width: var(--kt-app-sidebar-width-actual); + box-shadow: var(--kt-app-sidebar-minimize-hover-box-shadow-mobile); + } + + [data-kt-app-sidebar-collapse-mobile="on"] & { + transition: $app-sidebar-base-transition; + width: var(--kt-app-sidebar-width-actual); + margin-left: calc( -1 * var(--kt-app-sidebar-width-actual)); + } + } + + // Utilities + [data-kt-app-sidebar-minimize-mobile="on"] { + .app-sidebar-minimize-mobile-d-none { + display: none !important; + } + + .app-sidebar-minimize-mobile-d-flex { + display: flex !important; + } + } + + [data-kt-app-sidebar-collapse-mobile="on"] { + .app-sidebar-collapse-mobile-d-none { + display: none !important; + } + + .app-sidebar-collapse-mobile-d-flex { + display: flex !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_apexcharts.scss b/src/_res/assets/sass/core/vendors/plugins/_apexcharts.scss new file mode 100644 index 0000000..87b14f2 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_apexcharts.scss @@ -0,0 +1,129 @@ +// +// Apexcharts +// + +// Text +.apexcharts-text, +.apexcharts-title-text, +.apexcharts-legend-text { + font-family: $font-family-sans-serif !important; +} + +.apexcharts-title-text { + font-weight: $font-weight-normal; +} + +.apexcharts-pie-label { + font-weight: $font-weight-normal; + font-size: $font-size-sm; +} + +// Dropdown +.apexcharts-toolbar{ + text-align: left !important; +} + +.apexcharts-menu { + background-color: var(--kt-body-bg); + border: 0 !important; + padding: 0.5rem 0 !important; + box-shadow: var(--kt-dropdown-box-shadow); + border-radius: $border-radius !important; + overflow: hidden; + min-width: 10rem !important; + + .apexcharts-menu-item { + padding: $dropdown-item-padding-y $dropdown-item-padding-x; + transition: $transition-base; + + &:hover{ + background-color: var(--kt-hover-bg) !important; + } + } +} + +// Tooltips +.apexcharts-tooltip { + &.apexcharts-theme-light { + @include border-radius($border-radius); + box-shadow: var(--kt-dropdown-box-shadow); + border: 0 !important; + background: var(--kt-body-bg) !important; + color: var(--kt-gray-800); + + .apexcharts-tooltip-title { + background: var(--kt-body-bg) !important; + font-weight: $font-weight-semibold; + color: var(--kt-gray-800); + border-bottom: 1px solid var(--kt-gray-100) !important; + } + } + + .apexcharts-tooltip-title { + padding: 0.5rem 1rem; + } + + .apexcharts-tooltip-series-group { + } +} + +.apexcharts-xaxistooltip { + &.apexcharts-theme-light { + @include border-radius($border-radius !important); + box-shadow: var(--kt-dropdown-box-shadow) !important; + border: 0 !important; + background: var(--kt-dropdown-box-shadow) !important; + color: var(--kt-gray-800); + + &:before { + border-bottom: 0 !important; + } + + &:after { + border-bottom-color: var(--kt-dropdown-box-shadow) !important; + } + } +} + +// Border radius integration +.card-rounded-bottom { + .apexcharts-canvas { + svg { + border-bottom-left-radius: $card-border-radius; + border-bottom-right-radius: $card-border-radius; + } + } +} + +// Border radius options +.rounded { + .apexcharts-canvas { + svg { + border-radius: $border-radius !important; + } + } +} + +.rounded-sm { + .apexcharts-canvas { + svg { + border-radius: $border-radius-sm !important; + } + } +} + +.rounded-lg { + .apexcharts-canvas { + svg { + border-radius: $border-radius-lg !important; + } + } +} + +.rounded-xl { + .apexcharts-canvas { + svg { + border-radius: $border-radius-xl !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_bootstrap-maxlength.scss b/src/_res/assets/sass/core/vendors/plugins/_bootstrap-maxlength.scss new file mode 100644 index 0000000..a450979 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_bootstrap-maxlength.scss @@ -0,0 +1,16 @@ +// +// Bootstrap Maxlength +// + +.bootstrap-maxlength { + z-index: $bootstrap-maxlength-z-index !important; + + // In modal + .modal-open & { + z-index: #{$zindex-modal + 5} !important; + } + + &.badge { + display: inline-flex !important; + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_ckeditor.scss b/src/_res/assets/sass/core/vendors/plugins/_ckeditor.scss new file mode 100644 index 0000000..9d9c4e6 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_ckeditor.scss @@ -0,0 +1,54 @@ +// +// CKEditor +// + + +// Base +.ck-target{ + display: none; +} + +.ck-toolbar{ + @include border-radius($border-radius !important); +} + +.ck-content{ + min-height: 200px; + @include border-radius($border-radius !important); + + &.ck-focused{ + border-color: var(--kt-primary) !important; + box-shadow: none !important; + } +} + +// CKEditor Classic & Document +.ck-editor{ + .ck-toolbar{ + @include border-top-radius($border-radius !important); + @include border-bottom-radius(0 !important); + } + .ck-content{ + @include border-bottom-radius($border-radius !important); + @include border-top-radius(0 !important); + } +} + +// CKEditor Inline / Balloon / Balloon Block +.ck-body { + .ck-balloon-panel{ + .ck-content{ + min-height: 200px; + border-color: transparent !important; + + &.ck-focused{ + border-color: var(--kt-primary) !important; + } + } + + &.ck-toolbar-container, + .ck-toolbar { + @include border-radius($border-radius !important); + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_datatables.scss b/src/_res/assets/sass/core/vendors/plugins/_datatables.scss new file mode 100644 index 0000000..41d0dbc --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_datatables.scss @@ -0,0 +1,233 @@ +// +// DataTables +// + +$toolbar-spacing: 1rem 0; + +// Base +table.dataTable { + width: 100% !important; + margin: 0 !important; + + th { + border-bottom-color: var(--kt-table-border-color); + } +} + +// Toolbar +div.dataTables_wrapper div.dataTables_length { + padding: $toolbar-spacing; +} + +div.dataTables_wrapper div.dataTables_filter { + padding: $toolbar-spacing; +} + +div.dataTables_wrapper div.dataTables_info { + display: flex; + flex-direction: column; + font-weight: $font-weight-semibold; + color: var(--kt-gray-700); + padding: $toolbar-spacing; + + .select-info, + .select-item { + margin-left: 0; + font-size: 0.9rem; + color: var(--kt-text-muted); + } +} + +div.dataTables_length + div.dataTables_info { + margin-left: 1rem; +} + +// Pagination +div.dataTables_wrapper div.dataTables_paginate { + padding: $toolbar-spacing; + margin-left: 0.5rem; + + .pagination { + margin: 0; + } +} + +// Head +table.dataTable>thead>tr> { + td, th { + &:not(.sorting_disabled) { + padding-right: 0; + } + } +} + +// Sorting +table.dataTable > thead { + .sorting { + &:after, + &:before { + display: none !important; + } + } + + .sorting_asc, + .sorting_desc { + vertical-align: middle; + + &:before, + &:after { + position: relative !important; + opacity: 1 !important; + display: inline-block !important; + width: 0.75rem; + height: 0.75rem; + content: " " !important; + //top: 50%; + bottom: auto; + right: auto !important; + left: auto; + margin-left: 0.5rem; + } + + &:before { + display: none !important; + } + } +} + +table.dataTable > thead .sorting_asc:after { + opacity: 1; + @include svg-bg-icon(arrow-top, var(--kt-text-muted)); +} + +table.dataTable > thead .sorting_desc:after { + opacity: 1; + @include svg-bg-icon(arrow-bottom, var(--kt-text-muted)); +} + +// Processing +div.dataTables_wrapper { + .table-responsive { + position: relative; + } + + div.dataTables_processing { + @include border-radius($border-radius); + box-shadow: var(--kt-dropdown-box-shadow); + background-color: var(--kt-tooltip-bg); + color: var(--kt-gray-700); + font-weight: $font-weight-semibold; + margin: 0 !important; + width: auto; + padding: 1rem 2rem !important; + transform: translateX(-50%) translateY(-50%); + + > div { + display: none; + } + } +} + +// Responsive +table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control, +table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control { + $icon-size: 1.35rem; + + &:before { + top: 50%; + left: 0; + height: $icon-size; + width: $icon-size; + line-height: 1.5; + text-indent: -999px !important; + margin-top: -(divide($icon-size, 2)); + margin-right: divide($icon-size, 2); + display: inline-block; + position: relative; + font-size: 1.05rem; + border: 0; + box-shadow: none; + mask-size: 85%; + -webkit-mask-size: 85%; + content: "."; + + :root &, + [data-theme="light"] & { + @include svg-bg-icon(expand, $gray-600); + } + + [data-theme="dark"] & { + @include svg-bg-icon(expand, $gray-600-dark); + } + } +} + +table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td.dtr-control:before, +table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th.dtr-control:before { + @include svg-bg-icon(collapse, $primary); +} + +table.dataTable > tbody > tr.child span.dtr-title { + display: inline-block; + min-width: 100px; + font-weight: $font-weight-semibold; +} + +table.dataTable > tbody > tr.child span.dtr-data { + font-weight: $font-weight-normal; +} + +// Striped +table.dataTable.table-striped > tbody > tr.odd > * { + box-shadow: inset 0 0 0 9999px var(--bs-table-striped-bg); +} + +table.dataTable > tbody > tr.selected > * { + box-shadow: inset 0 0 0 9999px var(--kt-primary); + color: var(--kt-primary-inverse); + + a:not([class="btn"]) { + color: var(--kt-primary-light); + font-weight: $font-weight-semibold; + text-decoration: underline; + text-decoration-style: dotted; + + &:hover { + color: var(--kt-primary-inverse); + } + } +} + +// Scroll +div.dataTables_scrollBody { + border-left: 0 !important; +} + +.dataTables_scroll .dataTables_scrollBody .table { + thead { + line-height: 0; + + .sorting { + &:after, + &:before { + display: none !important; + } + } + } +} + +div.dtfc-right-top-blocker, +div.dtfc-left-top-blocker { + background-color: var(--kt-body-bg); +} + +// Fixed column +table.dataTable thead tr > .dtfc-fixed-left, +table.dataTable thead tr > .dtfc-fixed-right { + background-color: var(--kt-body-bg); +} + +table.dataTable tbody tr > .dtfc-fixed-left, +table.dataTable tbody tr > .dtfc-fixed-right { + background-color: var(--kt-body-bg); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_daterangepicker.scss b/src/_res/assets/sass/core/vendors/plugins/_daterangepicker.scss new file mode 100644 index 0000000..546af4b --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_daterangepicker.scss @@ -0,0 +1,272 @@ +// +// Bootstrap Daterangepicker plugin customization: https://www.daterangepicker.com +// + + +// Base +.daterangepicker { + padding: 0; + margin: 0; + border: 0; + width: auto; + background-color: var(--kt-body-bg); + box-shadow: var(--kt-dropdown-box-shadow); + font-family: $font-family-sans-serif; + z-index: $zindex-dropdown; + @include border-radius($dropdown-border-radius); + + &:after, + &:before { + display: none; + } + + td { + &.off, + &.off.in-range, + &.off.start-date, + &.off.end-date { + background-color: transparent; + } + } + + .modal-open & { + z-index: $zindex-modal + 1; + } + + .calendar-table { + background-color: var(--kt-body-bg); + border: 0; + } + + .ranges { + @include border-radius($dropdown-border-radius); + background-color: var(--kt-body-bg); + position: relative; + overflow: hidden; + + ul { + padding: 1rem 0; + width: $daterangepicker-ranges-list-width; + overflow: auto; + max-height: $daterangepicker-ranges-list-height; + } + + li { + padding: 0.7rem 1.75rem; + font-weight: 500; + font-size: 1rem; + color: var(--kt-gray-600); + transition: $transition-link; + + &:hover { + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + transition: $transition-link; + } + + &.active { + background-color: var(--kt-component-active-bg); + color: var(--kt-component-active-color); + transition: $transition-link; + } + } + } + + &.show-calendar { + .ranges { + @include border-radius(0); + @include border-top-start-radius($dropdown-border-radius); + margin-top: 0; + height: 297px; + } + } + + &.show-ranges { + &.show-calendar { + .ranges { + border-right: 1px solid var(--kt-gray-200); + } + } + + .drp-calendar.left { + border-left: 0; + } + } + + .drp-buttons { + padding: 1rem 1.75rem; + border-top: 1px solid var(--kt-gray-200); + + .btn { + font-size: 1rem; + font-weight: $font-weight-semibold; + padding: 0.5rem 1rem; + } + + .cancelBtn { + @include button-custom-variant( + $color: var(--kt-light-inverse), + $icon-color: var(--kt-light-inverse), + $border-color: var(--kt-light), + $bg-color: var(--kt-light), + $color-active: var(--kt-light-inverse), + $icon-color-active: var(--kt-light-inverse), + $border-color-active: var(--kt-light-active), + $bg-color-active: var(--kt-light-active) + ); + } + } + + .drp-selected { + font-size: 0.9rem; + } + + .drp-calendar { + &.left, + &.right { + padding: 1rem 1rem; + } + + &.left { + border-left: 0 !important; + } + + th, + td { + font-size: 1rem; + font-weight: $font-weight-normal; + width: 33px; + height: 33px; + + &.available:hover { + @include border-radius($border-radius); + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + } + } + + th { + font-weight: $font-weight-semibold; + color: var(--kt-gray-800); + + &.month { + font-weight: $font-weight-semibold; + color: var(--kt-gray-800); + } + + &.next, + &.prev { + span { + border-width: 0 1px 1px 0; + border-color: var(--kt-gray-600); + } + + &.available:hover { + span { + border-color: var(--kt-component-hover-color); + } + } + } + + &.next { + span { + margin-right: 1px; + } + } + + &.prev { + span { + margin-left: 1px; + } + } + } + + td { + color: var(--kt-gray-700); + + &.available.off { + color: var(--kt-gray-400); + } + + &.active { + background-color: var(--kt-component-active-bg) !important; + color: var(--kt-component-active-color) !important; + @include border-radius($border-radius); + + &.start-date { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &.end-date { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + &.start-date.end-date { + @include border-radius($border-radius); + } + } + + &.today, + &.today.active { + background: var(--kt-component-hover-bg) !important; + color: var(--kt-component-hover-color) !important; + @include border-radius($border-radius); + } + + &.in-range.available:not(.active):not(.off):not(.today) { + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + } + + &:hover { + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + } + } + } + + select.ampmselect, + select.minuteselect, + select.hourselect, + select.monthselect, + select.yearselect { + padding-top: 0.35rem; + padding-bottom: 0.35rem; + @include border-radius($border-radius); + background-color: var(--kt-body-bg) !important; + border-color: transparent; + color: var(--kt-input-color); + font-weight: $font-weight-semibold; + outline: 0 !important; + + &:focus { + background-color: var(--kt-gray-100); + } + } +} + +// Tablet mode +@include media-breakpoint-down(md) { + .daterangepicker { + &.show-calendar { + .ranges { + float: none !important; + height: auto !important; + + ul { + width: 100%; + } + } + + .drp-calendar { + float: none !important; + max-width: unset !important; + display: flex; + flex-direction: column; + align-items: center; + } + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_draggable.scss b/src/_res/assets/sass/core/vendors/plugins/_draggable.scss new file mode 100644 index 0000000..f542f34 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_draggable.scss @@ -0,0 +1,28 @@ +// +// Draggable plugin customization: https://shopify.github.io/draggable +// + +.draggable { + transition: opacity 0.3s ease; + outline: none !important; + + &.draggable-mirror { + opacity: 0.8; + transition: opacity 0.3s ease; + border: 2px dashed var(--kt-gray-300) !important; + @include border-radius($border-radius); + } + + &.draggable--original { + opacity: 0 !important; + } + + &.draggable-source--is-dragging.draggable--over { + opacity: 0 !important; + } + + // Handle + .draggable-handle { + cursor: move; + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_dropzone.scss b/src/_res/assets/sass/core/vendors/plugins/_dropzone.scss new file mode 100644 index 0000000..f0b4bb8 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_dropzone.scss @@ -0,0 +1,188 @@ +// +// Dropzone plugin customization: https://www.dropzonejs.com +// + +// Basic +.dropzone { + min-height: auto; + padding: 1.5rem 1.75rem; + text-align: center; + cursor: pointer; + border: 1px dashed var(--kt-primary); + background-color: var(--kt-primary-light); + border-radius: $border-radius !important; + + .dz-message{ + margin: 0; + display: flex; + text-align: left; + } + + .dz-preview { + border-radius: $border-radius !important; + margin: 0.75rem; + + .dz-image { + border-radius: $border-radius !important; + z-index: 1; + } + + &.dz-file-preview { + .dz-image { + background: var(--kt-gray-200); + } + } + } + + .dz-success-mark, + .dz-error-mark { + $size: 40px; + + margin-left: -(divide($size, 2)) !important; + margin-top: -(divide($size, 2)) !important; + + svg { + height: $size !important; + width: $size !important; + } + } + + .dz-remove { + $size: 1.65rem; + display:flex; + justify-content: center; + align-items: center; + height: $size; + width: $size; + font-size: 1rem; + text-indent: -9999px; + white-space: nowrap; + position: absolute; + z-index: 2; + background-color: var(--kt-body-bg) !important; + box-shadow: var(--kt-box-shadow); + border-radius: 100%; + top: -(divide($size,2)); + right: -(divide($size,2)); + + &:after { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + display: block; + content: ""; + mask-size: 40%; + -webkit-mask-size: 40%; + @include svg-bg-icon(close, var(--kt-gray-600)); + } + + &:hover { + &:after { + @include svg-bg-icon(close, var(--kt-primary)); + } + } + } + + .dz-error-message { + color: var(--kt-danger-inverse); + background: var(--kt-danger); + } +} + +// Queue upload +.dropzone.dropzone-queue { + border: 0; + padding: 0; + background-color: transparent; + text-align: left; + + .dz-message{ + display: none; + } + + .dropzone-panel { + .dropzone-upload, + .dropzone-remove-all{ + display: none; + } + } + + .dropzone-item { + display: flex; + align-items: center; + margin-top: 0.75rem; + @include border-radius($border-radius); + padding: 0.5rem 1rem; + background-color: var(--kt-gray-100); + + .dropzone-file { + flex-grow: 1; + + .dropzone-filename { + font-size: 0.9rem; + font-weight: 500; + color: var(--kt-gray-600); + text-overflow: ellipsis; + margin-right: 0.5rem; + + &:hover { + color: var(--kt-primary); + } + } + + .dropzone-error { + margin-top: 0.25rem; + font-size: 0.9rem; + font-weight: 400; + color: var(--kt-danger); + text-overflow: ellipsis; + } + } + + .dropzone-progress { + width: 15%; + + .progress { + height: 5px; + @include transition; + } + } + + .dropzone-toolbar { + margin-left: 1rem; + display: flex; + flex-wrap: nowrap; + + .dropzone-start, + .dropzone-cancel, + .dropzone-delete { + height: 25px; + width: 25px; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: $transition-link; + + i { + transition: $transition-link; + font-size: 0.8rem; + color: var(--kt-gray-600); + } + + &:hover { + transition: $transition-link; + i { + color: var(--kt-primary); + } + } + } + + .dropzone-start{ + transition: $transition-link; + } + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_flatpickr.scss b/src/_res/assets/sass/core/vendors/plugins/_flatpickr.scss new file mode 100644 index 0000000..8892ae6 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_flatpickr.scss @@ -0,0 +1,407 @@ +// +// Flatpickr +// + +$flatpickr-padding-y: 0.5rem; +$flatpickr-padding-x: 1rem; +$flatpickr-width: 280px; +$flatpickr-width-week-numbers: 325px; +$flatpickr-day-height: 36px; +$flatpickr-day-width: 100%; +$flatpickr-time-height: 46px; + +// Container +.flatpickr-calendar { + width: $flatpickr-width !important; + font-family: inherit; + border: 0; + border-radius: 0; + box-shadow: var(--kt-dropdown-box-shadow); + background-color: var(--kt-body-bg); + @include border-radius($dropdown-border-radius); + + // Remow arrows + &:before, + &:after { + display: none; + } + + // Week numbers + &.hasWeeks { + width: $flatpickr-width-week-numbers !important; + } +} + +// Months container +.flatpickr-months { + padding: 0 $flatpickr-padding-x; + padding-top: $flatpickr-padding-y; +} + +// Inner container +.flatpickr-innerContainer { + padding: $flatpickr-padding-y $flatpickr-padding-x; +} + +// Day containers +.flatpickr-days, +.dayContainer { + width: 100% !important; + min-width: 100% !important; + max-width: 100% !important; +} + +// Months +.flatpickr-months { + .flatpickr-month { + background: transparent; + color: var(--kt-gray-600); + fill: var(--kt-gray-600); + height: 46px; + } + + .flatpickr-prev-month, + .flatpickr-next-month { + display: flex; + align-items: center; + justify-content: center; + @include border-radius($border-radius); + top: 1rem; + + svg { + fill: var(--kt-gray-500); + height: 13px; + width: 13px; + } + + &:hover { + background: var(--kt-gray-100); + + svg { + fill: var(--kt-gray-700); + } + } + } + + .flatpickr-prev-month.flatpickr-prev-month, + .flatpickr-next-month.flatpickr-prev-month { + /*rtl:begin:ignore*/ + left: $flatpickr-padding-x; + /*rtl:end:ignore*/ + } + + .flatpickr-prev-month.flatpickr-next-month, + .flatpickr-next-month.flatpickr-next-month { + /*rtl:begin:ignore*/ + right: $flatpickr-padding-x; + /*rtl:end:ignore*/ + } +} + +// Month selector +.flatpickr-current-month { + font-weight: $font-weight-semibold; + color: inherit; + + .numInputWrapper { + @include border-radius($border-radius); + width: 65px; + + span { + &.arrowUp { + @include border-top-end-radius($border-radius); + } + + &.arrowDown { + @include border-bottom-end-radius($border-radius); + } + } + } + + .flatpickr-monthDropdown-months { + border: 0 !important; + background-color: var(--kt-body-bg); + font-size: 1rem; + color: var(--kt-gray-700); + font-weight: $font-weight-semibold; + padding: 0.5rem 0.75rem; + margin-right: 0.5rem; + outline: none !important; + @include border-radius($border-radius); + appearance: none; + -moz-appearance: none; + -webkit-appearance: none; + + &:hover { + background: var(--kt-gray-100); + } + + .flatpickr-monthDropdown-month { + font-size: 1rem; + color: var(--kt-gray-700); + font-weight: $font-weight-semibold; + background-color: transparent; + outline: none; + padding: 0; + } + } + + span.cur-month { + color: var(--kt-gray-700); + font-size: 1rem; + font-weight: $font-weight-semibold; + + &:hover { + background: var(--kt-gray-100); + } + } + + input.cur-year { + color: var(--kt-gray-700); + font-size: 1.1rem; + padding: 0.5rem 0.75rem; + font-weight: $font-weight-semibold; + outline: 0 !important; + } +} + +// Week days +span.flatpickr-weekday { + color: var(--kt-gray-800); + font-size: 1rem; + font-weight: $font-weight-bold; +} + +// Time +.flatpickr-time { + @include border-bottom-radius($border-radius); + + .flatpickr-calendar.hasTime & { + height: height; + line-height: height; + max-height: height; + border-top: 1px solid var(--kt-gray-100); + } + + .numInputWrapper { + height: height; + } + + .flatpickr-am-pm { + color: var(--kt-gray-700); + font-size: 1rem; + font-weight: $font-weight-semibold; + } + + input { + &.flatpickr-hour, + &.flatpickr-minute { + color: var(--kt-gray-700); + font-size: 1rem; + font-weight: $font-weight-semibold; + } + } + + input:hover, + .flatpickr-am-pm:hover, + input:focus, + .flatpickr-am-pm:focus { + background: transparent; + } +} + +// Number input +.numInputWrapper { + span { + border-left: 0 !important; + border-top: 0 !important; + border-bottom: 0 !important; + border-right: 0 !important; + + &:hover { + background: transparent !important; + } + + &:after { + top: 50% !important; + transform: translateY(-50%); + } + + &.arrowUp { + &:after { + border-bottom-color: var(--kt-gray-500) !important; + } + + &:hover { + &:after { + border-bottom-color: var(--kt-gray-700) !important; + } + } + } + + &.arrowDown { + &:after { + border-top-color: var(--kt-gray-500) !important; + } + + &:hover { + &:after { + border-top-color: var(--kt-gray-700) !important; + } + } + } + } + + &:hover { + background: transparent; + } +} + +// Day +.flatpickr-day { + font-size: 1rem; + @include border-radius($border-radius); + box-shadow: none !important; + height: $flatpickr-day-height; + width: $flatpickr-day-width; + max-width: 100% !important; + margin: 0; + line-height: $flatpickr-day-height; + color: var(--kt-gray-600); + margin-top: 0 !important; + + &.inRange, + &.prevMonthDay.inRange, + &.nextMonthDay.inRange, + &.today.inRange, + &.prevMonthDay.today.inRange, + &.nextMonthDay.today.inRange, + &:hover, + &.prevMonthDay:hover, + &.nextMonthDay:hover, + &:focus, + &.prevMonthDay:focus, + &.nextMonthDay:focus { + cursor: pointer; + outline: 0; + background: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + border-color: transparent; + } + + // Today + &.today { + background: var(--kt-gray-100); + color: var(--kt-gray-600); + border-color: transparent; + + &:hover, + &:focus { + border-color: transparent; + background: var(--kt-gray-200); + color: var(--kt-gray-700); + } + } + + // Selected + &.selected, + &.startRange, + &.endRange, + &.selected.inRange, + &.startRange.inRange, + &.endRange.inRange, + &.selected:focus, + &.startRange:focus, + &.endRange:focus, + &.selected:hover, + &.startRange:hover, + &.endRange:hover, + &.selected.prevMonthDay, + &.startRange.prevMonthDay, + &.endRange.prevMonthDay, + &.selected.nextMonthDay, + &.startRange.nextMonthDay, + &.endRange.nextMonthDay { + background: var(--kt-component-active-bg); + color: var(--kt-component-active-color);; + border-color: transparent; + } + + &.inRange, + &.prevMonthDay.inRange, + &.nextMonthDay.inRange, + &.today.inRange, + &.prevMonthDay.today.inRange, + &.nextMonthDay.today.inRange, + &:hover, + &.prevMonthDay:hover, + &.nextMonthDay:hover, + &:focus, + &.prevMonthDay:focus, + &.nextMonthDay:focus { + cursor: pointer; + outline: 0; + background: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + border-color: transparent; + } + + // Today + &.today { + border-color: transparent; + } + + &.today:hover, + &.today:focus { + border-color: transparent; + background: var(--kt-gray-100); + color: var(--kt-gray-600); + } + + // Selected + &.selected, + &.startRange, + &.endRange, + &.selected.inRange, + &.startRange.inRange, + &.endRange.inRange, + &.selected:focus, + &.startRange:focus, + &.endRange:focus, + &.selected:hover, + &.startRange:hover, + &.endRange:hover, + &.selected.prevMonthDay, + &.startRange.prevMonthDay, + &.endRange.prevMonthDay, + &.selected.nextMonthDay, + &.startRange.nextMonthDay, + &.endRange.nextMonthDay { + background: var(--kt-component-active-bg); + color: var(--kt-component-active-color);; + border-color: transparent; + } + + // Disabled + &.flatpickr-disabled, + &.flatpickr-disabled:hover, + &.prevMonthDay, + &.nextMonthDay, + &.notAllowed, + &.notAllowed.prevMonthDay, + &.notAllowed.nextMonthDay { + color: var(--kt-gray-400); + background: transparent; + border-color: transparent; + } + &.flatpickr-disabled, + &.flatpickr-disabled:hover { + cursor: not-allowed; + color: var(--kt-gray-400); + } +} + +// Week numbers +.flatpickr-weekwrapper { + margin-right: 5px; +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_formvalidation.scss b/src/_res/assets/sass/core/vendors/plugins/_formvalidation.scss new file mode 100644 index 0000000..dd853e4 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_formvalidation.scss @@ -0,0 +1,19 @@ +// +// FormValidation Customization. More info: https://formvalidation.io/ +// + +.fv-plugins-message-container { + margin-top: 0.3rem; + + .fv-help-block { + color: var(--kt-danger); + font-size: 1rem; + font-weight: $font-weight-normal; + } + + &.valid-feedback, + &.invalid-feedback { + display: block; + font-weight: $font-weight-normal; + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_fslightbox.scss b/src/_res/assets/sass/core/vendors/plugins/_fslightbox.scss new file mode 100644 index 0000000..a9390cf --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_fslightbox.scss @@ -0,0 +1,11 @@ +// +// fslightbox +// + +.fslightbox-slide-btn { + border-radius: $border-radius; +} + +.fslightbox-toolbar { + border-bottom-left-radius: $border-radius; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_fullcalendar.scss b/src/_res/assets/sass/core/vendors/plugins/_fullcalendar.scss new file mode 100644 index 0000000..2923198 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_fullcalendar.scss @@ -0,0 +1,297 @@ +// +// Fullcalendar plugin customization: https://fullcalendar.io/ +// + +body { + --fc-event-border-color: var(--kt-primary); + --fc-event-bg-color: var(--kt-primary); + --fc-event-text-color: var(--kt-primary-inverse); +} + +// Base +.fc { + // Border color + --fc-border-color: #{var(--kt-gray-200)}; + --fc-page-bg-color: #{$white}; + --fc-small-font-size: 0.95rem; + + // General + --fc-highlight-color: var(--kt-light); + //--fc-non-business-color: + //--fc-bg-event-color: + --fc-bg-event-opacity: 0.3; + --fc-neutral-bg-color: var(--kt-light); + //--fc-event-selected-overlay-color: + --fc-today-bg-color: var(--kt--success-light); + //--fc-neutral-bg-color: + //--fc-neutral-text-color: + //--fc-more-link-text-color: + //--fc-more-link-bg-color: + --fc-now-indicator-color: var(--kt-danger); + --fc-list-event-hover-bg-color: var(--kt-light); + + // Buttons + --fc-button-text-color: var(--kt-gray-600); + --fc-button-bg-color: var(--kt-gray-100); + --fc-button-border-color: var(--kt-gray-100); + + --fc-button-hover-bg-color: var(--kt-gray-100); + --fc-button-hover-border-color: var(--kt-gray-100); + + --fc-button-active-bg-color: var(--kt-gray-200); + --fc-button-active-border-color: var(--kt-gray-200); + + // Table + table { + font-size: 1rem; + } + + // Button + .fc-button { + padding: 0.75rem 1.25rem; + box-shadow: none !important; + border: 0 !important; + border-radius: $btn-border-radius; + vertical-align: middle; + font-weight: $font-weight-semibold; + text-transform: capitalize; + } + + // Primary button + .fc-button-primary { + margin: 0; + + // Icon + .fc-icon { + font-size: 1.35rem; + margin-bottom: 0.15rem; + } + + &:not(:disabled):not(.fc-button-active) { + &:focus, + &:hover, + &:active { + color: var(--kt-gray-900); + + .fc-icon { + color: var(--kt-gray-900); + } + } + } + + &:not(:disabled).fc-button-active { + color: var(--kt-gray-900); + + .fc-icon { + color: var(--kt-gray-900); + } + } + } + + // Button group + .fc-button-group { + .fc-button { + margin: 0 !important; + } + } + + // Toolbar title + .fc-toolbar-title { + font-size: 1.5rem; + font-weight: $font-weight-bold; + color: var(--kt-gray-800); + } + + // Header cell + .fc-col-header-cell { + padding: 0.75rem 0.5rem; + + .fc-col-header-cell-cushion { + font-size: 1.1rem; + font-weight: $font-weight-semibold; + color: var(--kt-gray-800); + } + } + + // Border radius + .fc-scrollgrid { + @include border-radius($border-radius); + + thead > tr { + td:first-child { + @include border-top-start-radius($border-radius); + } + + td:last-child { + @include border-top-end-radius($border-radius); + } + } + + tbody > tr:last-child { + td:first-child { + @include border-bottom-start-radius($border-radius); + } + + td:last-child { + @include border-bottom-end-radius($border-radius); + } + } + } + + // Event + .fc-daygrid-event { + margin-top: 3px; + } + + // Event title + .fc-daygrid-dot-event, + .fc-daygrid-block-event { + .fc-event-title, + .fc-event-time { + padding: 0.25rem 0.25rem; + } + } + + // Day number + .fc-daygrid-day-number { + color: var(--kt-gray-800); + } + + // Dot event + .fc-daygrid-dot-event { + background-color: var(--kt-light); + color: var(--kt-gray-600); + + .fc-event-title { + font-weight: $font-weight-semibold; + } + + &:hover, + &.fc-event-mirror { + background-color: var(--kt-light); + color: var(--kt-primary); + } + } + + // Event dot + .fc-daygrid-event-dot { + margin-left: 0.5rem; + margin-right: 0.1rem; + } + + // Popover + .fc-popover { + border: 0 !important; + background-color: var(--kt-tooltip-bg); + box-shadow: var(--kt-dropdown-box-shadow); + @include border-radius($dropdown-border-radius); + + .fc-popover-header { + @include border-top-radius($dropdown-border-radius); + padding: 0.65rem 0.75rem; + background-color: var(--kt-tooltip-bg); + + .fc-popover-title { + color: var(--kt-gray-800); + font-size: 1rem; + font-weight: $font-weight-semibold; + } + + .fc-popover-close { + font-size: 1rem; + color: var(--kt-gray-600); + + &:hover { + color: var(--kt-primary); + } + } + } + + .fc-popover-body { + padding: 0.5rem 0.75rem 0.75rem 0.75rem; + } + } + + // More link + .fc-daygrid-more-link { + font-weight: $font-weight-semibold; + } + + // Slot + .fc-timegrid-slot { + height: 2rem; + font-size: 0.95rem; + } + + // List + .fc-list-day-cushion, + .fc-list-table td { + padding: 0.85rem 1.15rem; + } + + .fc-list-day-text, + .fc-list-day-side-text { + font-size: 1.1rem; + color: var(--kt-gray-900); + font-weight: $font-weight-bold; + } + + .fc-list, + //.fc-scroller, + .fc-list-table { + @include border-radius($border-radius); + } + + .fc-list { + overflow: hidden; + position: relative; + } + + // Week + .fc-timegrid-axis { + padding-left: 0rem; + padding-right: 0; + } + + // Main + .fc-timegrid-event .fc-event-main { + padding: 0.25rem 0.25rem; + } + + // Indicator arrow + .fc-timegrid-now-indicator-arrow { + margin-top: -1px; + } +} + +// Event +.fc-h-event { + font-weight: $font-weight-normal; +} + +// Mobile mode +@include media-breakpoint-down(md) { + .fc { + // Header toolbar + .fc-header-toolbar { + flex-direction: column; + align-items: flex-start; + + .fc-toolbar-chunk { + &:nth-child(1), + &:nth-child(3) { + order: 2; + } + + &:nth-child(2) { + order: 1; + } + + &:nth-child(2), + &:nth-child(1) { + margin-bottom: 1rem; + } + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_gmaps.scss b/src/_res/assets/sass/core/vendors/plugins/_gmaps.scss new file mode 100644 index 0000000..0f9dd4c --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_gmaps.scss @@ -0,0 +1,18 @@ +// +// Gmaps Plugin +// + +.gmaps { + /* important! bootstrap sets max-width on img to 100% which conflicts with google map canvas*/ + img { + max-width: none; + } + + &.gmaps-static { + > div { + background-repeat: no-repeat ; + background-position: 50% 50% ; + display:block; + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_jkanban.scss b/src/_res/assets/sass/core/vendors/plugins/_jkanban.scss new file mode 100644 index 0000000..d889064 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_jkanban.scss @@ -0,0 +1,94 @@ +// +// Kanban Board +// + +// Variables +$kanban-spacer-y: 1.25rem; +$kanban-spacer-x: 1.25rem; + +.kanban-container { + width: 100% !important; + display: flex; + flex-wrap: wrap; + + .kanban-board { + float: none; + flex-shrink: 0; + margin-bottom: $kanban-spacer-y; + margin-right: $kanban-spacer-x !important; + background-color: var(--kt-gray-100); + @include border-radius($border-radius); + + &:last-child { + margin-right: 0 !important; + } + + .kanban-board-header { + @include border-top-start-radius($border-radius); + @include border-top-end-radius($border-radius); + + .kanban-title-board { + font-size: 1.2rem; + font-weight: 500; + color: var(--kt-gray-900); + } + + @each $name, $color in $theme-colors { + &.#{$name} { + background-color: var(--kt-#{$name}); + box-shadow: none; + + .kanban-title-board { + color: var(--kt-#{$name}-inverse); + } + } + + &.light-#{$name} { + color: rgba(var(--kt-#{$name}), 0.1); + box-shadow: none; + + .kanban-title-board { + color: var(--kt-#{$name}); + } + } + } + } + + .kanban-drag { + .kanban-item { + @include border-radius($border-radius); + box-shadow: 0px 0px 13px 0px rgba(0, 0, 0, 0.05); + background: var(--kt-body-bg); + + @each $name, $color in $theme-colors { + &[data-class="#{$name}"] { + background-color: var(--kt-#{$name}); + color: var(--kt-#{$name}-inverse); + box-shadow: none; + } + + &[data-class="light-#{$name}"] { + background-color: var(--kt-#{$name}-light); + color: var(--kt-#{$name}); + box-shadow: none; + } + } + } + } + + footer { + } + } +} + +// Fixed height +.kanban-fixed-height { + .kanban-container { + .kanban-board { + .kanban-drag { + position: relative; + overflow-y: auto; + } + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_jstree.scss b/src/_res/assets/sass/core/vendors/plugins/_jstree.scss new file mode 100644 index 0000000..412d142 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_jstree.scss @@ -0,0 +1,150 @@ +// +// jsTree +// + +.jstree-default { + .jstree-anchor { + color: var(--kt-gray-700); + padding: 0 8px 0 4px; + } + + .jstree-icon { + color: var(--kt-gray-700); + + font-size: 1.3rem; + + &.la { + font-size: 1.5rem; + } + &.fa { + font-size: 1.2rem; + } + } + + .jstree-disabled { + cursor: not-allowed; + line-height: auto; + height: auto; + opacity: 0.7; + + .jstree-icon { + color: var(--kt-gray-700); + } + } + + .jstree-clicked { + border: 0; + background: var(--kt-gray-100); + box-shadow: none; + } + + .jstree-hovered { + border: 0; + background-color: var(--kt-gray-100); + box-shadow: none; + } + + .jstree-wholerow-clicked, + .jstree-wholerow-clicked { + background: var(--kt-gray-200); + box-shadow: none; + } + + .jstree-wholerow-hovered, + &.jstree-wholerow .jstree-wholerow-hovered { + border: 0; + background-color: var(--kt-gray-100); + box-shadow: none; + } +} + +.jstree-open>.jstree-anchor>.fa-folder:before { + margin-left: 2px; + content: "\f07c"; +} + +.jstree-open>.jstree-anchor>.la-folder:before { + margin-left: 2px; + content: "\f200"; +} + +.jstree-default.jstree-rtl .jstree-node { + background-position: 100% 1px#{'/*rtl:ignore*/'} !important; +} + +.jstree-default.jstree-rtl .jstree-last { + background: transparent #{'/*rtl:ignore*/'}; + background-repeat: no-repeat; +} + +.jstree-rtl .jstree-anchor { + padding: 0 4px 0 8px#{'/*rtl:ignore*/'}; +} + +// context menu +.vakata-context, +.vakata-context ul { + padding: 0.5rem 0; + min-width: 150px; + font-size: 1rem; + font-family: $font-family-base; + background: var(--kt-body-bg); + box-shadow: var(--kt-dropdown-box-shadow); + border: 0; + @include border-radius($border-radius); + + li { + padding: 0; + border: 0; + + a { + padding: 0rem 1.2rem; + border: 0; + //line-height: 2.2em; + + i { + display: none; + } + + .vakata-contextmenu-sep { + display: none; + } + + span, + ins { + display: none; + border: 0 !important; + } + } + } + + .vakata-context-hover>a, + li a:hover { + margin: 0; + background-color: var(--kt-gray-100); + color: var(--kt-primary); + box-shadow: none; + + .span, + .ins { + border: 0 !important; + } + } +} + +.vakata-context .vakata-context-separator a, +.vakata-context-rtl .vakata-context-separator a { + margin: 0; + border: 0; + height: 2px; + background-color: var(--kt-gray-200); +} + +.jstree-rename-input { + outline: none !important; + padding: 2px 6px !important; + margin-right: -4px !important; + background-color: var(--kt-gray-100) !important; + border: 1px solid var(--kt-gray-100) !important; + @include border-radius($border-radius); +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_leaflet.scss b/src/_res/assets/sass/core/vendors/plugins/_leaflet.scss new file mode 100644 index 0000000..3cc6f34 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_leaflet.scss @@ -0,0 +1,23 @@ +// +// leaflet +// + +.leaflet-container { + .leaflet-pane, + .leaflet-top, + .leaflet-bottom, + .leaflet-control { + z-index: 1 !important; + } + + .leaflet-popup-content-wrapper { + border-radius: $border-radius !important; + text-align: center; + box-shadow: var(--kt-box-shadow) !important; + + .leaflet-popup-content { + font-family: $font-family-sans-serif; + font-size: $font-size-base; + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_mixins.scss b/src/_res/assets/sass/core/vendors/plugins/_mixins.scss new file mode 100644 index 0000000..c22460e --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_mixins.scss @@ -0,0 +1,5 @@ +// +// Mixins +// + +@import "mixins/nouislider"; diff --git a/src/_res/assets/sass/core/vendors/plugins/_nouislider.scss b/src/_res/assets/sass/core/vendors/plugins/_nouislider.scss new file mode 100644 index 0000000..e61522d --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_nouislider.scss @@ -0,0 +1,103 @@ +// +// NoUiSlider +// + + +// Base +.noUi-target { + border: 0; + background: var(--kt-gray-100); + box-shadow:none; + + &.noUi-horizontal { + height: 15px; + + .noUi-handle { + width: 24px; + height: 24px; + top: -4.5px; + border-radius: 50%; + outline: none; + + &::before { + display: none; + } + + &::after { + display: none; + } + } + } + + &.noUi-vertical { + height: 150px; + width: 15px; + + .noUi-handle { + width: 24px; + height: 24px; + right: -4.5px; + border-radius: 50%; + outline: none; + + &::before { + display: none; + } + + &::after { + display: none; + } + } + } + + .noUi-connect { + background: var(--kt-component-active-bg); + } + + .noUi-handle { + background-color: $white; //var(--kt-body-bg); + border: 1px solid var(--kt-gray-200); + box-shadow:var(--kt-box-shadow-sm) + } + + // Small size + &.noUi-sm { + @include nouislider-size(6px, 20px, 20px, 7px); + } + + // Large size + &.noUi-lg { + @include nouislider-size(18px, 30px, 30px, 6px); + } +} + +// Theme colors +@each $name, $value in $theme-colors { + // NoUiSlider success color option + .noUi-target.noUi-target-#{$name} { + .noUi-connects { + background-color: var(--kt-#{$name}-light); + + .noUi-connect { + background-color: var(--kt-#{$name}); + } + } + + .noUi-handle { + border: 1px solid var(--kt-#{$name}); + box-shadow: 0 3px 6px -3px rgba(var(--kt-#{$name}), 0.7); + background-color: var(--kt-#{$name}); + } + } +} + +// Tooltip +.noUi-tooltip { + box-shadow: var(--kt-tooltip-box-shadow); + background: var(--kt-tooltip-bg); + color: var(--kt-tooltip-color); + font-size: $tooltip-font-size; + border: 0; + padding: 0.5rem 0.75rem; + @include border-radius($tooltip-border-radius); +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_plugins.angular.scss b/src/_res/assets/sass/core/vendors/plugins/_plugins.angular.scss new file mode 100644 index 0000000..0242e13 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_plugins.angular.scss @@ -0,0 +1,12 @@ +// +// Plugins +// + +// Import Dependencies +@import "root"; +@import "prismjs"; +@import "nouislider"; +@import "apexcharts"; +@import "fslightbox"; +@import "tiny-slider"; +@import "fullcalendar"; \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_plugins.react.scss b/src/_res/assets/sass/core/vendors/plugins/_plugins.react.scss new file mode 100644 index 0000000..0242e13 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_plugins.react.scss @@ -0,0 +1,12 @@ +// +// Plugins +// + +// Import Dependencies +@import "root"; +@import "prismjs"; +@import "nouislider"; +@import "apexcharts"; +@import "fslightbox"; +@import "tiny-slider"; +@import "fullcalendar"; \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_plugins.scss b/src/_res/assets/sass/core/vendors/plugins/_plugins.scss new file mode 100644 index 0000000..c2df238 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_plugins.scss @@ -0,0 +1,32 @@ +// +// Plugins +// + +// Import Dependencies +@import "root"; +@import "prismjs"; +@import "fslightbox"; +@import "select2"; +@import "formvalidation"; +@import "daterangepicker"; +@import "flatpickr"; +@import "tagify"; +@import "bootstrap-maxlength"; +@import "ckeditor"; +@import "datatables"; +@import "dropzone"; +@import "gmaps"; +@import "nouislider"; +@import "quill"; +@import "recaptcha"; +@import "sweetalert2"; +@import "tinymce"; +@import "toastr"; +@import "draggable"; +@import "apexcharts"; +@import "leaflet"; +@import "tiny-slider"; +@import "fullcalendar"; +@import "jkanban"; +@import "jstree"; +@import "vis-timeline"; \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_plugins.vue.scss b/src/_res/assets/sass/core/vendors/plugins/_plugins.vue.scss new file mode 100644 index 0000000..0242e13 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_plugins.vue.scss @@ -0,0 +1,12 @@ +// +// Plugins +// + +// Import Dependencies +@import "root"; +@import "prismjs"; +@import "nouislider"; +@import "apexcharts"; +@import "fslightbox"; +@import "tiny-slider"; +@import "fullcalendar"; \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_prismjs.scss b/src/_res/assets/sass/core/vendors/plugins/_prismjs.scss new file mode 100644 index 0000000..fa95a54 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_prismjs.scss @@ -0,0 +1,84 @@ +// +// Prismjs +// + +// Highlight +.highlight { + position: relative; + background: var(--kt-highlight-bg); + border-radius: $border-radius; + padding: 1.75rem 1.5rem 1.75rem 1.5rem; + + // Tabs + .nav { + border-bottom: 1px solid var(--kt-highlight-border); + padding-bottom: 1rem; + margin-bottom: 1rem; + margin-top: -0.25rem; + + .nav-item { + margin-right: 0.75rem; + } + + .nav-link { + font-size: 0.9rem; + font-weight: 500; + padding: 0.35rem 1rem; + border-radius: $border-radius; + color: var(--kt-highlight-btn-color); + transition: $transition-base; + background-color: transparent; + + &:focus, + &.active { + transition: $transition-base; + background-color: var(--kt-highlight-btn-bg-hover); + color: var(--kt-highlight-btn-color-hover); + } + } + } + + .highlight-copy { + display: none; + position: absolute; + right: 1.75rem; + top: 1.5rem; + font-size: 0.85rem; + font-weight: 500; + padding: 0.35rem 1rem !important; + transition: $transition-base; + background-color: var(--kt-highlight-btn-bg); + color: var(--kt-highlight-btn-color); + + &:focus, + &:hover { + transition: $transition-base; + background-color: var(--kt-highlight-btn-bg-hover); + color: var(--kt-highlight-btn-color-hover); + } + } + + &:hover { + .highlight-copy { + display: flex; + } + } + + // Code + .highlight-code { + pre { + background-color: transparent; + overflow: auto; + padding: 0; + margin: 0; + + @include scrollbar-color( var(--kt-highlight-scrollbar-color), var(--kt-highlight-scrollbar-color-hover)); + + code[class*="language-"] { + padding: 0; + margin: 0; + font-size: 1rem !important; + } + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_quill.scss b/src/_res/assets/sass/core/vendors/plugins/_quill.scss new file mode 100644 index 0000000..5f52679 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_quill.scss @@ -0,0 +1,185 @@ +// +// Quill +// + +// Base +.ql-toolbar { + font-family: $font-family-sans-serif; + + &.ql-snow { + border: 1px solid var(--kt-border-color); + @include border-top-radius($border-radius); + + .ql-picker, + button { + .ql-fill, + .ql-stroke { + stroke: var(--kt-gray-500); + } + + .ql-fill { + fill: var(--kt-gray-500); + } + + &.ql-expanded, + &.ql-active, + &:focus, + &:hover { + .ql-fill, + .ql-stroke { + stroke: var(--kt-primary); + } + + .ql-fill { + fill: var(--kt-primary); + } + } + } + } +} + +.ql-editor { + color: var(--kt-input-color); + + &.ql-blank { + &:before { + left: auto !important; + right: auto !important; + color: var(--kt-text-muted) !important; + font-style: normal !important; + } + } +} + +.ql-container { + &.ql-snow { + background-color: var(--kt-input-bg); + border: 1px solid var(--kt-gray-200); + border-top: 0; + @include border-bottom-radius($border-radius); + } +} + +.ql-snow { + .ql-picker { + .ql-picker-label { + color: var(--kt-gray-500); + + &.ql-active, + &:hover { + color: var(--kt-primary); + } + } + + &.ql-expanded { + outline: none !important; + border-color: transparent !important; + + .ql-picker-label { + border-color: transparent !important; + color: var(--kt-primary); + outline: none !important; + + &.ql-active, + &:hover { + color: var(--kt-primary); + } + } + + .ql-picker-options { + border: 0; + padding: 0.5rem 1rem; + box-shadow: var(--kt-dropdown-box-shadow); + background-color: var(--kt-body-bg); + @include border-radius($border-radius); + + .ql-picker-item { + color: var(--kt-gray-600); + outline: none; + + &.ql-selected, + &.ql-active, + &:hover { + color: var(--kt-primary); + } + } + } + } + } + + .ql-tooltip { + border: 0; + padding: 0.5rem 1rem; + box-shadow: var(--kt-dropdown-box-shadow); + @include border-radius($border-radius); + + input[type=text] { + @include input-reset(); + border: 1px solid var(--kt-border-color); + color: $input-plaintext-color; + outline: none !important; + @include border-radius($border-radius); + + &:active, + &:focus { + border-color: var(--kt-input-focus-border-color) !important; + } + } + + .ql-preview { + color: var(--kt-gray-600); + } + + .ql-action { + transition: color 0.3s ease; + color: var(--kt-gray-600); + + &:hover { + transition: color 0.3s ease; + color: var(--kt-primary); + } + } + + // Tooltip adjustment in modal + .modal & { + &.ql-editing { + left: 20px !important; + } + } + } + + .ql-editor { + pre.ql-syntax { + background-color: var(--kt-gray-900); + color: var(--kt-text-muted); + overflow: visible; + @include border-radius($border-radius); + } + } +} + +// Plain Style +.ql-quil.ql-quil-plain { + .ql-toolbar { + padding: 0; + margin: 0; + border: 0; + + &:after { + display: none; + } + + .ql-picker-label { + padding-left: 0; + } + } + + .ql-container { + border: 0; + } + + .ql-editor { + border: 0; + padding: 0; + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_recaptcha.scss b/src/_res/assets/sass/core/vendors/plugins/_recaptcha.scss new file mode 100644 index 0000000..4c0d42e --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_recaptcha.scss @@ -0,0 +1,32 @@ +// +// Recaptcha +// + + +// Base +.recaptcha { + padding: 15px; + border: 1px solid var(--kt-gray-200); + @include border-radius($border-radius); + + .recaptcha-img { + margin-bottom: 10px; + } + + .recaptcha_only_if_incorrect_sol { + color: var(--kt-danger); + } + + .input-group { + .btn { + i { + padding-right: 0; + } + } + + .form-control { + @include border-top-start-radius($border-radius !important); + @include border-bottom-start-radius($border-radius !important); + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_root.scss b/src/_res/assets/sass/core/vendors/plugins/_root.scss new file mode 100644 index 0000000..afab66f --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_root.scss @@ -0,0 +1,36 @@ +// +// CSS Variables +// + +:root, +[data-theme="light"] { + // Select2 + + // Prismjs + --kt-highlight-bg: #{$highlight-bg}; + + --kt-highlight-border: #{$highlight-border}; + + --kt-highlight-btn-bg: #{$highlight-btn-bg}; + --kt-highlight-btn-bg-hover: #{$highlight-btn-bg-hover}; + --kt-highlight-btn-color: #{$highlight-btn-color}; + --kt-highlight-btn-color-hover: #{$highlight-btn-color-hover}; + + --kt-highlight-scrollbar-color: #{$highlight-scrollbar-color}; + --kt-highlight-scrollbar-color: #{$highlight-scrollbar-hover-color}; +} + +[data-theme="dark"] { + // Prismjs + --kt-highlight-bg: #{$highlight-bg-dark}; + + --kt-highlight-border: #{$highlight-border-dark}; + + --kt-highlight-btn-bg: #{$highlight-btn-bg-dark}; + --kt-highlight-btn-bg-hover: #{$highlight-btn-bg-hover-dark}; + --kt-highlight-btn-color: #{$highlight-btn-color-dark}; + --kt-highlight-btn-color-hover: #{$highlight-btn-color-hover-dark}; + + --kt-highlight-scrollbar-color: #{$highlight-scrollbar-color-dark}; + --kt-highlight-scrollbar-color-hover: #{$highlight-scrollbar-hover-color-dark}; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_select2.scss b/src/_res/assets/sass/core/vendors/plugins/_select2.scss new file mode 100644 index 0000000..20fc962 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_select2.scss @@ -0,0 +1,399 @@ +// +// Select2 plugin customization: https://select2.org +// + +$select2-dropdown-padding: 1rem 0; +$select2-dropdown-option-padding: 0.75rem 1.25rem; +$select2-dropdown-option-margin: 0 0; +$select2-dropdown-option-check-padding: 1.25rem; + +$select2-dropdown-group-padding: 0 1.25rem 0 1.25rem; +$select2-dropdown-group-margin: 0 0 0.25rem 0; + +$select2-search-padding: 0.5rem 1.25rem; +$select2-search-margin: 0 0 0.5rem 0; + +$select2-clear-size: 0.7rem; +$select2-clear-color: var(--kt-gray-700); +$select2-clear-color-dark: var(--kt-gray-700); +$select2-clear-color-hover: var(--kt-primary); +$select2-clear-right: $form-select-indicator-padding; //$form-select-padding-x + + + +// Bootstrap .form-control sizing integration +$select2-tag-clear-size: 0.6rem; + +$select2-tag-padding-y-sm: 0.1rem; +$select2-tag-padding-x-sm: 0.35rem; +$select2-input-padding-y-sm: $input-padding-y-sm - $select2-tag-padding-y-sm * 2; + +$select2-tag-padding-y: 0.1rem; +$select2-tag-padding-x: 0.5rem; +$select2-input-padding-y: $input-padding-y - $select2-tag-padding-y * 2; + +$select2-tag-padding-y-lg: 0.15rem; +$select2-tag-padding-x-lg: 0.65rem; +$select2-input-padding-y-lg: $input-padding-y-lg - $select2-tag-padding-y-lg * 2; + +// Bootstrapa 5 Theme +.select2-container--bootstrap5 { + // Selection + .select2-selection { + box-shadow: none !important; + height: auto; + outline: none !important; + } + + // Selection focus & open states + &.select2-container--focus, + &.select2-container--open { + .form-select-solid { + background-color: var(--kt-input-solid-bg-focus); + } + + .form-select:not(.form-select-solid):not(.form-select-transparent) { + border-color: var(--kt-input-focus-border-color); + } + } + + // Search + .select2-search.select2-search--inline { + .select2-search__field { + color: var(--kt-input-color); + @include placeholder($input-placeholder-color); + font-weight: $input-font-weight; + font-family: inherit !important; + background-color: transparent; + border: 0; + box-shadow: none; + outline: none; + line-height: 1; + margin: 0; + padding: 0; + } + } + + .form-select-solid .select2-search.select2-search--inline { + .select2-search__field { + color: var(--kt-input-solid-color); + font-family: inherit !important; + @include placeholder(var(--kt-input-solid-placeholder-color)); + } + } + + // Single mode + .select2-selection--single { + display: flex; + align-items: center; + + // Selected + .select2-selection__rendered { + display: block; + padding-left: 0; + padding-right: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--kt-input-color); + } + + // Placeholder + .select2-selection__placeholder { + color: $input-placeholder-color; + } + + // Form select solid + &.form-select-solid { + // Selected + .select2-selection__rendered { + color: var(--kt-input-solid-color); + } + + // Placeholder + .select2-selection__placeholder { + color: var(--kt-input-solid-placeholder-color); + } + } + + // Form select transparent + &.form-select-transparent { + // Selected + .select2-selection__rendered { + color: var(--kt-gray-800); + } + + // Placeholder + .select2-selection__placeholder { + color: var(--kt-gray-800); + } + } + + // Form select dark color + &.form-select-dark { + // Selected + .select2-selection__rendered { + color: var(--kt-gray-900); + } + } + } + + // Multiple mode + .select2-selection--multiple { + display: flex; + align-items: center; + + // Search + .select2-search.select2-search--inline { + display: inline-flex; + } + + // Selected + .select2-selection__rendered { + display: inline; + margin: 0; + padding: 0; + + .select2-selection__choice { + display: inline-flex; + align-items: center; + position: relative; + background-color: var(--kt-gray-300); + + .select2-selection__choice__remove { + @include svg-bg-icon(close, var(--kt-gray-700)); + display: block; + position: absolute; + transform: translateY(-50%); + opacity: 0.5; + border: 0; + transition: $transition-link; + top: 50%; + + span { + display: none; + } + + &:hover { + opacity: 1; + @include svg-bg-icon(close, var(--kt-primary)); + transition: $transition-link; + } + } + + .select2-selection__choice__display { + font-weight: $font-weight-semibold; + } + } + } + + // Choice + .select2-selection__choice { + .select2-selection__choice__remove { + height: $select2-tag-clear-size; + width: $select2-tag-clear-size; + } + } + + // Sizes + &.form-select-sm { + min-height: $input-height-sm; + padding-top: $select2-input-padding-y-sm; + padding-bottom: $select2-input-padding-y-sm; + + .select2-selection__choice { + border-radius: $btn-border-radius-sm; + padding: $select2-tag-padding-y-sm $select2-tag-padding-x-sm; + margin-right: $select2-tag-padding-x-sm; + margin-top: $select2-tag-padding-y-sm; + margin-bottom: $select2-tag-padding-y-sm; + + .select2-selection__choice__display { + margin-left: $select2-tag-padding-x-sm + $select2-tag-clear-size; + font-size: $input-btn-font-size-sm; + } + } + + .select2-search__field { + height: 14px; + } + } + + &:not(.form-select-sm):not(.form-select-lg) { + min-height: $input-height; + padding-top: $select2-input-padding-y; + padding-bottom: $select2-input-padding-y; + + .select2-selection__choice { + border-radius: $btn-border-radius; + padding: $select2-tag-padding-y $select2-tag-padding-x; + margin-right: $select2-tag-padding-x; + margin-top: $select2-tag-padding-y; + margin-bottom: $select2-tag-padding-y; + + .select2-selection__choice__display { + margin-left: $select2-tag-padding-x + $select2-tag-clear-size; + font-size: $input-btn-font-size; + } + } + + .select2-search__field { + height: 16px; + } + } + + &.form-select-lg { + min-height: $input-height-lg; + padding-top: $select2-input-padding-y-lg; + padding-bottom: $select2-input-padding-y-lg; + + .select2-selection__choice { + border-radius: $btn-border-radius-lg; + padding: $select2-tag-padding-y-lg $select2-tag-padding-x-lg; + margin-right: $select2-tag-padding-x-lg; + margin-top: $select2-tag-padding-y-lg; + margin-bottom: $select2-tag-padding-y-lg; + + .select2-selection__choice__display { + margin-left: $select2-tag-padding-x-lg + $select2-tag-clear-size; + font-size: $input-btn-font-size-lg; + } + } + + .select2-search__field { + height: 18px; + } + } + } + + // Dropdown + .select2-dropdown { + border: 0; + box-shadow: var(--kt-dropdown-box-shadow); + border-radius: $dropdown-border-radius; + padding: $select2-dropdown-padding; + background-color: var(--kt-dropdown-bg); + + // In modal + .modal-open & { + z-index: $zindex-modal + 1; + } + + // Search + .select2-search { + padding: $select2-search-padding; + margin: $select2-search-margin; + + .select2-search__field { + background-color: var(--kt-body-bg); + padding: $input-padding-y-sm $input-padding-x-sm; + color: var(--kt-input-color); + font-size: $input-font-size-sm; + border: 1px solid var(--kt-input-border-color); + border-radius: $input-border-radius-sm; + outline: 0 !important; + + &:focus, + &:active { + border: 1px solid var(--kt-input-focus-border-color); + } + } + } + + // Options + .select2-results__options { + max-height: 250px; + overflow-y: auto; + } + + // Option + .select2-results__option { + color: var(--kt-gray-700); + transition: $transition-link; + padding: $select2-dropdown-option-padding; + margin: $select2-dropdown-option-margin; + + &.select2-results__option--highlighted { + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + transition: $transition-link; + } + + &.select2-results__option--selected { + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + transition: $transition-link; + position: relative; + + &:after { + top: 50%; + display: block; + position: absolute; + transform: translateY(-50%); + height: 0.75rem; + width: 0.75rem; + content: ""; + @include svg-bg-icon(check, var(--kt-component-hover-color)); + mask-position: center; + -webkit-mask-position: center; + right: $select2-dropdown-option-check-padding; + } + } + + &.select2-results__option--disabled { + color: var(--kt-gray-400); + } + + &.select2-results__message { + color: var(--kt-gray-600); + } + + &.select2-results__option--group { + padding-left: 0; + padding-right: 0; + + .select2-results__group { + display: block; + color: var(--kt-gray-800); + font-weight: $font-weight-semibold; + font-size: $h5-font-size; + padding: $select2-dropdown-group-padding; + margin: $select2-dropdown-group-margin; + } + + .select2-results__option { + padding: $select2-dropdown-option-padding; + margin: $select2-dropdown-option-margin; + } + } + } + } + + // Clear + .select2-selection__clear { + display: block; + height: $select2-clear-size; + width: $select2-clear-size; + top: 50%; + right: $select2-clear-right; + position: absolute; + transform: translateY(-50%); + background-color: var(--kt-gray-700) !important; + @include svg-bg-icon(close, var(--kt-gray-700)); + + span { + display: none; + } + + &:hover { + background-color: var(--kt-primary) !important; + @include svg-bg-icon(close, var(--kt-primary)); + } + } +} + +// Floating label integration +.form-floating { + .form-select { + padding-top: $form-floating-input-padding-t !important; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_sweetalert2.scss b/src/_res/assets/sass/core/vendors/plugins/_sweetalert2.scss new file mode 100644 index 0000000..4dbe6ab --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_sweetalert2.scss @@ -0,0 +1,112 @@ +// +// SweetAlert2 +// + +// Base +html.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown), +body.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown):not(.modal-open) { + overflow-y: initial !important; + + &:not(.sweetalert2-nopadding) { + padding-right: 0 !important; + } +} + +// Popup +.swal2-popup { + background-color: var(--kt-body-bg); + padding: 2rem; + @include border-radius($border-radius); + + .swal2-title { + font-weight: 500; + font-size: 1.3rem; + color: var(--kt-dark); + } + + .swal2-html-container, + .swal2-content { + font-weight: normal; + font-size: 1.1rem; + margin-top: 1.5rem; + color: var(--kt-gray-800); + } + + .btn { + margin: 15px 5px 0; + } + + .swal2-styled { + &:focus { + box-shadow: none; + } + } + + .swal2-actions { + margin: 1.5rem auto 1rem auto; + } +} + +// Container +.swal2-container { + overflow-y: hidden !important; + + &.swal2-shown { + background-color: rgba($black, 0.2); + } + + // Content + .swal2-html-container { + max-height: 200px; + overflow: auto; + } +} + +body.swal2-height-auto { + height: 100% !important; +} + +// State Colors +.swal2-icon { + // Warning + &.swal2-warning { + border-color: var(--kt-warning); + color: var(--kt-warning); + } + + // Error + &.swal2-error { + border-color: var(--kt-danger); + color: var(--kt-danger); + + [class^=swal2-x-mark-line] { + background-color: rgba(var(--kt-danger-rgb), 0.75); + } + } + + // Success + &.swal2-success { + border-color: var(--kt-success); + color: var(--kt-success); + + [class^=swal2-success-line] { + background-color: var(--kt-success); + } + + .swal2-success-ring { + border-color: rgba(var(--kt-success-rgb), 0.3); + } + } + + // Info + &.swal2-info { + border-color: var(--kt-info); + color: var(--kt-info); + } + + // Question + &.swal2-question { + border-color: var(--kt-primary); + color: var(--kt-primary); + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_tagify.scss b/src/_res/assets/sass/core/vendors/plugins/_tagify.scss new file mode 100644 index 0000000..3be65c6 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_tagify.scss @@ -0,0 +1,221 @@ +// +// Tagify +// + +// Bootstrap .form-control sizing integration +$tagify-tag-padding-y-sm: 0.3rem; +$tagify-tag-padding-x-sm: 0.3rem; +$tagify-input-padding-y-sm: #{$input-padding-y-sm - $tagify-tag-padding-y-sm}; + +$tagify-tag-padding-y: 0.4rem; +$tagify-tag-padding-x: 0.4rem; +$tagify-input-padding-y: $input-padding-y - $tagify-tag-padding-y; + +$tagify-tag-padding-y-lg: 0.5rem; +$tagify-tag-padding-x-lg: 0.5rem; +$tagify-input-padding-y-lg: $input-padding-y-lg - $tagify-tag-padding-y-lg; + +// Base +.tagify { + --tagify-dd-bg-color : var(--kt-body-bg); + --tags-border-color : var(--kt-input-border-color); + --tags-hover-border-color : var(--kt-input-border-color); + --tags-focus-border-color : var(--kt-input-focus-border-color); + --tag-bg : var(--kt-gray-200); + --tag-hover : var(--kt-gray-200); + --tag-text-color : var(--kt-gray-700); + --tag-text-color--edit : var(--kt-gray-700); + --tag-pad : 0 0.5rem; + --tag-inset-shadow-size : 1rem; + --tag-invalid-color : var(--kt-danger); + --tag-invalid-bg : var(--kt-danger-light); + --tag-remove-bg : var(--kt-gray-200); + --tag-remove-btn-color : transparent; + --tag-remove-btn-bg : transparent; + --tag-remove-btn-bg--hover : transparent; + --input-color : var(--kt-gray-700); + --placeholder-color : var(--kt-gray-400); + --placeholder-color-focus : var(--kt-gray-500); + --loader-size : .8rem; + + .tagify__tag { + background-color: var(--tag-bg); + margin: 0; + line-height: 1; + + div { + border-radius: inherit; + } + + .tagify__tag-text { + overflow: visible; + } + + .tagify__tag__removeBtn { + width: 0.6rem; + height: 0.6rem; + margin: 0 0.5rem 0 0; + border-radius: 0; + content: " "; + @include svg-bg-icon(close, var(--kt-gray-500)); + + &:after { + display: none; + } + + &:hover { + @include svg-bg-icon(close, var(--kt-primary)); + } + } + + // Not allowed state + &.tagify--notAllowed { + div { + .tagify__tag-text { + color: var(--kt-danger); + opacity: .5; + } + } + + .tagify__tag__removeBtn { + opacity: .5; + @include svg-bg-icon(close, var(--kt-danger)); + + &:hover { + background: transparent; + opacity: .75; + } + } + } + } + + .tagify__input { + margin: 0; + + &:before { + font-size: inherit; + line-height: inherit; + font-weight: inherit; + } + } + + // Sizing + &.form-control { + display: flex; + align-items: center; + gap: 0.25rem; + } + + &.form-control-sm { + border-radius: $btn-border-radius-sm; + min-height: $input-height-sm; + padding-top: $tagify-input-padding-y-sm; + padding-bottom: $tagify-input-padding-y-sm; + + .tagify__tag { + padding: $tagify-tag-padding-y-sm $tagify-tag-padding-x-sm; + border-radius: $btn-border-radius-sm; + + .tagify__tag-text { + font-size: $input-btn-font-size-sm; + } + } + } + + &:not(.form-control-sm):not(.form-control-lg) { + border-radius: $btn-border-radius; + min-height: $input-height; + padding-top: $tagify-input-padding-y; + padding-bottom: $tagify-input-padding-y; + + .tagify__tag { + padding: $tagify-tag-padding-y $tagify-tag-padding-x; + border-radius: $btn-border-radius; + + .tagify__tag-text { + font-size: $input-btn-font-size; + } + } + } + + &.form-control-lg { + border-radius: $btn-border-radius-lg; + min-height: $input-height-lg; + padding-top: $tagify-input-padding-y-lg; + padding-bottom: $tagify-input-padding-y-lg; + + .tagify__tag { + padding: $tagify-tag-padding-y-lg $tagify-tag-padding-x-lg; + border-radius: $btn-border-radius-lg; + + .tagify__tag-text { + font-size: $input-btn-font-size-lg; + } + } + } +} + +// Dropdown +.tagify__dropdown { + box-shadow: var(--kt-dropdown-box-shadow); + border: 0 !important; + outline: none !important; + padding: 0.75rem 0; + z-index: $zindex-dropdown; + background-color: var(--kt-body-bg); + @include border-radius($border-radius); + + // Wrapper + ._wrapper { + max-height: none; + @include border-radius($border-radius); + } + + // In modal + .modal-open & { + z-index: $zindex-modal + 1; + } + + .tagify__dropdown__wrapper { + background-color: var(--kt-body-bg); + border: 0 !important; + outline: none !important; + box-shadow: none; + } + + .tagify__dropdown__item { + color: var(--kt-gray-700); + border-radius: 0; + padding: 0.75rem 1.5rem; + margin: 0; + box-shadow: none; + font-weight: $font-weight-semibold; + + &:hover, + &.tagify__dropdown__item--active { + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + } + } + + // Suggestions + &.tagify__inline__suggestions { + padding: $input-padding-y $input-padding-x; + + .tagify__dropdown__item { + display: inline-block; + font-size: $font-size-sm; + padding: 0.35rem 0.5rem; + margin: 0.25rem 0.5rem 0.25rem 0; + background-color: var(--kt-gray-200); + color: var(--kt-gray-700); + @include border-radius($border-radius); + + &:hover, + &.tagify__dropdown__item--active { + background-color: var(--kt-component-hover-bg); + color: var(--kt-component-hover-color); + } + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_tiny-slider.scss b/src/_res/assets/sass/core/vendors/plugins/_tiny-slider.scss new file mode 100644 index 0000000..c8a6872 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_tiny-slider.scss @@ -0,0 +1,109 @@ +// +// Slider +// + +// Base +.tns { + position: relative; + overflow: hidden; + + [data-tns="true"] { + display: none; + } + + .tns-item { + opacity: 0; + transition: all 0.3s ease; + } + + .tns-controls { + display: flex; + justify-content: center; + align-items: center; + + button { + outline: none; + border: 0; + margin: 0 0.25rem; + @include border-radius($btn-border-radius); + padding: 0.5rem 0.75rem; + background-color: var(--kt-primary); + color: var(--kt-primary-inverse); + + &:hover { + background-color: var(--kt-primary-active); + } + } + } + + .tns-nav { + display: flex; + justify-content: center; + align-items: center; + padding-top: 1.5rem; + padding-bottom: 1.5rem; + + button { + display: block; + outline: none; + width: 1.25rem; + height: 0.75rem; + background-color: var(--kt-gray-200); + margin: 0 0.25rem; + border: 0; + @include border-radius(0.35rem); + + &.tns-nav-active{ + background-color: var(--kt-primary); + } + } + } + + &.tns-initiazlied { + [data-tns="true"] { + display: flex; + } + + .tns-item { + opacity: 1; + transition: all 0.3s ease; + } + } + + // Default + &.tns-default { + position: relative; + + // Navs + [data-controls="prev"], + [data-controls="next"] { + position: absolute; + top: 50%; + transform: translateY(-50%); + } + + [data-controls="prev"] { + left: 0; + } + + [data-controls="next"] { + right: 0; + } + + .tns-outer { + margin: 0 4rem; + + // Tablet mode + @include media-breakpoint-down(md) { + margin: 0 2rem; + } + } + } +} + +// Utils +.tns-hide-disabled-nav { + [disabled] { + display: none !important; + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/_tinymce.scss b/src/_res/assets/sass/core/vendors/plugins/_tinymce.scss new file mode 100644 index 0000000..bc9f624 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_tinymce.scss @@ -0,0 +1,13 @@ +// +// TinyMCE +// + + +// Base +.tox-target{ + display: none; +} + +.tox-tinymce{ + @include border-radius($border-radius !important); +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_toastr.scss b/src/_res/assets/sass/core/vendors/plugins/_toastr.scss new file mode 100644 index 0000000..62d9fc4 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_toastr.scss @@ -0,0 +1,87 @@ +// +// Toastr +// + +// Base +.toastr { + // this is for RTL + background-position: calc(100% - 1.5rem) center !important; + /*rtl:ignore*/ + background-position: 1.5rem center !important; + box-shadow: var(--kt-dropdown-box-shadow) !important; + border-radius: $dropdown-border-radius !important; + border: 0 !important; + background-color: var(--kt-gray-100); + color: var(--kt-gray-700); + padding: 1.25rem 1.25rem 1.25rem 4.5rem !important; + + .toastr-close-button { + outline: none !important; + font-size: 0; + width: 0.85rem; + height: 0.85rem; + } + + // Title + .toastr-title { + font-size: 1.15rem; + font-weight: $font-weight-semibold; + + & + .toastr-message { + margin-top: 0.25rem; + } + } + + // Message + .toastr-message { + font-size: 1rem; + font-weight: $font-weight-normal; + } + + // States + &.toastr-success { + background-color: var(--kt-success); + color: var(--kt-success-inverse); + + .toastr-close-button { + @include svg-bg-icon(close, var(--kt-success-inverse)); + } + } + + &.toastr-info { + background-color: var(--kt-info); + color: var(--kt-info-inverse); + + .toastr-close-button { + @include svg-bg-icon(close, var(--kt-info-inverse)); + } + } + + &.toastr-warning { + background-color: var(--kt-warning); + color: var(--kt-warning-inverse); + + .toastr-close-button { + @include svg-bg-icon(close, var(--kt-warning-inverse)); + } + } + + &.toastr-error { + background-color: var(--kt-danger); + color: var(--kt-danger-inverse); + + .toastr-close-button { + @include svg-bg-icon(close, var(--kt-danger-inverse)); + } + } +} + + +// Placements +.toastr-top-center { + top: 12px; +} + +.toastr-bottom-center { + bottom: 12px; +} \ No newline at end of file diff --git a/src/_res/assets/sass/core/vendors/plugins/_variables.scss b/src/_res/assets/sass/core/vendors/plugins/_variables.scss new file mode 100644 index 0000000..6918d84 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_variables.scss @@ -0,0 +1,35 @@ +// +// 3rd-party config +// + + +// Prismjs +$highlight-bg: #1e1e3f; +$highlight-bg-dark: #151521; + +$highlight-border: rgba($white, 0.1); +$highlight-border-dark: rgba($white, 0.1); + +$highlight-btn-bg: lighten($highlight-bg, 9%); +$highlight-btn-bg-dark: lighten($highlight-bg-dark, 9%); +$highlight-btn-bg-hover: lighten($highlight-bg, 9%); +$highlight-btn-bg-hover-dark: lighten($highlight-bg-dark, 9%); + +$highlight-btn-color: rgba($white, 0.75); +$highlight-btn-color-dark: rgba($white, 0.75); +$highlight-btn-color-hover: $primary; +$highlight-btn-color-hover-dark: $primary; + +$highlight-scrollbar-color: lighten($highlight-bg, 12%); +$highlight-scrollbar-color-dark: lighten($highlight-bg-dark, 12%); +$highlight-scrollbar-hover-color: lighten($highlight-bg, 15%); +$highlight-scrollbar-hover-color-dark: lighten($highlight-bg-dark, 15%); + +// Bootstrap Maxlength +$bootstrap-maxlength-z-index: 1040; + +// Daterangepicker +$daterangepicker-ranges-list-height: 260px; +$daterangepicker-ranges-list-width: 150px; + + diff --git a/src/_res/assets/sass/core/vendors/plugins/_vis-timeline.scss b/src/_res/assets/sass/core/vendors/plugins/_vis-timeline.scss new file mode 100644 index 0000000..1f8e01c --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/_vis-timeline.scss @@ -0,0 +1,131 @@ +// +// Vis Timeline +// + +// Variables +$vis-border-color: var(--kt-border-color); +$vis-border-dashed-color: var(--kt-border-dashed-color); + +// General +.vis-timeline { + border: 1px solid $vis-border-color !important; + + @if ($enable-rounded) { + border-radius: $border-radius !important; + } + + .vis-labelset { + .vis-label { + display: flex; + align-items: center; + padding-left: 1rem; + padding-right: 1rem; + border-bottom: none; + font-size: $h4-font-size; + font-weight: $font-weight-semibold; + color: var(--kt-gray-900); + } + } + + .vis-itemset { + } + + .vis-foreground { + .vis-group { + border-bottom: none; + } + } + + .vis-item { + position: absolute; + color: var(--kt-gray-700); + border-color: var(--kt-primary); + border-width: 1px; + background-color: var(--kt-gray-100); + + @if ($enable-rounded) { + border-radius: $border-radius !important; + } + + &.vis-selected { + background-color: var(--kt-warning-light); + color: var(--kt-gray-700); + border-color: var(--kt-warning); + } + + .vis-item-content { + padding: 0.75rem 1rem; + width: 100%; + transform: none !important; + } + } + + .vis-time-axis { + font-size: $font-size-sm; + text-transform: uppercase; + font-weight: $font-weight-semibold; + + .vis-text { + color: var(--kt-gray-400); + } + + .vis-grid.vis-minor { + border-left-color: $vis-border-dashed-color !important; + } + + .vis-grid.vis-vertical { + border-left-style: dashed !important; + } + } + + .vis-panel { + .vis-shadow { + box-shadow: none !important; + } + } + + .vis-panel { + &.vis-bottom, + &.vis-center, + &.vis-left, + &.vis-right, + &.vis-top { + border-color: $vis-border-color !important; + } + } + + .vis-current-time { + background-color: var(--kt-success); + } +} + +// Custom style +.vis-timeline-custom { + .vis-timeline { + border: 0 !important; + + .vis-label { + padding-left: 0 !important; + } + } + + .vis-panel { + &.vis-bottom, + &.vis-center, + &.vis-left, + &.vis-right, + &.vis-top { + border: 0 !important; + } + } + + .vis-item { + background-color: transparent; + border: 0 !important; + border-radius: 0 !important; + + .vis-item-content { + padding: 0 !important; + } + } +} diff --git a/src/_res/assets/sass/core/vendors/plugins/mixins/_nouislider.scss b/src/_res/assets/sass/core/vendors/plugins/mixins/_nouislider.scss new file mode 100644 index 0000000..455a2b2 --- /dev/null +++ b/src/_res/assets/sass/core/vendors/plugins/mixins/_nouislider.scss @@ -0,0 +1,13 @@ +// +// noUiSlider Mixins +// + +@mixin nouislider-size($height, $handle-width, $handle-height, $handle-pos-top) { + height: $height; + + .noUi-handle { + width: $handle-width; + height: $handle-height; + top: -#{$handle-pos-top}; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/_content.scss b/src/_res/assets/sass/layout/_content.scss new file mode 100644 index 0000000..0aebeaa --- /dev/null +++ b/src/_res/assets/sass/layout/_content.scss @@ -0,0 +1,21 @@ +// +// Content +// + +// Desktop mode +@include media-breakpoint-up(lg) { + .app-content { + [data-kt-app-toolbar-enabled="true"]:not([data-kt-app-toolbar-fixed="true"]) & { + padding-top: 0; + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .app-content { + [data-kt-app-toolbar-enabled="true"]:not([data-kt-app-toolbar-fixed-mobile="true"]) & { + padding-top: 0; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/_layout.scss b/src/_res/assets/sass/layout/_layout.scss new file mode 100644 index 0000000..1ee48df --- /dev/null +++ b/src/_res/assets/sass/layout/_layout.scss @@ -0,0 +1,15 @@ +// +// Layout +// + +@import "root"; +@import "sidebar/sidebar"; +@import "sidebar/sidebar-minimize"; +@import "sidebar/sidebar-dark"; +@import "sidebar/sidebar-light"; +@import "header/header"; +@import "header/header-dark"; +@import "header/header-sidebar-light"; +@import "content"; +@import "toolbar"; +@import "page-title"; \ No newline at end of file diff --git a/src/_res/assets/sass/layout/_page-title.scss b/src/_res/assets/sass/layout/_page-title.scss new file mode 100644 index 0000000..f345706 --- /dev/null +++ b/src/_res/assets/sass/layout/_page-title.scss @@ -0,0 +1,14 @@ +// +// Page Title(used by Dark Header layout only) +// + +// Desktop mode +@include media-breakpoint-up(lg) { + [data-kt-app-layout="dark-header"] { + .app-header { + .page-heading { + color: $white !important; + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/_root.scss b/src/_res/assets/sass/layout/_root.scss new file mode 100644 index 0000000..8eab1bd --- /dev/null +++ b/src/_res/assets/sass/layout/_root.scss @@ -0,0 +1,89 @@ +// +// Root +// + +// Light mode +@include theme-light() { + // Reboot + --kt-app-bg-color: #{$app-bg-color}; + --kt-app-blank-bg-color: #{$app-blank-bg-color}; + + // Header base + --kt-app-header-base-bg-color: #{$app-header-base-bg-color}; + --kt-app-header-base-bg-color-mobile: #{$app-header-base-bg-color-mobile}; + --kt-app-header-base-box-shadow: #{$app-header-base-box-shadow}; + --kt-app-header-base-box-shadow-mobile: #{$app-header-base-box-shadow-mobile}; + --kt-app-header-base-menu-link-bg-color-active: #{$app-header-base-menu-link-bg-color-active}; + + // Header light + --kt-app-header-light-separator-color: #{$app-header-light-separator-color}; + + // Sidebar base + --kt-app-sidebar-base-toggle-btn-box-shadow: #{$app-sidebar-base-toggle-btn-box-shadow}; + --kt-app-sidebar-base-toggle-btn-bg-color: #{$app-sidebar-base-toggle-btn-bg-color}; + + // Sidebar light + --kt-app-sidebar-light-bg-color: #{$app-sidebar-light-bg-color}; + --kt-app-sidebar-light-box-shadow: #{$app-sidebar-light-box-shadow}; + --kt-app-sidebar-light-separator-color: #{$app-sidebar-light-separator-color}; + --kt-app-sidebar-light-scrollbar-color: #{$app-sidebar-light-scrollbar-color}; + --kt-app-sidebar-light-scrollbar-color-hover: #{$app-sidebar-light-scrollbar-color-hover}; + --kt-app-sidebar-light-menu-heading-color: #{$app-sidebar-light-menu-heading-color}; + --kt-app-sidebar-light-menu-link-bg-color-active: #{$app-sidebar-light-menu-link-bg-color-active}; + --kt-app-sidebar-light-header-menu-link-bg-color-active: #{$app-sidebar-light-header-menu-link-bg-color-active}; + + // Toolbar base + --kt-app-toolbar-base-bg-color: #{$app-toolbar-base-bg-color}; + --kt-app-toolbar-base-bg-color-mobile: #{$app-toolbar-base-bg-color-mobile}; + --kt-app-toolbar-base-box-shadow: #{$app-toolbar-base-box-shadow}; + --kt-app-toolbar-base-box-shadow-mobile: #{$app-toolbar-base-box-shadow-mobile}; + --kt-app-toolbar-base-border-top: #{$app-toolbar-base-border-top}; + --kt-app-toolbar-base-border-top-mobile: #{$app-toolbar-base-border-top-mobile}; + + // Footer + --kt-app-footer-bg-color: #{$app-footer-bg-color}; + --kt-app-footer-bg-color-mobile: #{$app-footer-bg-color-mobile}; +} + +// Dark mode +@include theme-dark() { + // Reboot + --kt-app-bg-color: #{$app-bg-color-dark}; + --kt-app-blank-bg-color: #{$app-blank-bg-color-dark}; + + // Header base + --kt-app-header-base-bg-color: #{$app-header-base-bg-color-dark}; + --kt-app-header-base-bg-color-mobile: #{$app-header-base-bg-color-mobile-dark}; + --kt-app-header-base-box-shadow: #{$app-header-base-box-shadow-dark}; + --kt-app-header-base-box-shadow-mobile: #{$app-header-base-box-shadow-mobile-dark}; + --kt-app-header-base-menu-link-bg-color-active: #{$app-header-base-menu-link-bg-color-active-dark}; + + // Header light + --kt-app-header-light-separator-color: #{$app-header-light-separator-color-dark}; + + // Sidebar base + --kt-app-sidebar-base-toggle-btn-box-shadow: #{$app-sidebar-base-toggle-btn-box-shadow-dark}; + --kt-app-sidebar-base-toggle-btn-bg-color: #{$app-sidebar-base-toggle-btn-bg-color-dark}; + + // Sidebar light + --kt-app-sidebar-light-bg-color: #{$app-sidebar-light-bg-color-dark}; + --kt-app-sidebar-light-box-shadow: #{$app-sidebar-light-box-shadow-dark}; + --kt-app-sidebar-light-separator-color: #{$app-sidebar-light-separator-color-dark}; + --kt-app-sidebar-light-scrollbar-color: #{$app-sidebar-light-scrollbar-color-dark}; + --kt-app-sidebar-light-scrollbar-color-hover: #{$app-sidebar-light-scrollbar-color-hover-dark}; + --kt-app-sidebar-light-menu-heading-color: #{$app-sidebar-light-menu-heading-color-dark}; + --kt-app-sidebar-light-menu-link-bg-color-active: #{$app-sidebar-light-menu-link-bg-color-active-dark}; + --kt-app-sidebar-light-header-menu-link-bg-color-active: #{$app-sidebar-light-header-menu-link-bg-color-active-dark}; + + // Toolbar base + --kt-app-toolbar-base-bg-color: #{$app-toolbar-base-bg-color-dark}; + --kt-app-toolbar-base-bg-color-mobile: #{$app-toolbar-base-bg-color-mobile-dark}; + --kt-app-toolbar-base-box-shadow: #{$app-toolbar-base-box-shadow-dark}; + --kt-app-toolbar-base-box-shadow-mobile: #{$app-toolbar-base-box-shadow-mobile-dark}; + --kt-app-toolbar-base-border-top: #{$app-toolbar-base-border-top-dark}; + --kt-app-toolbar-base-border-top-mobile: #{$app-toolbar-base-border-top-mobile-dark}; + + // Footer + --kt-app-footer-bg-color: #{$app-footer-bg-color-dark}; + --kt-app-footer-bg-color-mobile: #{$app-footer-bg-color-mobile-dark}; +} diff --git a/src/_res/assets/sass/layout/_toolbar.scss b/src/_res/assets/sass/layout/_toolbar.scss new file mode 100644 index 0000000..6b6dd12 --- /dev/null +++ b/src/_res/assets/sass/layout/_toolbar.scss @@ -0,0 +1,38 @@ +// +// Toolbar +// + +// Form controls +:is([data-kt-app-layout="light-sidebar"], [data-kt-app-layout="light-header"], [data-kt-app-layout="dark-header"]) { + .app-toolbar { + .form-select.form-select { + background-color: var(--kt-body-bg) !important; + } + } +} + +// Desktop mode +@include media-breakpoint-up(lg) { + .app-toolbar { + body:not([data-kt-app-toolbar-fixed="true"]) & { + height: auto; + background-color: transparent; + border-top: 0; + border-bottom: 0; + box-shadow: none; + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .app-toolbar { + body:not([data-kt-app-toolbar-fixed-mobile="true"]) & { + height: auto; + background-color: transparent; + border-top: 0; + border-bottom: 0; + box-shadow: none; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/_variables.custom.scss b/src/_res/assets/sass/layout/_variables.custom.scss new file mode 100644 index 0000000..ab486ed --- /dev/null +++ b/src/_res/assets/sass/layout/_variables.custom.scss @@ -0,0 +1,111 @@ +// +// Variables +// + +// Reboot +$app-bg-color: #f5f8fa; +$app-bg-color-dark: #151521; +$app-blank-bg-color: $white; +$app-blank-bg-color-dark: $app-bg-color-dark; + +// Header base +$app-header-base-height: 70px; +$app-header-base-height-mobile: 60px; +$app-header-base-bg-color: $body-bg; +$app-header-base-bg-color-dark: #1e1e2d; +$app-header-base-bg-color-mobile: $app-header-base-bg-color; +$app-header-base-bg-color-mobile-dark: $app-header-base-bg-color-dark; +$app-header-base-box-shadow: 0px 10px 30px 0px rgba(82,63,105,0.05); +$app-header-base-box-shadow-dark: none; +$app-header-base-box-shadow-mobile: $app-header-base-box-shadow; +$app-header-base-box-shadow-mobile-dark: $app-header-base-box-shadow-dark; +$app-header-base-menu-link-bg-color-active: $menu-link-bg-color-active; +$app-header-base-menu-link-bg-color-active-dark: #2A2A3C; + +// Header light +$app-header-light-separator-color: #E4E6EF; +$app-header-light-separator-color-dark: $border-color-dark; + +// Header dark +$app-header-dark-bg-color: #1e1e2d; +$app-header-dark-separator-color: #282a3d; +$app-header-dark-scrollbar-color: #3b3b64; +$app-header-dark-scrollbar-color-hover: lighten($app-header-dark-scrollbar-color, 3%); + +// Sidebar base +$app-sidebar-base-width: 265px; +$app-sidebar-base-width-mobile: 250px; + +$app-sidebar-base-toggle-btn-box-shadow: 0px 0px 10px rgba(113, 121, 136, 0.1); +$app-sidebar-base-toggle-btn-box-shadow-dark: none; +$app-sidebar-base-toggle-btn-bg-color: $body-bg; +$app-sidebar-base-toggle-btn-bg-color-dark: $app-header-base-menu-link-bg-color-active-dark; + +// Sidebar minimize +$app-sidebar-minimize-width: 75px; + +// Sidebar light +$app-sidebar-light-bg-color: $body-bg; +$app-sidebar-light-bg-color-dark: #1e1e2d; + +$app-sidebar-light-box-shadow: 0 0 28px 0 rgba(82,63,105,.05); +$app-sidebar-light-box-shadow-dark: none; + +$app-sidebar-light-separator-color: $app-header-light-separator-color; +$app-sidebar-light-separator-color-dark: $app-header-light-separator-color-dark; + +$app-sidebar-light-scrollbar-color: $gray-200; +$app-sidebar-light-scrollbar-color-dark: $gray-200-dark; +$app-sidebar-light-scrollbar-color-hover: $gray-200; +$app-sidebar-light-scrollbar-color-hover-dark: $gray-200-dark; +$app-sidebar-light-menu-heading-color: #B5B5C3; +$app-sidebar-light-menu-heading-color-dark: $gray-500-dark; +$app-sidebar-light-menu-link-bg-color-active: #F4F6FA; +$app-sidebar-light-menu-link-bg-color-active-dark: #2A2A3C; +$app-sidebar-light-header-menu-link-bg-color-active: #EAEEF2; +$app-sidebar-light-header-menu-link-bg-color-active-dark: $gray-100-dark; + +// Sidebar dark +$app-sidebar-dark-bg-color: #1e1e2d; +$app-sidebar-dark-separator-color: #393945; +$app-sidebar-dark-scrollbar-color: $gray-300-dark; +$app-sidebar-dark-scrollbar-color-hover: $gray-300-dark; +$app-sidebar-dark-menu-heading-color: #646477; +$app-sidebar-dark-menu-link-bg-color-active: #2A2A3C; + +// Toolbar base +$app-toolbar-base-height: 55px; +$app-toolbar-base-bg-color:$body-bg; +$app-toolbar-base-bg-color-dark: darken(#1e1e2d, 2%); +$app-toolbar-base-bg-color-mobile: $app-toolbar-base-bg-color; +$app-toolbar-base-bg-color-mobile-dark: $app-toolbar-base-bg-color-dark; +$app-toolbar-base-box-shadow: 0px 10px 30px 0px rgba(82,63,105,0.05); +$app-toolbar-base-box-shadow-dark: none; +$app-toolbar-base-box-shadow-mobile: $app-toolbar-base-box-shadow; +$app-toolbar-base-box-shadow-mobile-dark: $app-toolbar-base-box-shadow-mobile; +$app-toolbar-base-border-top: 1px solid $border-color; +$app-toolbar-base-border-top-dark: 0; +$app-toolbar-base-border-top-mobile: $app-toolbar-base-border-top; +$app-toolbar-base-border-top-mobile-dark: $app-toolbar-base-border-top-mobile; + +// Footer +$app-footer-height: 60px; +$app-footer-height-mobile: auto; +$app-footer-bg-color: $body-bg; +$app-footer-bg-color-dark: #1e1e2d; +$app-footer-bg-color-mobile: $app-footer-bg-color; +$app-footer-bg-color-mobile-dark: $app-footer-bg-color-dark; + +// Scrolltop +$scrolltop-bottom: 43px; +$scrolltop-bottom-mobile: 23px; +$scrolltop-end: 7px; +$scrolltop-end-mobile: 5px; + +// Layout builder toggle(used for Demo purposes only) +$app-layout-builder-toggle-end: 50px; +$app-layout-builder-toggle-end-mobile: 40px; +$app-layout-builder-toggle-bottom: 40px; +$app-layout-builder-toggle-bottom-mobile: 20px; + + diff --git a/src/_res/assets/sass/layout/header/_header-dark.scss b/src/_res/assets/sass/layout/header/_header-dark.scss new file mode 100644 index 0000000..3fd8699 --- /dev/null +++ b/src/_res/assets/sass/layout/header/_header-dark.scss @@ -0,0 +1,80 @@ +// +// Dark Header(used by Dark Header layout only) +// + +[data-kt-app-layout="dark-header"] { + .app-header { + background-color: $app-header-dark-bg-color; + border-bottom: 0 !important; + + .btn-custom { + @include button-custom-variant( + $color:#B5B5C3, + $icon-color: #B5B5C3, + $border-color: null, + $bg-color: null, + $color-active: #B5B5C3, + $icon-color-active: var(--kt-primary), + $border-color-active: null, + $bg-color-active: rgba(63, 66, 84, 0.35) + ); + } + } + + // Desktop mode + @include media-breakpoint-up(lg) { + // General mode + .app-header-menu { + .menu { + // Menu root links + > .menu-item { + @include menu-link-default-state( + $title-color: #9D9DA6, + $icon-color:#C5C5D8, + $bullet-color:#787887, + $arrow-color: #787887, + $bg-color: null, + $all-links: false + ); + + @include menu-link-hover-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: $app-sidebar-dark-menu-link-bg-color-active, + $all-links: false + ); + + @include menu-link-show-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: null, + $all-links: false + ); + + @include menu-link-here-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: $app-sidebar-dark-menu-link-bg-color-active, + $all-links: false + ); + + @include menu-link-active-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: $app-sidebar-dark-menu-link-bg-color-active, + $all-links: false + ); + } + } + } + } +} + diff --git a/src/_res/assets/sass/layout/header/_header-sidebar-light.scss b/src/_res/assets/sass/layout/header/_header-sidebar-light.scss new file mode 100644 index 0000000..db38db8 --- /dev/null +++ b/src/_res/assets/sass/layout/header/_header-sidebar-light.scss @@ -0,0 +1,55 @@ +// +// Custom Header(used by Light Sidebar layout only) +// + +[data-kt-app-layout="light-sidebar"] { + // Desktop mode + @include media-breakpoint-up(lg) { + .app-header-menu { + .menu { + // Menu root item + > .menu-item { + @include menu-link-here-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: var(--kt-app-sidebar-light-header-menu-link-bg-color-active), + $all-links: false + ); + + @include menu-link-active-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: var(--kt-app-sidebar-light-header-menu-link-bg-color-active), + $all-links: false + ); + } + } + } + } +} + +// Desktop mode +@include media-breakpoint-up(lg) { + [data-kt-app-layout="light-sidebar"]:not([data-kt-app-header-fixed="true"]) { + .app-header { + background-color: transparent; + box-shadow: none; + border-bottom: 1px solid var(--kt-app-sidebar-light-separator-color); + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + [data-kt-app-layout="light-sidebar"]:not([data-kt-app-header-fixed-mobile="true"]) { + .app-header { + background-color: transparent; + box-shadow: none; + border-bottom: 1px solid var(--kt-app-sidebar-light-separator-color); + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/header/_header.scss b/src/_res/assets/sass/layout/header/_header.scss new file mode 100644 index 0000000..693134d --- /dev/null +++ b/src/_res/assets/sass/layout/header/_header.scss @@ -0,0 +1,104 @@ +// +// Header +// + +// General mode +.app-header-menu { + .menu { + .menu-item { + @include menu-link-default-state( + $title-color: var(--kt-gray-700), + $icon-color: var(--kt-gray-500), + $bullet-color: var(--kt-gray-500), + $arrow-color: var(--kt-gray-500), + $bg-color: null, + ); + + @include menu-link-hover-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: var(--kt-menu-link-bg-color-active) + ); + + @include menu-link-show-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: null, + ); + + @include menu-link-here-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: var(--kt-menu-link-bg-color-active) + ); + + @include menu-link-active-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: var(--kt-menu-link-bg-color-active) + ); + } + } + + .menu-extended { + --kt-menu-link-bg-color-active: rgba(var(--kt-gray-100-rgb), 0.7); + --kt-menu-link-bg-color-hover: rgba(var(--kt-gray-100-rgb), 0.7); + + + .menu-custom-icon { + background-color: var(--kt-gray-100); + } + + .menu-link { + &.active, + &:hover { + .menu-custom-icon { + background-color: var(--kt-gray-200); + } + } + } + } +} + +// Desktop mode +@include media-breakpoint-up(lg) { + .app-header-menu { + .menu { + // Menu root item + > .menu-item { + margin-right: 0.5rem; + + > .menu-link { + padding-top: 0.775rem; + padding-bottom: 0.775rem; + font-weight: $font-weight-semibold; + } + + @include menu-link-here-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: var(--kt-app-header-base-menu-link-bg-color-active) + ); + } + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .app-header { + .page-title { + display: none !important; + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/sidebar/_sidebar-dark.scss b/src/_res/assets/sass/layout/sidebar/_sidebar-dark.scss new file mode 100644 index 0000000..360a232 --- /dev/null +++ b/src/_res/assets/sass/layout/sidebar/_sidebar-dark.scss @@ -0,0 +1,79 @@ +// +// Dark Sidebar(used by Dark Sidebar layout only) +// + +[data-kt-app-layout="dark-sidebar"] { + .app-sidebar { + background-color: $app-sidebar-dark-bg-color; + border-right: 0 !important; + + .hover-scroll-overlay-y { + @include scrollbar-color($app-sidebar-dark-scrollbar-color, $app-sidebar-dark-scrollbar-color-hover); + } + + .app-sidebar-logo { + border-bottom: 1px dashed $app-sidebar-dark-separator-color; + } + + .btn-custom { + @include button-custom-variant( + $color:#B5B5C3, + $icon-color: #B5B5C3, + $border-color: null, + $bg-color: rgba(63, 66, 84, 0.35), + $color-active: #B5B5C3, + $icon-color-active: null, + $border-color-active: null, + $bg-color-active: rgba(63, 66, 84, 0.35) + ); + } + + .menu { + .menu-item { + .menu-heading { + color: $app-sidebar-dark-menu-heading-color !important; + } + + @include menu-link-default-state( + $title-color: #9D9DA6, + $icon-color:#C5C5D8, + $bullet-color:#787887, + $arrow-color: #787887, + $bg-color: null + ); + + @include menu-link-hover-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: null + ); + + @include menu-link-here-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: null + ); + + @include menu-link-show-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: null + ); + + @include menu-link-active-state( + $title-color: var(--kt-primary-inverse), + $icon-color: var(--kt-primary-inverse), + $bullet-color: var(--kt-primary-inverse), + $arrow-color: var(--kt-primary-inverse), + $bg-color: $app-sidebar-dark-menu-link-bg-color-active + ); + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/sidebar/_sidebar-light.scss b/src/_res/assets/sass/layout/sidebar/_sidebar-light.scss new file mode 100644 index 0000000..ab0bd0e --- /dev/null +++ b/src/_res/assets/sass/layout/sidebar/_sidebar-light.scss @@ -0,0 +1,76 @@ +// +// Light Sidebar(used by Light Sidebar layout only) +// + +[data-kt-app-layout="light-sidebar"] { + .app-sidebar { + background-color: var(--kt-app-sidebar-light-bg-color); + border-right: 0 !important; + + .hover-scroll-overlay-y { + @include scrollbar-color(var(--kt-app-sidebar-light-scrollbar-color), var(--kt-app-sidebar-light-scrollbar-color-hover)); + } + + .app-sidebar-logo { + border-bottom: 1px solid var(--kt-app-sidebar-light-separator-color); + } + + .menu { + font-weight: $font-weight-semibold; + + .menu-item { + .menu-heading { + color: var(--kt-app-sidebar-light-menu-heading-color) !important; + } + + @include menu-link-default-state( + $title-color: var(--kt-gray-700), + $icon-color: var(--kt-gray-500), + $bullet-color: var(--kt-gray-500), + $arrow-color: var(--kt-gray-500), + $bg-color: null + ); + + @include menu-link-hover-state( + $title-color: var(--kt-gray-900), + $icon-color: var(--kt-gray-700), + $bullet-color: var(--kt-gray-700), + $arrow-color: var(--kt-gray-700), + $bg-color: null + ); + + @include menu-link-show-state( + $title-color: var(--kt-gray-900), + $icon-color: var(--kt-gray-700), + $bullet-color: var(--kt-gray-700), + $arrow-color: var(--kt-gray-700), + $bg-color: null + ); + + @include menu-link-here-state( + $title-color: var(--kt-gray-900), + $icon-color: var(--kt-gray-700), + $bullet-color: var(--kt-gray-700), + $arrow-color: var(--kt-gray-700), + $bg-color: null + ); + + @include menu-link-active-state( + $title-color: var(--kt-primary), + $icon-color: var(--kt-primary), + $bullet-color: var(--kt-primary), + $arrow-color: var(--kt-primary), + $bg-color: var(--kt-app-sidebar-light-menu-link-bg-color-active) + ); + } + } + } +} + +[data-kt-app-layout="light-sidebar"][data-kt-app-header-fixed="true"] { + .app-sidebar { + .app-sidebar-logo { + border-bottom: 1px dashed var(--kt-app-sidebar-light-separator-color); + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/sidebar/_sidebar-minimize.scss b/src/_res/assets/sass/layout/sidebar/_sidebar-minimize.scss new file mode 100644 index 0000000..99d3481 --- /dev/null +++ b/src/_res/assets/sass/layout/sidebar/_sidebar-minimize.scss @@ -0,0 +1,64 @@ +// +// Sidebar Minimize +// + +.app-sidebar-logo-minimize { + display: none; +} + +// Sidebar footer +.app-sidebar-footer { + .btn-custom { + .btn-icon { + display: none; + } + } +} + +// Desktop sidebar minimize mode +@include app-layout-minimize(app-sidebar) { + .app-sidebar-logo { + .app-sidebar-logo-default { + display: none; + } + + .app-sidebar-logo-minimize { + display: inline-block; + } + } + + .app-sidebar-wrapper { + width: var(--kt-app-sidebar-width-actual); + } + + .app-sidebar-menu { + .menu-content, + .menu-title { + opacity: 0; + @include app-layout-transition(opacity); + } + + .menu-item.show > .menu-sub { + height: 0; + overflow: hidden; + @include app-layout-transition(height); + } + } + + .app-sidebar-footer { + .btn-custom { + padding-left: 0 !important; + padding-right: 0 !important; + + .btn-label { + width: 0; + display: none; + } + + .btn-icon { + width: auto; + display: block; + } + } + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/layout/sidebar/_sidebar.scss b/src/_res/assets/sass/layout/sidebar/_sidebar.scss new file mode 100644 index 0000000..481890e --- /dev/null +++ b/src/_res/assets/sass/layout/sidebar/_sidebar.scss @@ -0,0 +1,51 @@ +// +// Sidebar +// + +// Desktop mode +@include media-breakpoint-up(lg) { + .app-sidebar-toggle { + box-shadow: var(--kt-app-sidebar-base-toggle-btn-box-shadow) !important; + background-color: var(--kt-app-sidebar-base-toggle-btn-bg-color) !important; + + .active .svg-icon { + transform: rotateZ(0deg) !important; + } + } + + [dir="rtl"] { + .app-sidebar-toggle { + .svg-icon { + transform: rotateZ(180deg); + } + + &.active .svg-icon { + transform: rotateZ(0deg) !important; + } + } + } + + .app-sidebar-logo { + height: var(--kt-app-header-height); + display: flex; + align-items: center; + justify-content: space-between; + position: relative; + flex-shrink: 0; + } + + .app-sidebar-menu { + .menu { + & > .menu-item { + margin-left: 0.115rem; + } + } + } +} + +// Tablet & mobile modes +@include media-breakpoint-down(lg) { + .app-sidebar-logo { + display: none; + } +} \ No newline at end of file diff --git a/src/_res/assets/sass/plugins.scss b/src/_res/assets/sass/plugins.scss new file mode 100644 index 0000000..e25c213 --- /dev/null +++ b/src/_res/assets/sass/plugins.scss @@ -0,0 +1,13 @@ +// +// Vendors customization +// + +//////////////////////////////////////////////////////////////// +///////////// DO NOT MODIFY BELOW INCLUDE ORDER //////////////// +//////////////////////////////////////////////////////////////// + +// Initialize +@import "init"; + +// Plugins +@import "./core/vendors/plugins/plugins"; diff --git a/src/_res/assets/sass/style.react.scss b/src/_res/assets/sass/style.react.scss new file mode 100644 index 0000000..67306fc --- /dev/null +++ b/src/_res/assets/sass/style.react.scss @@ -0,0 +1,7 @@ +// React vendors +@import '~socicon/css/socicon.css'; +@import '~@fortawesome/fontawesome-free/css/all.min.css'; +@import '~line-awesome/dist/line-awesome/css/line-awesome.css'; +@import '~prism-themes/themes/prism-shades-of-purple.css'; +@import '~bootstrap-icons/font/bootstrap-icons.css'; +@import '~animate.css/animate.css'; diff --git a/src/_res/assets/sass/style.scss b/src/_res/assets/sass/style.scss new file mode 100644 index 0000000..ae464dd --- /dev/null +++ b/src/_res/assets/sass/style.scss @@ -0,0 +1,14 @@ +// +// Theme style +// + +// Initialize +@import "init"; + +// Components +@import "./core/components/components"; +@import "components/components"; + +// Layout +@import "./core/layout/base/layout"; +@import "layout/layout"; \ No newline at end of file diff --git a/src/_res/assets/ts/_utils/DomHelpers.ts b/src/_res/assets/ts/_utils/DomHelpers.ts new file mode 100644 index 0000000..a98a203 --- /dev/null +++ b/src/_res/assets/ts/_utils/DomHelpers.ts @@ -0,0 +1,478 @@ +import {OffsetModel} from './models/OffsetModel' +import {ViewPortModel} from './models/ViewPortModel' +import {ElementStyleUtil} from './_ElementStyleUtil' +import {DataUtil} from './_DataUtil' +import {ElementAnimateUtil} from './ElementAnimateUtil' +import {getObjectPropertyValueByKey, toJSON} from './_TypesHelpers' + +function getCSS(el: HTMLElement, styleProp: string) { + const defaultView = (el.ownerDocument || document).defaultView + + if (!defaultView) { + return '' + } + + // sanitize property name to css notation + // (hyphen separated words eg. font-Size) + styleProp = styleProp.replace(/([A-Z])/g, '-$1').toLowerCase() + + return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp) +} + +function getCSSVariableValue(variableName: string) { + let hex = getComputedStyle(document.documentElement).getPropertyValue(variableName) + if (hex && hex.length > 0) { + hex = hex.trim() + } + + return hex +} + +function getElementActualCss(el: HTMLElement, prop: any, cache: boolean) { + let css = '' + + if (!el.getAttribute('kt-hidden-' + prop) || cache === false) { + let value + + // the element is hidden so: + // making the el block so we can meassure its height but still be hidden + css = el.style.cssText + el.style.cssText = 'position: absolute; visibility: hidden; display: block;' + + if (prop === 'width') { + value = el.offsetWidth + } else if (prop === 'height') { + value = el.offsetHeight + } + + el.style.cssText = css + + // store it in cache + if (value !== undefined) { + el.setAttribute('kt-hidden-' + prop, value.toString()) + return parseFloat(value.toString()) + } + return 0 + } else { + // store it in cache + const attributeValue = el.getAttribute('kt-hidden-' + prop) + if (attributeValue || attributeValue === '0') { + return parseFloat(attributeValue) + } + } +} + +function getElementActualHeight(el: HTMLElement) { + return getElementActualCss(el, 'height', false) +} + +function getElementActualWidth(el: HTMLElement, cache?: boolean) { + return getElementActualCss(el, 'width', false) +} + +function getElementIndex(element: HTMLElement) { + if (element.parentNode) { + const c = element.parentNode.children + for (let i = 0; i < c.length; i++) { + if (c[i] === element) return i + } + } + return -1 +} + +// https://developer.mozilla.org/en-US/docs/Web/API/Element/matches +function getElementMatches(element: HTMLElement, selector: string) { + const p = Element.prototype + const f = p.matches || p.webkitMatchesSelector + + if (element && element.tagName) { + return f.call(element, selector) + } else { + return false + } +} + +function getElementOffset(el: HTMLElement): OffsetModel { + // Return zeros for disconnected and hidden (display: none) elements (gh-2310) + // Support: IE <=11 only + // Running getBoundingClientRect on a + // disconnected node in IE throws an error + if (!el.getClientRects().length) { + return {top: 0, left: 0} + } + + // Get document-relative position by adding viewport scroll to viewport-relative gBCR + const rect = el.getBoundingClientRect() + const win = el.ownerDocument.defaultView + if (win) { + return { + top: rect.top + win.pageYOffset, + left: rect.left + win.pageXOffset, + } + } + + return rect +} + +function getElementParents(element: Element, selector: string) { + // Element.matches() polyfill + if (!Element.prototype.matches) { + Element.prototype.matches = function (s) { + const matches = (document || this.ownerDocument).querySelectorAll(s) + let i = matches.length + while (--i >= 0 && matches.item(i) !== this) {} + return i > -1 + } + } + + // Set up a parent array + const parents: Array = [] + + let el: Element | null = element + + // Push each parent element to the array + for (; el && el !== document.body; el = el.parentElement) { + if (selector) { + if (el.matches(selector)) { + parents.push(el) + } + continue + } + parents.push(el) + } + + // Return our parent array + return parents +} + +function getHighestZindex(el: HTMLElement) { + let bufferNode: Node | null = el as Node + let buffer = el + while (bufferNode && bufferNode !== document) { + // Ignore z-index if position is set to a value where z-index is ignored by the browser + // This makes behavior of this function consistent across browsers + // WebKit always returns auto if the element is positioned + const position = buffer.style.getPropertyValue('position') + if (position === 'absolute' || position === 'relative' || position === 'fixed') { + // IE returns 0 when zIndex is not specified + // other browsers return a string + // we ignore the case of nested elements with an explicit value of 0 + //
+ const value = parseInt(buffer.style.getPropertyValue('z-index')) + if (!isNaN(value) && value !== 0) { + return value + } + } + + bufferNode = bufferNode.parentNode + buffer = bufferNode as HTMLElement + } + return null +} + +function getScrollTop(): number { + return (document.scrollingElement || document.documentElement).scrollTop +} + +// https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth +function getViewPort(): ViewPortModel { + return { + width: window.innerWidth, + height: window.innerHeight, + } +} + +function insertAfterElement(el: HTMLElement, referenceNode: HTMLElement) { + return referenceNode.parentNode?.insertBefore(el, referenceNode.nextSibling) +} + +function isElementHasClasses(element: HTMLElement, classesStr: string): boolean { + const classes = classesStr.split(' ') + for (let i = 0; i < classes.length; i++) { + if (!element.classList.contains(classes[i])) { + return false + } + } + + return true +} + +function isVisibleElement(element: HTMLElement): boolean { + return !(element.offsetWidth === 0 && element.offsetHeight === 0) +} + +// Throttle function: Input as function which needs to be throttled and delay is the time interval in milliseconds +function throttle(timer: number | undefined, func: Function, delay?: number) { + // If setTimeout is already scheduled, no need to do anything + if (timer) { + return + } + + // Schedule a setTimeout after delay seconds + timer = window.setTimeout(function () { + func() + + // Once setTimeout function execution is finished, timerId = undefined so that in
+ // the next scroll event function execution can be scheduled by the setTimeout + timer = undefined + }, delay) +} + +function getElementChildren(element: HTMLElement, selector: string): Array | null { + if (!element || !element.childNodes) { + return null + } + + const result: Array = [] + for (let i = 0; i < element.childNodes.length; i++) { + const child = element.childNodes[i] + // child.nodeType == 1 => Element, Text, Comment, ProcessingInstruction, CDATASection, EntityReference + if (child.nodeType === 1 && getElementMatches(child as HTMLElement, selector)) { + result.push(child as HTMLElement) + } + } + + return result +} + +function getElementChild(element: HTMLElement, selector: string): HTMLElement | null { + const children = getElementChildren(element, selector) + return children ? children[0] : null +} + +function isMobileDevice(): boolean { + let test = getViewPort().width < +getBreakpoint('lg') ? true : false + + if (test === false) { + // For use within normal web clients + test = navigator.userAgent.match(/iPad/i) != null + } + + return test +} + +function slide(el: HTMLElement, dir: string, speed: number, callback: any) { + if ( + !el || + (dir === 'up' && isVisibleElement(el) === false) || + (dir === 'down' && isVisibleElement(el) === true) + ) { + return + } + + speed = speed ? speed : 600 + let calcHeight = getElementActualHeight(el) + let calcPaddingTop: number = 0 + let calcPaddingBottom: number = 0 + + if (ElementStyleUtil.get(el, 'padding-top') && DataUtil.get(el, 'slide-padding-top') !== true) { + DataUtil.set(el, 'slide-padding-top', ElementStyleUtil.get(el, 'padding-top')) + } + + if ( + ElementStyleUtil.get(el, 'padding-bottom') && + DataUtil.has(el, 'slide-padding-bottom') !== true + ) { + DataUtil.set(el, 'slide-padding-bottom', ElementStyleUtil.get(el, 'padding-bottom')) + } + + if (DataUtil.has(el, 'slide-padding-top')) { + const data = DataUtil.get(el, 'slide-padding-top') as string + calcPaddingTop = parseInt(data as string) + } + + if (DataUtil.has(el, 'slide-padding-bottom')) { + const data = DataUtil.get(el, 'slide-padding-bottom') as string + calcPaddingBottom = parseInt(data) + } + + if (dir === 'up') { + // up + el.style.cssText = 'display: block; overflow: hidden;' + + if (calcPaddingTop) { + ElementAnimateUtil.animate(0, calcPaddingTop, speed, function (value: number) { + el.style.paddingTop = calcPaddingTop - value + 'px' + }) + } + + if (calcPaddingBottom) { + ElementAnimateUtil.animate(0, calcPaddingBottom, speed, function (value: number) { + el.style.paddingBottom = calcPaddingBottom - value + 'px' + }) + } + + ElementAnimateUtil.animate( + 0, + calcHeight || 0, + speed, + function (value: number) { + el.style.height = (calcHeight || 0) - value + 'px' + }, + function () { + el.style.height = '' + el.style.display = 'none' + + if (typeof callback === 'function') { + callback() + } + } + ) + } else if (dir === 'down') { + // down + el.style.cssText = 'display: block; overflow: hidden;' + + if (calcPaddingTop) { + ElementAnimateUtil.animate( + 0, + calcPaddingTop, + speed, + function (value: number) { + // + el.style.paddingTop = value + 'px' + }, + function () { + el.style.paddingTop = '' + } + ) + } + + if (calcPaddingBottom) { + ElementAnimateUtil.animate( + 0, + calcPaddingBottom, + speed, + function (value: number) { + el.style.paddingBottom = value + 'px' + }, + function () { + el.style.paddingBottom = '' + } + ) + } + + ElementAnimateUtil.animate( + 0, + calcHeight || 0, + speed, + function (value: number) { + el.style.height = value + 'px' + }, + function () { + el.style.height = '' + el.style.display = '' + el.style.overflow = '' + + if (typeof callback === 'function') { + callback() + } + } + ) + } +} + +function slideUp(el: HTMLElement, speed: number, callback: any) { + slide(el, 'up', speed, callback) +} + +function slideDown(el: HTMLElement, speed: number, callback: any) { + slide(el, 'down', speed, callback) +} + +function getBreakpoint(breakpoint: string) { + let value: number | string = getCSSVariableValue('--kt-' + breakpoint) + if (value) { + value = parseInt(value.trim()) + } + + return value +} + +function getAttributeValueByBreakpoint(incomingAttr: string): string | JSON { + let value = toJSON(incomingAttr) + if (typeof value !== 'object') { + return incomingAttr + } + + const width = getViewPort().width + let resultKey + let resultBreakpoint = -1 + let breakpoint + + for (let key in value) { + if (key === 'default') { + breakpoint = 0 + } else { + breakpoint = getBreakpoint(key) ? +getBreakpoint(key) : parseInt(key) + } + + if (breakpoint <= width && breakpoint > resultBreakpoint) { + resultKey = key + resultBreakpoint = breakpoint + } + } + + return resultKey ? getObjectPropertyValueByKey(value, resultKey) : value +} + +function colorLighten(color: string, amount: number) { + const addLight = (_color: string, _amount: number) => { + const cc = parseInt(_color, 16) + _amount + const cNum = cc > 255 ? 255 : cc + const c = cNum.toString(16).length > 1 ? cNum.toString(16) : `0${cNum.toString(16)}` + return c + } + + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = parseInt(((255 * amount) / 100).toString()) + return (color = `#${addLight(color.substring(0, 2), amount)}${addLight( + color.substring(2, 4), + amount + )}${addLight(color.substring(4, 6), amount)}`) +} + +function colorDarken(color: string, amount: number) { + const subtractLight = (_color: string, _amount: number) => { + const cc = parseInt(color, 16) - amount + const cNum = cc < 0 ? 0 : cc + const c = cNum.toString(16).length > 1 ? cNum.toString(16) : `0${cNum.toString(16)}` + return c + } + + color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color + amount = parseInt(((255 * amount) / 100).toString()) + + return (color = `#${subtractLight(color.substring(0, 2), amount)}${subtractLight( + color.substring(2, 4), + amount + )}${subtractLight(color.substring(4, 6), amount)}`) +} + +export { + getBreakpoint, + getCSS, + getCSSVariableValue, + getElementActualCss, + getElementActualHeight, + getElementActualWidth, + getElementIndex, + getElementMatches, + getElementOffset, + getElementParents, + getHighestZindex, + getScrollTop, + getViewPort, + insertAfterElement, + isElementHasClasses, + isVisibleElement, + throttle, + getElementChildren, + getElementChild, + isMobileDevice, + slide, + slideUp, + slideDown, + getAttributeValueByBreakpoint, + colorLighten, + colorDarken, +} diff --git a/src/_res/assets/ts/_utils/ElementAnimateUtil.ts b/src/_res/assets/ts/_utils/ElementAnimateUtil.ts new file mode 100644 index 0000000..20a2339 --- /dev/null +++ b/src/_res/assets/ts/_utils/ElementAnimateUtil.ts @@ -0,0 +1,111 @@ +import {DOMEventHandlerUtil} from './_DOMEventHandlerUtil' +import {ElementStyleUtil} from './_ElementStyleUtil' +import {getElementOffset} from './DomHelpers' + +export class ElementAnimateUtil { + public static animate( + from: number, + to: number, + duration: number, + update: Function, + complete?: Function + ) { + /** + * TinyAnimate.easings + * Adapted from jQuery Easing + */ + const easings = { + linear: function (t: number, b: number, c: number, d: number) { + return (c * t) / d + b + }, + } + + // Create mock done() function if necessary + if (!complete) { + complete = function () {} + } + + // Animation loop + // let canceled = false; + const change = to - from + + function loop(timestamp: number) { + var time = (timestamp || +new Date()) - start + + if (time >= 0) { + update(easings.linear(time, from, change, duration)) + } + if (time >= 0 && time >= duration) { + update(to) + if (complete) { + complete() + } + } else { + window.requestAnimationFrame(loop) + } + } + + update(from) + + // Start animation loop + const start = + window.performance && window.performance.now ? window.performance.now() : +new Date() + + window.requestAnimationFrame(loop) + } + + public static animateClass( + element: HTMLElement, + animationName: string, + callBack?: Function + ): void { + const animateClasses = animationName.split(' ') + animateClasses.forEach((cssClass) => element.classList.add(cssClass)) + DOMEventHandlerUtil.one(element, 'animationend', function () { + animateClasses.forEach((cssClass) => element.classList.remove(cssClass)) + }) + + if (callBack) { + DOMEventHandlerUtil.one(element, 'animationend', callBack) + } + } + + public static transitionEnd(element: HTMLElement, callBack: Function) { + DOMEventHandlerUtil.one(element, 'transitionend', callBack) + } + + public static animationEnd(element: HTMLElement, callBack: Function) { + DOMEventHandlerUtil.one(element, 'animationend', callBack) + } + + public static animationDelay(element: HTMLElement, value: string) { + ElementStyleUtil.set(element, 'animation-delay', value) + } + + public static animationDuration(element: HTMLElement, value: string) { + ElementStyleUtil.set(element, 'animation-duration', value) + } + + public static scrollTo(element: HTMLElement | null, offset: number, duration: number = 500) { + let targetPos = element ? getElementOffset(element).top : 0 + let scrollPos = + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0 + + if (offset) { + scrollPos += offset + targetPos = targetPos - offset + } + + const from = scrollPos + const to = targetPos + + ElementAnimateUtil.animate(from, to, duration, function (value: number) { + document.documentElement.scrollTop = value + // document.body.parentNode.scrollTop = value; + document.body.scrollTop = value + }) //, easing, done + } + public static scrollTop(offset: number, duration: number) { + ElementAnimateUtil.scrollTo(null, offset, duration) + } +} diff --git a/src/_res/assets/ts/_utils/EventHandlerUtil.ts b/src/_res/assets/ts/_utils/EventHandlerUtil.ts new file mode 100644 index 0000000..878a793 --- /dev/null +++ b/src/_res/assets/ts/_utils/EventHandlerUtil.ts @@ -0,0 +1,144 @@ +import {DataUtil} from './_DataUtil' +import {getUniqueIdWithPrefix} from './_TypesHelpers' + +export interface EventMeta { + name: string + callback: Function + one: boolean + fired: boolean +} + +export class EventHandlerUtil { + static store: { + [name: string]: { + [handlerId: string]: EventMeta + } + } = {} + + private static setEventMetasByName( + name: string, + handlers: { + [handlerId: string]: EventMeta + } + ): void { + EventHandlerUtil.store[name] = handlers + } + + private static getEventMetaByName(name: string): + | { + [handlerId: string]: EventMeta + } + | undefined { + return EventHandlerUtil.store[name] + } + + private static setEventMetaByNameAndHandlerId( + name: string, + handlerId: string, + meta: EventMeta + ): void { + if (EventHandlerUtil.store[name]) { + EventHandlerUtil.store[name][handlerId] = meta + return + } + EventHandlerUtil.store[name] = {} + EventHandlerUtil.store[name][handlerId] = meta + } + + private static getEventMetaByHandlerId(name: string, handlerId: string): EventMeta | undefined { + const handlersIds = EventHandlerUtil.store[name] + if (!handlersIds) { + return + } + return handlersIds[handlerId] + } + + private static setFiredByNameAndHandlerId(name: string, handerId: string, fired: boolean): void { + const meta = EventHandlerUtil.getEventMetaByHandlerId(name, handerId) + if (!meta) { + return + } + + meta.fired = fired + EventHandlerUtil.setEventMetaByNameAndHandlerId(name, handerId, meta) + } + + private static addEvent( + element: HTMLElement, + name: string, + callback: Function, + one: boolean = false + ): string { + const handlerId = getUniqueIdWithPrefix('event') + const data = DataUtil.get(element, name) + const handlersIds = data ? (data as string[]) : [] + handlersIds.push(handlerId) + + DataUtil.set(element, name, handlersIds) + + const meta: EventMeta = { + name: name, + callback: callback, + one: one, + fired: false, + } + + EventHandlerUtil.setEventMetaByNameAndHandlerId(name, handlerId, meta) + return handlerId + } + + private static removeEvent(element: HTMLElement, name: string, handerId: string) { + DataUtil.removeOne(element, name, handerId) + const handlersIds = EventHandlerUtil.store[name] + if (handlersIds) { + return + } + + delete EventHandlerUtil.store[name][handerId] + } + + public static trigger(element: HTMLElement, name: string, target?: any, e?: Event): boolean { + let returnValue = true + if (!DataUtil.has(element, name)) { + return returnValue + } + + let eventValue + let handlerId + const data = DataUtil.get(element, name) + const handlersIds = data ? (data as string[]) : [] + for (let i = 0; i < handlersIds.length; i++) { + handlerId = handlersIds[i] + if (EventHandlerUtil.store[name] && EventHandlerUtil.store[name][handlerId]) { + const handler = EventHandlerUtil.store[name][handlerId] + if (handler.name === name) { + if (handler.one) { + if (handler.fired) { + EventHandlerUtil.store[name][handlerId].fired = true + eventValue = handler.callback.call(this, target) + } + } else { + eventValue = handler.callback.call(this, target) + } + + if (eventValue === false) { + returnValue = false + } + } + } + } + return returnValue + } + + public static on = function (element: HTMLElement, name: string, callBack: Function): void { + EventHandlerUtil.addEvent(element, name, callBack, false) + } + + public static one(element: HTMLElement, name: string, callBack: Function): void { + EventHandlerUtil.addEvent(element, name, callBack, true) + } + + public static off(element: HTMLElement, name: string, handerId: string): void { + EventHandlerUtil.removeEvent(element, name, handerId) + } +} diff --git a/src/_res/assets/ts/_utils/_DOMEventHandlerUtil.ts b/src/_res/assets/ts/_utils/_DOMEventHandlerUtil.ts new file mode 100644 index 0000000..568f812 --- /dev/null +++ b/src/_res/assets/ts/_utils/_DOMEventHandlerUtil.ts @@ -0,0 +1,60 @@ +import {getUniqueIdWithPrefix} from './_TypesHelpers' + +export class DOMEventHandlerUtil { + public static store = new Map() + + public static on( + element: HTMLElement, + selector: string, + eventName: string, + callBack: any + ): string { + const eventId = getUniqueIdWithPrefix('DOMEvent') + DOMEventHandlerUtil.store.set(eventId, (e: Event) => { + const targets = element.querySelectorAll(selector) + let target: HTMLElement | null = e.target as HTMLElement + while (target && target !== element) { + for (let i = 0; i < targets.length; i++) { + if (target === targets[i]) { + callBack.call(target, e) + } + } + + if (target.parentElement) { + target = target.parentElement + } else { + target = null + } + } + }) + element.addEventListener(eventName, DOMEventHandlerUtil.store.get(eventId)) + return eventId + } + + public static off(element: HTMLElement, eventName: string, eventId: string): void { + const funcFromStore = DOMEventHandlerUtil.store.get(eventId) + if (!funcFromStore) { + return + } + + element.removeEventListener(eventName, funcFromStore) + DOMEventHandlerUtil.store.delete(eventId) + } + + public static one(element: HTMLElement, eventName: string, callBack: Function): void { + element.addEventListener(eventName, function calee(e) { + // remove event + if (e.target && e.target.removeEventListener) { + e.target.removeEventListener(e.type, calee) + } + + if (element && e && e.currentTarget) { + // if (element && element.removeEventListener && e && e.currentTarget) { + e.currentTarget.removeEventListener(e.type, calee) + } + + // call hander + return callBack(e) + }) + } +} diff --git a/src/_res/assets/ts/_utils/_DataUtil.ts b/src/_res/assets/ts/_utils/_DataUtil.ts new file mode 100644 index 0000000..14e9cae --- /dev/null +++ b/src/_res/assets/ts/_utils/_DataUtil.ts @@ -0,0 +1,72 @@ +export class DataUtil { + static store: Map> = new Map() + + public static set(instance: HTMLElement | undefined, key: string, data: unknown): void { + if (!instance) { + return + } + + const instanceData = DataUtil.store.get(instance) + if (!instanceData) { + const newMap = new Map().set(key, data) + DataUtil.store.set(instance, newMap) + return + } + + instanceData.set(key, data) + } + + public static get(instance: HTMLElement, key: string): unknown | undefined { + const instanceData = DataUtil.store.get(instance) + if (!instanceData) { + return + } + + return instanceData.get(key) + } + + public static remove(instance: HTMLElement, key: string): void { + const instanceData = DataUtil.store.get(instance) + if (!instanceData) { + return + } + + instanceData.delete(key) + } + + public static removeOne(instance: HTMLElement, key: string, eventId: string) { + const instanceData = DataUtil.store.get(instance) + if (!instanceData) { + return + } + + const eventsIds = instanceData.get(key) + if (!eventsIds) { + return + } + + const updateEventsIds = (eventsIds as string[]).filter((f) => f !== eventId) + DataUtil.set(instance, key, updateEventsIds) + } + + public static has(instance: HTMLElement, key: string): boolean { + const instanceData = DataUtil.store.get(instance) + if (instanceData) { + return instanceData.has(key) + } + + return false + } + + public static getAllInstancesByKey(key: string) { + const result: any[] = [] + DataUtil.store.forEach((val) => { + val.forEach((v, k) => { + if (k === key) { + result.push(v) + } + }) + }) + return result + } +} diff --git a/src/_res/assets/ts/_utils/_ElementStyleUtil.ts b/src/_res/assets/ts/_utils/_ElementStyleUtil.ts new file mode 100644 index 0000000..b0ddda4 --- /dev/null +++ b/src/_res/assets/ts/_utils/_ElementStyleUtil.ts @@ -0,0 +1,17 @@ +export class ElementStyleUtil { + public static set(element: HTMLElement, property: string, value?: any, important?: boolean) { + if (important) { + element.style.setProperty(property, value, 'important') + } else { + element.style.setProperty(property, value) + } + } + + public static get(element: HTMLElement, attributeName: string) { + return element.style.getPropertyValue(attributeName) + } + + public static remove(element: HTMLElement, attibuteName: string) { + element.style.removeProperty(attibuteName) + } +} diff --git a/src/_res/assets/ts/_utils/_TypesHelpers.ts b/src/_res/assets/ts/_utils/_TypesHelpers.ts new file mode 100644 index 0000000..5c32269 --- /dev/null +++ b/src/_res/assets/ts/_utils/_TypesHelpers.ts @@ -0,0 +1,54 @@ +function getObjectPropertyValueByKey(obj: any, key: string): any | undefined { + const map = new Map(Object.entries(obj)) + if (obj.hasOwnProperty(key) && map) { + return map.get(key) + } +} + +/** + * Generates unique ID for give prefix. + * @param {string} prefix Prefix for generated ID + * @returns {boolean} + */ +function getUniqueIdWithPrefix(prefix: string | undefined): string { + const result = Math.floor(Math.random() * new Date().getTime()).toString() + if (!prefix) { + return result + } + + return `${prefix}${result}` +} + +/* eslint-disable no-useless-escape */ +function stringSnakeToCamel(str: string): string { + return str.replace(/(\-\w)/g, function (m) { + return m[1].toUpperCase() + }) +} + +function toJSON(value: string | JSON): JSON | undefined { + if (typeof value !== 'string') { + return value + } + + if (!value) { + return undefined + } + + // ("'" => "\""); + const result = value + .toString() + .split('') + .map((el) => (el !== "'" ? el : '"')) + .join('') + var jsonStr = result.replace(/(\w+:)|(\w+ :)/g, function (matched) { + return '"' + matched.substring(0, matched.length - 1) + '":' + }) + try { + return JSON.parse(jsonStr) + } catch { + return undefined + } +} + +export {getObjectPropertyValueByKey, getUniqueIdWithPrefix, stringSnakeToCamel, toJSON} diff --git a/src/_res/assets/ts/_utils/index.ts b/src/_res/assets/ts/_utils/index.ts new file mode 100644 index 0000000..02ad68f --- /dev/null +++ b/src/_res/assets/ts/_utils/index.ts @@ -0,0 +1,12 @@ +// Types +export * from './models/OffsetModel' +export * from './models/ViewPortModel' +// Helpers +export * from './DomHelpers' +export * from './_TypesHelpers' +// Basic +export * from './_DataUtil' +export * from './_DOMEventHandlerUtil' +export * from './_ElementStyleUtil' +export * from './ElementAnimateUtil' +export * from './EventHandlerUtil' diff --git a/src/_res/assets/ts/_utils/models/OffsetModel.ts b/src/_res/assets/ts/_utils/models/OffsetModel.ts new file mode 100644 index 0000000..bea6c4e --- /dev/null +++ b/src/_res/assets/ts/_utils/models/OffsetModel.ts @@ -0,0 +1,4 @@ +export interface OffsetModel { + top: number + left: number +} diff --git a/src/_res/assets/ts/_utils/models/ViewPortModel.ts b/src/_res/assets/ts/_utils/models/ViewPortModel.ts new file mode 100644 index 0000000..63ee145 --- /dev/null +++ b/src/_res/assets/ts/_utils/models/ViewPortModel.ts @@ -0,0 +1,4 @@ +export interface ViewPortModel { + width: number + height: number +} diff --git a/src/_res/assets/ts/components/MenuComponent.ts b/src/_res/assets/ts/components/MenuComponent.ts new file mode 100644 index 0000000..e27ac0b --- /dev/null +++ b/src/_res/assets/ts/components/MenuComponent.ts @@ -0,0 +1,1088 @@ +import {createPopper, VirtualElement} from '@popperjs/core' +import { + getElementChild, + getElementParents, + getAttributeValueByBreakpoint, + getUniqueIdWithPrefix, + DataUtil, + ElementStyleUtil, + EventHandlerUtil, + insertAfterElement, + slideUp, + slideDown, + DOMEventHandlerUtil, + throttle, + getHighestZindex, +} from '../_utils/index' + +export interface MenuOptions { + dropdown: { + hoverTimeout: number + zindex: number + } + accordion: { + slideSpeed: number + expand: boolean + } +} + +const defaultMenuOptions: MenuOptions = { + dropdown: { + hoverTimeout: 200, + zindex: 105, + }, + accordion: { + slideSpeed: 250, + expand: false, + }, +} + +type PopperPlacement = + | 'right' + | 'auto' + | 'auto-start' + | 'auto-end' + | 'top' + | 'bottom' + | 'left' + | 'top-start' + | 'top-end' + | 'bottom-start' + | 'bottom-end' + | 'right-start' + | 'right-end' + | 'left-start' + | 'left-end' + | undefined + +class MenuComponent { + element: HTMLElement + options: MenuOptions + instanceUid: string + triggerElement: HTMLElement | null = null + + constructor(_element: HTMLElement, options: MenuOptions) { + this.element = _element + this.options = Object.assign(defaultMenuOptions, options) + this.instanceUid = getUniqueIdWithPrefix('menu') + // this.element.setAttribute('data-kt-menu', 'true') + this._setTriggerElement() + this._update() + DataUtil.set(this.element, 'menu', this) + return this + } + + // Set external trigger element + private _setTriggerElement = () => { + const target = document.querySelector( + `[data-kt-menu-target="#${this.element.getAttribute('id')}"` + ) + + if (target) { + this.triggerElement = target as HTMLElement + } else if (this.element.closest('[data-kt-menu-trigger]')) { + this.triggerElement = this.element.closest('[data-kt-menu-trigger]') as HTMLElement + } else if ( + this.element.parentNode && + getElementChild(this.element.parentNode as HTMLElement, '[data-kt-menu-trigger]') + ) { + const child = getElementChild( + this.element.parentNode as HTMLElement, + '[data-kt-menu-trigger]' + ) + if (child) { + this.triggerElement = child + } + } + + if (this.triggerElement) { + DataUtil.set(this.triggerElement, 'menu', this) + } + } + + // Test if menu has external trigger element + private _isTriggerElement = (item: HTMLElement) => { + return this.triggerElement === item + } + + // Get item option(through html attributes) + private _getItemOption = (item: HTMLElement, name: string) => { + let value: string | JSON | null | boolean = null + if (item && item.hasAttribute('data-kt-menu-' + name)) { + const attr = item.getAttribute('data-kt-menu-' + name) || '' + value = getAttributeValueByBreakpoint(attr) + if (value !== null && String(value) === 'true') { + value = true + } else if (value !== null && String(value) === 'false') { + value = false + } + } + return value + } + + // Get item element + private _getItemElement = (_element: HTMLElement): HTMLElement | undefined => { + // Element is the external trigger element + if (this._isTriggerElement(_element)) { + return _element + } + + // Element has item toggler attribute + if (_element.hasAttribute('data-kt-menu-trigger')) { + return _element + } + + // Element has item DOM reference in it's data storage + const itemElement = DataUtil.get(_element, 'item') + if (itemElement) { + return itemElement as HTMLElement + } + + // Item is parent of element + const item = _element.closest('.menu-item[data-kt-menu-trigger]') + if (item) { + return item + } + + // Element's parent has item DOM reference in it's data storage + const sub = _element.closest('.menu-sub') + if (sub) { + const subItem = DataUtil.get(sub as HTMLElement, 'item') + if (subItem) { + return subItem as HTMLElement + } + } + } + + // Get item parent element + private _getItemParentElement = (item: HTMLElement) => { + const sub = item.closest('.menu-sub') + if (!sub) { + return null + } + + const subItem = DataUtil.get(sub, 'item') + if (subItem) { + return subItem as HTMLElement + } + + const parentItem = sub.closest('.menu-item[data-kt-menu-trigger]') + if (sub && parentItem) { + return parentItem + } + + return null + } + + // Get item parent elements + private _getItemParentElements = (item: HTMLElement) => { + const parents: Array = [] + let parent: HTMLElement | null + let i = 0 + let buffer: HTMLElement = item + + do { + parent = this._getItemParentElement(buffer) + if (parent) { + parents.push(parent) + buffer = parent as HTMLElement + } + + i++ + } while (parent !== null && i < 20) + + if (this.triggerElement) { + parents.unshift(this.triggerElement) + } + + return parents + } + + // Prepare popper config for dropdown(see: https://popper.js.org/docs/v2/) + private _getDropdownPopperConfig = (item: HTMLElement) => { + // Placement + const placementOption = this._getItemOption(item, 'placement') + let placement: PopperPlacement = 'right' + if (placementOption) { + placement = placementOption as PopperPlacement + } + + // Flip + // const flipValue = this._getItemOption(item, 'flip') + // const flip = flipValue ? flipValue.toString().split(',') : [] + + // Offset + const offsetValue = this._getItemOption(item, 'offset') + const offset = offsetValue ? offsetValue.toString().split(',') : [] + + // Strategy + const strategy: 'absolute' | 'fixed' | undefined = + this._getItemOption(item, 'overflow') === true ? 'absolute' : 'fixed' + + return { + placement: placement, + strategy: strategy, + modifiers: [ + { + name: 'offset', + options: { + offset: offset, + }, + }, + { + name: 'preventOverflow', + }, + { + name: 'flip', + options: { + // altBoundary: true, + // fallbackPlacements: flip, + flipVariations: false, + }, + }, + ], + } + } + + // Get item child element + private _getItemChildElement = (item: HTMLElement): HTMLElement | null => { + let selector = item + + const subItem = DataUtil.get(item, 'sub') + if (subItem) { + selector = subItem as HTMLElement + } + + if (selector) { + //element = selector.querySelector('.show.menu-item[data-kt-menu-trigger]'); + const element = selector.querySelector('.menu-item[data-kt-menu-trigger]') + if (element) { + return element + } + } + return null + } + + // Get item child elements + private _getItemChildElements = (item: HTMLElement) => { + const children: Array = [] + let child: HTMLElement | null + let i = 0 + let buffer = item + do { + child = this._getItemChildElement(buffer) + if (child) { + children.push(child) + buffer = child as HTMLElement + } + + i++ + } while (child !== null && i < 20) + + return children + } + + // Get item sub element + private _getItemSubElement = (item: HTMLElement): HTMLElement | null => { + if (!item) { + return null + } + + if (this._isTriggerElement(item)) { + return this.element + } + + if (item.classList.contains('menu-sub')) { + return item + } else if (DataUtil.has(item, 'sub')) { + const itemSub = DataUtil.get(item, 'sub') + return itemSub ? (itemSub as HTMLElement) : null + } else { + return getElementChild(item, '.menu-sub') + } + } + + private _getCss = (el: HTMLElement, styleProp: string) => { + const defaultView = (el.ownerDocument || document).defaultView + if (!defaultView) { + return '' + } + + // sanitize property name to css notation + // (hyphen separated words eg. font-Size) + styleProp = styleProp.replace(/([A-Z])/g, '-$1').toLowerCase() + + return defaultView.getComputedStyle(el, null).getPropertyValue(styleProp) + } + + // Get item sub type + private _getItemSubType = (element: HTMLElement) => { + const sub = this._getItemSubElement(element) + if (sub && parseInt(this._getCss(sub as HTMLElement, 'z-index')) > 0) { + return 'dropdown' + } else { + return 'accordion' + } + } + + // Test if item's sub is shown + private _isItemSubShown = (item: HTMLElement) => { + let sub = this._getItemSubElement(item) + if (sub) { + if (this._getItemSubType(item) === 'dropdown') { + const subHTMLElement = sub as HTMLElement + return ( + subHTMLElement.classList.contains('show') && + subHTMLElement.hasAttribute('data-popper-placement') + ) + } else { + return item.classList.contains('show') + } + } + + return false + } + + // Test if item dropdown is permanent + private _isItemDropdownPermanent = (item: HTMLElement) => { + return this._getItemOption(item, 'permanent') === true + } + + // Test if item's parent is shown + private _isItemParentShown = (item: HTMLElement) => { + return getElementParents(item, '.menu-item.show').length > 0 + } + + // Test of it is item sub element + private _isItemSubElement = (item: HTMLElement) => { + return item.classList.contains('menu-sub') + } + + // Test if item has sub + private _hasItemSub = (item: HTMLElement) => { + return item.classList.contains('menu-item') && item.hasAttribute('data-kt-menu-trigger') + } + + // Get link element + private _getItemLinkElement = (item: HTMLElement) => { + return getElementChild(item, '.menu-link') + } + + // Get toggle element + private _getItemToggleElement = (item: HTMLElement) => { + if (this.triggerElement) { + return this.triggerElement + } + + return this._getItemLinkElement(item) + } + + // Show item dropdown + private _showDropdown = (item: HTMLElement) => { + if (EventHandlerUtil.trigger(this.element, 'kt.menu.dropdown.show') === false) { + return + } + + // Hide all currently shown dropdowns except current one + MenuComponent.hideDropdowns(item) + + // const toggle = this._isTriggerElement(item) ? item : this._getItemLinkElement(item); + const sub = this._getItemSubElement(item) + const width = this._getItemOption(item, 'width') + const height = this._getItemOption(item, 'height') + + let zindex = this.options.dropdown.zindex + const parentZindex = getHighestZindex(item) // update + // Apply a new z-index if dropdown's toggle element or it's parent has greater z-index // update + if (parentZindex !== null && parentZindex >= zindex) { + zindex = parentZindex + 1 + } + + if (zindex && sub) { + ElementStyleUtil.set(sub, 'z-index', zindex) + } + + if (width && sub) { + ElementStyleUtil.set(sub, 'width', width) + } + + if (height && sub) { + ElementStyleUtil.set(sub, 'height', height) + } + + this.initDropdownPopper(item, sub as HTMLElement) + + item.classList.add('show') + item.classList.add('menu-dropdown') + sub?.classList.add('show') + + // Append the sub the the root of the menu + if (this._getItemOption(item, 'overflow') === true) { + if (sub) { + document.body.appendChild(sub) + DataUtil.set(item, 'sub', sub) + DataUtil.set(sub, 'item', item) + DataUtil.set(sub, 'menu', this) + } + } else { + if (sub) { + DataUtil.set(sub, 'item', item) + } + } + + EventHandlerUtil.trigger(this.element, 'kt.menu.dropdown.shown') + } + + // Init dropdown popper(new) + private initDropdownPopper = (item: HTMLElement, sub: HTMLElement) => { + // Setup popper instance + let reference + const attach = this._getItemOption(item, 'attach') as string + + if (attach) { + if (attach === 'parent') { + reference = item.parentNode + } else { + reference = document.querySelector(attach) + } + } else { + reference = item + } + + if (reference) { + const popper = createPopper( + reference as Element | VirtualElement, + sub, + this._getDropdownPopperConfig(item) + ) + DataUtil.set(item, 'popper', popper) + } + } + + // Hide item dropdown + private _hideDropdown = (item: HTMLElement) => { + if (EventHandlerUtil.trigger(this.element, 'kt.menu.dropdown.hide') === false) { + return + } + + const sub = this._getItemSubElement(item) + if (sub) { + ElementStyleUtil.set(sub, 'z-index', '') + ElementStyleUtil.set(sub, 'width', '') + ElementStyleUtil.set(sub, 'height', '') + } + + item.classList.remove('show') + item.classList.remove('menu-dropdown') + if (sub) { + sub.classList.remove('show') + } + + // Append the sub back to it's parent + if (this._getItemOption(item, 'overflow') === true) { + if (item.classList.contains('menu-item')) { + if (sub) { + item.appendChild(sub) + } + } else { + insertAfterElement(this.element, item) + } + + if (sub) { + DataUtil.remove(item, 'sub') + DataUtil.remove(sub, 'item') + DataUtil.remove(sub, 'menu') + } + } + + if (DataUtil.has(item, 'popper') === true) { + // @ts-ignore + DataUtil.get(item, 'popper').destroy() + DataUtil.remove(item, 'popper') + } + + // Destroy popper(new) + this.destroyDropdownPopper(item) + EventHandlerUtil.trigger(this.element, 'kt.menu.dropdown.hidden') + } + + // Destroy dropdown popper(new) + private destroyDropdownPopper = (item: HTMLElement) => { + if (DataUtil.has(item, 'popper') === true) { + // @ts-ignore + DataUtil.get(item, 'popper').destroy() + DataUtil.remove(item, 'popper') + } + + EventHandlerUtil.trigger(this.element, 'kt.menu.dropdown.hidden') + } + + private _showAccordion = (item: HTMLElement) => { + if (EventHandlerUtil.trigger(this.element, 'kt.menu.accordion.show') === false) { + return + } + + if (this.options.accordion.expand === false) { + this._hideAccordions(item) + } + + if (DataUtil.has(item, 'popper') === true) { + this._hideDropdown(item) + } + + item.classList.add('hover') // updateWW + item.classList.add('showing') + + const subElement = this._getItemSubElement(item) + if (subElement) { + const sub = subElement as HTMLElement + slideDown(sub, this.options.accordion.slideSpeed, () => { + item.classList.remove('showing') + item.classList.add('show') + sub.classList.add('show') + EventHandlerUtil.trigger(this.element, 'kt.menu.accordion.shown') + }) + } + } + + private _hideAccordion = (item: HTMLElement) => { + if (EventHandlerUtil.trigger(this.element, 'kt.menu.accordion.hide') === false) { + return + } + + const sub = this._getItemSubElement(item) + item.classList.add('hiding') + + if (sub) { + slideUp(sub, this.options.accordion.slideSpeed, () => { + item.classList.remove('hiding') + item.classList.remove('show') + sub.classList.remove('show') + item.classList.remove('hover') // update + EventHandlerUtil.trigger(this.element, 'kt.menu.accordion.hidden') + }) + } + } + + // Hide all shown accordions of item + private _hideAccordions = (item: HTMLElement) => { + const itemsToHide = this.element.querySelectorAll('.show[data-kt-menu-trigger]') + if (itemsToHide && itemsToHide.length > 0) { + for (var i = 0, len = itemsToHide.length; i < len; i++) { + const itemToHide = itemsToHide[i] as HTMLElement + + if ( + this._getItemSubType(itemToHide) === 'accordion' && + itemToHide !== item && + item.contains(itemToHide) === false && + itemToHide.contains(item) === false + ) { + this._hideAccordion(itemToHide) + } + } + } + } + + // Event Handlers + // Reset item state classes if item sub type changed + private _reset = (item: HTMLElement) => { + if (this._hasItemSub(item) === false) { + return + } + + const sub = this._getItemSubElement(item) + + // Reset sub state if sub type is changed during the window resize + if (DataUtil.has(item, 'type') && DataUtil.get(item, 'type') !== this._getItemSubType(item)) { + // updated + item.classList.remove('hover') + item.classList.remove('show') + item.classList.remove('show') + if (sub) { + sub.classList.remove('show') + } + } // updated + } + + // TODO: not done + private _destroy = () => {} + + // Update all item state classes if item sub type changed + private _update = () => { + const items = this.element.querySelectorAll('.menu-item[data-kt-menu-trigger]') + items.forEach((el) => this._reset(el as HTMLElement)) + } + + // Hide item sub + private _hide = (item: HTMLElement) => { + if (!item) { + return + } + + if (this._isItemSubShown(item) === false) { + return + } + + if (this._getItemSubType(item) === 'dropdown') { + this._hideDropdown(item) + } else if (this._getItemSubType(item) === 'accordion') { + this._hideAccordion(item) + } + } + + // Show item sub + private _show = (item: HTMLElement) => { + if (!item) { + return + } + + if (this._isItemSubShown(item) === true) { + return + } + + if (this._getItemSubType(item) === 'dropdown') { + this._showDropdown(item) // // show current dropdown + } else if (this._getItemSubType(item) === 'accordion') { + this._showAccordion(item) + } + + // Remember last submenu type + + DataUtil.set(item, 'type', this._getItemSubType(item)) // updated + } + + // Toggle item sub + private _toggle = (item: HTMLElement) => { + if (!item) { + return + } + + if (this._isItemSubShown(item) === true) { + this._hide(item) + } else { + this._show(item) + } + } + + // Mouseout handle + private _mouseout = (element: HTMLElement, e: MouseEvent) => { + const item = this._getItemElement(element) + if (!item) { + return + } + + if (this._getItemOption(item, 'trigger') !== 'hover') { + return + } + + const timeout = setTimeout(() => { + if (DataUtil.get(item, 'hover') === '1') { + this._hide(item) + } + }, this.options.dropdown.hoverTimeout) + + DataUtil.set(item, 'hover', '1') + DataUtil.set(item, 'timeout', timeout) + } + + // Mouseover handle + private _mouseover = (element: HTMLElement, e: MouseEvent) => { + const item = this._getItemElement(element) + if (!item) { + return + } + + if (this._getItemOption(item, 'trigger') !== 'hover') { + return + } + + if (DataUtil.get(item, 'hover') === '1') { + const timeout = DataUtil.get(item, 'timeout') + if (timeout) { + clearTimeout(timeout as number) + } + DataUtil.remove(item, 'hover') + DataUtil.remove(item, 'timeout') + } + + this._show(item) + } + + // Dismiss handler + private _dismiss = (element: HTMLElement, e: Event) => { + const item = this._getItemElement(element) + if (!item) { + return + } + const items = this._getItemChildElements(item) + //if ( item !== null && _getItemOption(item, 'trigger') === 'click' && _getItemSubType(item) === 'dropdown' ) { + const itemSubType = this._getItemSubType(item) + if (item !== null && itemSubType === 'dropdown') { + this._hide(item) // hide items dropdown + + // Hide all child elements as well + if (items.length > 0) { + for (let i = 0, len = items.length; i < len; i++) { + //if ( _getItemOption(item, 'trigger') === 'click' && _getItemSubType(item) === 'dropdown' ) { + if (items[i] !== null && this._getItemSubType(items[i] as HTMLElement) === 'dropdown') { + this._hide(items[i] as HTMLElement) + } + } + } + } + } + + // Link handler + private _link = (element: HTMLElement, e: Event) => { + if (EventHandlerUtil.trigger(this.element, 'kt.menu.link.click') === false) { + return + } + + // Dismiss all shown dropdowns + MenuComponent.hideDropdowns(undefined) + EventHandlerUtil.trigger(this.element, 'kt.menu.link.clicked') + } + + private _click = (element: HTMLElement, e: Event) => { + e.preventDefault() + const item = this._getItemElement(element) + if (item) { + if (this._getItemOption(item, 'trigger') !== 'click') { + return + } + + if (this._getItemOption(item, 'toggle') === false) { + this._show(item) + } else { + this._toggle(item) + } + } + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + public click = (element: HTMLElement, e: Event) => { + return this._click(element, e) + } + + public link = (element: HTMLElement, e: Event) => { + return this._link(element, e) + } + + public dismiss = (element: HTMLElement, e: Event) => { + return this._dismiss(element, e) + } + + public mouseover = (element: HTMLElement, e: Event) => { + return this._mouseover(element, e as MouseEvent) + } + + public mouseout = (element: HTMLElement, e: Event) => { + return this._mouseout(element, e as MouseEvent) + } + + // General Methods + public getItemTriggerType = (item: HTMLElement) => { + return this._getItemOption(item, 'trigger') + } + + public getItemSubType = (element: HTMLElement) => { + return this._getItemSubType(element) + } + + public show = (item: HTMLElement) => { + return this._show(item) + } + + public hide = (item: HTMLElement) => { + return this._hide(item) + } + + public reset = (item: HTMLElement) => { + return this._reset(item) + } + + public update = () => { + return this._update() + } + + public getElement = () => { + return this.element + } + + public getItemLinkElement = (item: HTMLElement) => { + return this._getItemLinkElement(item) + } + + public getItemToggleElement = (item: HTMLElement) => { + return this._getItemToggleElement(item) + } + + public getItemSubElement = (item: HTMLElement) => { + return this._getItemSubElement(item) + } + + public getItemParentElements = (item: HTMLElement) => { + return this._getItemParentElements(item) + } + + public isItemSubShown = (item: HTMLElement) => { + return this._isItemSubShown(item) + } + + public isItemParentShown = (item: HTMLElement) => { + return this._isItemParentShown(item) + } + + public getTriggerElement = () => { + return this.triggerElement + } + + public isItemDropdownPermanent = (item: HTMLElement) => { + return this._isItemDropdownPermanent(item) + } + + // Accordion Mode Methods + public hideAccordions = (item: HTMLElement) => { + return this._hideAccordions(item) + } + + // Event API + public on = (name: string, handler: any) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: any) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handlerId: string) => { + return EventHandlerUtil.off(this.element, name, handlerId) + } + + // public static methods + // Get KTMenu instance by element + public static getInstance = (element: HTMLElement): MenuComponent | null => { + // Element has menu DOM reference in it's DATA storage + const elementMenu = DataUtil.get(element, 'menu') + if (elementMenu) { + return elementMenu as MenuComponent + } + + // Element has .menu parent + const menu = element.closest('.menu') + if (menu) { + const menuData = DataUtil.get(menu as HTMLElement, 'menu') + if (menuData) { + return menuData as MenuComponent + } + } + + // Element has a parent with DOM reference to .menu in it's DATA storage + if (element.classList.contains('menu-link')) { + const sub = element.closest('.menu-sub') + if (sub) { + const subMenu = DataUtil.get(sub as HTMLElement, 'menu') + if (subMenu) { + return subMenu as MenuComponent + } + } + } + + return null + } + + // Hide all dropdowns and skip one if provided + public static hideDropdowns = (skip: HTMLElement | undefined) => { + const items = document.querySelectorAll( + '.show.menu-dropdown[data-kt-menu-trigger]' + ) + + if (items && items.length > 0) { + for (let i = 0, len = items.length; i < len; i++) { + const item = items[i] + const menu = MenuComponent.getInstance(item as HTMLElement) + + if (menu && menu.getItemSubType(item) === 'dropdown') { + if (skip) { + if ( + // @ts-ignore + menu.getItemSubElement(item).contains(skip) === false && + item.contains(skip) === false && + item !== skip + ) { + menu.hide(item) + } + } else { + menu.hide(item) + } + } + } + } + } + + public static updateDropdowns = () => { + const items = document.querySelectorAll('.show.menu-dropdown[data-kt-menu-trigger]') + if (items && items.length > 0) { + for (var i = 0, len = items.length; i < len; i++) { + var item = items[i] + + if (DataUtil.has(item as HTMLElement, 'popper')) { + // @ts-ignore + DataUtil.get(item as HTMLElement, 'popper').forceUpdate() + } + } + } + } + + // Global handlers + public static createInstances = (selector: string) => { + // Initialize menus + document.querySelectorAll(selector).forEach((el) => { + const menuItem = el as HTMLElement + let menuInstance = MenuComponent.getInstance(menuItem) + if (!menuInstance) { + menuInstance = new MenuComponent(el as HTMLElement, defaultMenuOptions) + } + }) + } + + public static initGlobalHandlers = () => { + // Dropdown handler + document.addEventListener('click', (e) => { + const menuItems = document.querySelectorAll('.show.menu-dropdown[data-kt-menu-trigger]') + if (menuItems && menuItems.length > 0) { + for (let i = 0; i < menuItems.length; i++) { + const item = menuItems[i] as HTMLElement + const menuObj = MenuComponent.getInstance(item) as MenuComponent + if (menuObj && menuObj.getItemSubType(item) === 'dropdown') { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const menu = menuObj.getElement() + const sub = menuObj.getItemSubElement(item) as HTMLElement + if (item === e.target || item.contains(e.target as HTMLElement)) { + continue + } + + if (sub && (sub === e.target || sub.contains(e.target as HTMLElement))) { + continue + } + menuObj.hide(item) + } + } + } + }) + + // Sub toggle handler + DOMEventHandlerUtil.on( + document.body, + '.menu-item[data-kt-menu-trigger] > .menu-link, [data-kt-menu-trigger]:not(.menu-item):not([data-kt-menu-trigger="auto"])', + 'click', + function (this: HTMLElement, e: Event) { + const menu = MenuComponent.getInstance(this) as MenuComponent + if (menu) { + return menu.click(this, e) + } + } + ) + + // // Link handler + DOMEventHandlerUtil.on( + document.body, + '.menu-item:not([data-kt-menu-trigger]) > .menu-link', + 'click', + function (this: HTMLElement, e: Event) { + e.stopPropagation() + const menu = MenuComponent.getInstance(this) + if (menu && menu.link) { + return menu.link(this, e) + } + } + ) + + // Dismiss handler + DOMEventHandlerUtil.on( + document.body, + '[data-kt-menu-dismiss="true"]', + 'click', + function (this: HTMLElement, e: Event) { + const menu = MenuComponent.getInstance(this) as MenuComponent + if (menu) { + return menu.dismiss(this, e) + } + } + ) + + // Mouseover handler + DOMEventHandlerUtil.on( + document.body, + '[data-kt-menu-trigger], .menu-sub', + 'mouseover', + function (this: HTMLElement, e: Event) { + const menu = MenuComponent.getInstance(this) as MenuComponent + if (menu && menu.getItemSubType(this) === 'dropdown') { + return menu.mouseover(this, e) + } + } + ) + + // Mouseout handler + DOMEventHandlerUtil.on( + document.body, + '[data-kt-menu-trigger], .menu-sub', + 'mouseout', + function (this: HTMLElement, e: Event) { + const menu = MenuComponent.getInstance(this) as MenuComponent + if (menu && menu.getItemSubType(this) === 'dropdown') { + return menu.mouseout(this, e) + } + } + ) + + // Resize handler + window.addEventListener('resize', () => { + let timer + throttle( + timer, + () => { + // Locate and update Drawer instances on window resize + const elements = document.querySelectorAll('[data-kt-menu="true"]') + elements.forEach((el) => { + const menu = MenuComponent.getInstance(el as HTMLElement) + if (menu) { + menu.update() + } + }) + }, + 200 + ) + }) + } + + public static bootstrap = () => { + MenuComponent.initGlobalHandlers() + MenuComponent.createInstances('[data-kt-menu="true"]') + } + + public static reinitialization = () => { + MenuComponent.createInstances('[data-kt-menu="true"]') + } + + public static createInsance = ( + selector: string, + options: MenuOptions = defaultMenuOptions + ): MenuComponent | undefined => { + const element = document.body.querySelector(selector) + if (!element) { + return + } + const item = element as HTMLElement + let menu = MenuComponent.getInstance(item) + if (!menu) { + menu = new MenuComponent(item, options) + } + return menu + } +} + +export {MenuComponent, defaultMenuOptions} diff --git a/src/_res/assets/ts/components/SearchComponent.ts b/src/_res/assets/ts/components/SearchComponent.ts new file mode 100644 index 0000000..88a6609 --- /dev/null +++ b/src/_res/assets/ts/components/SearchComponent.ts @@ -0,0 +1,478 @@ +import { + EventHandlerUtil, + DataUtil, + getBreakpoint, + getAttributeValueByBreakpoint, + stringSnakeToCamel, + getObjectPropertyValueByKey, + getViewPort, + isVisibleElement, + throttle, +} from '../_utils/index' + +import {MenuComponent, defaultMenuOptions} from './MenuComponent' + +export interface ISearchOptions { + minLength: number // Miniam text lenght to query search + keypress: boolean // Enable search on keypress + enter: boolean // Enable search on enter key press + layout: 'menu' | 'inline' // Use 'menu' or 'inline' layout options to display search results + responsive?: number // Pass integer value or bootstrap compatible breakpoint key(sm,md,lg,xl,xxl) to enable reponsive form mode for device width below the breakpoint value + showOnFocus: boolean // Always show menu on input focus +} + +export interface ISearchQueries { + componentName: string + instanseQuery: string + attrQuery: string +} + +const defaultSearchOptions: ISearchOptions = { + minLength: 2, // Miniam text lenght to query search + keypress: true, // Enable search on keypress + enter: true, // Enable search on enter key press + layout: 'menu', // Use 'menu' or 'inline' layout options to display search results + showOnFocus: true, // Always show menu on input focus +} + +const defaultSearchQueires: ISearchQueries = { + componentName: 'search', + instanseQuery: '[data-kt-search]', + attrQuery: 'data-kt-search-', +} + +class SearchComponent { + element: HTMLElement + contentElement: HTMLElement + formElement: HTMLFormElement + inputElement: HTMLInputElement + spinnerElement: HTMLElement + clearElement: HTMLElement + toggleElement: HTMLElement + submitElement: HTMLElement + toolbarElement: HTMLElement + resultsElement: HTMLElement + suggestionElement: HTMLElement + emptyElement: HTMLElement + layout: any + + options: ISearchOptions + queries: ISearchQueries + + processing: boolean = false + menuObject: MenuComponent | undefined + + constructor(_element: HTMLElement, _options: ISearchOptions, _queries: ISearchQueries) { + // Variables + this.options = Object.assign(defaultSearchOptions, _options) + this.queries = _queries + + // Elements + this.element = _element + this.contentElement = this._getElement('content') as HTMLElement + this.formElement = this._getElement('form') as HTMLFormElement + this.inputElement = this._getElement('input') as HTMLInputElement + this.spinnerElement = this._getElement('spinner') as HTMLElement + this.clearElement = this._getElement('clear') as HTMLElement + this.toggleElement = this._getElement('toggle') as HTMLElement + this.submitElement = this._getElement('submit') as HTMLElement + this.toolbarElement = this._getElement('toolbar') as HTMLElement + + this.resultsElement = this._getElement('results') as HTMLElement + this.suggestionElement = this._getElement('suggestion') as HTMLElement + this.emptyElement = this._getElement('empty') as HTMLElement + + // Layout + this.layout = this.getOption('layout') + if (this.layout === 'menu') { + this.menuObject = new MenuComponent(this.contentElement, defaultMenuOptions) + } + + // Update + this.update() + + // Event Handlers + this.handlers() + + DataUtil.set(this.element, this.queries.componentName, this) + } + + private _getElement = (name: string) => { + return this.element.querySelector('[data-kt-search-element="' + name + '"]') + } + + // Get option + private getOption = (name: string) => { + const attr = this.element.getAttribute(`${this.queries.attrQuery}${name}`) + if (attr) { + let value = getAttributeValueByBreakpoint(attr) + + if (value !== null && String(value) === 'true') { + return true + } else if (value !== null && String(value) === 'false') { + return false + } + + return value + } else { + const optionName = stringSnakeToCamel(name) + + const option = getObjectPropertyValueByKey(this.options, optionName) + if (option) { + return getAttributeValueByBreakpoint(option) + } else { + return null + } + } + } + + // Check if responsive form mode is enabled + private getResponsiveFormMode = () => { + const responsive = this.getOption('responsive') as string + const width = getViewPort().width + + if (!responsive) { + return null + } + + const breakpoint = getBreakpoint(responsive) + let breakPointNum = -1 + if (!breakpoint) { + breakPointNum = parseInt(responsive) + } else { + breakPointNum = +breakpoint + } + + if (width < breakPointNum) { + return 'on' + } else { + return 'off' + } + } + + // Focus + private focus = () => { + this.element.classList.add('focus') + + if ( + this.getOption('show-on-focus') === true || + this.inputElement.value.length >= this.options.minLength + ) { + this.show() + } + } + + // Blur + private blur = () => { + this.element.classList.remove('focus') + } + + // Enter + private enter = (e: KeyboardEvent) => { + const key = e.charCode || e.keyCode || 0 + + if (key === 13) { + e.preventDefault() + + this.search() + } + } + + // Input + private input = () => { + if (this.getOption('min-length')) { + const minLength = parseInt(this.getOption('min-length') as string) + + if (this.inputElement.value.length >= minLength) { + this.search() + } else if (this.inputElement.value.length === 0) { + this.clear() + } + } + } + + private handlers(): void { + const context = this + + // Focus + this.inputElement.addEventListener('focus', this.focus) + + // Blur + this.inputElement.addEventListener('blur', this.blur) + + // Keypress + if (this.getOption('keypress') === true) { + this.inputElement.addEventListener('input', this.input) + } + + // Submit + if (this.submitElement) { + this.submitElement.addEventListener('click', this.search) + } + + // Enter + if (this.getOption('enter') === true) { + this.inputElement.addEventListener('keypress', this.enter) + } + + // Clear + if (this.clearElement) { + this.clearElement.addEventListener('click', this.clear) + } + + // Menu + if (this.menuObject) { + // Toggle menu + if (this.toggleElement) { + this.toggleElement.addEventListener('click', this.show) + + this.menuObject.on('kt.menu.dropdown.show', function () { + // @ts-ignore + if (isVisibleElement(context.toggleElement)) { + // @ts-ignore + context.toggleElement.classList.add('active') + // @ts-ignore + context.toggleElement.classList.add('show') + } + }) + + this.menuObject.on('kt.menu.dropdown.hide', function () { + // @ts-ignore + if (isVisibleElement(context.toggleElement)) { + // @ts-ignore + context.toggleElement.classList.remove('active') + // @ts-ignore + context.toggleElement.classList.remove('show') + } + }) + } + + this.menuObject.on('kt.menu.dropdown.shown', function () { + // @ts-ignore + context.inputElement.focus() + }) + } + + // Window resize handling + window.addEventListener('resize', () => { + let timer + + throttle( + timer, + () => { + this.update() + }, + 200 + ) + }) + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + // Update + public update = () => { + // Handle responsive form + if (this.layout === 'menu') { + let responsiveFormMode = this.getResponsiveFormMode() + + if (responsiveFormMode === 'on' && !this.contentElement.contains(this.formElement)) { + this.contentElement.prepend(this.formElement) + this.formElement.classList.remove('d-none') + } else if (responsiveFormMode === 'off' && this.contentElement.contains(this.formElement)) { + this.element.prepend(this.formElement) + this.formElement.classList.add('d-none') + } + } + } + + // Show menu + public show = () => { + if (this.menuObject) { + this.update() + + this.menuObject.show(this.element) + } + } + + // Hide menu + public hide = () => { + if (this.menuObject) { + this.update() + + this.menuObject.hide(this.element) + } + } + + // Search + public search = () => { + if (!this.processing) { + // Show search spinner + if (this.spinnerElement) { + this.spinnerElement.classList.remove('d-none') + } + + // Hide search clear button + if (this.clearElement) { + this.clearElement.classList.add('d-none') + } + + // Hide search toolbar + if (this.toolbarElement) { + this.toolbarElement.classList.add('d-none') + } + + // Focus input + this.inputElement.focus() + + this.processing = true + EventHandlerUtil.trigger(this.element, 'kt.search.process', this) + } + } + + // Complete + public complete = () => { + if (this.spinnerElement) { + this.spinnerElement.classList.add('d-none') + } + + // Show search toolbar + if (this.clearElement) { + this.clearElement.classList.remove('d-none') + } + + if (this.inputElement.value.length === 0) { + this.clear() + } + + // Focus input + this.inputElement.focus() + + this.show() + + this.processing = false + } + + // Clear + public clear = () => { + if (EventHandlerUtil.trigger(this.element, 'kt.search.clear') === false) { + return + } + + // Clear and focus input + this.inputElement.value = '' + this.inputElement.focus() + + // Hide clear icon + if (this.clearElement) { + this.clearElement.classList.add('d-none') + } + + // Show search toolbar + if (this.toolbarElement) { + this.toolbarElement.classList.remove('d-none') + } + + // Hide menu + if (this.getOption('show-on-focus') === false) { + this.hide() + } + + EventHandlerUtil.trigger(this.element, 'kt.search.cleared') + } + + public isProcessing = () => { + return this.processing + } + + public getQuery = () => { + return this.inputElement.value + } + + public getMenu = () => { + return this.menuObject + } + + public getFormElement = () => { + return this.formElement + } + + public getInputElement(): HTMLInputElement { + return this.inputElement + } + + public getContentElement(): HTMLElement { + return this.contentElement + } + + public getElement(): HTMLElement { + return this.element + } + + // Event API + public on = (name: string, handler: Function) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: Function) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handlerId: string) => { + return EventHandlerUtil.off(this.element, name, handlerId) + } + + // Static methods + public static getInstance = ( + el: HTMLElement, + componentName: string = defaultSearchQueires.componentName + ) => { + const Search = DataUtil.get(el, componentName) + if (Search) { + return Search as SearchComponent + } + + return null + } + + public static createInstances = ( + selector: string = defaultSearchQueires.instanseQuery, + options: ISearchOptions = defaultSearchOptions, + queries: ISearchQueries = defaultSearchQueires + ) => { + const elements = document.body.querySelectorAll(selector) + elements.forEach((el) => { + const item = el as HTMLElement + let Search = SearchComponent.getInstance(item) + if (!Search) { + Search = new SearchComponent(item, options, queries) + } + }) + } + + public static createInsance = ( + selector: string = defaultSearchQueires.instanseQuery, + options: ISearchOptions = defaultSearchOptions, + queries: ISearchQueries = defaultSearchQueires + ): SearchComponent | undefined => { + const element = document.body.querySelector(selector) + if (!element) { + return + } + const item = element as HTMLElement + let Search = SearchComponent.getInstance(item) + if (!Search) { + Search = new SearchComponent(item, options, queries) + } + return Search + } + + public static bootstrap = (selector: string = defaultSearchQueires.instanseQuery) => { + SearchComponent.createInstances(selector) + } + + public static reinitialization = (selector: string = defaultSearchQueires.instanseQuery) => { + SearchComponent.createInstances(selector) + } +} +export {SearchComponent, defaultSearchOptions, defaultSearchQueires} diff --git a/src/_res/assets/ts/components/_CookieComponent.ts b/src/_res/assets/ts/components/_CookieComponent.ts new file mode 100644 index 0000000..67b3d44 --- /dev/null +++ b/src/_res/assets/ts/components/_CookieComponent.ts @@ -0,0 +1,60 @@ +/* eslint-disable no-useless-escape */ +// DOCS: https://javascript.info/cookie +export class CookieComponent { + /** + * Returns the cookie with the given name, or undefined if not found + * + * @param {string} name - cookie name + * @returns string | null + */ + public static get(name: string): string | undefined { + let matches = document.cookie.match( + new RegExp('(?:^|; )' + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + '=([^;]*)') + ) + return matches ? decodeURIComponent(matches[1]) : undefined + } + + /** + * Please note that a cookie value is encoded, + * so getCookie uses a built-in decodeURIComponent function to decode it. + * + * @param {string} name - cookie name + * @param {string | number | boolean} value - cookie value + * @param {any} cookieOptions - cookie options + * @returns void + */ + public static set(name: string, value: string | number | boolean, cookieOptions: any): void { + const options = { + path: '/', + // add other defaults here if necessary + ...cookieOptions, + } + + if (options.expires instanceof Date) { + options.expires = options.expires.toUTCString() + } + + let updatedCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + + for (let optionKey in options) { + updatedCookie += '; ' + optionKey + let optionValue = options[optionKey] + if (optionValue !== true) { + updatedCookie += '=' + optionValue + } + } + + document.cookie = updatedCookie + } + + /** + * To delete a cookie, we can call it with a negative expiration date + * + * @param {string} name + */ + public static delete(name: string): void { + CookieComponent.set(name, '', { + 'max-age': -1, + }) + } +} diff --git a/src/_res/assets/ts/components/_DrawerComponent.ts b/src/_res/assets/ts/components/_DrawerComponent.ts new file mode 100644 index 0000000..6dbfd44 --- /dev/null +++ b/src/_res/assets/ts/components/_DrawerComponent.ts @@ -0,0 +1,385 @@ +import { + EventHandlerUtil, + getUniqueIdWithPrefix, + getObjectPropertyValueByKey, + stringSnakeToCamel, + getAttributeValueByBreakpoint, + throttle, + getCSS, + DOMEventHandlerUtil, + ElementStyleUtil, +} from '../_utils/index' + +export class DrawerStore { + static store: Map = new Map() + + public static set(instanceId: string, drawerComponentObj: DrawerComponent): void { + if (DrawerStore.has(instanceId)) { + return + } + + DrawerStore.store.set(instanceId, drawerComponentObj) + } + + public static get(instanceId: string): DrawerComponent | undefined { + if (!DrawerStore.has(instanceId)) { + return + } + return DrawerStore.store.get(instanceId) + } + + public static remove(instanceId: string): void { + if (!DrawerStore.has(instanceId)) { + return + } + + DrawerStore.store.delete(instanceId) + } + + public static has(instanceId: string): boolean { + return DrawerStore.store.has(instanceId) + } + + public static getAllInstances() { + return DrawerStore.store + } +} + +export interface DrawerOptions { + overlay: boolean + baseClass: string + overlayClass: string + direction: string +} + +const defaultDrawerOptions: DrawerOptions = { + overlay: true, + baseClass: 'drawer', + overlayClass: 'drawer-overlay', + direction: 'end', +} + +class DrawerComponent { + element: HTMLElement + overlayElement: HTMLElement | null = null + toggleElement: HTMLElement | null = null + options: DrawerOptions + instanceUid: string + name: string = '' + shown: boolean = false + lastWidth: number = 0 + closeElement: HTMLElement | null = null + + constructor(_element: HTMLElement, options: DrawerOptions) { + this.element = _element + this.options = Object.assign(defaultDrawerOptions, options) + this.instanceUid = getUniqueIdWithPrefix('drawer') + this.overlayElement = null + this.name = this.element.getAttribute('data-kt-drawer-name') || '' + this.shown = false + this.toggleElement = null + // Event Handlers + this._handlers() + // Update Instance + this._update() + // Bind Instance + DrawerStore.set(this.element.id, this) + } + + private _handlers = () => { + const togglers = this._getOption('toggle') as string + const closers = this._getOption('close') as string + + if (togglers !== null && togglers.length > 0) { + DOMEventHandlerUtil.on(document.body, togglers, 'click', (e: Event) => { + e.preventDefault() + this.toggleElement = document.getElementById(togglers) + this._toggle() + }) + } + + if (closers !== null && closers.length > 0) { + DOMEventHandlerUtil.on(document.body, closers, 'click', (e: Event) => { + e.preventDefault() + this.closeElement = document.getElementById(closers) + + this._hide() + }) + } + } + + private _update = () => { + const width = String(this._getOption('width')) + const direction = String(this._getOption('direction')) + + // Reset state + const hasBaseClass = this.element.classList.contains(`${this.options.baseClass}-on`) + const bodyCanvasAttr = String(document.body.getAttribute(`data-kt-drawer-${this.name}-`)) + + if (hasBaseClass === true && bodyCanvasAttr === 'on') { + this.shown = true + } else { + this.shown = false + } + + // Activate/deactivate + if (this._getOption('activate') === true) { + this.element.classList.add(this.options.baseClass) + this.element.classList.add(`${this.options.baseClass}-${direction}`) + ElementStyleUtil.set(this.element, 'width', width, true) + + this.lastWidth = parseInt(width) + } else { + ElementStyleUtil.set(this.element, 'width', '') + this.element.classList.remove(this.options.baseClass) + this.element.classList.remove(`${this.options.baseClass}-${direction}`) + this._hide() + } + } + + private _getOption = (name: string) => { + const attr = this.element.getAttribute(`data-kt-drawer-${name}`) + if (attr) { + let value = getAttributeValueByBreakpoint(attr) + if (value !== null && String(value) === 'true') { + return true + } else { + if (value !== null && String(value) === 'false') { + return false + } + } + + return value + } else { + const optionName = stringSnakeToCamel(name) + const option = getObjectPropertyValueByKey(this.options, optionName) + if (option) { + return getAttributeValueByBreakpoint(option) + } else { + return null + } + } + } + + private _toggle = () => { + if (EventHandlerUtil.trigger(this.element, 'kt.drawer.toggle') === false) { + return + } + + if (this.shown) { + this._hide() + } else { + this._show() + } + + EventHandlerUtil.trigger(this.element, 'kt.drawer.toggled') + } + + private _hide = () => { + if (EventHandlerUtil.trigger(this.element, 'kt.drawer.hide') === false) { + return + } + + this.shown = false + this._deleteOverlay() + document.body.removeAttribute(`data-kt-drawer-${this.name}`) + document.body.removeAttribute(`data-kt-drawer`) + this.element.classList.remove(`${this.options.baseClass}-on`) + if (this.toggleElement != null) { + this.toggleElement.classList.remove('active') + } + + EventHandlerUtil.trigger(this.element, 'kt.drawer.after.hidden') + } + + private _show = () => { + if (EventHandlerUtil.trigger(this.element, 'kt.drawer.show') === false) { + return + } + + this.shown = true + this._createOverlay() + document.body.setAttribute(`data-kt-drawer-${this.name}`, 'on') + document.body.setAttribute('data-kt-drawer', 'on') + this.element.classList.add(`${this.options.baseClass}-on`) + if (this.toggleElement !== null) { + this.toggleElement.classList.add('active') + } + + EventHandlerUtil.trigger(this.element, 'kt.drawer.shown') + } + + private _createOverlay = () => { + if (this._getOption('overlay') === true) { + this.overlayElement = document.createElement('DIV') + const elementZIndex = getCSS(this.element, 'z-index') + if (elementZIndex) { + const overlayZindex = parseInt(elementZIndex) - 1 + ElementStyleUtil.set(this.overlayElement, 'z-index', overlayZindex) // update + } + document.body.append(this.overlayElement) + const overlayClassOption = this._getOption('overlay-class') + if (overlayClassOption) { + this.overlayElement.classList.add(overlayClassOption.toString()) + } + this.overlayElement.addEventListener('click', (e) => { + e.preventDefault() + this._hide() + }) + } + } + + private _deleteOverlay = () => { + if (this.overlayElement !== null && this.overlayElement.parentNode) { + this.overlayElement.parentNode.removeChild(this.overlayElement) + } + } + + private _getDirection = () => { + return String(this._getOption('direction')) === 'left' ? 'left' : 'right' + } + + private _getWidth = () => { + let width = this._getOption('width') + if (width && width === 'auto') { + width = getCSS(this.element, 'width') + } + + return width + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + public toggle = () => { + this._toggle() + } + + public show = () => { + this._show() + } + + public hide = () => { + this._hide() + } + + public isShown = () => { + return this.shown + } + + public update = () => { + this._update() + } + + public goElement = () => { + return this.element + } + + // Event API + public on = (name: string, handler: Function) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: Function) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handerId: string) => { + return EventHandlerUtil.off(this.element, name, handerId) + } + + public trigger = (name: string, event: Event) => { + return EventHandlerUtil.trigger(this.element, name, event) + } + + // Static methods + public static hasInstace = (elementId: string): boolean => { + return DrawerStore.has(elementId) + } + + public static getInstance = (elementId: string) => { + return DrawerStore.get(elementId) + } + + public static hideAll = () => { + const oldInstances = DrawerStore.getAllInstances() + oldInstances.forEach((dr) => { + dr.hide() + }) + } + + public static updateAll = () => { + const oldInstances = DrawerStore.getAllInstances() + oldInstances.forEach((dr) => { + dr.update() + }) + } + + // Create Instances + public static createInstances(selector: string): void { + const elements = document.body.querySelectorAll(selector) + elements.forEach((element) => { + const item = element as HTMLElement + let drawer = DrawerComponent.getInstance(item.id) + if (!drawer) { + drawer = new DrawerComponent(item, defaultDrawerOptions) + } + drawer.element = item + drawer.hide() + }) + } + + // Dismiss instances + public static handleDismiss = () => { + // External drawer toggle handler + DOMEventHandlerUtil.on(document.body, '[data-kt-drawer-dismiss="true"]', 'click', () => { + /* @ts-ignore */ + const element = this.closest('[data-kt-drawer="true"]') + if (element) { + const drawer = DrawerComponent.getInstance(element) + if (drawer && drawer.isShown()) { + drawer.hide() + } + } + }) + } + + // Global Initialization + public static initGlobalHandlers(): void { + // Window Resize Handling + window.addEventListener('resize', function () { + let timer: number | undefined + throttle( + timer, + () => { + // Locate and update Drawer instances on window resize + const elements = document.body.querySelectorAll('[data-kt-drawer="true"]') + elements.forEach((el) => { + const item = el as HTMLElement + const instance = DrawerComponent.getInstance(item.id) + if (instance) { + instance.element = item + instance.update() + } + }) + }, + 200 + ) + }) + } + + public static bootstrap = () => { + DrawerComponent.createInstances('[data-kt-drawer="true"]') + DrawerComponent.initGlobalHandlers() + DrawerComponent.handleDismiss() + } + + public static reinitialization = () => { + DrawerComponent.createInstances('[data-kt-drawer="true"]') + DrawerComponent.hideAll() + DrawerComponent.updateAll() + DrawerComponent.handleDismiss() + } +} + +export {DrawerComponent, defaultDrawerOptions} diff --git a/src/_res/assets/ts/components/_FeedbackComponent.ts b/src/_res/assets/ts/components/_FeedbackComponent.ts new file mode 100644 index 0000000..c3ebb12 --- /dev/null +++ b/src/_res/assets/ts/components/_FeedbackComponent.ts @@ -0,0 +1,152 @@ +import { + DataUtil, + ElementStyleUtil, + EventHandlerUtil, + getUniqueIdWithPrefix, + getAttributeValueByBreakpoint, +} from '../_utils/index' + +export interface FeedbackOptions { + width?: number + placement?: string + content?: string + type?: string +} + +const defaultFeedbackOptions: FeedbackOptions = { + width: 100, + placement: 'top-center', + content: '', + type: 'popup', +} + +class FeedbackComponent { + element: HTMLElement + options: FeedbackOptions + instanceUid: string + shown: boolean + + constructor(_element: HTMLElement, options: FeedbackOptions) { + this.element = _element + this.options = Object.assign(defaultFeedbackOptions, options) + this.instanceUid = getUniqueIdWithPrefix('feedback') + this.shown = false + + // Event handlers + this._handlers() // will add in the show popup + DataUtil.set(this.element, 'feedback', this) + } + + private _handlers = () => { + this.element.addEventListener('click', (e: Event) => { + e.preventDefault() + this._go() + }) + } + + private _go = () => {} + + private showPopup = () => { + this.element = document.createElement('DIV') + + this.element.classList.add('feedback feedback-popup') + this.element.innerHTML = this.options.content || '' + + if (this.options.placement === 'top-center') { + this.setPopupTopCenterPosition() + } + + document.body.appendChild(this.element) + this.element.classList.add('feedback-shown') + this.shown = true + } + + private setPopupTopCenterPosition = () => { + const width = getAttributeValueByBreakpoint(this.options.width?.toString() || '0') + const height = ElementStyleUtil.get(this.element, 'height') + this.element.classList.add('feedback-top-center') + ElementStyleUtil.set(this.element, 'width', width) + ElementStyleUtil.set(this.element, 'left', '50%') + ElementStyleUtil.set(this.element, 'top', '-' + height) + } + + private hidePopup = () => { + this.element.remove() + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + public show = () => { + if (EventHandlerUtil.trigger(this.element, 'kt.feedback.show') === false) { + return + } + + if (this.options.type === 'popup') { + this.showPopup() + } + + EventHandlerUtil.trigger(this.element, 'kt.feedback.shown') + + return this + } + + public hide = () => { + if (EventHandlerUtil.trigger(this.element, 'kt.feedback.hide') === false) { + return + } + + if (this.options.type === 'popup') { + this.hidePopup() + } + + this.shown = false + EventHandlerUtil.trigger(this.element, 'kt.feedback.hidden') + return this + } + + public isShown = () => { + return this.isShown + } + + public getElement = () => { + return this.element + } + + // Event API + public on = (name: string, handler: Function) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: Function) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handerId: string) => { + return EventHandlerUtil.off(this.element, name, handerId) + } + + public trigger = (name: string, event: Event) => { + return EventHandlerUtil.trigger(this.element, name, event) + } + + // Create Instances + public static createInstances(selector: string) { + throw new Error('not implemented') + } + + // Static methods + public static hasInstace(element: HTMLElement) { + throw new Error('not implemented') + } + + public static getInstance(element: HTMLElement) { + throw new Error('not implemented') + } + + public static bootstrap(attr: string = '[data-Feedback]') { + throw new Error('not implemented') + } +} + +export {FeedbackComponent, defaultFeedbackOptions} diff --git a/src/_res/assets/ts/components/_ImageInputComponent.ts b/src/_res/assets/ts/components/_ImageInputComponent.ts new file mode 100644 index 0000000..1301a95 --- /dev/null +++ b/src/_res/assets/ts/components/_ImageInputComponent.ts @@ -0,0 +1,229 @@ +import {EventHandlerUtil, DataUtil, getUniqueIdWithPrefix, getCSS} from '../_utils/index' + +export interface IImageInputOptions {} + +export interface IImageInputQueries { + componentName: string + instanseQuery: string + inputQuery: string + wrapperQuery: string + cancelQuery: string + removeQuery: string + hiddenQuery: string +} + +const defaultImageInputOptions = {} + +const defaultImageInputQueires: IImageInputQueries = { + componentName: 'image-input', + instanseQuery: '[data-kt-image-input]', + inputQuery: 'input[type="file"]', + wrapperQuery: '.image-input-wrapper', + cancelQuery: '[data-kt-image-input-action="cancel"]', + removeQuery: '[data-kt-image-input-action="remove"]', + hiddenQuery: 'input[type="hidden"]', +} + +class ImageInputComponent { + element: HTMLElement + inputElement: HTMLInputElement | null + wrapperElement: HTMLElement | null + cancelElement: HTMLElement | null + removeElement: HTMLElement | null + hiddenElement: HTMLInputElement | null + src: string = '' + options: IImageInputOptions + queries: IImageInputQueries + uid: string + value: string = '' + + constructor(_element: HTMLElement, _options: IImageInputOptions, _queries: IImageInputQueries) { + // Variables + this.options = Object.assign(defaultImageInputOptions, _options) + this.queries = _queries + this.uid = getUniqueIdWithPrefix(this.queries.componentName) + + // Elements + this.element = _element + this.inputElement = this.element.querySelector(this.queries.inputQuery) + this.wrapperElement = this.element.querySelector(this.queries.wrapperQuery) + this.cancelElement = this.element.querySelector(this.queries.cancelQuery) + this.removeElement = this.element.querySelector(this.queries.removeQuery) + this.hiddenElement = this.element.querySelector(this.queries.hiddenQuery) + if (this.wrapperElement) { + this.src = getCSS(this.wrapperElement, 'backgroundImage') + } + + // Event Handlers + this.handlers() + + DataUtil.set(this.element, this.queries.componentName, this) + } + + private handlers(): void { + this.element.addEventListener('change', this._change) + if (this.cancelElement) { + this.cancelElement.addEventListener('click', this._cancel) + } + + if (this.removeElement) { + this.removeElement.addEventListener('click', this._cancel) + } + } + + // Event Handlers + private _change = (e: Event) => { + e.preventDefault() + + if (this.inputElement !== null && this.inputElement.files && this.inputElement.files[0]) { + // Fire change event + if (EventHandlerUtil.trigger(this.element, 'kt.imageinput.change', e) === false) { + return + } + + const reader = new FileReader() + + reader.onload = (e: ProgressEvent) => { + if (this.wrapperElement && e.target) { + this.wrapperElement.style.setProperty('background-image', `url('${e.target.result}')`) + } + } + + reader.readAsDataURL(this.inputElement.files[0]) + this.element.classList.add('image-input-changed') + this.element.classList.remove('image-input-empty') + + // Fire removed event + EventHandlerUtil.trigger(this.element, 'kt.imageinput.changed', e) + } + } + + private _cancel = (e: Event) => { + e.preventDefault() + + // Fire cancel event + if (EventHandlerUtil.trigger(this.element, 'kt.imageinput.cancel', e) === false) { + return + } + + this.element.classList.remove('image-input-changed') + this.element.classList.remove('image-input-empty') + this.element.style.setProperty('background-image', this.src) + if (this.inputElement) { + this.inputElement.value = '' + } + + if (this.hiddenElement !== null) { + this.hiddenElement.value = '0' + } + + // Fire canceled event + EventHandlerUtil.trigger(this.element, 'kt.imageinput.canceled', e) + } + + private _remove = (e: Event) => { + e.preventDefault() + + // Fire remove event + if (EventHandlerUtil.trigger(this.element, 'kt.imageinput.remove', e) === false) { + return + } + + this.element.classList.remove('image-input-changed') + this.element.classList.add('image-input-empty') + if (this.wrapperElement) { + this.wrapperElement.style.setProperty('background-image', 'none') + } + + if (this.inputElement) { + this.inputElement.value = '' + } + + if (this.hiddenElement !== null) { + this.hiddenElement.value = '1' + } + + // Fire removed event + EventHandlerUtil.trigger(this.element, 'kt.imageinput.removed', e) + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + public getInputElement(): HTMLInputElement | null { + return this.inputElement + } + + public getElement(): HTMLElement { + return this.element + } + + // Event API + public on = (name: string, handler: Function) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: Function) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handlerId: string) => { + return EventHandlerUtil.off(this.element, name, handlerId) + } + + public trigger = (name: string, event: Event) => { + return EventHandlerUtil.trigger(this.element, name, event) + } + + // Static methods + public static getInstance = ( + el: HTMLElement, + componentName: string = defaultImageInputQueires.componentName + ): ImageInputComponent | undefined => { + const ImageInput = DataUtil.get(el, componentName) + if (ImageInput) { + return ImageInput as ImageInputComponent + } + } + + public static createInstances = ( + selector: string = defaultImageInputQueires.instanseQuery, + options: IImageInputOptions = defaultImageInputOptions, + queries: IImageInputQueries = defaultImageInputQueires + ) => { + const elements = document.body.querySelectorAll(selector) + elements.forEach((el) => { + const item = el as HTMLElement + let ImageInput = ImageInputComponent.getInstance(item) + if (!ImageInput) { + ImageInput = new ImageInputComponent(item, options, queries) + } + }) + } + + public static createInsance = ( + selector: string = defaultImageInputQueires.instanseQuery, + options: IImageInputOptions = defaultImageInputOptions, + queries: IImageInputQueries = defaultImageInputQueires + ): ImageInputComponent | undefined => { + const element = document.body.querySelector(selector) + if (!element) { + return + } + const item = element as HTMLElement + let ImageInput = ImageInputComponent.getInstance(item) + if (!ImageInput) { + ImageInput = new ImageInputComponent(item, options, queries) + } + return ImageInput + } + + public static bootstrap = (selector: string = defaultImageInputQueires.instanseQuery) => { + ImageInputComponent.createInstances(selector) + } + + public static reinitialization = (selector: string = defaultImageInputQueires.instanseQuery) => { + ImageInputComponent.createInstances(selector) + } +} +export {ImageInputComponent, defaultImageInputOptions, defaultImageInputQueires} diff --git a/src/_res/assets/ts/components/_PasswordMeterComponent.ts b/src/_res/assets/ts/components/_PasswordMeterComponent.ts new file mode 100644 index 0000000..8a90252 --- /dev/null +++ b/src/_res/assets/ts/components/_PasswordMeterComponent.ts @@ -0,0 +1,273 @@ +/* eslint-disable array-callback-return */ +/* eslint-disable no-useless-escape */ +import {DataUtil} from '../_utils/index' + +export interface IPasswordMeterOptions { + minLength: number + checkUppercase: boolean + checkLowercase: boolean + checkDigit: boolean + checkChar: boolean + scoreHighlightClass: string +} + +export interface IPasswordMeterQueries { + componentName: string + instanseQuery: string + inputQuery: string + visibilityQuery: string + highlightQuery: string +} + +const defaultPasswordMeterOptions = { + minLength: 8, + checkUppercase: true, + checkLowercase: true, + checkDigit: true, + checkChar: true, + scoreHighlightClass: 'active', +} + +const defaultPasswordMeterQueires: IPasswordMeterQueries = { + componentName: 'password-meter', + instanseQuery: '[data-kt-password-meter]', + inputQuery: 'input[type]', + visibilityQuery: '[data-kt-password-meter-control="visibility"]', + highlightQuery: '[data-kt-password-meter-control="highlight"]', +} + +class PasswordMeterComponent { + element: HTMLElement + inputElement: HTMLInputElement | null + visibilityElement: HTMLElement | null + highlightElement: HTMLElement | null + options: IPasswordMeterOptions + queries: IPasswordMeterQueries + score: number + checkSteps: number + + constructor( + _element: HTMLElement, + _options: IPasswordMeterOptions, + _queries: IPasswordMeterQueries + ) { + this.element = _element + this.options = Object.assign(defaultPasswordMeterOptions, _options) + this.queries = _queries + this.score = 0 + this.checkSteps = 5 + + // Elements + this.inputElement = this.element.querySelector(this.queries.inputQuery) + this.visibilityElement = this.element.querySelector(this.queries.visibilityQuery) + this.highlightElement = this.element.querySelector(this.queries.highlightQuery) + + // Event Handlers + this.handlers() + + DataUtil.set(this.element, this.queries.componentName, this) + } + + private handlers(): void { + if (this.inputElement) { + this.inputElement.addEventListener('input', () => { + this.check() + }) + } + + if (this.visibilityElement) { + this.visibilityElement.addEventListener('click', () => { + this.visitbility() + }) + } + } + + private visitbility() { + if (this.visibilityElement && this.inputElement) { + const visibleIcon = this.visibilityElement.querySelector( + 'i:not(.d-none), .svg-icon:not(.d-none)' + ) + + const hiddenIcon = this.visibilityElement.querySelector('i.d-none, .svg-icon.d-none') + + const typeAttr = this.inputElement.getAttribute('type') || '' + + if (typeAttr === 'password') { + this.inputElement.setAttribute('type', 'text') + } else { + this.inputElement.setAttribute('type', 'password') + } + + visibleIcon?.classList.add('d-none') + hiddenIcon?.classList.remove('d-none') + + this.inputElement.focus() + } + } + + private checkScore(): number { + return 0 + } + + private checkLength(): boolean { + if (this.inputElement) { + return this.inputElement.value.length >= this.options.minLength // 20 score + } + + return false + } + + private checkLowerCase(): boolean { + const val = this.inputElement ? this.inputElement.value : '' + return /[a-z]/.test(val) // 20 score + } + + private checkUppercase(): boolean { + const val = this.inputElement ? this.inputElement.value : '' + return /[A-Z]/.test(val) // 20 score + } + + private checkDigit(): boolean { + const val = this.inputElement ? this.inputElement.value : '' + return /[0-9]/.test(val) // 20 score + } + + private checkChar(): boolean { + const val = this.inputElement ? this.inputElement.value : '' + return /[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(val) // 20 score + } + + private getCheckScore(): number { + let count = 1 + if (this.options.checkUppercase) { + count++ + } + + if (this.options.checkLowercase) { + count++ + } + + if (this.options.checkDigit) { + count++ + } + + if (this.options.checkChar) { + count++ + } + + this.checkSteps = count + return 100 / this.checkSteps + } + + private highlight() { + const items = this.highlightElement + ? [].slice.call(this.highlightElement.querySelectorAll('div')) + : [] + const total = items.length + let index = 0 + const checkScore = this.getCheckScore() + const score = this.getScore() + + items.map((item: HTMLElement) => { + index++ + if (checkScore * index * (this.checkSteps / total) <= score) { + item.classList.add('active') + } else { + item.classList.remove('active') + } + }) + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + public reset = () => { + this.score = 0 + this.highlight() + } + + public getScore() { + return this.score + } + + public check() { + let score = 0 + const checkScore = this.getCheckScore() + if (this.checkLength()) { + score = score + checkScore + } + + if (this.options.checkUppercase && this.checkLowerCase()) { + score = score + checkScore + } + + if (this.options.checkLowercase && this.checkUppercase()) { + score = score + checkScore + } + + if (this.options.checkDigit && this.checkDigit()) { + score = score + checkScore + } + + if (this.options.checkChar && this.checkChar()) { + score = score + checkScore + } + + this.score = score + this.highlight() + } + + // Static methods + public static getInstance = ( + el: HTMLElement, + componentName: string = defaultPasswordMeterQueires.componentName + ): PasswordMeterComponent | undefined => { + const passwordMeter = DataUtil.get(el, componentName) + if (passwordMeter) { + return passwordMeter as PasswordMeterComponent + } + } + + public static createInstances = ( + selector: string = defaultPasswordMeterQueires.instanseQuery, + options: IPasswordMeterOptions = defaultPasswordMeterOptions, + queries: IPasswordMeterQueries = defaultPasswordMeterQueires + ) => { + const elements = document.body.querySelectorAll(selector) + elements.forEach((el) => { + const item = el as HTMLElement + let passwordMeter = PasswordMeterComponent.getInstance(item) + if (!passwordMeter) { + passwordMeter = new PasswordMeterComponent(item, options, queries) + } + }) + } + + public static createInsance = ( + selector: string = defaultPasswordMeterQueires.instanseQuery, + options: IPasswordMeterOptions = defaultPasswordMeterOptions, + queries: IPasswordMeterQueries = defaultPasswordMeterQueires + ): PasswordMeterComponent | undefined => { + const element = document.body.querySelector(selector) + if (!element) { + return + } + const item = element as HTMLElement + let passwordMeter = PasswordMeterComponent.getInstance(item) + if (!passwordMeter) { + passwordMeter = new PasswordMeterComponent(item, options, queries) + } + return passwordMeter + } + + public static bootstrap = (selector: string = defaultPasswordMeterQueires.instanseQuery) => { + PasswordMeterComponent.createInstances(selector) + } + + public static reinitialization = ( + selector: string = defaultPasswordMeterQueires.instanseQuery + ) => { + PasswordMeterComponent.createInstances(selector) + } +} +export {PasswordMeterComponent, defaultPasswordMeterOptions, defaultPasswordMeterQueires} diff --git a/src/_res/assets/ts/components/_ScrollComponent.ts b/src/_res/assets/ts/components/_ScrollComponent.ts new file mode 100644 index 0000000..67a461f --- /dev/null +++ b/src/_res/assets/ts/components/_ScrollComponent.ts @@ -0,0 +1,312 @@ +import { + DataUtil, + getObjectPropertyValueByKey, + stringSnakeToCamel, + getAttributeValueByBreakpoint, + getViewPort, + isVisibleElement, + throttle, + getCSS, + ElementStyleUtil, +} from '../_utils/index' +import {CookieComponent} from './_CookieComponent' + +export interface ScrollOptions { + saveState?: boolean +} + +const defaultScrollOptions: ScrollOptions = { + saveState: true, +} + +class ScrollComponent { + element: HTMLElement + options: ScrollOptions + id: string + + constructor(_element: HTMLElement, options: ScrollOptions) { + this.element = _element + this.options = Object.assign(defaultScrollOptions, options) + this.id = this.element.getAttribute('id') || '' + this.update() + // this.element.setAttribute('data-kt-scrolltop', 'true') + DataUtil.set(this.element, 'scroll', this) + } + + private getOption = (name: string) => { + if (this.element.hasAttribute('data-kt-scroll-' + name) === true) { + const attr = this.element.getAttribute('data-kt-scroll-' + name) || '' + let value: string | JSON | boolean = getAttributeValueByBreakpoint(attr) + if (value !== null && String(value) === 'true') { + value = true + } else if (value !== null && String(value) === 'false') { + value = false + } + + return value + } else { + const optionName = stringSnakeToCamel(name) + const option = getObjectPropertyValueByKey(this.options, optionName) + if (option) { + return getAttributeValueByBreakpoint(option) + } else { + return null + } + } + } + + private getHeightType = () => { + if (this.getOption('height')) { + return 'height' + } + if (this.getOption('min-height')) { + return 'min-height' + } + if (this.getOption('max-height')) { + return 'max-height' + } + } + + private getAutoHeight = () => { + let height: number | string = getViewPort().height + const dependencies = this.getOption('dependencies') + const wrappers = this.getOption('wrappers') + const offset = this.getOption('offset') + + // Height dependencies + if (dependencies !== null) { + const elements = document.querySelectorAll(dependencies as string) + if (elements && elements.length > 0) { + for (let i = 0, len = elements.length; i < len; i++) { + const element = elements[i] as HTMLElement + if (isVisibleElement(element) === false) { + continue + } + + height = height - parseInt(getCSS(element, 'height')) + height = height - parseInt(getCSS(element, 'margin-top')) + height = height - parseInt(getCSS(element, 'margin-bottom')) + + const borderTop = getCSS(element, 'border-top') + if (borderTop) { + height = height - parseInt(borderTop) + } + + const borderBottom = getCSS(element, 'border-bottom') + if (borderBottom) { + height = height - parseInt(borderBottom) + } + } + } + } + + // Wrappers + if (wrappers !== null) { + var elements = document.querySelectorAll(wrappers as string) + if (elements && elements.length > 0) { + for (let i = 0, len = elements.length; i < len; i++) { + const element = elements[i] as HTMLElement + + if (!isVisibleElement(element)) { + continue + } + + height = height - parseInt(getCSS(element, 'margin-top')) + height = height - parseInt(getCSS(element, 'margin-bottom')) + height = height - parseInt(getCSS(element, 'padding-top')) + height = height - parseInt(getCSS(element, 'padding-bottom')) + + const borderTop = getCSS(element, 'border-top') + if (borderTop) { + height = height - parseInt(borderTop) + } + + const borderBottom = getCSS(element, 'border-bottom') + if (borderBottom) { + height = height - parseInt(borderBottom) + } + } + } + } + + // Custom offset + if (offset !== null) { + height = height - parseInt(offset as string) + } + + height = height - parseInt(getCSS(this.element, 'margin-top')) + height = height - parseInt(getCSS(this.element, 'margin-bottom')) + + const borderTop = getCSS(this.element, 'border-top') + if (borderTop) { + height = height - parseInt(borderTop) + } + + const borderBottom = getCSS(this.element, 'border-bottom') + if (borderBottom) { + height = height - parseInt(borderBottom) + } + + height = String(height) + 'px' + + return height + } + + private setupHeight = () => { + let height = this.getHeight() + let heightType = this.getHeightType() as string + + // Set height + if (height !== null && height.length > 0) { + ElementStyleUtil.set(this.element, heightType, height) + } else { + ElementStyleUtil.set(this.element, heightType, '') + } + } + + private setupState = () => { + if (this.getOption('save-state') === true && this.id) { + const cookie = CookieComponent.get(this.id + 'st') + if (cookie) { + var pos = parseInt(cookie) + + if (pos > 0) { + this.element.scrollTop = pos + } + } + } + } + + private setupScrollHandler = () => { + if (this.getOption('save-state') === true && this.id) { + this.element.addEventListener('scroll', this.scrollHandler) + } else { + this.element.removeEventListener('scroll', this.scrollHandler) + } + } + + private scrollHandler = () => { + const cookieId = this.id + 'st' + CookieComponent.set(cookieId, this.element.scrollTop, {}) + } + + private destroyScrollHandler = () => { + this.element.removeEventListener('scroll', this.scrollHandler) + } + + private resetHeight = () => { + const heghtType = this.getHeightType() + if (heghtType) { + ElementStyleUtil.set(this.element, heghtType, '') + } + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + public update = () => { + // Activate/deactivate + if ( + this.getOption('activate') === true || + !this.element.hasAttribute('data-kt-scroll-activate') + ) { + this.setupHeight() + this.setupScrollHandler() + this.setupState() + } else { + this.resetHeight() + this.destroyScrollHandler() + } + } + + public getHeight = () => { + const heightType = this.getHeightType() + const height = this.getOption(heightType || '') + if (height instanceof Function) { + return height.call(height) + } else if (height !== null && typeof height === 'string' && height.toLowerCase() === 'auto') { + return this.getAutoHeight() + } else { + return height + } + } + + public getElement = () => { + return this.element + } + + // Static methods + public static hasInstace(element: HTMLElement) { + return DataUtil.has(element, 'scroll') + } + + public static getInstance(element: HTMLElement): ScrollComponent | undefined { + if (element !== null && ScrollComponent.hasInstace(element)) { + const data = DataUtil.get(element, 'scroll') + if (data) { + return data as ScrollComponent + } + } + } + + // Create Instances + public static createInstances(selector: string) { + const elements = document.body.querySelectorAll(selector) + elements.forEach((element: Element) => { + const item = element as HTMLElement + let scroll = ScrollComponent.getInstance(item) + if (!scroll) { + scroll = new ScrollComponent(item, defaultScrollOptions) + } + }) + } + + public static destroyAll(attr: string = '[data-kt-scroll="true"]') {} + + public static bootstrap(attr: string = '[data-kt-scroll="true"]') { + ScrollComponent.createInstances(attr) + ScrollComponent.resize() + } + + public static createInstance = ( + element: HTMLElement, + options: ScrollOptions = defaultScrollOptions + ): ScrollComponent | undefined => { + let scroll = ScrollComponent.getInstance(element) + if (!scroll) { + scroll = new ScrollComponent(element, options) + } + return scroll + } + + public static reinitialization(attr: string = '[data-kt-scroll="true"]') { + ScrollComponent.createInstances(attr) + } + + public static updateAll() { + const elements = document.body.querySelectorAll('[data-kt-scroll="true"]') + elements.forEach((element: Element) => { + const instance = ScrollComponent.getInstance(element as HTMLElement) + if (instance) { + instance.update() + } + }) + } + + public static resize() { + // Window Resize Handling + window.addEventListener('resize', function () { + let timer + throttle( + timer, + () => { + // Locate and update Drawer instances on window resize + ScrollComponent.updateAll() + }, + 200 + ) + }) + } +} + +export {ScrollComponent, defaultScrollOptions} diff --git a/src/_res/assets/ts/components/_ScrollTopComponent.ts b/src/_res/assets/ts/components/_ScrollTopComponent.ts new file mode 100644 index 0000000..ea8d924 --- /dev/null +++ b/src/_res/assets/ts/components/_ScrollTopComponent.ts @@ -0,0 +1,148 @@ +import { + getScrollTop, + getAttributeValueByBreakpoint, + throttle, + getObjectPropertyValueByKey, + stringSnakeToCamel, + getUniqueIdWithPrefix, + DataUtil, + ElementAnimateUtil, +} from '../_utils/index' + +export interface IScrollTopOptions { + offset: number + speed: number +} + +const defaultScrollTopOptions: IScrollTopOptions = { + offset: 200, + speed: 600, +} + +class ScrollTopComponent { + element: HTMLElement + options: IScrollTopOptions + instanceUid: string + + constructor(_element: HTMLElement, options: IScrollTopOptions) { + this.element = _element + this.options = Object.assign(defaultScrollTopOptions, options) + this.instanceUid = getUniqueIdWithPrefix('scrolltop') + + // Event Handlers + this._handlers() + + // Bind Instance + DataUtil.set(this.element, 'scrolltop', this) + } + + private _handlers = () => { + let timer: number + window.addEventListener('scroll', () => { + throttle(timer, () => { + this._scroll() + }) + }) + + this.element.addEventListener('click', (e: Event) => { + e.preventDefault() + this._go() + }) + } + + private _scroll = () => { + const offset = parseInt(this._getOption('offset') as string) + const pos = getScrollTop() // current vertical position + if (pos > offset) { + if (!document.body.hasAttribute('data-kt-scrolltop')) { + document.body.setAttribute('data-kt-scrolltop', 'on') + } + } else { + if (document.body.hasAttribute('data-kt-scrolltop')) { + document.body.removeAttribute('data-kt-scrolltop') + } + } + } + + private _go = () => { + const speed = parseInt(this._getOption('speed') as string) + ElementAnimateUtil.scrollTop(0, speed) + } + + private _getOption = (name: string) => { + const attr = this.element.getAttribute(`data-kt-scrolltop-${name}`) + if (attr) { + const value = getAttributeValueByBreakpoint(attr) + return value !== null && String(value) === 'true' + } + + const optionName = stringSnakeToCamel(name) + const option = getObjectPropertyValueByKey(this.options, optionName) + if (option) { + return getAttributeValueByBreakpoint(option) + } + + return null + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + + // Plugin API + public go = () => { + return this._go() + } + + public getElement = () => { + return this.element + } + + // Static methods + public static getInstance = (el: HTMLElement): ScrollTopComponent | undefined => { + const scrollTop = DataUtil.get(el, 'scrolltop') + if (scrollTop) { + return scrollTop as ScrollTopComponent + } + } + + public static createInstances = (selector: string) => { + const elements = document.body.querySelectorAll(selector) + elements.forEach((el) => { + const item = el as HTMLElement + let scrollTop = ScrollTopComponent.getInstance(item) + if (!scrollTop) { + scrollTop = new ScrollTopComponent(item, defaultScrollTopOptions) + } + }) + } + + public static createInsance = ( + selector: string, + options: IScrollTopOptions = defaultScrollTopOptions + ): ScrollTopComponent | undefined => { + const element = document.body.querySelector(selector) + if (!element) { + return + } + const item = element as HTMLElement + let scrollTop = ScrollTopComponent.getInstance(item) + if (!scrollTop) { + scrollTop = new ScrollTopComponent(item, options) + } + return scrollTop + } + + public static bootstrap = () => { + ScrollTopComponent.createInstances('[data-kt-scrolltop="true"]') + } + + public static reinitialization = () => { + ScrollTopComponent.createInstances('[data-kt-scrolltop="true"]') + } + + public static goTop = () => { + ElementAnimateUtil.scrollTop(0, defaultScrollTopOptions.speed) + } +} +export {ScrollTopComponent, defaultScrollTopOptions} diff --git a/src/_res/assets/ts/components/_StepperComponent.ts b/src/_res/assets/ts/components/_StepperComponent.ts new file mode 100644 index 0000000..4e88aa6 --- /dev/null +++ b/src/_res/assets/ts/components/_StepperComponent.ts @@ -0,0 +1,332 @@ +import { + getElementIndex, + getUniqueIdWithPrefix, + ElementAnimateUtil, + EventHandlerUtil, + DataUtil, + DOMEventHandlerUtil, + ElementStyleUtil, +} from '../_utils/index' + +export interface IStepperOptions { + startIndex: number + animation: boolean + animationSpeed: string + animationNextClass: string + animationPreviousClass: string +} + +const defaultStepperOptions: IStepperOptions = { + startIndex: 1, + animation: false, + animationSpeed: '0.3s', + animationNextClass: 'animate__animated animate__slideInRight animate__fast', + animationPreviousClass: 'animate__animated animate__slideInLeft animate__fast', +} + +class StepperComponent { + element: HTMLElement + options: IStepperOptions + instanceUid: string + steps: NodeListOf + btnNext: HTMLElement | null + btnPrev: HTMLElement | null + btnSubmit: HTMLElement | null + totatStepsNumber: number = 0 + passedStepIndex: number = 0 + currentStepIndex: number = 1 + + constructor(_element: HTMLElement, options: IStepperOptions) { + this.element = _element + this.options = Object.assign(defaultStepperOptions, options) + this.instanceUid = getUniqueIdWithPrefix('stepper') + + // Elements + this.steps = this.element.querySelectorAll('[data-kt-stepper-element="nav"]') + this.btnNext = this.element.querySelector('[data-kt-stepper-action="next"]') + this.btnPrev = this.element.querySelector('[data-kt-stepper-action="previous"]') + this.btnSubmit = this.element.querySelector('[data-kt-stepper-action="submit"]') + + // Variables + this.totatStepsNumber = this.steps?.length | 0 + this.passedStepIndex = 0 + this.currentStepIndex = 1 + + // Set Current Step + if (this.options.startIndex > 1) { + this._goTo(this.options.startIndex) + } + + // Event Handlers + this.initHandlers() + + // Bind Instance + DataUtil.set(this.element, 'stepper', this) + } + + private _goTo = (index: number) => { + EventHandlerUtil.trigger(this.element, 'kt.stepper.change') + // Skip if this step is already shown + if (index === this.currentStepIndex || index > this.totatStepsNumber || index < 0) { + return + } + + // Validate step number + index = parseInt(index.toString()) + // Set current step + this.passedStepIndex = this.currentStepIndex + this.currentStepIndex = index + + // Refresh elements + this.refreshUI() + + EventHandlerUtil.trigger(this.element, 'kt.stepper.changed') + } + + private initHandlers = () => { + this.btnNext?.addEventListener('click', (e: Event) => { + e.preventDefault() + + EventHandlerUtil.trigger(this.element, 'kt.stepper.next', e) + }) + + this.btnPrev?.addEventListener('click', (e: Event) => { + e.preventDefault() + + EventHandlerUtil.trigger(this.element, 'kt.stepper.previous', e) + }) + + DOMEventHandlerUtil.on(this.element, '[data-kt-stepper-action="step"]', 'click', (e: Event) => { + e.preventDefault() + + if (this.steps && this.steps.length > 0) { + for (let i = 0; i < this.steps.length; i++) { + if ((this.steps[i] as HTMLElement) === this.element) { + let index = i + 1 + + const stepDirection = this._getStepDirection(index) + EventHandlerUtil.trigger(this.element, `stepper.${stepDirection}`, e) + return + } + } + } + }) + } + + private _getStepDirection = (index: number) => { + return index > this.currentStepIndex ? 'next' : 'previous' + } + + private getStepContent = (index: number) => { + const content = this.element.querySelectorAll('[data-kt-stepper-element="content"]') + if (!content) { + return false + } + + if (content[index - 1]) { + return content[index - 1] + } + + return false + } + + private getLastStepIndex = () => { + return this.totatStepsNumber + } + + private getTotalStepsNumber = () => { + return this.totatStepsNumber + } + + private refreshUI = () => { + let state = '' + + if (this.isLastStep()) { + state = 'last' + } else if (this.isFirstStep()) { + state = 'first' + } else { + state = 'between' + } + + // Set state class + this.element.classList.remove('last') + this.element.classList.remove('first') + this.element.classList.remove('between') + + this.element.classList.add(state) + + // Step Items + const elements = this.element.querySelectorAll( + '[data-kt-stepper-element="nav"], [data-kt-stepper-element="content"], [data-kt-stepper-element="info"]' + ) + + if (!elements || elements.length <= 0) { + return + } + + for (var i = 0, len = elements.length; i < len; i++) { + var element = elements[i] as HTMLElement + var index = getElementIndex(element) + 1 + + element.classList.remove('current') + element.classList.remove('completed') + element.classList.remove('pending') + + if (index === this.currentStepIndex) { + element.classList.add('current') + + if ( + this.options.animation !== false && + element.getAttribute('data-kt-stepper-element') === 'content' + ) { + ElementStyleUtil.set(element, 'animationDuration', this.options.animationSpeed) + + const animation = + this._getStepDirection(this.passedStepIndex) === 'previous' + ? this.options.animationPreviousClass + : this.options.animationNextClass + ElementAnimateUtil.animateClass(element, animation) + } + } else { + if (index < this.currentStepIndex) { + element.classList.add('completed') + } else { + element.classList.add('pending') + } + } + } + } + + private isLastStep = () => { + return this.currentStepIndex === this.totatStepsNumber + } + + private isFirstStep = () => { + return this.currentStepIndex === 1 + } + + private isBetweenStep = () => { + return this.isLastStep() === false && this.isFirstStep() === false + } + + // /////////////////////// + // // ** Public API ** // + // /////////////////////// + + // // Plugin API + public goto = (index: number) => { + return this._goTo(index) + } + + public goNext = () => { + return this.goto(this.getNextStepIndex()) + } + + public goPrev = () => { + return this.goto(this.getPrevStepIndex()) + } + + public goFirst = () => { + return this.goto(1) + } + + public goLast = () => { + return this.goto(this.getLastStepIndex()) + } + + public getCurrentStepIndex = () => { + return this.currentStepIndex + } + + public getNextStepIndex = () => { + if (this.totatStepsNumber >= this.currentStepIndex + 1) { + return this.currentStepIndex + 1 + } else { + return this.totatStepsNumber + } + } + + public getPassedStepIndex = () => { + return this.passedStepIndex + } + + public getPrevStepIndex = () => { + if (this.currentStepIndex - 1 > 1) { + return this.currentStepIndex - 1 + } else { + return 1 + } + } + + public getElement = (index: number) => { + return this.element + } + + // Event API + public on = (name: string, handler: Function) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: Function) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handlerId: string) => { + return EventHandlerUtil.off(this.element, name, handlerId) + } + + public destroy = () => { + console.log('destroy stepper') + } + + public trigger = (name: string, event: Event) => { + return EventHandlerUtil.trigger(this.element, name, event) + } + + // Static methods + public static hasInstace(element: HTMLElement): boolean { + return DataUtil.has(element, 'stepper') + } + + public static getInstance(element: HTMLElement): StepperComponent | undefined { + if (element !== null && StepperComponent.hasInstace(element)) { + const data = DataUtil.get(element, 'stepper') + if (data) { + return data as StepperComponent + } + } + } + + // Create Instances + public static createInstances(selector: string): void { + const elements = document.body.querySelectorAll(selector) + elements.forEach((element) => { + const item = element as HTMLElement + let stepper = StepperComponent.getInstance(item) + if (!stepper) { + stepper = new StepperComponent(item, defaultStepperOptions) + } + }) + } + + public static createInsance = ( + element: HTMLElement, + options: IStepperOptions = defaultStepperOptions + ): StepperComponent | null => { + if (!element) { + return null + } + let stepper = StepperComponent.getInstance(element) + if (!stepper) { + stepper = new StepperComponent(element, options) + } + return stepper + } + + public static bootstrap(attr: string = '[data-kt-stepper]') { + StepperComponent.createInstances(attr) + } +} + +export {StepperComponent, defaultStepperOptions} diff --git a/src/_res/assets/ts/components/_StickyComponent.ts b/src/_res/assets/ts/components/_StickyComponent.ts new file mode 100644 index 0000000..0a5bd85 --- /dev/null +++ b/src/_res/assets/ts/components/_StickyComponent.ts @@ -0,0 +1,285 @@ +import { + getElementOffset, + getScrollTop, + getAttributeValueByBreakpoint, + getUniqueIdWithPrefix, + getObjectPropertyValueByKey, + stringSnakeToCamel, + getCSS, + DataUtil, + ElementAnimateUtil, + ElementStyleUtil, + EventHandlerUtil, +} from '../_utils/index' + +export interface StickyOptions { + offset: number + reverse: boolean + animation: boolean + animationSpeed: string + animationClass: string +} + +const defaultStickyOptions: StickyOptions = { + offset: 200, + reverse: false, + animation: true, + animationSpeed: '0.3s', + animationClass: 'animation-slide-in-down', +} + +class StickyComponent { + element: HTMLElement + options: StickyOptions + instanceUid: string + instanceName: string | null = '' + attributeName: string + eventTriggerState: boolean + lastScrollTop: number + + constructor(_element: HTMLElement, options: StickyOptions) { + this.element = _element + this.options = Object.assign(defaultStickyOptions, options) + this.instanceUid = getUniqueIdWithPrefix('sticky') + this.instanceName = this.element.getAttribute('data-kt-sticky-name') + this.attributeName = 'data-kt-sticky-' + this.instanceName + this.eventTriggerState = true + this.lastScrollTop = 0 + + // Event Handlers + window.addEventListener('scroll', this.scroll) + + // Initial Launch + this.scroll() + + DataUtil.set(this.element, 'sticky', this) + } + + private scroll = () => { + let offset = this.getOption('offset') + let reverse = this.getOption('reverse') + + // Exit if false + if (offset === false) { + return + } + + let offsetNum = 0 + if (typeof offset === 'string') { + offsetNum = parseInt(offset) + } + + const st = getScrollTop() + + // Reverse scroll mode + if (reverse === true) { + // Release on reverse scroll mode + if (st > offsetNum && this.lastScrollTop < st) { + if (document.body.hasAttribute(this.attributeName) === false) { + this.enable() + document.body.setAttribute(this.attributeName, 'on') + } + + if (this.eventTriggerState === true) { + EventHandlerUtil.trigger(this.element, 'kt.sticky.on') + EventHandlerUtil.trigger(this.element, 'kt.sticky.change') + + this.eventTriggerState = false + } + } else { + // Back scroll mode + if (document.body.hasAttribute(this.attributeName)) { + this.disable() + document.body.removeAttribute(this.attributeName) + } + + if (this.eventTriggerState === false) { + EventHandlerUtil.trigger(this.element, 'kt.sticky.off') + EventHandlerUtil.trigger(this.element, 'kt.sticky.change') + + this.eventTriggerState = true + } + } + + this.lastScrollTop = st + return + } + + // Classic scroll mode + if (st > offsetNum) { + if (document.body.hasAttribute(this.attributeName) === false) { + this.enable() + document.body.setAttribute(this.attributeName, 'on') + } + + if (this.eventTriggerState === true) { + EventHandlerUtil.trigger(this.element, 'kt.sticky.on') + EventHandlerUtil.trigger(this.element, 'kt.sticky.change') + this.eventTriggerState = false + } + } else { + // back scroll mode + if (document.body.hasAttribute(this.attributeName) === true) { + this.disable() + document.body.removeAttribute(this.attributeName) + } + + if (this.eventTriggerState === false) { + EventHandlerUtil.trigger(this.element, 'kt.sticky.off') + EventHandlerUtil.trigger(this.element, 'kt.sticky.change') + this.eventTriggerState = true + } + } + } + + private getOption = (name: string) => { + const dataStickyAttr = 'data-kt-sticky-' + name + if (this.element.hasAttribute(dataStickyAttr) === true) { + const attrValueInStr = this.element.getAttribute(dataStickyAttr) + const attrValue = getAttributeValueByBreakpoint(attrValueInStr || '') + if (attrValue !== null && String(attrValue) === 'true') { + return true + } else if (attrValue !== null && String(attrValue) === 'false') { + return false + } + + return attrValue + } else { + const optionName = stringSnakeToCamel(name) + const option = getObjectPropertyValueByKey(this.options, optionName) + if (option) { + return getAttributeValueByBreakpoint(option) + } + } + } + + private disable = () => { + ElementStyleUtil.remove(this.element, 'top') + ElementStyleUtil.remove(this.element, 'width') + ElementStyleUtil.remove(this.element, 'left') + ElementStyleUtil.remove(this.element, 'right') + ElementStyleUtil.remove(this.element, 'z-index') + ElementStyleUtil.remove(this.element, 'position') + } + + private enable = (update: boolean = false) => { + const top = this.getOption('top') + const left = this.getOption('left') + // const right = this.getOption("right"); + let width = this.getOption('width') + const zindex = this.getOption('zindex') + + if (update !== true && this.getOption('animation') === true) { + ElementStyleUtil.set(this.element, 'animationDuration', this.getOption('animationSpeed')) + ElementAnimateUtil.animateClass(this.element, 'animation ' + this.getOption('animationClass')) + } + + if (zindex !== null) { + ElementStyleUtil.set(this.element, 'z-index', zindex) + ElementStyleUtil.set(this.element, 'position', 'fixed') + } + + if (top !== null) { + ElementStyleUtil.set(this.element, 'top', top) + } + + if (width !== null && width !== undefined) { + const widthTarget = getObjectPropertyValueByKey(width, 'target') + if (widthTarget) { + const targetElement = document.querySelector(widthTarget) + if (targetElement) { + width = getCSS(targetElement, 'width') + } + } + ElementStyleUtil.set(this.element, 'width', width) + } + + if (left !== null) { + if (String(left).toLowerCase() === 'auto') { + var offsetLeft = getElementOffset(this.element).left + + if (offsetLeft > 0) { + ElementStyleUtil.set(this.element, 'left', String(offsetLeft) + 'px') + } + } + } + } + + public update = () => { + if (document.body.hasAttribute(this.attributeName) === true) { + this.disable() + document.body.removeAttribute(this.attributeName) + this.enable(true) + document.body.setAttribute(this.attributeName, 'on') + } + } + + // Event API + public on = (name: string, callBack: Function) => { + return EventHandlerUtil.on(this.element, name, callBack) + } + + public one = (name: string, callback: Function) => { + return EventHandlerUtil.one(this.element, name, callback) + } + + public off = (name: string, handlerId: string) => { + return EventHandlerUtil.off(this.element, name, handlerId) + } + + public trigger = (name: string) => { + return EventHandlerUtil.trigger(this.element, name) + } + + // Static methods + public static hasInstace(element: HTMLElement) { + return DataUtil.has(element, 'sticky') + } + + public static getInstance(element: HTMLElement): StickyComponent | undefined { + if (element !== null && StickyComponent.hasInstace(element)) { + const data = DataUtil.get(element, 'sticky') + if (data) { + return data as StickyComponent + } + } + } + + // Create Instances + public static createInstances(selector: string) { + const elements = document.body.querySelectorAll(selector) + elements.forEach((element) => { + const item = element as HTMLElement + let sticky = StickyComponent.getInstance(item) + if (!sticky) { + sticky = new StickyComponent(item, defaultStickyOptions) + } + }) + } + + public static createInsance = ( + selector: string, + options: StickyOptions = defaultStickyOptions + ): StickyComponent | undefined => { + const element = document.body.querySelector(selector) + if (!element) { + return + } + const item = element as HTMLElement + let sticky = StickyComponent.getInstance(item) + if (!sticky) { + sticky = new StickyComponent(item, options) + } + return sticky + } + + public static bootstrap(attr: string = '[data-kt-sticky="true"]') { + StickyComponent.createInstances(attr) + } + + public static reInitialization(attr: string = '[data-kt-sticky="true"]') { + StickyComponent.createInstances(attr) + } +} + +export {StickyComponent, defaultStickyOptions} diff --git a/src/_res/assets/ts/components/_SwapperComponent.ts b/src/_res/assets/ts/components/_SwapperComponent.ts new file mode 100644 index 0000000..31e99e8 --- /dev/null +++ b/src/_res/assets/ts/components/_SwapperComponent.ts @@ -0,0 +1,210 @@ +import { + getAttributeValueByBreakpoint, + stringSnakeToCamel, + getObjectPropertyValueByKey, + EventHandlerUtil, + throttle, +} from '../_utils/index' + +export class SwapperStore { + static store: Map = new Map() + + public static set(instanceId: string, drawerComponentObj: SwapperComponent): void { + if (SwapperStore.has(instanceId)) { + return + } + + SwapperStore.store.set(instanceId, drawerComponentObj) + } + + public static get(instanceId: string): SwapperComponent | undefined { + if (!SwapperStore.has(instanceId)) { + return + } + return SwapperStore.store.get(instanceId) + } + + public static remove(instanceId: string): void { + if (!SwapperStore.has(instanceId)) { + return + } + + SwapperStore.store.delete(instanceId) + } + + public static has(instanceId: string): boolean { + return SwapperStore.store.has(instanceId) + } + + public static getAllInstances() { + return SwapperStore.store + } +} + +export interface ISwapperOptions { + mode: string +} + +export interface ISwapperQueries { + componentName: string + instanseQuery: string + attrQuery: string +} + +const defaultSwapperOptions: ISwapperOptions = { + mode: 'append', +} + +const defaultSwapperQueires: ISwapperQueries = { + componentName: 'swapper', + instanseQuery: '[data-kt-swapper="true"]', + attrQuery: 'data-kt-swapper-', +} + +class SwapperComponent { + element: HTMLElement + options: ISwapperOptions + queries: ISwapperQueries + + constructor(_element: HTMLElement, _options: ISwapperOptions, _queries: ISwapperQueries) { + this.element = _element + this.options = Object.assign(defaultSwapperOptions, _options) + this.queries = _queries + + // Initial update + this.update() + + SwapperStore.set(this.element.id, this) + } + + private getOption(name: string) { + const attr = this.element.getAttribute(`${this.queries.attrQuery}${name}`) + if (attr) { + let value = getAttributeValueByBreakpoint(attr) + if (attr != null && String(value) === 'true') { + return true + } else if (value !== null && String(value) === 'false') { + return false + } + return value + } else { + const optionName = stringSnakeToCamel(name) + const option = getObjectPropertyValueByKey(this.options, optionName) + if (option) { + return getAttributeValueByBreakpoint(option) + } else { + return null + } + } + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + public update = () => { + const parentSelector = this.getOption('parent')?.toString() + const mode = this.getOption('mode') + const parentElement = parentSelector ? document.querySelector(parentSelector) : null + if (parentElement && this.element.parentNode !== parentElement) { + const alreadyPended = document.getElementById('kt_header_menu') !== null + if (!alreadyPended) { + if (mode === 'prepend') { + parentElement.prepend(this.element) + } else if (mode === 'append') { + parentElement.append(this.element) + } + } + } + } + + // Event API + public on = (name: string, handler: Function) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: Function) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handlerId: string) => { + return EventHandlerUtil.off(this.element, name, handlerId) + } + + public trigger = (name: string, event: Event) => { + return EventHandlerUtil.trigger(this.element, name, event) + } + + // Static methods + public static getInstance = ( + el: HTMLElement, + componentName: string = defaultSwapperQueires.componentName + ): SwapperComponent | null => { + const place = SwapperStore.get(el.id) + if (place) { + return place as SwapperComponent + } + + return null + } + + public static createInstances = ( + selector: string = defaultSwapperQueires.instanseQuery, + options: ISwapperOptions = defaultSwapperOptions, + queries: ISwapperQueries = defaultSwapperQueires + ) => { + const elements = document.body.querySelectorAll(selector) + elements.forEach((el) => { + const item = el as HTMLElement + let place = SwapperComponent.getInstance(item) + if (!place) { + place = new SwapperComponent(item, options, queries) + } + }) + } + + public static createInsance = ( + selector: string = defaultSwapperQueires.instanseQuery, + options: ISwapperOptions = defaultSwapperOptions, + queries: ISwapperQueries = defaultSwapperQueires + ): SwapperComponent | undefined => { + const element = document.body.querySelector(selector) + if (!element) { + return + } + const item = element as HTMLElement + let place = SwapperComponent.getInstance(item) + if (!place) { + place = new SwapperComponent(item, options, queries) + } + return place + } + + public static bootstrap = (selector: string = defaultSwapperQueires.instanseQuery) => { + SwapperComponent.createInstances(selector) + } + + public static reinitialization = (selector: string = defaultSwapperQueires.instanseQuery) => { + SwapperComponent.createInstances(selector) + } +} + +// Window resize handler +window.addEventListener('resize', function () { + let timer + throttle( + timer, + () => { + // Locate and update Offcanvas instances on window resize + const elements = document.querySelectorAll(defaultSwapperQueires.instanseQuery) + elements.forEach((el) => { + const place = SwapperComponent.getInstance(el as HTMLElement) + if (place) { + place.update() + } + }) + }, + 200 + ) +}) + +export {SwapperComponent, defaultSwapperOptions, defaultSwapperQueires} diff --git a/src/_res/assets/ts/components/_ToggleComponent.ts b/src/_res/assets/ts/components/_ToggleComponent.ts new file mode 100644 index 0000000..9119b94 --- /dev/null +++ b/src/_res/assets/ts/components/_ToggleComponent.ts @@ -0,0 +1,200 @@ +import {DataUtil, getUniqueIdWithPrefix, EventHandlerUtil} from '../_utils/index' +// Helpers +import {CookieComponent} from './_CookieComponent' + +export interface ToggleOptions { + saveState: boolean + targetState?: string + toggleState?: string + targetToggleMode?: string +} + +const defaultToggleOptions: ToggleOptions = { + saveState: false, +} + +class ToggleComponent { + element: HTMLElement + instanceUid: string + options: ToggleOptions + state: string = '' + mode: string = '' + target: HTMLElement | null = null + attribute: string = '' + + constructor(_element: HTMLElement, options: ToggleOptions) { + this.options = Object.assign(defaultToggleOptions, options) + this.instanceUid = getUniqueIdWithPrefix('toggle') + this.element = _element + + const elementTargetAttr = this.element.getAttribute('data-kt-toggle-target') + if (elementTargetAttr) { + this.target = document.querySelector(elementTargetAttr) + } + const elementToggleAttr = this.element.getAttribute('data-kt-toggle-state') + this.state = elementToggleAttr || '' + const elementModeAttr = this.element.getAttribute('data-kt-toggle-mode') + this.mode = elementModeAttr || '' + this.attribute = 'data-kt-' + this.element.getAttribute('data-kt-toggle-name') + + // Event Handlers + this._handlers() + + // Update Instance + // Bind Instance + DataUtil.set(this.element, 'toggle', this) + } + + private _handlers = () => { + this.element.addEventListener('click', (e: Event) => { + e.preventDefault() + + if (this.mode === '') { + this._toggle() + return + } + + if (this.mode === 'off' && !this._isEnabled()) { + this._toggle() + } else if (this.mode === 'on' && this._isEnabled()) { + this._toggle() + } + }) + } + + // Event handlers + private _toggle = () => { + // Trigger "after.toggle" event + EventHandlerUtil.trigger(this.element, 'kt.toggle.change') + + if (this._isEnabled()) { + this._disable() + } else { + this._enable() + } + + // Trigger "before.toggle" event + EventHandlerUtil.trigger(this.element, 'kt.toggle.changed') + return this + } + + private _enable = () => { + if (this._isEnabled()) { + return + } + + EventHandlerUtil.trigger(this.element, 'kt.toggle.enable') + this.target?.setAttribute(this.attribute, 'on') + if (this.state.length > 0) { + this.element.classList.add(this.state) + } + + if (this.options.saveState) { + CookieComponent.set(this.attribute, 'on', {}) + } + + EventHandlerUtil.trigger(this.element, 'kt.toggle.enabled') + return this + } + + private _disable = () => { + if (!this._isEnabled()) { + return false + } + + EventHandlerUtil.trigger(this.element, 'kt.toggle.disable') + this.target?.removeAttribute(this.attribute) + + if (this.state.length > 0) { + this.element.classList.remove(this.state) + } + + if (this.options.saveState) { + CookieComponent.delete(this.attribute) + } + + EventHandlerUtil.trigger(this.element, 'kt.toggle.disabled') + return this + } + + private _isEnabled = () => { + if (!this.target) { + return false + } + + return String(this.target.getAttribute(this.attribute)).toLowerCase() === 'on' + } + + /////////////////////// + // ** Public API ** // + /////////////////////// + + // Plugin API + // Plugin API + public toggle = () => { + return this._toggle() + } + + public enable = () => { + return this._enable() + } + + public disable = () => { + return this._disable() + } + + public isEnabled = () => { + return this._isEnabled() + } + + public goElement = () => { + return this.element + } + + // Event API + public on = (name: string, handler: Function) => { + return EventHandlerUtil.on(this.element, name, handler) + } + + public one = (name: string, handler: Function) => { + return EventHandlerUtil.one(this.element, name, handler) + } + + public off = (name: string, handlerId: string) => { + return EventHandlerUtil.off(this.element, name, handlerId) + } + + public trigger = (name: string, event?: Event) => { + return EventHandlerUtil.trigger(this.element, name, event) + } + + // Static methods + public static getInstance = (el: HTMLElement) => { + const toggleElement = DataUtil.get(el, 'toggle') + if (toggleElement) { + return toggleElement + } + + return null + } + + public static createInstances = (selector: string) => { + const elements = document.body.querySelectorAll(selector) + elements.forEach((el) => { + let toggle = ToggleComponent.getInstance(el) + if (!toggle) { + toggle = new ToggleComponent(el, defaultToggleOptions) + } + }) + } + + public static reinitialization = () => { + ToggleComponent.createInstances('[data-kt-toggle]') + } + + public static bootstrap = () => { + ToggleComponent.createInstances('[data-kt-toggle]') + } +} + +export {ToggleComponent, defaultToggleOptions} diff --git a/src/_res/assets/ts/components/index.ts b/src/_res/assets/ts/components/index.ts new file mode 100644 index 0000000..bf59774 --- /dev/null +++ b/src/_res/assets/ts/components/index.ts @@ -0,0 +1,14 @@ +export * from './_CookieComponent' +export * from './_DrawerComponent' +export * from './_FeedbackComponent' +export * from './_ImageInputComponent' +export * from './_ScrollComponent' +export * from './_ScrollTopComponent' +export * from './_StepperComponent' +export * from './_StickyComponent' +export * from './_ToggleComponent' +// export * from './_DialerComponent'; +export * from './_PasswordMeterComponent' +export * from './_SwapperComponent' +export * from './MenuComponent' +export * from './SearchComponent' diff --git a/src/_res/assets/ts/index.ts b/src/_res/assets/ts/index.ts new file mode 100644 index 0000000..eb9a9f9 --- /dev/null +++ b/src/_res/assets/ts/index.ts @@ -0,0 +1,43 @@ +export * as KTUtil from './_utils/index' +export * as components from './components/index' +// declare global { +// interface Window { +// keenthemes: any; +// } +// } + +// window.keenthemes = { +// components: { +// ScrollTop: components.ScrollTopComponent, +// Coockie: components.CookieComponent, +// Drawer: components.DrawerComponent, +// Feedback: components.FeedbackComponent, +// ImageInput: components.ImageInputComponent, +// Scroll: components.ScrollComponent, +// Stepper: components.StepperComponent, +// Sticky: components.StickyComponent, +// Toggle: components.ToggleComponent, +// Menu: components.MenuComponent, +// Search: components.SearchComponent, +// Dialder: components.DialerComponent, +// PasswordMeter: components.PasswordMeterComponent, +// Place: components.PlaceComponent, +// defaultDialerOptions: components.defaultDialerOptions, +// defaultDialderQueries: components.defaultDialerQueires, +// defaultPasswordMeterOptions: components.defaultPasswordMeterOptions, +// defaultPasswordMeterQueries: components.defaultPasswordMeterQueires, +// defaultPlaceOptions: components.defaultPlaceOptions, +// defaultPlaceQueries: components.defaultPlaceQueires, +// defaultDrawerOptions: components.defaultDrawerOptions, +// defaultFeedbackOptions: components.defaultFeedbackOptions, +// defaultImageInputOptions: components.defaultImageInputOptions, +// defaultScrollOptions: components.defaultScrollOptions, +// defaultScrollTopOptions: components.defaultScrollTopOptions, +// defaultStepperOptions: components.defaultStepperOptions, +// defaultStickyOptions: components.defaultStickyOptions, +// defaultToggleOptions: components.defaultToggleOptions, +// defaultMenuOptions: components.defaultMenuOptions, +// defaultSearchOptions: components.defaultSearchOptions, +// }, +// utils: KTUtil, +// }; diff --git a/src/_res/assets/ts/layout/ThemeMode.ts b/src/_res/assets/ts/layout/ThemeMode.ts new file mode 100644 index 0000000..d96c629 --- /dev/null +++ b/src/_res/assets/ts/layout/ThemeMode.ts @@ -0,0 +1,195 @@ +import {themeMenuModeLSKey, themeModelSKey} from '../../../partials' +import {EventHandlerUtil} from '../_utils' + +type Mode = 'light' | 'dark' | 'system' + +class ThemeMode { + menu: HTMLElement | null = null + element: HTMLElement | null = null + + public getMode = (): Mode => { + const menuMode: Mode | '' = this.getMenuMode() + const defaultMode = 'light' + if (!localStorage) { + return defaultMode + } + + const ls = localStorage.getItem(themeModelSKey) + if (ls) { + return ls as Mode + } + + const dataTheme = this.element?.getAttribute('data-theme') + if (dataTheme) { + return dataTheme as Mode + } + + if (!menuMode) { + return defaultMode + } + + if (menuMode === 'system') { + return this.getSystemMode() + } + + return menuMode + } + + public setMode = (mode: Mode, menuMode: Mode | ''): void => { + // Check input values + if (mode !== 'light' && mode !== 'dark') { + return + } + + // Reset mode if system mode was changed + if (menuMode === 'system') { + if (this.getSystemMode() !== mode) { + mode = this.getSystemMode() + } + } + + // Check menu mode + if (!menuMode) { + menuMode = mode + } + + // Read active menu mode value + const activeMenuItem: HTMLElement | null = + this.menu?.querySelector('[data-kt-element="mode"][data-kt-value="' + menuMode + '"]') || null + + // Enable switching state + this.element?.setAttribute('data-kt-theme-mode-switching', 'true') + + // Set mode to the target element + this.element?.setAttribute('data-theme', mode) + + // Disable switching state + const self = this + setTimeout(function () { + self.element?.removeAttribute('data-kt-theme-mode-switching') + }, 300) + + // Store mode value in storage + if (localStorage) { + localStorage.setItem(themeModelSKey, mode) + } + + // Set active menu item + if (activeMenuItem && localStorage) { + localStorage.setItem(themeMenuModeLSKey, menuMode) + this.setActiveMenuItem(activeMenuItem) + } + + // Flip images + this.flipImages() + } + + public getMenuMode = (): Mode | '' => { + const menuItem = this.menu?.querySelector('.active[data-kt-element="mode"]') + const dataKTValue = menuItem?.getAttribute('data-kt-value') + if (dataKTValue) { + return dataKTValue as Mode + } + + const ls = localStorage ? localStorage.getItem(themeMenuModeLSKey) : null + return (ls as Mode) || '' + } + + public getSystemMode = (): Mode => { + return window.matchMedia('(prefers-color-scheme: dark)') ? 'dark' : 'light' + } + + private initMode = (): void => { + this.setMode(this.getMode(), this.getMenuMode()) + if (this.element) { + EventHandlerUtil.trigger(this.element, 'kt.thememode.init') + } + } + + private getActiveMenuItem = (): HTMLElement | null => { + return ( + this.menu?.querySelector( + '[data-kt-element="mode"][data-kt-value="' + this.getMenuMode() + '"]' + ) || null + ) + } + + private setActiveMenuItem = (item: HTMLElement): void => { + const menuMode = item.getAttribute('data-kt-value') + const activeItem = this.menu?.querySelector('.active[data-kt-element="mode"]') + if (activeItem) { + activeItem.classList.remove('active') + } + + item.classList.add('active') + if (localStorage && menuMode) { + localStorage.setItem(themeMenuModeLSKey, menuMode) + } + } + + private handleMenu = (): void => { + this.menu + ?.querySelectorAll('[data-kt-element="mode"]') + ?.forEach((item: HTMLElement) => { + item.addEventListener('click', (e) => { + e.preventDefault() + + const menuMode: string | null = item.getAttribute('data-kt-value') + const mode = menuMode === 'system' ? this.getSystemMode() : menuMode + + if (mode) { + this.setMode(mode as Mode, menuMode as Mode | '') + } + }) + }) + } + + public flipImages = () => { + document.querySelectorAll('[data-kt-img-dark]')?.forEach((item: HTMLElement) => { + if (item.tagName === 'IMG') { + if (this.getMode() === 'dark' && item.hasAttribute('data-kt-img-dark')) { + item.setAttribute('data-kt-img-light', item.getAttribute('src') || '') + item.setAttribute('src', item.getAttribute('data-kt-img-dark') || '') + } else if (this.getMode() === 'light' && item.hasAttribute('data-kt-img-light')) { + item.setAttribute('data-kt-img-dark', item.getAttribute('src') || '') + item.setAttribute('src', item.getAttribute('data-kt-img-light') || '') + } + } else { + if (this.getMode() === 'dark' && item.hasAttribute('data-kt-img-dark')) { + item.setAttribute('data-kt-img-light', item.getAttribute('src') || '') + item.style.backgroundImage = "url('" + item.getAttribute('data-kt-img-dark') + "')" + } else if (this.getMode() === 'light' && item.hasAttribute('data-kt-img-light')) { + item.setAttribute('data-kt-img-dark', item.getAttribute('src') || '') + item.style.backgroundImage = "url('" + item.getAttribute('data-kt-img-light') + "')" + } + } + }) + } + + public on = (name: string, hander: Function) => { + if (this.element) { + return EventHandlerUtil.on(this.element, name, hander) + } + } + + public off = (name: string, handlerId: string) => { + if (this.element) { + return EventHandlerUtil.off(this.element, name, handlerId) + } + } + + public init = () => { + this.menu = document.querySelector('[data-kt-element="theme-mode-menu"]') + this.element = document.documentElement + + this.initMode() + + if (this.menu) { + this.handleMenu() + } + } +} + +const ThemeModeComponent = new ThemeMode() +// Initialize app on document ready => ThemeModeComponent.init() +export {ThemeModeComponent} diff --git a/src/_res/assets/ts/layout/index.ts b/src/_res/assets/ts/layout/index.ts new file mode 100644 index 0000000..8b157b2 --- /dev/null +++ b/src/_res/assets/ts/layout/index.ts @@ -0,0 +1 @@ +export * from './ThemeMode' diff --git a/src/_res/helpers/AssetHelpers.ts b/src/_res/helpers/AssetHelpers.ts new file mode 100644 index 0000000..821a9d8 --- /dev/null +++ b/src/_res/helpers/AssetHelpers.ts @@ -0,0 +1 @@ +export const toAbsoluteUrl = (pathname: string) => process.env.PUBLIC_URL + pathname diff --git a/src/_res/helpers/RouterHelpers.ts b/src/_res/helpers/RouterHelpers.ts new file mode 100644 index 0000000..7cc10dc --- /dev/null +++ b/src/_res/helpers/RouterHelpers.ts @@ -0,0 +1,20 @@ +export function getCurrentUrl(pathname: string) { + return pathname.split(/[?#]/)[0] +} + +export function checkIsActive(pathname: string, url: string) { + const current = getCurrentUrl(pathname) + if (!current || !url) { + return false + } + + if (current === url) { + return true + } + + if (current.indexOf(url) > -1) { + return true + } + + return false +} diff --git a/src/_res/helpers/components/KTCard.tsx b/src/_res/helpers/components/KTCard.tsx new file mode 100644 index 0000000..dace09c --- /dev/null +++ b/src/_res/helpers/components/KTCard.tsx @@ -0,0 +1,62 @@ +import {FC} from 'react' +import clsx from 'clsx' +import {WithChildren} from '../react18MigrationHelpers' + +// Wrapper on html card: +// https://preview.keenthemes.com/metronic8/demo1/documentation/base/cards.html + +type Props = { + className?: string + shadow?: boolean + flush?: boolean // https://preview.keenthemes.com/metronic8/demo1/documentation/base/cards.html#flush + resetSidePaddings?: boolean // https://preview.keenthemes.com/metronic8/demo1/documentation/base/cards.html#reset-side-paddings + border?: boolean // https://preview.keenthemes.com/metronic8/demo1/documentation/base/cards.html#bordered + dashed?: boolean // https://preview.keenthemes.com/metronic8/demo1/documentation/base/cards.html#dashed + stretch?: 'stretch' | 'stretch-75' | 'stretch-50' | 'stretch-33' | 'stretch-25' // https://preview.keenthemes.com/metronic8/demo1/documentation/base/cards.html#stretch + rounded?: 'rounded' | 'rounded-top' | 'rounded-bottom' + // https://preview.keenthemes.com/metronic8/demo1/documentation/base/cards.html#utilities + utilityP?: number + utilityPY?: number + utilityPX?: number +} + +const KTCard: FC = (props) => { + const { + className, + shadow, + flush, + resetSidePaddings, + border, + dashed, + stretch, + rounded, + utilityP, + utilityPY, + utilityPX, + children, + } = props + return ( +
+ {children} +
+ ) +} + +export {KTCard} diff --git a/src/_res/helpers/components/KTCardBody.tsx b/src/_res/helpers/components/KTCardBody.tsx new file mode 100644 index 0000000..3611852 --- /dev/null +++ b/src/_res/helpers/components/KTCardBody.tsx @@ -0,0 +1,29 @@ +import clsx from 'clsx' +import {FC} from 'react' +import {WithChildren} from '../react18MigrationHelpers' + +type Props = { + className?: string + scroll?: boolean + height?: number +} + +const KTCardBody: FC = (props) => { + const {className, scroll, height, children} = props + return ( +
+ {children} +
+ ) +} + +export {KTCardBody} diff --git a/src/_res/helpers/components/KTSVG.tsx b/src/_res/helpers/components/KTSVG.tsx new file mode 100644 index 0000000..112d069 --- /dev/null +++ b/src/_res/helpers/components/KTSVG.tsx @@ -0,0 +1,18 @@ +import React from 'react' +import SVG from 'react-inlinesvg' +import {toAbsoluteUrl} from '../AssetHelpers' +type Props = { + className?: string + path: string + svgClassName?: string +} + +const KTSVG: React.FC = ({className = '', path, svgClassName = 'mh-50px'}) => { + return ( + + + + ) +} + +export {KTSVG} diff --git a/src/_res/helpers/crud-helper/consts.ts b/src/_res/helpers/crud-helper/consts.ts new file mode 100644 index 0000000..8c09903 --- /dev/null +++ b/src/_res/helpers/crud-helper/consts.ts @@ -0,0 +1,5 @@ +const QUERIES = { + USERS_LIST: 'users-list', +} + +export {QUERIES} diff --git a/src/_res/helpers/crud-helper/helpers.tsx b/src/_res/helpers/crud-helper/helpers.tsx new file mode 100644 index 0000000..9208603 --- /dev/null +++ b/src/_res/helpers/crud-helper/helpers.tsx @@ -0,0 +1,124 @@ +import {createContext, Dispatch, SetStateAction, useEffect, useState} from 'react' +import qs from 'qs' +import {ID, QueryResponseContextProps, QueryState} from './models' + +function createResponseContext(initialState: QueryResponseContextProps) { + return createContext(initialState) +} + +function isNotEmpty(obj: unknown) { + return obj !== undefined && obj !== null && obj !== '' +} + +// Example: page=1&items_per_page=10&sort=id&order=desc&search=a&filter_name=a&filter_online=false +function stringifyRequestQuery(state: QueryState): string { + const pagination = qs.stringify(state, {filter: ['page', 'items_per_page'], skipNulls: true}) + const sort = qs.stringify(state, {filter: ['sort', 'order'], skipNulls: true}) + const search = isNotEmpty(state.search) + ? qs.stringify(state, {filter: ['search'], skipNulls: true}) + : '' + + const filter = state.filter + ? Object.entries(state.filter as Object) + .filter((obj) => isNotEmpty(obj[1])) + .map((obj) => { + return `filter_${obj[0]}=${obj[1]}` + }) + .join('&') + : '' + + return [pagination, sort, search, filter] + .filter((f) => f) + .join('&') + .toLowerCase() +} + +function parseRequestQuery(query: string): QueryState { + const cache: unknown = qs.parse(query) + return cache as QueryState +} + +function calculatedGroupingIsDisabled(isLoading: boolean, data: Array | undefined): boolean { + if (isLoading) { + return true + } + + return !data || !data.length +} + +function calculateIsAllDataSelected(data: Array | undefined, selected: Array): boolean { + if (!data) { + return false + } + + return data.length > 0 && data.length === selected.length +} + +function groupingOnSelect( + id: ID, + selected: Array, + setSelected: Dispatch>> +) { + if (!id) { + return + } + + if (selected.includes(id)) { + setSelected(selected.filter((itemId) => itemId !== id)) + } else { + const updatedSelected = [...selected] + updatedSelected.push(id) + setSelected(updatedSelected) + } +} + +function groupingOnSelectAll( + isAllSelected: boolean, + setSelected: Dispatch>>, + data?: Array +) { + if (isAllSelected) { + setSelected([]) + return + } + + if (!data || !data.length) { + return + } + + setSelected(data.filter((item) => item.id).map((item) => item.id)) +} + +// Hook +function useDebounce(value: string | undefined, delay: number) { + // State and setters for debounced value + const [debouncedValue, setDebouncedValue] = useState(value) + useEffect( + () => { + // Update debounced value after delay + const handler = setTimeout(() => { + setDebouncedValue(value) + }, delay) + // Cancel the timeout if value changes (also on delay change or unmount) + // This is how we prevent debounced value from updating if value is changed ... + // .. within the delay period. Timeout gets cleared and restarted. + return () => { + clearTimeout(handler) + } + }, + [value, delay] // Only re-call effect if value or delay changes + ) + return debouncedValue +} + +export { + createResponseContext, + stringifyRequestQuery, + parseRequestQuery, + calculatedGroupingIsDisabled, + calculateIsAllDataSelected, + groupingOnSelect, + groupingOnSelectAll, + useDebounce, + isNotEmpty, +} diff --git a/src/_res/helpers/crud-helper/models.ts b/src/_res/helpers/crud-helper/models.ts new file mode 100644 index 0000000..3f36d9f --- /dev/null +++ b/src/_res/helpers/crud-helper/models.ts @@ -0,0 +1,83 @@ +import {Dispatch, SetStateAction} from 'react' + +export type ID = undefined | null | number + +export type PaginationState = { + page: number + items_per_page: 10 | 30 | 50 | 100 + links?: Array<{label: string; active: boolean; url: string | null; page: number | null}> +} + +export type SortState = { + sort?: string + order?: 'asc' | 'desc' +} + +export type FilterState = { + filter?: unknown +} + +export type SearchState = { + search?: string +} + +export type Response = { + data?: T + payload?: { + message?: string + errors?: { + [key: string]: Array + } + pagination?: PaginationState + } +} + +export type QueryState = PaginationState & SortState & FilterState & SearchState + +export type QueryRequestContextProps = { + state: QueryState + updateState: (updates: Partial) => void +} + +export const initialQueryState: QueryState = { + page: 1, + items_per_page: 10, +} + +export const initialQueryRequest: QueryRequestContextProps = { + state: initialQueryState, + updateState: () => {}, +} + +export type QueryResponseContextProps = { + response?: Response> | undefined + refetch: () => void + isLoading: boolean + query: string +} + +export const initialQueryResponse = {refetch: () => {}, isLoading: false, query: ''} + +export type ListViewContextProps = { + selected: Array + onSelect: (selectedId: ID) => void + onSelectAll: () => void + clearSelected: () => void + // NULL => (CREATION MODE) | MODAL IS OPENED + // NUMBER => (EDIT MODE) | MODAL IS OPENED + // UNDEFINED => MODAL IS CLOSED + itemIdForUpdate?: ID + setItemIdForUpdate: Dispatch> + isAllSelected: boolean + disabled: boolean +} + +export const initialListView: ListViewContextProps = { + selected: [], + onSelect: () => {}, + onSelectAll: () => {}, + clearSelected: () => {}, + setItemIdForUpdate: () => {}, + isAllSelected: false, + disabled: false, +} diff --git a/src/_res/helpers/dataExamples.ts b/src/_res/helpers/dataExamples.ts new file mode 100644 index 0000000..1aa0a31 --- /dev/null +++ b/src/_res/helpers/dataExamples.ts @@ -0,0 +1,281 @@ +export interface MessageModel { + user: number + type: 'in' | 'out' + text: string + time: string + template?: boolean +} + +const defaultMessages: Array = [ + { + user: 4, + type: 'in', + text: 'How likely are you to recommend our company to your friends and family ?', + time: '2 mins', + }, + { + user: 2, + type: 'out', + text: 'Hey there, we’re just writing to let you know that you’ve been subscribed to a repository on GitHub.', + time: '5 mins', + }, + { + user: 4, + type: 'in', + text: 'Ok, Understood!', + time: '1 Hour', + }, + { + user: 2, + type: 'out', + text: 'You’ll receive notifications for all issues, pull requests!', + time: '2 Hours', + }, + { + user: 4, + type: 'in', + text: 'You can unwatch this repository immediately by clicking here: Keenthemes.com', + time: '3 Hours', + }, + { + user: 2, + type: 'out', + text: 'Most purchased Business courses during this sale!', + time: '4 Hours', + }, + { + user: 4, + type: 'in', + text: 'Company BBQ to celebrate the last quater achievements and goals. Food and drinks provided', + time: '5 Hours', + }, + { + template: true, + user: 2, + type: 'out', + text: '', + time: 'Just now', + }, + { + template: true, + user: 4, + type: 'in', + text: 'Right before vacation season we have the next Big Deal for you.', + time: 'Just now', + }, +] + +export interface UserInfoModel { + initials?: {label: string; state: 'warning' | 'danger' | 'primary' | 'success' | 'info'} + name: string + avatar?: string + email: string + position: string + online: boolean +} + +const defaultUserInfos: Array = [ + { + name: 'Emma Smith', + avatar: 'avatars/300-6.jpg', + email: 'e.smith@kpmg.com.au', + position: 'Art Director', + online: false, + }, + { + name: 'Melody Macy', + initials: {label: 'M', state: 'danger'}, + email: 'melody@altbox.com', + position: 'Marketing Analytic', + online: true, + }, + { + name: 'Max Smith', + avatar: 'avatars/300-1.jpg', + email: 'max@kt.com', + position: 'Software Enginer', + online: false, + }, + { + name: 'Sean Bean', + avatar: 'avatars/300-5.jpg', + email: 'sean@dellito.com', + position: 'Web Developer', + online: false, + }, + { + name: 'Brian Cox', + avatar: 'avatars/300-25.jpg', + email: 'brian@exchange.com', + position: 'UI/UX Designer', + online: false, + }, + { + name: 'Mikaela Collins', + initials: {label: 'M', state: 'warning'}, + email: 'mikaela@pexcom.com', + position: 'Head Of Marketing', + online: true, + }, + { + name: 'Francis Mitcham', + avatar: 'avatars/300-9.jpg', + email: 'f.mitcham@kpmg.com.au', + position: 'Software Arcitect', + online: false, + }, + + { + name: 'Olivia Wild', + initials: {label: 'O', state: 'danger'}, + email: 'olivia@corpmail.com', + position: 'System Admin', + online: true, + }, + { + name: 'Neil Owen', + initials: {label: 'N', state: 'primary'}, + email: 'owen.neil@gmail.com', + position: 'Account Manager', + online: true, + }, + { + name: 'Dan Wilson', + avatar: 'avatars/300-23.jpg', + email: 'dam@consilting.com', + position: 'Web Desinger', + online: false, + }, + { + name: 'Emma Bold', + initials: {label: 'E', state: 'danger'}, + email: 'emma@intenso.com', + position: 'Corporate Finance', + online: true, + }, + { + name: 'Ana Crown', + avatar: 'avatars/300-12.jpg', + email: 'ana.cf@limtel.com', + position: 'Customer Relationship', + online: false, + }, + { + name: 'Robert Doe', + initials: {label: 'A', state: 'info'}, + email: 'robert@benko.com', + position: 'Marketing Executive', + online: true, + }, + { + name: 'John Miller', + avatar: 'avatars/300-13.jpg', + email: 'miller@mapple.com', + position: 'Project Manager', + online: false, + }, + { + name: 'Lucy Kunic', + initials: {label: 'L', state: 'success'}, + email: 'lucy.m@fentech.com', + position: 'SEO Master', + online: true, + }, + { + name: 'Ethan Wilder', + avatar: 'avatars/300-21.jpg', + email: 'ethan@loop.com.au', + position: 'Accountant', + online: true, + }, +] + +const messageFromClient: MessageModel = { + user: 4, + type: 'in', + text: 'Thank you for your awesome support!', + time: 'Just now', +} + +export interface AlertModel { + title: string + description: string + time: string + icon: string + state: 'primary' | 'danger' | 'warning' | 'success' | 'info' +} + +const defaultAlerts: Array = [ + { + title: 'Project Alice', + description: 'Phase 1 development', + time: '1 hr', + icon: 'icons/duotune/technology/teh008.svg', + state: 'primary', + }, + { + title: 'HR Confidential', + description: 'Confidential staff documents', + time: '2 hrs', + icon: 'icons/duotune/general/gen044.svg', + state: 'danger', + }, + { + title: 'Company HR', + description: 'Corporeate staff profiles', + time: '5 hrs', + icon: 'icons/duotune/finance/fin006.svg', + state: 'warning', + }, + { + title: 'Project Red', + description: 'New frontend admin theme', + time: '2 days', + icon: 'icons/duotune/files/fil023.svg', + state: 'success', + }, + { + title: 'Project Breafing', + description: 'Product launch status update', + time: '21 Jan', + icon: 'icons/duotune/maps/map001.svg', + state: 'primary', + }, + { + title: 'Banner Assets', + description: 'Collection of banner images', + time: '21 Jan', + icon: 'icons/duotune/general/gen006.svg', + state: 'info', + }, + { + title: 'Icon Assets', + description: 'Collection of SVG icons', + time: '20 March', + icon: 'icons/duotune/art/art002.svg', + state: 'warning', + }, +] +export interface LogModel { + code: string + state: 'success' | 'danger' | 'warning' + message: string + time: string +} + +const defaultLogs: Array = [ + {code: '200 OK', state: 'success', message: 'New order', time: 'Just now'}, + {code: '500 ERR', state: 'danger', message: 'New customer', time: '2 hrs'}, + {code: '200 OK', state: 'success', message: 'Payment process', time: '5 hrs'}, + {code: '300 WRN', state: 'warning', message: 'Search query', time: '2 days'}, + {code: '200 OK', state: 'success', message: 'API connection', time: '1 week'}, + {code: '200 OK', state: 'success', message: 'Database restore', time: 'Mar 5'}, + {code: '300 WRN', state: 'warning', message: 'System update', time: 'May 15'}, + {code: '300 WRN', state: 'warning', message: 'Server OS update', time: 'Apr 3'}, + {code: '300 WRN', state: 'warning', message: 'API rollback', time: 'Jun 30'}, + {code: '500 ERR', state: 'danger', message: 'Refund process', time: 'Jul 10'}, + {code: '500 ERR', state: 'danger', message: 'Withdrawal process', time: 'Sep 10'}, + {code: '500 ERR', state: 'danger', message: 'Mail tasks', time: 'Dec 10'}, +] + +export {defaultMessages, defaultUserInfos, defaultAlerts, defaultLogs, messageFromClient} diff --git a/src/_res/helpers/index.ts b/src/_res/helpers/index.ts new file mode 100644 index 0000000..095f84d --- /dev/null +++ b/src/_res/helpers/index.ts @@ -0,0 +1,10 @@ +export * from './AssetHelpers' +export * from './RouterHelpers' +export * from './components/KTSVG' +export * from './components/KTCard' +export * from './components/KTCardBody' +export * from './dataExamples' +export * from './crud-helper/helpers' +export * from './crud-helper/models' +export * from './crud-helper/consts' +export * from './react18MigrationHelpers' \ No newline at end of file diff --git a/src/_res/helpers/react18MigrationHelpers.ts b/src/_res/helpers/react18MigrationHelpers.ts new file mode 100644 index 0000000..256f0a2 --- /dev/null +++ b/src/_res/helpers/react18MigrationHelpers.ts @@ -0,0 +1,14 @@ +import {ReactNode} from 'react' +import {MenuComponent} from '../assets/ts/components' + +type WithChildren = { + children?: ReactNode +} + +const reInitMenu = () => { + setTimeout(() => { + MenuComponent.reinitialization() + }, 500) +} + +export {type WithChildren, reInitMenu} diff --git a/src/_res/i18n/Metronici18n.tsx b/src/_res/i18n/Metronici18n.tsx new file mode 100644 index 0000000..2ba569c --- /dev/null +++ b/src/_res/i18n/Metronici18n.tsx @@ -0,0 +1,42 @@ +import React, {FC, createContext, useContext} from 'react' +import {WithChildren} from '../helpers' + +const I18N_CONFIG_KEY = process.env.REACT_APP_I18N_CONFIG_KEY || 'i18nConfig' + +type Props = { + selectedLang: 'de' | 'en' | 'es' | 'fr' | 'ja' | 'zh' +} +const initialState: Props = { + selectedLang: 'en', +} + +function getConfig(): Props { + const ls = localStorage.getItem(I18N_CONFIG_KEY) + if (ls) { + try { + return JSON.parse(ls) as Props + } catch (er) { + console.error(er) + } + } + return initialState +} + +// Side effect +export function setLanguage(lang: string) { + localStorage.setItem(I18N_CONFIG_KEY, JSON.stringify({selectedLang: lang})) + window.location.reload() +} + +const I18nContext = createContext(initialState) + +const useLang = () => { + return useContext(I18nContext).selectedLang +} + +const MetronicI18nProvider: FC = ({children}) => { + const lang = getConfig() + return {children} +} + +export {MetronicI18nProvider, useLang} diff --git a/src/_res/i18n/Site18n.tsx b/src/_res/i18n/Site18n.tsx new file mode 100644 index 0000000..c6faf13 --- /dev/null +++ b/src/_res/i18n/Site18n.tsx @@ -0,0 +1,42 @@ +import React, {FC, createContext, useContext} from 'react' +import {WithChildren} from '../helpers' + +const I18N_CONFIG_KEY = process.env.REACT_APP_I18N_CONFIG_KEY || 'i18nConfig' + +type Props = { + selectedLang: 'de' | 'en' | 'es' | 'fr' | 'ja' | 'zh' +} +const initialState: Props = { + selectedLang: 'en', +} + +function getConfig(): Props { + const ls = localStorage.getItem(I18N_CONFIG_KEY) + if (ls) { + try { + return JSON.parse(ls) as Props + } catch (er) { + console.error(er) + } + } + return initialState +} + +// Side effect +export function setLanguage(lang: string) { + localStorage.setItem(I18N_CONFIG_KEY, JSON.stringify({selectedLang: lang})) + window.location.reload() +} + +const I18nContext = createContext(initialState) + +const useLang = () => { + return useContext(I18nContext).selectedLang +} + +const Site18nProvider: FC = ({children}) => { + const lang = getConfig() + return {children} +} + +export {Site18nProvider, useLang} diff --git a/src/_res/i18n/i18nProvider.tsx b/src/_res/i18n/i18nProvider.tsx new file mode 100644 index 0000000..2ed481f --- /dev/null +++ b/src/_res/i18n/i18nProvider.tsx @@ -0,0 +1,40 @@ +import {FC} from 'react' +import {useLang} from './Metronici18n' +import {IntlProvider} from 'react-intl' +import '@formatjs/intl-relativetimeformat/polyfill' +import '@formatjs/intl-relativetimeformat/locale-data/en' +import '@formatjs/intl-relativetimeformat/locale-data/de' +import '@formatjs/intl-relativetimeformat/locale-data/es' +import '@formatjs/intl-relativetimeformat/locale-data/fr' +import '@formatjs/intl-relativetimeformat/locale-data/ja' +import '@formatjs/intl-relativetimeformat/locale-data/zh' + +import deMessages from './messages/de.json' +import enMessages from './messages/en.json' +import esMessages from './messages/es.json' +import frMessages from './messages/fr.json' +import jaMessages from './messages/ja.json' +import zhMessages from './messages/zh.json' +import { WithChildren } from '../helpers' + +const allMessages = { + de: deMessages, + en: enMessages, + es: esMessages, + fr: frMessages, + ja: jaMessages, + zh: zhMessages, +} + +const I18nProvider: FC = ({children}) => { + const locale = useLang() + const messages = allMessages[locale] + + return ( + + {children} + + ) +} + +export {I18nProvider} diff --git a/src/_res/i18n/messages/de.json b/src/_res/i18n/messages/de.json new file mode 100644 index 0000000..37ba3ce --- /dev/null +++ b/src/_res/i18n/messages/de.json @@ -0,0 +1,69 @@ +{ + "TRANSLATOR.SELECT": "Wähle deine Sprache", + "MENU.NEW": "Neu", + "MENU.ACTIONS": "Aktionen", + "MENU.CREATE_POST": "Erstellen Sie einen neuen Beitrag", + "MENU.PAGES": "Pages", + "MENU.FEATURES": "Eigenschaften", + "MENU.APPS": "Apps", + "MENU.DASHBOARD": "Instrumententafel", + "AUTH.GENERAL.OR": "Oder", + "AUTH.GENERAL.SUBMIT_BUTTON": "einreichen", + "AUTH.GENERAL.NO_ACCOUNT": "Hast du kein Konto?", + "AUTH.GENERAL.SIGNUP_BUTTON": "Anmelden", + "AUTH.GENERAL.FORGOT_BUTTON": "Passwort vergessen", + "AUTH.GENERAL.BACK_BUTTON": "Zurück", + "AUTH.GENERAL.PRIVACY": "Privatsphäre", + "AUTH.GENERAL.LEGAL": "Legal", + "AUTH.GENERAL.CONTACT": "Kontakt", + "AUTH.LOGIN.TITLE": "Create Account", + "AUTH.LOGIN.BUTTON": "Sign In", + "AUTH.FORGOT.TITLE": "Forgotten Password?", + "AUTH.FORGOT.DESC": "Enter your email to reset your password", + "AUTH.FORGOT.SUCCESS": "Your account has been successfully reset.", + "AUTH.REGISTER.TITLE": "Sign Up", + "AUTH.REGISTER.DESC": "Enter your details to create your account", + "AUTH.REGISTER.SUCCESS": "Your account has been successfuly registered.", + "AUTH.INPUT.EMAIL": "Email", + "AUTH.INPUT.FULLNAME": "Fullname", + "AUTH.INPUT.PASSWORD": "Password", + "AUTH.INPUT.CONFIRM_PASSWORD": "Confirm Password", + "AUTH.INPUT.USERNAME": "Nutzername", + "AUTH.VALIDATION.INVALID": "{name} is not valid", + "AUTH.VALIDATION.REQUIRED": "{name} is required", + "AUTH.VALIDATION.MIN_LENGTH": "{name}} minimum length is {{min}", + "AUTH.VALIDATION.AGREEMENT_REQUIRED": "Accepting terms & conditions are required", + "AUTH.VALIDATION.NOT_FOUND": "The requested {name} is not found", + "AUTH.VALIDATION.INVALID_LOGIN": "The login detail is incorrect", + "AUTH.VALIDATION.REQUIRED_FIELD": "Required field", + "AUTH.VALIDATION.MIN_LENGTH_FIELD": "Minimum field length:", + "AUTH.VALIDATION.MAX_LENGTH_FIELD": "Maximum field length:", + "AUTH.VALIDATION.INVALID_FIELD": "Field is not valid", + "ECOMMERCE.COMMON.SELECTED_RECORDS_COUNT": "Selected records count: ", + "ECOMMERCE.COMMON.ALL": "All", + "ECOMMERCE.COMMON.SUSPENDED": "Suspended", + "ECOMMERCE.COMMON.ACTIVE": "Active", + "ECOMMERCE.COMMON.FILTER": "Filter", + "ECOMMERCE.COMMON.BY_STATUS": "by Status", + "ECOMMERCE.COMMON.BY_TYPE": "by Type", + "ECOMMERCE.COMMON.BUSINESS": "Business", + "ECOMMERCE.COMMON.INDIVIDUAL": "Individual", + "ECOMMERCE.COMMON.SEARCH": "Search", + "ECOMMERCE.COMMON.IN_ALL_FIELDS": "in all fields", + "ECOMMERCE.ECOMMERCE": "eCommerce", + "ECOMMERCE.CUSTOMERS.CUSTOMERS": "Customers", + "ECOMMERCE.CUSTOMERS.CUSTOMERS_LIST": "Customers list", + "ECOMMERCE.CUSTOMERS.NEW_CUSTOMER": "New Customer", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.TITLE": "Customer Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.DESCRIPTION": "Are you sure to permanently delete this customer?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.WAIT_DESCRIPTION": "Customer is deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.MESSAGE": "Customer has been deleted", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.TITLE": "Customers Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.DESCRIPTION": "Are you sure to permanently delete selected customers?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.WAIT_DESCRIPTION": "Customers are deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.MESSAGE": "Selected customers have been deleted", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.TITLE": "Status has been updated for selected customers", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.MESSAGE": "Selected customers status have successfully been updated", + "ECOMMERCE.CUSTOMERS.EDIT.UPDATE_MESSAGE": "Customer has been updated", + "ECOMMERCE.CUSTOMERS.EDIT.ADD_MESSAGE": "Customer has been created" +} diff --git a/src/_res/i18n/messages/en.json b/src/_res/i18n/messages/en.json new file mode 100644 index 0000000..1835e12 --- /dev/null +++ b/src/_res/i18n/messages/en.json @@ -0,0 +1,69 @@ +{ + "TRANSLATOR.SELECT": "Select your language", + "MENU.NEW": "new", + "MENU.ACTIONS": "Actions", + "MENU.CREATE_POST": "Create New Post", + "MENU.PAGES": "Pages", + "MENU.FEATURES": "Features", + "MENU.APPS": "Apps", + "MENU.DASHBOARD": "Dashboard", + "AUTH.GENERAL.OR": "Or", + "AUTH.GENERAL.SUBMIT_BUTTON": "Submit", + "AUTH.GENERAL.NO_ACCOUNT": "Don't have an account?", + "AUTH.GENERAL.SIGNUP_BUTTON": "Sign Up", + "AUTH.GENERAL.FORGOT_BUTTON": "Forgot Password", + "AUTH.GENERAL.BACK_BUTTON": "Back", + "AUTH.GENERAL.PRIVACY": "Privacy", + "AUTH.GENERAL.LEGAL": "Legal", + "AUTH.GENERAL.CONTACT": "Contact", + "AUTH.LOGIN.TITLE": "Login Account", + "AUTH.LOGIN.BUTTON": "Sign In", + "AUTH.FORGOT.TITLE": "Forgotten Password?", + "AUTH.FORGOT.DESC": "Enter your email to reset your password", + "AUTH.FORGOT.SUCCESS": "Your account has been successfully reset.", + "AUTH.REGISTER.TITLE": "Sign Up", + "AUTH.REGISTER.DESC": "Enter your details to create your account", + "AUTH.REGISTER.SUCCESS": "Your account has been successfuly registered.", + "AUTH.INPUT.EMAIL": "Email", + "AUTH.INPUT.FULLNAME": "Fullname", + "AUTH.INPUT.PASSWORD": "Password", + "AUTH.INPUT.CONFIRM_PASSWORD": "Confirm Password", + "AUTH.INPUT.USERNAME": "Username", + "AUTH.VALIDATION.INVALID": "{name} is not valid", + "AUTH.VALIDATION.REQUIRED": "{name} is required", + "AUTH.VALIDATION.MIN_LENGTH": "{name}} minimum length is {{min}", + "AUTH.VALIDATION.AGREEMENT_REQUIRED": "Accepting terms & conditions are required", + "AUTH.VALIDATION.NOT_FOUND": "The requested {name} is not found", + "AUTH.VALIDATION.INVALID_LOGIN": "The login detail is incorrect", + "AUTH.VALIDATION.REQUIRED_FIELD": "Required field", + "AUTH.VALIDATION.MIN_LENGTH_FIELD": "Minimum field length:", + "AUTH.VALIDATION.MAX_LENGTH_FIELD": "Maximum field length:", + "AUTH.VALIDATION.INVALID_FIELD": "Field is not valid", + "ECOMMERCE.COMMON.SELECTED_RECORDS_COUNT": "Selected records count: ", + "ECOMMERCE.COMMON.ALL": "All", + "ECOMMERCE.COMMON.SUSPENDED": "Suspended", + "ECOMMERCE.COMMON.ACTIVE": "Active", + "ECOMMERCE.COMMON.FILTER": "Filter", + "ECOMMERCE.COMMON.BY_STATUS": "by Status", + "ECOMMERCE.COMMON.BY_TYPE": "by Type", + "ECOMMERCE.COMMON.BUSINESS": "Business", + "ECOMMERCE.COMMON.INDIVIDUAL": "Individual", + "ECOMMERCE.COMMON.SEARCH": "Search", + "ECOMMERCE.COMMON.IN_ALL_FIELDS": "in all fields", + "ECOMMERCE.ECOMMERCE": "eCommerce", + "ECOMMERCE.CUSTOMERS.CUSTOMERS": "Customers", + "ECOMMERCE.CUSTOMERS.CUSTOMERS_LIST": "Customers list", + "ECOMMERCE.CUSTOMERS.NEW_CUSTOMER": "New Customer", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.TITLE": "Customer Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.DESCRIPTION": "Are you sure to permanently delete this customer?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.WAIT_DESCRIPTION": "Customer is deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.MESSAGE": "Customer has been deleted", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.TITLE": "Customers Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.DESCRIPTION": "Are you sure to permanently delete selected customers?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.WAIT_DESCRIPTION": "Customers are deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.MESSAGE": "Selected customers have been deleted", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.TITLE": "Status has been updated for selected customers", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.MESSAGE": "Selected customers status have successfully been updated", + "ECOMMERCE.CUSTOMERS.EDIT.UPDATE_MESSAGE": "Customer has been updated", + "ECOMMERCE.CUSTOMERS.EDIT.ADD_MESSAGE": "Customer has been created" +} diff --git a/src/_res/i18n/messages/es.json b/src/_res/i18n/messages/es.json new file mode 100644 index 0000000..b2d3693 --- /dev/null +++ b/src/_res/i18n/messages/es.json @@ -0,0 +1,69 @@ +{ + "TRANSLATOR.SELECT": "Elige tu idioma", + "MENU.NEW": "nuevo", + "MENU.ACTIONS": "Comportamiento", + "MENU.CREATE_POST": "Crear nueva publicación", + "MENU.PAGES": "Pages", + "MENU.FEATURES": "Caracteristicas", + "MENU.APPS": "Aplicaciones", + "MENU.DASHBOARD": "Tablero", + "AUTH.GENERAL.OR": "O", + "AUTH.GENERAL.SUBMIT_BUTTON": "Enviar", + "AUTH.GENERAL.NO_ACCOUNT": "No tienes una cuenta?", + "AUTH.GENERAL.SIGNUP_BUTTON": "Regístrate", + "AUTH.GENERAL.FORGOT_BUTTON": "Se te olvidó tu contraseña", + "AUTH.GENERAL.BACK_BUTTON": "Espalda", + "AUTH.GENERAL.PRIVACY": "Intimidad", + "AUTH.GENERAL.LEGAL": "Legal", + "AUTH.GENERAL.CONTACT": "Contacto", + "AUTH.LOGIN.TITLE": "Crear una cuenta", + "AUTH.LOGIN.BUTTON": "Registrarse", + "AUTH.FORGOT.TITLE": "Contraseña olvidada?", + "AUTH.FORGOT.DESC": "Ingrese su correo electrónico para restablecer su contraseña", + "AUTH.FORGOT.SUCCESS": "Your account has been successfully reset.", + "AUTH.REGISTER.TITLE": "Sign Up", + "AUTH.REGISTER.DESC": "Enter your details to create your account", + "AUTH.REGISTER.SUCCESS": "Your account has been successfuly registered.", + "AUTH.INPUT.EMAIL": "Email", + "AUTH.INPUT.FULLNAME": "Fullname", + "AUTH.INPUT.PASSWORD": "Password", + "AUTH.INPUT.CONFIRM_PASSWORD": "Confirm Password", + "AUTH.INPUT.USERNAME": "Usuario", + "AUTH.VALIDATION.INVALID": "{name} is not valid", + "AUTH.VALIDATION.REQUIRED": "{name} is required", + "AUTH.VALIDATION.MIN_LENGTH": "{name}} minimum length is {{min}", + "AUTH.VALIDATION.AGREEMENT_REQUIRED": "Accepting terms & conditions are required", + "AUTH.VALIDATION.NOT_FOUND": "The requested {name} is not found", + "AUTH.VALIDATION.INVALID_LOGIN": "The login detail is incorrect", + "AUTH.VALIDATION.REQUIRED_FIELD": "Required field", + "AUTH.VALIDATION.MIN_LENGTH_FIELD": "Minimum field length:", + "AUTH.VALIDATION.MAX_LENGTH_FIELD": "Maximum field length:", + "AUTH.VALIDATION.INVALID_FIELD": "Field is not valid", + "ECOMMERCE.COMMON.SELECTED_RECORDS_COUNT": "Selected records count: ", + "ECOMMERCE.COMMON.ALL": "All", + "ECOMMERCE.COMMON.SUSPENDED": "Suspended", + "ECOMMERCE.COMMON.ACTIVE": "Active", + "ECOMMERCE.COMMON.FILTER": "Filter", + "ECOMMERCE.COMMON.BY_STATUS": "by Status", + "ECOMMERCE.COMMON.BY_TYPE": "by Type", + "ECOMMERCE.COMMON.BUSINESS": "Business", + "ECOMMERCE.COMMON.INDIVIDUAL": "Individual", + "ECOMMERCE.COMMON.SEARCH": "Search", + "ECOMMERCE.COMMON.IN_ALL_FIELDS": "in all fields", + "ECOMMERCE.ECOMMERCE": "eCommerce", + "ECOMMERCE.CUSTOMERS.CUSTOMERS": "Customers", + "ECOMMERCE.CUSTOMERS.CUSTOMERS_LIST": "Customers list", + "ECOMMERCE.CUSTOMERS.NEW_CUSTOMER": "New Customer", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.TITLE": "Customer Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.DESCRIPTION": "Are you sure to permanently delete this customer?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.WAIT_DESCRIPTION": "Customer is deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.MESSAGE": "Customer has been deleted", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.TITLE": "Customers Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.DESCRIPTION": "Are you sure to permanently delete selected customers?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.WAIT_DESCRIPTION": "Customers are deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.MESSAGE": "Selected customers have been deleted", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.TITLE": "Status has been updated for selected customers", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.MESSAGE": "Selected customers status have successfully been updated", + "ECOMMERCE.CUSTOMERS.EDIT.UPDATE_MESSAGE": "Customer has been updated", + "ECOMMERCE.CUSTOMERS.EDIT.ADD_MESSAGE": "Customer has been created" +} diff --git a/src/_res/i18n/messages/fr.json b/src/_res/i18n/messages/fr.json new file mode 100644 index 0000000..accb3f3 --- /dev/null +++ b/src/_res/i18n/messages/fr.json @@ -0,0 +1,69 @@ +{ + "TRANSLATOR.SELECT": "choisissez votre langue", + "MENU.NEW": "Nouveau", + "MENU.ACTIONS": "Actes", + "MENU.CREATE_POST": "Créer un nouveau Post", + "MENU.PAGES": "Pages", + "MENU.FEATURES": "Fonctionnalités", + "MENU.APPS": "Applications", + "MENU.DASHBOARD": "Tableau de Bord", + "AUTH.GENERAL.OR": "Ou", + "AUTH.GENERAL.SUBMIT_BUTTON": "Soumettre", + "AUTH.GENERAL.NO_ACCOUNT": "Ne pas avoir de compte?", + "AUTH.GENERAL.SIGNUP_BUTTON": "Registre", + "AUTH.GENERAL.FORGOT_BUTTON": "Mot de passe oublié", + "AUTH.GENERAL.BACK_BUTTON": "Back", + "AUTH.GENERAL.PRIVACY": "Privacy", + "AUTH.GENERAL.LEGAL": "Legal", + "AUTH.GENERAL.CONTACT": "Contact", + "AUTH.LOGIN.TITLE": "Créer un compte", + "AUTH.LOGIN.BUTTON": "Sign In", + "AUTH.FORGOT.TITLE": "Forgotten Password?", + "AUTH.FORGOT.DESC": "Enter your email to reset your password", + "AUTH.FORGOT.SUCCESS": "Your account has been successfully reset.", + "AUTH.REGISTER.TITLE": "Sign Up", + "AUTH.REGISTER.DESC": "Enter your details to create your account", + "AUTH.REGISTER.SUCCESS": "Your account has been successfuly registered.", + "AUTH.INPUT.EMAIL": "Email", + "AUTH.INPUT.FULLNAME": "Fullname", + "AUTH.INPUT.PASSWORD": "Mot de passe", + "AUTH.INPUT.CONFIRM_PASSWORD": "Confirm Password", + "AUTH.INPUT.USERNAME": "Nom d'utilisateur", + "AUTH.VALIDATION.INVALID": "{name} n'est pas valide", + "AUTH.VALIDATION.REQUIRED": "{name} est requis", + "AUTH.VALIDATION.MIN_LENGTH": "{name}} minimum length is {{min}", + "AUTH.VALIDATION.AGREEMENT_REQUIRED": "Accepting terms & conditions are required", + "AUTH.VALIDATION.NOT_FOUND": "The requested {name} is not found", + "AUTH.VALIDATION.INVALID_LOGIN": "The login detail is incorrect", + "AUTH.VALIDATION.REQUIRED_FIELD": "Required field", + "AUTH.VALIDATION.MIN_LENGTH_FIELD": "Minimum field length:", + "AUTH.VALIDATION.MAX_LENGTH_FIELD": "Maximum field length:", + "AUTH.VALIDATION.INVALID_FIELD": "Field is not valid", + "ECOMMERCE.COMMON.SELECTED_RECORDS_COUNT": "Nombre d'enregistrements sélectionnés: ", + "ECOMMERCE.COMMON.ALL": "All", + "ECOMMERCE.COMMON.SUSPENDED": "Suspended", + "ECOMMERCE.COMMON.ACTIVE": "Active", + "ECOMMERCE.COMMON.FILTER": "Filter", + "ECOMMERCE.COMMON.BY_STATUS": "by Status", + "ECOMMERCE.COMMON.BY_TYPE": "by Type", + "ECOMMERCE.COMMON.BUSINESS": "Business", + "ECOMMERCE.COMMON.INDIVIDUAL": "Individual", + "ECOMMERCE.COMMON.SEARCH": "Search", + "ECOMMERCE.COMMON.IN_ALL_FIELDS": "in all fields", + "ECOMMERCE.ECOMMERCE": "éCommerce", + "ECOMMERCE.CUSTOMERS.CUSTOMERS": "Les clients", + "ECOMMERCE.CUSTOMERS.CUSTOMERS_LIST": "Liste des clients", + "ECOMMERCE.CUSTOMERS.NEW_CUSTOMER": "Nouveau client", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.TITLE": "Suppression du client", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.DESCRIPTION": "Êtes-vous sûr de supprimer définitivement ce client?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.WAIT_DESCRIPTION": "Le client est en train de supprimer ...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.MESSAGE": "Le client a été supprimé", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.TITLE": "Supprimer les clients", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.DESCRIPTION": "Êtes-vous sûr de supprimer définitivement les clients sélectionnés?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.WAIT_DESCRIPTION": "Les clients suppriment ...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.MESSAGE": "Les clients sélectionnés ont été supprimés", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.TITLE": "Le statut a été mis à jour pour les clients sélectionnés", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.MESSAGE": "Le statut des clients sélectionnés a été mis à jour avec succès", + "ECOMMERCE.CUSTOMERS.EDIT.UPDATE_MESSAGE": "Le client a été mis à jour", + "ECOMMERCE.CUSTOMERS.EDIT.ADD_MESSAGE": "Le client a été créé" +} diff --git a/src/_res/i18n/messages/ja.json b/src/_res/i18n/messages/ja.json new file mode 100644 index 0000000..0f3c395 --- /dev/null +++ b/src/_res/i18n/messages/ja.json @@ -0,0 +1,69 @@ +{ + "TRANSLATOR.SELECT": "あなたが使う言語を選んでください", + "MENU.NEW": "新しい", + "MENU.ACTIONS": "行動", + "MENU.CREATE_POST": "新しい投稿を作成", + "MENU.PAGES": "Pages", + "MENU.FEATURES": "特徴", + "MENU.APPS": "アプリ", + "MENU.DASHBOARD": "ダッシュボード", + "AUTH.GENERAL.OR": "または", + "AUTH.GENERAL.SUBMIT_BUTTON": "提出する", + "AUTH.GENERAL.NO_ACCOUNT": "アカウントを持っていない?", + "AUTH.GENERAL.SIGNUP_BUTTON": "サインアップ", + "AUTH.GENERAL.FORGOT_BUTTON": "パスワードをお忘れですか", + "AUTH.GENERAL.BACK_BUTTON": "バック", + "AUTH.GENERAL.PRIVACY": "プライバシー", + "AUTH.GENERAL.LEGAL": "法的", + "AUTH.GENERAL.CONTACT": "接触", + "AUTH.LOGIN.TITLE": "Create Account", + "AUTH.LOGIN.BUTTON": "Sign In", + "AUTH.FORGOT.TITLE": "Forgotten Password?", + "AUTH.FORGOT.DESC": "Enter your email to reset your password", + "AUTH.FORGOT.SUCCESS": "Your account has been successfully reset.", + "AUTH.REGISTER.TITLE": "Sign Up", + "AUTH.REGISTER.DESC": "Enter your details to create your account", + "AUTH.REGISTER.SUCCESS": "Your account has been successfuly registered.", + "AUTH.INPUT.EMAIL": "Email", + "AUTH.INPUT.FULLNAME": "Fullname", + "AUTH.INPUT.PASSWORD": "Password", + "AUTH.INPUT.CONFIRM_PASSWORD": "Confirm Password", + "AUTH.INPUT.USERNAME": "ユーザー名", + "AUTH.VALIDATION.INVALID": "{name} is not valid", + "AUTH.VALIDATION.REQUIRED": "{name} is required", + "AUTH.VALIDATION.MIN_LENGTH": "{name}} minimum length is {{min}", + "AUTH.VALIDATION.AGREEMENT_REQUIRED": "Accepting terms & conditions are required", + "AUTH.VALIDATION.NOT_FOUND": "The requested {name} is not found", + "AUTH.VALIDATION.INVALID_LOGIN": "The login detail is incorrect", + "AUTH.VALIDATION.REQUIRED_FIELD": "Required field", + "AUTH.VALIDATION.MIN_LENGTH_FIELD": "Minimum field length:", + "AUTH.VALIDATION.MAX_LENGTH_FIELD": "Maximum field length:", + "AUTH.VALIDATION.INVALID_FIELD": "Field is not valid", + "ECOMMERCE.COMMON.SELECTED_RECORDS_COUNT": "Selected records count: ", + "ECOMMERCE.COMMON.ALL": "All", + "ECOMMERCE.COMMON.SUSPENDED": "Suspended", + "ECOMMERCE.COMMON.ACTIVE": "Active", + "ECOMMERCE.COMMON.FILTER": "Filter", + "ECOMMERCE.COMMON.BY_STATUS": "by Status", + "ECOMMERCE.COMMON.BY_TYPE": "by Type", + "ECOMMERCE.COMMON.BUSINESS": "Business", + "ECOMMERCE.COMMON.INDIVIDUAL": "Individual", + "ECOMMERCE.COMMON.SEARCH": "Search", + "ECOMMERCE.COMMON.IN_ALL_FIELDS": "in all fields", + "ECOMMERCE.ECOMMERCE": "eCommerce", + "ECOMMERCE.CUSTOMERS.CUSTOMERS": "Customers", + "ECOMMERCE.CUSTOMERS.CUSTOMERS_LIST": "Customers list", + "ECOMMERCE.CUSTOMERS.NEW_CUSTOMER": "New Customer", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.TITLE": "Customer Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.DESCRIPTION": "Are you sure to permanently delete this customer?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.WAIT_DESCRIPTION": "Customer is deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.MESSAGE": "Customer has been deleted", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.TITLE": "Customers Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.DESCRIPTION": "Are you sure to permanently delete selected customers?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.WAIT_DESCRIPTION": "Customers are deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.MESSAGE": "Selected customers have been deleted", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.TITLE": "Status has been updated for selected customers", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.MESSAGE": "Selected customers status have successfully been updated", + "ECOMMERCE.CUSTOMERS.EDIT.UPDATE_MESSAGE": "Customer has been updated", + "ECOMMERCE.CUSTOMERS.EDIT.ADD_MESSAGE": "Customer has been created" +} diff --git a/src/_res/i18n/messages/zh.json b/src/_res/i18n/messages/zh.json new file mode 100644 index 0000000..1389d5c --- /dev/null +++ b/src/_res/i18n/messages/zh.json @@ -0,0 +1,69 @@ +{ + "TRANSLATOR.SELECT": "选择你的语言", + "MENU.NEW": "新", + "MENU.ACTIONS": "行动", + "MENU.CREATE_POST": "创建新帖子", + "MENU.PAGES": "Pages", + "MENU.FEATURES": "特征", + "MENU.APPS": "应用", + "MENU.DASHBOARD": "仪表板", + "AUTH.GENERAL.OR": "要么", + "AUTH.GENERAL.SUBMIT_BUTTON": "提交", + "AUTH.GENERAL.NO_ACCOUNT": "没有账号?", + "AUTH.GENERAL.SIGNUP_BUTTON": "注册", + "AUTH.GENERAL.FORGOT_BUTTON": "忘记密码", + "AUTH.GENERAL.BACK_BUTTON": "背部", + "AUTH.GENERAL.PRIVACY": "隐私", + "AUTH.GENERAL.LEGAL": "法律", + "AUTH.GENERAL.CONTACT": "联系", + "AUTH.LOGIN.TITLE": "创建帐号", + "AUTH.LOGIN.BUTTON": "签到", + "AUTH.FORGOT.TITLE": "Forgotten Password?", + "AUTH.FORGOT.DESC": "Enter your email to reset your password", + "AUTH.FORGOT.SUCCESS": "Your account has been successfully reset.", + "AUTH.REGISTER.TITLE": "Sign Up", + "AUTH.REGISTER.DESC": "Enter your details to create your account", + "AUTH.REGISTER.SUCCESS": "Your account has been successfuly registered.", + "AUTH.INPUT.EMAIL": "Email", + "AUTH.INPUT.FULLNAME": "Fullname", + "AUTH.INPUT.PASSWORD": "Password", + "AUTH.INPUT.CONFIRM_PASSWORD": "Confirm Password", + "AUTH.INPUT.USERNAME": "用戶名", + "AUTH.VALIDATION.INVALID": "{name} is not valid", + "AUTH.VALIDATION.REQUIRED": "{name} is required", + "AUTH.VALIDATION.MIN_LENGTH": "{name}} minimum length is {{min}", + "AUTH.VALIDATION.AGREEMENT_REQUIRED": "Accepting terms & conditions are required", + "AUTH.VALIDATION.NOT_FOUND": "The requested {name} is not found", + "AUTH.VALIDATION.INVALID_LOGIN": "The login detail is incorrect", + "AUTH.VALIDATION.REQUIRED_FIELD": "Required field", + "AUTH.VALIDATION.MIN_LENGTH_FIELD": "Minimum field length:", + "AUTH.VALIDATION.MAX_LENGTH_FIELD": "Maximum field length:", + "AUTH.VALIDATION.INVALID_FIELD": "Field is not valid", + "ECOMMERCE.COMMON.SELECTED_RECORDS_COUNT": "Selected records count: ", + "ECOMMERCE.COMMON.ALL": "All", + "ECOMMERCE.COMMON.SUSPENDED": "Suspended", + "ECOMMERCE.COMMON.ACTIVE": "Active", + "ECOMMERCE.COMMON.FILTER": "Filter", + "ECOMMERCE.COMMON.BY_STATUS": "by Status", + "ECOMMERCE.COMMON.BY_TYPE": "by Type", + "ECOMMERCE.COMMON.BUSINESS": "Business", + "ECOMMERCE.COMMON.INDIVIDUAL": "Individual", + "ECOMMERCE.COMMON.SEARCH": "Search", + "ECOMMERCE.COMMON.IN_ALL_FIELDS": "in all fields", + "ECOMMERCE.ECOMMERCE": "eCommerce", + "ECOMMERCE.CUSTOMERS.CUSTOMERS": "顾客", + "ECOMMERCE.CUSTOMERS.CUSTOMERS_LIST": "客户名单", + "ECOMMERCE.CUSTOMERS.NEW_CUSTOMER": "New Customer", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.TITLE": "Customer Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.DESCRIPTION": "Are you sure to permanently delete this customer?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.WAIT_DESCRIPTION": "Customer is deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_SIMPLE.MESSAGE": "Customer has been deleted", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.TITLE": "Customers Delete", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.DESCRIPTION": "Are you sure to permanently delete selected customers?", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.WAIT_DESCRIPTION": "Customers are deleting...", + "ECOMMERCE.CUSTOMERS.DELETE_CUSTOMER_MULTY.MESSAGE": "Selected customers have been deleted", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.TITLE": "Status has been updated for selected customers", + "ECOMMERCE.CUSTOMERS.UPDATE_STATUS.MESSAGE": "Selected customers status have successfully been updated", + "ECOMMERCE.CUSTOMERS.EDIT.UPDATE_MESSAGE": "Customer has been updated", + "ECOMMERCE.CUSTOMERS.EDIT.ADD_MESSAGE": "Customer has been created" +} diff --git a/src/_res/layout/MasterInit.tsx b/src/_res/layout/MasterInit.tsx new file mode 100644 index 0000000..203e449 --- /dev/null +++ b/src/_res/layout/MasterInit.tsx @@ -0,0 +1,44 @@ +import {useEffect, useRef} from 'react' +import {Tab} from 'bootstrap' +import { + MenuComponent, + DrawerComponent, + ScrollComponent, + ScrollTopComponent, + StickyComponent, + ToggleComponent, + SwapperComponent, +} from '../assets/ts/components' +import {ThemeModeComponent} from '../assets/ts/layout' + +import {useLayout} from './core' + +export function MasterInit() { + const {config} = useLayout() + const isFirstRun = useRef(true) + const pluginsInitialization = () => { + isFirstRun.current = false + ThemeModeComponent.init() + setTimeout(() => { + ToggleComponent.bootstrap() + ScrollTopComponent.bootstrap() + DrawerComponent.bootstrap() + StickyComponent.bootstrap() + MenuComponent.bootstrap() + ScrollComponent.bootstrap() + SwapperComponent.bootstrap() + document.querySelectorAll('[data-bs-toggle="tab"]').forEach((tab) => { + Tab.getOrCreateInstance(tab) + }) + }, 500) + } + + useEffect(() => { + if (isFirstRun.current) { + isFirstRun.current = false + pluginsInitialization() + } + }, [config]) + + return <> +} diff --git a/src/_res/layout/MasterLayout.tsx b/src/_res/layout/MasterLayout.tsx new file mode 100644 index 0000000..1095a49 --- /dev/null +++ b/src/_res/layout/MasterLayout.tsx @@ -0,0 +1,63 @@ +import {useEffect} from 'react' +import {Outlet, useLocation} from 'react-router-dom' +import {HeaderWrapper} from './components/header' +import {RightToolbar} from '../partials/layout/RightToolbar' +import {ScrollTop} from './components/scroll-top' +import {Content} from './components/content' +import {FooterWrapper} from './components/footer' +import {Sidebar} from './components/sidebar' +import { + DrawerMessenger, + ActivityDrawer, + InviteUsers, + UpgradePlan, + ThemeModeProvider, +} from '../partials' +import {PageDataProvider} from './core' +import {reInitMenu} from '../helpers' +import {ToolbarWrapper} from './components/toolbar' + +const MasterLayout = () => { + const location = useLocation() + useEffect(() => { + reInitMenu() + }, [location.key]) + + return ( + + +
+
+ +
+ +
+
+ + + + +
+ +
+
+
+
+ + {/* begin:: Drawers */} + + + + {/* end:: Drawers */} + + {/* begin:: Modals */} + + + {/* end:: Modals */} + +
+
+ ) +} + +export {MasterLayout} diff --git a/src/_res/layout/components/content/Content.tsx b/src/_res/layout/components/content/Content.tsx new file mode 100644 index 0000000..16b8ca3 --- /dev/null +++ b/src/_res/layout/components/content/Content.tsx @@ -0,0 +1,39 @@ +import {useEffect} from 'react' +import {useLocation} from 'react-router' +import clsx from 'clsx' +import {useLayout} from '../../core' +import {DrawerComponent} from '../../../assets/ts/components' +import {WithChildren} from '../../../helpers' + +const Content = ({children}: WithChildren) => { + const {config, classes} = useLayout() + const location = useLocation() + useEffect(() => { + DrawerComponent.hideAll() + }, [location]) + + const appContentContainer = config.app?.content?.container + return ( +
+ {appContentContainer ? ( +
+ {children} +
+ ) : ( + <>{children} + )} +
+ ) +} + +export {Content} diff --git a/src/_res/layout/components/content/index.ts b/src/_res/layout/components/content/index.ts new file mode 100644 index 0000000..aa90efe --- /dev/null +++ b/src/_res/layout/components/content/index.ts @@ -0,0 +1 @@ +export * from './Content' diff --git a/src/_res/layout/components/footer/Footer.tsx b/src/_res/layout/components/footer/Footer.tsx new file mode 100644 index 0000000..2d8748a --- /dev/null +++ b/src/_res/layout/components/footer/Footer.tsx @@ -0,0 +1,62 @@ +/* eslint-disable react/jsx-no-target-blank */ +import {useEffect} from 'react' +import {ILayout, useLayout} from '../../core' + +const Footer = () => { + const {config} = useLayout() + useEffect(() => { + updateDOM(config) + }, [config]) + return ( + <> +
+ + {new Date().getFullYear().toString()}© + + + Keenthemes + +
+ + + + ) +} + +const updateDOM = (config: ILayout) => { + if (config.app?.footer?.fixed?.desktop) { + document.body.classList.add('data-kt-app-footer-fixed', 'true') + } + + if (config.app?.footer?.fixed?.mobile) { + document.body.classList.add('data-kt-app-footer-fixed-mobile', 'true') + } +} + +export {Footer} diff --git a/src/_res/layout/components/footer/FooterWrapper.tsx b/src/_res/layout/components/footer/FooterWrapper.tsx new file mode 100644 index 0000000..0a1ca6f --- /dev/null +++ b/src/_res/layout/components/footer/FooterWrapper.tsx @@ -0,0 +1,24 @@ +import clsx from 'clsx' +import {useLayout} from '../../core' +import {Footer} from './Footer' + +const FooterWrapper = () => { + const {config} = useLayout() + if (!config.app?.footer?.display) { + return null + } + + return ( + + ) +} + +export {FooterWrapper} diff --git a/src/_res/layout/components/footer/index.ts b/src/_res/layout/components/footer/index.ts new file mode 100644 index 0000000..eeeabf7 --- /dev/null +++ b/src/_res/layout/components/footer/index.ts @@ -0,0 +1 @@ +export * from './FooterWrapper' diff --git a/src/_res/layout/components/header/Header.tsx b/src/_res/layout/components/header/Header.tsx new file mode 100644 index 0000000..9ae256d --- /dev/null +++ b/src/_res/layout/components/header/Header.tsx @@ -0,0 +1,89 @@ +import {FC, useEffect} from 'react' +import {ILayout, useLayout} from '../../core' +import {MenuInner} from './header-menus' + +const Header: FC = () => { + const {config} = useLayout() + useEffect(() => { + updateDOM(config) + }, [config]) + + return ( +
+ +
+ ) +} + +const updateDOM = (config: ILayout) => { + if (config.app?.header?.default?.fixed?.desktop) { + document.body.setAttribute('data-kt-app-header-fixed', 'true') + } + + if (config.app?.header?.default?.fixed?.mobile) { + document.body.setAttribute('data-kt-app-header-fixed-mobile', 'true') + } + + if (config.app?.header?.default?.stacked) { + document.body.setAttribute('data-kt-app-header-stacked', 'true') + } + + const appHeaderDefaultStickyEnabled = config.app?.header?.default?.sticky?.enabled + let appHeaderDefaultStickyAttributes: {[attrName: string]: string} = {} + if (appHeaderDefaultStickyEnabled) { + appHeaderDefaultStickyAttributes = config.app?.header?.default?.sticky?.attributes as { + [attrName: string]: string + } + } + + const appHeaderDefaultMinimizeEnabled = config.app?.header?.default?.minimize?.enabled + let appHeaderDefaultMinimizeAttributes: {[attrName: string]: string} = {} + if (appHeaderDefaultMinimizeEnabled) { + appHeaderDefaultMinimizeAttributes = config.app?.header?.default?.minimize?.attributes as { + [attrName: string]: string + } + } + + setTimeout(() => { + const headerElement = document.getElementById('kt_app_header') + // header + if (headerElement) { + const headerAttributes = headerElement + .getAttributeNames() + .filter((t) => t.indexOf('data-') > -1) + headerAttributes.forEach((attr) => headerElement.removeAttribute(attr)) + + if (appHeaderDefaultStickyEnabled) { + for (const key in appHeaderDefaultStickyAttributes) { + if (appHeaderDefaultStickyAttributes.hasOwnProperty(key)) { + headerElement.setAttribute(key, appHeaderDefaultStickyAttributes[key]) + } + } + } + + if (appHeaderDefaultMinimizeEnabled) { + for (const key in appHeaderDefaultMinimizeAttributes) { + if (appHeaderDefaultMinimizeAttributes.hasOwnProperty(key)) { + headerElement.setAttribute(key, appHeaderDefaultMinimizeAttributes[key]) + } + } + } + } + }, 0) +} + +export {Header} diff --git a/src/_res/layout/components/header/HeaderWrapper.tsx b/src/_res/layout/components/header/HeaderWrapper.tsx new file mode 100644 index 0000000..a7d0097 --- /dev/null +++ b/src/_res/layout/components/header/HeaderWrapper.tsx @@ -0,0 +1,100 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import clsx from 'clsx' +import {Link} from 'react-router-dom' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' +import {useLayout} from '../../core' +import {Header} from './Header' +import {Navbar} from './Navbar' + +export function HeaderWrapper() { + const {config, classes} = useLayout() + if (!config.app?.header?.display) { + return null + } + + return ( +
+
+ {config.app.sidebar?.display && ( + <> +
+
+ +
+
+ + Logo + +
+
+ + )} + + {!config.app.sidebar?.display && ( +
+ + {config.layoutType !== 'dark-header' ? ( + Logo + ) : ( + <> + Logo + Logo + + )} + +
+ )} + +
+ {config.app.header.default?.content === 'menu' && + config.app.header.default.menu?.display && ( +
+
+
+ )} + +
+
+
+ ) +} diff --git a/src/_res/layout/components/header/Navbar.tsx b/src/_res/layout/components/header/Navbar.tsx new file mode 100644 index 0000000..3006bbe --- /dev/null +++ b/src/_res/layout/components/header/Navbar.tsx @@ -0,0 +1,75 @@ +import clsx from 'clsx' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' +import {HeaderNotificationsMenu, HeaderUserMenu, Search, ThemeModeSwitcher} from '../../../partials' +import {useLayout} from '../../core' + +const itemClass = 'ms-1 ms-lg-3' +const btnClass = + 'btn btn-icon btn-custom btn-icon-muted btn-active-light btn-active-color-primary w-35px h-35px w-md-40px h-md-40px' +const userAvatarClass = 'symbol-35px symbol-md-40px' +const btnIconClass = 'svg-icon-1' + +const Navbar = () => { + const {config} = useLayout() + return ( +
+
+ +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+
+ + +
+
+ +
+ +
+ +
+
+ +
+ +
+ + {config.app?.header?.default?.menu?.display && ( +
+
+ +
+
+ )} +
+ ) +} + +export {Navbar} diff --git a/src/_res/layout/components/header/header-menus/MegaMenu.tsx b/src/_res/layout/components/header/header-menus/MegaMenu.tsx new file mode 100644 index 0000000..0291c55 --- /dev/null +++ b/src/_res/layout/components/header/header-menus/MegaMenu.tsx @@ -0,0 +1,162 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {Link} from 'react-router-dom' +import {toAbsoluteUrl} from '../../../../helpers' +import {useLayout} from '../../../core' + +const MegaMenu: FC = () => { + const {setLayoutType, setToolbarType} = useLayout() + return ( +
+ {/* begin:Col */} +
+ {/* begin:Row */} +
+ {/* begin:Col */} +
+ {/* begin:Heading */} +

Layouts

+ {/* end:Heading */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setLayoutType('light-sidebar')} className='menu-link'> + + + + Light Sidebar + + {/* end:Menu link */} +
+ {/* end:Menu item */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setLayoutType('dark-sidebar')} className='menu-link'> + + + + Dark Sidebar + + {/* end:Menu link */} +
+ {/* end:Menu item */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setLayoutType('light-header')} className='menu-link'> + + + + Light Header + + {/* end:Menu link */} +
+ {/* end:Menu item */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setLayoutType('dark-header')} className='menu-link'> + + + + Dark Header + + {/* end:Menu link */} +
+ {/* end:Menu item */} +
+ {/* end:Col */} + {/* begin:Col */} +
+ {/* begin:Heading */} +

Toolbars

+ {/* end:Heading */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setToolbarType('classic')} className='menu-link'> + + + + Classic + + {/* end:Menu link */} +
+ {/* end:Menu item */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setToolbarType('saas')} className='menu-link'> + + + + SaaS + + {/* end:Menu link */} +
+ {/* end:Menu item */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setToolbarType('accounting')} className='menu-link'> + + + + Accounting + + {/* end:Menu link */} +
+ {/* end:Menu item */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setToolbarType('extended')} className='menu-link'> + + + + Extended + + {/* end:Menu link */} +
+ {/* end:Menu item */} + {/* begin:Menu item */} +
+ {/* begin:Menu link */} + setToolbarType('reports')} className='menu-link'> + + + + Reports + + {/* end:Menu link */} +
+ {/* end:Menu item */} +
+ {/* end:Col */} +
+ {/* end:Row */} +
+ {/* begin:Layout Builder */} +
+
+
Layout Builder
+
Customize view
+
+ + Try Builder + +
+ {/* end:Layout Builder */} +
+ {/* end:Col */} + {/* begin:Col */} +
+ +
+ {/* end:Col */} +
+ ) +} + +export {MegaMenu} diff --git a/src/_res/layout/components/header/header-menus/MenuInner.tsx b/src/_res/layout/components/header/header-menus/MenuInner.tsx new file mode 100644 index 0000000..68b2243 --- /dev/null +++ b/src/_res/layout/components/header/header-menus/MenuInner.tsx @@ -0,0 +1,134 @@ +import {useIntl} from 'react-intl' +import {MenuItem} from './MenuItem' +import {MenuInnerWithSub} from './MenuInnerWithSub' +import {MegaMenu} from './MegaMenu' + +export function MenuInner() { + const intl = useIntl() + return ( + <> + + + + {/* PAGES */} + + + + + + + + + + + + + + + {/* ACCOUNT */} + + + + + + {/* ERRORS */} + + + + + + {/* Widgets */} + + + + + + + + + + + + {/* PAGES */} + + + + + + + + + + + + + ) +} diff --git a/src/_res/layout/components/header/header-menus/MenuInnerWithSub.tsx b/src/_res/layout/components/header/header-menus/MenuInnerWithSub.tsx new file mode 100644 index 0000000..a3ce71e --- /dev/null +++ b/src/_res/layout/components/header/header-menus/MenuInnerWithSub.tsx @@ -0,0 +1,82 @@ +import {FC, useRef, useEffect} from 'react' +import {useLocation} from 'react-router' +import clsx from 'clsx' +import {checkIsActive, KTSVG, WithChildren} from '../../../../helpers' + +type Props = { + to: string + title: string + icon?: string + fontIcon?: string + menuTrigger?: 'click' | `{default:'click', lg: 'hover'}` + menuPlacement?: 'right-start' | 'bottom-start' | 'left-start' + hasArrow?: boolean + hasBullet?: boolean + isMega?: boolean +} + +const MenuInnerWithSub: FC = ({ + children, + to, + title, + icon, + fontIcon, + menuTrigger, + menuPlacement, + hasArrow = false, + hasBullet = false, + isMega = false, +}) => { + const menuItemRef = useRef(null) + const {pathname} = useLocation() + + useEffect(() => { + if (menuItemRef.current && menuTrigger && menuPlacement) { + menuItemRef.current.setAttribute('data-kt-menu-trigger', menuTrigger) + menuItemRef.current.setAttribute('data-kt-menu-placement', menuPlacement) + } + }, [menuTrigger, menuPlacement]) + + return ( +
+ + {hasBullet && ( + + + + )} + + {icon && ( + + + + )} + + {fontIcon && ( + + + + )} + + {title} + + {hasArrow && } + +
+ {children} +
+
+ ) +} + +export {MenuInnerWithSub} diff --git a/src/_res/layout/components/header/header-menus/MenuItem.tsx b/src/_res/layout/components/header/header-menus/MenuItem.tsx new file mode 100644 index 0000000..84616b1 --- /dev/null +++ b/src/_res/layout/components/header/header-menus/MenuItem.tsx @@ -0,0 +1,53 @@ +import {FC} from 'react' +import {useLocation} from 'react-router' +import {Link} from 'react-router-dom' +import clsx from 'clsx' +import {checkIsActive, KTSVG} from '../../../../helpers' + +type Props = { + to: string + title: string + icon?: string + fontIcon?: string + hasArrow?: boolean + hasBullet?: boolean +} + +const MenuItem: FC = ({to, title, icon, fontIcon, hasArrow = false, hasBullet = false}) => { + const {pathname} = useLocation() + + return ( +
+ + {hasBullet && ( + + + + )} + + {icon && ( + + + + )} + + {fontIcon && ( + + + + )} + + {title} + + {hasArrow && } + +
+ ) +} + +export {MenuItem} diff --git a/src/_res/layout/components/header/header-menus/index.ts b/src/_res/layout/components/header/header-menus/index.ts new file mode 100644 index 0000000..fecbc56 --- /dev/null +++ b/src/_res/layout/components/header/header-menus/index.ts @@ -0,0 +1 @@ +export * from './MenuInner' diff --git a/src/_res/layout/components/header/index.ts b/src/_res/layout/components/header/index.ts new file mode 100644 index 0000000..1019be4 --- /dev/null +++ b/src/_res/layout/components/header/index.ts @@ -0,0 +1 @@ +export * from './HeaderWrapper' diff --git a/src/_res/layout/components/scroll-top/ScrollTop.tsx b/src/_res/layout/components/scroll-top/ScrollTop.tsx new file mode 100644 index 0000000..23f86aa --- /dev/null +++ b/src/_res/layout/components/scroll-top/ScrollTop.tsx @@ -0,0 +1,57 @@ +import {useEffect, useRef} from 'react' +import {useLocation} from 'react-router-dom' +import { + ScrollTopComponent, + DrawerComponent, + ToggleComponent, + StickyComponent, +} from '../../../assets/ts/components' +import {KTSVG} from '../../../helpers' + +export function ScrollTop() { + const {pathname} = useLocation() + const isFirstRun = useRef(true) + + const pluginsReinitialization = () => { + setTimeout(() => { + StickyComponent.reInitialization() + setTimeout(() => { + ToggleComponent.reinitialization() + DrawerComponent.reinitialization() + }, 70) + }, 140) + } + + const scrollTop = () => { + ScrollTopComponent.goTop() + } + + const updateHeaderSticky = () => { + const stickyHeader = document.body.querySelectorAll(`[data-kt-sticky-name="header"]`) + if (stickyHeader && stickyHeader.length > 0) { + const sticky = StickyComponent.getInstance(stickyHeader[0] as HTMLElement) + if (sticky) { + sticky.update() + } + } + } + + useEffect(() => { + if (isFirstRun.current) { + isFirstRun.current = false + } else { + pluginsReinitialization() + } + + updateHeaderSticky() + setTimeout(() => { + scrollTop() + }, 0) + }, [pathname]) + + return ( +
+ +
+ ) +} diff --git a/src/_res/layout/components/scroll-top/index.ts b/src/_res/layout/components/scroll-top/index.ts new file mode 100644 index 0000000..44b0415 --- /dev/null +++ b/src/_res/layout/components/scroll-top/index.ts @@ -0,0 +1 @@ +export * from './ScrollTop' diff --git a/src/_res/layout/components/sidebar/Sidebar.tsx b/src/_res/layout/components/sidebar/Sidebar.tsx new file mode 100644 index 0000000..c1621c5 --- /dev/null +++ b/src/_res/layout/components/sidebar/Sidebar.tsx @@ -0,0 +1,129 @@ +import clsx from 'clsx' +import {useEffect} from 'react' +import {ILayout, useLayout} from '../../core' +import {SidebarMenu} from './sidebar-menu/SidebarMenu' +import {SidebarFooter} from './SidebarFooter' +import {SidebarLogo} from './SidebarLogo' + +const Sidebar = () => { + const {config} = useLayout() + + useEffect(() => { + updateDOM(config) + }, [config]) + + if (!config.app?.sidebar?.display) { + return null + } + + return ( +
+ + + +
+ ) +} + +const updateDOM = (config: ILayout) => { + if (config.app?.sidebar?.default?.minimize?.desktop?.enabled) { + if (config.app?.sidebar?.default?.minimize?.desktop?.default) { + document.body.setAttribute('data-kt-app-sidebar-minimize', 'on') + } + + if (config.app?.sidebar?.default?.minimize?.desktop?.hoverable) { + document.body.setAttribute('data-kt-app-sidebar-hoverable', 'true') + } + } + + if (config.app?.sidebar?.default?.minimize?.mobile?.enabled) { + if (config.app?.sidebar?.default?.minimize?.mobile?.default) { + document.body.setAttribute('data-kt-app-sidebar-minimize-mobile', 'on') + } + + if (config.app?.sidebar?.default?.minimize?.mobile?.hoverable) { + document.body.setAttribute('data-kt-app-sidebar-hoverable-mobile', 'true') + } + } + + if (config.app?.sidebar?.default?.collapse?.desktop?.enabled) { + if (config.app?.sidebar?.default?.collapse?.desktop?.default) { + document.body.setAttribute('data-kt-app-sidebar-collapse', 'on') + } + } + + if (config.app?.sidebar?.default?.collapse?.mobile?.enabled) { + if (config.app?.sidebar?.default?.collapse?.mobile?.default) { + document.body.setAttribute('data-kt-app-sidebar-collapse-mobile', 'on') + } + } + + if (config.app?.sidebar?.default?.push) { + if (config.app?.sidebar?.default?.push?.header) { + document.body.setAttribute('data-kt-app-sidebar-push-header', 'true') + } + + if (config.app?.sidebar?.default?.push?.toolbar) { + document.body.setAttribute('data-kt-app-sidebar-push-toolbar', 'true') + } + + if (config.app?.sidebar?.default?.push?.footer) { + document.body.setAttribute('data-kt-app-sidebar-push-footer', 'true') + } + } + + if (config.app?.sidebar?.default?.stacked) { + document.body.setAttribute('app-sidebar-stacked', 'true') + } + + document.body.setAttribute('data-kt-app-sidebar-enabled', 'true') + document.body.setAttribute( + 'data-kt-app-sidebar-fixed', + config.app?.sidebar?.default?.fixed?.desktop?.toString() || '' + ) + + const appSidebarDefaultDrawerEnabled = config.app?.sidebar?.default?.drawer?.enabled + let appSidebarDefaultDrawerAttributes: {[attrName: string]: string} = {} + if (appSidebarDefaultDrawerEnabled) { + appSidebarDefaultDrawerAttributes = config.app?.sidebar?.default?.drawer?.attributes as { + [attrName: string]: string + } + } + + const appSidebarDefaultStickyEnabled = config.app?.sidebar?.default?.sticky?.enabled + let appSidebarDefaultStickyAttributes: {[attrName: string]: string} = {} + if (appSidebarDefaultStickyEnabled) { + appSidebarDefaultStickyAttributes = config.app?.sidebar?.default?.sticky?.attributes as { + [attrName: string]: string + } + } + + setTimeout(() => { + const sidebarElement = document.getElementById('kt_app_sidebar') + // sidebar + if (sidebarElement) { + const sidebarAttributes = sidebarElement + .getAttributeNames() + .filter((t) => t.indexOf('data-') > -1) + sidebarAttributes.forEach((attr) => sidebarElement.removeAttribute(attr)) + + if (appSidebarDefaultDrawerEnabled) { + for (const key in appSidebarDefaultDrawerAttributes) { + if (appSidebarDefaultDrawerAttributes.hasOwnProperty(key)) { + sidebarElement.setAttribute(key, appSidebarDefaultDrawerAttributes[key]) + } + } + } + + if (appSidebarDefaultStickyEnabled) { + for (const key in appSidebarDefaultStickyAttributes) { + if (appSidebarDefaultStickyAttributes.hasOwnProperty(key)) { + sidebarElement.setAttribute(key, appSidebarDefaultStickyAttributes[key]) + } + } + } + } + }, 0) +} + +export {Sidebar} diff --git a/src/_res/layout/components/sidebar/SidebarFooter.tsx b/src/_res/layout/components/sidebar/SidebarFooter.tsx new file mode 100644 index 0000000..3b5ee97 --- /dev/null +++ b/src/_res/layout/components/sidebar/SidebarFooter.tsx @@ -0,0 +1,23 @@ +/* eslint-disable react/jsx-no-target-blank */ +import {KTSVG} from '../../../helpers' + +const SidebarFooter = () => { + return ( + + ) +} + +export {SidebarFooter} diff --git a/src/_res/layout/components/sidebar/SidebarLogo.tsx b/src/_res/layout/components/sidebar/SidebarLogo.tsx new file mode 100644 index 0000000..c4194fe --- /dev/null +++ b/src/_res/layout/components/sidebar/SidebarLogo.tsx @@ -0,0 +1,69 @@ +import {Link} from 'react-router-dom' +import clsx from 'clsx' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' +import {useLayout} from '../../core' + +const SidebarLogo = () => { + const {config} = useLayout() + const appSidebarDefaultMinimizeDesktopEnabled = + config?.app?.sidebar?.default?.minimize?.desktop?.enabled + const appSidebarDefaultCollapseDesktopEnabled = + config?.app?.sidebar?.default?.collapse?.desktop?.enabled + const toggleType = appSidebarDefaultCollapseDesktopEnabled + ? 'collapse' + : appSidebarDefaultMinimizeDesktopEnabled + ? 'minimize' + : '' + const toggleState = appSidebarDefaultMinimizeDesktopEnabled ? 'active' : '' + const appSidebarDefaultMinimizeDefault = config.app?.sidebar?.default?.minimize?.desktop?.default + return ( + + ) +} + +export {SidebarLogo} diff --git a/src/_res/layout/components/sidebar/index.ts b/src/_res/layout/components/sidebar/index.ts new file mode 100644 index 0000000..9130e63 --- /dev/null +++ b/src/_res/layout/components/sidebar/index.ts @@ -0,0 +1 @@ +export * from './Sidebar' diff --git a/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenu.tsx b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenu.tsx new file mode 100644 index 0000000..187d09e --- /dev/null +++ b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenu.tsx @@ -0,0 +1,30 @@ +import {SidebarMenuMain} from './SidebarMenuMain' + +const SidebarMenu = () => { + return ( +
+
+
+ +
+
+
+ ) +} + +export {SidebarMenu} diff --git a/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuItem.tsx b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuItem.tsx new file mode 100644 index 0000000..149a8c1 --- /dev/null +++ b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuItem.tsx @@ -0,0 +1,53 @@ +import {FC} from 'react' +import clsx from 'clsx' +import {Link} from 'react-router-dom' +import {useLocation} from 'react-router' +import {checkIsActive, KTSVG, WithChildren} from '../../../../helpers' +import {useLayout} from '../../../core' + +type Props = { + to: string + title: string + icon?: string + fontIcon?: string + hasBullet?: boolean +} + +const SidebarMenuItem: FC = ({ + children, + to, + title, + icon, + fontIcon, + hasBullet = false, +}) => { + const {pathname} = useLocation() + const isActive = checkIsActive(pathname, to) + const {config} = useLayout() + const {app} = config + + return ( +
+ + {hasBullet && ( + + + + )} + {icon && app?.sidebar?.default?.menu?.iconType === 'svg' && ( + + {' '} + + + )} + {fontIcon && app?.sidebar?.default?.menu?.iconType === 'font' && ( + + )} + {title} + + {children} +
+ ) +} + +export {SidebarMenuItem} diff --git a/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuItemWithSub.tsx b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuItemWithSub.tsx new file mode 100644 index 0000000..a40e558 --- /dev/null +++ b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuItemWithSub.tsx @@ -0,0 +1,57 @@ +import React from 'react' +import clsx from 'clsx' +import {useLocation} from 'react-router' +import {checkIsActive, KTSVG, WithChildren} from '../../../../helpers' +import {useLayout} from '../../../core' + +type Props = { + to: string + title: string + icon?: string + fontIcon?: string + hasBullet?: boolean +} + +const SidebarMenuItemWithSub: React.FC = ({ + children, + to, + title, + icon, + fontIcon, + hasBullet, +}) => { + const {pathname} = useLocation() + const isActive = checkIsActive(pathname, to) + const {config} = useLayout() + const {app} = config + + return ( +
+ + {hasBullet && ( + + + + )} + {icon && app?.sidebar?.default?.menu?.iconType === 'svg' && ( + + + + )} + {fontIcon && app?.sidebar?.default?.menu?.iconType === 'font' && ( + + )} + {title} + + +
+ {children} +
+
+ ) +} + +export {SidebarMenuItemWithSub} diff --git a/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuMain.tsx b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuMain.tsx new file mode 100644 index 0000000..e49dbfa --- /dev/null +++ b/src/_res/layout/components/sidebar/sidebar-menu/SidebarMenuMain.tsx @@ -0,0 +1,133 @@ +/* eslint-disable react/jsx-no-target-blank */ +import React from 'react' +import {useIntl} from 'react-intl' +import {KTSVG} from '../../../../helpers' +import {SidebarMenuItemWithSub} from './SidebarMenuItemWithSub' +import {SidebarMenuItem} from './SidebarMenuItem' + +const SidebarMenuMain = () => { + const intl = useIntl() + + return ( + <> + + +
+
+ Crafted +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ Apps +
+
+ + + + + + + + + ) +} + +export {SidebarMenuMain} diff --git a/src/_res/layout/components/toolbar/Toolbar.tsx b/src/_res/layout/components/toolbar/Toolbar.tsx new file mode 100644 index 0000000..4f70327 --- /dev/null +++ b/src/_res/layout/components/toolbar/Toolbar.tsx @@ -0,0 +1,101 @@ +import {useEffect} from 'react' +import {ILayout, useLayout} from '../../core' +import { + ToolbarAccounting, + ToolbarClassic, + ToolbarExtended, + ToolbarReports, + ToolbarSaas, +} from './toolbars' + +const Toolbar = () => { + const {config} = useLayout() + useEffect(() => { + updateDOM(config) + document.body.setAttribute('data-kt-app-toolbar-enabled', 'true') + }, [config]) + + switch (config.app?.toolbar?.layout) { + case 'classic': + return + case 'accounting': + return + case 'extended': + return + case 'reports': + return + case 'saas': + return + default: + return + } +} + +const updateDOM = (config: ILayout) => { + let appToolbarSwapAttributes: {[attrName: string]: string} = {} + const appToolbarSwapEnabled = config.app?.toolbar?.swap?.enabled + if (appToolbarSwapEnabled) { + appToolbarSwapAttributes = config.app?.toolbar?.swap?.attributes as {[attrName: string]: string} + } + + let appToolbarStickyAttributes: {[attrName: string]: string} = {} + const appToolbarStickyEnabled = config.app?.toolbar?.sticky?.enabled + if (appToolbarStickyEnabled) { + appToolbarStickyAttributes = config.app?.toolbar?.sticky?.attributes as { + [attrName: string]: string + } + + let appToolbarMinimizeAttributes: {[attrName: string]: string} = {} + const appToolbarMinimizeEnabled = config.app?.toolbar?.minimize?.enabled + if (appToolbarMinimizeEnabled) { + appToolbarMinimizeAttributes = config.app?.toolbar?.minimize?.attributes as { + [attrName: string]: string + } + } + + if (config.app?.toolbar?.fixed?.desktop) { + document.body.setAttribute('data-kt-app-toolbar-fixed', 'true') + } + + if (config.app?.toolbar?.fixed?.mobile) { + document.body.setAttribute('data-kt-app-toolbar-fixed-mobile', 'true') + } + + setTimeout(() => { + const toolbarElement = document.getElementById('kt_app_toolbar') + // toolbar + if (toolbarElement) { + const toolbarAttributes = toolbarElement + .getAttributeNames() + .filter((t) => t.indexOf('data-') > -1) + toolbarAttributes.forEach((attr) => toolbarElement.removeAttribute(attr)) + + if (appToolbarSwapEnabled) { + for (const key in appToolbarSwapAttributes) { + if (appToolbarSwapAttributes.hasOwnProperty(key)) { + toolbarElement.setAttribute(key, appToolbarSwapAttributes[key]) + } + } + } + + if (appToolbarStickyEnabled) { + for (const key in appToolbarStickyAttributes) { + if (appToolbarStickyAttributes.hasOwnProperty(key)) { + toolbarElement.setAttribute(key, appToolbarStickyAttributes[key]) + } + } + } + + if (appToolbarMinimizeEnabled) { + for (const key in appToolbarMinimizeAttributes) { + if (appToolbarMinimizeAttributes.hasOwnProperty(key)) { + toolbarElement.setAttribute(key, appToolbarMinimizeAttributes[key]) + } + } + } + } + }, 0) + } +} + +export {Toolbar} diff --git a/src/_res/layout/components/toolbar/ToolbarWrapper.tsx b/src/_res/layout/components/toolbar/ToolbarWrapper.tsx new file mode 100644 index 0000000..e95d0fe --- /dev/null +++ b/src/_res/layout/components/toolbar/ToolbarWrapper.tsx @@ -0,0 +1,51 @@ +import clsx from 'clsx' +import {ToolbarType, useLayout} from '../../core' +import {Toolbar} from './Toolbar' +import {PageTitleWrapper} from './page-title' + +const ToolbarWrapper = () => { + const {config, classes} = useLayout() + if (!config.app?.toolbar?.display) { + return null + } + + const isPageTitleVisible = showPageTitle( + config.app?.toolbar?.layout, + config.app?.pageTitle?.display + ) + + return ( +
+
+ {isPageTitleVisible && } + +
+
+ ) +} + +const showPageTitle = (appToolbarLayout?: ToolbarType, appPageTitleDisplay?: boolean): boolean => { + const viewsWithPageTitles = ['classic', 'reports', 'saas'] + if (!appToolbarLayout || !appPageTitleDisplay) { + return false + } + + return appPageTitleDisplay && viewsWithPageTitles.some((t) => t === appToolbarLayout) +} + +export {ToolbarWrapper} diff --git a/src/_res/layout/components/toolbar/index.ts b/src/_res/layout/components/toolbar/index.ts new file mode 100644 index 0000000..f89cb26 --- /dev/null +++ b/src/_res/layout/components/toolbar/index.ts @@ -0,0 +1 @@ +export * from './ToolbarWrapper' diff --git a/src/_res/layout/components/toolbar/page-title/PageTitle.tsx b/src/_res/layout/components/toolbar/page-title/PageTitle.tsx new file mode 100644 index 0000000..b0c47c5 --- /dev/null +++ b/src/_res/layout/components/toolbar/page-title/PageTitle.tsx @@ -0,0 +1,86 @@ +import clsx from 'clsx' +import {Link} from 'react-router-dom' +import {useLayout} from '../../../core' +import {usePageData} from '../../../core/PageData' + +const PageTitle = () => { + const {pageTitle, pageDescription, pageBreadcrumbs} = usePageData() + const {config, classes} = useLayout() + const appPageTitleDirection = config.app?.pageTitle?.direction + + return ( +
+ {/* begin::Title */} + {config.app?.pageTitle?.display && pageTitle && ( +

+ {pageTitle} + {pageDescription && config.app?.pageTitle && config.app?.pageTitle?.description && ( + + {config.app?.pageTitle?.direction === 'row' && ( + + )} + {pageDescription}{' '} + + )} +

+ )} + {/* end::Title */} + + {pageBreadcrumbs && + pageBreadcrumbs.length > 0 && + config.app?.pageTitle && + config.app?.pageTitle?.breadCrumb && ( + <> + {config.app?.pageTitle?.direction === 'row' && ( + + )} +
    + {Array.from(pageBreadcrumbs).map((item, index) => ( +
  • + {!item.isSeparator ? ( + + {item.title} + + ) : ( + + )} +
  • + ))} +
  • {pageTitle}
  • +
+ + )} +
+ ) +} + +export {PageTitle} diff --git a/src/_res/layout/components/toolbar/page-title/PageTitleWrapper.tsx b/src/_res/layout/components/toolbar/page-title/PageTitleWrapper.tsx new file mode 100644 index 0000000..87360e5 --- /dev/null +++ b/src/_res/layout/components/toolbar/page-title/PageTitleWrapper.tsx @@ -0,0 +1,13 @@ +import {useLayout} from '../../../core' +import {PageTitle} from './PageTitle' + +const PageTitleWrapper = () => { + const {config} = useLayout() + if (!config.app?.pageTitle?.display) { + return null + } + + return +} + +export {PageTitleWrapper} diff --git a/src/_res/layout/components/toolbar/page-title/index.ts b/src/_res/layout/components/toolbar/page-title/index.ts new file mode 100644 index 0000000..9c82991 --- /dev/null +++ b/src/_res/layout/components/toolbar/page-title/index.ts @@ -0,0 +1 @@ +export * from './PageTitleWrapper' diff --git a/src/_res/layout/components/toolbar/toolbars/ToolbarAccounting.tsx b/src/_res/layout/components/toolbar/toolbars/ToolbarAccounting.tsx new file mode 100644 index 0000000..74d293b --- /dev/null +++ b/src/_res/layout/components/toolbar/toolbars/ToolbarAccounting.tsx @@ -0,0 +1,139 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC, useEffect, useState} from 'react' +import {KTSVG} from '../../../../helpers' + +const ToolbarAccounting: FC = () => { + const [progress, setProgress] = useState('1') + const [filter, setFilter] = useState('1') + + useEffect(() => { + document.body.setAttribute('data-kt-app-toolbar-fixed', 'true') + }, []) + + return ( + <> +
+ {/* begin::Input group */} +
+ {/* begin::Label */} + Actions: + {/* end::Label */} + + {/* begin::Actions */} +
+ {/* begin::Button */} +
+ + + +
+ {/* end::Button */} + + {/* begin::Button */} +
+ + + +
+ {/* end::Button */} + + {/* begin::Button */} +
+ + + +
+ {/* end::Button */} +
+ {/* end::Actions */} +
+ {/* end::Input group */} + + {/* begin::Input group */} +
+ {/* begin::Desktop separartor */} +
+ {/* end::Desktop separartor */} + + {/* begin::Label */} + Progress: + {/* end::Label */} + +
+
+ 72% +
+
+
+ {/* end::Input group */} + {/* end::Toolbar start */} +
+ {/* begin::Toolbar end */} +
+ {/* begin::Input group */} +
+ {/* begin::Select */} + + {/* end::Select */} +
+ {/* end::Input group- */} + + {/* begin::Input group- */} +
+ {/* begin::Select */} + + {/* end::Content */} +
+ {/* end::Input group- */} +
+ + ) +} + +export {ToolbarAccounting} diff --git a/src/_res/layout/components/toolbar/toolbars/ToolbarClassic.tsx b/src/_res/layout/components/toolbar/toolbars/ToolbarClassic.tsx new file mode 100644 index 0000000..01a40d2 --- /dev/null +++ b/src/_res/layout/components/toolbar/toolbars/ToolbarClassic.tsx @@ -0,0 +1,71 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import clsx from 'clsx' +import {useState} from 'react' +import {KTSVG} from '../../../../helpers' +import {CreateAppModal, Dropdown1} from '../../../../partials' +import {useLayout} from '../../../core' + +const ToolbarClassic = () => { + const {config} = useLayout() + const [showCreateAppModal, setShowCreateAppModal] = useState(false) + const daterangepickerButtonClass = config.app?.toolbar?.fixed?.desktop + ? 'btn-light' + : 'bg-body btn-color-gray-700 btn-active-color-primary' + + return ( +
+ {config.app?.toolbar?.filterButton && ( + + )} + + {config.app?.toolbar?.daterangepickerButton && ( +
+
Loading date range...
+ +
+ )} + + {config.app?.toolbar?.secondaryButton && ( + + Filter + + )} + + {config.app?.toolbar?.primaryButton && ( + setShowCreateAppModal(true)} + className='btn btn-sm fw-bold btn-primary' + data-bs-toggle='modal' + data-bs-target='#kt_modal_create_app' + > + Create + + )} + setShowCreateAppModal(false)} /> +
+ ) +} + +export {ToolbarClassic} diff --git a/src/_res/layout/components/toolbar/toolbars/ToolbarExtended.tsx b/src/_res/layout/components/toolbar/toolbars/ToolbarExtended.tsx new file mode 100644 index 0000000..358712f --- /dev/null +++ b/src/_res/layout/components/toolbar/toolbars/ToolbarExtended.tsx @@ -0,0 +1,163 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC, useEffect, useState} from 'react' +import {KTSVG, toAbsoluteUrl} from '../../../../helpers' + +const ToolbarExtended: FC = () => { + const [progress, setProgress] = useState('1') + const [search, setSearch] = useState('') + + useEffect(() => { + document.body.setAttribute('data-kt-app-toolbar-fixed', 'true') + }, []) + + return ( + <> +
+ {/* begin::Label */} + Team: + {/* end::Label */} + + {/* begin::Users */} +
+ {/* begin::User */} +
+
A
+
+ {/* end::User */} + + {/* begin::User */} +
+ +
+ {/* end::User */} + + {/* begin::User */} +
+ +
+ {/* end::User */} + + {/* begin::User */} +
+
S
+
+ {/* end::User */} + + {/* begin::User */} +
+ +
+ {/* end::User */} + + {/* begin::User */} +
+
P
+
+ {/* end::User */} + + {/* begin::User */} +
+ +
+ {/* end::User */} +
+ {/* end::Users */} + + {/* begin::Button */} +
+ + + +
+
+ {/* end::Button */} + {/* end::Toolbar start */} + + {/* begin::Toolbar end */} +
+ {/* begin::Search */} +
+ + setSearch(e.target.value)} + placeholder='Search Team' + /> +
+ {/* end::Search */} + + {/* begin::Separartor */} +
+ {/* end::Separartor */} + + {/* begin::Label */} + + Sort By: + + {/* end::Label */} + + {/* begin::Select */} + + {/* end::Select */} + + {/* begin::Actions */} +
+ + + +
+ {/* end::Actions */} +
+ + ) +} + +export {ToolbarExtended} diff --git a/src/_res/layout/components/toolbar/toolbars/ToolbarReports.tsx b/src/_res/layout/components/toolbar/toolbars/ToolbarReports.tsx new file mode 100644 index 0000000..08b0b78 --- /dev/null +++ b/src/_res/layout/components/toolbar/toolbars/ToolbarReports.tsx @@ -0,0 +1,121 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {useEffect, useState} from 'react' +import {KTSVG} from '../../../../helpers' + +const ToolbarReports = () => { + const [progress, setProgress] = useState('1') + + useEffect(() => { + document.body.setAttribute('data-kt-app-toolbar-fixed', 'true') + }, []) + + return ( +
+ {/* begin::Wrapper */} +
+ {/* begin::Label */} + + Filter By: + + {/* end::Label */} + +
+ +
+
+ {/* end::Wrapper */} + + {/* begin::Separartor */} +
+ {/* end::Separartor */} + + {/* begin::Wrapper */} +
+ {/* begin::Label */} + + Sort By: + + {/* end::Label */} + + {/* begin::Select */} + + {/* end::Select */} + + {/* begin::Actions */} +
+ + + +
+ {/* end::Actions */} +
+ {/* end::Wrapper */} +
+ ) +} + +export {ToolbarReports} diff --git a/src/_res/layout/components/toolbar/toolbars/ToolbarSaas.tsx b/src/_res/layout/components/toolbar/toolbars/ToolbarSaas.tsx new file mode 100644 index 0000000..b349fcf --- /dev/null +++ b/src/_res/layout/components/toolbar/toolbars/ToolbarSaas.tsx @@ -0,0 +1,126 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC, useEffect, useState} from 'react' +import {KTSVG} from '../../../../helpers' + +const ToolbarSaas: FC = () => { + const [progress, setProgress] = useState('1') + useEffect(() => { + document.body.setAttribute('data-kt-app-toolbar-fixed', 'true') + }, []) + + return ( +
+ {/* begin::Action wrapper */} +
+ {/* begin::Label */} + + Sort By: + + {/* end::Label */} + + {/* begin::Select */} + + {/* end::Select */} +
+ {/* end::Action wrapper */} + + {/* begin::Action wrapper */} +
+ {/* begin::Separartor */} +
+ {/* end::Separartor */} + + {/* begin::Label */} + Impact Level: + {/* end::Label */} + + {/* begin::NoUiSlider */} +
+
+ + +
+ {/* end::NoUiSlider */} + + {/* begin::Separartor */} +
+ {/* end::Separartor */} +
+ {/* end::Action wrapper */} + + {/* begin::Action wrapper */} +
+ {/* begin::Label */} + Quick Tools: + {/* end::Label */} + + {/* begin::Actions */} +
+ {/* begin::Action */} + + + + {/* end::Action */} + + {/* begin::Action */} + + + + {/* end::Action */} + + {/* begin::Action */} + + + + {/* end::Action */} +
+ {/* end::Actions */} +
+ {/* end::Action wrapper */} +
+ ) +} + +export {ToolbarSaas} diff --git a/src/_res/layout/components/toolbar/toolbars/index.ts b/src/_res/layout/components/toolbar/toolbars/index.ts new file mode 100644 index 0000000..c3a7436 --- /dev/null +++ b/src/_res/layout/components/toolbar/toolbars/index.ts @@ -0,0 +1,5 @@ +export * from './ToolbarAccounting' +export * from './ToolbarClassic' +export * from './ToolbarExtended' +export * from './ToolbarReports' +export * from './ToolbarSaas' diff --git a/src/_res/layout/core/MetronicSplashScreen.tsx b/src/_res/layout/core/MetronicSplashScreen.tsx new file mode 100644 index 0000000..a66b9f8 --- /dev/null +++ b/src/_res/layout/core/MetronicSplashScreen.tsx @@ -0,0 +1,79 @@ +import React, { + FC, + createContext, + useContext, + useState, + useEffect, + SetStateAction, + Dispatch, +} from 'react' +import {WithChildren} from '../../helpers' + +const MetronicSplashScreenContext = createContext> | undefined>( + undefined +) + +const MetronicSplashScreenProvider: FC = ({children}) => { + const [count, setCount] = useState(0) + let visible = count > 0 + + useEffect(() => { + const splashScreen = document.getElementById('splash-screen') + + // Show SplashScreen + if (splashScreen && visible) { + splashScreen.classList.remove('hidden') + + return () => { + splashScreen.classList.add('hidden') + } + } + + // Hide SplashScreen + let timeout: number + if (splashScreen && !visible) { + timeout = window.setTimeout(() => { + splashScreen.classList.add('hidden') + }, 3000) + } + + return () => { + clearTimeout(timeout) + } + }, [visible]) + + return ( + + {children} + + ) +} + +const LayoutSplashScreen: FC<{visible?: boolean}> = ({visible = true}) => { + // Everything are ready - remove splashscreen + const setCount = useContext(MetronicSplashScreenContext) + + useEffect(() => { + if (!visible) { + return + } + + if (setCount) { + setCount((prev) => { + return prev + 1 + }) + } + + return () => { + if (setCount) { + setCount((prev) => { + return prev - 1 + }) + } + } + }, [setCount, visible]) + + return null +} + +export {MetronicSplashScreenProvider, LayoutSplashScreen} diff --git a/src/_res/layout/core/PageData.tsx b/src/_res/layout/core/PageData.tsx new file mode 100644 index 0000000..99195ee --- /dev/null +++ b/src/_res/layout/core/PageData.tsx @@ -0,0 +1,96 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import React, {FC, createContext, useContext, useEffect, useState} from 'react' +import {WithChildren} from '../../helpers' + +export interface PageLink { + title: string + path: string + isActive: boolean + isSeparator?: boolean +} + +export interface PageDataContextModel { + pageTitle?: string + setPageTitle: (_title: string) => void + pageDescription?: string + setPageDescription: (_description: string) => void + pageBreadcrumbs?: Array + setPageBreadcrumbs: (_breadcrumbs: Array) => void +} + +const PageDataContext = createContext({ + setPageTitle: (_title: string) => {}, + setPageBreadcrumbs: (_breadcrumbs: Array) => {}, + setPageDescription: (_description: string) => {}, +}) + +const PageDataProvider: FC = ({children}) => { + const [pageTitle, setPageTitle] = useState('') + const [pageDescription, setPageDescription] = useState('') + const [pageBreadcrumbs, setPageBreadcrumbs] = useState>([]) + const value: PageDataContextModel = { + pageTitle, + setPageTitle, + pageDescription, + setPageDescription, + pageBreadcrumbs, + setPageBreadcrumbs, + } + return {children} +} + +function usePageData() { + return useContext(PageDataContext) +} + +type Props = { + description?: string + breadcrumbs?: Array +} + +const PageTitle: FC = ({children, description, breadcrumbs}) => { + const {setPageTitle, setPageDescription, setPageBreadcrumbs} = usePageData() + useEffect(() => { + if (children) { + setPageTitle(children.toString()) + } + return () => { + setPageTitle('') + } + }, [children]) + + useEffect(() => { + if (description) { + setPageDescription(description) + } + return () => { + setPageDescription('') + } + }, [description]) + + useEffect(() => { + if (breadcrumbs) { + setPageBreadcrumbs(breadcrumbs) + } + return () => { + setPageBreadcrumbs([]) + } + }, [breadcrumbs]) + + return <> +} + +const PageDescription: FC = ({children}) => { + const {setPageDescription} = usePageData() + useEffect(() => { + if (children) { + setPageDescription(children.toString()) + } + return () => { + setPageDescription('') + } + }, [children]) + return <> +} + +export {PageDescription, PageTitle, PageDataProvider, usePageData} diff --git a/src/_res/layout/core/_LayoutConfig.ts b/src/_res/layout/core/_LayoutConfig.ts new file mode 100644 index 0000000..e63dcfa --- /dev/null +++ b/src/_res/layout/core/_LayoutConfig.ts @@ -0,0 +1,138 @@ +import {ILayout} from './_Models' + +export const DefaultConfig: ILayout = { + layoutType: 'dark-sidebar', + main: { + componentName: 'main', + type: 'default', + pageBgWhite: false, + }, + app: { + general: { + componentName: 'general', + evolution: true, + layoutType: 'default', + mode: 'light', + rtl: false, + primaryColor: '#50CD89', + pageBgWhite: false, + pageWidth: 'default', + }, + header: { + componentName: 'header', + display: true, + default: { + container: 'fluid', + containerClass: 'd-flex align-items-stretch justify-content-between', + fixed: { + desktop: true, + mobile: false, + }, + content: 'menu', + menu: { + display: true, + iconType: 'svg', + }, + }, + }, + sidebar: { + componentName: 'sidebar', + display: true, + default: { + class: 'flex-column', + push: { + header: true, + toolbar: true, + footer: true, + }, + drawer: { + enabled: true, + attributes: { + 'data-kt-drawer': 'true', + 'data-kt-drawer-name': 'app-sidebar', + 'data-kt-drawer-activate': '{default: true, lg: false}', + 'data-kt-drawer-overlay': 'true', + 'data-kt-drawer-width': '225px', + 'data-kt-drawer-direction': 'start', + 'data-kt-drawer-toggle': '#kt_app_sidebar_mobile_toggle', + }, + }, + fixed: { + desktop: true, + }, + minimize: { + desktop: { + enabled: true, + default: false, + hoverable: true, + }, + }, + menu: { + iconType: 'svg', + }, + }, + }, + toolbar: { + componentName: 'toolbar', + display: true, + layout: 'classic', + class: 'py-3 py-lg-6', + container: 'fluid', + containerClass: 'd-flex flex-stack', + fixed: { + desktop: false, + mobile: false, + }, + // custom settings, + filterButton: true, + daterangepickerButton: false, + primaryButton: true, + primaryButtonLabel: 'Create', + primaryButtonModal: 'create-app', + }, + pageTitle: { + componentName: 'page-title', + display: true, + breadCrumb: true, + description: false, + direction: 'column', + }, + content: { + componentName: 'content', + container: 'fluid', + }, + footer: { + componentName: 'footer', + display: true, + container: 'fluid', + containerClass: 'd-flex flex-column flex-md-row flex-center flex-md-stack py-3', + fixed: { + desktop: false, + mobile: false, + }, + }, + pageLoader: { + componentName: 'page-loader', + type: 'none', + logoImage: 'default.svg', + logoClass: 'mh-75px', + }, + }, + illustrations: { + componentName: 'illustrations', + set: 'sketchy-1', + }, + scrolltop: { + componentName: 'scrolltop', + display: true, + }, + engage: { + componentName: 'engage', + demos: { + enabled: true, + }, + purchase: { + enabled: false, + }, + }, +} diff --git a/src/_res/layout/core/_LayoutProvider.tsx b/src/_res/layout/core/_LayoutProvider.tsx new file mode 100644 index 0000000..82908e9 --- /dev/null +++ b/src/_res/layout/core/_LayoutProvider.tsx @@ -0,0 +1,111 @@ +import {FC, createContext, useContext, useState, useEffect} from 'react' +import {DefaultConfig} from './_LayoutConfig' +import { + setLayoutIntoLocalStorage, + getEmptyCssClasses, + getEmptyCSSVariables, + getEmptyHTMLAttributes, + LayoutSetup, +} from './_LayoutSetup' +import { + ILayout, + ILayoutCSSVariables, + ILayoutCSSClasses, + ILayoutHTMLAttributes, + LayoutType, + ToolbarType, +} from './_Models' +import {WithChildren} from '../../helpers' + +export interface LayoutContextModel { + config: ILayout + classes: ILayoutCSSClasses + attributes: ILayoutHTMLAttributes + cssVariables: ILayoutCSSVariables + setLayout: (config: LayoutSetup) => void + setLayoutType: (layoutType: LayoutType) => void + setToolbarType: (toolbarType: ToolbarType) => void +} + +const LayoutContext = createContext({ + config: DefaultConfig, + classes: getEmptyCssClasses(), + attributes: getEmptyHTMLAttributes(), + cssVariables: getEmptyCSSVariables(), + setLayout: (config: LayoutSetup) => {}, + setLayoutType: (layoutType: LayoutType) => {}, + setToolbarType: (toolbarType: ToolbarType) => {}, +}) + +const enableSplashScreen = () => { + const splashScreen = document.getElementById('splash-screen') + if (splashScreen) { + splashScreen.style.setProperty('display', 'flex') + } +} + +const disableSplashScreen = () => { + const splashScreen = document.getElementById('splash-screen') + if (splashScreen) { + splashScreen.style.setProperty('display', 'none') + } +} + +const LayoutProvider: FC = ({children}) => { + const [config, setConfig] = useState(LayoutSetup.config) + const [classes, setClasses] = useState(LayoutSetup.classes) + const [attributes, setAttributes] = useState(LayoutSetup.attributes) + const [cssVariables, setCSSVariables] = useState(LayoutSetup.cssVariables) + + const setLayout = (_themeConfig: Partial) => { + enableSplashScreen() + const bodyClasses = Array.from(document.body.classList) + bodyClasses.forEach((cl) => document.body.classList.remove(cl)) + const updatedConfig = LayoutSetup.updatePartialConfig(_themeConfig) + setConfig(Object.assign({}, updatedConfig)) + setClasses(LayoutSetup.classes) + setAttributes(LayoutSetup.attributes) + setCSSVariables(LayoutSetup.cssVariables) + setTimeout(() => { + disableSplashScreen() + }, 500) + } + + const setToolbarType = (toolbarType: ToolbarType) => { + const updatedConfig = {...config} + if (updatedConfig.app?.toolbar) { + updatedConfig.app.toolbar.layout = toolbarType + } + + setLayoutIntoLocalStorage(updatedConfig) + window.location.reload() + } + + const setLayoutType = (layoutType: LayoutType) => { + const updatedLayout = {...config, layoutType} + setLayoutIntoLocalStorage(updatedLayout) + window.location.reload() + } + + const value: LayoutContextModel = { + config, + classes, + attributes, + cssVariables, + setLayout, + setLayoutType, + setToolbarType, + } + + useEffect(() => { + disableSplashScreen() + }, []) + + return {children} +} + +export {LayoutContext, LayoutProvider} + +export function useLayout() { + return useContext(LayoutContext) +} diff --git a/src/_res/layout/core/_LayoutSetup.ts b/src/_res/layout/core/_LayoutSetup.ts new file mode 100644 index 0000000..1a865fc --- /dev/null +++ b/src/_res/layout/core/_LayoutSetup.ts @@ -0,0 +1,222 @@ +import {ILayout, ILayoutCSSClasses, ILayoutHTMLAttributes, ILayoutCSSVariables} from './_Models' +import {DefaultConfig} from './_LayoutConfig' + +const LAYOUT_CONFIG_KEY = process.env.REACT_APP_BASE_LAYOUT_CONFIG_KEY || 'LayoutConfig' + +const getLayoutFromLocalStorage = (): ILayout => { + const ls = localStorage.getItem(LAYOUT_CONFIG_KEY) + if (ls) { + try { + return JSON.parse(ls) as ILayout + } catch (er) { + console.error(er) + } + } + return DefaultConfig +} + +const setLayoutIntoLocalStorage = (config: ILayout) => { + try { + localStorage.setItem(LAYOUT_CONFIG_KEY, JSON.stringify(config)) + } catch (er) { + console.error(er) + } +} + +const getEmptyCssClasses = (): ILayoutCSSClasses => { + return { + header: [], + headerContainer: [], + headerMobile: [], + headerMenu: [], + aside: [], + asideMenu: [], + asideToggle: [], + toolbar: [], + toolbarContainer: [], + content: [], + contentContainer: [], + footerContainer: [], + sidebar: [], + pageTitle: [], + pageContainer: [], + } +} + +const getEmptyHTMLAttributes = () => { + return { + asideMenu: new Map(), + headerMobile: new Map(), + headerMenu: new Map(), + headerContainer: new Map(), + pageTitle: new Map(), + } +} + +const getEmptyCSSVariables = () => { + return { + body: new Map(), + } +} + +class LayoutSetup { + public static isLoaded: boolean = false + public static config: ILayout = getLayoutFromLocalStorage() + public static classes: ILayoutCSSClasses = getEmptyCssClasses() + public static attributes: ILayoutHTMLAttributes = getEmptyHTMLAttributes() + public static cssVariables: ILayoutCSSVariables = getEmptyCSSVariables() + + private static initCSSClasses(): void { + LayoutSetup.classes = getEmptyCssClasses() + } + + private static initHTMLAttributes(): void { + LayoutSetup.attributes = Object.assign({}, getEmptyHTMLAttributes()) + } + + private static initCSSVariables(): void { + LayoutSetup.cssVariables = getEmptyCSSVariables() + } + + private static initConfig(config: ILayout): ILayout { + let updatedConfig = LayoutSetup.initLayoutSettings(config) + updatedConfig = LayoutSetup.initToolbarSetting(updatedConfig) + return LayoutSetup.initWidthSettings(updatedConfig) + } + + private static initLayoutSettings(config: ILayout): ILayout { + const updatedConfig = {...config} + // clear body classes + const bodyClasses = document.body.classList.value.split(' ') + bodyClasses.forEach((cssClass) => document.body.classList.remove(cssClass)) + // clear body attributes + const bodyAttributes = document.body.getAttributeNames().filter((t) => t.indexOf('data-') > -1) + bodyAttributes.forEach((attr) => document.body.removeAttribute(attr)) + document.body.setAttribute('style', '') + document.body.setAttribute('id', 'kt_app_body') + document.body.setAttribute('data-kt-app-layout', updatedConfig.layoutType) + document.body.setAttribute('data-kt-name', 'metronic') + document.body.classList.add('app-default') + + const pageWidth = updatedConfig.app?.general?.pageWidth + if (updatedConfig.layoutType === 'light-header' || updatedConfig.layoutType === 'dark-header') { + if (pageWidth === 'default') { + const header = updatedConfig.app?.header + if (header && header.default && header.default.container) { + header.default.container = 'fixed' + } + + const toolbar = updatedConfig.app?.toolbar + if (toolbar) { + toolbar.container = 'fixed' + } + + const content = updatedConfig.app?.content + if (content) { + content.container = 'fixed' + } + + const footer = updatedConfig.app?.footer + if (footer) { + footer.container = 'fixed' + } + + const updatedApp = { + ...updatedConfig.app, + ...header, + ...toolbar, + ...content, + ...footer, + } + return {...updatedConfig, app: updatedApp} + } + } + return updatedConfig + } + + private static initToolbarSetting(config: ILayout): ILayout { + const updatedConfig = {...config} + const appHeaderDefaultContent = updatedConfig.app?.header?.default?.content + if (appHeaderDefaultContent === 'page-title') { + const toolbar = updatedConfig.app?.toolbar + if (toolbar) { + toolbar.display = false + const updatedApp = {...updatedConfig.app, ...toolbar} + return {...updatedConfig, app: updatedApp} + } + return updatedConfig + } + + const pageTitle = updatedConfig.app?.pageTitle + if (pageTitle) { + pageTitle.description = false + pageTitle.breadCrumb = true + const updatedApp = {...updatedConfig.app, ...pageTitle} + return {...updatedConfig, app: updatedApp} + } + + return updatedConfig + } + + private static initWidthSettings(config: ILayout): ILayout { + const updatedConfig = {...config} + const pageWidth = updatedConfig.app?.general?.pageWidth + if (!pageWidth || pageWidth === 'default') { + return config + } + + const header = updatedConfig.app?.header + if (header && header.default) { + header.default.container = pageWidth + } + const toolbar = updatedConfig.app?.toolbar + if (toolbar) { + toolbar.container = pageWidth + } + const content = updatedConfig.app?.content + if (content) { + content.container = pageWidth + } + const footer = updatedConfig.app?.footer + if (footer) { + footer.container = pageWidth + } + const updatedApp = { + ...updatedConfig.app, + ...header, + ...toolbar, + ...content, + ...footer, + } + return {...updatedConfig, app: updatedApp} + } + + public static updatePartialConfig(fieldsToUpdate: Partial): ILayout { + const config = LayoutSetup.config + const updatedConfig = {...config, ...fieldsToUpdate} + LayoutSetup.initCSSClasses() + LayoutSetup.initCSSVariables() + LayoutSetup.initHTMLAttributes() + LayoutSetup.isLoaded = false + LayoutSetup.config = LayoutSetup.initConfig(Object.assign({}, updatedConfig)) + LayoutSetup.isLoaded = true // remove loading there + return updatedConfig + } + + public static setConfig(config: ILayout): void { + setLayoutIntoLocalStorage(config) + } + + public static bootstrap = (() => { + LayoutSetup.updatePartialConfig(LayoutSetup.config) + })() +} + +export { + LayoutSetup, + getLayoutFromLocalStorage, + setLayoutIntoLocalStorage, + getEmptyCssClasses, + getEmptyCSSVariables, + getEmptyHTMLAttributes, +} diff --git a/src/_res/layout/core/_Models.ts b/src/_res/layout/core/_Models.ts new file mode 100644 index 0000000..89df93c --- /dev/null +++ b/src/_res/layout/core/_Models.ts @@ -0,0 +1,257 @@ +export type LayoutType = 'dark-sidebar' | 'light-sidebar' | 'dark-header' | 'light-header' + +export type CSSClassesType = { + [key: string]: string[] +} + +export type HTMLAttributesType = { + [key: string]: { + [attrName: string]: string | boolean + } +} + +export interface ILayoutComponent { + componentName?: string +} + +export interface IPageLoader extends ILayoutComponent { + componentName?: 'page-loader' + type?: 'none' | 'default' | 'spinner-message' | 'spinner-logo' + logoImage?: string + logoClass?: string +} + +export interface IScrollTop extends ILayoutComponent { + display?: boolean +} + +export interface IHeader extends ILayoutComponent { + componentName?: 'header' + display?: boolean + default?: { + container?: 'fluid' | 'fixed' + containerClass?: string + fixed?: { + desktop?: boolean + mobile?: boolean + } + content?: string + menu?: { + display?: boolean + iconType?: 'svg' | 'font' + } + stacked?: boolean + sticky?: { + enabled?: boolean + attributes?: {[attrName: string]: string} + } + minimize?: { + enabled?: boolean + attributes?: {[attrName: string]: string} + } + } +} + +export interface ISidebar extends ILayoutComponent { + componentName?: 'sidebar' + display?: boolean + default?: { + class?: string + push?: { + header?: boolean + toolbar?: boolean + footer?: boolean + } + drawer?: { + enabled?: boolean + attributes?: {[attrName: string]: string} + } + sticky?: { + enabled?: boolean + attributes?: {[attrName: string]: string} + } + fixed?: { + desktop?: boolean + } + minimize?: { + desktop?: { + enabled?: boolean + default?: boolean + hoverable?: boolean + } + mobile?: { + enabled?: boolean + default?: boolean + hoverable?: boolean + } + } + menu?: { + iconType?: 'svg' | 'font' + } + collapse?: { + desktop?: { + enabled?: boolean + default?: boolean + } + mobile?: { + enabled?: boolean + default?: boolean + } + } + stacked?: boolean + } + toggle?: boolean +} + +export type ToolbarType = 'classic' | 'accounting' | 'extended' | 'reports' | 'saas' + +export interface IToolbar extends ILayoutComponent { + componentName?: 'toolbar' + display?: boolean + layout?: ToolbarType + class?: string + container?: 'fixed' | 'fluid' + containerClass?: string + fixed?: { + desktop?: boolean + mobile?: boolean + } + swap?: { + enabled?: boolean + attributes?: {[attrName: string]: string} + } + sticky?: { + enabled?: boolean + attributes?: {[attrName: string]: string} + } + minimize?: { + enabled?: boolean + attributes?: {[attrName: string]: string} + } + + // Custom settings + filterButton?: boolean + daterangepickerButton?: boolean + primaryButton?: boolean + primaryButtonLabel?: string + primaryButtonModal?: string + secondaryButton?: boolean +} + +export interface IMain extends ILayoutComponent { + type?: 'blank' | 'default' | 'none' // Set layout type: default|blank|none + pageBgWhite?: boolean // Set true if page background color is white +} + +export interface IIllustrations extends ILayoutComponent { + componentName?: 'illustrations' + set?: 'sketchy-1' +} + +export interface IGeneral extends ILayoutComponent { + componentName?: 'general' + evolution?: boolean + layoutType?: 'default' | 'blank' + mode?: 'light' | 'dark' | 'system' + rtl?: boolean + primaryColor?: string // Used in email templates + pageBgWhite?: boolean // Set true if page background color is white + pageWidth?: 'default' | 'fluid' | 'fixed' +} + +export interface IMegaMenu extends ILayoutComponent { + display: boolean +} + +export interface ISidebarPanel extends ILayoutComponent { + componentName?: 'sidebar-panel' + display: boolean +} + +export interface IContent extends ILayoutComponent { + componentName?: 'content' + container?: 'fixed' | 'fluid' + class?: string +} + +export interface IFooter extends ILayoutComponent { + componentName?: 'footer' + display?: boolean + container?: 'fluid' | 'fixed' + containerClass?: string + placement?: string + fixed?: { + desktop?: boolean + mobile?: boolean + } +} + +export interface IPageTitle extends ILayoutComponent { + componentName?: 'page-title' + display?: boolean + breadCrumb?: boolean + description?: boolean + direction?: 'row' | 'column' + class?: string +} + +export interface IEngage extends ILayoutComponent { + componentName?: 'engage' + demos?: { + enabled?: boolean + } + purchase?: { + enabled?: boolean + } +} + +export interface IApp { + general?: IGeneral + header?: IHeader + sidebar?: ISidebar + sidebarPanel?: ISidebarPanel + toolbar?: IToolbar + pageTitle?: IPageTitle + content?: IContent + footer?: IFooter + pageLoader?: IPageLoader +} + +export interface ILayout { + layoutType: LayoutType + main?: IMain + app?: IApp + illustrations?: IIllustrations + scrolltop?: IScrollTop + engage?: IEngage +} + +export interface ILayoutCSSClasses { + header: Array + headerContainer: Array + headerMobile: Array + headerMenu: Array + aside: Array + asideMenu: Array + asideToggle: Array + sidebar: Array + toolbar: Array + toolbarContainer: Array + content: Array + contentContainer: Array + footerContainer: Array + pageTitle: Array + pageContainer: Array +} + +export interface ILayoutHTMLAttributes { + asideMenu: Map + headerMobile: Map + headerMenu: Map + headerContainer: Map + pageTitle: Map +} + +export interface ILayoutCSSVariables { + body: Map +} diff --git a/src/_res/layout/core/index.ts b/src/_res/layout/core/index.ts new file mode 100644 index 0000000..90d0d9b --- /dev/null +++ b/src/_res/layout/core/index.ts @@ -0,0 +1,6 @@ +export * from './_LayoutConfig' +export * from './_LayoutProvider' +export * from './_Models' +export * from './_LayoutSetup' +export * from './PageData' +export * from './MetronicSplashScreen' diff --git a/src/_res/partials/chat/ChatInner.tsx b/src/_res/partials/chat/ChatInner.tsx new file mode 100644 index 0000000..e53422b --- /dev/null +++ b/src/_res/partials/chat/ChatInner.tsx @@ -0,0 +1,193 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC, useState} from 'react' +import clsx from 'clsx' +import { + toAbsoluteUrl, + defaultMessages, + defaultUserInfos, + MessageModel, + UserInfoModel, + messageFromClient, +} from '../../helpers' + +type Props = { + isDrawer?: boolean +} + +const bufferMessages = defaultMessages + +const ChatInner: FC = ({isDrawer = false}) => { + const [chatUpdateFlag, toggleChatUpdateFlat] = useState(false) + const [message, setMessage] = useState('') + const [messages, setMessages] = useState(bufferMessages) + const [userInfos] = useState(defaultUserInfos) + + const sendMessage = () => { + const newMessage: MessageModel = { + user: 2, + type: 'out', + text: message, + time: 'Just now', + } + + bufferMessages.push(newMessage) + setMessages(bufferMessages) + toggleChatUpdateFlat(!chatUpdateFlag) + setMessage('') + setTimeout(() => { + bufferMessages.push(messageFromClient) + setMessages(() => bufferMessages) + toggleChatUpdateFlat((flag) => !flag) + }, 1000) + } + + const onEnterPress = (e: React.KeyboardEvent) => { + if (e.keyCode === 13 && e.shiftKey === false) { + e.preventDefault() + sendMessage() + } + } + + return ( +
+
+ {messages.map((message, index) => { + const userInfo = userInfos[message.user] + const state = message.type === 'in' ? 'info' : 'primary' + const templateAttr = {} + if (message.template) { + Object.defineProperty(templateAttr, 'data-kt-element', { + value: `template-${message.type}`, + }) + } + const contentClass = `${isDrawer ? '' : 'd-flex'} justify-content-${ + message.type === 'in' ? 'start' : 'end' + } mb-10` + return ( +
+
+
+ {message.type === 'in' ? ( + <> +
+ Pic +
+
+ + {userInfo.name} + + {message.time} +
+ + ) : ( + <> +
+ {message.time} + + You + +
+
+ Pic +
+ + )} +
+ +
+
+
+ ) + })} +
+ +
+ + +
+
+ + +
+ +
+
+
+ ) +} + +export {ChatInner} diff --git a/src/_res/partials/content/activity/Item1.tsx b/src/_res/partials/content/activity/Item1.tsx new file mode 100644 index 0000000..22a4b12 --- /dev/null +++ b/src/_res/partials/content/activity/Item1.tsx @@ -0,0 +1,106 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' + +const Item1: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+
+ There are 2 new tasks for you in “AirPlus Mobile APp” project: +
+ +
+
Added at 4:23 PM by
+ +
+ img +
+
+
+ +
+
+ + Meeting with customer + + +
+ Application Design +
+ +
+
+ img +
+ +
+ img +
+ +
+
A
+
+
+ +
+ In Progress +
+ + + View + +
+ +
+ + Project Delivery Preparation + + +
+ CRM System Development +
+ +
+
+ img +
+ +
+
B
+
+
+ +
+ Completed +
+ + + View + +
+
+
+
+ ) +} + +export {Item1} diff --git a/src/_res/partials/content/activity/Item2.tsx b/src/_res/partials/content/activity/Item2.tsx new file mode 100644 index 0000000..c0cf134 --- /dev/null +++ b/src/_res/partials/content/activity/Item2.tsx @@ -0,0 +1,43 @@ +import {FC} from 'react' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' + +const Item2: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+
+ Invitation for crafting engaging designs that speak human workshop +
+ +
+
Sent at 4:23 PM by
+ +
+ img +
+
+
+
+
+ ) +} + +export {Item2} diff --git a/src/_res/partials/content/activity/Item3.tsx b/src/_res/partials/content/activity/Item3.tsx new file mode 100644 index 0000000..052038c --- /dev/null +++ b/src/_res/partials/content/activity/Item3.tsx @@ -0,0 +1,84 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' + +const Item3: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+ + 3 New Incoming Project Files: + + +
+
Sent at 10:30 PM by
+ +
+ img +
+
+
+ +
+
+
+ + + +
+ + + +
+ + + +
+
+
+
+
+ ) +} + +export {Item3} diff --git a/src/_res/partials/content/activity/Item4.tsx b/src/_res/partials/content/activity/Item4.tsx new file mode 100644 index 0000000..3007711 --- /dev/null +++ b/src/_res/partials/content/activity/Item4.tsx @@ -0,0 +1,52 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' + +const Item4: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+
+ Task{' '} + + #45890 + + merged with{' '} + + #45890 + {' '} + in “Ads Pro Admin Dashboard project: +
+ +
+
Initiated at 4:23 PM by
+ +
+ img +
+
+
+
+
+ ) +} + +export {Item4} diff --git a/src/_res/partials/content/activity/Item5.tsx b/src/_res/partials/content/activity/Item5.tsx new file mode 100644 index 0000000..a2e40a4 --- /dev/null +++ b/src/_res/partials/content/activity/Item5.tsx @@ -0,0 +1,94 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' + +const Item5: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+
3 new application design concepts added:
+ +
+
Created at 4:23 PM by
+ +
+ img +
+
+
+ +
+
+
+
+ img +
+ + +
+ +
+
+ img +
+ + +
+ +
+
+ img +
+ + +
+
+
+
+
+ ) +} + +export {Item5} diff --git a/src/_res/partials/content/activity/Item6.tsx b/src/_res/partials/content/activity/Item6.tsx new file mode 100644 index 0000000..b650ea1 --- /dev/null +++ b/src/_res/partials/content/activity/Item6.tsx @@ -0,0 +1,44 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {KTSVG} from '../../../helpers' + +const Item6: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+
+ New case{' '} + + #67890 + + is assigned to you in Multi-platform Database Design project +
+ +
+
+
Added at 4:23 PM by
+ + + Alice Tan + +
+
+
+
+
+ ) +} + +export {Item6} diff --git a/src/_res/partials/content/activity/Item7.tsx b/src/_res/partials/content/activity/Item7.tsx new file mode 100644 index 0000000..5260ca0 --- /dev/null +++ b/src/_res/partials/content/activity/Item7.tsx @@ -0,0 +1,62 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {KTSVG, toAbsoluteUrl} from '../../../helpers' + +const Item7: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+
You have received a new order:
+ +
+
Placed at 5:05 AM by
+ +
+ img +
+
+
+ +
+
+ +
+
+

Database Backup Process Completed!

+
+ Login into Metronic Admin Dashboard to make sure the data integrity is OK +
+
+ + Proceed + +
+
+
+
+
+ ) +} + +export {Item7} diff --git a/src/_res/partials/content/activity/Item8.tsx b/src/_res/partials/content/activity/Item8.tsx new file mode 100644 index 0000000..a9ba755 --- /dev/null +++ b/src/_res/partials/content/activity/Item8.tsx @@ -0,0 +1,42 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {KTSVG} from '../../../helpers' + +const Item8: FC = () => { + return ( +
+
+ +
+
+ +
+
+ +
+
+
+ New order{' '} + + #67890 + + is placed for Workshow Planning & Budget Estimation +
+ +
+
Placed at 4:23 PM by
+ + + Jimmy Bold + +
+
+
+
+ ) +} + +export {Item8} diff --git a/src/_res/partials/content/cards/Card1.tsx b/src/_res/partials/content/cards/Card1.tsx new file mode 100644 index 0000000..8df8f83 --- /dev/null +++ b/src/_res/partials/content/cards/Card1.tsx @@ -0,0 +1,68 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {toAbsoluteUrl} from '../../../helpers' + +type Props = { + color?: string + avatar?: string + online?: boolean + name: string + job: string + avgEarnings: string + totalEarnings: string +} + +const Card1: FC = ({ + color = '', + avatar = '', + online = false, + name, + job, + avgEarnings, + totalEarnings, +}) => { + return ( +
+
+
+
+ {color ? ( + + {name.charAt(0)} + + ) : ( + Pic + )} + {online && ( +
+ )} +
+
+ + + {name} + + +
{job}
+ +
+
+
{avgEarnings}
+
Avg. Earnings
+
+ +
+
{totalEarnings}
+
Total Sales
+
+
+ + +
+
+ ) +} + +export {Card1} diff --git a/src/_res/partials/content/cards/Card2.tsx b/src/_res/partials/content/cards/Card2.tsx new file mode 100644 index 0000000..3170ae8 --- /dev/null +++ b/src/_res/partials/content/cards/Card2.tsx @@ -0,0 +1,87 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {Link} from 'react-router-dom' +import {IconUserModel} from '../../../../app/modules/profile/ProfileModels' +import {UsersList} from '../../../../app/modules/profile/components/UsersList' +import {toAbsoluteUrl} from '../../../helpers' + +type Props = { + icon: string + badgeColor: string + status: string + statusColor: string + title: string + description: string + date: string + budget: string + progress: number + users?: Array +} + +const Card2: FC = ({ + icon, + badgeColor, + status, + statusColor, + title, + description, + date, + budget, + progress, + users = undefined, +}) => { + return ( + +
+
+
+ card2 +
+
+ +
+ + {status} + +
+
+ +
+
{title}
+ +

{description}

+ +
+
+
{date}
+
Due Date
+
+ +
+
{budget}
+
Budget
+
+
+ +
+
+
+ + +
+ + ) +} + +export {Card2} diff --git a/src/_res/partials/content/cards/Card3.tsx b/src/_res/partials/content/cards/Card3.tsx new file mode 100644 index 0000000..c127a19 --- /dev/null +++ b/src/_res/partials/content/cards/Card3.tsx @@ -0,0 +1,69 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {toAbsoluteUrl, KTSVG} from '../../../helpers' + +type Props = { + color?: string + avatar?: string + online?: boolean + name: string + job: string + avgEarnings: string + totalEarnings: string +} + +const Card3: FC = ({ + color = '', + avatar = '', + online = false, + name, + job, + avgEarnings, + totalEarnings, +}) => { + return ( +
+
+
+
+ {color ? ( + + {name.charAt(0)} + + ) : ( + Pic + )} + {online && ( +
+ )} +
+
+ + + {name} + + +
{job}
+ +
+
+
{avgEarnings}
+
Avg. Earnings
+
+ +
+
{totalEarnings}
+
Total Sales
+
+
+ + + + Connect + +
+
+ ) +} + +export {Card3} diff --git a/src/_res/partials/content/cards/Card4.tsx b/src/_res/partials/content/cards/Card4.tsx new file mode 100644 index 0000000..9dd1ad2 --- /dev/null +++ b/src/_res/partials/content/cards/Card4.tsx @@ -0,0 +1,27 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {toAbsoluteUrl} from '../../../helpers' + +type Props = { + icon: string + title: string + description: string +} + +const Card4: FC = ({icon, title, description}) => { + return ( +
+
+ +
+ +
+
{title}
+
+
{description}
+
+
+ ) +} + +export {Card4} diff --git a/src/_res/partials/content/cards/Card5.tsx b/src/_res/partials/content/cards/Card5.tsx new file mode 100644 index 0000000..c81eb5e --- /dev/null +++ b/src/_res/partials/content/cards/Card5.tsx @@ -0,0 +1,93 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' +import {toAbsoluteUrl, KTSVG} from '../../../helpers' +import {Dropdown1} from '../dropdown/Dropdown1' + +type Props = { + image: string + title: string + description: string + status: 'up' | 'down' + statusValue: number + statusDesc: string + progress: number + progressType: string +} + +const Card5: FC = ({ + image, + title, + description, + status, + statusValue, + statusDesc, + progress, + progressType, +}) => { + return ( +
+
+
+
+ Metronic +
+ + + {title} + +
+ +
+ + + +
+
+ +
+
{description}
+ +
+ {status === 'up' && ( + + )} + + {status === 'down' && ( + + )} + +
+ {status === 'up' ? '+' : '-'} + {statusValue}% +
+ +
{statusDesc}
+
+ +
+ {progress}% + {progressType} +
+
+
+ ) +} + +export {Card5} diff --git a/src/_res/partials/content/code-highlight/CodeBlock.tsx b/src/_res/partials/content/code-highlight/CodeBlock.tsx new file mode 100644 index 0000000..e69e425 --- /dev/null +++ b/src/_res/partials/content/code-highlight/CodeBlock.tsx @@ -0,0 +1,74 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +// @ts-nocheck +import React, {useState, useEffect, useRef} from 'react' +import {CopyToClipboard} from 'react-copy-to-clipboard' +import Highlight, {defaultProps, Language} from 'prism-react-renderer' +import theme from 'prism-react-renderer/themes/shadesOfPurple' +import {OverlayTrigger, Tooltip} from 'react-bootstrap' + +type Props = { + code: string + language: Language +} + +const CodeBlock: React.FC = ({code, language}) => { + const codeRef = useRef(null) + const [copied, setCopied] = useState(false) + useEffect(() => { + if (!copied) { + return + } + + setTimeout(() => { + setCopied(false) + }, 1500) + }, [copied]) + + useEffect(() => { + if (!codeRef.current) { + return + } + + const prismCodeElement = codeRef.current.querySelector('.prism-code ') as HTMLDivElement + if (prismCodeElement) { + prismCodeElement.style.background = 'none' + prismCodeElement.style.fontSize = '13px' + } + }, []) + + return ( +
+
+ Copy Code} + > + setCopied(true)}> + {copied ? 'copied' : 'copy'} + + + +
+ + {({className, style, tokens, getLineProps, getTokenProps}) => { + return ( +
+                  {tokens.map((line, i) => (
+                    
+ {line.map((token, key) => ( + + ))} +
+ ))} +
+ ) + }} +
+
+
+
+ ) +} + +export {CodeBlock} diff --git a/src/_res/partials/content/dropdown/Dropdown1.tsx b/src/_res/partials/content/dropdown/Dropdown1.tsx new file mode 100644 index 0000000..34e16b9 --- /dev/null +++ b/src/_res/partials/content/dropdown/Dropdown1.tsx @@ -0,0 +1,79 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +export function Dropdown1() { + return ( +
+
+
Filter Options
+
+ +
+ +
+
+ + +
+ +
+
+ +
+ + +
+ + + +
+
+ +
+ + +
+ + +
+
+ +
+ + + +
+
+
+ ) +} diff --git a/src/_res/partials/content/dropdown/Dropdown2.tsx b/src/_res/partials/content/dropdown/Dropdown2.tsx new file mode 100644 index 0000000..3871d12 --- /dev/null +++ b/src/_res/partials/content/dropdown/Dropdown2.tsx @@ -0,0 +1,79 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' + +const Dropdown2: FC = () => { + return ( +
+
+
Quick Actions
+
+ +
+ + + + + + + + + +
+ + +
+ ) +} + +export {Dropdown2} diff --git a/src/_res/partials/content/dropdown/Dropdown3.tsx b/src/_res/partials/content/dropdown/Dropdown3.tsx new file mode 100644 index 0000000..b8c4894 --- /dev/null +++ b/src/_res/partials/content/dropdown/Dropdown3.tsx @@ -0,0 +1,96 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import {FC} from 'react' + +const Dropdown3: FC = () => { + return ( +
+
+
Payments
+
+ + + + + + + +
+ + Subscription + + + +
+ + + + + + +
+ +
+
+ +
+
+
+
+ + +
+ ) +} + +export {Dropdown3} diff --git a/src/_res/partials/content/editor/EditorToolbar.ts b/src/_res/partials/content/editor/EditorToolbar.ts new file mode 100644 index 0000000..f656c1a --- /dev/null +++ b/src/_res/partials/content/editor/EditorToolbar.ts @@ -0,0 +1,52 @@ +export const editorToolbarSettings = { + options: ['inline', 'fontSize', 'fontFamily', 'link', 'image'], + inline: { + inDropdown: false, + className: undefined, + component: undefined, + dropdownClassName: undefined, + options: ['bold', 'italic', 'underline', 'strikethrough'], + }, + fontSize: { + options: [8, 9, 10, 11, 12, 14, 16, 18, 24, 30, 36, 48, 60, 72, 96], + className: undefined, + component: undefined, + dropdownClassName: undefined, + }, + fontFamily: { + options: ['Arial', 'Georgia', 'Impact', 'Tahoma', 'Times New Roman', 'Verdana'], + className: undefined, + component: undefined, + dropdownClassName: undefined, + }, + + link: { + inDropdown: false, + className: undefined, + component: undefined, + popupClassName: undefined, + dropdownClassName: undefined, + showOpenOptionOnHover: true, + defaultTargetOption: '_self', + options: ['link', 'unlink'], + link: {className: undefined}, + unlink: {className: undefined}, + linkCallback: undefined, + }, + image: { + className: undefined, + component: undefined, + popupClassName: undefined, + urlEnabled: true, + uploadEnabled: true, + alignmentEnabled: true, + uploadCallback: undefined, + previewImage: false, + inputAccept: 'image/gif,image/jpeg,image/jpg,image/png,image/svg', + alt: {present: false, mandatory: false}, + defaultSize: { + height: 'auto', + width: 'auto', + }, + }, +} diff --git a/src/_res/partials/content/portal/Portal.tsx b/src/_res/partials/content/portal/Portal.tsx new file mode 100644 index 0000000..1117a49 --- /dev/null +++ b/src/_res/partials/content/portal/Portal.tsx @@ -0,0 +1,27 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +import {FC, useState, useEffect} from 'react' +import {createPortal} from 'react-dom' +import {WithChildren} from '../../../helpers' + +/** + * React portal based on https://stackoverflow.com/a/59154364 + * @param children Child elements + * @param className CSS classname + * @param el HTML element to create. default: div + */ +const Portal: FC<{className?: string} & WithChildren> = ({children, className = ''}) => { + const [container] = useState(document.createElement('div')) + + if (className) container.classList.add(className) + + useEffect(() => { + document.body.appendChild(container) + return () => { + document.body.removeChild(container) + } + }, []) + + return createPortal(children, container) +} + +export {Portal} diff --git a/src/_res/partials/index.ts b/src/_res/partials/index.ts new file mode 100644 index 0000000..2c9e535 --- /dev/null +++ b/src/_res/partials/index.ts @@ -0,0 +1,33 @@ +export * from './layout/quick-links/QuicLinks' +export * from './layout/search/Search' +export * from './layout/search/SearchInner' +export * from './layout/SearchModal' +export * from './layout/InboxCompose' +export * from './layout/header-menus/HeaderUserMenu' +export * from './layout/header-menus/HeaderNotificationsMenu' +export * from './layout/demos-drawer/DemosDrawer' +export * from './layout/drawer-messenger/DrawerMessenger' +export * from './layout/activity-drawer/ActivityDrawer' +export * from './layout/create-app/CreateApp' +export * from './layout/theme-mode/ThemeModeProvider' +export * from './layout/theme-mode/ThemeModeSwitcher' + +// dropdpwns +export * from './content/dropdown/Dropdown1' +export * from './content/dropdown/Dropdown2' + +// editors +export * from './content/editor/EditorToolbar' + +export * from './content/code-highlight/CodeBlock' + +export * from './content/portal/Portal' + +// modals +export * from './modals/create-app-stepper/CreateAppModal' +export * from './modals/select-location/SelectLocationModal' +export * from './modals/invite-users/InviteUsers' +export * from './modals/upgrade-plan/UpgradePlan' + +// chat +export * from './chat/ChatInner' diff --git a/src/_res/partials/layout/InboxCompose.tsx b/src/_res/partials/layout/InboxCompose.tsx new file mode 100644 index 0000000..b172b8e --- /dev/null +++ b/src/_res/partials/layout/InboxCompose.tsx @@ -0,0 +1,221 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import React, {useState, useRef} from 'react' +import {Modal} from 'react-bootstrap' +import {KTSVG} from '../../helpers' + +export type Props = { + show: boolean + handleClose: () => void +} + +const InboxCompose: React.FC = ({show, handleClose}) => { + const composeToRef = useRef(null) + const formRef = useRef(null) + const [composeCC, setComposeCC] = useState('') + const [composeBCC, setComposeBCC] = useState('') + const [subject, setSubject] = useState('') + + return ( + + ) +} + +export {InboxCompose} diff --git a/src/_res/partials/layout/RightToolbar.tsx b/src/_res/partials/layout/RightToolbar.tsx new file mode 100644 index 0000000..086438b --- /dev/null +++ b/src/_res/partials/layout/RightToolbar.tsx @@ -0,0 +1,23 @@ +import {FC} from 'react' +import {DemosToggleDrawer} from './demos-drawer/DemosToggleDrawer' +import {ToggleHelpDrawer} from './help-drawer/ToggleHelpDrawer' +import {DemosDrawer} from './demos-drawer/DemosDrawer' +import {HelpDrawer} from './help-drawer/HelpDrawer' +import {PurchaseButton} from './purchase/PurchaseButton' + +const RightToolbar: FC = () => { + return ( + <> +
+ + + +
+ + + + + ) +} + +export {RightToolbar} diff --git a/src/_res/partials/layout/SearchModal.tsx b/src/_res/partials/layout/SearchModal.tsx new file mode 100644 index 0000000..df5aff4 --- /dev/null +++ b/src/_res/partials/layout/SearchModal.tsx @@ -0,0 +1,152 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import React from 'react' +import {Modal} from 'react-bootstrap' +import {KTSVG, toAbsoluteUrl} from '../../helpers' +// import {ListsWidget4, ListsWidget5} from '../widgets' + +type Props = { + show: boolean + handleClose: () => void +} + +const SearchModal: React.FC = ({show, handleClose}) => { + return ( +