diff --git a/package.json b/package.json
index baa0419..87b6123 100644
--- a/package.json
+++ b/package.json
@@ -7,14 +7,13 @@
},
"devDependencies": {
"@rollup/plugin-inject": "^5.0.5",
- "autoprefixer": "^10.4.19",
- "axios": "^1.6.4",
+ "autoprefixer": "^10.4.20",
"laravel-vite-plugin": "^1.0",
- "postcss": "^8.4.39",
+ "postcss": "^8.4.45",
"prettier": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.6",
"sass": "^1.77.6",
- "tailwindcss": "^3.4.4",
+ "tailwindcss": "^3.4.11",
"vite": "^5.0"
},
"dependencies": {
@@ -24,6 +23,11 @@
"notie": "^4.3.1",
"sweetalert2": "^11.12.4",
"toastr": "^2.1.4",
- "tom-select": "^2.3.1"
+ "tom-select": "^2.3.1",
+ "apexcharts": "^3.53.0",
+ "axios": "^1.7.7",
+ "clipboard": "^2.0.11",
+ "esri-leaflet": "^3.0.12",
+ "esri-leaflet-geocoder": "^3.1.4"
}
}
diff --git a/resources/metronic/app/datatables/allowed-ip-addresses.ts b/resources/metronic/app/datatables/allowed-ip-addresses.ts
new file mode 100644
index 0000000..8d82d02
--- /dev/null
+++ b/resources/metronic/app/datatables/allowed-ip-addresses.ts
@@ -0,0 +1,147 @@
+import {
+ KTDataTable,
+ KTDataTableConfigInterface,
+ KTDataTableDataInterface,
+ KTDataTableInterface,
+} from '../../core/components/datatable';
+
+const apiUrl: string = /^(localhost|127.0.0.1)$/.test(window.location.hostname)
+ ? 'http://127.0.0.1:8001/metronic-tailwind-html/demo1/account/security/allowed-ip-addresses/_data.html'
+ : 'https://keenthemes.com/metronic/tailwind/demo1/account/security/allowed-ip-addresses/_data.html';
+const element: HTMLElement = document.querySelector('#ip_addresses_table') as HTMLElement;
+
+
+interface IPAddressData extends KTDataTableDataInterface {
+ id: number;
+ status: string;
+ ipAddress: string;
+ lastSession: string;
+ label: string;
+ method: string;
+}
+
+// Example usage of the plugin with server-side API, pagination, and sorting
+const dataTableOptions: KTDataTableConfigInterface = {
+ // Initialization options for the DataTable
+ apiEndpoint: apiUrl,
+
+ // mapResponse: (responseData): KTDatatableResponseDataInterface => {
+ // // Custom transformation logic for custom API
+ // return {
+ // data: responseData.data, // Assuming the response has an 'items' array
+ // totalCount: responseData.totalCount // Assuming the response has a 'total' field
+ // };
+ // },
+
+ // mapRequest: (query: URLSearchParams): URLSearchParams => {
+ // // Custom query mapping logic
+ // query.set('test', 'test');
+ // return query;
+ // },
+
+ // pageSizes: [5, 10, 20, 30, 50],
+
+ pageSize: 10,
+ // stateSave: false,
+ stateNamespace: 'allowed-ip-addresses',
+ columns: {
+ select: {
+ render: (
+ item: keyof KTDataTableDataInterface,
+ data: IPAddressData,
+ context: KTDataTableInterface
+ ): string => {
+ const checkbox = document.createElement('input');
+ checkbox.className = 'checkbox checkbox-sm';
+ checkbox.type = 'checkbox';
+ checkbox.value = data.id.toString();
+ checkbox.setAttribute('data-datatable-row-check', 'true');
+ return checkbox.outerHTML.trim();
+ },
+ },
+ status: {
+ title: 'Status',
+ render: (item: string): string => {
+ return ``;
+ },
+ createdCell(cell) {
+ cell.classList.add('text-center');
+ },
+ },
+ ipAddress: {
+ title: 'IP Address',
+ },
+ lastSession: {
+ title: 'Last Session',
+ },
+ label: {
+ title: 'Label',
+ },
+ method: {
+ title: 'Method',
+ },
+ edit: {
+ render: (
+ item: string,
+ data: IPAddressData
+ ): string => {
+ const button = document.createElement('button');
+ button.className = 'btn btn-sm btn-icon btn-clear btn-light';
+ button.innerHTML = '';
+ return button.outerHTML.trim();
+ },
+ createdCell: (cell, cellData, rowData) => {
+ cell.querySelector('.btn').addEventListener('click', () => {
+ alert(`Clicked on edit button for row ${rowData.label}`);
+ });
+ },
+ },
+ delete: {
+ render: (
+ item: string,
+ data: IPAddressData
+ ): string => {
+ const button = document.createElement('button');
+ button.className = 'btn btn-sm btn-icon btn-clear btn-light';
+ button.innerHTML = '';
+ return button.outerHTML.trim();
+ },
+ createdCell: (cell, cellData, rowData) => {
+ cell.querySelector('.btn').addEventListener('click', () => {
+ alert(`Clicked on delete button for row ${rowData.label}`);
+ });
+ },
+ },
+ },
+};
+
+const dataTable = new KTDataTable(element, dataTableOptions);
+
+document.querySelector('#select_ip_btn').addEventListener('click', () => {
+ const selected = dataTable.getChecked();
+ if (selected.length) {
+ alert(`Selected rows: ${selected}`);
+ } else {
+ alert('No rows selected');
+ }
+})
+
+// Cache elements with the data-datatable-search attribute
+const searchElements = document.querySelectorAll('[data-datatable-search]');
+
+searchElements.forEach((element) => {
+ // Get the ID of the datatable to be searched
+ const tableId = element.getAttribute('data-datatable-search');
+ // Find the corresponding datatable element
+ const datatable = document.querySelector(tableId);
+
+ if (datatable) {
+ // Retrieve the datatable instance once
+ const dataTableInstance = (datatable as any).instance;
+
+ // Add the event listener for the keyup event
+ element.addEventListener('keyup', () => {
+ dataTableInstance.search(element.value);
+ });
+ }
+});
diff --git a/resources/metronic/app/datatables/current-sessions.js b/resources/metronic/app/datatables/current-sessions.js
new file mode 100644
index 0000000..d07fd6a
--- /dev/null
+++ b/resources/metronic/app/datatables/current-sessions.js
@@ -0,0 +1,192 @@
+class DataTableManager {
+ constructor(tableElement, apiUrl) {
+ this.tableElement = tableElement;
+ this.apiUrl = apiUrl;
+ this.dataTableOptions = this.createDataTableOptions();
+ this.dataTable = new KTDataTable(tableElement, this.dataTableOptions);
+ this.filterMap = this.createFilterMap();
+ }
+
+ static isLocalhost() {
+ return /^(localhost|127.0.0.1)$/.test(window.location.hostname);
+ }
+
+ /**
+ * Creates the options for the DataTable.
+ *
+ * @return {Object} The options for the DataTable.
+ */
+ createDataTableOptions() {
+ return {
+ apiEndpoint: this.apiUrl,
+ pageSize: 10,
+ columns: {
+ select: {
+ render: (item, data, context) => {
+ const checkbox = document.createElement('input');
+ checkbox.className = 'checkbox checkbox-sm';
+ checkbox.type = 'checkbox';
+ checkbox.value = data.id.toString();
+ checkbox.setAttribute('data-datatable-row-check', 'true');
+ return checkbox.outerHTML.trim();
+ },
+ },
+ user: {
+ title: 'Person',
+ render: (item) => {
+ const prefix = DataTableManager.isLocalhost() ? 'metronic-tailwind-html' : 'metronic/tailwind';
+ return `
+
+ `;
+ },
+ },
+ browser: {
+ title: 'Browser',
+ render: (item) => {
+ return `
+
+
+ ${item.name}
+
+ `;
+ },
+ },
+ ipAddress: {
+ title: 'IP Address',
+ },
+ location: {
+ title: 'Location',
+ render: (item) => {
+ const prefix = DataTableManager.isLocalhost() ? 'metronic-tailwind-html' : 'metronic/tailwind';
+ return `
+
+

+
${item.name}
+
+ `;
+ },
+ },
+ action: {
+ title: '',
+ render: (item) => {
+ return `
+
+ `;
+ },
+ createdCell: (cell, cellData, rowData) => {
+ cell.querySelector('.btn').addEventListener('click', () => {
+ alert(`Clicked on action button for row ${rowData.user.name}`);
+ });
+ },
+ },
+ },
+ };
+ }
+
+ /**
+ * Creates a map of filter elements based on the data-datatable-filter-column attribute.
+ *
+ * @return {Map} A map of filter elements, where the key is the value of the data-datatable-filter-column attribute and the value is the corresponding HTMLSelectElement.
+ */
+ createFilterMap() {
+ const filterElements = document.querySelectorAll(
+ 'select[data-datatable-filter-column]'
+ );
+ return new Map(
+ Array.from(filterElements).map((el) => [
+ el.getAttribute('data-datatable-filter-column'),
+ el,
+ ])
+ );
+ }
+
+ /**
+ * Initialize the filters based on the state and map the filter elements to their corresponding datatable columns.
+ */
+ initializeFilters() {
+ this.dataTable.getState().filters.forEach(({ column, value }) => {
+ if (this.filterMap.has(column)) {
+ const filterEl = this.filterMap.get(column);
+ if (filterEl !== null) {
+ filterEl.value = value || '';
+ }
+ }
+ });
+
+ this.filterMap.forEach((el, column) => {
+ el.addEventListener('change', () => {
+ this.dataTable
+ .setFilter({
+ column,
+ type: 'text',
+ value: el.value || '',
+ })
+ .redraw();
+ });
+ });
+ }
+
+ /**
+ * A debounced function that delays invoking the input function until after wait milliseconds have elapsed since the last time the debounced function is invoked.
+ *
+ * @param {Function} func - The function to debounce.
+ * @param {number} wait - The number of milliseconds to delay.
+ * @return {Function} The debounced function.
+ */
+ debounce(func, wait) {
+ let timeout;
+ return function (...args) {
+ const context = this;
+ clearTimeout(timeout);
+ timeout = setTimeout(() => func.apply(context, args), wait);
+ };
+ }
+
+ /**
+ * Initializes the search functionality for the current table.
+ * It sets up a debounced search event listener on the search element
+ * to perform a search on the datatable whenever the user types in the search input.
+ *
+ * @return {void}
+ */
+ initSearch() {
+ const searchElement = document.querySelector('[data-datatable-search="true"]');
+ if (this.dataTable && searchElement) {
+ const debouncedSearch = this.debounce(() => {
+ this.dataTable.search(searchElement.value);
+ }, 300);
+ searchElement.addEventListener('keyup', debouncedSearch);
+ }
+ }
+
+ /**
+ * Creates a new instance of DataTableManager with the specified tableElement and apiUrl.
+ * Initializes filters and search functionality for the instance.
+ *
+ * @param {void}
+ * @return {void}
+ */
+ static createInstance() {
+ const apiUrl = DataTableManager.isLocalhost()
+ ? 'http://127.0.0.1:8001/metronic-tailwind-html/demo1/account/security/current-sessions/_data.html'
+ : 'https://keenthemes.com/metronic/tailwind/demo1/account/security/current-sessions/_data.html';
+ const tableElement = document.querySelector('#current_sessions_table');
+
+ const dataTableManager = new DataTableManager(tableElement, apiUrl);
+ dataTableManager.initializeFilters();
+ dataTableManager.initSearch();
+ }
+}
+
+KTDom.ready(() => {
+ DataTableManager.createInstance();
+});
diff --git a/resources/metronic/app/layouts/base.js b/resources/metronic/app/layouts/base.js
index 4dbab0c..5928400 100644
--- a/resources/metronic/app/layouts/base.js
+++ b/resources/metronic/app/layouts/base.js
@@ -4,10 +4,10 @@ class KTLayout {
}
static _handleMegaMenu() {
- const megamenuEl = document.querySelector('#megamenu');
- if (!megamenuEl) return;
+ const megaMenuEl = document.querySelector('#mega_menu');
+ if (!megaMenuEl) return;
- const menu = KTMenu.getInstance(megamenuEl);
+ const menu = KTMenu.getInstance(megaMenuEl);
menu.disable();
setTimeout(() => {
diff --git a/resources/metronic/app/widgets/general.js b/resources/metronic/app/widgets/general.js
new file mode 100644
index 0000000..095998e
--- /dev/null
+++ b/resources/metronic/app/widgets/general.js
@@ -0,0 +1,645 @@
+class KTGeneralWidgets {
+ static initCompanyProfileMap() {
+ const element = 'company_profile_map';
+
+ if (!KTDom.getElement(`#${element}`)) return;
+
+ // Check if Leaflet is included
+ if (!L) {
+ return;
+ }
+
+ // Define Map Location
+ const leaflet = L.map(element, {
+ center: [40.725, -73.985],
+ zoom: 30
+ });
+
+ // Init Leaflet Map. For more info check the plugin's documentation: https://leafletjs.com/
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
+ attribution: '© OpenStreetMap contributors'
+ }).addTo(leaflet);
+
+ // Set Geocoding
+ let geocodeService;
+ if (typeof L.esri.Geocoding === 'undefined') {
+ geocodeService = L.esri.geocodeService();
+ } else {
+ geocodeService = L.esri.Geocoding.geocodeService();
+ }
+
+ // Define Marker Layer
+ const markerLayer = L.layerGroup().addTo(leaflet);
+
+ // Set Custom SVG icon marker
+ const leafletIcon = L.divIcon({
+ html: ``,
+ bgPos: [10, 10],
+ iconAnchor: [20, 37],
+ popupAnchor: [0, -37],
+ className: 'leaflet-marker'
+ });
+
+ // Show current address
+ L.marker([40.724716, -73.984789], { icon: leafletIcon }).addTo(markerLayer).bindPopup('430 E 6th St, New York, 10009.', { closeButton: false }).openPopup();
+
+ // Map onClick Action
+ leaflet.on('click', function (e) {
+ geocodeService.reverse().latlng(e.latlng).run(function (error, result) {
+ if (error) {
+ return;
+ }
+ markerLayer.clearLayers();
+ const selectedlocation = result.address.Match_addr;
+ L.marker(result.latlng, { icon: leafletIcon }).addTo(markerLayer).bindPopup(result.address.Match_addr, { closeButton: false }).openPopup();
+ });
+ });
+ }
+
+ static initContributionChart() {
+ const data = [44, 55, 41, 17, 15];
+ const labels = ['ERP', 'HRM', 'DMS', 'CRM', 'DAM'];
+ const colors = ['var(--tw-primary)', 'var(--tw-brand)', 'var(--tw-success)', 'var(--tw-info)', 'var(--tw-warning)'];
+
+ const options = {
+ series: data,
+ labels: labels,
+ colors: colors,
+ fill: {
+ colors: colors,
+ },
+ chart: {
+ type: 'donut',
+ },
+ stroke: {
+ show: true,
+ width: 2, // Set the width of the border
+ colors: 'var(--tw-light)' // Set the color of the border
+ },
+ dataLabels: {
+ enabled: false,
+ },
+ plotOptions: {
+ pie: {
+ expandOnClick: false,
+ }
+ },
+ legend: {
+ offsetY: -10,
+ offsetX: -10,
+ fontSize: '13px', // Set the font size
+ fontWeight: '500', // Set the font weight
+ itemMargin: {
+ vertical: 1 // Reduce the vertical margin between legend items
+ },
+ labels: {
+ colors: 'var(--tw-gray-700)', // Set the font color for the legend text
+ useSeriesColors: false // Optional: Set to true to use series colors for legend text
+ },
+ markers: {
+ width: 8,
+ height: 8
+ }
+ },
+ responsive: [{
+ breakpoint: 480,
+ options: {
+ chart: {
+ width: 200
+ },
+ legend: {
+ position: 'bottom'
+ }
+ }
+ }]
+ };
+
+ const element = document.querySelector('#contributions_chart');
+ if (!element) return;
+
+ const chart = new ApexCharts(element, options);
+ chart.render();
+ }
+
+ static initMediaUploadsChart() {
+ const data = [85, 65, 50, 70, 40, 45, 100, 55, 85, 60, 70, 90];
+ const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+ const options = {
+ series: [{
+ name: 'series1',
+ data: data
+ }],
+ chart: {
+ height: 250,
+ type: 'area',
+ toolbar: {
+ show: false
+ }
+ },
+ dataLabels: {
+ enabled: false
+ },
+ legend: {
+ show: false
+ },
+ stroke: {
+ curve: 'smooth',
+ show: true,
+ width: 3,
+ colors: ['var(--tw-primary)']
+ },
+ xaxis: {
+ categories: categories,
+ axisBorder: {
+ show: false,
+ },
+ maxTicks: 12,
+ axisTicks: {
+ show: false
+ },
+ labels: {
+ style: {
+ colors: 'var(--tw-gray-500)',
+ fontSize: '12px'
+ }
+ },
+ crosshairs: {
+ position: 'front',
+ stroke: {
+ color: 'var(--tw-primary)',
+ width: 1,
+ dashArray: 3
+ }
+ },
+ tooltip: {
+ enabled: false,
+ formatter: undefined,
+ offsetY: 0,
+ style: {
+ fontSize: '12px'
+ }
+ }
+ },
+ yaxis: {
+ min: 0,
+ max: 100,
+ tickAmount: 5, // This will create 5 ticks: 0, 20, 40, 60, 80, 100
+ axisTicks: {
+ show: false
+ },
+ labels: {
+ style: {
+ colors: 'var(--tw-gray-500)',
+ fontSize: '12px'
+ },
+ formatter: (value) => {
+ return `$${value}K`;
+ }
+ }
+ },
+ tooltip: {
+ enabled: true,
+ custom({series, seriesIndex, dataPointIndex, w}) {
+ const number = parseInt(series[seriesIndex][dataPointIndex]) * 1000;
+ const month = w.globals.seriesX[seriesIndex][dataPointIndex];
+ const monthName = categories[month];
+
+ const formatter = new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD',
+ });
+
+ const formattedNumber = formatter.format(number);
+
+ return (
+ `
+
+
${monthName}, 2024 Sales
+
+
${formattedNumber}
+
+24%
+
+
+ `
+ );
+ }
+ },
+ markers: {
+ size: 0,
+ colors: 'var(--tw-primary-light)',
+ strokeColors: 'var(--tw-primary)',
+ strokeWidth: 4,
+ strokeOpacity: 1,
+ strokeDashArray: 0,
+ fillOpacity: 1,
+ discrete: [],
+ shape: "circle",
+ radius: 2,
+ offsetX: 0,
+ offsetY: 0,
+ onClick: undefined,
+ onDblClick: undefined,
+ showNullDataPoints: true,
+ hover: {
+ size: 8,
+ sizeOffset: 0
+ }
+ },
+ fill: {
+ gradient: {
+ enabled: true,
+ opacityFrom: 0.25,
+ opacityTo: 0
+ }
+ },
+ grid: {
+ borderColor: 'var(--tw-gray-200)',
+ strokeDashArray: 5,
+ clipMarkers: false,
+ yaxis: {
+ lines: {
+ show: true
+ }
+ },
+ xaxis: {
+ lines: {
+ show: false
+ }
+ },
+ },
+ };
+
+ const element = document.querySelector('#media_uploads_chart');
+ if (!element) return;
+
+ const chart = new ApexCharts(element, options);
+ chart.render();
+ }
+
+ static initEarningsChart() {
+ const data = [75, 25, 45, 15, 85, 35, 70, 25, 35, 15, 45, 30];
+ const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+ const options = {
+ series: [{
+ name: 'series1',
+ data: data
+ }],
+ chart: {
+ height: 250,
+ type: 'area',
+ toolbar: {
+ show: false
+ }
+ },
+ dataLabels: {
+ enabled: false
+ },
+ legend: {
+ show: false
+ },
+ stroke: {
+ curve: 'smooth',
+ show: true,
+ width: 3,
+ colors: ['var(--tw-primary)']
+ },
+ xaxis: {
+ categories: categories,
+ axisBorder: {
+ show: false,
+ },
+ maxTicks: 12,
+ axisTicks: {
+ show: false
+ },
+ labels: {
+ style: {
+ colors: 'var(--tw-gray-500)',
+ fontSize: '12px'
+ }
+ },
+ crosshairs: {
+ position: 'front',
+ stroke: {
+ color: 'var(--tw-primary)',
+ width: 1,
+ dashArray: 3
+ }
+ },
+ tooltip: {
+ enabled: false,
+ formatter: undefined,
+ offsetY: 0,
+ style: {
+ fontSize: '12px'
+ }
+ }
+ },
+ yaxis: {
+ min: 0,
+ max: 100,
+ tickAmount: 5, // This will create 5 ticks: 0, 20, 40, 60, 80, 100
+ axisTicks: {
+ show: false
+ },
+ labels: {
+ style: {
+ colors: 'var(--tw-gray-500)',
+ fontSize: '12px'
+ },
+ formatter: (value) => {
+ return `$${value}K`;
+ }
+ }
+ },
+ tooltip: {
+ enabled: true,
+ custom({series, seriesIndex, dataPointIndex, w}) {
+ const number = parseInt(series[seriesIndex][dataPointIndex]) * 1000;
+ const month = w.globals.seriesX[seriesIndex][dataPointIndex];
+ const monthName = categories[month];
+
+ const formatter = new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD',
+ });
+
+ const formattedNumber = formatter.format(number);
+
+ return (
+ `
+
+
${monthName}, 2024 Sales
+
+
${formattedNumber}
+
+24%
+
+
+ `
+ );
+ }
+ },
+ markers: {
+ size: 0,
+ colors: 'var(--tw-primary-light)',
+ strokeColors: 'var(--tw-primary)',
+ strokeWidth: 4,
+ strokeOpacity: 1,
+ strokeDashArray: 0,
+ fillOpacity: 1,
+ discrete: [],
+ shape: "circle",
+ radius: 2,
+ offsetX: 0,
+ offsetY: 0,
+ onClick: undefined,
+ onDblClick: undefined,
+ showNullDataPoints: true,
+ hover: {
+ size: 8,
+ sizeOffset: 0
+ }
+ },
+ fill: {
+ gradient: {
+ enabled: true,
+ opacityFrom: 0.25,
+ opacityTo: 0
+ }
+ },
+ grid: {
+ borderColor: 'var(--tw-gray-200)',
+ strokeDashArray: 5,
+ clipMarkers: false,
+ yaxis: {
+ lines: {
+ show: true
+ }
+ },
+ xaxis: {
+ lines: {
+ show: false
+ }
+ },
+ },
+ };
+
+ const element = document.querySelector('#earnings_chart');
+ if (!element) return;
+
+ const chart = new ApexCharts(element, options);
+ chart.render();
+ }
+
+ static initMyBalanceChart(chartId, data, categories) {
+ const options = {
+ series: [{
+ name: 'series1',
+ data: data
+ }],
+ chart: {
+ height: 250,
+ type: 'area',
+ toolbar: {
+ show: false
+ }
+ },
+ dataLabels: {
+ enabled: false
+ },
+ legend: {
+ show: false
+ },
+ stroke: {
+ curve: 'smooth',
+ show: true,
+ width: 3,
+ colors: ['var(--tw-primary)']
+ },
+ xaxis: {
+ categories: categories,
+ axisBorder: {
+ show: false,
+ },
+ axisTicks: {
+ show: false
+ },
+ labels: {
+ style: {
+ colors: 'var(--tw-gray-600)',
+ fontSize: '12px'
+ }
+ },
+ crosshairs: {
+ position: 'front',
+ stroke: {
+ color: 'var(--tw-primary)',
+ width: 1,
+ dashArray: 3
+ }
+ },
+ tooltip: {
+ enabled: false,
+ formatter: undefined,
+ offsetY: 0,
+ style: {
+ fontSize: '12px'
+ }
+ }
+ },
+ yaxis: {
+ min: 0,
+ max: 100,
+ tickAmount: 5,
+ axisTicks: {
+ show: false
+ },
+ labels: {
+ style: {
+ colors: 'var(--tw-gray-600)',
+ fontSize: '12px'
+ },
+ formatter: (value) => {
+ return `$${value}K`;
+ }
+ }
+ },
+ tooltip: {
+ enabled: true,
+ custom({series, seriesIndex, dataPointIndex, w}) {
+ const number = parseInt(series[seriesIndex][dataPointIndex]) * 1000;
+ const month = w.globals.seriesX[seriesIndex][dataPointIndex];
+ const monthName = categories[month];
+
+ const formatter = new Intl.NumberFormat('en-US', {
+ style: 'currency',
+ currency: 'USD',
+ });
+
+ const formattedNumber = formatter.format(number);
+
+ return (
+ `
+
+
${monthName}, 2024 Sales
+
+
${formattedNumber}
+
+24%
+
+
+ `
+ );
+ }
+ },
+ markers: {
+ size: 0,
+ colors: 'var(--tw-primary-light)',
+ strokeColors: 'var(--tw-primary)',
+ strokeWidth: 4,
+ strokeOpacity: 1,
+ strokeDashArray: 0,
+ fillOpacity: 1,
+ discrete: [],
+ shape: "circle",
+ radius: 2,
+ offsetX: 0,
+ offsetY: 0,
+ onClick: undefined,
+ onDblClick: undefined,
+ showNullDataPoints: true,
+ hover: {
+ size: 8,
+ sizeOffset: 0
+ }
+ },
+ fill: {
+ gradient: {
+ enabled: true,
+ opacityFrom: 0.25,
+ opacityTo: 0
+ }
+ },
+ grid: {
+ borderColor: 'var(--tw-gray-200)',
+ strokeDashArray: 5,
+ clipMarkers: false,
+ yaxis: {
+ lines: {
+ show: true
+ }
+ },
+ xaxis: {
+ lines: {
+ show: false
+ }
+ },
+ },
+ };
+
+ const element = document.querySelector(`#${chartId}`);
+ if (!element) return;
+
+ // Destroy the old chart instance if it exists
+ if (element.chart) {
+ element.chart.destroy();
+ }
+
+ const chart = new ApexCharts(element, options);
+ element.chart = chart; // Store the chart instance on the element
+ chart.render();
+ }
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ // Initial chart rendering
+ KTGeneralWidgets.initMyBalanceChart('my_balance_chart', [75, 25, 45, 15, 85, 35, 70, 25, 35], ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep']);
+
+ // Event listener for tab buttons
+ document.querySelectorAll('.tab-button').forEach(button => {
+ button.addEventListener('click', (event) => {
+ // Remove active class from all buttons
+ document.querySelectorAll('.tab-button').forEach(btn => btn.classList.remove('active'));
+
+ // Add active class to the clicked button
+ event.target.classList.add('active');
+
+ // Determine chart data and categories based on the clicked tab
+ const chartId = 'my_balance_chart'; // You might need to adjust this if you have multiple charts
+ let data, categories;
+ switch (event.target.getAttribute('data-chart')) {
+ case 'my_balance_chart1':
+ data = [45, 35, 45, 35, 55, 85, 20, 25, 55];
+ categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'];
+ break;
+ case 'my_balance_chart2':
+ data = [25, 55, 65, 45, 25, 65, 50, 40, 60];
+ categories = ['Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
+ break;
+ case 'my_balance_chart3':
+ data = [80, 40, 50, 20, 50, 80, 60, 20, 30];
+ categories = ['Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan', 'Feb', 'Mar'];
+ break;
+ case 'my_balance_chart4':
+ data = [20, 65, 20, 50, 70, 25, 40, 60, 80];
+ categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'];
+ break;
+ default:
+ data = [];
+ categories = [];
+ }
+
+ // Update chart with new data and categories
+ KTGeneralWidgets.initMyBalanceChart(chartId, data, categories);
+ });
+ });
+});
+
+
+KTDom.ready(() => {
+ KTGeneralWidgets.initCompanyProfileMap();
+ KTGeneralWidgets.initContributionChart();
+ KTGeneralWidgets.initMediaUploadsChart();
+ KTGeneralWidgets.initEarningsChart();
+});
\ No newline at end of file
diff --git a/resources/metronic/core/components/collapse/collapse.ts b/resources/metronic/core/components/collapse/collapse.ts
index 8f3e7d4..f2e0f18 100644
--- a/resources/metronic/core/components/collapse/collapse.ts
+++ b/resources/metronic/core/components/collapse/collapse.ts
@@ -166,7 +166,7 @@ export class KTCollapse extends KTComponent implements KTCollapseInterface {
}
public static createInstances(): void {
- const elements = document.querySelectorAll('[data-collapse]:not([data-collapse="false"]');
+ const elements = document.querySelectorAll('[data-collapse]:not([data-collapse="false"])');
elements.forEach((element) => {
new KTCollapse(element as HTMLElement);
diff --git a/resources/metronic/core/components/component.ts b/resources/metronic/core/components/component.ts
index f30d7ab..249d88f 100644
--- a/resources/metronic/core/components/component.ts
+++ b/resources/metronic/core/components/component.ts
@@ -70,21 +70,21 @@ export default class KTComponent {
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);
+ for (let i = parts.length - 1; i < parts.length; i--) {
+ const part = parts[i];
+ if (part.includes(':')) {
+ const [breakpointKey, breakpointValue] = part.split(':');
+ const breakpoint = KTUtils.getBreakpoint(breakpointKey as KTBreakpointType);
if (breakpoint <= width) {
result = breakpointValue;
- return false;
+ break;
}
} else {
result = part;
+ break;
}
-
- return true;
- });
+ }
} else {
result = value;
}
diff --git a/resources/metronic/core/components/datatable/types.ts b/resources/metronic/core/components/datatable/types.ts
index 717e941..decef07 100644
--- a/resources/metronic/core/components/datatable/types.ts
+++ b/resources/metronic/core/components/datatable/types.ts
@@ -76,7 +76,7 @@ export interface KTDataTableConfigInterface {
stateSave?: boolean;
stateNamespace?: string;
pageSizes?: number[];
- columns: {
+ columns?: {
[key: keyof KTDataTableDataInterface | string]: {
title?: string,
render?: (item: KTDataTableDataInterface[keyof KTDataTableDataInterface] | string, data: KTDataTableDataInterface, context: KTDataTableInterface) => string,
diff --git a/resources/metronic/core/components/dismiss/dismiss.ts b/resources/metronic/core/components/dismiss/dismiss.ts
index 94ddb7f..255ae3a 100644
--- a/resources/metronic/core/components/dismiss/dismiss.ts
+++ b/resources/metronic/core/components/dismiss/dismiss.ts
@@ -120,7 +120,7 @@ export class KTDismiss extends KTComponent implements KTDismissInterface {
}
public static createInstances(): void {
- const elements = document.querySelectorAll('[data-dismiss]:not([data-dismiss="false"]');
+ const elements = document.querySelectorAll('[data-dismiss]:not([data-dismiss="false"])');
elements.forEach((element) => {
new KTDismiss(element as HTMLElement);
diff --git a/resources/metronic/core/components/menu/menu.ts b/resources/metronic/core/components/menu/menu.ts
index 920c946..2cc8dc1 100644
--- a/resources/metronic/core/components/menu/menu.ts
+++ b/resources/metronic/core/components/menu/menu.ts
@@ -1128,7 +1128,7 @@ export class KTMenu extends KTComponent implements KTMenuInterface {
public static handleClick() {
KTEventHandler.on(
document.body,
- '.menu-item[data-menu-item-trigger] > .menu-link, .menu-item[data-menu-item-trigger] > .menu-toggle, .menu-item[data-menu-item-trigger] > .menu-label .menu-toggle, [data-menu-item-trigger]:not(.menu-item):not([data-menu-item-trigger="auto"])',
+ '.menu-item[data-menu-item-trigger] > .menu-link, .menu-item[data-menu-item-trigger] > .menu-label .menu-toggle, .menu-item[data-menu-item-trigger] > .menu-toggle, [data-menu-item-trigger]:not(.menu-item):not([data-menu-item-trigger="auto"])',
'click',
(event: Event, target: HTMLElement) => {
const menu = KTMenu.getInstance(target);
@@ -1147,6 +1147,9 @@ export class KTMenu extends KTComponent implements KTMenuInterface {
const menu = KTMenu.getInstance(target);
if (menu !== null) {
+ if (target.tagName == 'a' || target.hasAttribute('href')) {
+ menu.dismiss(target);
+ }
return menu.link(target, event);
}
}
@@ -1188,12 +1191,12 @@ export class KTMenu extends KTComponent implements KTMenuInterface {
}
public static initHandlers(): void {
+ this.handleDismiss();
this.handleClickAway();
this.handleKeyboard();
this.handleMouseover();
this.handleMouseout();
this.handleClick();
- this.handleDismiss();
this.handleResize();
}
diff --git a/resources/metronic/core/components/scrollable/scrollable.ts b/resources/metronic/core/components/scrollable/scrollable.ts
index d1aba69..fba0bad 100644
--- a/resources/metronic/core/components/scrollable/scrollable.ts
+++ b/resources/metronic/core/components/scrollable/scrollable.ts
@@ -19,7 +19,7 @@ export class KTScrollable extends KTComponent implements KTScrollableInterface {
save: true,
dependencies: '',
wrappers: '',
- offset: '',
+ offset: ''
};
protected override _config: KTScrollableConfigInterface = this._defaultConfig;
protected _elementId: string | null = null;
@@ -53,11 +53,12 @@ export class KTScrollable extends KTComponent implements KTScrollableInterface {
protected _setupHeight(): void {
if (!this._element) return;
+
const heightType = this._getHeightType();
const height = this._getHeight();
// Set height
- if (height && height.length > 0) {
+ if (height && height != '0' && height.length > 0) {
this._element.style.setProperty(heightType, height);
} else {
this._element.style.setProperty(heightType, '');
diff --git a/resources/metronic/core/components/scrollable/types.ts b/resources/metronic/core/components/scrollable/types.ts
index 8d8f07f..b6b2565 100644
--- a/resources/metronic/core/components/scrollable/types.ts
+++ b/resources/metronic/core/components/scrollable/types.ts
@@ -2,7 +2,7 @@ export interface KTScrollableConfigInterface {
save: boolean,
dependencies: string,
wrappers: string,
- offset: string,
+ offset: string
}
export interface KTScrollableInterface {
diff --git a/resources/metronic/core/components/scrollto/scrollto.ts b/resources/metronic/core/components/scrollto/scrollto.ts
index 884418f..d0d2009 100644
--- a/resources/metronic/core/components/scrollto/scrollto.ts
+++ b/resources/metronic/core/components/scrollto/scrollto.ts
@@ -90,7 +90,7 @@ export class KTScrollto extends KTComponent implements KTScrolltoInterface {
}
public static createInstances(): void {
- const elements = document.querySelectorAll('[data-scrollto]:not([data-scrollto="false"]');
+ const elements = document.querySelectorAll('[data-scrollto]:not([data-scrollto="false"])');
elements.forEach((element) => {
new KTScrollto(element as HTMLElement);
diff --git a/resources/metronic/core/components/sticky/sticky.ts b/resources/metronic/core/components/sticky/sticky.ts
index e32b75e..fc44b93 100644
--- a/resources/metronic/core/components/sticky/sticky.ts
+++ b/resources/metronic/core/components/sticky/sticky.ts
@@ -20,13 +20,14 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
offset: 0,
reverse: false,
release: '',
- activate: ''
+ activate: '',
};
protected override _config: KTStickyConfigInterface = this._defaultConfig;
protected _attributeRoot: string;
protected _eventTriggerState: boolean;
protected _lastScrollTop: number;
protected _releaseElement: HTMLElement;
+ protected _activateElement: HTMLElement;
protected _wrapperElement: HTMLElement;
constructor(element: HTMLElement, config: KTStickyConfigInterface | null = null) {
@@ -38,6 +39,7 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
this._buildConfig(config);
this._releaseElement = KTDom.getElement(this._getOption('release') as string);
+ this._activateElement = KTDom.getElement(this._getOption('activate') as string);
this._wrapperElement = this._element.closest('[data-sticky-wrapper]');
this._attributeRoot = `data-sticky-${this._getOption('name')}`;
this._eventTriggerState = true;
@@ -68,21 +70,20 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
protected _process(): void {
const reverse = this._getOption('reverse');
- const activateOffset = this._getActivateOffset();
- const releaseOffset = this._getReleaseOffset();
+ const offset = this._getOffset();
- if (activateOffset < 0) {
+ if (offset < 0) {
this._disable();
return;
}
const st = KTDom.getScrollTop();
- const proceed = (!this._releaseElement || releaseOffset > st);
+ const release = (this._releaseElement && KTDom.isPartiallyInViewport(this._releaseElement));
// Release on reverse scroll mode
if (reverse === true) {
// Forward scroll mode
- if (st > activateOffset && proceed) {
+ if (st > offset && !release) {
if (document.body.hasAttribute(this._attributeRoot) === false) {
if (this._enable() === false) {
return;
@@ -101,6 +102,9 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
} else {
if (document.body.hasAttribute(this._attributeRoot) === true) {
this._disable();
+ if (release) {
+ this._element.classList.add('release');
+ }
document.body.removeAttribute(this._attributeRoot);
}
@@ -116,7 +120,7 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
// Classic scroll mode
} else {
// Forward scroll mode
- if (st > activateOffset && proceed) {
+ if (st > offset && !release) {
if (document.body.hasAttribute(this._attributeRoot) === false) {
if (this._enable() === false) {
return;
@@ -135,6 +139,9 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
} else { // back scroll mode
if (document.body.hasAttribute(this._attributeRoot) === true) {
this._disable();
+ if (release) {
+ this._element.classList.add('release');
+ }
document.body.removeAttribute(this._attributeRoot);
}
@@ -148,7 +155,7 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
}
}
- protected _getActivateOffset(): number {
+ protected _getOffset(): number {
let offset = parseInt(this._getOption('offset') as string);
const activateElement = KTDom.getElement(this._getOption('activate') as string);
@@ -159,16 +166,6 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
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;
@@ -235,6 +232,7 @@ export class KTSticky extends KTComponent implements KTStickyInterface {
}
this._element.classList.add('active');
+ this._element.classList.remove('release');
return true;
}
diff --git a/resources/metronic/core/components/toggle-password/toggle-password.ts b/resources/metronic/core/components/toggle-password/toggle-password.ts
index 5fe5d7e..4681bab 100644
--- a/resources/metronic/core/components/toggle-password/toggle-password.ts
+++ b/resources/metronic/core/components/toggle-password/toggle-password.ts
@@ -24,7 +24,7 @@ export class KTTogglePassword extends KTComponent implements KTTogglePasswordInt
this._buildConfig(config);
this._triggerElement = this._element.querySelector('[data-toggle-password-trigger]');
- this._inputElement = this._element.querySelector('input[type="password"]');
+ this._inputElement = this._element.querySelector('input');
if (!this._triggerElement || !this._inputElement) {
return;
@@ -36,12 +36,11 @@ export class KTTogglePassword extends KTComponent implements KTTogglePasswordInt
protected _handlers(): void {
if (!this._element) return;
- this._triggerElement.addEventListener('click', () => {
+ this._triggerElement.addEventListener('click', (e: Event) => {
this._toggle();
});
this._inputElement.addEventListener('input', () => {
-
this._update();
});
}
diff --git a/resources/metronic/core/components/toggle/toggle.ts b/resources/metronic/core/components/toggle/toggle.ts
index 6aab462..e052954 100644
--- a/resources/metronic/core/components/toggle/toggle.ts
+++ b/resources/metronic/core/components/toggle/toggle.ts
@@ -131,7 +131,7 @@ export class KTToggle extends KTComponent implements KTToggleInterface {
}
public static createInstances(): void {
- const elements = document.querySelectorAll('[data-toggle]:not([data-toggle="false"]');
+ const elements = document.querySelectorAll('[data-toggle]:not([data-toggle="false"])');
elements.forEach((element) => {
new KTToggle(element as HTMLElement);
});
diff --git a/resources/metronic/core/components/tooltip/tooltip.ts b/resources/metronic/core/components/tooltip/tooltip.ts
index 1806a50..03e31c4 100644
--- a/resources/metronic/core/components/tooltip/tooltip.ts
+++ b/resources/metronic/core/components/tooltip/tooltip.ts
@@ -286,7 +286,7 @@ export class KTTooltip extends KTComponent implements KTTooltipInterface {
}
public static createInstances(): void {
- document.querySelectorAll('[data-tooltip]:not([data-tooltip="false"]').forEach((element) => {
+ document.querySelectorAll('[data-tooltip]:not([data-tooltip="false"])').forEach((element) => {
new KTTooltip(element as HTMLElement);
});
}
diff --git a/resources/metronic/core/index.spa.ts b/resources/metronic/core/index.spa.ts
index 1a8e452..066f6db 100644
--- a/resources/metronic/core/index.spa.ts
+++ b/resources/metronic/core/index.spa.ts
@@ -1,130 +1,135 @@
-
/*
-* Index
-* @version: 1.0.0
+* Metronic
* @author: Keenthemes
* Copyright 2024 Keenthemes
*/
-import KTUtils from './helpers/utils';
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';
+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;
+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();
- }
+ 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;
\ No newline at end of file
+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();
+});
diff --git a/resources/metronic/core/index.ts b/resources/metronic/core/index.ts
index f4fef06..066f6db 100644
--- a/resources/metronic/core/index.ts
+++ b/resources/metronic/core/index.ts
@@ -1,10 +1,9 @@
-
/*
-* Index
-* @version: 1.0.0
+* Metronic
* @author: Keenthemes
* Copyright 2024 Keenthemes
*/
+
import KTDom from './helpers/dom';
import KTUtils from './helpers/utils';
import KTEventHandler from './helpers/event-handler';
@@ -51,57 +50,57 @@ 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();
- }
+ 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;
- }
+ 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;
@@ -132,6 +131,5 @@ window.KTComponents = KTComponents;
export default KTComponents;
KTDom.ready(() => {
- KTComponents.init();
+ KTComponents.init();
});
-
diff --git a/resources/metronic/core/plugins/components/accordion.js b/resources/metronic/core/plugins/components/accordion.js
index e65d01a..95fc275 100644
--- a/resources/metronic/core/plugins/components/accordion.js
+++ b/resources/metronic/core/plugins/components/accordion.js
@@ -11,6 +11,7 @@ export default plugin(({addComponents}) => {
'display': 'flex',
'flex-grow': '1',
'align-items': 'center',
+ 'text-align': 'start',
'justify-content': 'space-between',
},
'.accordion-content': {
diff --git a/resources/metronic/core/plugins/components/btn.js b/resources/metronic/core/plugins/components/btn.js
index 666ed8a..a569c5b 100644
--- a/resources/metronic/core/plugins/components/btn.js
+++ b/resources/metronic/core/plugins/components/btn.js
@@ -209,7 +209,6 @@ export default plugin(({addComponents, theme}) => {
'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' : {
diff --git a/resources/metronic/core/plugins/components/checkbox.js b/resources/metronic/core/plugins/components/checkbox.js
index 5069685..60f47c3 100644
--- a/resources/metronic/core/plugins/components/checkbox.js
+++ b/resources/metronic/core/plugins/components/checkbox.js
@@ -10,6 +10,9 @@ export default plugin(({addComponents, theme}) => {
'appearance': 'none',
'box-shadow': 'none',
'background-color': 'var(--tw-light-light)',
+ '.dark &': {
+ 'background-color': 'var(--tw-coal-500)',
+ },
'border-radius': theme('custom.components.checkbox.DEFAULT.borderRadius'),
'height': theme('custom.components.checkbox.DEFAULT.size'),
'width': theme('custom.components.checkbox.DEFAULT.size'),
diff --git a/resources/metronic/core/plugins/components/container.js b/resources/metronic/core/plugins/components/container.js
index 971b510..008e4ef 100644
--- a/resources/metronic/core/plugins/components/container.js
+++ b/resources/metronic/core/plugins/components/container.js
@@ -6,6 +6,7 @@ export default plugin(({addComponents, theme}) => {
addComponents({
'.container-fixed': {
'flex-grow': '1',
+ 'width': '100%',
'padding-left': theme('custom.components.container.fixed.px.DEFAULT'),
'padding-right': theme('custom.components.container.fixed.px.DEFAULT')
},
@@ -23,6 +24,7 @@ export default plugin(({addComponents, theme}) => {
// Fluid
addComponents({
'.container-fluid': {
+ 'width': '100%',
'flex-grow': '1',
'padding-left': theme('custom.components.container.fluid.px.DEFAULT'),
'padding-right': theme('custom.components.container.fluid.px.DEFAULT')
diff --git a/resources/metronic/core/plugins/components/radio.js b/resources/metronic/core/plugins/components/radio.js
index 69857b2..d62cb0f 100644
--- a/resources/metronic/core/plugins/components/radio.js
+++ b/resources/metronic/core/plugins/components/radio.js
@@ -10,6 +10,9 @@ export default plugin(({addComponents, theme}) => {
'appearance': 'none',
'box-shadow': 'none',
'background-color': 'var(--tw-light-light)',
+ '.dark &': {
+ 'background-color': 'var(--tw-coal-500)',
+ },
'border-radius': '50%',
'height': theme('custom.components.radio.DEFAULT.size'),
'width': theme('custom.components.radio.DEFAULT.size'),
diff --git a/resources/metronic/core/plugins/plugin.js b/resources/metronic/core/plugins/plugin.js
index 4e984b3..73d8054 100644
--- a/resources/metronic/core/plugins/plugin.js
+++ b/resources/metronic/core/plugins/plugin.js
@@ -27,13 +27,19 @@ export default plugin(({config, addBase, addComponents, addVariant, e}) => {
'flex-grow': '1',
'line-height': '1',
},
+ '.menu-toggle': {
+ 'display': 'flex',
+ 'align-items': 'center',
+ 'flex-grow': '1',
+ 'line-height': '1',
+ },
'.menu-title': {
'display': 'flex',
'align-items': 'center',
'line-height': '1',
'flex-grow': '1',
},
- '.menu-icon, .menu-toggle, .menu-bullet, .menu-badge, .menu-arrow': {
+ '.menu-icon, .menu-bullet, .menu-badge, .menu-arrow': {
'display': 'flex',
'align-items': 'center',
'flex-shrink': '0',
@@ -85,6 +91,16 @@ export default plugin(({config, addBase, addComponents, addVariant, e}) => {
modifySelectors(({className}) => {
return `.menu-item.active > .menu-label .${e(`menu-item-active${separator}${className}`)}`;
});
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.active > .menu-toggle.${e(`menu-item-active${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.active > .menu-toggle .${e(`menu-item-active${separator}${className}`)}`;
+ });
}
]);
@@ -113,6 +129,16 @@ export default plugin(({config, addBase, addComponents, addVariant, e}) => {
modifySelectors(({className}) => {
return `.menu-item.here > .menu-label .${e(`menu-item-here${separator}${className}`)}`;
});
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.here > .menu-toggle.${e(`menu-item-here${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.here > .menu-toggle .${e(`menu-item-here${separator}${className}`)}`;
+ });
}
]);
@@ -141,6 +167,54 @@ export default plugin(({config, addBase, addComponents, addVariant, e}) => {
modifySelectors(({className}) => {
return `.menu-item.show > .menu-label .${e(`menu-item-show${separator}${className}`)}`;
});
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.show > .menu-toggle.${e(`menu-item-show${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.show > .menu-toggle .${e(`menu-item-show${separator}${className}`)}`;
+ });
+ }
+ ]);
+
+ addVariant('menu-item-disabled', [
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.disabled.${e(`menu-item-disabled${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.disabled > .menu-link.${e(`menu-item-disabled${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.disabled > .menu-link .${e(`menu-item-disabled${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.disabled > .menu-label.${e(`menu-item-disabled${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.disabled > .menu-label .${e(`menu-item-disabled${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.disabled > .menu-toggle.${e(`menu-item-disabled${separator}${className}`)}`;
+ });
+ },
+ ({modifySelectors, separator}) => {
+ modifySelectors(({className}) => {
+ return `.menu-item.disabled > .menu-toggle .${e(`menu-item-disabled${separator}${className}`)}`;
+ });
}
]);
@@ -168,7 +242,7 @@ export default plugin(({config, addBase, addComponents, addVariant, e}) => {
return `.menu-link:focus .${e(`menu-link-focus${separator}${className}`)}`;
});
},
- ]);
+ ]);
// DataTable
addVariant('datatable-loading', [
diff --git a/resources/metronic/css/base.css b/resources/metronic/css/base.css
index 8d9bf41..31b289a 100644
--- a/resources/metronic/css/base.css
+++ b/resources/metronic/css/base.css
@@ -1,126 +1,126 @@
/* Variables */
.metronic {
- --tw-sidebar-transition-duration: 0.3s;
- --tw-sidebar-transition-timing: ease;
- --tw-sidebar-width: theme('custom.layouts.metronic.sidebar.width.desktop');
- --tw-sidebar-defualt-width: theme('custom.layouts.metronic.sidebar.width.desktop');
- --tw-header-height: theme('custom.layouts.metronic.header.height.desktop');
+ --tw-sidebar-transition-duration: 0.3s;
+ --tw-sidebar-transition-timing: ease;
+ --tw-sidebar-width: theme('custom.layouts.metronic.sidebar.width.desktop');
+ --tw-sidebar-defualt-width: theme('custom.layouts.metronic.sidebar.width.desktop');
+ --tw-header-height: theme('custom.layouts.metronic.header.height.desktop');
}
@media (max-width: theme('screens.lg')) {
- .metronic {
- --tw-sidebar-width: theme('custom.layouts.metronic.sidebar.width.mobile');
- --tw-header-height: theme('custom.layouts.metronic.header.height.mobile');
- }
+ .metronic {
+ --tw-sidebar-width: theme('custom.layouts.metronic.sidebar.width.mobile');
+ --tw-header-height: theme('custom.layouts.metronic.header.height.mobile');
+ }
}
/* Base */
.metronic .header {
- height: var(--tw-header-height);
+ height: var(--tw-header-height);
}
.metronic .sidebar {
- width: var(--tw-sidebar-width);
+ width: var(--tw-sidebar-width);
}
.metronic.header-fixed .wrapper {
- padding-top: var(--tw-header-height);
+ padding-top: var(--tw-header-height);
}
/* Desktop mode */
@media (min-width: theme('screens.lg')) {
- .metronic .sidebar {
- width: var(--tw-sidebar-width);
- transition: width var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
- }
+ .metronic .sidebar {
+ width: var(--tw-sidebar-width);
+ transition: width var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
+ }
- .metronic .sidebar .sidebar-header {
- height: var(--tw-header-height);
- }
+ .metronic .sidebar .sidebar-header {
+ height: var(--tw-header-height);
+ }
- .metronic .sidebar .sidebar-wrapper {
- width: var(--tw-sidebar-defualt-width);
- }
+ .metronic .sidebar .sidebar-wrapper {
+ width: var(--tw-sidebar-defualt-width);
+ }
- .metronic .sidebar .sidebar-logo {
- width: var(--tw-sidebar-defualt-width);
- }
+ .metronic .sidebar .sidebar-logo {
+ width: var(--tw-sidebar-defualt-width);
+ }
- .metronic .sidebar .small-logo {
- display: none;
- }
+ .metronic .sidebar .small-logo {
+ display: none;
+ }
- .metronic.sidebar-fixed .wrapper {
- padding-left: var(--tw-sidebar-width);
- transition: padding-left var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
- }
+ .metronic.sidebar-fixed .wrapper {
+ padding-left: var(--tw-sidebar-width);
+ transition: padding-left var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
+ }
- .metronic.sidebar-fixed.header-fixed .header {
- left: var(--tw-sidebar-width);
- transition: left var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
- }
+ .metronic.sidebar-fixed.header-fixed .header {
+ left: var(--tw-sidebar-width);
+ transition: left var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
+ }
- .metronic.sidebar-fixed.header-fixed .wrapper {
- padding-top: var(--tw-header-height);
- }
+ .metronic.sidebar-fixed.header-fixed .wrapper {
+ padding-top: var(--tw-header-height);
+ }
- .metronic.sidebar-collapse {
- --tw-sidebar-width: theme('custom.layouts.metronic.sidebar.width.desktopCollapse');
- }
+ .metronic.sidebar-collapse {
+ --tw-sidebar-width: theme('custom.layouts.metronic.sidebar.width.desktopCollapse');
+ }
- .metronic.sidebar-collapse .sidebar {
- transition: width var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
- }
+ .metronic.sidebar-collapse .sidebar {
+ transition: width var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
+ }
- .metronic.sidebar-collapse .sidebar.animating {
- pointer-events: none;
- }
+ .metronic.sidebar-collapse .sidebar.animating {
+ pointer-events: none;
+ }
- .metronic.sidebar-collapse .sidebar:hover:not(.animating) {
- width: var(--tw-sidebar-defualt-width);
- transition: width var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
- }
+ .metronic.sidebar-collapse .sidebar:hover:not(.animating) {
+ width: var(--tw-sidebar-defualt-width);
+ transition: width var(--tw-sidebar-transition-duration) var(--tw-sidebar-transition-timing);
+ }
- .metronic.sidebar-collapse .sidebar:not(:hover) .default-logo {
- display: none;
- }
+ .metronic.sidebar-collapse .sidebar:not(:hover) .default-logo {
+ display: none;
+ }
- .metronic.sidebar-collapse .sidebar:not(:hover) .small-logo {
- display: flex;
- }
+ .metronic.sidebar-collapse .sidebar:not(:hover) .small-logo {
+ display: flex;
+ }
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-link .menu-title,
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-link .menu-arrow,
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-link .menu-badge,
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-label .menu-title,
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-label .menu-arrow,
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-label .menu-badge {
- display: none;
- }
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-link .menu-title,
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-link .menu-arrow,
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-link .menu-badge,
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-label .menu-title,
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-label .menu-arrow,
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-label .menu-badge {
+ display: none;
+ }
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-accordion {
- display: none;
- }
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-accordion {
+ display: none;
+ }
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-heading {
- visibility: hidden;
- position: relative;
- }
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-heading {
+ visibility: hidden;
+ position: relative;
+ }
- .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-heading::before {
- content: "...";
- color: currentColor;
- font-size: inherit;
- position: absolute;
- visibility: visible;
- display: inline-block;
- bottom: 50%;
- left: 0;
- margin-left: 0.225rem;
- transform: translateX(100%);
- }
+ .metronic.sidebar-collapse .sidebar:not(:hover) .menu > .menu-item > .menu-heading::before {
+ content: "...";
+ color: currentColor;
+ font-size: inherit;
+ position: absolute;
+ visibility: visible;
+ display: inline-block;
+ bottom: 50%;
+ left: 0;
+ margin-left: 0.225rem;
+ transform: translateX(100%);
+ }
- .metronic.sidebar-collapse .sidebar .sidebar-content {
- overflow: hidden;
- }
+ .metronic.sidebar-collapse .sidebar .sidebar-content {
+ overflow: hidden;
+ }
}