Feature #6 : Add Metronic
This commit is contained in:
parent
0543882998
commit
098e51e764
67
resources/metronic/app/layouts/base.js
Normal file
67
resources/metronic/app/layouts/base.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
class KTLayout {
|
||||||
|
static _isSidebarCollapse() {
|
||||||
|
return document.body.classList.contains('sidebar-collapse');
|
||||||
|
}
|
||||||
|
|
||||||
|
static _handleMegaMenu() {
|
||||||
|
const megamenuEl = document.querySelector('#megamenu');
|
||||||
|
if (!megamenuEl) return;
|
||||||
|
|
||||||
|
const menu = KTMenu.getInstance(megamenuEl);
|
||||||
|
menu.disable();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
menu.enable();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _handleSidebar() {
|
||||||
|
const sidebarToggle = KTToggle.getInstance(this.sidebarToggleEl);
|
||||||
|
sidebarToggle?.on('toggle', () => {
|
||||||
|
this.sidebarEl.classList.add('animating');
|
||||||
|
|
||||||
|
this._handleMegaMenu();
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this.sidebarEl, () => {
|
||||||
|
this.sidebarEl.classList.remove('animating');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static _handleSidebarMenu() {
|
||||||
|
const menuEl = document.querySelector('#sidebar_menu');
|
||||||
|
const scrollableEl = document.querySelector('#sidebar_scrollable');
|
||||||
|
const menuActiveItemEl = menuEl.querySelector(".menu-item.active");
|
||||||
|
|
||||||
|
if (!menuActiveItemEl || KTDom.isVisibleInParent(menuActiveItemEl, scrollableEl)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollableEl.scroll({
|
||||||
|
top: KTDom.getRelativeTopPosition(menuActiveItemEl, scrollableEl) - 100,
|
||||||
|
behavior: 'instant'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static init() {
|
||||||
|
this.sidebarEl = document.querySelector('#sidebar');
|
||||||
|
this.sidebarWrapperEl = document.querySelector('#sidebar_wrapper');
|
||||||
|
this.headerEl = document.querySelector('#header');
|
||||||
|
this.sidebarToggleEl = document.querySelector('#sidebar_toggle');
|
||||||
|
|
||||||
|
if (this.sidebarEl && this.sidebarToggleEl) {
|
||||||
|
this._handleSidebar();
|
||||||
|
this._handleSidebarMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static isSidebarCollapse() {
|
||||||
|
return this._isSidebarCollapse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KTDom.ready(() => {
|
||||||
|
KTLayout.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
export default KTLayout;
|
171
resources/metronic/core/components/accordion/accordion.ts
Normal file
171
resources/metronic/core/components/accordion/accordion.ts
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTAccordionInterface, KTAccordionConfigInterface } from './types';
|
||||||
|
|
||||||
|
export class KTAccordion extends KTComponent implements KTAccordionInterface {
|
||||||
|
protected override _name: string = 'accordion';
|
||||||
|
protected override _defaultConfig: KTAccordionConfigInterface = {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
activeClass: 'active',
|
||||||
|
expandAll: false
|
||||||
|
};
|
||||||
|
protected override _config: KTAccordionConfigInterface = this._defaultConfig;
|
||||||
|
protected _accordionElements: NodeListOf<HTMLElement>;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTAccordionConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
KTEventHandler.on(this._element, '[data-accordion-toggle]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const accordionElement = target.closest('[data-accordion-item]') as HTMLElement;
|
||||||
|
|
||||||
|
if (accordionElement) this._toggle(accordionElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(accordionElement: HTMLElement): void {
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('toggle', payload);
|
||||||
|
this._dispatchEvent('toggle', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accordionElement.classList.contains('active')) {
|
||||||
|
this._hide(accordionElement);
|
||||||
|
} else {
|
||||||
|
this._show(accordionElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _show(accordionElement: HTMLElement): void {
|
||||||
|
if (accordionElement.hasAttribute('animating') || accordionElement.classList.contains(this._getOption('activeClass') as string)) return;
|
||||||
|
|
||||||
|
const toggleElement = KTDom.child(accordionElement, '[data-accordion-toggle]');
|
||||||
|
if (!toggleElement) return;
|
||||||
|
|
||||||
|
const contentElement = KTDom.getElement(toggleElement.getAttribute('data-accordion-toggle'));
|
||||||
|
if (!contentElement) return;
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('show', payload);
|
||||||
|
this._dispatchEvent('show', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('expandAll') as boolean === false) {
|
||||||
|
this._hideSiblings(accordionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
accordionElement.setAttribute('aria-expanded', 'true');
|
||||||
|
accordionElement.classList.add(this._getOption('activeClass') as string);
|
||||||
|
|
||||||
|
accordionElement.setAttribute('animating', 'true');
|
||||||
|
contentElement.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
contentElement.style.height = `0px`;
|
||||||
|
KTDom.reflow(contentElement);
|
||||||
|
contentElement.style.height = `${contentElement.scrollHeight}px`;
|
||||||
|
|
||||||
|
KTDom.transitionEnd(contentElement, () => {
|
||||||
|
accordionElement.removeAttribute('animating');
|
||||||
|
contentElement.style.height = ''
|
||||||
|
|
||||||
|
this._fireEvent('shown');
|
||||||
|
this._dispatchEvent('shown');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _hide(accordionElement: HTMLElement): void {
|
||||||
|
if (accordionElement.hasAttribute('animating') || !accordionElement.classList.contains(this._getOption('activeClass') as string)) return;
|
||||||
|
|
||||||
|
const toggleElement = KTDom.child(accordionElement, '[data-accordion-toggle]');
|
||||||
|
if (!toggleElement) return;
|
||||||
|
|
||||||
|
const contentElement = KTDom.getElement(toggleElement.getAttribute('data-accordion-toggle'));
|
||||||
|
if (!contentElement) return;
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('hide', payload);
|
||||||
|
this._dispatchEvent('hide', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
accordionElement.setAttribute('aria-expanded', 'false');
|
||||||
|
|
||||||
|
contentElement.style.height = `${contentElement.scrollHeight}px`;
|
||||||
|
KTDom.reflow(contentElement);
|
||||||
|
contentElement.style.height = '0px';
|
||||||
|
accordionElement.setAttribute('animating', 'true');
|
||||||
|
|
||||||
|
KTDom.transitionEnd(contentElement, () => {
|
||||||
|
accordionElement.removeAttribute('animating');
|
||||||
|
accordionElement.classList.remove(this._getOption('activeClass') as string);
|
||||||
|
contentElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
|
||||||
|
this._fireEvent('hidden');
|
||||||
|
this._dispatchEvent('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _hideSiblings(accordionElement: HTMLElement): void {
|
||||||
|
const siblings = KTDom.siblings(accordionElement);
|
||||||
|
|
||||||
|
siblings?.forEach((sibling) => {
|
||||||
|
this._hide(sibling as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public show(accordionElement: HTMLElement): void {
|
||||||
|
this._show(accordionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public hide(accordionElement: HTMLElement): void {
|
||||||
|
this._hide(accordionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle(accordionElement: HTMLElement): void {
|
||||||
|
this._toggle(accordionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTAccordion {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'accordion')) {
|
||||||
|
return KTData.get(element, 'accordion') as KTAccordion;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-accordion') === "true") {
|
||||||
|
return new KTAccordion(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTAccordionConfigInterface): KTAccordion {
|
||||||
|
return this.getInstance(element) || new KTAccordion(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-accordion="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTAccordion(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTAccordion.createInstances();
|
||||||
|
}
|
||||||
|
}
|
2
resources/metronic/core/components/accordion/index.ts
Normal file
2
resources/metronic/core/components/accordion/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTAccordion } from './accordion';
|
||||||
|
export type { KTAccordionConfigInterface, KTAccordionInterface } from './types';
|
11
resources/metronic/core/components/accordion/types.ts
Normal file
11
resources/metronic/core/components/accordion/types.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface KTAccordionConfigInterface {
|
||||||
|
hiddenClass: string;
|
||||||
|
activeClass: string
|
||||||
|
expandAll: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTAccordionInterface {
|
||||||
|
show(accordionElement: HTMLElement): void;
|
||||||
|
hide(accordionElement: HTMLElement): void;
|
||||||
|
toggle(accordionElement: HTMLElement): void;
|
||||||
|
}
|
179
resources/metronic/core/components/collapse/collapse.ts
Normal file
179
resources/metronic/core/components/collapse/collapse.ts
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTCollapseInterface, KTCollapseConfigInterface } from './types';
|
||||||
|
|
||||||
|
export class KTCollapse extends KTComponent implements KTCollapseInterface {
|
||||||
|
protected override _name: string = 'collapse';
|
||||||
|
protected override _defaultConfig: KTCollapseConfigInterface = {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
activeClass: 'active',
|
||||||
|
target: ''
|
||||||
|
};
|
||||||
|
protected override _config: KTCollapseConfigInterface = this._defaultConfig;
|
||||||
|
protected _isAnimating: boolean = false;
|
||||||
|
protected _targetElement: HTMLElement;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTCollapseConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._targetElement = this._getTargetElement();
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTargetElement(): HTMLElement | null {
|
||||||
|
return (
|
||||||
|
KTDom.getElement(this._element.getAttribute('data-collapse') as string) ||
|
||||||
|
KTDom.getElement(this._getOption('target') as string)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _isOpen(): boolean {
|
||||||
|
return this._targetElement.classList.contains(this._getOption('activeClass') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
this._element.addEventListener('click', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this._toggle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _expand(): void {
|
||||||
|
if (this._isAnimating || this._isOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('expand', payload);
|
||||||
|
this._dispatchEvent('expand', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._element) {
|
||||||
|
this._element.setAttribute('aria-expanded', 'true');
|
||||||
|
this._element.classList.add(this._getOption('activeClass') as string);
|
||||||
|
}
|
||||||
|
this._targetElement.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
this._targetElement.classList.add(this._getOption('activeClass') as string);
|
||||||
|
|
||||||
|
this._targetElement.style.height = '0px';
|
||||||
|
this._targetElement.style.overflow = 'hidden';
|
||||||
|
KTDom.reflow(this._targetElement);
|
||||||
|
this._targetElement.style.height = `${this._targetElement.scrollHeight}px`;
|
||||||
|
this._isAnimating = true;
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._targetElement, () => {
|
||||||
|
this._isAnimating = false;
|
||||||
|
this._targetElement.style.height = '';
|
||||||
|
this._targetElement.style.overflow = '';
|
||||||
|
|
||||||
|
this._fireEvent('expanded');
|
||||||
|
this._dispatchEvent('expanded');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _collapse(): void {
|
||||||
|
if (this._isAnimating || !this._isOpen()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('collapse', payload);
|
||||||
|
this._dispatchEvent('collapse', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
this._element.setAttribute('aria-expanded', 'false');
|
||||||
|
this._element.classList.remove(this._getOption('activeClass') as string);
|
||||||
|
this._targetElement.classList.remove(this._getOption('activeClass') as string);
|
||||||
|
|
||||||
|
this._targetElement.style.height = `${this._targetElement.scrollHeight}px`;
|
||||||
|
KTDom.reflow(this._targetElement);
|
||||||
|
this._targetElement.style.height = `0px`;
|
||||||
|
this._targetElement.style.overflow = 'hidden';
|
||||||
|
this._isAnimating = true;
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._targetElement, () => {
|
||||||
|
this._isAnimating = false;
|
||||||
|
this._targetElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
this._targetElement.style.overflow = '';
|
||||||
|
|
||||||
|
this._fireEvent('collapsed');
|
||||||
|
this._dispatchEvent('collapsed');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(): void {
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('toggle', payload);
|
||||||
|
this._dispatchEvent('toggle', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isOpen()) {
|
||||||
|
this._collapse();
|
||||||
|
} else {
|
||||||
|
this._expand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public expand(): void {
|
||||||
|
return this._expand();
|
||||||
|
}
|
||||||
|
|
||||||
|
public collapse(): void {
|
||||||
|
return this._collapse();
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOpen(): boolean {
|
||||||
|
return this._isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTCollapse {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'collapse')) {
|
||||||
|
return KTData.get(element, 'collapse') as KTCollapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-collapse') !== "false") {
|
||||||
|
return new KTCollapse(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTCollapseConfigInterface): KTCollapse {
|
||||||
|
return this.getInstance(element) || new KTCollapse(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-collapse]:not([data-collapse="false"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTCollapse(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTCollapse.createInstances();
|
||||||
|
}
|
||||||
|
}
|
2
resources/metronic/core/components/collapse/index.ts
Normal file
2
resources/metronic/core/components/collapse/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTCollapse } from './collapse';
|
||||||
|
export type { KTCollapseConfigInterface, KTCollapseInterface } from './types';
|
11
resources/metronic/core/components/collapse/types.ts
Normal file
11
resources/metronic/core/components/collapse/types.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface KTCollapseConfigInterface {
|
||||||
|
hiddenClass: string;
|
||||||
|
activeClass: string;
|
||||||
|
target: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTCollapseInterface {
|
||||||
|
collapse(): void;
|
||||||
|
expand(): void;
|
||||||
|
isOpen(): boolean;
|
||||||
|
}
|
147
resources/metronic/core/components/component.ts
Normal file
147
resources/metronic/core/components/component.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/* eslint-disable guard-for-in */
|
||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KTGlobalComponentsConfig: object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import KTData from '../helpers/data';
|
||||||
|
import KTDom from '../helpers/dom';
|
||||||
|
import KTUtils from '../helpers/utils';
|
||||||
|
import KTGlobalComponentsConfig from './config';
|
||||||
|
import {KTBreakpointType, KTOptionType} from '../types';
|
||||||
|
|
||||||
|
export default class KTComponent {
|
||||||
|
protected _name: string;
|
||||||
|
protected _defaultConfig: object;
|
||||||
|
protected _config: object;
|
||||||
|
protected _events: Map<string, Map<string, CallableFunction>>;
|
||||||
|
protected _uid: string | null = null;
|
||||||
|
protected _element: HTMLElement | null = null;
|
||||||
|
|
||||||
|
protected _init(element: HTMLElement | null) {
|
||||||
|
element = KTDom.getElement(element);
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element = element;
|
||||||
|
this._events = new Map();
|
||||||
|
this._uid = KTUtils.geUID(this._name);
|
||||||
|
|
||||||
|
KTData.set(this._element, this._name, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _fireEvent(eventType: string, payload: object = null): void {
|
||||||
|
this._events.get(eventType)?.forEach((callable) => {
|
||||||
|
callable(payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _dispatchEvent(eventType: string, payload: object = null): void {
|
||||||
|
const event = new CustomEvent(eventType, {
|
||||||
|
detail: { payload },
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
composed: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
this._element.dispatchEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getOption(name: string): KTOptionType {
|
||||||
|
const value = this._config[name as keyof object];
|
||||||
|
|
||||||
|
if (value && (typeof value) === 'string') {
|
||||||
|
return this._getResponsiveOption(value);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getResponsiveOption(value: string): KTOptionType {
|
||||||
|
let result = null;
|
||||||
|
const width = KTDom.getViewPort().width;
|
||||||
|
const parts = String(value).split('|');
|
||||||
|
|
||||||
|
if (parts.length > 1) {
|
||||||
|
parts.every((part) => {
|
||||||
|
if (part.includes(':')) {
|
||||||
|
const [breakpointKey, breakpointValue] = part.split(':');
|
||||||
|
const breakpoint = KTUtils.getBreakpoint(breakpointKey as KTBreakpointType);
|
||||||
|
|
||||||
|
if (breakpoint <= width) {
|
||||||
|
result = breakpointValue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = part;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
result = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = KTUtils.parseDataAttribute(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getGlobalConfig(): object {
|
||||||
|
if (window.KTGlobalComponentsConfig && (window.KTGlobalComponentsConfig as object)[this._name as keyof object]) {
|
||||||
|
return (window.KTGlobalComponentsConfig as object)[this._name as keyof object] as object;
|
||||||
|
} else if (KTGlobalComponentsConfig && (KTGlobalComponentsConfig as object)[this._name as keyof object]) {
|
||||||
|
return (KTGlobalComponentsConfig as object)[this._name as keyof object] as object;
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _buildConfig(config: object = {}): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._config = {
|
||||||
|
...this._defaultConfig,
|
||||||
|
...this._getGlobalConfig(),
|
||||||
|
...KTDom.getDataAttributes(this._element, this._name),
|
||||||
|
...config,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
KTData.remove(this._element, this._name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public on(eventType: string, callback: CallableFunction): string {
|
||||||
|
const eventId = KTUtils.geUID();
|
||||||
|
|
||||||
|
if (!this._events.get(eventType)) {
|
||||||
|
this._events.set(eventType, new Map());
|
||||||
|
}
|
||||||
|
|
||||||
|
this._events.get(eventType).set(eventId, callback);
|
||||||
|
|
||||||
|
return eventId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public off(eventType: string, eventId: string): void {
|
||||||
|
this._events.get(eventType)?.delete(eventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getOption(name: string): KTOptionType {
|
||||||
|
return this._getOption(name as keyof object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getElement(): HTMLElement {
|
||||||
|
if (!this._element) return null;
|
||||||
|
return this._element;
|
||||||
|
}
|
||||||
|
}
|
25
resources/metronic/core/components/config.ts
Normal file
25
resources/metronic/core/components/config.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
const KTGlobalComponentsConfig = {
|
||||||
|
modal: {
|
||||||
|
backdropClass: 'transition-all duration-300',
|
||||||
|
},
|
||||||
|
drawer: {
|
||||||
|
backdropClass: 'transition-all duration-300',
|
||||||
|
hiddenClass: 'hidden'
|
||||||
|
},
|
||||||
|
collapse: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
},
|
||||||
|
dismiss: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
},
|
||||||
|
tabs: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
},
|
||||||
|
accordion: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KTGlobalComponentsConfig;
|
||||||
|
|
23
resources/metronic/core/components/config.umd.js
Normal file
23
resources/metronic/core/components/config.umd.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
window.KTGlobalComponentsConfig = {
|
||||||
|
modal: {
|
||||||
|
backdropClass: 'transition-all duration-300',
|
||||||
|
},
|
||||||
|
drawer: {
|
||||||
|
backdropClass: 'transition-all duration-300',
|
||||||
|
hiddenClass: 'hidden'
|
||||||
|
},
|
||||||
|
collapse: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
},
|
||||||
|
dismiss: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
},
|
||||||
|
tabs: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
},
|
||||||
|
accordion: {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
11
resources/metronic/core/components/constants.ts
Normal file
11
resources/metronic/core/components/constants.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export const KT_ACCESSIBILITY_KEYS = [
|
||||||
|
'ArrowUp',
|
||||||
|
'ArrowLeft',
|
||||||
|
'ArrowDown',
|
||||||
|
'ArrowRight',
|
||||||
|
'Home',
|
||||||
|
'End',
|
||||||
|
'Escape',
|
||||||
|
'Enter',
|
||||||
|
'Tab',
|
||||||
|
];
|
1580
resources/metronic/core/components/datatable/datatable.ts
Normal file
1580
resources/metronic/core/components/datatable/datatable.ts
Normal file
File diff suppressed because it is too large
Load Diff
14
resources/metronic/core/components/datatable/index.ts
Normal file
14
resources/metronic/core/components/datatable/index.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
export { KTDataTable } from './datatable';
|
||||||
|
export type {
|
||||||
|
KTDataTableSortOrderInterface,
|
||||||
|
KTDataTableDataInterface,
|
||||||
|
KTDataTableStateInterface as KTDataTableState,
|
||||||
|
KTDataTableInterface,
|
||||||
|
KTDatatableResponseDataInterface,
|
||||||
|
KTDataTableConfigInterface,
|
||||||
|
KTDataTableColumnFilterTypeInterface,
|
||||||
|
KTDataTableColumnFilterInterface,
|
||||||
|
KTDatatableCheckConfigInterface,
|
||||||
|
KTDatatableCheckInterface,
|
||||||
|
KTDatatableCheckChangePayloadInterface
|
||||||
|
} from './types';
|
173
resources/metronic/core/components/datatable/types.ts
Normal file
173
resources/metronic/core/components/datatable/types.ts
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
// Define the sort order and filter criteria types
|
||||||
|
export type KTDataTableSortOrderInterface = 'asc' | 'desc' | '';
|
||||||
|
|
||||||
|
export interface KTDataTableDataInterface {
|
||||||
|
[key: string]: string | number | boolean | object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTDataTableAttributeInterface {
|
||||||
|
[index: number]: { [key: string]: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTDataTableStateInterface {
|
||||||
|
page: number;
|
||||||
|
sortField: keyof KTDataTableDataInterface | number;
|
||||||
|
sortOrder: KTDataTableSortOrderInterface;
|
||||||
|
pageSize: number;
|
||||||
|
totalItems: number;
|
||||||
|
totalPages: number;
|
||||||
|
selectedRows: number[];
|
||||||
|
filters: KTDataTableColumnFilterInterface[];
|
||||||
|
search: string | object;
|
||||||
|
originalData: KTDataTableDataInterface[];
|
||||||
|
originalDataAttributes: KTDataTableAttributeInterface[]
|
||||||
|
_contentChecksum?: string;
|
||||||
|
_configChecksum?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The public methods of the DataTable component
|
||||||
|
*/
|
||||||
|
export interface KTDataTableInterface {
|
||||||
|
/**
|
||||||
|
* Sort the data by the given field. The sort order is ASC by default.
|
||||||
|
* @param field The field to sort the data by
|
||||||
|
*/
|
||||||
|
sort: (field: keyof KTDataTableDataInterface | number) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go to the given page.
|
||||||
|
* @param page The page number to go to
|
||||||
|
*/
|
||||||
|
goPage: (page: number) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload the data from the API endpoint.
|
||||||
|
*/
|
||||||
|
reload: () => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the page size.
|
||||||
|
* @param size The new page size
|
||||||
|
*/
|
||||||
|
setPageSize: (pageSize: number) => void;
|
||||||
|
|
||||||
|
showSpinner(): void;
|
||||||
|
|
||||||
|
hideSpinner(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTDatatableResponseDataInterface {
|
||||||
|
data: KTDataTableDataInterface[];
|
||||||
|
totalCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the DataTable options type
|
||||||
|
export interface KTDataTableConfigInterface {
|
||||||
|
requestMethod?: string;
|
||||||
|
requestHeaders?: { [key: string]: string };
|
||||||
|
apiEndpoint?: string;
|
||||||
|
mapResponse?: (data: KTDatatableResponseDataInterface) => KTDatatableResponseDataInterface;
|
||||||
|
mapRequest?: (query: URLSearchParams) => URLSearchParams;
|
||||||
|
|
||||||
|
pageSize?: number;
|
||||||
|
pageMore?: boolean;
|
||||||
|
pageMoreLimit?: number;
|
||||||
|
stateSave?: boolean;
|
||||||
|
stateNamespace?: string;
|
||||||
|
pageSizes?: number[];
|
||||||
|
columns: {
|
||||||
|
[key: keyof KTDataTableDataInterface | string]: {
|
||||||
|
title?: string,
|
||||||
|
render?: (item: KTDataTableDataInterface[keyof KTDataTableDataInterface] | string, data: KTDataTableDataInterface, context: KTDataTableInterface) => string,
|
||||||
|
checkbox?: boolean,
|
||||||
|
createdCell?: (cell: HTMLTableCellElement, cellData: KTDataTableDataInterface[keyof KTDataTableDataInterface] | string, rowData: KTDataTableDataInterface, row: HTMLTableRowElement) => void,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
infoEmpty?: string;
|
||||||
|
|
||||||
|
info?: string;
|
||||||
|
|
||||||
|
loading?: {
|
||||||
|
template: string,
|
||||||
|
content: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
sort?: {
|
||||||
|
classes?: {
|
||||||
|
base?: string,
|
||||||
|
asc?: string,
|
||||||
|
desc?: string,
|
||||||
|
};
|
||||||
|
// local data sort callback
|
||||||
|
callback?: (data: KTDataTableDataInterface[], sortField: keyof KTDataTableDataInterface | number, sortOrder: KTDataTableSortOrderInterface) => KTDataTableDataInterface[];
|
||||||
|
},
|
||||||
|
|
||||||
|
search?: {
|
||||||
|
delay?: number, // delay in milliseconds
|
||||||
|
callback?: (data: KTDataTableDataInterface[], search: string) => KTDataTableDataInterface[]; // search callback
|
||||||
|
},
|
||||||
|
|
||||||
|
pagination?: {
|
||||||
|
number: {
|
||||||
|
class: string,
|
||||||
|
text: string,
|
||||||
|
},
|
||||||
|
previous: {
|
||||||
|
class: string,
|
||||||
|
text: string,
|
||||||
|
},
|
||||||
|
next: {
|
||||||
|
class: string,
|
||||||
|
text: string,
|
||||||
|
},
|
||||||
|
more: {
|
||||||
|
class: string,
|
||||||
|
text: string,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
attributes?: {
|
||||||
|
table?: string,
|
||||||
|
info?: string,
|
||||||
|
size?: string,
|
||||||
|
pagination?: string,
|
||||||
|
spinner?: string,
|
||||||
|
check?: string,
|
||||||
|
checkbox?: string,
|
||||||
|
},
|
||||||
|
|
||||||
|
checkbox?: {
|
||||||
|
checkedClass?: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
_state?: KTDataTableStateInterface;
|
||||||
|
_data?: KTDataTableDataInterface[];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export type KTDataTableColumnFilterTypeInterface = 'text' | 'numeric' | 'dateRange';
|
||||||
|
|
||||||
|
export type KTDataTableColumnFilterInterface = {
|
||||||
|
column: keyof KTDataTableDataInterface;
|
||||||
|
type: KTDataTableColumnFilterTypeInterface;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface KTDatatableCheckConfigInterface {
|
||||||
|
target: string;
|
||||||
|
checkedClass: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTDatatableCheckInterface {
|
||||||
|
toggle(): void;
|
||||||
|
check(): void;
|
||||||
|
uncheck(): void;
|
||||||
|
isChecked(): boolean;
|
||||||
|
getChecked(): string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTDatatableCheckChangePayloadInterface {
|
||||||
|
cancel?: boolean;
|
||||||
|
}
|
133
resources/metronic/core/components/dismiss/dismiss.ts
Normal file
133
resources/metronic/core/components/dismiss/dismiss.ts
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTDismissInterface, KTDismissConfigInterface } from './types';
|
||||||
|
import { KTDismissModeType } from './types';
|
||||||
|
|
||||||
|
export class KTDismiss extends KTComponent implements KTDismissInterface {
|
||||||
|
protected override _name: string = 'dismiss';
|
||||||
|
protected override _defaultConfig: KTDismissConfigInterface = {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
mode: 'remove',
|
||||||
|
interrupt: true,
|
||||||
|
target: '',
|
||||||
|
};
|
||||||
|
protected override _config: KTDismissConfigInterface = this._defaultConfig;
|
||||||
|
protected _isAnimating: boolean = false;
|
||||||
|
protected _targetElement: HTMLElement | null = null;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTDismissConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._config['mode'] = this._config['mode'] as KTDismissModeType;
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._targetElement = this._getTargetElement();
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTargetElement(): HTMLElement | null {
|
||||||
|
return (
|
||||||
|
KTDom.getElement(this._element.getAttribute('data-dismiss') as string) ||
|
||||||
|
KTDom.getElement(this._getOption('target') as string)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._element.addEventListener('click', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if ((this._getOption('interrupt') as boolean) === true ) {
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._dismiss();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _dismiss(): void {
|
||||||
|
if (this._isAnimating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('dismiss', payload);
|
||||||
|
this._dispatchEvent('dismiss', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._targetElement) return;
|
||||||
|
this._targetElement.style.opacity = '0';
|
||||||
|
KTDom.reflow(this._targetElement);
|
||||||
|
this._isAnimating = true;
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._targetElement, () => {
|
||||||
|
if (!this._targetElement) return;
|
||||||
|
this._isAnimating = false;
|
||||||
|
this._targetElement.style.opacity = '';
|
||||||
|
|
||||||
|
if (this._getOption('mode').toString().toLowerCase() === 'hide') {
|
||||||
|
this._targetElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
} else {
|
||||||
|
KTDom.remove(this._targetElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fireEvent('dismissed');
|
||||||
|
this._dispatchEvent('dismissed');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTargetElement(): HTMLElement {
|
||||||
|
return this._targetElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public dismiss(): void {
|
||||||
|
this._dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTDismiss {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'dismiss')) {
|
||||||
|
return KTData.get(element, 'dismiss') as KTDismiss;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-dismiss') !== "false") {
|
||||||
|
return new KTDismiss(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTDismissConfigInterface): KTDismiss {
|
||||||
|
return this.getInstance(element) || new KTDismiss(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-dismiss]:not([data-dismiss="false"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTDismiss(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTDismiss.createInstances();
|
||||||
|
}
|
||||||
|
}
|
2
resources/metronic/core/components/dismiss/index.ts
Normal file
2
resources/metronic/core/components/dismiss/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTDismiss } from './dismiss';
|
||||||
|
export type { KTDismissConfigInterface, KTDismissInterface } from './types';
|
12
resources/metronic/core/components/dismiss/types.ts
Normal file
12
resources/metronic/core/components/dismiss/types.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export declare type KTDismissModeType = 'remove' | 'hide';
|
||||||
|
|
||||||
|
export interface KTDismissConfigInterface {
|
||||||
|
hiddenClass: string;
|
||||||
|
target: string;
|
||||||
|
interrupt: boolean;
|
||||||
|
mode?: KTDismissModeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTDismissInterface {
|
||||||
|
dismiss(): void;
|
||||||
|
}
|
377
resources/metronic/core/components/drawer/drawer.ts
Normal file
377
resources/metronic/core/components/drawer/drawer.ts
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTUtils from '../../helpers/utils';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTDrawerInterface, KTDrawerConfigInterface } from './types';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KT_DRAWER_INITIALIZED: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KTDrawer extends KTComponent implements KTDrawerInterface {
|
||||||
|
protected override _name: string = 'drawer';
|
||||||
|
protected override _defaultConfig: KTDrawerConfigInterface = {
|
||||||
|
zindex: '100',
|
||||||
|
enable: true,
|
||||||
|
class: '',
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
backdrop: true,
|
||||||
|
backdropClass: 'transition-all duration-300 fixed inset-0 bg-gray-900 opacity-25',
|
||||||
|
backdropStatic: false,
|
||||||
|
keyboard: true,
|
||||||
|
disableScroll: true,
|
||||||
|
persistent: false,
|
||||||
|
focus: true
|
||||||
|
};
|
||||||
|
protected override _config: KTDrawerConfigInterface = this._defaultConfig;
|
||||||
|
protected _isOpen: boolean = false;
|
||||||
|
protected _isTransitioning: boolean = false;
|
||||||
|
protected _backdropElement: HTMLElement | null = null;
|
||||||
|
protected _relatedTarget: HTMLElement | null = null;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTDrawerConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
this._handleClose();
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handleClose(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
KTEventHandler.on(this._element, '[data-drawer-hide]', 'click', () => {
|
||||||
|
this._hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(relatedTarget?: HTMLElement): void {
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('toggle', payload);
|
||||||
|
this._dispatchEvent('toggle', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isOpen === true) {
|
||||||
|
this._hide();
|
||||||
|
} else {
|
||||||
|
this._show(relatedTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _show(relatedTarget?: HTMLElement): void {
|
||||||
|
if (this._isOpen || this._isTransitioning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('show', payload);
|
||||||
|
this._dispatchEvent('show', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KTDrawer.hide();
|
||||||
|
|
||||||
|
if (this._getOption('backdrop') === true) this._createBackdrop();
|
||||||
|
|
||||||
|
if (relatedTarget) this._relatedTarget = relatedTarget;
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
this._isTransitioning = true;
|
||||||
|
this._element.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
this._element.setAttribute('role', 'dialog');
|
||||||
|
this._element.setAttribute('aria-modal', 'true');
|
||||||
|
this._element.setAttribute('tabindex', '-1');
|
||||||
|
|
||||||
|
const zindex: number = parseInt(this._getOption('zindex') as string);
|
||||||
|
if (zindex > 0) {
|
||||||
|
this._element.style.zIndex = `${zindex}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('disableScroll')) {
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
KTDom.reflow(this._element);
|
||||||
|
this._element.classList.add('open');
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._element, () => {
|
||||||
|
this._isTransitioning = false;
|
||||||
|
this._isOpen = true;
|
||||||
|
|
||||||
|
if (this._getOption('focus') === true) {
|
||||||
|
this._autoFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fireEvent('shown');
|
||||||
|
this._dispatchEvent('shown');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _hide(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
if (this._isOpen === false || this._isTransitioning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('hide', payload);
|
||||||
|
this._dispatchEvent('hide', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._isTransitioning = true;
|
||||||
|
this._element.removeAttribute('role');
|
||||||
|
this._element.removeAttribute('aria-modal');
|
||||||
|
this._element.removeAttribute('tabindex');
|
||||||
|
if (this._getOption('disableScroll')) {
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
KTDom.reflow(this._element);
|
||||||
|
this._element.classList.remove('open');
|
||||||
|
|
||||||
|
if (this._getOption('backdrop') === true) {
|
||||||
|
this._deleteBackdrop();
|
||||||
|
}
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._element, () => {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._isTransitioning = false;
|
||||||
|
this._isOpen = false;
|
||||||
|
this._element.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
this._element.style.zIndex = '';
|
||||||
|
|
||||||
|
this._fireEvent('hidden');
|
||||||
|
this._dispatchEvent('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update(): void {
|
||||||
|
if ((this._getOption('class') as string).length > 0) {
|
||||||
|
if (this.isEnabled()) {
|
||||||
|
KTDom.addClass(this._element, this._getOption('class') as string);
|
||||||
|
} else {
|
||||||
|
KTDom.removeClass(this._element, this._getOption('class') as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _autoFocus(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const input: HTMLInputElement | null = this._element.querySelector('[data-drawer-focus]');
|
||||||
|
if (!input) return; else input.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _createBackdrop(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
const zindex: number = parseInt(this._getOption('zindex') as string);
|
||||||
|
|
||||||
|
this._backdropElement = document.createElement('DIV');
|
||||||
|
this._backdropElement.style.zIndex = (zindex - 1).toString();
|
||||||
|
this._backdropElement.classList.add('drawer-backdrop');
|
||||||
|
document.body.append(this._backdropElement);
|
||||||
|
KTDom.reflow(this._backdropElement);
|
||||||
|
KTDom.addClass(this._backdropElement, this._getOption('backdropClass') as string);
|
||||||
|
|
||||||
|
this._backdropElement.addEventListener('click', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (this._getOption('backdropStatic') === false) {
|
||||||
|
this._hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _deleteBackdrop(): void {
|
||||||
|
if (!this._backdropElement) return;
|
||||||
|
|
||||||
|
KTDom.reflow(this._backdropElement);
|
||||||
|
this._backdropElement.style.opacity = "0";
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._backdropElement, () => {
|
||||||
|
if (!this._backdropElement) return;
|
||||||
|
KTDom.remove(this._backdropElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _isEnabled(): boolean {
|
||||||
|
return this._getOption('enable') as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle(): void {
|
||||||
|
return this._toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public show(relatedTarget?: HTMLElement): void {
|
||||||
|
return this._show(relatedTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public hide(): void {
|
||||||
|
return this._hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
return this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRelatedTarget(): HTMLElement | null {
|
||||||
|
return this._relatedTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOpen(): boolean {
|
||||||
|
return this._isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isEnabled(): boolean {
|
||||||
|
return this._isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTDrawer {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'drawer')) {
|
||||||
|
return KTData.get(element, 'drawer') as KTDrawer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-drawer') === "true") {
|
||||||
|
return new KTDrawer(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTDrawerConfigInterface): KTDrawer {
|
||||||
|
return this.getInstance(element) || new KTDrawer(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static hide(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-drawer]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
const drawer = KTDrawer.getInstance(element as HTMLElement);
|
||||||
|
|
||||||
|
if (drawer && drawer.isOpen()) {
|
||||||
|
drawer.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleResize(): void {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
let timer;
|
||||||
|
|
||||||
|
KTUtils.throttle(timer, () => {
|
||||||
|
document.querySelectorAll('[data-drawer]').forEach((element) => {
|
||||||
|
const drawer = KTDrawer.getInstance(element as HTMLElement);
|
||||||
|
drawer.update();
|
||||||
|
|
||||||
|
if (drawer && drawer.isOpen() && !drawer.isEnabled()) {
|
||||||
|
drawer.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleToggle(): void {
|
||||||
|
KTEventHandler.on(document.body, '[data-drawer-toggle]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const selector = target.getAttribute("data-drawer-toggle");
|
||||||
|
if (!selector) return;
|
||||||
|
|
||||||
|
const drawerElement = document.querySelector(selector);
|
||||||
|
const drawer = KTDrawer.getInstance(drawerElement as HTMLElement);
|
||||||
|
if (drawer) {
|
||||||
|
drawer.toggle();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleDismiss(): void {
|
||||||
|
KTEventHandler.on(document.body, '[data-drawer-dismiss]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const modalElement = target.closest('[data-drawer="true"]') as HTMLElement;
|
||||||
|
if (modalElement) {
|
||||||
|
const modal = KTDrawer.getInstance(modalElement);
|
||||||
|
if (modal) {
|
||||||
|
modal.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleClickAway() {
|
||||||
|
document.addEventListener('click', (event: Event) => {
|
||||||
|
const drawerElement = document.querySelector('.open[data-drawer]');
|
||||||
|
if (!drawerElement) return;
|
||||||
|
|
||||||
|
const drawer = KTDrawer.getInstance(drawerElement as HTMLElement);
|
||||||
|
if (!drawer) return;
|
||||||
|
|
||||||
|
if (drawer.getOption('persistent')) return;
|
||||||
|
|
||||||
|
if (drawer.getOption('backdrop')) return;
|
||||||
|
|
||||||
|
if (drawerElement !== event.target &&
|
||||||
|
drawer.getRelatedTarget() !== event.target &&
|
||||||
|
drawerElement.contains(event.target as HTMLElement) === false) {
|
||||||
|
drawer.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleKeyword() {
|
||||||
|
document.addEventListener('keydown', (event: KeyboardEvent) => {
|
||||||
|
const drawerElement = document.querySelector('.open[data-drawer]');
|
||||||
|
const drawer = KTDrawer.getInstance(drawerElement as HTMLElement);
|
||||||
|
if (!drawer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if esc key was not pressed in combination with ctrl or alt or shift
|
||||||
|
if (event.key === 'Escape' && !(event.ctrlKey || event.altKey || event.shiftKey)) {
|
||||||
|
drawer.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.code === 'Tab' && !event.metaKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-drawer="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTDrawer(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTDrawer.createInstances();
|
||||||
|
|
||||||
|
if (window.KT_DRAWER_INITIALIZED !== true) {
|
||||||
|
KTDrawer.handleToggle();
|
||||||
|
KTDrawer.handleDismiss();
|
||||||
|
KTDrawer.handleResize();
|
||||||
|
KTDrawer.handleClickAway();
|
||||||
|
KTDrawer.handleKeyword();
|
||||||
|
window.KT_DRAWER_INITIALIZED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
resources/metronic/core/components/drawer/index.ts
Normal file
2
resources/metronic/core/components/drawer/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTDrawer } from './drawer';
|
||||||
|
export type { KTDrawerConfigInterface, KTDrawerInterface } from './types';
|
18
resources/metronic/core/components/drawer/types.ts
Normal file
18
resources/metronic/core/components/drawer/types.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export interface KTDrawerConfigInterface {
|
||||||
|
enable?: boolean,
|
||||||
|
class: string,
|
||||||
|
zindex?: string,
|
||||||
|
hiddenClass: string
|
||||||
|
backdrop: boolean,
|
||||||
|
backdropClass: string,
|
||||||
|
backdropStatic: boolean,
|
||||||
|
keyboard: boolean,
|
||||||
|
disableScroll: boolean,
|
||||||
|
persistent: boolean;
|
||||||
|
focus: boolean;
|
||||||
|
}
|
||||||
|
export interface KTDrawerInterface {
|
||||||
|
show(): void;
|
||||||
|
hide(): void;
|
||||||
|
toggle(): void;
|
||||||
|
}
|
484
resources/metronic/core/components/dropdown/dropdown.ts
Normal file
484
resources/metronic/core/components/dropdown/dropdown.ts
Normal file
@ -0,0 +1,484 @@
|
|||||||
|
import { Instance as PopperInstance, createPopper, Placement, VirtualElement } from '@popperjs/core';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTDropdownConfigInterface, KTDropdownInterface } from './types';
|
||||||
|
import { KTMenu } from '../menu';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KT_DROPDOWN_INITIALIZED: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
||||||
|
protected override _name: string = 'dropdown';
|
||||||
|
protected override _defaultConfig: KTDropdownConfigInterface = {
|
||||||
|
zindex: 105,
|
||||||
|
hoverTimeout: 200,
|
||||||
|
placement: 'bottom-start',
|
||||||
|
permanent: false,
|
||||||
|
dismiss: false,
|
||||||
|
trigger: 'click',
|
||||||
|
attach: '',
|
||||||
|
offset: '0px, 5px',
|
||||||
|
hiddenClass: 'hidden'
|
||||||
|
};
|
||||||
|
protected override _config: KTDropdownConfigInterface = this._defaultConfig;
|
||||||
|
protected _disabled: boolean = false;
|
||||||
|
protected _toggleElement: HTMLElement;
|
||||||
|
protected _contentElement: HTMLElement;
|
||||||
|
protected _isTransitioning: boolean = false;
|
||||||
|
protected _isOpen: boolean = false;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTDropdownConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._toggleElement = this._element.querySelector('.dropdown-toggle');
|
||||||
|
if (!this._toggleElement) return;
|
||||||
|
this._contentElement = this._element.querySelector('.dropdown-content, [data-dropdown-content="true"]');
|
||||||
|
if (!this._contentElement) return;
|
||||||
|
|
||||||
|
KTData.set(this._contentElement, 'dropdownElement', this._element);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _click(event: Event): void {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
if (this._disabled === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('trigger') !== 'click') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _mouseover(): void {
|
||||||
|
if (this._disabled === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('trigger') !== 'hover') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KTData.get(this._element, 'hover') === '1') {
|
||||||
|
clearTimeout(KTData.get(this._element, 'timeout') as number);
|
||||||
|
KTData.remove(this._element, 'hover');
|
||||||
|
KTData.remove(this._element, 'timeout');
|
||||||
|
}
|
||||||
|
|
||||||
|
this._show();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _mouseout(): void {
|
||||||
|
if (this._disabled === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('trigger') !== 'hover') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
if (KTData.get(this._element, 'hover') === '1') {
|
||||||
|
this._hide();
|
||||||
|
}
|
||||||
|
}, parseInt(this._getOption('hoverTimeout') as string));
|
||||||
|
|
||||||
|
KTData.set(this._element, 'hover', '1');
|
||||||
|
KTData.set(this._element, 'timeout', timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(): void {
|
||||||
|
if (this._isOpen) {
|
||||||
|
this._hide();
|
||||||
|
} else {
|
||||||
|
this._show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _show(): void {
|
||||||
|
if (this._isOpen || this._isTransitioning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('show', payload);
|
||||||
|
this._dispatchEvent('show', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide all currently shown dropdowns except current one
|
||||||
|
KTDropdown.hide();
|
||||||
|
KTMenu.hide(this._element);
|
||||||
|
|
||||||
|
let zIndex: number = parseInt(this._getOption('zindex') as string);
|
||||||
|
const parentZindex: number = KTDom.getHighestZindex(this._element);
|
||||||
|
|
||||||
|
if (parentZindex !== null && parentZindex >= zIndex) {
|
||||||
|
zIndex = parentZindex + 1;
|
||||||
|
}
|
||||||
|
if (zIndex > 0) {
|
||||||
|
this._contentElement.style.zIndex = zIndex.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._contentElement.style.display = 'block';
|
||||||
|
this._contentElement.style.opacity = '0';
|
||||||
|
KTDom.reflow(this._contentElement);
|
||||||
|
this._contentElement.style.opacity = '1';
|
||||||
|
|
||||||
|
this._contentElement.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
this._toggleElement.classList.add('active');
|
||||||
|
this._contentElement.classList.add('open');
|
||||||
|
this._element.classList.add('open');
|
||||||
|
|
||||||
|
this._initPopper();
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._contentElement, () => {
|
||||||
|
this._isTransitioning = false;
|
||||||
|
this._isOpen = true;
|
||||||
|
|
||||||
|
this._fireEvent('shown');
|
||||||
|
this._dispatchEvent('shown');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _hide(): void {
|
||||||
|
if (this._isOpen === false || this._isTransitioning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('hide', payload);
|
||||||
|
this._dispatchEvent('hide', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._contentElement.style.opacity = '1';
|
||||||
|
KTDom.reflow(this._contentElement);
|
||||||
|
this._contentElement.style.opacity = '0';
|
||||||
|
this._contentElement.classList.remove('open');
|
||||||
|
this._toggleElement.classList.remove('active');
|
||||||
|
this._element.classList.remove('open');
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._contentElement, () => {
|
||||||
|
this._isTransitioning = false;
|
||||||
|
this._isOpen = false;
|
||||||
|
|
||||||
|
this._contentElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
this._contentElement.style.display = '';
|
||||||
|
this._contentElement.style.zIndex = '';
|
||||||
|
|
||||||
|
// Destroy popper(new)
|
||||||
|
this._destroyPopper();
|
||||||
|
|
||||||
|
// Handle dropdown hidden event
|
||||||
|
this._fireEvent('hidden');
|
||||||
|
this._dispatchEvent('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _initPopper(): void {
|
||||||
|
// Setup popper instance
|
||||||
|
let reference: HTMLElement;
|
||||||
|
const attach: string = this._getOption('attach') as string;
|
||||||
|
|
||||||
|
if (attach) {
|
||||||
|
if (attach === 'parent') {
|
||||||
|
reference = this._toggleElement.parentNode as HTMLElement;
|
||||||
|
} else {
|
||||||
|
reference = document.querySelector(attach) as HTMLElement;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reference = this._toggleElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reference) {
|
||||||
|
const popper = createPopper(reference as Element | VirtualElement, this._contentElement, this._getPopperConfig());
|
||||||
|
KTData.set(this._element, 'popper', popper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _destroyPopper(): void {
|
||||||
|
if (KTData.has(this._element, 'popper')) {
|
||||||
|
(KTData.get(this._element, 'popper') as PopperInstance).destroy();
|
||||||
|
KTData.remove(this._element, 'popper');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected __isOpen(): boolean {
|
||||||
|
return this._element.classList.contains('open') && this._contentElement.classList.contains('open');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getPopperConfig(): object {
|
||||||
|
// Placement
|
||||||
|
let placement = this._getOption('placement') as Placement;
|
||||||
|
if (!placement) {
|
||||||
|
placement = 'right';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Offset
|
||||||
|
const offsetValue = this._getOption('offset') as string;
|
||||||
|
const offset = offsetValue ? offsetValue.toString().split(',').map(value => parseInt(value.trim(), 10)) : [0, 0];
|
||||||
|
|
||||||
|
// Strategy
|
||||||
|
const strategy = this._getOption('overflow') === true ? 'absolute' : 'fixed';
|
||||||
|
const altAxis = this._getOption('flip') !== false ? true : false;
|
||||||
|
const popperConfig = {
|
||||||
|
placement: placement,
|
||||||
|
strategy: strategy,
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
name: 'offset',
|
||||||
|
options: {
|
||||||
|
offset: offset
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'preventOverflow',
|
||||||
|
options: {
|
||||||
|
altAxis: altAxis
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'flip',
|
||||||
|
options: {
|
||||||
|
flipVariations: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
return popperConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getToggleElement(): HTMLElement {
|
||||||
|
return this._toggleElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getContentElement(): HTMLElement {
|
||||||
|
return this._contentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
// General Methods
|
||||||
|
public click(event: Event): void {
|
||||||
|
this._click(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public mouseover(): void {
|
||||||
|
this._mouseover();
|
||||||
|
}
|
||||||
|
|
||||||
|
public mouseout(): void {
|
||||||
|
this._mouseout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public show(): void {
|
||||||
|
return this._show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public hide(): void {
|
||||||
|
this._hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle(): void {
|
||||||
|
this._toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getToggleElement(): HTMLElement {
|
||||||
|
return this._toggleElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getContentElement(): HTMLElement {
|
||||||
|
return this._contentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isPermanent(): boolean {
|
||||||
|
return this._getOption('permanent') as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public disable(): void {
|
||||||
|
this._disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enable(): void {
|
||||||
|
this._disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOpen(): boolean {
|
||||||
|
return this._isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Statics methods
|
||||||
|
public static getElement(reference: HTMLElement): HTMLElement {
|
||||||
|
if (reference.hasAttribute('data-dropdown')) return reference;
|
||||||
|
|
||||||
|
const findElement = reference.closest('[data-dropdown]') as HTMLElement;
|
||||||
|
if (findElement) return findElement;
|
||||||
|
|
||||||
|
if (reference.classList.contains('dropdown-content') && KTData.has(reference, 'dropdownElement')) {
|
||||||
|
return KTData.get(reference, 'dropdownElement') as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTDropdown {
|
||||||
|
element = this.getElement(element);
|
||||||
|
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'dropdown')) {
|
||||||
|
return KTData.get(element, 'dropdown') as KTDropdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-dropdown') === "true") {
|
||||||
|
return new KTDropdown(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTDropdownConfigInterface): KTDropdown {
|
||||||
|
return this.getInstance(element) || new KTDropdown(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static update(): void {
|
||||||
|
document.querySelectorAll('.open[data-dropdown]').forEach((item) => {
|
||||||
|
if (KTData.has(item as HTMLElement, 'popper')) {
|
||||||
|
(KTData.get(item as HTMLElement, 'popper') as PopperInstance).forceUpdate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static hide(skipElement?: HTMLElement): void {
|
||||||
|
document.querySelectorAll('.open[data-dropdown]').forEach((item) => {
|
||||||
|
if (skipElement && (skipElement === item || item.contains(skipElement))) return;
|
||||||
|
|
||||||
|
const dropdown = KTDropdown.getInstance(item as HTMLElement);
|
||||||
|
if (dropdown) dropdown.hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleClickAway() {
|
||||||
|
document.addEventListener('click', (event: Event) => {
|
||||||
|
document.querySelectorAll('.open[data-dropdown]').forEach((element) => {
|
||||||
|
const dropdown = KTDropdown.getInstance(element as HTMLElement);
|
||||||
|
|
||||||
|
if (dropdown && dropdown.isPermanent() === false) {
|
||||||
|
const contentElement = dropdown.getContentElement();
|
||||||
|
|
||||||
|
if (element === event.target || element.contains(event.target as HTMLElement)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentElement && (contentElement === event.target || contentElement.contains(event.target as HTMLElement))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dropdown.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleKeyboard() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleMouseover() {
|
||||||
|
KTEventHandler.on(
|
||||||
|
document.body,
|
||||||
|
'.dropdown-toggle',
|
||||||
|
'mouseover',
|
||||||
|
(event: Event, target: HTMLElement) => {
|
||||||
|
const dropdown = KTDropdown.getInstance(target);
|
||||||
|
|
||||||
|
if (dropdown !== null && dropdown.getOption('trigger') === 'hover') {
|
||||||
|
return dropdown.mouseover();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleMouseout() {
|
||||||
|
KTEventHandler.on(
|
||||||
|
document.body,
|
||||||
|
'.dropdown-toggle',
|
||||||
|
'mouseout',
|
||||||
|
(event: Event, target: HTMLElement) => {
|
||||||
|
const dropdown = KTDropdown.getInstance(target);
|
||||||
|
|
||||||
|
if (dropdown !== null && dropdown.getOption('trigger') === 'hover') {
|
||||||
|
return dropdown.mouseout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleClick() {
|
||||||
|
KTEventHandler.on(
|
||||||
|
document.body,
|
||||||
|
'.dropdown-toggle',
|
||||||
|
'click',
|
||||||
|
(event: Event, target: HTMLElement) => {
|
||||||
|
const dropdown = KTDropdown.getInstance(target);
|
||||||
|
if (dropdown) {
|
||||||
|
return dropdown.click(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleDismiss() {
|
||||||
|
KTEventHandler.on(
|
||||||
|
document.body,
|
||||||
|
'[data-dropdown-dismiss]',
|
||||||
|
'click',
|
||||||
|
(event: Event, target: HTMLElement) => {
|
||||||
|
const dropdown = KTDropdown.getInstance(target);
|
||||||
|
if (dropdown) {
|
||||||
|
return dropdown.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static initHandlers(): void {
|
||||||
|
this.handleClickAway();
|
||||||
|
this.handleKeyboard();
|
||||||
|
this.handleMouseover();
|
||||||
|
this.handleMouseout();
|
||||||
|
this.handleClick();
|
||||||
|
this.handleDismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-dropdown="true"]');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTDropdown(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTDropdown.createInstances();
|
||||||
|
|
||||||
|
if (window.KT_DROPDOWN_INITIALIZED !== true) {
|
||||||
|
KTDropdown.initHandlers();
|
||||||
|
window.KT_DROPDOWN_INITIALIZED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
resources/metronic/core/components/dropdown/index.ts
Normal file
2
resources/metronic/core/components/dropdown/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTDropdown } from './dropdown';
|
||||||
|
export type { KTDropdownConfigInterface, KTDropdownInterface } from './types';
|
20
resources/metronic/core/components/dropdown/types.ts
Normal file
20
resources/metronic/core/components/dropdown/types.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
export declare type KTDropdownTriggerType = 'hover' | 'click';
|
||||||
|
|
||||||
|
export interface KTDropdownConfigInterface {
|
||||||
|
zindex: number,
|
||||||
|
hoverTimeout: number,
|
||||||
|
permanent: boolean,
|
||||||
|
dismiss: boolean,
|
||||||
|
placement: string,
|
||||||
|
attach: string,
|
||||||
|
offset: string,
|
||||||
|
trigger: KTDropdownTriggerType,
|
||||||
|
hiddenClass: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTDropdownInterface {
|
||||||
|
disable(): void;
|
||||||
|
enable(): void;
|
||||||
|
show(): void;
|
||||||
|
hide(): void;
|
||||||
|
}
|
208
resources/metronic/core/components/image-input/image-input.ts
Normal file
208
resources/metronic/core/components/image-input/image-input.ts
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import {KTImageInputInterface, KTImageInputConfigInterface} from './types';
|
||||||
|
|
||||||
|
export class KTImageInput extends KTComponent implements KTImageInputInterface {
|
||||||
|
protected override _name: string = 'image-input';
|
||||||
|
protected override _defaultConfig: KTImageInputConfigInterface = {
|
||||||
|
hiddenClass: 'hidden'
|
||||||
|
};
|
||||||
|
protected _inputElement: HTMLInputElement;
|
||||||
|
protected _hiddenElement: HTMLInputElement;
|
||||||
|
protected _removeElement: HTMLElement;
|
||||||
|
protected _previewElement: HTMLElement;
|
||||||
|
protected _previewUrl: string = '';
|
||||||
|
protected _lastMode: string;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTImageInputConfigInterface = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._inputElement = this._element.querySelector('input[type="file"]');
|
||||||
|
this._hiddenElement = this._element.querySelector('input[type="hidden"]');
|
||||||
|
this._removeElement = this._element.querySelector('[data-image-input-remove]');
|
||||||
|
this._previewElement = this._element.querySelector('.image-input-preview');
|
||||||
|
|
||||||
|
this._update();
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
KTEventHandler.on(this._element, '.image-input-placeholder', 'click', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this._inputElement.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
this._inputElement.addEventListener('change', () => {
|
||||||
|
this._change();
|
||||||
|
});
|
||||||
|
|
||||||
|
this._removeElement.addEventListener('click', () => {
|
||||||
|
this._remove();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _change(): void {
|
||||||
|
const payload = {cancel: false};
|
||||||
|
this._fireEvent('change', payload);
|
||||||
|
this._dispatchEvent('change', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = () => {
|
||||||
|
this._previewElement.style.backgroundImage = `url(${reader.result})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.readAsDataURL(this._inputElement.files[0]);
|
||||||
|
this._inputElement.value = "";
|
||||||
|
this._hiddenElement.value = "";
|
||||||
|
this._lastMode = 'new';
|
||||||
|
|
||||||
|
this._element.classList.add('changed');
|
||||||
|
this._removeElement.classList.remove('hidden');
|
||||||
|
this._element.classList.remove('empty');
|
||||||
|
|
||||||
|
this._fireEvent('changed');
|
||||||
|
this._dispatchEvent('changed');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _remove(): void {
|
||||||
|
const payload = {cancel: false};
|
||||||
|
this._fireEvent('remove', payload);
|
||||||
|
this._dispatchEvent('remove', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.classList.remove('empty');
|
||||||
|
this._element.classList.remove('changed');
|
||||||
|
|
||||||
|
if (this._lastMode == 'new') {
|
||||||
|
if (this._previewUrl == '') this._removeElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
|
||||||
|
if (this._previewUrl) {
|
||||||
|
this._previewElement.style.backgroundImage = `url(${this._previewUrl})`;
|
||||||
|
} else {
|
||||||
|
this._previewElement.style.backgroundImage = 'none';
|
||||||
|
this._element.classList.add('empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
this._inputElement.value = "";
|
||||||
|
this._hiddenElement.value = "";
|
||||||
|
|
||||||
|
this._lastMode = 'saved';
|
||||||
|
} else if (this._lastMode == 'saved') {
|
||||||
|
if (this._previewUrl == '') this._removeElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
|
||||||
|
this._previewElement.style.backgroundImage = 'none';
|
||||||
|
this._element.classList.add('empty');
|
||||||
|
|
||||||
|
this._hiddenElement.value = "1";
|
||||||
|
this._inputElement.value = "";
|
||||||
|
|
||||||
|
this._lastMode = 'placeholder';
|
||||||
|
} else if (this._lastMode == 'placeholder') {
|
||||||
|
if (this._previewUrl == '') this._removeElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
|
||||||
|
if (this._previewUrl) {
|
||||||
|
this._previewElement.style.backgroundImage = `url(${this._previewUrl})`;
|
||||||
|
} else {
|
||||||
|
this._element.classList.add('empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
this._inputElement.value = "";
|
||||||
|
this._hiddenElement.value = "";
|
||||||
|
|
||||||
|
this._lastMode = 'saved';
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fireEvent('remove');
|
||||||
|
this._dispatchEvent('remove');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update() {
|
||||||
|
if (this._previewElement.style.backgroundImage) {
|
||||||
|
this._setPreviewUrl(this._previewElement.style.backgroundImage);
|
||||||
|
this._removeElement.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
this._lastMode = 'saved';
|
||||||
|
} else {
|
||||||
|
this._removeElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
this._element.classList.add('empty');
|
||||||
|
this._lastMode = 'placeholder';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getPreviewUrl(): string {
|
||||||
|
return this._previewUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _setPreviewUrl(url: string): void {
|
||||||
|
this._previewUrl = url.replace(/(url\(|\)|")/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
public isEmpty(): boolean {
|
||||||
|
return this._inputElement.value.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isChanged(): boolean {
|
||||||
|
return this._inputElement.value.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public remove(): void {
|
||||||
|
this._remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setPreviewUrl(url: string): void {
|
||||||
|
this._setPreviewUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPreviewUrl(): string {
|
||||||
|
return this._getPreviewUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTImageInput {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'image-input')) {
|
||||||
|
return KTData.get(element, 'image-input') as KTImageInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-image-input') === "true") {
|
||||||
|
return new KTImageInput(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTImageInputConfigInterface): KTImageInput {
|
||||||
|
return this.getInstance(element) || new KTImageInput(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-image-input="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTImageInput(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTImageInput.createInstances();
|
||||||
|
}
|
||||||
|
}
|
2
resources/metronic/core/components/image-input/index.ts
Normal file
2
resources/metronic/core/components/image-input/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTImageInput } from './image-input';
|
||||||
|
export type { KTImageInputConfigInterface, KTImageInputInterface } from './types';
|
7
resources/metronic/core/components/image-input/types.ts
Normal file
7
resources/metronic/core/components/image-input/types.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export interface KTImageInputConfigInterface {
|
||||||
|
hiddenClass: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTImageInputInterface {
|
||||||
|
remove(): void;
|
||||||
|
}
|
2
resources/metronic/core/components/menu/index.ts
Normal file
2
resources/metronic/core/components/menu/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTMenu } from './menu';
|
||||||
|
export type { KTMenuConfigInterface, KTMenuInterface } from './types';
|
1215
resources/metronic/core/components/menu/menu.ts
Normal file
1215
resources/metronic/core/components/menu/menu.ts
Normal file
File diff suppressed because it is too large
Load Diff
15
resources/metronic/core/components/menu/types.ts
Normal file
15
resources/metronic/core/components/menu/types.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export declare type KTMenuItemToggleType = 'dropdown' | 'accordion';
|
||||||
|
|
||||||
|
export declare type KTMenuItemTriggerType = 'hover' | 'click';
|
||||||
|
|
||||||
|
export interface KTMenuConfigInterface {
|
||||||
|
dropdownZindex: string,
|
||||||
|
dropdownHoverTimeout: number,
|
||||||
|
accordionExpandAll: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTMenuInterface {
|
||||||
|
disable(): void;
|
||||||
|
enable(): void;
|
||||||
|
update(): void;
|
||||||
|
}
|
2
resources/metronic/core/components/modal/index.ts
Normal file
2
resources/metronic/core/components/modal/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTModal } from './modal';
|
||||||
|
export type { KTModalConfigInterface, KTModalInterface } from './types';
|
344
resources/metronic/core/components/modal/modal.ts
Normal file
344
resources/metronic/core/components/modal/modal.ts
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTModalInterface, KTModalConfigInterface } from './types';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KT_MODAL_INITIALIZED: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KTModal extends KTComponent implements KTModalInterface {
|
||||||
|
protected override _name: string = 'modal';
|
||||||
|
protected override _defaultConfig: KTModalConfigInterface = {
|
||||||
|
zindex: '90',
|
||||||
|
backdrop: true,
|
||||||
|
backdropClass: 'transition-all duration-300 fixed inset-0 bg-gray-900 opacity-25',
|
||||||
|
backdropStatic: false,
|
||||||
|
keyboard: true,
|
||||||
|
disableScroll: true,
|
||||||
|
persistent: false,
|
||||||
|
focus: true,
|
||||||
|
hiddenClass: 'hidden'
|
||||||
|
};
|
||||||
|
protected override _config: KTModalConfigInterface = this._defaultConfig;
|
||||||
|
protected _isOpen: boolean = false;
|
||||||
|
protected _isTransitioning: boolean = false;
|
||||||
|
protected _backdropElement: HTMLElement | null = null;
|
||||||
|
protected _targetElement: HTMLElement | null = null;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTModalConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers() {
|
||||||
|
this._element.addEventListener('click', (event: Event) => {
|
||||||
|
if (this._element !== event.target ) return;
|
||||||
|
|
||||||
|
if (this._getOption('backdropStatic') === false) {
|
||||||
|
this._hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(targetElement?: HTMLElement): void {
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('toggle', payload);
|
||||||
|
this._dispatchEvent('toggle', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isOpen === true) {
|
||||||
|
this._hide();
|
||||||
|
} else {
|
||||||
|
this._show(targetElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _show(targetElement?: HTMLElement): void {
|
||||||
|
if (this._isOpen || this._isTransitioning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//const beforeScroll = this.fireEvent('beforeScroll', this.el);
|
||||||
|
//this.dispatch('beforeScroll.hs.scrollspy', this.el, this.el);
|
||||||
|
//if (beforeScroll instanceof Promise) beforeScroll.then(() => scrollFn());
|
||||||
|
//else scrollFn();
|
||||||
|
|
||||||
|
if (targetElement) this._targetElement = targetElement;
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('show', payload);
|
||||||
|
this._dispatchEvent('show', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KTModal.hide();
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
this._isTransitioning = true;
|
||||||
|
this._element.setAttribute('role', 'dialog');
|
||||||
|
this._element.setAttribute('aria-modal', 'true');
|
||||||
|
this._element.setAttribute('tabindex', '-1');
|
||||||
|
|
||||||
|
this._setZindex();
|
||||||
|
if (this._getOption('backdrop') === true) this._createBackdrop();
|
||||||
|
|
||||||
|
if (this._getOption('disableScroll')) {
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.style.display = 'block';
|
||||||
|
KTDom.reflow(this._element);
|
||||||
|
this._element.classList.add('open');
|
||||||
|
this._element.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._element, () => {
|
||||||
|
this._isTransitioning = false;
|
||||||
|
this._isOpen = true;
|
||||||
|
|
||||||
|
if (this._getOption('focus') === true) {
|
||||||
|
this._autoFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fireEvent('shown');
|
||||||
|
this._dispatchEvent('shown');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _hide(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
if (this._isOpen === false || this._isTransitioning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('hide', payload);
|
||||||
|
this._dispatchEvent('hide', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._isTransitioning = true;
|
||||||
|
this._element.removeAttribute('role');
|
||||||
|
this._element.removeAttribute('aria-modal');
|
||||||
|
this._element.removeAttribute('tabindex');
|
||||||
|
if (this._getOption('disableScroll')) {
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
KTDom.reflow(this._element);
|
||||||
|
this._element.classList.remove('open');
|
||||||
|
|
||||||
|
if (this._getOption('backdrop') === true) {
|
||||||
|
this._deleteBackdrop();
|
||||||
|
}
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._element, () => {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._isTransitioning = false;
|
||||||
|
this._isOpen = false;
|
||||||
|
this._element.style.display = '';
|
||||||
|
this._element.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
|
||||||
|
this._fireEvent('hidden');
|
||||||
|
this._dispatchEvent('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _setZindex(): void {
|
||||||
|
let zindex: number = parseInt(this._getOption('zindex') as string);
|
||||||
|
|
||||||
|
if (parseInt(KTDom.getCssProp(this._element, 'z-index')) > zindex) {
|
||||||
|
zindex = parseInt(KTDom.getCssProp(this._element, 'z-index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KTDom.getHighestZindex(this._element) > zindex) {
|
||||||
|
zindex =KTDom.getHighestZindex(this._element) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.style.zIndex = String(zindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _autoFocus(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const input: HTMLInputElement | null = this._element.querySelector('[data-modal-input-focus]');
|
||||||
|
if (!input) return; else input.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _createBackdrop(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const zindex: number = parseInt(KTDom.getCssProp(this._element, 'z-index'));
|
||||||
|
this._backdropElement = document.createElement('DIV');
|
||||||
|
this._backdropElement.style.zIndex = (zindex - 1).toString();
|
||||||
|
this._backdropElement.classList.add('modal-backdrop');
|
||||||
|
document.body.append(this._backdropElement);
|
||||||
|
KTDom.reflow(this._backdropElement);
|
||||||
|
KTDom.addClass(this._backdropElement, this._getOption('backdropClass') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _deleteBackdrop(): void {
|
||||||
|
if (!this._backdropElement) return;
|
||||||
|
|
||||||
|
KTDom.reflow(this._backdropElement);
|
||||||
|
this._backdropElement.style.opacity = "0";
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._backdropElement, () => {
|
||||||
|
if (!this._backdropElement) return;
|
||||||
|
KTDom.remove(this._backdropElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle(targetElement?: HTMLElement): void {
|
||||||
|
return this._toggle(targetElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public show(targetElement?: HTMLElement): void {
|
||||||
|
return this._show(targetElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public hide(): void {
|
||||||
|
return this._hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTargetElement(): HTMLElement | null {
|
||||||
|
return this._targetElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOpen(): boolean {
|
||||||
|
return this._isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTModal {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'modal')) {
|
||||||
|
return KTData.get(element, 'modal') as KTModal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-modal') === "true") {
|
||||||
|
return new KTModal(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTModalConfigInterface): KTModal {
|
||||||
|
return this.getInstance(element) || new KTModal(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static hide(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-modal]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
const modal = KTModal.getInstance(element as HTMLElement);
|
||||||
|
|
||||||
|
if (modal && modal.isOpen()) {
|
||||||
|
modal.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleToggle(): void {
|
||||||
|
KTEventHandler.on(document.body, '[data-modal-toggle]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const selector = target.getAttribute("data-modal-toggle");
|
||||||
|
if (!selector) return;
|
||||||
|
|
||||||
|
const modalElement = document.querySelector(selector);
|
||||||
|
const modal = KTModal.getInstance(modalElement as HTMLElement);
|
||||||
|
if (modal) {
|
||||||
|
modal.toggle(target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleDismiss(): void {
|
||||||
|
KTEventHandler.on(document.body, '[data-modal-dismiss]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const modalElement = target.closest('[data-modal]') as HTMLElement;
|
||||||
|
if (modalElement) {
|
||||||
|
const modal = KTModal.getInstance(modalElement);
|
||||||
|
if (modal) {
|
||||||
|
modal.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleClickAway() {
|
||||||
|
document.addEventListener('click', (event: Event) => {
|
||||||
|
const modalElement = document.querySelector('.open[data-modal]');
|
||||||
|
if (!modalElement) return;
|
||||||
|
|
||||||
|
const modal = KTModal.getInstance(modalElement as HTMLElement);
|
||||||
|
if (!modal) return;
|
||||||
|
|
||||||
|
if (modal.getOption('persistent')) return;
|
||||||
|
|
||||||
|
if (modal.getOption('backdrop')) return;
|
||||||
|
|
||||||
|
if (modalElement !== event.target &&
|
||||||
|
modal.getTargetElement() !== event.target &&
|
||||||
|
modalElement.contains(event.target as HTMLElement) === false) {
|
||||||
|
modal.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleKeyword() {
|
||||||
|
document.addEventListener('keydown', (event: KeyboardEvent) => {
|
||||||
|
const modalElement = document.querySelector('.open[data-modal]');
|
||||||
|
const modal = KTModal.getInstance(modalElement as HTMLElement);
|
||||||
|
if (!modal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if esc key was not pressed in combination with ctrl or alt or shift
|
||||||
|
if (event.key === 'Escape' && !(event.ctrlKey || event.altKey || event.shiftKey)) {
|
||||||
|
modal.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.code === 'Tab' && !event.metaKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-modal="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTModal(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTModal.createInstances();
|
||||||
|
|
||||||
|
if (window.KT_MODAL_INITIALIZED !== true) {
|
||||||
|
KTModal.handleToggle();
|
||||||
|
KTModal.handleDismiss();
|
||||||
|
KTModal.handleClickAway();
|
||||||
|
KTModal.handleKeyword();
|
||||||
|
window.KT_MODAL_INITIALIZED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
resources/metronic/core/components/modal/types.ts
Normal file
16
resources/metronic/core/components/modal/types.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export interface KTModalConfigInterface {
|
||||||
|
zindex?: string,
|
||||||
|
backdrop: boolean,
|
||||||
|
backdropClass: string,
|
||||||
|
backdropStatic: boolean,
|
||||||
|
keyboard: boolean,
|
||||||
|
disableScroll: boolean,
|
||||||
|
persistent: boolean;
|
||||||
|
focus: boolean;
|
||||||
|
hiddenClass: string;
|
||||||
|
}
|
||||||
|
export interface KTModalInterface {
|
||||||
|
show(): void;
|
||||||
|
hide(): void;
|
||||||
|
toggle(): void;
|
||||||
|
}
|
2
resources/metronic/core/components/reparent/index.ts
Normal file
2
resources/metronic/core/components/reparent/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTReparent } from './reparent';
|
||||||
|
export type { KTReparentConfigInterface, KTReparentInterface } from './types';
|
89
resources/metronic/core/components/reparent/reparent.ts
Normal file
89
resources/metronic/core/components/reparent/reparent.ts
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTUtils from '../../helpers/utils';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTReparentInterface, KTReparentConfigInterface } from './types';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KT_REPARENT_INITIALIZED: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KTReparent extends KTComponent implements KTReparentInterface {
|
||||||
|
protected override _name: string = 'reparent';
|
||||||
|
protected override _defaultConfig: KTReparentConfigInterface = {
|
||||||
|
mode: '',
|
||||||
|
target: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTReparentConfigInterface | null = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const target = this._getOption('target') as string;
|
||||||
|
const targetEl = KTDom.getElement(target);
|
||||||
|
const mode = this._getOption('mode');
|
||||||
|
|
||||||
|
if (targetEl && this._element.parentNode !== targetEl) {
|
||||||
|
if (mode === 'prepend') {
|
||||||
|
targetEl.prepend(this._element);
|
||||||
|
} else if (mode === 'append') {
|
||||||
|
targetEl.append(this._element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleResize(): void {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
let timer;
|
||||||
|
|
||||||
|
KTUtils.throttle(timer, () => {
|
||||||
|
document.querySelectorAll('[data-reparent]').forEach((element) => {
|
||||||
|
const reparent = KTReparent.getInstance(element as HTMLElement);
|
||||||
|
reparent?.update();
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTReparent {
|
||||||
|
return KTData.get(element, 'reparent') as KTReparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTReparentConfigInterface): KTReparent {
|
||||||
|
return this.getInstance(element) || new KTReparent(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-reparent="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTReparent(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTReparent.createInstances();
|
||||||
|
|
||||||
|
if (window.KT_REPARENT_INITIALIZED !== true) {
|
||||||
|
KTReparent.handleResize();
|
||||||
|
window.KT_REPARENT_INITIALIZED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
resources/metronic/core/components/reparent/types.ts
Normal file
10
resources/metronic/core/components/reparent/types.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export declare type KTOverlayModeType = 'drawer' | 'modal' | 'popover';
|
||||||
|
|
||||||
|
export interface KTReparentConfigInterface {
|
||||||
|
mode: string,
|
||||||
|
target: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTReparentInterface {
|
||||||
|
update(): void;
|
||||||
|
}
|
2
resources/metronic/core/components/scrollable/index.ts
Normal file
2
resources/metronic/core/components/scrollable/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTScrollable } from './scrollable';
|
||||||
|
export type { KTScrollableConfigInterface, KTScrollableInterface } from './types';
|
271
resources/metronic/core/components/scrollable/scrollable.ts
Normal file
271
resources/metronic/core/components/scrollable/scrollable.ts
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTUtils from '../../helpers/utils';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTScrollableInterface, KTScrollableConfigInterface } from './types';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KT_SCROLL_INITIALIZED: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KTScrollable extends KTComponent implements KTScrollableInterface {
|
||||||
|
protected override _name: string = 'scrollable';
|
||||||
|
protected override _defaultConfig: KTScrollableConfigInterface = {
|
||||||
|
save: true,
|
||||||
|
dependencies: '',
|
||||||
|
wrappers: '',
|
||||||
|
offset: '',
|
||||||
|
};
|
||||||
|
protected override _config: KTScrollableConfigInterface = this._defaultConfig;
|
||||||
|
protected _elementId: string | null = null;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTScrollableConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
this._elementId = this._element.getAttribute('id');
|
||||||
|
this._handlers();
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
this._element.addEventListener('scroll', () => {
|
||||||
|
if (!this._element) return;
|
||||||
|
localStorage.setItem(`${this._elementId}st`, this._element.scrollTop.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update(): void {
|
||||||
|
this._setupHeight();
|
||||||
|
this._setupState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _setupHeight(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const heightType = this._getHeightType();
|
||||||
|
const height = this._getHeight();
|
||||||
|
|
||||||
|
// Set height
|
||||||
|
if (height && height.length > 0) {
|
||||||
|
this._element.style.setProperty(heightType, height);
|
||||||
|
} else {
|
||||||
|
this._element.style.setProperty(heightType, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _setupState(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const stateEnabled = this._getOption('state') === true;
|
||||||
|
const elementIdExists = Boolean(this._elementId);
|
||||||
|
|
||||||
|
if (stateEnabled && elementIdExists) {
|
||||||
|
const storedPosition = localStorage.getItem(this._elementId + 'st');
|
||||||
|
|
||||||
|
if (storedPosition) {
|
||||||
|
const pos = parseInt(storedPosition);
|
||||||
|
|
||||||
|
if (pos > 0) {
|
||||||
|
this._element.scroll({
|
||||||
|
top: pos,
|
||||||
|
behavior: 'instant'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getHeight(): string {
|
||||||
|
const height = this._getHeightOption();
|
||||||
|
|
||||||
|
if (height !== null && typeof height === 'string' && height.toLowerCase() === 'auto') {
|
||||||
|
return this._getAutoHeight();
|
||||||
|
} else if (height) {
|
||||||
|
return parseInt(height).toString() + 'px';
|
||||||
|
} else {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getAutoHeight(): string {
|
||||||
|
if (!this._element) return '';
|
||||||
|
let height = KTDom.getViewPort().height;
|
||||||
|
const dependencies = this._getOption('dependencies') as string;
|
||||||
|
const wrappers = this._getOption('wrappers') as string;
|
||||||
|
const offset = this._getOption('offset') as string;
|
||||||
|
height -= this._getElementSpacing(this._element);
|
||||||
|
|
||||||
|
if (dependencies && dependencies.length > 0) {
|
||||||
|
const elements = document.querySelectorAll(dependencies);
|
||||||
|
elements.forEach((element) => {
|
||||||
|
if (KTDom.getCssProp(element as HTMLElement, 'display') === 'none') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
height -= this._getElementHeight(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wrappers && wrappers.length > 0) {
|
||||||
|
const elements = document.querySelectorAll(wrappers);
|
||||||
|
elements.forEach((element) => {
|
||||||
|
if (KTDom.getCssProp(element as HTMLElement, 'display') === 'none') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
height -= this._getElementSpacing(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset && offset.length > 0) {
|
||||||
|
height -= parseInt(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return height.toString() + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getElementHeight(element: HTMLElement): number {
|
||||||
|
let height = 0;
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
const computedStyle = window.getComputedStyle(element);
|
||||||
|
if (computedStyle.height) {
|
||||||
|
height += parseInt(computedStyle.height);
|
||||||
|
}
|
||||||
|
if (computedStyle.marginTop) {
|
||||||
|
height += parseInt(computedStyle.marginTop);
|
||||||
|
}
|
||||||
|
if (computedStyle.marginBottom) {
|
||||||
|
height += parseInt(computedStyle.marginBottom);
|
||||||
|
}
|
||||||
|
if (computedStyle.borderTopWidth) {
|
||||||
|
height += parseInt(computedStyle.borderTopWidth);
|
||||||
|
}
|
||||||
|
if (computedStyle.borderBottomWidth) {
|
||||||
|
height += parseInt(computedStyle.borderBottomWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getElementSpacing(element: HTMLElement): number {
|
||||||
|
let spacing: number = 0;
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
return spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
const computedStyle = window.getComputedStyle(element);
|
||||||
|
if (computedStyle.marginTop) {
|
||||||
|
spacing += parseInt(computedStyle.marginTop);
|
||||||
|
}
|
||||||
|
if (computedStyle.marginBottom) {
|
||||||
|
spacing += parseInt(computedStyle.marginBottom);
|
||||||
|
}
|
||||||
|
if (computedStyle.paddingTop) {
|
||||||
|
spacing += parseInt(computedStyle.paddingTop);
|
||||||
|
}
|
||||||
|
if (computedStyle.paddingBottom) {
|
||||||
|
spacing += parseInt(computedStyle.paddingBottom);
|
||||||
|
}
|
||||||
|
if (computedStyle.borderTopWidth) {
|
||||||
|
spacing += parseInt(computedStyle.borderTopWidth);
|
||||||
|
}
|
||||||
|
if (computedStyle.borderBottomWidth) {
|
||||||
|
spacing += parseInt(computedStyle.borderBottomWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
return spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getHeightType(): string {
|
||||||
|
if (this._getOption('minHeight')) {
|
||||||
|
return 'min-height';
|
||||||
|
} if (this._getOption('maxHeight')) {
|
||||||
|
return 'max-height';
|
||||||
|
} else {
|
||||||
|
return 'height';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getHeightOption(): string {
|
||||||
|
const heightType = this._getHeightType();
|
||||||
|
|
||||||
|
if (heightType == 'min-height') {
|
||||||
|
return this._getOption('minHeight') as string;
|
||||||
|
} if (heightType == 'max-height') {
|
||||||
|
return this._getOption('maxHeight') as string;
|
||||||
|
} else {
|
||||||
|
return this._getOption('height') as string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
return this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getHeight(): string {
|
||||||
|
return this._getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTScrollable {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'scrollable')) {
|
||||||
|
return KTData.get(element, 'scrollable') as KTScrollable;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-scrollable') === "true") {
|
||||||
|
return new KTScrollable(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTScrollableConfigInterface): KTScrollable {
|
||||||
|
return this.getInstance(element) || new KTScrollable(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-scrollable="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTScrollable(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleResize(): void {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
let timer;
|
||||||
|
|
||||||
|
KTUtils.throttle(timer, function () {
|
||||||
|
// Locate and update scrollable instances on window resize
|
||||||
|
const elements = document.querySelectorAll('[data-scrollable]');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
KTScrollable.getInstance(element as HTMLElement)?.update();
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTScrollable.createInstances();
|
||||||
|
|
||||||
|
if (window.KT_SCROLL_INITIALIZED !== true) {
|
||||||
|
KTScrollable.handleResize();
|
||||||
|
|
||||||
|
window.KT_SCROLL_INITIALIZED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
resources/metronic/core/components/scrollable/types.ts
Normal file
11
resources/metronic/core/components/scrollable/types.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface KTScrollableConfigInterface {
|
||||||
|
save: boolean,
|
||||||
|
dependencies: string,
|
||||||
|
wrappers: string,
|
||||||
|
offset: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTScrollableInterface {
|
||||||
|
update(): void;
|
||||||
|
getHeight(): string;
|
||||||
|
}
|
2
resources/metronic/core/components/scrollspy/index.ts
Normal file
2
resources/metronic/core/components/scrollspy/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTScrollspy } from './scrollspy';
|
||||||
|
export type { KTScrollspyConfigInterface, KTScrollspyInterface } from './types';
|
182
resources/metronic/core/components/scrollspy/scrollspy.ts
Normal file
182
resources/metronic/core/components/scrollspy/scrollspy.ts
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTScrollspyInterface, KTScrollspyConfigInterface } from './types';
|
||||||
|
|
||||||
|
export class KTScrollspy extends KTComponent implements KTScrollspyInterface {
|
||||||
|
protected override _name: string = 'scrollspy';
|
||||||
|
protected override _defaultConfig: KTScrollspyConfigInterface = {
|
||||||
|
target: 'body',
|
||||||
|
offset: 0,
|
||||||
|
smooth: true
|
||||||
|
};
|
||||||
|
protected override _config: KTScrollspyConfigInterface = this._defaultConfig;
|
||||||
|
protected _targetElement: HTMLElement | Document | null = null;
|
||||||
|
protected _anchorElements: NodeListOf<HTMLElement> | null = null;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTScrollspyConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
const targetElement = this._getTarget() === 'body' ? document : KTDom.getElement(this._getTarget());
|
||||||
|
if (!targetElement) return;
|
||||||
|
|
||||||
|
this._targetElement = targetElement;
|
||||||
|
|
||||||
|
this._anchorElements = this._element.querySelectorAll('[data-scrollspy-anchor]');
|
||||||
|
|
||||||
|
if (!this._anchorElements) return;
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTarget(): string {
|
||||||
|
return (this._element.getAttribute('data-scrollspy-target') as string || this._getOption('target') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._anchorElements) return;
|
||||||
|
|
||||||
|
this._targetElement.addEventListener('scroll', () => {
|
||||||
|
this._anchorElements.forEach((anchorElement) => {
|
||||||
|
this._updateAnchor(anchorElement);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
KTEventHandler.on(this._element, '[data-scrollspy-anchor]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this._scrollTo(target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _scrollTo(anchorElement: HTMLElement): void {
|
||||||
|
if (!anchorElement) return;
|
||||||
|
|
||||||
|
const sectionElement = KTDom.getElement(anchorElement.getAttribute('href'));
|
||||||
|
if (!sectionElement) return;
|
||||||
|
|
||||||
|
const targetElement = this._targetElement === document ? window : this._targetElement;
|
||||||
|
if (!targetElement) return;
|
||||||
|
|
||||||
|
let offset = parseInt(this._getOption('offset') as string);
|
||||||
|
if (anchorElement.getAttribute('data-scrollspy-anchor-offset')) {
|
||||||
|
offset = parseInt(anchorElement.getAttribute('data-scrollspy-anchor-offset') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
const scrollTop = sectionElement.offsetTop - offset;
|
||||||
|
|
||||||
|
if ('scrollTo' in targetElement) {
|
||||||
|
targetElement.scrollTo({
|
||||||
|
top: scrollTop,
|
||||||
|
left: 0,
|
||||||
|
behavior: this._getOption('smooth') ? 'smooth' : 'instant',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _updateAnchor(anchorElement: HTMLElement): void {
|
||||||
|
const sectionElement = KTDom.getElement(anchorElement.getAttribute('href'));
|
||||||
|
if (!sectionElement) return;
|
||||||
|
|
||||||
|
if (!KTDom.isVisible(anchorElement)) return;
|
||||||
|
|
||||||
|
if (!this._anchorElements) return;
|
||||||
|
|
||||||
|
const scrollPosition = this._targetElement === document ? (document.documentElement.scrollTop || document.body.scrollTop) : (this._targetElement as HTMLElement).scrollTop;
|
||||||
|
|
||||||
|
let offset = parseInt(this._getOption('offset') as string);
|
||||||
|
if (anchorElement.getAttribute('data-scrollspy-anchor-offset')) {
|
||||||
|
offset = parseInt(anchorElement.getAttribute('data-scrollspy-anchor-offset') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
const offsetTop = sectionElement.offsetTop;
|
||||||
|
|
||||||
|
if ((scrollPosition + offset) >= offsetTop) {
|
||||||
|
this._anchorElements.forEach((anchorElement) => {
|
||||||
|
anchorElement.classList.remove('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
const payload = { element: anchorElement };
|
||||||
|
this._fireEvent('activate', payload);
|
||||||
|
this._dispatchEvent('activate', payload);
|
||||||
|
|
||||||
|
anchorElement.classList.add('active');
|
||||||
|
|
||||||
|
const parentAnchorElements = KTDom.parents(anchorElement, '[data-scrollspy-group]');
|
||||||
|
if (parentAnchorElements) {
|
||||||
|
parentAnchorElements.forEach((parentAnchorElement) => {
|
||||||
|
parentAnchorElement.querySelector('[data-scrollspy-anchor]')?.classList.add('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update() {
|
||||||
|
if (!this._anchorElements) return;
|
||||||
|
|
||||||
|
this._anchorElements.forEach((anchorElement) => {
|
||||||
|
this._updateAnchor(anchorElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _isActive(anchorElement: HTMLElement): boolean {
|
||||||
|
return anchorElement.classList.contains('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateAnchor(anchorElement: HTMLElement): void {
|
||||||
|
this._updateAnchor(anchorElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isActive(anchorElement: HTMLElement): boolean {
|
||||||
|
return this._isActive(anchorElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public scrollTo(anchorElement: HTMLElement): void {
|
||||||
|
this._scrollTo(anchorElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTScrollspy {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'scrollspy')) {
|
||||||
|
return KTData.get(element, 'scrollspy') as KTScrollspy;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-scrollspy') === "true") {
|
||||||
|
return new KTScrollspy(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTScrollspyConfigInterface): KTScrollspy {
|
||||||
|
return this.getInstance(element) || new KTScrollspy(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-scrollspy="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTScrollspy(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTScrollspy.createInstances();
|
||||||
|
}
|
||||||
|
}
|
10
resources/metronic/core/components/scrollspy/types.ts
Normal file
10
resources/metronic/core/components/scrollspy/types.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface KTScrollspyConfigInterface {
|
||||||
|
target: string,
|
||||||
|
smooth: boolean,
|
||||||
|
offset: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTScrollspyInterface {
|
||||||
|
update(anchorElement: HTMLElement, event: Event): void;
|
||||||
|
scrollTo(anchorElement: HTMLElement): void;
|
||||||
|
}
|
2
resources/metronic/core/components/scrollto/index.ts
Normal file
2
resources/metronic/core/components/scrollto/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTScrollto } from './scrollto';
|
||||||
|
export type { KTScrolltoConfigInterface, KTScrolltoInterface } from './types';
|
103
resources/metronic/core/components/scrollto/scrollto.ts
Normal file
103
resources/metronic/core/components/scrollto/scrollto.ts
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTScrolltoInterface, KTScrolltoConfigInterface } from './types';
|
||||||
|
|
||||||
|
export class KTScrollto extends KTComponent implements KTScrolltoInterface {
|
||||||
|
protected override _name: string = 'scrollto';
|
||||||
|
protected override _defaultConfig: KTScrolltoConfigInterface = {
|
||||||
|
smooth: true,
|
||||||
|
parent: 'body',
|
||||||
|
target: '',
|
||||||
|
offset: 0,
|
||||||
|
};
|
||||||
|
protected override _config: KTScrolltoConfigInterface = this._defaultConfig;
|
||||||
|
protected _targetElement: HTMLElement;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTScrolltoConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._targetElement = this._getTargetElement();
|
||||||
|
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTargetElement(): HTMLElement | null {
|
||||||
|
return (
|
||||||
|
KTDom.getElement(this._element.getAttribute('data-scrollto') as string) ||
|
||||||
|
KTDom.getElement(this._getOption('target') as string)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._element.addEventListener('click', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this._scroll();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _scroll(): void {
|
||||||
|
const pos = this._targetElement.offsetTop + parseInt(this._getOption('offset') as string);
|
||||||
|
|
||||||
|
let parent: HTMLElement | Window = KTDom.getElement(this._getOption('parent') as string);
|
||||||
|
|
||||||
|
if (!parent || parent === document.body) {
|
||||||
|
parent = window;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.scrollTo({
|
||||||
|
top: pos,
|
||||||
|
behavior: (this._getOption('smooth') as boolean) ? 'smooth' : 'instant',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public scroll(): void {
|
||||||
|
this._scroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTScrollto {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'scrollto')) {
|
||||||
|
return KTData.get(element, 'scrollto') as KTScrollto;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-scrollto') !== "false") {
|
||||||
|
return new KTScrollto(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTScrolltoConfigInterface): KTScrollto {
|
||||||
|
return this.getInstance(element) || new KTScrollto(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-scrollto]:not([data-scrollto="false"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTScrollto(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTScrollto.createInstances();
|
||||||
|
}
|
||||||
|
};
|
10
resources/metronic/core/components/scrollto/types.ts
Normal file
10
resources/metronic/core/components/scrollto/types.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface KTScrolltoConfigInterface {
|
||||||
|
smooth: boolean,
|
||||||
|
parent: string,
|
||||||
|
target: string,
|
||||||
|
offset: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTScrolltoInterface {
|
||||||
|
scroll(): void;
|
||||||
|
}
|
2
resources/metronic/core/components/stepper/index.ts
Normal file
2
resources/metronic/core/components/stepper/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTStepper } from './stepper';
|
||||||
|
export type { KTStepperConfigInterface, KTStepperInterface } from './types';
|
282
resources/metronic/core/components/stepper/stepper.ts
Normal file
282
resources/metronic/core/components/stepper/stepper.ts
Normal file
@ -0,0 +1,282 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTStepperInterface, KTStepperConfigInterface } from './types';
|
||||||
|
|
||||||
|
export class KTStepper extends KTComponent implements KTStepperInterface {
|
||||||
|
protected override _name: string = 'stepper';
|
||||||
|
protected override _defaultConfig: KTStepperConfigInterface = {
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
activeStep: 1
|
||||||
|
};
|
||||||
|
protected override _config: KTStepperConfigInterface = this._defaultConfig;
|
||||||
|
protected _activeStep: number = 0;
|
||||||
|
protected _nextElement: HTMLElement | null = null;
|
||||||
|
protected _backElement: HTMLElement | null = null;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTStepperConfigInterface | null = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
this._nextElement = this._element.querySelector('[data-stepper-next]');
|
||||||
|
this._backElement = this._element.querySelector('[data-stepper-back]');
|
||||||
|
|
||||||
|
this._activeStep = 1;
|
||||||
|
if (this._getOption('activeStep') !== this._activeStep) {
|
||||||
|
this._go(this._getOption('activeStep') as number);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._update();
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._nextElement) {
|
||||||
|
console.error('data-stepper-next not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._nextElement) {
|
||||||
|
this._nextElement.addEventListener('click', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this._goNext()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._backElement) {
|
||||||
|
this._backElement.addEventListener('click', (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this._goBack()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
let state = '';
|
||||||
|
|
||||||
|
if (this._activeStep === this._getTotalSteps()) {
|
||||||
|
state = 'last';
|
||||||
|
} else if (this._activeStep === 1) {
|
||||||
|
state = 'first';
|
||||||
|
} else {
|
||||||
|
state = 'between';
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.classList.remove('first');
|
||||||
|
this._element.classList.remove('last');
|
||||||
|
this._element.classList.remove('between');
|
||||||
|
this._element.classList.add(state);
|
||||||
|
|
||||||
|
this._getItemElements().forEach((element, index) => {
|
||||||
|
const contentElement = KTDom.getElement(element.getAttribute('data-stepper-item'));
|
||||||
|
if (!contentElement) return;
|
||||||
|
|
||||||
|
element.classList.remove('active');
|
||||||
|
element.classList.remove('completed');
|
||||||
|
element.classList.remove('pending');
|
||||||
|
|
||||||
|
const numberElement = element.querySelector('[data-stepper-number]');
|
||||||
|
if (numberElement) numberElement.innerHTML = String(index + 1);
|
||||||
|
|
||||||
|
if (index + 1 == this._activeStep) {
|
||||||
|
element.classList.add('active');
|
||||||
|
contentElement.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
} else {
|
||||||
|
contentElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
if (index + 1 < this._activeStep) {
|
||||||
|
element.classList.add('completed');
|
||||||
|
} else {
|
||||||
|
element.classList.add('pending');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getItemElements(): Array<HTMLElement> {
|
||||||
|
const elements: Array<HTMLElement> = [];
|
||||||
|
|
||||||
|
this._element.querySelectorAll('[data-stepper-item]').forEach((element) => {
|
||||||
|
if (KTDom.isVisible(element as HTMLElement)) {
|
||||||
|
elements.push(element as HTMLElement);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _go(step: number): void {
|
||||||
|
if (step === this._activeStep || step > this._getTotalSteps() || step < 0) return;
|
||||||
|
|
||||||
|
const payload = { step: step, cancel: false };
|
||||||
|
this._fireEvent('change', payload);
|
||||||
|
this._dispatchEvent('change', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._activeStep = step;
|
||||||
|
this._update();
|
||||||
|
|
||||||
|
this._fireEvent('changed');
|
||||||
|
this._dispatchEvent('changed');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _goTo(itemElement: HTMLElement): void {
|
||||||
|
const step = this._getStep(itemElement);
|
||||||
|
this._go(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getStep(itemElement: HTMLElement): number {
|
||||||
|
let step = -1;
|
||||||
|
|
||||||
|
this._getItemElements().forEach((element, index) => {
|
||||||
|
if (element === itemElement) {
|
||||||
|
step = index + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getItemElement(step: number) {
|
||||||
|
return this._getItemElements()[step - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getTotalSteps(): number {
|
||||||
|
return this._getItemElements().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _goNext(): void {
|
||||||
|
let step;
|
||||||
|
|
||||||
|
if (this._getTotalSteps() >= (this._activeStep + 1)) {
|
||||||
|
step = this._activeStep + 1;
|
||||||
|
} else {
|
||||||
|
step = this._getTotalSteps();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._go(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _goBack(): void {
|
||||||
|
let step;
|
||||||
|
|
||||||
|
if ((this._activeStep - 1) > 1) {
|
||||||
|
step = this._activeStep - 1;
|
||||||
|
} else {
|
||||||
|
step = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._go(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _goLast(): void {
|
||||||
|
const step = this._getTotalSteps();
|
||||||
|
this._go(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _goFirst(): void {
|
||||||
|
const step = 1;
|
||||||
|
this._go(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _isLast(): boolean {
|
||||||
|
return this._getTotalSteps() === this._activeStep + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _isFirst(): boolean {
|
||||||
|
return this._activeStep === 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isLast(): boolean {
|
||||||
|
return this._isLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
public isFirst(): boolean {
|
||||||
|
return this._isFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public go(step: number): void {
|
||||||
|
this._go(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
public goTo(itemElement: HTMLElement): void {
|
||||||
|
this.goTo(itemElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public goFirst(): void {
|
||||||
|
this._goFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public goLast(): void {
|
||||||
|
this._goLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
public goNext(): void {
|
||||||
|
this._goNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public goBack(): void {
|
||||||
|
this._goBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getStep(itemElement: HTMLElement): number {
|
||||||
|
return this._getStep(itemElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getItemElement(step: number): HTMLElement {
|
||||||
|
return this._getItemElement(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTotalSteps(): number {
|
||||||
|
return this._getTotalSteps();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getItemElements(): Array<HTMLElement> {
|
||||||
|
return this._getItemElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTStepper {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'stepper')) {
|
||||||
|
return KTData.get(element, 'stepper') as KTStepper;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-stepper') === "true") {
|
||||||
|
return new KTStepper(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTStepperConfigInterface): KTStepper | null {
|
||||||
|
return this.getInstance(element) || new KTStepper(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-stepper="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTStepper(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTStepper.createInstances();
|
||||||
|
}
|
||||||
|
}
|
8
resources/metronic/core/components/stepper/types.ts
Normal file
8
resources/metronic/core/components/stepper/types.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export interface KTStepperConfigInterface {
|
||||||
|
hiddenClass: string,
|
||||||
|
activeStep: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTStepperInterface {
|
||||||
|
go(step: number): void;
|
||||||
|
}
|
2
resources/metronic/core/components/sticky/index.ts
Normal file
2
resources/metronic/core/components/sticky/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTSticky } from './sticky';
|
||||||
|
export type { KTStickyConfigInterface, KTStickyInterface } from './types';
|
333
resources/metronic/core/components/sticky/sticky.ts
Normal file
333
resources/metronic/core/components/sticky/sticky.ts
Normal file
@ -0,0 +1,333 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTUtils from '../../helpers/utils';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTStickyInterface, KTStickyConfigInterface } from './types';
|
||||||
|
|
||||||
|
export class KTSticky extends KTComponent implements KTStickyInterface {
|
||||||
|
protected override _name: string = 'sticky';
|
||||||
|
protected override _defaultConfig: KTStickyConfigInterface = {
|
||||||
|
name: '',
|
||||||
|
class: '',
|
||||||
|
top: '',
|
||||||
|
left: '',
|
||||||
|
right: '',
|
||||||
|
width: '',
|
||||||
|
zindex: '',
|
||||||
|
offset: 0,
|
||||||
|
reverse: false,
|
||||||
|
release: '',
|
||||||
|
activate: ''
|
||||||
|
};
|
||||||
|
protected override _config: KTStickyConfigInterface = this._defaultConfig;
|
||||||
|
protected _attributeRoot: string;
|
||||||
|
protected _eventTriggerState: boolean;
|
||||||
|
protected _lastScrollTop: number;
|
||||||
|
protected _releaseElement: HTMLElement;
|
||||||
|
protected _wrapperElement: HTMLElement;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTStickyConfigInterface | null = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._releaseElement = KTDom.getElement(this._getOption('release') as string);
|
||||||
|
this._wrapperElement = this._element.closest('[data-sticky-wrapper]');
|
||||||
|
this._attributeRoot = `data-sticky-${this._getOption('name')}`;
|
||||||
|
this._eventTriggerState = true;
|
||||||
|
this._lastScrollTop = 0;
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
this._process();
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
let timer;
|
||||||
|
|
||||||
|
KTUtils.throttle(
|
||||||
|
timer,
|
||||||
|
() => {
|
||||||
|
this._update();
|
||||||
|
},
|
||||||
|
200
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('scroll', () => {
|
||||||
|
this._process();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _process(): void {
|
||||||
|
const reverse = this._getOption('reverse');
|
||||||
|
const activateOffset = this._getActivateOffset();
|
||||||
|
const releaseOffset = this._getReleaseOffset();
|
||||||
|
|
||||||
|
if (activateOffset < 0) {
|
||||||
|
this._disable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const st = KTDom.getScrollTop();
|
||||||
|
const proceed = (!this._releaseElement || releaseOffset > st);
|
||||||
|
|
||||||
|
// Release on reverse scroll mode
|
||||||
|
if (reverse === true) {
|
||||||
|
// Forward scroll mode
|
||||||
|
if (st > activateOffset && proceed) {
|
||||||
|
if (document.body.hasAttribute(this._attributeRoot) === false) {
|
||||||
|
if (this._enable() === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.setAttribute(this._attributeRoot, 'on');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._eventTriggerState === true) {
|
||||||
|
const payload = { active: true };
|
||||||
|
this._fireEvent('change', payload);
|
||||||
|
this._dispatchEvent('change', payload);
|
||||||
|
this._eventTriggerState = false;
|
||||||
|
}
|
||||||
|
// Back scroll mode
|
||||||
|
} else {
|
||||||
|
if (document.body.hasAttribute(this._attributeRoot) === true) {
|
||||||
|
this._disable();
|
||||||
|
document.body.removeAttribute(this._attributeRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._eventTriggerState === false) {
|
||||||
|
const payload = { active: false };
|
||||||
|
this._fireEvent('change', payload);
|
||||||
|
this._dispatchEvent('change', payload);
|
||||||
|
this._eventTriggerState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._lastScrollTop = st;
|
||||||
|
// Classic scroll mode
|
||||||
|
} else {
|
||||||
|
// Forward scroll mode
|
||||||
|
if (st > activateOffset && proceed) {
|
||||||
|
if (document.body.hasAttribute(this._attributeRoot) === false) {
|
||||||
|
if (this._enable() === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.body.setAttribute(this._attributeRoot, 'on');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._eventTriggerState === true) {
|
||||||
|
const payload = { active: true };
|
||||||
|
this._fireEvent('change', payload);
|
||||||
|
this._dispatchEvent('change', payload);
|
||||||
|
this._eventTriggerState = false;
|
||||||
|
}
|
||||||
|
// Back scroll mode
|
||||||
|
} else { // back scroll mode
|
||||||
|
if (document.body.hasAttribute(this._attributeRoot) === true) {
|
||||||
|
this._disable();
|
||||||
|
document.body.removeAttribute(this._attributeRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._eventTriggerState === false) {
|
||||||
|
const payload = { active: false };
|
||||||
|
this._fireEvent('change', payload);
|
||||||
|
this._dispatchEvent('change', payload);
|
||||||
|
this._eventTriggerState = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getActivateOffset(): number {
|
||||||
|
let offset = parseInt(this._getOption('offset') as string);
|
||||||
|
const activateElement = KTDom.getElement(this._getOption('activate') as string);
|
||||||
|
|
||||||
|
if (activateElement) {
|
||||||
|
offset = Math.abs(offset - activateElement.offsetTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getReleaseOffset(): number {
|
||||||
|
let offset = parseInt(this._getOption('offset') as string);
|
||||||
|
|
||||||
|
if (this._releaseElement && this._releaseElement.offsetTop) {
|
||||||
|
offset = Math.abs(offset - this._releaseElement.offsetTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _enable(): boolean {
|
||||||
|
if (!this._element) return false;
|
||||||
|
|
||||||
|
let width = this._getOption('width') as string;
|
||||||
|
const top = this._getOption('top') as string;
|
||||||
|
const left = this._getOption('left') as string;
|
||||||
|
const right = this._getOption('right') as string;
|
||||||
|
const height = this._calculateHeight();
|
||||||
|
const zindex = this._getOption('zindex') as string;
|
||||||
|
const classList = this._getOption('class') as string;
|
||||||
|
|
||||||
|
if (height + parseInt(top) > KTDom.getViewPort().height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width) {
|
||||||
|
const targetElement = document.querySelector(width) as HTMLElement;
|
||||||
|
if (targetElement) {
|
||||||
|
width = KTDom.getCssProp(targetElement, 'width');
|
||||||
|
} else if (width == 'auto') {
|
||||||
|
width = KTDom.getCssProp(this._element, 'width');
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.style.width = `${Math.round(parseFloat(width))}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top) {
|
||||||
|
this._element.style.top = `${top}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left) {
|
||||||
|
if (left === 'auto') {
|
||||||
|
const offsetLeft = KTDom.offset(this._element).left;
|
||||||
|
if (offsetLeft >= 0) {
|
||||||
|
this._element.style.left = `${offsetLeft}px`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._element.style.left = `${left}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (right) {
|
||||||
|
if (right === 'auto') {
|
||||||
|
const offseRight = KTDom.offset(this._element).right;
|
||||||
|
if (offseRight >= 0) {
|
||||||
|
this._element.style.right = `${offseRight}px`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._element.style.right = `${right}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zindex) {
|
||||||
|
this._element.style.zIndex = zindex;
|
||||||
|
this._element.style.position = 'fixed';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classList) {
|
||||||
|
KTDom.addClass(this._element, classList);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._wrapperElement) {
|
||||||
|
this._wrapperElement.style.height = `${height}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.classList.add('active');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _disable(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._element.style.top = '';
|
||||||
|
this._element.style.width = '';
|
||||||
|
this._element.style.left = '';
|
||||||
|
this._element.style.right = '';
|
||||||
|
this._element.style.zIndex = '';
|
||||||
|
this._element.style.position = '';
|
||||||
|
|
||||||
|
const classList = this._getOption('class') as string;
|
||||||
|
|
||||||
|
if (this._wrapperElement) {
|
||||||
|
this._wrapperElement.style.height = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classList) {
|
||||||
|
KTDom.removeClass(this._element, classList);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update(): void {
|
||||||
|
if (this._isActive()) {
|
||||||
|
this._disable();
|
||||||
|
this._enable();
|
||||||
|
} else {
|
||||||
|
this._disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _calculateHeight(): number {
|
||||||
|
if (!this._element) return 0;
|
||||||
|
|
||||||
|
let height = parseFloat(KTDom.getCssProp(this._element, 'height'));
|
||||||
|
height += parseFloat(KTDom.getCssProp(this._element, 'margin-top'));
|
||||||
|
height += parseFloat(KTDom.getCssProp(this._element, 'margin-bottom'));
|
||||||
|
|
||||||
|
if (KTDom.getCssProp(this._element, 'border-top')) {
|
||||||
|
height = height + parseFloat(KTDom.getCssProp(this._element, 'border-top'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KTDom.getCssProp(this._element, 'border-bottom')) {
|
||||||
|
height = height + parseFloat(KTDom.getCssProp(this._element, 'border-bottom'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _isActive(): boolean {
|
||||||
|
return this._element.classList.contains('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public isActive(): boolean {
|
||||||
|
return this._isActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTSticky {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'sticky')) {
|
||||||
|
return KTData.get(element, 'sticky') as KTSticky;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-sticky') === "true") {
|
||||||
|
return new KTSticky(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTStickyConfigInterface): KTSticky {
|
||||||
|
return this.getInstance(element) || new KTSticky(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-sticky="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTSticky(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTSticky.createInstances();
|
||||||
|
}
|
||||||
|
}
|
17
resources/metronic/core/components/sticky/types.ts
Normal file
17
resources/metronic/core/components/sticky/types.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
export interface KTStickyConfigInterface {
|
||||||
|
name: string,
|
||||||
|
class: string,
|
||||||
|
zindex: string,
|
||||||
|
top: string,
|
||||||
|
left: string,
|
||||||
|
right: string,
|
||||||
|
width: string | number | object,
|
||||||
|
offset: number,
|
||||||
|
reverse: boolean,
|
||||||
|
release: string,
|
||||||
|
activate: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTStickyInterface {
|
||||||
|
update(): void;
|
||||||
|
}
|
2
resources/metronic/core/components/tabs/index.ts
Normal file
2
resources/metronic/core/components/tabs/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTTabs } from './tabs';
|
||||||
|
export type { KTTabsConfigInterface, KTTabsInterface } from './types';
|
157
resources/metronic/core/components/tabs/tabs.ts
Normal file
157
resources/metronic/core/components/tabs/tabs.ts
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTTabsInterface, KTTabsConfigInterface } from './types';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KT_TABS_INITIALIZED: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KTTabs extends KTComponent implements KTTabsInterface {
|
||||||
|
protected override _name: string = 'tabs';
|
||||||
|
protected override _defaultConfig: KTTabsConfigInterface = {
|
||||||
|
hiddenClass: '',
|
||||||
|
};
|
||||||
|
protected override _config: KTTabsConfigInterface = this._defaultConfig;
|
||||||
|
protected _currentTabElement: HTMLElement | null = null;
|
||||||
|
protected _currentContentElement: HTMLElement | null = null;
|
||||||
|
protected _lastTabElement: HTMLElement | null = null;
|
||||||
|
protected _lastContentElement: HTMLElement | null = null;
|
||||||
|
protected _tabElements: NodeListOf<HTMLElement> | null = null;
|
||||||
|
protected _isTransitioning: boolean = false;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config?: KTTabsConfigInterface) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
if (!this._element) return;
|
||||||
|
this._tabElements = this._element.querySelectorAll('[data-tab-toggle]');
|
||||||
|
this._currentTabElement = this._element.querySelector('.active[data-tab-toggle]');
|
||||||
|
this._currentContentElement = this._currentTabElement && (KTDom.getElement(this._currentTabElement.getAttribute('data-tab-toggle')) || KTDom.getElement(this._currentTabElement.getAttribute('href')))|| null;
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
KTEventHandler.on(this._element, '[data-tab-toggle]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.preventDefault();
|
||||||
|
this._show(target);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _show(tabElement: HTMLElement): void {
|
||||||
|
if (this._isShown(tabElement) || this._isTransitioning) return;
|
||||||
|
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('show', payload);
|
||||||
|
this._dispatchEvent('show', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._currentTabElement?.classList.remove('active');
|
||||||
|
this._currentContentElement?.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
this._lastTabElement = this._currentTabElement;
|
||||||
|
this._getDropdownToggleElement(this._lastTabElement)?.classList.remove('active');
|
||||||
|
|
||||||
|
this._lastContentElement = this._currentContentElement;
|
||||||
|
this._currentTabElement = tabElement;
|
||||||
|
this._currentContentElement = KTDom.getElement(tabElement.getAttribute('data-tab-toggle')) || KTDom.getElement(tabElement.getAttribute('href'));
|
||||||
|
this._currentTabElement?.classList.add('active');
|
||||||
|
this._currentContentElement?.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
this._getDropdownToggleElement(this._currentTabElement)?.classList.add('active');
|
||||||
|
|
||||||
|
this._currentContentElement.style.opacity = '0';
|
||||||
|
KTDom.reflow(this._currentContentElement);
|
||||||
|
this._currentContentElement.style.opacity = '1';
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._currentContentElement, () => {
|
||||||
|
this._isTransitioning = false;
|
||||||
|
this._currentContentElement.style.opacity = '';
|
||||||
|
|
||||||
|
this._fireEvent('shown');
|
||||||
|
this._dispatchEvent('shown');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getDropdownToggleElement(element: HTMLElement): HTMLElement {
|
||||||
|
const containerElement = element.closest('.dropdown') as HTMLElement;
|
||||||
|
|
||||||
|
if (containerElement) {
|
||||||
|
return containerElement.querySelector('.dropdown-toggle');
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _isShown(tabElement: HTMLElement): boolean {
|
||||||
|
return tabElement.classList.contains('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
public isShown(tabElement: HTMLElement): boolean {
|
||||||
|
return this._isShown(tabElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public show(tabElement: HTMLElement): void {
|
||||||
|
return this._show(tabElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static keyboardArrow(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static keyboardJump(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static handleAccessibility(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTTabs {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'tabs')) {
|
||||||
|
return KTData.get(element, 'tabs') as KTTabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-tabs') === "true") {
|
||||||
|
return new KTTabs(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTTabsConfigInterface): KTTabs {
|
||||||
|
return this.getInstance(element) || new KTTabs(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-tabs="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTTabs(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTTabs.createInstances();
|
||||||
|
|
||||||
|
if (window.KT_TABS_INITIALIZED !== true) {
|
||||||
|
KTTabs.handleAccessibility();
|
||||||
|
window.KT_TABS_INITIALIZED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
resources/metronic/core/components/tabs/types.ts
Normal file
8
resources/metronic/core/components/tabs/types.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export interface KTTabsConfigInterface {
|
||||||
|
hiddenClass: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTTabsInterface {
|
||||||
|
show(tabElement: HTMLElement): void;
|
||||||
|
isShown(tabElement: HTMLElement): boolean;
|
||||||
|
}
|
2
resources/metronic/core/components/theme/index.ts
Normal file
2
resources/metronic/core/components/theme/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTTheme } from './theme';
|
||||||
|
export type { KTThemeConfigInterface, KTThemeInterface } from './types';
|
147
resources/metronic/core/components/theme/theme.ts
Normal file
147
resources/metronic/core/components/theme/theme.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTEventHandler from '../../helpers/event-handler';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTThemeInterface, KTThemeConfigInterface } from './types';
|
||||||
|
import { KTThemeModeType } from './types';
|
||||||
|
|
||||||
|
export class KTTheme extends KTComponent implements KTThemeInterface {
|
||||||
|
protected override _name: string = 'theme';
|
||||||
|
protected override _defaultConfig: KTThemeConfigInterface = {
|
||||||
|
mode: 'light',
|
||||||
|
class: true,
|
||||||
|
attribute: 'data-theme-mode',
|
||||||
|
};
|
||||||
|
protected _mode: KTThemeModeType | null = null;
|
||||||
|
protected _currentMode: KTThemeModeType | null = null;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTThemeConfigInterface | null = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
this._setMode((localStorage.getItem('theme') || this._getOption('mode')) as KTThemeModeType);
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
KTEventHandler.on(this._element, '[data-theme-toggle="true"]', 'click', () => {
|
||||||
|
this._toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
KTEventHandler.on(this._element, '[data-theme-switch]', 'click', (event: Event, target: HTMLElement) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const mode = target.getAttribute('data-theme-switch') as KTThemeModeType;
|
||||||
|
this._setMode(mode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle() {
|
||||||
|
const mode = this._currentMode === 'light' ? 'dark' : 'light';
|
||||||
|
|
||||||
|
this._setMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _setMode(mode: KTThemeModeType): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('change', payload);
|
||||||
|
this._dispatchEvent('change', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentMode: KTThemeModeType = mode;
|
||||||
|
if (mode === 'system') {
|
||||||
|
currentMode = this._getSystemMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
this._mode = mode;
|
||||||
|
this._currentMode = currentMode;
|
||||||
|
this._bindMode();
|
||||||
|
this._updateState();
|
||||||
|
localStorage.setItem('theme', this._mode);
|
||||||
|
this._element.setAttribute('data-theme-mode', mode);
|
||||||
|
|
||||||
|
this._fireEvent('changed', {});
|
||||||
|
this._dispatchEvent('changed', {});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getMode(): KTThemeModeType {
|
||||||
|
return localStorage.getItem('theme') as KTThemeModeType || this._mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _getSystemMode(): KTThemeModeType {
|
||||||
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _bindMode(): void {
|
||||||
|
if (!this._currentMode || !this._element) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('class')) {
|
||||||
|
this._element.classList.remove('dark');
|
||||||
|
this._element.classList.remove('light');
|
||||||
|
this._element.removeAttribute(this._getOption('attribute') as string);
|
||||||
|
this._element.classList.add(this._currentMode);
|
||||||
|
} else {
|
||||||
|
this._element.classList.remove(this._currentMode);
|
||||||
|
this._element.setAttribute(this._getOption('attribute') as string, this._currentMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _updateState() {
|
||||||
|
const elements = document.querySelectorAll<HTMLInputElement>('input[type="checkbox"][data-theme-state]');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
if (element.getAttribute('data-theme-state') === this._mode) {
|
||||||
|
element.checked = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getMode(): KTThemeModeType {
|
||||||
|
return this._getMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setMode(mode: KTThemeModeType) {
|
||||||
|
this.setMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTTheme {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'theme')) {
|
||||||
|
return KTData.get(element, 'theme') as KTTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-theme') !== "false") {
|
||||||
|
return new KTTheme(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement = document.body, config?: KTThemeConfigInterface): KTTheme | null {
|
||||||
|
return this.getInstance(element) || new KTTheme(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-theme]:not([data-theme="false"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTTheme(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTTheme.createInstances();
|
||||||
|
}
|
||||||
|
}
|
12
resources/metronic/core/components/theme/types.ts
Normal file
12
resources/metronic/core/components/theme/types.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export declare type KTThemeModeType = 'light' | 'dark' | 'system';
|
||||||
|
|
||||||
|
export interface KTThemeConfigInterface {
|
||||||
|
mode: KTThemeModeType,
|
||||||
|
class: boolean,
|
||||||
|
attribute: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTThemeInterface {
|
||||||
|
setMode(mode: KTThemeModeType): void;
|
||||||
|
getMode(): KTThemeModeType;
|
||||||
|
}
|
@ -0,0 +1,2 @@
|
|||||||
|
export { KTTogglePassword } from './toggle-password';
|
||||||
|
export type { KTTogglePasswordConfigInterface, KTTogglePasswordInterface } from './types';
|
@ -0,0 +1,133 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTTogglePasswordConfigInterface, KTTogglePasswordInterface } from './types';
|
||||||
|
|
||||||
|
export class KTTogglePassword extends KTComponent implements KTTogglePasswordInterface {
|
||||||
|
protected override _name: string = 'toggle-password';
|
||||||
|
protected override _defaultConfig: KTTogglePasswordConfigInterface = {
|
||||||
|
permanent: false
|
||||||
|
};
|
||||||
|
protected override _config: KTTogglePasswordConfigInterface = this._defaultConfig;
|
||||||
|
protected _triggerElement: HTMLElement;
|
||||||
|
protected _inputElement: HTMLInputElement;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTTogglePasswordConfigInterface | null = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._triggerElement = this._element.querySelector('[data-toggle-password-trigger]');
|
||||||
|
this._inputElement = this._element.querySelector('input[type="password"]');
|
||||||
|
|
||||||
|
if (!this._triggerElement || !this._inputElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._triggerElement.addEventListener('click', () => {
|
||||||
|
this._toggle();
|
||||||
|
});
|
||||||
|
|
||||||
|
this._inputElement.addEventListener('input', () => {
|
||||||
|
|
||||||
|
this._update();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('toggle', payload);
|
||||||
|
this._dispatchEvent('toggle', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isVisible()) {
|
||||||
|
this._element.classList.remove('active')
|
||||||
|
this._setVisible(false);
|
||||||
|
} else {
|
||||||
|
this._element.classList.add('active')
|
||||||
|
this._setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fireEvent('toggled');
|
||||||
|
this._dispatchEvent('toggled');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
if ((this._getOption('permanent') as boolean) === false) {
|
||||||
|
if (this._isVisible()) {
|
||||||
|
this._setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public _isVisible(): boolean {
|
||||||
|
return this._inputElement.getAttribute('type') === 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
public _setVisible(flag: boolean) {
|
||||||
|
if (flag) {
|
||||||
|
this._inputElement.setAttribute('type', 'text');
|
||||||
|
} else {
|
||||||
|
this._inputElement.setAttribute('type', 'password');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle(): void {
|
||||||
|
this._toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setVisible(flag: boolean): void {
|
||||||
|
this._setVisible(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public isVisible(): boolean {
|
||||||
|
return this._isVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTTogglePassword {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'toggle-password')) {
|
||||||
|
return KTData.get(element, 'toggle-password') as KTTogglePassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-toggle-password') === "true") {
|
||||||
|
return new KTTogglePassword(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTTogglePasswordConfigInterface): KTTogglePassword {
|
||||||
|
return this.getInstance(element) || new KTTogglePassword(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-toggle-password="true"]');
|
||||||
|
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTTogglePassword(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTTogglePassword.createInstances();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
export interface KTTogglePasswordConfigInterface {
|
||||||
|
permanent?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTTogglePasswordInterface {
|
||||||
|
toggle(): void;
|
||||||
|
isVisible(): boolean;
|
||||||
|
}
|
2
resources/metronic/core/components/toggle/index.ts
Normal file
2
resources/metronic/core/components/toggle/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTToggle } from './toggle';
|
||||||
|
export type { KTToggleConfigInterface, KTToggleInterface } from './types';
|
143
resources/metronic/core/components/toggle/toggle.ts
Normal file
143
resources/metronic/core/components/toggle/toggle.ts
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTToggleConfigInterface, KTToggleInterface } from './types';
|
||||||
|
|
||||||
|
export class KTToggle extends KTComponent implements KTToggleInterface {
|
||||||
|
protected override _name: string = 'toggle';
|
||||||
|
protected override _defaultConfig: KTToggleConfigInterface = {
|
||||||
|
target: '',
|
||||||
|
activeClass: 'active',
|
||||||
|
class: '',
|
||||||
|
removeClass: '',
|
||||||
|
attribute: ''
|
||||||
|
};
|
||||||
|
protected override _config: KTToggleConfigInterface = this._defaultConfig;
|
||||||
|
protected _targetElement: HTMLElement;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTToggleConfigInterface | null = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._targetElement = this._getTargetElement();
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._element.addEventListener('click', () => {
|
||||||
|
this._toggle();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTargetElement(): HTMLElement | null {
|
||||||
|
return (
|
||||||
|
KTDom.getElement(this._element.getAttribute('data-toggle') as string) ||
|
||||||
|
KTDom.getElement(this._getOption('target') as string)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('toggle', payload);
|
||||||
|
this._dispatchEvent('toggle', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._element.classList.toggle(this._getOption('activeClass') as string);
|
||||||
|
this._update();
|
||||||
|
|
||||||
|
this._fireEvent('toggled');
|
||||||
|
this._dispatchEvent('toggled');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _update(): void {
|
||||||
|
if (!this._targetElement) return;
|
||||||
|
|
||||||
|
if (this._getOption('removeClass')) {
|
||||||
|
KTDom.removeClass(this._targetElement, this._getOption('removeClass') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._isActive()) {
|
||||||
|
if (this._getOption('class')) {
|
||||||
|
KTDom.addClass(this._targetElement, this._getOption('class') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('attribute')) {
|
||||||
|
this._targetElement.setAttribute(this._getOption('attribute') as string, 'true');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this._getOption('class')) {
|
||||||
|
KTDom.removeClass(this._targetElement, this._getOption('class') as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('attribute')) {
|
||||||
|
this._targetElement.removeAttribute(this._getOption('attribute') as string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public _isActive(): boolean {
|
||||||
|
if (!this._element) return false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
KTDom.hasClass(this._targetElement, this._getOption('class') as string) ||
|
||||||
|
this._targetElement.hasAttribute(this._getOption('attribute') as string)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle(): void {
|
||||||
|
this._toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(): void {
|
||||||
|
this._update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public isActive(): boolean {
|
||||||
|
return this._isActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTToggle {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'toggle')) {
|
||||||
|
return KTData.get(element, 'toggle') as KTToggle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-toggle') !== "false") {
|
||||||
|
return new KTToggle(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTToggleConfigInterface): KTToggle {
|
||||||
|
return this.getInstance(element) || new KTToggle(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
const elements = document.querySelectorAll('[data-toggle]:not([data-toggle="false"]');
|
||||||
|
elements.forEach((element) => {
|
||||||
|
new KTToggle(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTToggle.createInstances();
|
||||||
|
}
|
||||||
|
}
|
13
resources/metronic/core/components/toggle/types.ts
Normal file
13
resources/metronic/core/components/toggle/types.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
export interface KTToggleConfigInterface {
|
||||||
|
target?: string,
|
||||||
|
activeClass?: string,
|
||||||
|
class?: string,
|
||||||
|
removeClass?: string,
|
||||||
|
attribute?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTToggleInterface {
|
||||||
|
toggle(): void;
|
||||||
|
update(): void;
|
||||||
|
isActive(): boolean;
|
||||||
|
}
|
2
resources/metronic/core/components/tooltip/index.ts
Normal file
2
resources/metronic/core/components/tooltip/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { KTTooltip } from './tooltip';
|
||||||
|
export type { KTTooltipConfigInterface, KTTooltipInterface } from './types';
|
302
resources/metronic/core/components/tooltip/tooltip.ts
Normal file
302
resources/metronic/core/components/tooltip/tooltip.ts
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
/* eslint-disable require-jsdoc */
|
||||||
|
|
||||||
|
import KTData from '../../helpers/data';
|
||||||
|
import KTDom from '../../helpers/dom';
|
||||||
|
import KTComponent from '../component';
|
||||||
|
import { KTTooltipInterface, KTTooltipConfigInterface } from './types';
|
||||||
|
import { createPopper, PositioningStrategy, Instance, Placement } from '@popperjs/core';
|
||||||
|
import { KTTooltipTriggerType } from './types';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KT_TOOLTIP_INITIALIZED: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class KTTooltip extends KTComponent implements KTTooltipInterface {
|
||||||
|
protected override _name: string = 'tooltip';
|
||||||
|
protected override _defaultConfig: KTTooltipConfigInterface = {
|
||||||
|
target: '',
|
||||||
|
hiddenClass: 'hidden',
|
||||||
|
trigger: 'hover',
|
||||||
|
placement: 'top',
|
||||||
|
container: '',
|
||||||
|
strategy: 'fixed',
|
||||||
|
offset: '0, 5px',
|
||||||
|
delayShow: 0,
|
||||||
|
delayHide: 0,
|
||||||
|
permanent: false,
|
||||||
|
zindex: '100'
|
||||||
|
};
|
||||||
|
protected override _config: KTTooltipConfigInterface = this._defaultConfig;
|
||||||
|
protected _isOpen: boolean = false;
|
||||||
|
protected _targetElement: HTMLElement;
|
||||||
|
protected _popper!: Instance;
|
||||||
|
protected _transitioning: boolean = false;
|
||||||
|
protected _timeout!: ReturnType<typeof setTimeout>;
|
||||||
|
|
||||||
|
constructor(element: HTMLElement, config: KTTooltipConfigInterface | null = null) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
if (KTData.has(element as HTMLElement, this._name)) return;
|
||||||
|
|
||||||
|
this._init(element);
|
||||||
|
this._buildConfig(config);
|
||||||
|
|
||||||
|
this._targetElement = this._getTargetElement();
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._handlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getTargetElement(): HTMLElement | null {
|
||||||
|
return (
|
||||||
|
KTDom.getElement(this._element.getAttribute('data-tooltip') as string) ||
|
||||||
|
this._element.querySelector('.tooltip, .popover, [data-tooltip-content]') ||
|
||||||
|
KTDom.getElement(this._getOption('target') as string)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handlers(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
if (this._getOption('trigger') === 'click') {
|
||||||
|
this._element.addEventListener('click', () => this._toggle());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('trigger') === 'focus') {
|
||||||
|
this._element.addEventListener('focus', () => this._toggle());
|
||||||
|
this._element.addEventListener('blur', () => this._hide());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._getOption('trigger') === 'hover') {
|
||||||
|
this._element.addEventListener('mouseenter', () => this._show());
|
||||||
|
this._element.addEventListener('mouseleave', () => this._hide());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _show(): void {
|
||||||
|
if (this._isOpen) return;
|
||||||
|
|
||||||
|
if (this._timeout) {
|
||||||
|
clearTimeout(this._timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._timeout = setTimeout(() => {
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('show', payload);
|
||||||
|
this._dispatchEvent('show', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this._element) return;
|
||||||
|
|
||||||
|
this._createPopper();
|
||||||
|
this._handleContainer();
|
||||||
|
this._setZindex();
|
||||||
|
|
||||||
|
this._targetElement.classList.add('show');
|
||||||
|
this._targetElement.classList.remove(this._getOption('hiddenClass') as string);
|
||||||
|
this._targetElement.style.opacity = '0';
|
||||||
|
KTDom.reflow(this._targetElement);
|
||||||
|
this._targetElement.style.opacity = '1';
|
||||||
|
this._transitioning = true;
|
||||||
|
this._isOpen = true;
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._targetElement, () => {
|
||||||
|
this._targetElement.style.opacity = '';
|
||||||
|
this._transitioning = false;
|
||||||
|
this._fireEvent('shown');
|
||||||
|
this._dispatchEvent('shown');
|
||||||
|
});
|
||||||
|
}, this._getOption('delayShow') as number);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _hide(): void {
|
||||||
|
if (!this._isOpen) return;
|
||||||
|
|
||||||
|
if (this._timeout) {
|
||||||
|
clearTimeout(this._timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._timeout = setTimeout(() => {
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('hide', payload);
|
||||||
|
this._dispatchEvent('hide', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
this._targetElement.style.opacity = '1';
|
||||||
|
KTDom.reflow(this._targetElement);
|
||||||
|
this._targetElement.style.opacity = '0';
|
||||||
|
this._transitioning = true;
|
||||||
|
this._isOpen = false;
|
||||||
|
|
||||||
|
KTDom.transitionEnd(this._targetElement, () => {
|
||||||
|
this._popper.destroy();
|
||||||
|
this._targetElement.classList.remove('show');
|
||||||
|
this._targetElement.classList.add(this._getOption('hiddenClass') as string);
|
||||||
|
this._targetElement.style.opacity = '';
|
||||||
|
this._transitioning = false;
|
||||||
|
this._fireEvent('hidden');
|
||||||
|
this._dispatchEvent('hidden');
|
||||||
|
});
|
||||||
|
}, this._getOption('delayHide') as number);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _toggle(): void {
|
||||||
|
const payload = { cancel: false };
|
||||||
|
this._fireEvent('toggle', payload);
|
||||||
|
this._dispatchEvent('toggle', payload);
|
||||||
|
if (payload.cancel === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._isOpen) {
|
||||||
|
this._hide();
|
||||||
|
} else {
|
||||||
|
this._show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _createPopper(): void {
|
||||||
|
if (!this._element) return;
|
||||||
|
const offsetValue = this._getOption('offset');
|
||||||
|
const offset = offsetValue ? offsetValue.toString().split(',').map(value => parseInt(value.trim(), 10)) : [0, 0];
|
||||||
|
|
||||||
|
if (!this._targetElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._popper = createPopper(
|
||||||
|
this._element,
|
||||||
|
this._targetElement,
|
||||||
|
{
|
||||||
|
placement: this._getOption('placement') as Placement,
|
||||||
|
strategy: this._getOption('strategy') as PositioningStrategy,
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
name: 'offset',
|
||||||
|
options: {
|
||||||
|
offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _handleContainer(): void {
|
||||||
|
if (this._getOption('container')) {
|
||||||
|
if (this._getOption('container') === 'body') {
|
||||||
|
document.body.appendChild(this._targetElement);
|
||||||
|
} else {
|
||||||
|
document.querySelector(this._getOption('container') as string)?.appendChild(this._targetElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _setZindex(): void {
|
||||||
|
let zindex: number = parseInt(this._getOption('zindex') as string);
|
||||||
|
|
||||||
|
if (parseInt(KTDom.getCssProp(this._element, 'z-index')) > zindex) {
|
||||||
|
zindex = parseInt(KTDom.getCssProp(this._element, 'z-index'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KTDom.getHighestZindex(this._element) > zindex) {
|
||||||
|
zindex =KTDom.getHighestZindex(this._element) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._targetElement.style.zIndex = String(zindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public show(): void {
|
||||||
|
this._show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public hide(): void {
|
||||||
|
this._hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle(): void {
|
||||||
|
this._toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
public getContentElement(): HTMLElement | null {
|
||||||
|
return this._targetElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isOpen(): boolean {
|
||||||
|
return this._isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTriggerOption(): KTTooltipTriggerType {
|
||||||
|
return this._getOption('trigger') as KTTooltipTriggerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isPermanent(): boolean {
|
||||||
|
return this._getOption('permanent') as boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static initHandlers(): void {
|
||||||
|
document.addEventListener('click', (event: Event) => {
|
||||||
|
document.querySelectorAll('[data-tooltip]').forEach((tooltipElement) => {
|
||||||
|
const tooltip = KTTooltip.getInstance(tooltipElement as HTMLElement);
|
||||||
|
|
||||||
|
if (tooltip && tooltip.isOpen() && tooltip.getTriggerOption() !== 'hover' && !tooltip.isPermanent()) {
|
||||||
|
const contentElement = tooltip.getContentElement();
|
||||||
|
if (contentElement && (contentElement === event.target || contentElement.contains(event.target as HTMLElement))) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
tooltip.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getInstance(element: HTMLElement): KTTooltip {
|
||||||
|
if (!element) return null;
|
||||||
|
|
||||||
|
if (KTData.has(element, 'tooltip')) {
|
||||||
|
return KTData.get(element, 'tooltip') as KTTooltip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.getAttribute('data-tooltip') !== "false") {
|
||||||
|
return new KTTooltip(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getOrCreateInstance(element: HTMLElement, config?: KTTooltipConfigInterface): KTTooltip {
|
||||||
|
return this.getInstance(element) || new KTTooltip(element, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static createInstances(): void {
|
||||||
|
document.querySelectorAll('[data-tooltip]:not([data-tooltip="false"]').forEach((element) => {
|
||||||
|
new KTTooltip(element as HTMLElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static init(): void {
|
||||||
|
KTTooltip.createInstances();
|
||||||
|
|
||||||
|
if (window.KT_TOOLTIP_INITIALIZED !== true) {
|
||||||
|
KTTooltip.initHandlers();
|
||||||
|
window.KT_TOOLTIP_INITIALIZED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
resources/metronic/core/components/tooltip/types.ts
Normal file
21
resources/metronic/core/components/tooltip/types.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
export declare type KTTooltipTriggerType = 'hover' | 'click' | 'focus';
|
||||||
|
|
||||||
|
export interface KTTooltipConfigInterface {
|
||||||
|
hiddenClass: string;
|
||||||
|
target: string;
|
||||||
|
trigger: string,
|
||||||
|
container: string,
|
||||||
|
placement: string,
|
||||||
|
strategy: string,
|
||||||
|
permanent: boolean,
|
||||||
|
offset: string,
|
||||||
|
delayShow: number,
|
||||||
|
delayHide: number,
|
||||||
|
zindex: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KTTooltipInterface {
|
||||||
|
show(): void;
|
||||||
|
hide(): void;
|
||||||
|
toggle(): void;
|
||||||
|
}
|
41
resources/metronic/core/helpers/data.ts
Normal file
41
resources/metronic/core/helpers/data.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
const KTElementMap = new Map();
|
||||||
|
|
||||||
|
const KTData = {
|
||||||
|
set(element: HTMLElement, key: string, value: unknown): void {
|
||||||
|
if (!KTElementMap.has(element)) {
|
||||||
|
KTElementMap.set(element, new Map());
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueMap = KTElementMap.get(element);
|
||||||
|
|
||||||
|
valueMap.set(key, value);
|
||||||
|
},
|
||||||
|
|
||||||
|
get(element: HTMLElement, key: string): unknown {
|
||||||
|
if (KTElementMap.has(element)) {
|
||||||
|
return KTElementMap.get(element).get(key) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
has(element: HTMLElement, key: string): boolean {
|
||||||
|
return KTElementMap.has(element) && KTElementMap.get(element).has(key);
|
||||||
|
},
|
||||||
|
|
||||||
|
remove(element: HTMLElement, key: string): void {
|
||||||
|
if (!KTElementMap.has(element) || !KTElementMap.get(element).has(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valueMap = KTElementMap.get(element);
|
||||||
|
|
||||||
|
valueMap.delete(key);
|
||||||
|
|
||||||
|
if (valueMap.size === 0) {
|
||||||
|
KTElementMap.delete(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KTData;
|
365
resources/metronic/core/helpers/dom.ts
Normal file
365
resources/metronic/core/helpers/dom.ts
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import KTUtils from './utils';
|
||||||
|
import { KTOffsetType, KTOptionType, KTViewPortType } from '../types';
|
||||||
|
|
||||||
|
const KTDom = {
|
||||||
|
isElement(element: HTMLElement): boolean {
|
||||||
|
if (element && element instanceof HTMLElement) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getElement(element: HTMLElement | string): HTMLElement {
|
||||||
|
if (this.isElement(element)) {
|
||||||
|
return element as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element && (element as string).length > 0) {
|
||||||
|
return document.querySelector(KTUtils.parseSelector((element as string)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
remove(element: HTMLElement): void {
|
||||||
|
if (this.isElement(element) && element.parentNode) {
|
||||||
|
element.parentNode.removeChild(element);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
hasClass(element: HTMLElement, className: string): boolean {
|
||||||
|
// Split classNames string into an array of individual class names
|
||||||
|
const classes = className.split(' ');
|
||||||
|
|
||||||
|
// Loop through each class name
|
||||||
|
for (const className of classes) {
|
||||||
|
// Check if the element has the current class name
|
||||||
|
if (!element.classList.contains(className)) {
|
||||||
|
// Return false if any class is missing
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if all classes are present
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
addClass(element: HTMLElement, className: string): void {
|
||||||
|
const classNames = className.split(' ');
|
||||||
|
|
||||||
|
if (element.classList) {
|
||||||
|
for (let i = 0; i < classNames.length; i++) {
|
||||||
|
if (classNames[i] && classNames[i].length > 0) {
|
||||||
|
element.classList.add(classNames[i].trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!this.hasClass(element, className)) {
|
||||||
|
for (let x = 0; x < classNames.length; x++) {
|
||||||
|
element.className += ' ' + classNames[x].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
removeClass(element: HTMLElement, className: string): void {
|
||||||
|
const classNames = className.split(' ');
|
||||||
|
|
||||||
|
if (element.classList) {
|
||||||
|
for (let i = 0; i < classNames.length; i++) {
|
||||||
|
element.classList.remove(classNames[i].trim());
|
||||||
|
}
|
||||||
|
} else if (this.hasClass(element, className)) {
|
||||||
|
for (let x = 0; x < classNames.length; x++) {
|
||||||
|
element.className = element.className.replace(new RegExp('\\b' + classNames[x].trim() + '\\b', 'g'), '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getCssProp(element: HTMLElement, prop: string): string {
|
||||||
|
return (element ? window.getComputedStyle(element).getPropertyValue(prop) : '').replace(' ', '');
|
||||||
|
},
|
||||||
|
|
||||||
|
setCssProp(element: HTMLElement, prop: string, value: string) {
|
||||||
|
if (element) {
|
||||||
|
window.getComputedStyle(element).setProperty(prop, value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
offsetOld(element: HTMLElement): KTOffsetType {
|
||||||
|
if (!element) return { top: 0, left: 0, right: 0, bottom: 0 };
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
const view = element.ownerDocument.defaultView;
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: rect.top + (view?.scrollY || 0),
|
||||||
|
left: rect.left,
|
||||||
|
right: window.innerWidth - rect.right,
|
||||||
|
bottom: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
offset(element: HTMLElement): KTOffsetType {
|
||||||
|
if (!element) return { top: 0, left: 0, right: 0, bottom: 0 };
|
||||||
|
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
|
||||||
|
return {
|
||||||
|
top: rect.top,
|
||||||
|
left: rect.left,
|
||||||
|
right: window.innerWidth - rect.right,
|
||||||
|
bottom: window.innerHeight - rect.top,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getIndex(element: HTMLElement): number {
|
||||||
|
const children = Array.from(element.parentNode?.children || []);
|
||||||
|
return children.indexOf(element);
|
||||||
|
},
|
||||||
|
|
||||||
|
parents(element: HTMLElement, selector: string): Array<HTMLElement> {
|
||||||
|
const parents: Array<HTMLElement> = [];
|
||||||
|
|
||||||
|
// Push each parent element to the array
|
||||||
|
for (element && element !== document.documentElement; (element = element.parentElement as HTMLElement);) {
|
||||||
|
if (selector) {
|
||||||
|
if (element.matches(selector)) {
|
||||||
|
parents.push(element as HTMLElement);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
parents.push(element as HTMLElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return our parent array
|
||||||
|
return parents;
|
||||||
|
},
|
||||||
|
|
||||||
|
siblings(element: HTMLElement) {
|
||||||
|
const parent = element.parentNode;
|
||||||
|
if (!parent) return [];
|
||||||
|
return Array.from(parent.children).filter((child) => child !== element);
|
||||||
|
},
|
||||||
|
|
||||||
|
children(element: HTMLElement, selector: string): Array<HTMLElement> {
|
||||||
|
if (!element || !element.childNodes) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result: Array<HTMLElement> = [];
|
||||||
|
const l = element.childNodes.length;
|
||||||
|
let i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < l; i++) {
|
||||||
|
if (element.childNodes[i].nodeType == 1 && (element.childNodes[i] as HTMLElement).matches(selector)) {
|
||||||
|
result.push(element.childNodes[i] as HTMLElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
child(element: HTMLElement, selector: string): HTMLElement {
|
||||||
|
const children = KTDom.children(element, selector);
|
||||||
|
|
||||||
|
return children ? children[0] : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
isVisible(element: HTMLElement): boolean {
|
||||||
|
if (!this.isElement(element) || element.getClientRects().length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
|
return getComputedStyle(element).getPropertyValue('visibility') === 'visible';
|
||||||
|
},
|
||||||
|
|
||||||
|
isDisabled(element: HTMLInputElement | HTMLSelectElement | HTMLButtonElement): boolean {
|
||||||
|
if (!element || element.nodeType !== Node.ELEMENT_NODE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.classList.contains('disabled')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof element.disabled !== 'undefined') {
|
||||||
|
return element.disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
|
||||||
|
},
|
||||||
|
|
||||||
|
transitionEnd(element: HTMLElement, callback: CallableFunction): void {
|
||||||
|
const duration: number = this.getCSSTransitionDuration(element);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
callback();
|
||||||
|
}, duration);
|
||||||
|
},
|
||||||
|
|
||||||
|
animationEnd(element: HTMLElement, callback: CallableFunction): void {
|
||||||
|
const duration: number = this.getCSSAnimationDuration(element);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
callback();
|
||||||
|
}, duration);
|
||||||
|
},
|
||||||
|
|
||||||
|
getCSSTransitionDuration(element: HTMLElement): number {
|
||||||
|
return (parseFloat(window.getComputedStyle(element).transitionDuration)) * 1000;
|
||||||
|
},
|
||||||
|
|
||||||
|
getCSSAnimationDuration(element: HTMLElement): number {
|
||||||
|
return (parseFloat(window.getComputedStyle(element).animationDuration)) * 1000;
|
||||||
|
},
|
||||||
|
|
||||||
|
reflow(element: HTMLElement): void {
|
||||||
|
element.offsetHeight;
|
||||||
|
},
|
||||||
|
|
||||||
|
insertAfter(element: HTMLElement, referenceNode: HTMLElement) {
|
||||||
|
const parentNode = referenceNode.parentNode;
|
||||||
|
if (parentNode) {
|
||||||
|
parentNode.insertBefore(element, referenceNode.nextSibling);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getHighestZindex(element: HTMLElement): number {
|
||||||
|
let position: string, value: number;
|
||||||
|
|
||||||
|
while (element && element !== document.documentElement) {
|
||||||
|
// 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
|
||||||
|
position = element.style.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
|
||||||
|
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
|
||||||
|
value = parseInt(element.style.zIndex);
|
||||||
|
|
||||||
|
if (!isNaN(value) && value !== 0) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
element = element.parentNode as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
isParentOrElementHidden(element: HTMLElement): boolean {
|
||||||
|
if (!element) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const computedStyle = window.getComputedStyle(element);
|
||||||
|
|
||||||
|
if (computedStyle.display === 'none') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.isParentOrElementHidden(element.parentElement);
|
||||||
|
},
|
||||||
|
|
||||||
|
getViewPort(): KTViewPortType {
|
||||||
|
return {
|
||||||
|
width: window.innerWidth,
|
||||||
|
height: window.innerHeight
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getScrollTop() {
|
||||||
|
return (document.scrollingElement || document.documentElement).scrollTop;
|
||||||
|
},
|
||||||
|
|
||||||
|
isInViewport(element: HTMLElement): boolean {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
|
||||||
|
return (
|
||||||
|
rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
isPartiallyInViewport(element: HTMLElement): boolean {
|
||||||
|
const x = element.getBoundingClientRect().left;
|
||||||
|
const y = element.getBoundingClientRect().top;
|
||||||
|
const ww = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
|
||||||
|
const hw = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
|
||||||
|
const w = element.clientWidth;
|
||||||
|
const h = element.clientHeight;
|
||||||
|
|
||||||
|
return (
|
||||||
|
(y < hw && y + h > 0) && (x < ww && x + w > 0)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
isVisibleInParent(child: HTMLElement, parent: HTMLElement): boolean {
|
||||||
|
const childRect = child.getBoundingClientRect();
|
||||||
|
const parentRect = parent.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Check if the child element is visible
|
||||||
|
if (child.offsetParent === null || getComputedStyle(child).visibility === 'hidden' || getComputedStyle(child).display === 'none') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the child is within the vertical bounds of the parent
|
||||||
|
const isVisibleVertically = childRect.top >= parentRect.top && childRect.bottom <= parentRect.bottom;
|
||||||
|
|
||||||
|
// Check if the child is within the horizontal bounds of the parent
|
||||||
|
const isVisibleHorizontally = childRect.left >= parentRect.left && childRect.right <= parentRect.right;
|
||||||
|
|
||||||
|
return isVisibleVertically && isVisibleHorizontally;
|
||||||
|
},
|
||||||
|
|
||||||
|
getRelativeTopPosition(child: HTMLElement, parent: HTMLElement): number {
|
||||||
|
const childRect = child.getBoundingClientRect();
|
||||||
|
const parentRect = parent.getBoundingClientRect();
|
||||||
|
|
||||||
|
// Calculate the relative top position
|
||||||
|
const relativeTop = childRect.top - parentRect.top;
|
||||||
|
|
||||||
|
return relativeTop;
|
||||||
|
},
|
||||||
|
|
||||||
|
getDataAttributes(element: HTMLElement, prefix: string): object {
|
||||||
|
if (!element) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix = KTUtils.camelCase(prefix);
|
||||||
|
|
||||||
|
const attributes: { [key: string]: KTOptionType } = {};
|
||||||
|
const keys = Object.keys(element.dataset).filter((key) => key.startsWith(prefix));
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
let normalizedKey = key.replace(prefix, '');
|
||||||
|
normalizedKey = KTUtils.uncapitalize(normalizedKey);
|
||||||
|
attributes[normalizedKey] = KTUtils.parseDataAttribute(element.dataset[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return attributes;
|
||||||
|
},
|
||||||
|
|
||||||
|
ready(callback: CallableFunction): void {
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KTDom;
|
49
resources/metronic/core/helpers/event-handler.ts
Normal file
49
resources/metronic/core/helpers/event-handler.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { KTCallableType } from '../types';
|
||||||
|
import KTUtils from './utils';
|
||||||
|
|
||||||
|
export interface KTDelegatedEventHandlersInterface {
|
||||||
|
[key: string]: KTCallableType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const KTDelegatedEventHandlers: KTDelegatedEventHandlersInterface = {};
|
||||||
|
|
||||||
|
const KTEventHandler = {
|
||||||
|
on: function(element: HTMLElement, selector: string, eventName: string, handler: KTCallableType): string {
|
||||||
|
if ( element === null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventId = KTUtils.geUID('event');
|
||||||
|
|
||||||
|
KTDelegatedEventHandlers[eventId] = (event: Event & {target: HTMLElement}) => {
|
||||||
|
const targets = element.querySelectorAll(selector);
|
||||||
|
let target = event.target;
|
||||||
|
|
||||||
|
while (target && target !== element) {
|
||||||
|
for (let i = 0, j = targets.length; i < j; i++ ) {
|
||||||
|
if (target === targets[i] ) {
|
||||||
|
handler.call(this, event, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target = target.parentNode as HTMLElement;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
element.addEventListener(eventName, KTDelegatedEventHandlers[eventId]);
|
||||||
|
|
||||||
|
return eventId;
|
||||||
|
},
|
||||||
|
|
||||||
|
off(element: HTMLElement, eventName: string, eventId: string) {
|
||||||
|
if (!element || KTDelegatedEventHandlers[eventId] === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.removeEventListener(eventName, KTDelegatedEventHandlers[eventId]);
|
||||||
|
|
||||||
|
delete KTDelegatedEventHandlers[eventId];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KTEventHandler;
|
115
resources/metronic/core/helpers/utils.ts
Normal file
115
resources/metronic/core/helpers/utils.ts
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
import { KTBreakpointType, KTOptionType } from '../types';
|
||||||
|
|
||||||
|
const KTUtils = {
|
||||||
|
geUID(prefix: string = ''): string {
|
||||||
|
return prefix + Math.floor(Math.random() * (new Date()).getTime());
|
||||||
|
},
|
||||||
|
|
||||||
|
getBreakpoint(breakpoint: KTBreakpointType): number {
|
||||||
|
const value: string = KTUtils.getCssVar(`--tw-${breakpoint}`);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
return parseInt(value.trim());
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getCssVar(variable: string): string {
|
||||||
|
let hex = getComputedStyle(document.documentElement).getPropertyValue(variable);
|
||||||
|
|
||||||
|
if (hex && hex.length > 0) {
|
||||||
|
hex = hex.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex;
|
||||||
|
},
|
||||||
|
|
||||||
|
parseDataAttribute(value: string): KTOptionType {
|
||||||
|
if (value === 'true') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === 'false') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === Number(value).toString()) {
|
||||||
|
return Number(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === '' || value === 'null') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return KTUtils.parseJson(value) as object;
|
||||||
|
} catch {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
parseJson(value: string): JSON {
|
||||||
|
return value && value.length > 0 ? JSON.parse(decodeURIComponent(value)) : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
parseSelector(selector: string): string {
|
||||||
|
if (selector && window.CSS && window.CSS.escape) {
|
||||||
|
// Escape any IDs in the selector using CSS.escape
|
||||||
|
selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${window.CSS.escape(id)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return selector;
|
||||||
|
},
|
||||||
|
|
||||||
|
capitalize(value: string): string {
|
||||||
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
||||||
|
},
|
||||||
|
|
||||||
|
uncapitalize(value: string): string {
|
||||||
|
return value.charAt(0).toLowerCase() + value.slice(1);
|
||||||
|
},
|
||||||
|
|
||||||
|
camelCase(value: string): string {
|
||||||
|
return value.replace(/-([a-z])/g, (match, letter) => {
|
||||||
|
return letter.toUpperCase();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
isRTL(): boolean {
|
||||||
|
const htmlElement = document.querySelector('html');
|
||||||
|
return Boolean(htmlElement && htmlElement.getAttribute('direction') === 'rtl');
|
||||||
|
},
|
||||||
|
|
||||||
|
throttle(timer: undefined | ReturnType<typeof setTimeout>, func: CallableFunction, delay: number): void {
|
||||||
|
// If setTimeout is already scheduled, no need to do anything
|
||||||
|
if (timer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule a setTimeout after delay seconds
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
func();
|
||||||
|
|
||||||
|
// Once setTimeout function execution is finished, timerId = undefined so that in <br>
|
||||||
|
// the next scroll event function execution can be scheduled by the setTimeout
|
||||||
|
clearTimeout(timer);
|
||||||
|
}, delay);
|
||||||
|
},
|
||||||
|
|
||||||
|
checksum(value: string): string {
|
||||||
|
let hash = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < value.length; i++) {
|
||||||
|
hash = ((hash << 5) - hash + value.charCodeAt(i)) | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ('0000000' + (hash >>> 0).toString(16)).slice(-8);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KTUtils;
|
130
resources/metronic/core/index.spa.ts
Normal file
130
resources/metronic/core/index.spa.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Index
|
||||||
|
* @version: 1.0.0
|
||||||
|
* @author: Keenthemes
|
||||||
|
* Copyright 2024 Keenthemes
|
||||||
|
*/
|
||||||
|
|
||||||
|
import KTUtils from './helpers/utils';
|
||||||
|
import KTDom from './helpers/dom';
|
||||||
|
import KTEventHandler from './helpers/event-handler';
|
||||||
|
import {KTMenu} from './components/menu';
|
||||||
|
import {KTDropdown} from './components/dropdown';
|
||||||
|
import {KTModal} from './components/modal';
|
||||||
|
import {KTDrawer} from './components/drawer';
|
||||||
|
import {KTCollapse} from './components/collapse';
|
||||||
|
import {KTDismiss} from './components/dismiss';
|
||||||
|
import {KTTabs} from './components/tabs';
|
||||||
|
import {KTAccordion} from './components/accordion';
|
||||||
|
import {KTScrollspy} from './components/scrollspy';
|
||||||
|
import {KTScrollable} from './components/scrollable';
|
||||||
|
import {KTScrollto} from './components/scrollto';
|
||||||
|
import {KTSticky} from './components/sticky';
|
||||||
|
import {KTReparent} from './components/reparent';
|
||||||
|
import {KTToggle} from './components/toggle';
|
||||||
|
import {KTTooltip} from './components/tooltip';
|
||||||
|
import {KTStepper} from './components/stepper';
|
||||||
|
import {KTTheme} from './components/theme';
|
||||||
|
import {KTImageInput} from './components/image-input';
|
||||||
|
import {KTTogglePassword} from './components/toggle-password';
|
||||||
|
import {KTDataTable} from './components/datatable';
|
||||||
|
|
||||||
|
export {default as KTUtils} from './helpers/utils';
|
||||||
|
export {default as KTDom} from './helpers/dom';
|
||||||
|
export {default as KTEventHandler} from './helpers/event-handler';
|
||||||
|
export {KTMenu} from './components/menu';
|
||||||
|
export {KTDropdown} from './components/dropdown';
|
||||||
|
export {KTModal} from './components/modal';
|
||||||
|
export {KTDrawer} from './components/drawer';
|
||||||
|
export {KTCollapse} from './components/collapse';
|
||||||
|
export {KTDismiss} from './components/dismiss';
|
||||||
|
export {KTTabs} from './components/tabs';
|
||||||
|
export {KTAccordion} from './components/accordion';
|
||||||
|
export {KTScrollspy} from './components/scrollspy';
|
||||||
|
export {KTScrollable} from './components/scrollable';
|
||||||
|
export {KTScrollto} from './components/scrollto';
|
||||||
|
export {KTSticky} from './components/sticky';
|
||||||
|
export {KTReparent} from './components/reparent';
|
||||||
|
export {KTToggle} from './components/toggle'
|
||||||
|
export {KTTooltip} from './components/tooltip';
|
||||||
|
export {KTStepper} from './components/stepper';
|
||||||
|
export {KTTheme} from './components/theme';
|
||||||
|
export {KTImageInput} from './components/image-input';
|
||||||
|
export {KTTogglePassword} from './components/toggle-password';
|
||||||
|
export {KTDataTable} from './components/datatable';
|
||||||
|
|
||||||
|
declare let globalThis: {
|
||||||
|
KTUtils: typeof KTUtils,
|
||||||
|
KTDom: typeof KTDom,
|
||||||
|
KTEventHandler: typeof KTEventHandler;
|
||||||
|
KTMenu: typeof KTMenu;
|
||||||
|
KTDropdown: typeof KTDropdown;
|
||||||
|
KTModal: typeof KTModal;
|
||||||
|
KTDrawer: typeof KTDrawer;
|
||||||
|
KTCollapse: typeof KTCollapse;
|
||||||
|
KTDismiss: typeof KTDismiss;
|
||||||
|
KTTabs: typeof KTTabs;
|
||||||
|
KTAccordion: typeof KTAccordion;
|
||||||
|
KTScrollspy: typeof KTScrollspy;
|
||||||
|
KTScrollable: typeof KTScrollable;
|
||||||
|
KTScrollto: typeof KTScrollto;
|
||||||
|
KTSticky: typeof KTSticky;
|
||||||
|
KTReparent: typeof KTReparent;
|
||||||
|
KTToggle: typeof KTToggle;
|
||||||
|
KTTooltip: typeof KTTooltip;
|
||||||
|
KTStepper: typeof KTStepper;
|
||||||
|
KTTheme: typeof KTTheme;
|
||||||
|
KTImageInput: typeof KTImageInput;
|
||||||
|
KTTogglePassword: typeof KTTogglePassword;
|
||||||
|
};
|
||||||
|
|
||||||
|
globalThis.KTUtils = KTUtils;
|
||||||
|
globalThis.KTDom = KTDom;
|
||||||
|
globalThis.KTEventHandler = KTEventHandler;
|
||||||
|
globalThis.KTMenu = KTMenu;
|
||||||
|
globalThis.KTDropdown = KTDropdown;
|
||||||
|
globalThis.KTModal = KTModal;
|
||||||
|
globalThis.KTDrawer = KTDrawer;
|
||||||
|
globalThis.KTCollapse = KTCollapse;
|
||||||
|
globalThis.KTDismiss = KTDismiss;
|
||||||
|
globalThis.KTTabs = KTTabs;
|
||||||
|
globalThis.KTAccordion = KTAccordion;
|
||||||
|
globalThis.KTScrollspy = KTScrollspy;
|
||||||
|
globalThis.KTScrollable = KTScrollable;
|
||||||
|
globalThis.KTScrollto = KTScrollto;
|
||||||
|
globalThis.KTSticky = KTSticky;
|
||||||
|
globalThis.KTReparent = KTReparent;
|
||||||
|
globalThis.KTToggle = KTToggle;
|
||||||
|
globalThis.KTTooltip = KTTooltip;
|
||||||
|
globalThis.KTStepper = KTStepper;
|
||||||
|
globalThis.KTTheme = KTTheme;
|
||||||
|
globalThis.KTImageInput = KTImageInput;
|
||||||
|
globalThis.KTTogglePassword = KTTogglePassword;
|
||||||
|
|
||||||
|
const KTComponents = {
|
||||||
|
init(): void {
|
||||||
|
KTMenu.init();
|
||||||
|
KTDropdown.init();
|
||||||
|
KTModal.init();
|
||||||
|
KTDrawer.init();
|
||||||
|
KTCollapse.init();
|
||||||
|
KTDismiss.init();
|
||||||
|
KTTabs.init();
|
||||||
|
KTAccordion.init();
|
||||||
|
KTScrollspy.init();
|
||||||
|
KTScrollable.init();
|
||||||
|
KTScrollto.init();
|
||||||
|
KTSticky.init();
|
||||||
|
KTReparent.init();
|
||||||
|
KTToggle.init();
|
||||||
|
KTTooltip.init();
|
||||||
|
KTStepper.init();
|
||||||
|
KTTheme.init();
|
||||||
|
KTImageInput.init();
|
||||||
|
KTTogglePassword.init();
|
||||||
|
KTDataTable.init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default KTComponents;
|
137
resources/metronic/core/index.ts
Normal file
137
resources/metronic/core/index.ts
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Index
|
||||||
|
* @version: 1.0.0
|
||||||
|
* @author: Keenthemes
|
||||||
|
* Copyright 2024 Keenthemes
|
||||||
|
*/
|
||||||
|
import KTDom from './helpers/dom';
|
||||||
|
import KTUtils from './helpers/utils';
|
||||||
|
import KTEventHandler from './helpers/event-handler';
|
||||||
|
import { KTMenu } from './components/menu';
|
||||||
|
import { KTDropdown } from './components/dropdown';
|
||||||
|
import { KTModal } from './components/modal';
|
||||||
|
import { KTDrawer } from './components/drawer';
|
||||||
|
import { KTCollapse } from './components/collapse';
|
||||||
|
import { KTDismiss } from './components/dismiss';
|
||||||
|
import { KTTabs } from './components/tabs';
|
||||||
|
import { KTAccordion } from './components/accordion';
|
||||||
|
import { KTScrollspy } from './components/scrollspy';
|
||||||
|
import { KTScrollable } from './components/scrollable';
|
||||||
|
import { KTScrollto } from './components/scrollto';
|
||||||
|
import { KTSticky } from './components/sticky';
|
||||||
|
import { KTReparent } from './components/reparent';
|
||||||
|
import { KTToggle } from './components/toggle';
|
||||||
|
import { KTTooltip } from './components/tooltip';
|
||||||
|
import { KTStepper } from './components/stepper';
|
||||||
|
import { KTTheme } from './components/theme';
|
||||||
|
import { KTImageInput } from './components/image-input';
|
||||||
|
import { KTTogglePassword } from './components/toggle-password';
|
||||||
|
import { KTDataTable } from './components/datatable';
|
||||||
|
|
||||||
|
export { KTMenu } from './components/menu';
|
||||||
|
export { KTDropdown } from './components/dropdown';
|
||||||
|
export { KTModal } from './components/modal';
|
||||||
|
export { KTDrawer } from './components/drawer';
|
||||||
|
export { KTCollapse } from './components/collapse';
|
||||||
|
export { KTDismiss } from './components/dismiss';
|
||||||
|
export { KTTabs } from './components/tabs';
|
||||||
|
export { KTAccordion } from './components/accordion';
|
||||||
|
export { KTScrollspy } from './components/scrollspy';
|
||||||
|
export { KTScrollable } from './components/scrollable';
|
||||||
|
export { KTScrollto } from './components/scrollto';
|
||||||
|
export { KTSticky } from './components/sticky';
|
||||||
|
export { KTReparent } from './components/reparent';
|
||||||
|
export { KTToggle } from './components/toggle';
|
||||||
|
export { KTTooltip } from './components/tooltip';
|
||||||
|
export { KTStepper } from './components/stepper';
|
||||||
|
export { KTTheme } from './components/theme';
|
||||||
|
export { KTImageInput } from './components/image-input';
|
||||||
|
export { KTTogglePassword } from './components/toggle-password';
|
||||||
|
export { KTDataTable } from './components/datatable';
|
||||||
|
|
||||||
|
const KTComponents = {
|
||||||
|
init(): void {
|
||||||
|
KTMenu.init();
|
||||||
|
KTDropdown.init();
|
||||||
|
KTModal.init();
|
||||||
|
KTDrawer.init();
|
||||||
|
KTCollapse.init();
|
||||||
|
KTDismiss.init();
|
||||||
|
KTTabs.init();
|
||||||
|
KTAccordion.init();
|
||||||
|
KTScrollspy.init();
|
||||||
|
KTScrollable.init();
|
||||||
|
KTScrollto.init();
|
||||||
|
KTSticky.init();
|
||||||
|
KTReparent.init();
|
||||||
|
KTToggle.init();
|
||||||
|
KTTooltip.init();
|
||||||
|
KTStepper.init();
|
||||||
|
KTTheme.init();
|
||||||
|
KTImageInput.init();
|
||||||
|
KTTogglePassword.init();
|
||||||
|
KTDataTable.init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
KTUtils: typeof KTUtils;
|
||||||
|
KTDom: typeof KTDom;
|
||||||
|
KTEventHandler: typeof KTEventHandler;
|
||||||
|
KTMenu: typeof KTMenu;
|
||||||
|
KTDropdown: typeof KTDropdown;
|
||||||
|
KTModal: typeof KTModal;
|
||||||
|
KTDrawer: typeof KTDrawer;
|
||||||
|
KTCollapse: typeof KTCollapse;
|
||||||
|
KTDismiss: typeof KTDismiss;
|
||||||
|
KTTabs: typeof KTTabs;
|
||||||
|
KTAccordion: typeof KTAccordion;
|
||||||
|
KTScrollspy: typeof KTScrollspy;
|
||||||
|
KTScrollable: typeof KTScrollable;
|
||||||
|
KTScrollto: typeof KTScrollto;
|
||||||
|
KTSticky: typeof KTSticky;
|
||||||
|
KTReparent: typeof KTReparent;
|
||||||
|
KTToggle: typeof KTToggle;
|
||||||
|
KTTooltip: typeof KTTooltip;
|
||||||
|
KTStepper: typeof KTStepper;
|
||||||
|
KTTheme: typeof KTTheme;
|
||||||
|
KTImageInput: typeof KTImageInput;
|
||||||
|
KTTogglePassword: typeof KTTogglePassword;
|
||||||
|
KTDataTable: typeof KTDataTable;
|
||||||
|
KTComponents: typeof KTComponents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.KTUtils = KTUtils;
|
||||||
|
window.KTDom = KTDom;
|
||||||
|
window.KTEventHandler = KTEventHandler;
|
||||||
|
window.KTMenu = KTMenu;
|
||||||
|
window.KTDropdown = KTDropdown;
|
||||||
|
window.KTModal = KTModal;
|
||||||
|
window.KTDrawer = KTDrawer;
|
||||||
|
window.KTCollapse = KTCollapse;
|
||||||
|
window.KTDismiss = KTDismiss;
|
||||||
|
window.KTTabs = KTTabs;
|
||||||
|
window.KTAccordion = KTAccordion;
|
||||||
|
window.KTScrollspy = KTScrollspy;
|
||||||
|
window.KTScrollable = KTScrollable;
|
||||||
|
window.KTScrollto = KTScrollto;
|
||||||
|
window.KTSticky = KTSticky;
|
||||||
|
window.KTReparent = KTReparent;
|
||||||
|
window.KTToggle = KTToggle;
|
||||||
|
window.KTTooltip = KTTooltip;
|
||||||
|
window.KTStepper = KTStepper;
|
||||||
|
window.KTTheme = KTTheme;
|
||||||
|
window.KTImageInput = KTImageInput;
|
||||||
|
window.KTTogglePassword = KTTogglePassword;
|
||||||
|
window.KTDataTable = KTDataTable;
|
||||||
|
window.KTComponents = KTComponents;
|
||||||
|
|
||||||
|
export default KTComponents;
|
||||||
|
|
||||||
|
KTDom.ready(() => {
|
||||||
|
KTComponents.init();
|
||||||
|
});
|
||||||
|
|
25
resources/metronic/core/plugins/components/accordion.js
Normal file
25
resources/metronic/core/plugins/components/accordion.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents}) => {
|
||||||
|
addComponents({
|
||||||
|
'.accordion-item': {
|
||||||
|
'display': 'flex',
|
||||||
|
'flex-direction': 'column',
|
||||||
|
},
|
||||||
|
'.accordion-toggle': {
|
||||||
|
'display': 'flex',
|
||||||
|
'flex-grow': '1',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'space-between',
|
||||||
|
},
|
||||||
|
'.accordion-content': {
|
||||||
|
'transition': 'height 300ms ease',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
'.accordion.active &': {
|
||||||
|
'display': 'block',
|
||||||
|
'transition': 'height 300ms ease'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
114
resources/metronic/core/plugins/components/apexcharts.js
Normal file
114
resources/metronic/core/plugins/components/apexcharts.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.apexcharts-text, .apexcharts-title-text, .apexcharts-legend-text': {
|
||||||
|
'font-family': 'inherit !important',
|
||||||
|
},
|
||||||
|
'.apexcharts-title-text': {
|
||||||
|
'font-weight': theme('fontWeight.normal'),
|
||||||
|
},
|
||||||
|
'.apexcharts-pie-label': {
|
||||||
|
'font-size': theme('fontSize.xs'),
|
||||||
|
'line-height': theme('fontSize.xs.1.lineHeight'),
|
||||||
|
},
|
||||||
|
'.apexcharts-toolbar': {
|
||||||
|
'text-align': 'left !important',
|
||||||
|
},
|
||||||
|
'.apexcharts-menu': {
|
||||||
|
'border': '1px solid var(--tw-gray-200) !important',
|
||||||
|
'box-shadow': 'var(--tw-default-box-shadow) !important',
|
||||||
|
'background-color': 'var(--tw-light) !important',
|
||||||
|
'border-radius': '0.625rem !important',
|
||||||
|
'padding': '0.5rem 0 !important',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
'min-width': '10rem !important',
|
||||||
|
'.apexcharts-menu-item': {
|
||||||
|
'padding': '0.5rem 0.5rem !important',
|
||||||
|
'&:hover': {
|
||||||
|
'background-color': 'var(--tw-gray-100) !important'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.apexcharts-tooltip': {
|
||||||
|
'border': '1px solid var(--tw-gray-200) !important',
|
||||||
|
'box-shadow': 'var(--tw-default-box-shadow) !important',
|
||||||
|
'background-color': 'var(--tw-light) !important',
|
||||||
|
'border-radius': '0.625rem !important',
|
||||||
|
'color': 'var(--tw-gray-700) !important',
|
||||||
|
'.apexcharts-tooltip-title': {
|
||||||
|
'padding': '0.25rem 0.5rem !important',
|
||||||
|
'background-color': 'transparent !important',
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'line-height': theme('fontSize.2sm.1.lineHeight'),
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
'border-bottom': '1px solid var(--tw-gray-200) !important',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.apexcharts-xaxistooltip': {
|
||||||
|
'border': '1px solid var(--tw-gray-200) !important',
|
||||||
|
'box-shadow': 'var(--tw-default-box-shadow)',
|
||||||
|
'background-color': 'var(--tw-light) !important',
|
||||||
|
'border-radius': '0.625rem',
|
||||||
|
'color': 'var(--tw-gray-900)',
|
||||||
|
'&:before': {
|
||||||
|
'border-bottom': '0 !important',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.apexcharts-legend': {
|
||||||
|
'display': 'flex',
|
||||||
|
'flex-direction': 'column',
|
||||||
|
'gap': theme('spacing.2'),
|
||||||
|
'.apexcharts-legend-series': {
|
||||||
|
'gap': theme('spacing.1'),
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'.apexcharts-legend-text': {
|
||||||
|
'font-size': `${theme('fontSize.sm')}`,
|
||||||
|
'line-height': theme('fontSize.sm.1.lineHeight'),
|
||||||
|
'font-weight': `${theme('fontWeight.medium')}`,
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.apexcharts-card-rounded': {
|
||||||
|
'.apexcharts-canvas': {
|
||||||
|
'svg': {
|
||||||
|
'border-bottom-left-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
'border-bottom-right-radius': theme('custom.components.common.borderRadius.card')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.apexcharts-rounded-sm': {
|
||||||
|
'.apexcharts-canvas': {
|
||||||
|
'svg': {
|
||||||
|
'border-radius': theme('borderRadius.sm'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.apexcharts-rounded': {
|
||||||
|
'.apexcharts-canvas': {
|
||||||
|
'svg': {
|
||||||
|
'border-radius': theme('borderRadius.DEFAULT'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.apexcharts-rounded-lg': {
|
||||||
|
'.apexcharts-canvas': {
|
||||||
|
'svg': {
|
||||||
|
'border-radius': theme('borderRadius.lg'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.apexcharts-rounded-xl': {
|
||||||
|
'.apexcharts-canvas': {
|
||||||
|
'svg': {
|
||||||
|
'border-radius': theme('borderRadius.xl'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
88
resources/metronic/core/plugins/components/badge.js
Normal file
88
resources/metronic/core/plugins/components/badge.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.badge': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'center',
|
||||||
|
'line-height': '1',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.badge'),
|
||||||
|
'padding': '0.5rem 0.5rem',
|
||||||
|
'border': '1px solid transparent',
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'font-size': '0.6875rem',
|
||||||
|
'&.badge-pill': {
|
||||||
|
'border-radius': '1.875rem',
|
||||||
|
'padding-left': '0.625rem',
|
||||||
|
'padding-right': '0.625rem'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.badge-dot': {
|
||||||
|
'padding':'0',
|
||||||
|
'border-radius': '50%'
|
||||||
|
},
|
||||||
|
'.badge-circle': {
|
||||||
|
'padding':'0',
|
||||||
|
'border-radius': '50%',
|
||||||
|
'flex-shrink': '0',
|
||||||
|
'line-height': '0'
|
||||||
|
},
|
||||||
|
'.badge-xs': {
|
||||||
|
'font-size': '0.625rem',
|
||||||
|
'padding': '0.1875rem 0.3125rem',
|
||||||
|
'&.badge-pill': {
|
||||||
|
'padding-left': '0.25rem',
|
||||||
|
'padding-right': '0.25rem'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.badge-sm': {
|
||||||
|
'padding': '0.3125rem 0.375rem',
|
||||||
|
'&.badge-pill': {
|
||||||
|
'padding-left': '0.375rem',
|
||||||
|
'padding-right': '0.375rem'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.badge-lg': {
|
||||||
|
'padding': '0.5625rem 0.6875rem',
|
||||||
|
'font-size': '0.8125rem',
|
||||||
|
'&.badge-pill': {
|
||||||
|
'padding-left': '0.6875rem',
|
||||||
|
'padding-right': '0.6875rem',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Default option
|
||||||
|
addComponents({
|
||||||
|
'.badge': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'background-color': 'var(--tw-gray-200)',
|
||||||
|
},
|
||||||
|
'.badge-outline': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
'border-color': 'var(--tw-gray-300)',
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Color options
|
||||||
|
const colors = ['primary', 'success', 'danger', 'warning', 'info', 'dark'];
|
||||||
|
|
||||||
|
colors.forEach((color) => {
|
||||||
|
addComponents({
|
||||||
|
[`.badge-${color}`]: {
|
||||||
|
'color': theme('colors.white'),
|
||||||
|
'background-color': `var(--tw-${color})`
|
||||||
|
},
|
||||||
|
[`.badge-outline.badge-${color}`]: {
|
||||||
|
'color': `var(--tw-${color})`,
|
||||||
|
'background-color': `var(--tw-${color}-light)`,
|
||||||
|
'border-color': `var(--tw-${color}-clarity)`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
10
resources/metronic/core/plugins/components/breakpoints.js
Normal file
10
resources/metronic/core/plugins/components/breakpoints.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addVariant, config}) => {
|
||||||
|
const screens = config().theme.screens;
|
||||||
|
|
||||||
|
for (const screen of Object.keys(screens)) {
|
||||||
|
addVariant(`below-${screen}`, `@media screen and (max-width: theme('screens.${screen}'))`);
|
||||||
|
}
|
||||||
|
});
|
20
resources/metronic/core/plugins/components/btn-group.js
Normal file
20
resources/metronic/core/plugins/components/btn-group.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents}) => {
|
||||||
|
addComponents({
|
||||||
|
'.btn-group': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'stretch',
|
||||||
|
'.btn + .btn': {
|
||||||
|
'border-top-left-radius': '0',
|
||||||
|
'border-bottom-left-radius': '0',
|
||||||
|
'border-left': '0'
|
||||||
|
},
|
||||||
|
'.btn:has(+ .btn)': {
|
||||||
|
'border-top-right-radius': '0',
|
||||||
|
'border-bottom-right-radius': '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
471
resources/metronic/core/plugins/components/btn.js
Normal file
471
resources/metronic/core/plugins/components/btn.js
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.btn': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'line-height': '1',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.btn'),
|
||||||
|
'height': theme('custom.components.btn.DEFAULT.height'),
|
||||||
|
'padding-left': theme('custom.components.btn.DEFAULT.px'),
|
||||||
|
'padding-right': theme('custom.components.btn.DEFAULT.px'),
|
||||||
|
'gap': theme('custom.components.btn.DEFAULT.gap'),
|
||||||
|
'border': '1px solid transparent',
|
||||||
|
'font-weight': theme('custom.components.btn.DEFAULT.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.fontSize'),
|
||||||
|
'outline': 'none'
|
||||||
|
},
|
||||||
|
'.btn-icon': {
|
||||||
|
'flex-shrink': '0',
|
||||||
|
'padding': '0',
|
||||||
|
'gap': '0',
|
||||||
|
'width': theme('custom.components.btn.DEFAULT.height'),
|
||||||
|
'i': {
|
||||||
|
'line-height': '0 !important'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-xs': {
|
||||||
|
'height': theme('custom.components.btn.xs.height'),
|
||||||
|
'padding-left': theme('custom.components.btn.xs.px'),
|
||||||
|
'padding-right': theme('custom.components.btn.xs.px'),
|
||||||
|
'font-weight': theme('custom.components.btn.xs.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.xs.fontSize'),
|
||||||
|
'gap': theme('custom.components.btn.xs.gap'),
|
||||||
|
'&.btn-icon': {
|
||||||
|
'width': theme('custom.components.btn.xs.height')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-sm': {
|
||||||
|
'height': theme('custom.components.btn.sm.height'),
|
||||||
|
'padding-left': theme('custom.components.btn.sm.px'),
|
||||||
|
'padding-right': theme('custom.components.btn.sm.px'),
|
||||||
|
'font-weight': theme('custom.components.btn.sm.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.sm.fontSize'),
|
||||||
|
'gap': theme('custom.components.btn.sm.gap'),
|
||||||
|
'&.btn-icon': {
|
||||||
|
'width': theme('custom.components.btn.sm.height')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-lg': {
|
||||||
|
'height': theme('custom.components.btn.lg.height'),
|
||||||
|
'padding-left': theme('custom.components.btn.lg.px'),
|
||||||
|
'padding-right': theme('custom.components.btn.lg.px'),
|
||||||
|
'font-weight': theme('custom.components.btn.lg.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.lg.fontSize'),
|
||||||
|
'gap': theme('custom.components.btn.lg.gap'),
|
||||||
|
'&.btn-icon': {
|
||||||
|
'width': theme('custom.components.btn.lg.height')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disabled state
|
||||||
|
addComponents({
|
||||||
|
'.btn': {
|
||||||
|
'&[disabled], &.disabled': {
|
||||||
|
'opacity': '0.5',
|
||||||
|
'pointer-events': 'none'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only icon option
|
||||||
|
addComponents({
|
||||||
|
'.btn-icon': {
|
||||||
|
'justify-content': 'center',
|
||||||
|
'flex-shrink': '0',
|
||||||
|
'padding': '0',
|
||||||
|
'gap': '0',
|
||||||
|
'width': theme('custom.components.btn.DEFAULT.height')
|
||||||
|
},
|
||||||
|
'.btn-icon.btn-xs': {
|
||||||
|
'width': theme('custom.components.btn.xs.height')
|
||||||
|
},
|
||||||
|
'.btn-icon.btn-sm': {
|
||||||
|
'width': theme('custom.components.btn.sm.height')
|
||||||
|
},
|
||||||
|
'.btn-icon.btn-lg': {
|
||||||
|
'width': theme('custom.components.btn.lg.height')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Icon sizes
|
||||||
|
addComponents({
|
||||||
|
'.btn': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.iconFontSize'),
|
||||||
|
'line-height': '0 !important',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-icon': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.onlyIconFontSize'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-xs': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.xs.iconFontSize'),
|
||||||
|
},
|
||||||
|
'&.btn-icon': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.xs.onlyIconFontSize'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-sm': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.sm.iconFontSize'),
|
||||||
|
},
|
||||||
|
'&.btn-icon': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.sm.onlyIconFontSize'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-lg': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.lg.iconFontSize'),
|
||||||
|
},
|
||||||
|
'&.btn-icon': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.lg.onlyIconFontSize'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-icon-xs': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.xs')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-icon-sm': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.sm')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-icon-md': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.md')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-icon-lg': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.lg')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-icon-xl': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.xl')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-icon-2xl': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.2xl')}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Icon extended sizes
|
||||||
|
addComponents({
|
||||||
|
'.btn': {
|
||||||
|
'&.btn-icon-sm': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.sm')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.btn-icon-md': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.md')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.btn-icon-lg': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.lg')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.btn-icon-xl': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.xl')}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.btn-icon-2xl': {
|
||||||
|
'i': {
|
||||||
|
'font-size': `${theme('fontSize.2xl')}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Link varaint
|
||||||
|
addComponents({
|
||||||
|
'.btn-link': {
|
||||||
|
'color': 'var(--tw-primary)',
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'height': 'auto',
|
||||||
|
'padding-bottom': '0.25em',
|
||||||
|
'padding-left': '0',
|
||||||
|
'padding-right': '0',
|
||||||
|
'border-radius': '0',
|
||||||
|
'font-weight': theme('fontWeight.semibold'),
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'border-bottom': '1px dashed var(--tw-primary)',
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'border-bottom': '1px dashed var(--tw-primary-active)',
|
||||||
|
'color': 'var(--tw-primary-active)',
|
||||||
|
},
|
||||||
|
'&.btn-sm': {
|
||||||
|
'font-size': theme('fontSize.xs'),
|
||||||
|
},
|
||||||
|
'&.btn-lg': {
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tabs
|
||||||
|
addComponents({
|
||||||
|
'.btn-tabs': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'line-height': '1',
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'border': '1px solid var(--tw-gray-200)',
|
||||||
|
'.btn': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
},
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'background-color': 'var(--tw-light)',
|
||||||
|
'border': '1px solid var(--tw-gray-200)',
|
||||||
|
'color': 'var(--tw-gray-900)',
|
||||||
|
'box-shadow': 'var(--tw-light-box-shadow)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tabs sizes
|
||||||
|
addComponents({
|
||||||
|
'.btn-tabs': {
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.btn'),
|
||||||
|
'height': theme('custom.components.btn.DEFAULT.height'),
|
||||||
|
'padding': theme('custom.components.btn.DEFAULT.tabsGap'),
|
||||||
|
'gap': theme('custom.components.btn.DEFAULT.tabsGap'),
|
||||||
|
'.btn': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.iconFontSize'),
|
||||||
|
},
|
||||||
|
'height': `calc(${theme('custom.components.btn.DEFAULT.height')} - 2 * ${theme('custom.components.btn.DEFAULT.tabsGap')})`,
|
||||||
|
'&.btn-icon': {
|
||||||
|
'width': `calc(${theme('custom.components.btn.DEFAULT.height')} - 2 * ${theme('custom.components.btn.DEFAULT.tabsGap')})`,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.btn-tabs-sm': {
|
||||||
|
'height': theme('custom.components.btn.sm.height'),
|
||||||
|
'padding': theme('custom.components.btn.sm.tabsGap'),
|
||||||
|
'gap': theme('custom.components.btn.sm.tabsGap'),
|
||||||
|
'.btn': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.sm.iconFontSize'),
|
||||||
|
},
|
||||||
|
'height': `calc(${theme('custom.components.btn.sm.height')} - 2 * ${theme('custom.components.btn.sm.tabsGap')})`,
|
||||||
|
'&.btn-icon': {
|
||||||
|
'width': `calc(${theme('custom.components.btn.sm.height')} - 2 * ${theme('custom.components.btn.sm.tabsGap')})`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.btn-tabs-lg': {
|
||||||
|
'height': theme('custom.components.btn.lg.height'),
|
||||||
|
'padding': theme('custom.components.btn.lg.tabsGap'),
|
||||||
|
'gap': theme('custom.components.btn.lg.tabsGap'),
|
||||||
|
'.btn': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.lg.iconFontSize'),
|
||||||
|
},
|
||||||
|
'height': `calc(${theme('custom.components.btn.lg.height')} - 2 * ${theme('custom.components.btn.lg.tabsGap')})`,
|
||||||
|
'&.btn-icon': {
|
||||||
|
'width': `calc(${theme('custom.components.btn.lg.height')} - 2 * ${theme('custom.components.btn.lg.tabsGap')})`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Input
|
||||||
|
addComponents({
|
||||||
|
'.btn-input': {
|
||||||
|
'cursor': 'auto',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'border-color': 'var(--tw-gray-300)',
|
||||||
|
'background-color': 'var(--tw-light-active)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Color varaints
|
||||||
|
const colors = ['primary', 'success', 'danger', 'warning', 'info', 'dark', 'light', 'secondary'];
|
||||||
|
|
||||||
|
colors.forEach((color) => {
|
||||||
|
if (color === 'light') {
|
||||||
|
addComponents({
|
||||||
|
'.btn-light': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'border-color': 'var(--tw-gray-300)',
|
||||||
|
'background-color': 'var(--tw-light)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
},
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'border-color': 'var(--tw-gray-300)',
|
||||||
|
'background-color': 'var(--tw-light-active)',
|
||||||
|
'box-shadow': 'var(--tw-default-box-shadow)',
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&[disabled], &.disabled': {
|
||||||
|
'opacity': '1',
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
'border-color': 'var(--tw-gray-200)',
|
||||||
|
'background-color': 'var(--tw-light)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.btn-light.btn-clear': {
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'background-color': 'var(--tw-gray-200)',
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&[disabled], &.disabled': {
|
||||||
|
'opacity': '1',
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (color === 'secondary') {
|
||||||
|
addComponents({
|
||||||
|
'.btn-secondary': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'border-color': 'var(--tw-gray-200)',
|
||||||
|
'background-color': 'var(--tw-secondary)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
},
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'border-color': 'var(--tw-gray-300)',
|
||||||
|
'background-color': 'var(--tw-secondary-active)',
|
||||||
|
'box-shadow': 'var(--tw-default-box-shadow)',
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&[disabled], &.disabled': {
|
||||||
|
'opacity': '1',
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
'border-color': 'var(--tw-gray-200)',
|
||||||
|
'background-color': 'var(--tw-light)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addComponents({
|
||||||
|
[`.btn-${color}`]: {
|
||||||
|
'color': theme('colors.white'),
|
||||||
|
'background-color': `var(--tw-${color})`,
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'background-color': `var(--tw-${color}-active)`,
|
||||||
|
'box-shadow': `var(--tw-${color}-box-shadow)`,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[`.btn-outline.btn-${color}`]: {
|
||||||
|
'color': `var(--tw-${color})`,
|
||||||
|
'background-color': `var(--tw-${color}-light)`,
|
||||||
|
'border-color': `var(--tw-${color}-clarity)`,
|
||||||
|
'i': {
|
||||||
|
'color': `var(--tw-${color})`,
|
||||||
|
},
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'color': `var(--tw-${color}-inverse)`,
|
||||||
|
'background-color': `var(--tw-${color})`,
|
||||||
|
'border-color': `var(--tw-${color})`,
|
||||||
|
'box-shadow': `none`,
|
||||||
|
'i': {
|
||||||
|
'color': `var(--tw-${color}-inverse)`
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[`.btn-clear.btn-${color}`]: {
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'color': `var(--tw-${color})`,
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'color': `var(--tw-${color}-inverse)`,
|
||||||
|
'background-color': `var(--tw-${color})`,
|
||||||
|
'border-color': `var(--tw-${color})`,
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'i': {
|
||||||
|
'color': `var(--tw-${color}-inverse)`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[`.btn-subtle.btn-${color}`]: {
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'color': `var(--tw-${color})`,
|
||||||
|
'i': {
|
||||||
|
'color': `var(--tw-${color})`
|
||||||
|
},
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'color': `var(--tw-${color})`,
|
||||||
|
'background-color': `var(--tw-${color}-light)`,
|
||||||
|
'border-color': `var(--tw-${color}-light)`,
|
||||||
|
'box-shadow': `none`,
|
||||||
|
'i': {
|
||||||
|
'color': `var(--tw-${color})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
addComponents({
|
||||||
|
'.btn-rounded': {
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.btn')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
151
resources/metronic/core/plugins/components/card.js
Normal file
151
resources/metronic/core/plugins/components/card.js
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.card': {
|
||||||
|
'display': 'flex',
|
||||||
|
'flex-direction': 'column',
|
||||||
|
'box-shadow': 'var(--tw-card-box-shadow)',
|
||||||
|
'background-color': 'var(--tw-card-background-color)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
'border': 'var(--tw-card-border)',
|
||||||
|
},
|
||||||
|
'.card-title': {
|
||||||
|
'font-size': theme('fontSize.base'),
|
||||||
|
'line-height': theme('fontSize.base.1.lineHeight'),
|
||||||
|
'font-weight': theme('fontWeight.semibold'),
|
||||||
|
'color': 'var(--tw-gray-900)',
|
||||||
|
},
|
||||||
|
'.card-header': {
|
||||||
|
'display': 'flex',
|
||||||
|
'min-height': '56px',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'space-between',
|
||||||
|
'border-bottom': 'var(--tw-card-border)',
|
||||||
|
'padding-left': theme('custom.components.card.px'),
|
||||||
|
'padding-right': theme('custom.components.card.px'),
|
||||||
|
'padding-top': theme('custom.components.card.py.header'),
|
||||||
|
'padding-bottom': theme('custom.components.card.py.header'),
|
||||||
|
},
|
||||||
|
'.card-body': {
|
||||||
|
'flex-grow': '1',
|
||||||
|
'padding-left': theme('custom.components.card.px'),
|
||||||
|
'padding-right': theme('custom.components.card.px'),
|
||||||
|
'padding-top': theme('custom.components.card.py.body'),
|
||||||
|
'padding-bottom': theme('custom.components.card.py.body'),
|
||||||
|
},
|
||||||
|
'.card-footer': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'space-between',
|
||||||
|
'border-top': 'var(--tw-card-border)',
|
||||||
|
'padding-left': theme('custom.components.card.px'),
|
||||||
|
'padding-right': theme('custom.components.card.px'),
|
||||||
|
'padding-top': theme('custom.components.card.py.footer'),
|
||||||
|
'padding-bottom': theme('custom.components.card.py.footer'),
|
||||||
|
},
|
||||||
|
'.card-table': {
|
||||||
|
'table': {
|
||||||
|
'th:first-child, td:first-child': {
|
||||||
|
'padding-left': theme('custom.components.card.px'),
|
||||||
|
},
|
||||||
|
'th:last-child, td:last-child': {
|
||||||
|
'padding-right': theme('custom.components.card.px'),
|
||||||
|
},
|
||||||
|
'&.table-border': {
|
||||||
|
'border': '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.card-group': {
|
||||||
|
'padding-left': theme('custom.components.card.px'),
|
||||||
|
'padding-right': theme('custom.components.card.px'),
|
||||||
|
'padding-top': theme('custom.components.card.py.group'),
|
||||||
|
'padding-bottom': theme('custom.components.card.py.group'),
|
||||||
|
'border-bottom': 'var(--tw-card-border)',
|
||||||
|
'&:last-child': {
|
||||||
|
'border-bottom': '0',
|
||||||
|
},
|
||||||
|
'& + .card-footer': {
|
||||||
|
'border-top': '0',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Border radius
|
||||||
|
addComponents({
|
||||||
|
'.table': {
|
||||||
|
'th:first-child': {
|
||||||
|
'border-top-left-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
},
|
||||||
|
'th:last-child': {
|
||||||
|
'border-top-right-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.card-header + .card-body, .card-header + .card-table': {
|
||||||
|
'table': {
|
||||||
|
'th:first-child, th:last-child': {
|
||||||
|
'border-radius': '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Grid
|
||||||
|
addComponents({
|
||||||
|
'.card-grid': {
|
||||||
|
'.card-header, .card-footer': {
|
||||||
|
'padding-left': theme('custom.components.card.grid.px'),
|
||||||
|
'padding-right': theme('custom.components.card.grid.px')
|
||||||
|
},
|
||||||
|
'.card-body': {
|
||||||
|
'padding': '0',
|
||||||
|
'table': {
|
||||||
|
'border': '0',
|
||||||
|
'th:first-child, td:first-child': {
|
||||||
|
'padding-left': theme('custom.components.card.grid.px')
|
||||||
|
},
|
||||||
|
'th:last-child, td:last-child': {
|
||||||
|
'padding-right': theme('custom.components.card.grid.px')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
addComponents({
|
||||||
|
'.card-border': {
|
||||||
|
'border': 'var(--tw-card-border)'
|
||||||
|
},
|
||||||
|
'.card-rounded': {
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
'&.table': {
|
||||||
|
'border-collapse': 'separate',
|
||||||
|
'border-spacing': '0'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.card-rounded-b': {
|
||||||
|
'border-bottom-left-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
'border-bottom-right-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
},
|
||||||
|
'.card-rounded-bl': {
|
||||||
|
'border-bottom-left-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
},
|
||||||
|
'.card-rounded-br': {
|
||||||
|
'border-bottom-right-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
},
|
||||||
|
'.card-rounded-t': {
|
||||||
|
'border-top-left-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
'border-top-right-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
},
|
||||||
|
'.card-rounded-tl': {
|
||||||
|
'border-top-left-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
},
|
||||||
|
'.card-rounded-tr': {
|
||||||
|
'border-top-right-radius': theme('custom.components.common.borderRadius.card'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
103
resources/metronic/core/plugins/components/checkbox.js
Normal file
103
resources/metronic/core/plugins/components/checkbox.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
import svgToDataUri from 'mini-svg-data-uri';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Checkbox
|
||||||
|
addComponents({
|
||||||
|
'.checkbox[type="checkbox"]': {
|
||||||
|
'flex-shrink': '0',
|
||||||
|
'appearance': 'none',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'background-color': 'var(--tw-light-light)',
|
||||||
|
'border-radius': theme('custom.components.checkbox.DEFAULT.borderRadius'),
|
||||||
|
'height': theme('custom.components.checkbox.DEFAULT.size'),
|
||||||
|
'width': theme('custom.components.checkbox.DEFAULT.size'),
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'background-repeat': 'no-repeat',
|
||||||
|
'background-position': 'center',
|
||||||
|
'background-size': 'auto',
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-color': 'var(--tw-primary)',
|
||||||
|
'border': '1px solid var(--tw-primary)',
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="12" height="9" viewBox="0 0 12 9" fill="none"><path d="M10.3667 0.541643L4.80007 6.10831L1.56674 2.87498C1.41061 2.71977 1.1994 2.63265 0.979241 2.63265C0.759086 2.63265 0.547876 2.71977 0.391741 2.87498C0.236532 3.03111 0.149414 3.24232 0.149414 3.46248C0.149414 3.68263 0.236532 3.89384 0.391741 4.04998L4.21674 7.87498C4.37288 8.03019 4.58409 8.1173 4.80424 8.1173C5.0244 8.1173 5.23561 8.03019 5.39174 7.87498L11.5417 1.72498C11.6198 1.64751 11.6818 1.55534 11.7241 1.45379C11.7665 1.35224 11.7882 1.24332 11.7882 1.13331C11.7882 1.0233 11.7665 0.914379 11.7241 0.81283C11.6818 0.711281 11.6198 0.619113 11.5417 0.541643C11.3856 0.386434 11.1744 0.299316 10.9542 0.299316C10.7341 0.299316 10.5229 0.386434 10.3667 0.541643Z" fill="white"/></svg>')}")`
|
||||||
|
},
|
||||||
|
'&:indeterminate': {
|
||||||
|
'background-color': 'var(--tw-primary)',
|
||||||
|
'border': '1px solid var(--tw-primary)',
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M6 10h8"/></svg>')}")`
|
||||||
|
},
|
||||||
|
'&:focus': {
|
||||||
|
'border-color': 'var(--tw-primary)',
|
||||||
|
'box-shadow': 'var(--tw-input-focus-box-shadow)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&:active': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
'box-shadow': 'none',
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
'cursor': 'not-allowed',
|
||||||
|
'background-color': 'var(--tw-gray-200)',
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'&:indeterminate': {
|
||||||
|
'background-color': 'var(--tw-primary-clarity)',
|
||||||
|
'border': '0',
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path fill="none" stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M6 10h8"/></svg>')}")`
|
||||||
|
},
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-color': 'var(--tw-primary-clarity)',
|
||||||
|
'border': '0',
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="12" height="9" viewBox="0 0 12 9" fill="none"><path d="M10.3667 0.541643L4.80007 6.10831L1.56674 2.87498C1.41061 2.71977 1.1994 2.63265 0.979241 2.63265C0.759086 2.63265 0.547876 2.71977 0.391741 2.87498C0.236532 3.03111 0.149414 3.24232 0.149414 3.46248C0.149414 3.68263 0.236532 3.89384 0.391741 4.04998L4.21674 7.87498C4.37288 8.03019 4.58409 8.1173 4.80424 8.1173C5.0244 8.1173 5.23561 8.03019 5.39174 7.87498L11.5417 1.72498C11.6198 1.64751 11.6818 1.55534 11.7241 1.45379C11.7665 1.35224 11.7882 1.24332 11.7882 1.13331C11.7882 1.0233 11.7665 0.914379 11.7241 0.81283C11.6818 0.711281 11.6198 0.619113 11.5417 0.541643C11.3856 0.386434 11.1744 0.299316 10.9542 0.299316C10.7341 0.299316 10.5229 0.386434 10.3667 0.541643Z" fill="white"/></svg>')}")`
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.checkbox-sm[type="checkbox"]': {
|
||||||
|
'border-radius': theme('custom.components.checkbox.sm.borderRadius'),
|
||||||
|
'height': theme('custom.components.checkbox.sm.size'),
|
||||||
|
'width': theme('custom.components.checkbox.sm.size'),
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="10" height="7" viewBox="0 0 10 7" fill="none"><path d="M8.4932 0.23329L4.03986 4.68662L1.4532 2.09996C1.32829 1.97579 1.15932 1.9061 0.983198 1.9061C0.807074 1.9061 0.638106 1.97579 0.513198 2.09996C0.38903 2.22487 0.319336 2.39383 0.319336 2.56996C0.319336 2.74608 0.38903 2.91505 0.513198 3.03996L3.5732 6.09996C3.69811 6.22412 3.86707 6.29382 4.0432 6.29382C4.21932 6.29382 4.38829 6.22412 4.5132 6.09996L9.4332 1.17996C9.49568 1.11798 9.54528 1.04425 9.57912 0.963008C9.61297 0.881768 9.6304 0.794632 9.6304 0.706624C9.6304 0.618616 9.61297 0.531479 9.57912 0.45024C9.54528 0.369 9.49568 0.295266 9.4332 0.23329C9.30829 0.109123 9.13932 0.0394287 8.9632 0.0394287C8.78707 0.0394287 8.61811 0.109123 8.4932 0.23329Z" fill="white"/></svg>')}")`
|
||||||
|
},
|
||||||
|
'&:indeterminate': {
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="10" height="2" viewBox="0 0 10 2" fill="none"><path d="M9.04638 0.293335L1.03971 0.333335C0.862903 0.333335 0.693333 0.403573 0.568309 0.528598C0.443285 0.653622 0.373047 0.823191 0.373047 1C0.373047 1.17681 0.443285 1.34638 0.568309 1.47141C0.693333 1.59643 0.862903 1.66667 1.03971 1.66667L9.03971 1.62667C9.21653 1.62667 9.3861 1.55643 9.51112 1.43141C9.63614 1.30638 9.70638 1.13681 9.70638 0.960002C9.70638 0.783191 9.63614 0.613622 9.51112 0.488597C9.3861 0.363573 9.21653 0.293335 9.03971 0.293335H9.04638Z" fill="white"/></svg>')}")`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.checkbox-lg[type="checkbox"]': {
|
||||||
|
'border-radius': theme('custom.components.checkbox.lg.borderRadius'),
|
||||||
|
'height': theme('custom.components.checkbox.lg.size'),
|
||||||
|
'width': theme('custom.components.checkbox.lg.size'),
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="15" height="10" viewBox="0 0 15 10" fill="none"><path d="M13.2403 0.849997L6.56029 7.53L2.68028 3.65C2.49292 3.46375 2.23947 3.3592 1.97528 3.3592C1.7111 3.3592 1.45765 3.46375 1.27028 3.65C1.08403 3.83736 0.979492 4.09081 0.979492 4.355C0.979492 4.61918 1.08403 4.87263 1.27028 5.06L5.86028 9.65C6.04765 9.83625 6.3011 9.94079 6.56528 9.94079C6.82947 9.94079 7.08292 9.83625 7.27029 9.65L14.6503 2.27C14.744 2.17703 14.8184 2.06643 14.8692 1.94457C14.9199 1.82271 14.9461 1.69201 14.9461 1.56C14.9461 1.42799 14.9199 1.29728 14.8692 1.17542C14.8184 1.05356 14.744 0.94296 14.6503 0.849997C14.4629 0.663746 14.2095 0.559204 13.9453 0.559204C13.6811 0.559204 13.4276 0.663746 13.2403 0.849997Z" fill="white"/></svg>')}")`
|
||||||
|
},
|
||||||
|
'&:indeterminate': {
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="15" height="3" viewBox="0 0 15 3" fill="none"><path d="M13.0696 0.939941L1.05957 0.999942C0.794354 0.999942 0.54 1.1053 0.352464 1.29284C0.164927 1.48037 0.0595703 1.73473 0.0595703 1.99994C0.0595703 2.26516 0.164927 2.51951 0.352464 2.70705C0.54 2.89458 0.794354 2.99994 1.05957 2.99994L13.0596 2.93994C13.3248 2.93994 13.5791 2.83459 13.7667 2.64705C13.9542 2.45951 14.0596 2.20516 14.0596 1.93994C14.0596 1.67472 13.9542 1.42037 13.7667 1.23283C13.5791 1.0453 13.3248 0.939941 13.0596 0.939941H13.0696Z" fill="white"/></svg>')}")`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Group & labels
|
||||||
|
addComponents({
|
||||||
|
'.checkbox-group': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': '0.4rem',
|
||||||
|
},
|
||||||
|
'.checkbox-label': {
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'line-height': theme('fontSize.2sm.1.lineHeight')
|
||||||
|
},
|
||||||
|
'.checkbox-label-lg': {
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
'line-height': theme('fontSize.sm.1.lineHeight')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
37
resources/metronic/core/plugins/components/container.js
Normal file
37
resources/metronic/core/plugins/components/container.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Fixed
|
||||||
|
addComponents({
|
||||||
|
'.container-fixed': {
|
||||||
|
'flex-grow': '1',
|
||||||
|
'padding-left': theme('custom.components.container.fixed.px.DEFAULT'),
|
||||||
|
'padding-right': theme('custom.components.container.fixed.px.DEFAULT')
|
||||||
|
},
|
||||||
|
[`@media (min-width: ${theme('screens.xl')})`]: {
|
||||||
|
'.container-fixed': {
|
||||||
|
'margin-left': 'auto',
|
||||||
|
'margin-right': 'auto',
|
||||||
|
'padding-left': theme('custom.components.container.fixed.px.xl'),
|
||||||
|
'padding-right': theme('custom.components.container.fixed.px.xl'),
|
||||||
|
'max-width': theme('custom.components.container.fixed')['max-width']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fluid
|
||||||
|
addComponents({
|
||||||
|
'.container-fluid': {
|
||||||
|
'flex-grow': '1',
|
||||||
|
'padding-left': theme('custom.components.container.fluid.px.DEFAULT'),
|
||||||
|
'padding-right': theme('custom.components.container.fluid.px.DEFAULT')
|
||||||
|
},
|
||||||
|
[`@media (min-width: ${theme('screens.xl')})`]: {
|
||||||
|
'.container-fluid': {
|
||||||
|
'padding-left': theme('custom.components.container.fluid.px.xl'),
|
||||||
|
'padding-right': theme('custom.components.container.fluid.px.xl')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
61
resources/metronic/core/plugins/components/drawer.js
Normal file
61
resources/metronic/core/plugins/components/drawer.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents}) => {
|
||||||
|
addComponents({
|
||||||
|
'.drawer': {
|
||||||
|
'transition': 'transform 300ms ease',
|
||||||
|
'position': 'fixed',
|
||||||
|
'background-color': 'var(--tw-drawer-background-color)',
|
||||||
|
'&.open': {
|
||||||
|
'box-shadow': 'var(--tw-drawer-box-shadow)',
|
||||||
|
'transition': 'transform 300ms ease'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.drawer-start': {
|
||||||
|
'top': '0',
|
||||||
|
'bottom': '0',
|
||||||
|
'left': '0',
|
||||||
|
'right': 'auto',
|
||||||
|
'transform': 'translateX(-100%)',
|
||||||
|
'&.drawer.open': {
|
||||||
|
'transform': 'translateX(0)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.drawer-end': {
|
||||||
|
'top': '0',
|
||||||
|
'bottom': '0',
|
||||||
|
'right': '0',
|
||||||
|
'left': 'auto',
|
||||||
|
'transform': 'translateX(100%)',
|
||||||
|
'&.drawer.open': {
|
||||||
|
'transform': 'translateX(0)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.drawer-top': {
|
||||||
|
'top': '0',
|
||||||
|
'bottom': 'auto',
|
||||||
|
'left': '0',
|
||||||
|
'right': '0',
|
||||||
|
'transform': 'translateY(-100%)',
|
||||||
|
'&.drawer.open': {
|
||||||
|
'transform': 'translateY(0)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.drawer-bottom': {
|
||||||
|
'bottom': '0',
|
||||||
|
'top': 'auto',
|
||||||
|
'left': '0',
|
||||||
|
'right': '0',
|
||||||
|
'transform': 'translateY(100%)',
|
||||||
|
'&.drawer.open': {
|
||||||
|
'transform': 'translateY(0)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.drawer-backdrop': {
|
||||||
|
'position': 'fixed',
|
||||||
|
'inset': 0,
|
||||||
|
'background-color': 'var(--tw-backdrop-background-color)'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
35
resources/metronic/core/plugins/components/dropdown.js
Normal file
35
resources/metronic/core/plugins/components/dropdown.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.dropdown': {
|
||||||
|
'display': 'flex',
|
||||||
|
},
|
||||||
|
'.dropdown-content': {
|
||||||
|
'display': 'none',
|
||||||
|
'align-items': 'stretch',
|
||||||
|
'flex-direction': 'column',
|
||||||
|
'border': 'var(--tw-dropdown-border)',
|
||||||
|
'box-shadow': 'var(--tw-dropdown-box-shadow)',
|
||||||
|
'background-color': 'var(--tw-dropdown-background-color)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.dropdown'),
|
||||||
|
'.open.dropdown > &, &.open[data-popper-placement]': {
|
||||||
|
'will-change': 'transform'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
addComponents({
|
||||||
|
'.modal-rounded-t': {
|
||||||
|
'border-top-left-radius': theme('custom.components.common.borderRadius.dropdown'),
|
||||||
|
'border-top-right-radius': theme('custom.components.common.borderRadius.dropdown')
|
||||||
|
},
|
||||||
|
'.modal-rounded-b': {
|
||||||
|
'border-bottom-left-radius': theme('custom.components.common.borderRadius.dropdown'),
|
||||||
|
'border-bottom-right-radius': theme('custom.components.common.borderRadius.dropdown')
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
88
resources/metronic/core/plugins/components/file-input.js
Normal file
88
resources/metronic/core/plugins/components/file-input.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Form input
|
||||||
|
addComponents({
|
||||||
|
'.file-input': {
|
||||||
|
'display': 'block',
|
||||||
|
'width': '100%',
|
||||||
|
'appearance': 'none',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'outline': 'none',
|
||||||
|
'font-weight': theme('custom.components.btn.DEFAULT.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.fontSize'),
|
||||||
|
'line-height': '1',
|
||||||
|
'background-color': 'var(--tw-light-active)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.btn'),
|
||||||
|
'height': theme('custom.components.btn.DEFAULT.height'),
|
||||||
|
'padding': '0',
|
||||||
|
'padding-right': theme('custom.components.btn.DEFAULT.px'),
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
},
|
||||||
|
'&::file-selector-button': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
'height': '100%',
|
||||||
|
'appearance': 'none',
|
||||||
|
'padding-left': theme('custom.components.btn.DEFAULT.px'),
|
||||||
|
'padding-right': theme('custom.components.btn.DEFAULT.px'),
|
||||||
|
'margin-right': theme('custom.components.btn.DEFAULT.px'),
|
||||||
|
'outline': 'none',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'border-top-left-radius': theme('custom.components.common.borderRadius.btn'),
|
||||||
|
'border-bottom-left-radius': theme('custom.components.common.borderRadius.btn'),
|
||||||
|
'border': '0',
|
||||||
|
'border-right': '1px solid var(--tw-gray-300)',
|
||||||
|
'box-shadow': 'none'
|
||||||
|
},
|
||||||
|
'&:hover': {
|
||||||
|
'border-color': 'var(--tw-gray-400)',
|
||||||
|
},
|
||||||
|
'&:focus': {
|
||||||
|
'border-color': 'var(--tw-primary)',
|
||||||
|
'box-shadow': 'var(--tw-input-focus-box-shadow)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&:active': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
'box-shadow': 'none',
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-300)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.file-input-sm': {
|
||||||
|
'font-weight': theme('custom.components.btn.sm.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.sm.fontSize'),
|
||||||
|
'height': theme('custom.components.btn.sm.height'),
|
||||||
|
'padding-right': theme('custom.components.btn.sm.px'),
|
||||||
|
'&::file-selector-button': {
|
||||||
|
'padding-left': theme('custom.components.btn.sm.px'),
|
||||||
|
'padding-right': theme('custom.components.btn.sm.px')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.file-input-lg': {
|
||||||
|
'font-weight': theme('custom.components.btn.lg.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.lg.fontSize'),
|
||||||
|
'height': theme('custom.components.btn.lg.height'),
|
||||||
|
'padding-right': theme('custom.components.btn.lg.px'),
|
||||||
|
'&::file-selector-button': {
|
||||||
|
'padding-left': theme('custom.components.btn.lg.px'),
|
||||||
|
'padding-right': theme('custom.components.btn.lg.px')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
39
resources/metronic/core/plugins/components/image-input.js
Normal file
39
resources/metronic/core/plugins/components/image-input.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.image-input': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'position': 'relative',
|
||||||
|
'align-items': 'stretch',
|
||||||
|
'justify-content': 'center',
|
||||||
|
'input[type="file"]': {
|
||||||
|
'appearance': 'none',
|
||||||
|
'position': 'absolute',
|
||||||
|
'width': '0 !important',
|
||||||
|
'height': '0 !important',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
'opacity': '0',
|
||||||
|
},
|
||||||
|
'.image-input-preview': {
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'position': 'relative',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
'width': '100%',
|
||||||
|
'height': '100%',
|
||||||
|
'background-size': 'cover',
|
||||||
|
'background-repeat': 'no-repeat',
|
||||||
|
},
|
||||||
|
'.image-input-placeholder': {
|
||||||
|
'position': 'relative',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
'width': '100%',
|
||||||
|
'height': '100%',
|
||||||
|
'background-size': 'cover',
|
||||||
|
'background-repeat': 'no-repeat',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
38
resources/metronic/core/plugins/components/input-group.js
Normal file
38
resources/metronic/core/plugins/components/input-group.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents}) => {
|
||||||
|
// Form input
|
||||||
|
addComponents({
|
||||||
|
'.input-group': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'stretch',
|
||||||
|
'.btn': {
|
||||||
|
'flex-shrink': '0'
|
||||||
|
},
|
||||||
|
'.input': {
|
||||||
|
'flex-grow': '1',
|
||||||
|
},
|
||||||
|
'.input ~ .btn, .input ~ .dropdown > .btn': {
|
||||||
|
'border-top-left-radius': '0',
|
||||||
|
'border-bottom-left-radius': '0'
|
||||||
|
},
|
||||||
|
'.input + .btn, .input + .dropdown > .btn': {
|
||||||
|
'border-left': '0'
|
||||||
|
},
|
||||||
|
'.btn ~ .input, .btn ~ .btn, .input ~ .input': {
|
||||||
|
'border-top-left-radius': '0',
|
||||||
|
'border-bottom-left-radius': '0'
|
||||||
|
},
|
||||||
|
'.input:has(~ .btn), .input:has(~ .input), .input:has(~ .dropdown > .btn)': {
|
||||||
|
'border-top-right-radius': '0',
|
||||||
|
'border-bottom-right-radius': '0'
|
||||||
|
},
|
||||||
|
'.btn:has(~ .input, ~ .btn), .input:has(~ .input)': {
|
||||||
|
'border-top-right-radius': '0',
|
||||||
|
'border-bottom-right-radius': '0',
|
||||||
|
'border-right': '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
117
resources/metronic/core/plugins/components/input.js
Normal file
117
resources/metronic/core/plugins/components/input.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Form input
|
||||||
|
addComponents({
|
||||||
|
'.input': {
|
||||||
|
'display': 'block',
|
||||||
|
'width': '100%',
|
||||||
|
'appearance': 'none',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'outline': 'none',
|
||||||
|
'font-weight': theme('custom.components.btn.DEFAULT.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.fontSize'),
|
||||||
|
'line-height': '1',
|
||||||
|
'background-color': 'var(--tw-light-active)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.btn'),
|
||||||
|
'height': theme('custom.components.btn.DEFAULT.height'),
|
||||||
|
'padding-left': theme('custom.components.input.DEFAULT.px'),
|
||||||
|
'padding-right': theme('custom.components.input.DEFAULT.px'),
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder, input::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
},
|
||||||
|
'&:hover': {
|
||||||
|
'border-color': 'var(--tw-gray-400)',
|
||||||
|
},
|
||||||
|
'&:focus, &:has(input:focus)': {
|
||||||
|
'border-color': 'var(--tw-primary)',
|
||||||
|
'box-shadow': 'var(--tw-input-focus-box-shadow)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder, input::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&:active, &:has(input:active)': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder, input::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)'
|
||||||
|
},
|
||||||
|
'box-shadow': 'none',
|
||||||
|
},
|
||||||
|
'&:disabled, &:has(input:disabled)': {
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
'&::placeholder, input::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-300)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.input-sm': {
|
||||||
|
'font-weight': theme('custom.components.btn.sm.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.sm.fontSize'),
|
||||||
|
'height': theme('custom.components.btn.sm.height'),
|
||||||
|
'padding-left': theme('custom.components.input.sm.px'),
|
||||||
|
'padding-right': theme('custom.components.input.sm.px')
|
||||||
|
},
|
||||||
|
'.input-lg': {
|
||||||
|
'font-weight': theme('custom.components.btn.lg.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.lg.fontSize'),
|
||||||
|
'height': theme('custom.components.btn.lg.height'),
|
||||||
|
'padding-left': theme('custom.components.input.lg.px'),
|
||||||
|
'padding-right': theme('custom.components.input.lg.px')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Form input with icons
|
||||||
|
addComponents({
|
||||||
|
'.input:not(input)': {
|
||||||
|
'display': 'flex',
|
||||||
|
'gap': '0.375rem',
|
||||||
|
'align-items': 'center',
|
||||||
|
'appearance': 'none',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'outline': 'none',
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
'input': {
|
||||||
|
'flex-grow': '1',
|
||||||
|
'background-color': 'transparent',
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'color': 'inherit',
|
||||||
|
'outline': 'none',
|
||||||
|
'font-size': 'inherit',
|
||||||
|
'font-weight': 'inherit'
|
||||||
|
},
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.iconFontSize')
|
||||||
|
},
|
||||||
|
'.btn-icon': {
|
||||||
|
'border': '0',
|
||||||
|
'height': 'auto',
|
||||||
|
'width': 'auto',
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.input:not(input).input-xs': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.xs.iconFontSize')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.input:not(input).input-sm': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.sm.iconFontSize')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.input:not(input).input-lg': {
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('custom.components.btn.lg.iconFontSize')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
22
resources/metronic/core/plugins/components/leaflet.js
Normal file
22
resources/metronic/core/plugins/components/leaflet.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.leaflet-container': {
|
||||||
|
'.leaflet-pane, .leaflet-top, .leaflet-bottom, .leaflet-control': {
|
||||||
|
'z-index': '1 !important'
|
||||||
|
},
|
||||||
|
'.leaflet-popup-content-wrapper': {
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.dropdown'),
|
||||||
|
'text-align': 'center',
|
||||||
|
'background-color': 'var(--tw-dropdown-background-color)',
|
||||||
|
'.leaflet-popup-content': {
|
||||||
|
'font-family': 'inherit',
|
||||||
|
'font-size': theme('fontSize.2sm')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
138
resources/metronic/core/plugins/components/menu.js
Normal file
138
resources/metronic/core/plugins/components/menu.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Menu dropdown
|
||||||
|
addComponents({
|
||||||
|
'.menu-dropdown': {
|
||||||
|
'gap': '0.125rem',
|
||||||
|
'border': 'var(--tw-dropdown-border)',
|
||||||
|
'box-shadow': 'var(--tw-dropdown-box-shadow)',
|
||||||
|
'background-color': 'var(--tw-dropdown-background-color)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.dropdown')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Menu default
|
||||||
|
addComponents({
|
||||||
|
'.menu-default': {
|
||||||
|
'padding-top': theme('spacing')['2.5'],
|
||||||
|
'padding-bottom': theme('spacing')['2.5'],
|
||||||
|
'.menu-link': {
|
||||||
|
'margin-left': theme('spacing')['2.5'],
|
||||||
|
'margin-right': theme('spacing')['2.5'],
|
||||||
|
'padding': theme('spacing')['2.5'],
|
||||||
|
'border-radius': theme('borderRadius.md'),
|
||||||
|
},
|
||||||
|
'.menu-title': {
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'line-height': theme('fontSize.2sm.1.lineHeight'),
|
||||||
|
'font-weight': theme('fontWeight.medium')
|
||||||
|
},
|
||||||
|
'.menu-icon': {
|
||||||
|
'margin-right': theme('spacing')['2.5'],
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('fontSize.lg')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.menu-bullet': {
|
||||||
|
'margin-right': theme('spacing')['2.5']
|
||||||
|
},
|
||||||
|
'.menu-arrow': {
|
||||||
|
'margin-left': theme('spacing')['2'],
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('fontSize.2xs')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.menu-badge': {
|
||||||
|
'margin-left': theme('spacing')['2.5']
|
||||||
|
},
|
||||||
|
'.menu-separator': {
|
||||||
|
'border-bottom': 'var(--tw-dropdown-border)',
|
||||||
|
'margin-top': theme('spacing')['2.5'],
|
||||||
|
'margin-bottom': theme('spacing')['2.5']
|
||||||
|
},
|
||||||
|
'.menu-accordion:not(.menu-no-indent)': {
|
||||||
|
'.menu-item > .menu-link': {
|
||||||
|
'margin-left': theme('spacing')['5'],
|
||||||
|
},
|
||||||
|
'.menu-item > .menu-accordion .menu-item > .menu-link': {
|
||||||
|
'margin-left': theme('spacing')['8'],
|
||||||
|
},
|
||||||
|
'.menu-item > .menu-accordion .menu-item > .menu-accordion .menu-item > .menu-link': {
|
||||||
|
'margin-left': theme('spacing')['11'],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.menu-fit': {
|
||||||
|
'padding-top': '0',
|
||||||
|
'padding-bottom': '0',
|
||||||
|
'.menu-link': {
|
||||||
|
'margin-left': '0',
|
||||||
|
'margin-right': '0',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.menu-space': {
|
||||||
|
'padding-top': theme('spacing')['2.5'],
|
||||||
|
'padding-bottom': theme('spacing')['2.5'],
|
||||||
|
'.menu-link': {
|
||||||
|
'margin-left': theme('spacing')['2.5'],
|
||||||
|
'margin-right': theme('spacing')['2.5'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Menu theming
|
||||||
|
addComponents({
|
||||||
|
'.menu-default': {
|
||||||
|
'.menu-item': {
|
||||||
|
'.menu-title': {
|
||||||
|
'color': 'var(--tw-gray-800)'
|
||||||
|
},
|
||||||
|
'.menu-icon i': {
|
||||||
|
'color': 'var(--tw-gray-500)'
|
||||||
|
},
|
||||||
|
'.menu-arrow i': {
|
||||||
|
'color': 'var(--tw-gray-500)'
|
||||||
|
},
|
||||||
|
'.menu-link:hover': {
|
||||||
|
'.menu-title': {
|
||||||
|
'color': 'var(--tw-gray-900)'
|
||||||
|
},
|
||||||
|
'.menu-icon i': {
|
||||||
|
'color': 'var(--tw-primary)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.active, &.show, &.here, &.focus': {
|
||||||
|
'> .menu-link': {
|
||||||
|
'.menu-title': {
|
||||||
|
'color': 'var(--tw-gray-900)'
|
||||||
|
},
|
||||||
|
'.menu-icon i': {
|
||||||
|
'color': 'var(--tw-primary)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.active, &.here': {
|
||||||
|
'> .menu-link': {
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'.dark &': {
|
||||||
|
'background-color': 'var(--tw-coal-300)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'& > .menu-link:hover': {
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'.dark &': {
|
||||||
|
'background-color': 'var(--tw-coal-300)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.disabled': {
|
||||||
|
'> .menu-link': {
|
||||||
|
'opacity': '0.5'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
126
resources/metronic/core/plugins/components/modal.js
Normal file
126
resources/metronic/core/plugins/components/modal.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.modal': {
|
||||||
|
'width': '100%',
|
||||||
|
'display': 'none',
|
||||||
|
'opacity': '0',
|
||||||
|
'position': 'fixed',
|
||||||
|
'overflow': 'auto',
|
||||||
|
'inset': '0',
|
||||||
|
'padding': theme('spacing.5'),
|
||||||
|
'transition': 'opacity 300ms ease',
|
||||||
|
'&.open': {
|
||||||
|
'opacity': '1',
|
||||||
|
'transition': 'opacity 300ms ease'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-content': {
|
||||||
|
'position': 'relative',
|
||||||
|
'margin-left': 'auto',
|
||||||
|
'margin-right': 'auto',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.modal'),
|
||||||
|
'box-shadow': 'var(--tw-modal-box-shadow)',
|
||||||
|
'background-color': 'var(--tw-modal-background-color)',
|
||||||
|
'display': 'flex',
|
||||||
|
'flex-direction': 'column'
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-header': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'space-between',
|
||||||
|
'border-bottom': '1px solid var(--tw-gray-200)',
|
||||||
|
'padding-left': theme('spacing')['5'],
|
||||||
|
'padding-right': theme('spacing')['5'],
|
||||||
|
'padding-top': theme('spacing')['2.5'],
|
||||||
|
'padding-bottom': theme('spacing')['2.5']
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-title': {
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
'line-height': theme('fontSize.sm.1.lineHeight'),
|
||||||
|
'font-weight': theme('fontWeight.semibold'),
|
||||||
|
'color': 'var(--tw-gray-900)'
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-body': {
|
||||||
|
'padding-left': theme('spacing')['5'],
|
||||||
|
'padding-right': theme('spacing')['5'],
|
||||||
|
'padding-top': theme('spacing')['2.5'],
|
||||||
|
'padding-bottom': theme('spacing')['2.5']
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-footer': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'justify-content': 'between',
|
||||||
|
'border-top': '1px solid var(--tw-gray-200)',
|
||||||
|
'padding-left': theme('spacing')['5'],
|
||||||
|
'padding-right': theme('spacing')['5'],
|
||||||
|
'padding-top': theme('spacing')['2.5'],
|
||||||
|
'padding-bottom': theme('spacing')['2.5']
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-table': {
|
||||||
|
'.table': {
|
||||||
|
'th:first-child, td:first-child': {
|
||||||
|
'padding-left': theme('spacing')['5']
|
||||||
|
},
|
||||||
|
'th:last-child, td:last-child': {
|
||||||
|
'padding-right': theme('spacing')['5']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-backdrop': {
|
||||||
|
'position': 'fixed',
|
||||||
|
'inset': 0,
|
||||||
|
'background-color': 'var(--tw-backdrop-background-color)'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
addComponents({
|
||||||
|
'.modal-dialog': {
|
||||||
|
'inset': 'auto'
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-overlay': {
|
||||||
|
'inset': '0',
|
||||||
|
'height': '100%'
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-center': {
|
||||||
|
'left': '50%',
|
||||||
|
'top': '50%',
|
||||||
|
'margin-left': '0',
|
||||||
|
'margin-right': '0',
|
||||||
|
'transform': 'translate(-50%, -50%)'
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-center-y': {
|
||||||
|
'top': '50%',
|
||||||
|
'transform': 'translateY(-50%)'
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-center-x': {
|
||||||
|
'left': '50%',
|
||||||
|
'transform': 'translateX(-50%)'
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-rounded-t': {
|
||||||
|
'border-top-left-radius': theme('custom.components.common.borderRadius.modal'),
|
||||||
|
'border-top-right-radius': theme('custom.components.common.borderRadius.modal')
|
||||||
|
},
|
||||||
|
|
||||||
|
'.modal-rounded-b': {
|
||||||
|
'border-bottom-left-radius': theme('custom.components.common.borderRadius.modal'),
|
||||||
|
'border-bottom-right-radius': theme('custom.components.common.borderRadius.modal')
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
64
resources/metronic/core/plugins/components/pagination.js
Normal file
64
resources/metronic/core/plugins/components/pagination.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
addComponents({
|
||||||
|
'.pagination': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': '0.25rem',
|
||||||
|
'.btn': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'flex-shrink': '0',
|
||||||
|
'justify-content': 'center',
|
||||||
|
'height': '1.875rem',
|
||||||
|
'width': '1.875rem',
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'padding': '0',
|
||||||
|
'line-height': '0',
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('fontSize.base'),
|
||||||
|
'color': 'var(--tw-gray-700)'
|
||||||
|
},
|
||||||
|
'&:hover, &:focus, &:active, &.active' : {
|
||||||
|
'background-color': 'var(--tw-gray-200)',
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-900)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&[disabled], &.disabled': {
|
||||||
|
'opacity': '1',
|
||||||
|
'pointer-events': 'none',
|
||||||
|
'color': 'var(--tw-gray-500)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-gray-400)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.pagination-sm': {
|
||||||
|
'gap': '0.175rem',
|
||||||
|
'.btn': {
|
||||||
|
'height': '1.575rem',
|
||||||
|
'width': '1.575rem',
|
||||||
|
'font-size': theme('fontSize.xs'),
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('fontSize.sm')
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.pagination-lg': {
|
||||||
|
'gap': '0.35rem',
|
||||||
|
'.btn': {
|
||||||
|
'height': '2.275rem',
|
||||||
|
'width': '2.275rem',
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('fontSize.xl')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
32
resources/metronic/core/plugins/components/popover.js
Normal file
32
resources/metronic/core/plugins/components/popover.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
addComponents({
|
||||||
|
'.popover': {
|
||||||
|
'display': 'none',
|
||||||
|
'box-shadow': 'var(--tw-popover-box-shadow)',
|
||||||
|
'background-color': 'var(--tw-popover-background-color)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.popover'),
|
||||||
|
'border': 'var(--tw-popover-border)',
|
||||||
|
'&.show': {
|
||||||
|
'display': 'block'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.popover-header': {
|
||||||
|
'padding': '0.50rem 0.75rem',
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
'line-height': theme('fontSize.sm.1.lineHeight'),
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'color': 'var(--tw-gray-900)',
|
||||||
|
'border-bottom': '1px solid var(--tw-gray-200)',
|
||||||
|
},
|
||||||
|
'.popover-body': {
|
||||||
|
'padding': '0.75rem 0.75rem',
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'line-height': theme('fontSize.2sm.1.lineHeight'),
|
||||||
|
'font-weight': theme('fontWeight.normal'),
|
||||||
|
'color': 'var(--tw-gray-700)'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
40
resources/metronic/core/plugins/components/progress.js
Normal file
40
resources/metronic/core/plugins/components/progress.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.progress': {
|
||||||
|
'width': '100%',
|
||||||
|
'display': 'flex',
|
||||||
|
'min-height': '4px',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.progress'),
|
||||||
|
},
|
||||||
|
'.progress-bar': {
|
||||||
|
'display': 'flex',
|
||||||
|
'flex-direction': 'column',
|
||||||
|
'justify-content': 'center',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
'text-align': 'center',
|
||||||
|
'white-space': 'nowrap',
|
||||||
|
'background-color': 'var(--tw-gray-300)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.progress'),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Color options
|
||||||
|
const colors = ['primary', 'success', 'danger', 'warning', 'info', 'dark'];
|
||||||
|
|
||||||
|
colors.forEach((color) => {
|
||||||
|
addComponents({
|
||||||
|
[`.progress-${color}`]: {
|
||||||
|
'background-color': `var(--tw-${color}-light)`,
|
||||||
|
'.progress-bar': {
|
||||||
|
'background-color': `var(--tw-${color})`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
84
resources/metronic/core/plugins/components/radio.js
Normal file
84
resources/metronic/core/plugins/components/radio.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
import svgToDataUri from 'mini-svg-data-uri';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Radio
|
||||||
|
addComponents({
|
||||||
|
'.radio[type="radio"]': {
|
||||||
|
'flex-shrink': '0',
|
||||||
|
'appearance': 'none',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'background-color': 'var(--tw-light-light)',
|
||||||
|
'border-radius': '50%',
|
||||||
|
'height': theme('custom.components.radio.DEFAULT.size'),
|
||||||
|
'width': theme('custom.components.radio.DEFAULT.size'),
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'background-repeat': 'no-repeat',
|
||||||
|
'background-size': 'contain',
|
||||||
|
'background-position': 'center',
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-color': 'var(--tw-primary)',
|
||||||
|
'border': '1px solid var(--tw-primary)',
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22" fill="none"><circle cx="10.9995" cy="11" r="5.86667" fill="white"/></svg>')}")`
|
||||||
|
},
|
||||||
|
'&:focus': {
|
||||||
|
'border-color': 'var(--tw-primary)',
|
||||||
|
'box-shadow': 'var(--tw-input-focus-box-shadow)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&:active': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
'box-shadow': 'none',
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
'cursor': 'not-allowed',
|
||||||
|
'background-color': 'var(--tw-gray-200)',
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-color': 'var(--tw-primary-clarity)',
|
||||||
|
'border': '0',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.radio-sm[type="radio"]': {
|
||||||
|
'height': theme('custom.components.radio.sm.size'),
|
||||||
|
'width': theme('custom.components.radio.sm.size'),
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" fill="none"><circle cx="9.0002" cy="8.99995" r="4.8" fill="white"/></svg>')}")`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.radio-lg[type="radio"]': {
|
||||||
|
'height': theme('custom.components.radio.lg.size'),
|
||||||
|
'width': theme('custom.components.radio.lg.size'),
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-image': `url("${svgToDataUri('<svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 26 26" fill="none"><circle cx="12.9997" cy="13" r="6.93333" fill="white"/></svg>')}")`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Group & labels
|
||||||
|
addComponents({
|
||||||
|
'.radio-group': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': '0.4rem',
|
||||||
|
},
|
||||||
|
'.radio-label': {
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'line-height': theme('fontSize.2sm.1.lineHeight')
|
||||||
|
},
|
||||||
|
'.radio-label-lg': {
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
'line-height': theme('fontSize.sm.1.lineHeight')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
74
resources/metronic/core/plugins/components/range.js
Normal file
74
resources/metronic/core/plugins/components/range.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents}) => {
|
||||||
|
addComponents({
|
||||||
|
'.range': {
|
||||||
|
'width': '100%',
|
||||||
|
'height': '0.5rem',
|
||||||
|
'padding': '0',
|
||||||
|
'appearance': 'none',
|
||||||
|
'&:focus': {
|
||||||
|
'outline': 0
|
||||||
|
},
|
||||||
|
'&::-moz-focus-outer': {
|
||||||
|
'border': '0'
|
||||||
|
},
|
||||||
|
'&::-webkit-slider-thumb': {
|
||||||
|
'width': '1.625rem',
|
||||||
|
'height': '1.625rem',
|
||||||
|
'margin-top': '-0.563rem',
|
||||||
|
'box-shadow': 'var(--tw-default-box-shadow)',
|
||||||
|
'appearance': 'none',
|
||||||
|
'border': '1px solid var(--tw-gray-200)',
|
||||||
|
'transition': 'background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out',
|
||||||
|
'border-radius': '50%',
|
||||||
|
'background-color': 'var(--tw-light)',
|
||||||
|
'&:active': {
|
||||||
|
'background-color': 'var(--tw-light)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&::-moz-range-thumb': {
|
||||||
|
'width': '1.625rem',
|
||||||
|
'height': '1.625rem',
|
||||||
|
'margin-top': '-0.563rem',
|
||||||
|
'box-shadow': 'var(--tw-default-box-shadow)',
|
||||||
|
'appearance': 'none',
|
||||||
|
'border': '1px solid var(--tw-gray-200)',
|
||||||
|
'transition': 'background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out',
|
||||||
|
'border-radius': '50%',
|
||||||
|
'background-color': 'var(--tw-light)',
|
||||||
|
'&:active': {
|
||||||
|
'background-color': 'var(--tw-light)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&::-moz-range-track': {
|
||||||
|
'width': '100%',
|
||||||
|
'height': '0.5rem',
|
||||||
|
'color': 'transparent',
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'background-color': 'var(--tw-gray-200)',
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'border-radius': '0.188rem'
|
||||||
|
},
|
||||||
|
'&::-webkit-slider-runnable-track': {
|
||||||
|
'width': '100%',
|
||||||
|
'height': '0.5rem',
|
||||||
|
'color': 'transparent',
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'background-color': 'var(--tw-gray-200)',
|
||||||
|
'border-color': 'transparent',
|
||||||
|
'border-radius': '0.188rem'
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
'pointer-events': 'none',
|
||||||
|
'&::-webkit-slider-thumb': {
|
||||||
|
'background-color': 'var(--tw-gray-100)'
|
||||||
|
},
|
||||||
|
'&::-moz-range-thumb': {
|
||||||
|
'background-color': 'var(--tw-gray-100)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
66
resources/metronic/core/plugins/components/rating.js
Normal file
66
resources/metronic/core/plugins/components/rating.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents}) => {
|
||||||
|
addComponents({
|
||||||
|
'.rating': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'stretch',
|
||||||
|
'input': {
|
||||||
|
'appearance': 'none',
|
||||||
|
'position': 'absolute',
|
||||||
|
'left': '9999px',
|
||||||
|
'&[disabled]': {
|
||||||
|
'display': 'none',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.rating-on': {
|
||||||
|
'color': 'var(--tw-warning)',
|
||||||
|
},
|
||||||
|
'.rating-off': {
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
},
|
||||||
|
'.rating-label': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'.rating-on': {
|
||||||
|
'display': 'none',
|
||||||
|
},
|
||||||
|
'.rating-off': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.rating:hover label.rating-label, label.rating-label, label.rating-label.checked, div.rating-label.checked': {
|
||||||
|
'.rating-on': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
},
|
||||||
|
'.rating-off': {
|
||||||
|
'display': 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'label.rating-label:hover ~ label.rating-label, .rating-input:checked ~ .rating-label': {
|
||||||
|
'.rating-on': {
|
||||||
|
'display': 'none',
|
||||||
|
},
|
||||||
|
'.rating-off': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'.rating-label.indeterminate': {
|
||||||
|
'position': 'relative',
|
||||||
|
'.rating-on': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'position': 'absolute',
|
||||||
|
'z-index': '1',
|
||||||
|
'overflow': 'hidden',
|
||||||
|
},
|
||||||
|
'.rating-off': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'label.rating-label': {
|
||||||
|
'cursor': 'pointer'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
63
resources/metronic/core/plugins/components/scrollable.js
Normal file
63
resources/metronic/core/plugins/components/scrollable.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
addComponents({
|
||||||
|
'.scrollable, .scrollable-y, .scrollable-x, .scrollable-hover, .scrollable-y-hover, .scrollable-x-hover, .scrollable-auto, .scrollable-y-auto, .scrollable-x-auto': {
|
||||||
|
'scrollbar-width': 'thin',
|
||||||
|
'scrollbar-color': 'transparent transparent',
|
||||||
|
'position': 'relative',
|
||||||
|
'&::-webkit-scrollbar': {
|
||||||
|
'width': '0.35rem',
|
||||||
|
'height': '0.35rem',
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-track': {
|
||||||
|
'background-color': 'transparent'
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-thumb': {
|
||||||
|
'border-radius': '1.25rem',
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-corner': {
|
||||||
|
'background-color': 'transparent'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.scrollable, .scrollable-hover': {
|
||||||
|
'overflow': 'scroll',
|
||||||
|
},
|
||||||
|
'.scrollable-y, .scrollable-y-hover': {
|
||||||
|
'overflow-y': 'scroll',
|
||||||
|
},
|
||||||
|
'.scrollable-x, .scrollable-x-hover': {
|
||||||
|
'overflow-x': 'scroll',
|
||||||
|
},
|
||||||
|
'.scrollable-auto': {
|
||||||
|
'overflow': 'auto',
|
||||||
|
},
|
||||||
|
'.scrollable-y-auto': {
|
||||||
|
'overflow-y': 'auto',
|
||||||
|
},
|
||||||
|
'.scrollable-x-auto': {
|
||||||
|
'overflow-x': 'auto',
|
||||||
|
},
|
||||||
|
'.scrollable, .scrollable-y, .scrollable-x, .scrollable-auto, .scrollable-y-auto, .scrollable-x-auto, .scrollable-hover:hover, .scrollable-y-hover:hover, .scrollable-x-hover:hover': {
|
||||||
|
'scrollbar-color': 'var(--tw-scrollbar-thumb-color, var(--tw-gray-200)) transparent',
|
||||||
|
'&::-webkit-scrollbar-thumb': {
|
||||||
|
'background-color': 'var(--tw-scrollbar-thumb-color, var(--tw-gray-200))',
|
||||||
|
},
|
||||||
|
'&::-webkit-scrollbar-corner': {
|
||||||
|
'background-color': 'transparent'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[`@media (max-width: ${theme('screens.lg')})`]: {
|
||||||
|
'.scrollable, .scrollable-hover': {
|
||||||
|
'overflow': 'auto',
|
||||||
|
},
|
||||||
|
'.scrollable-y, .scrollable-y-hover': {
|
||||||
|
'overflow-y': 'auto',
|
||||||
|
},
|
||||||
|
'.scrollable-x, .scrollable-x-hover': {
|
||||||
|
'overflow-x': 'auto',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
84
resources/metronic/core/plugins/components/select.js
Normal file
84
resources/metronic/core/plugins/components/select.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
import svgToDataUri from 'mini-svg-data-uri';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
addComponents({
|
||||||
|
'.select': {
|
||||||
|
'display': 'block',
|
||||||
|
'width': '100%',
|
||||||
|
'appearance': 'none',
|
||||||
|
'box-shadow': 'none',
|
||||||
|
'outline': 'none',
|
||||||
|
'background-repeat': 'no-repeat',
|
||||||
|
'background-position': `right 0.675rem center`,
|
||||||
|
'background-size': '14px 11px',
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="none" stroke="${theme('base.colors.gray.light.600')}" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m2 5 6 6 6-6"/></svg>`)}")`,
|
||||||
|
'.dark &': {
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="none" stroke="${theme('base.colors.gray.dark.600')}" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m2 5 6 6 6-6"/></svg>`)}")`,
|
||||||
|
},
|
||||||
|
'&[multiple], &[size]:not([size="1"])': {
|
||||||
|
'padding-right': `${theme('custom.components.btn.DEFAULT.px')}`,
|
||||||
|
'background-image': 'none'
|
||||||
|
},
|
||||||
|
// Remove outline from select box in FF
|
||||||
|
'&:-moz-focusring': {
|
||||||
|
'color': 'transparent',
|
||||||
|
'text-shadow': 'none'
|
||||||
|
},
|
||||||
|
'font-weight': theme('custom.components.btn.DEFAULT.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.DEFAULT.fontSize'),
|
||||||
|
'line-height': '1',
|
||||||
|
'background-color': 'var(--tw-light-active)',
|
||||||
|
'border-radius': theme('custom.components.common.borderRadius.btn'),
|
||||||
|
'height': theme('custom.components.btn.DEFAULT.height'),
|
||||||
|
'padding-left': theme('custom.components.input.DEFAULT.px'),
|
||||||
|
'padding-right': theme('custom.components.input.DEFAULT.px'),
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&:hover': {
|
||||||
|
'border-color': 'var(--tw-gray-400)',
|
||||||
|
},
|
||||||
|
'&:focus': {
|
||||||
|
'border-color': 'var(--tw-primary)',
|
||||||
|
'box-shadow': 'var(--tw-input-focus-box-shadow)',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'&:active': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
'box-shadow': 'none',
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'color': 'var(--tw-gray-400)',
|
||||||
|
'&::placeholder': {
|
||||||
|
'color': 'var(--tw-gray-300)',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.select-sm': {
|
||||||
|
'font-weight': theme('custom.components.btn.sm.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.sm.fontSize'),
|
||||||
|
'height': theme('custom.components.btn.sm.height'),
|
||||||
|
'padding-left': theme('custom.components.input.sm.px'),
|
||||||
|
'padding-right': theme('custom.components.input.sm.px'),
|
||||||
|
'background-size': '14px 10px',
|
||||||
|
'background-position': `right 0.55rem center`,
|
||||||
|
},
|
||||||
|
'.select-lg': {
|
||||||
|
'font-weight': theme('custom.components.btn.lg.fontWeight'),
|
||||||
|
'font-size': theme('custom.components.btn.lg.fontSize'),
|
||||||
|
'height': theme('custom.components.btn.lg.height'),
|
||||||
|
'padding-left': theme('custom.components.input.lg.px'),
|
||||||
|
'padding-right': theme('custom.components.input.lg.px'),
|
||||||
|
'background-size': '14px 12px',
|
||||||
|
'background-position': `right 0.75rem center`,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
116
resources/metronic/core/plugins/components/switch.js
Normal file
116
resources/metronic/core/plugins/components/switch.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addVariant, addComponents, theme, e}) => {
|
||||||
|
addComponents({
|
||||||
|
'.switch': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': theme('spacing')['2.5'],
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'input[type=checkbox]': {
|
||||||
|
'display': 'flex',
|
||||||
|
'appearance': 'none',
|
||||||
|
'background-color': 'var(--tw-gray-300)',
|
||||||
|
'position': 'relative',
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'flex-shrink': '0',
|
||||||
|
'height': theme('custom.components.switch.DEFAULT.height'),
|
||||||
|
'width': theme('custom.components.switch.DEFAULT.width'),
|
||||||
|
'border-radius': theme('custom.components.switch.DEFAULT.height'),
|
||||||
|
'transition': 'all .15s ease-in-out',
|
||||||
|
'&:before': {
|
||||||
|
'display': 'flex',
|
||||||
|
'position': 'absolute',
|
||||||
|
'content': '""',
|
||||||
|
'height': '1rem',
|
||||||
|
'width': '1rem',
|
||||||
|
'border-radius': '100%',
|
||||||
|
'background-color': 'var(--tw-light)',
|
||||||
|
'left': '0.25rem',
|
||||||
|
'top': '50%',
|
||||||
|
'transform': 'translateY(-50%)',
|
||||||
|
'filter': 'drop-shadow(0px 3px 4px rgba(0, 0, 0, 0.03))',
|
||||||
|
'transition': 'all .15s ease-in-out'
|
||||||
|
},
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-color': 'var(--tw-primary)',
|
||||||
|
'transition': 'all .15s ease-in-out',
|
||||||
|
'&:before': {
|
||||||
|
'background-color': '#ffffff',
|
||||||
|
'transition': 'all .15s ease-in-out',
|
||||||
|
'left': 'calc(100% - 0.25rem)',
|
||||||
|
'transform': 'translate(-100%, -50%)',
|
||||||
|
'filter': 'none'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
'background-color': 'var(--tw-gray-100)',
|
||||||
|
'border': '1px solid var(--tw-gray-300)',
|
||||||
|
'cursor': 'not-allowed',
|
||||||
|
'opacity': '0.5',
|
||||||
|
'&:before': {
|
||||||
|
'background-color': 'var(--tw-gray-300)'
|
||||||
|
},
|
||||||
|
'&:checked, &[aria-checked="true"]': {
|
||||||
|
'background-color': 'var(--tw-primary-clarity)',
|
||||||
|
'border': '0',
|
||||||
|
'&:before': {
|
||||||
|
'background-color': 'var(--tw-light)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.switch-label': {
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'line-height': theme('lineHeight.4')
|
||||||
|
},
|
||||||
|
'input[type=checkbox] + .switch-label': {
|
||||||
|
'color': 'var(--tw-gray-800)',
|
||||||
|
},
|
||||||
|
'&:has(input[type=checkbox]:disabled)': {
|
||||||
|
'.switch-label': {
|
||||||
|
'color': 'var(--tw-gray-500)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.switch-sm': {
|
||||||
|
'input[type=checkbox]': {
|
||||||
|
'height': theme('custom.components.switch.sm.height'),
|
||||||
|
'width': theme('custom.components.switch.sm.width'),
|
||||||
|
'border-radius': theme('custom.components.switch.sm.height'),
|
||||||
|
'&:before': {
|
||||||
|
'height': '0.75rem',
|
||||||
|
'width': '0.75rem',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.switch-label': {
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.switch-lg': {
|
||||||
|
'input[type=checkbox]': {
|
||||||
|
'height': theme('custom.components.switch.lg.height'),
|
||||||
|
'width': theme('custom.components.switch.lg.width'),
|
||||||
|
'border-radius': theme('custom.components.switch.lg.height'),
|
||||||
|
'&:before': {
|
||||||
|
'height': '1.25rem',
|
||||||
|
'width': '1.25rem',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.switch-label': {
|
||||||
|
'font-size': theme('fontSize.md'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addVariant('switch-on', [
|
||||||
|
({modifySelectors, separator}) => {
|
||||||
|
modifySelectors(({className}) => {
|
||||||
|
return `.switch:has([type="checkbox"]:checked) .${e(`switch-on${separator}${className}`)}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
154
resources/metronic/core/plugins/components/table.js
Normal file
154
resources/metronic/core/plugins/components/table.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
import svgToDataUri from 'mini-svg-data-uri';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.table': {
|
||||||
|
'width': '100%',
|
||||||
|
'caption-side': 'bottom',
|
||||||
|
'border-collapse': 'collapse',
|
||||||
|
'vertical-align': 'middle',
|
||||||
|
'text-align': 'left',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'font-size': theme('fontSize.sm'),
|
||||||
|
'line-height': theme('fontSize.sm.1.lineHeight'),
|
||||||
|
'th, td': {
|
||||||
|
'input[type="checkbox"]': {
|
||||||
|
'vertical-align': 'inherit'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'thead, tfoot': {
|
||||||
|
'td, th': {
|
||||||
|
'padding-left': theme('custom.components.table.px'),
|
||||||
|
'padding-right': theme('custom.components.table.px'),
|
||||||
|
'padding-top': theme('custom.components.table.py.head'),
|
||||||
|
'padding-bottom': theme('custom.components.table.py.head'),
|
||||||
|
'background-color': 'var(--tw-table-head-background-color)',
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'line-height': theme('fontSize.2sm.1.lineHeight'),
|
||||||
|
'vertical-align': 'middle'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'thead': {
|
||||||
|
'td, th': {
|
||||||
|
'border-bottom': 'var(--tw-table-border)'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'tfoot': {
|
||||||
|
'td, th': {
|
||||||
|
'border-top': 'var(--tw-table-border)'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'tbody': {
|
||||||
|
'vertical-align': 'inherit',
|
||||||
|
'tr': {
|
||||||
|
'td, th': {
|
||||||
|
'padding-left': theme('custom.components.table.px'),
|
||||||
|
'padding-right': theme('custom.components.table.px'),
|
||||||
|
'padding-top': theme('custom.components.table.py.body'),
|
||||||
|
'padding-bottom': theme('custom.components.table.py.body'),
|
||||||
|
'border-bottom': 'var(--tw-table-border)'
|
||||||
|
},
|
||||||
|
'&:last-child': {
|
||||||
|
'td, th': {
|
||||||
|
'border-bottom': '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Border
|
||||||
|
addComponents({
|
||||||
|
'.table-border': {
|
||||||
|
'border': 'var(--tw-table-border)',
|
||||||
|
'td, th': {
|
||||||
|
'border-right': 'var(--tw-table-border)',
|
||||||
|
'&:last-child': {
|
||||||
|
'border-right': '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.table-border-l': {
|
||||||
|
'border-left': 'var(--tw-table-border)'
|
||||||
|
},
|
||||||
|
'.table-border-r': {
|
||||||
|
'border-right': 'var(--tw-table-border)'
|
||||||
|
},
|
||||||
|
'.table-border-t': {
|
||||||
|
'border-top': 'var(--tw-table-border)'
|
||||||
|
},
|
||||||
|
'.table-border-b': {
|
||||||
|
'border-bottom': 'var(--tw-table-border)'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort
|
||||||
|
addComponents({
|
||||||
|
'.sort': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': '0.35rem',
|
||||||
|
'cursor': 'pointer',
|
||||||
|
'line-height': '1'
|
||||||
|
},
|
||||||
|
'.sort-icon': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'flex-direction': 'column',
|
||||||
|
'justify-content': 'center',
|
||||||
|
'align-items': 'center',
|
||||||
|
'height': '0.875rem',
|
||||||
|
'width': '0.875rem',
|
||||||
|
'gap': '0.125rem',
|
||||||
|
'line-height': '1',
|
||||||
|
'&:before': {
|
||||||
|
'display': 'inline-block',
|
||||||
|
'content': '""',
|
||||||
|
'height': '0.25rem',
|
||||||
|
'width': '0.438rem',
|
||||||
|
'background-repeat': 'no-repeat',
|
||||||
|
'background-position': `center`,
|
||||||
|
'background-size': 'cover',
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" width="8" height="5" viewBox="0 0 8 5" fill="none"><path d="M1.08333 4.83333C0.908333 4.83333 0.791667 4.775 0.675 4.65833C0.441667 4.425 0.441667 4.075 0.675 3.84167L3.59167 0.925C3.825 0.691667 4.175 0.691667 4.40833 0.925L7.325 3.84167C7.55833 4.075 7.55833 4.425 7.325 4.65833C7.09167 4.89167 6.74167 4.89167 6.50833 4.65833L4 2.15L1.49167 4.65833C1.375 4.775 1.25833 4.83333 1.08333 4.83333Z" fill="${theme('base.colors.gray.light.600')}"/></svg>`)}")`
|
||||||
|
},
|
||||||
|
'&:after': {
|
||||||
|
'display': 'inline-block',
|
||||||
|
'content': '""',
|
||||||
|
'height': '0.25rem',
|
||||||
|
'width': '0.438rem',
|
||||||
|
'background-repeat': 'no-repeat',
|
||||||
|
'background-position': `center`,
|
||||||
|
'background-size': 'cover',
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" width="8" height="5" viewBox="0 0 8 5" fill="none"><path d="M4 4.24984C3.825 4.24984 3.70833 4.1915 3.59167 4.07484L0.675 1.15817C0.441667 0.924838 0.441667 0.574837 0.675 0.341504C0.908333 0.108171 1.25833 0.108171 1.49167 0.341504L4 2.84984L6.50833 0.341504C6.74167 0.108171 7.09167 0.108171 7.325 0.341504C7.55833 0.574837 7.55833 0.924838 7.325 1.15817L4.40833 4.07484C4.29167 4.1915 4.175 4.24984 4 4.24984Z" fill="${theme('base.colors.gray.light.600')}"/></svg>`)}")`
|
||||||
|
},
|
||||||
|
'.asc > &': {
|
||||||
|
'&:before': {
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" width="8" height="5" viewBox="0 0 8 5" fill="none"><path d="M1.08333 4.83333C0.908333 4.83333 0.791667 4.775 0.675 4.65833C0.441667 4.425 0.441667 4.075 0.675 3.84167L3.59167 0.925C3.825 0.691667 4.175 0.691667 4.40833 0.925L7.325 3.84167C7.55833 4.075 7.55833 4.425 7.325 4.65833C7.09167 4.89167 6.74167 4.89167 6.50833 4.65833L4 2.15L1.49167 4.65833C1.375 4.775 1.25833 4.83333 1.08333 4.83333Z" fill="${theme('base.colors.gray.light.700')}"/></svg>`)}")`
|
||||||
|
},
|
||||||
|
'&:after': {
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" width="8" height="5" viewBox="0 0 8 5" fill="none"><path d="M4 4.24984C3.825 4.24984 3.70833 4.1915 3.59167 4.07484L0.675 1.15817C0.441667 0.924838 0.441667 0.574837 0.675 0.341504C0.908333 0.108171 1.25833 0.108171 1.49167 0.341504L4 2.84984L6.50833 0.341504C6.74167 0.108171 7.09167 0.108171 7.325 0.341504C7.55833 0.574837 7.55833 0.924838 7.325 1.15817L4.40833 4.07484C4.29167 4.1915 4.175 4.24984 4 4.24984Z" fill="${theme('base.colors.gray.light.400')}"/></svg>`)}")`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.desc > &': {
|
||||||
|
'&:before': {
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" width="8" height="5" viewBox="0 0 8 5" fill="none"><path d="M1.08333 4.83333C0.908333 4.83333 0.791667 4.775 0.675 4.65833C0.441667 4.425 0.441667 4.075 0.675 3.84167L3.59167 0.925C3.825 0.691667 4.175 0.691667 4.40833 0.925L7.325 3.84167C7.55833 4.075 7.55833 4.425 7.325 4.65833C7.09167 4.89167 6.74167 4.89167 6.50833 4.65833L4 2.15L1.49167 4.65833C1.375 4.775 1.25833 4.83333 1.08333 4.83333Z" fill="${theme('base.colors.gray.light.400')}"/></svg>`)}")`
|
||||||
|
},
|
||||||
|
'&:after': {
|
||||||
|
'background-image': `url("${svgToDataUri(`<svg xmlns="http://www.w3.org/2000/svg" width="8" height="5" viewBox="0 0 8 5" fill="none"><path d="M4 4.24984C3.825 4.24984 3.70833 4.1915 3.59167 4.07484L0.675 1.15817C0.441667 0.924838 0.441667 0.574837 0.675 0.341504C0.908333 0.108171 1.25833 0.108171 1.49167 0.341504L4 2.84984L6.50833 0.341504C6.74167 0.108171 7.09167 0.108171 7.325 0.341504C7.55833 0.574837 7.55833 0.924838 7.325 1.15817L4.40833 4.07484C4.29167 4.1915 4.175 4.24984 4 4.24984Z" fill="${theme('base.colors.gray.light.700')}"/></svg>`)}")`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'.sort-label': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': '0.35rem'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
38
resources/metronic/core/plugins/components/tabs.js
Normal file
38
resources/metronic/core/plugins/components/tabs.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/* eslint-disable max-len */
|
||||||
|
import plugin from 'tailwindcss/plugin';
|
||||||
|
|
||||||
|
export default plugin(({addComponents, theme}) => {
|
||||||
|
// Base
|
||||||
|
addComponents({
|
||||||
|
'.tabs': {
|
||||||
|
'display': 'flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': theme('spacing.5'),
|
||||||
|
'border-bottom': '1px solid var(--tw-gray-200)'
|
||||||
|
},
|
||||||
|
'.tab': {
|
||||||
|
'display': 'inline-flex',
|
||||||
|
'align-items': 'center',
|
||||||
|
'gap': theme('spacing')['2'],
|
||||||
|
'font-size': theme('fontSize.2sm'),
|
||||||
|
'line-height': '1',
|
||||||
|
'color': 'var(--tw-gray-700)',
|
||||||
|
'i': {
|
||||||
|
'font-size': theme('fontSize.md'),
|
||||||
|
'color': 'var(--tw-gray-600)',
|
||||||
|
},
|
||||||
|
'font-weight': theme('fontWeight.medium'),
|
||||||
|
'padding': `${theme('spacing.4')} 0`,
|
||||||
|
'border-bottom': '2px solid transparent',
|
||||||
|
'&.active, &:hover, &:focus': {
|
||||||
|
'color': 'var(--tw-primary)',
|
||||||
|
'i': {
|
||||||
|
'color': 'var(--tw-primary)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'&.active': {
|
||||||
|
'border-bottom-color': 'var(--tw-primary)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user