366 lines
12 KiB
JavaScript
366 lines
12 KiB
JavaScript
/**
|
|
* Bootstrap to Tailwind Migration Helper
|
|
*
|
|
* This script provides class mappings for migrating Bootstrap templates to Tailwind CSS.
|
|
* Usage: Include this script temporarily during migration to add Bootstrap-compatible classes.
|
|
*
|
|
* NOTE: This is a temporary compatibility layer. Templates should be properly migrated
|
|
* to use px360.css classes (hh-* prefix) for long-term maintainability.
|
|
*/
|
|
|
|
(function() {
|
|
// Bootstrap to Tailwind class mappings
|
|
const bootstrapToTailwind = {
|
|
// Container & Layout
|
|
'container': 'max-w-7xl mx-auto px-4 sm:px-6 lg:px-8',
|
|
'container-fluid': 'w-full px-4',
|
|
'row': 'flex flex-wrap -mx-2',
|
|
'col': 'w-full px-2',
|
|
'col-auto': 'w-auto px-2',
|
|
|
|
// Grid columns (simplified mapping)
|
|
'col-1': 'w-1/12 px-2',
|
|
'col-2': 'w-2/12 px-2',
|
|
'col-3': 'w-3/12 px-2',
|
|
'col-4': 'w-4/12 px-2',
|
|
'col-5': 'w-5/12 px-2',
|
|
'col-6': 'w-6/12 px-2',
|
|
'col-7': 'w-7/12 px-2',
|
|
'col-8': 'w-8/12 px-2',
|
|
'col-9': 'w-9/12 px-2',
|
|
'col-10': 'w-10/12 px-2',
|
|
'col-11': 'w-11/12 px-2',
|
|
'col-12': 'w-full px-2',
|
|
|
|
// Responsive breakpoints
|
|
'col-md-1': 'md:w-1/12 px-2',
|
|
'col-md-2': 'md:w-2/12 px-2',
|
|
'col-md-3': 'md:w-3/12 px-2',
|
|
'col-md-4': 'md:w-4/12 px-2',
|
|
'col-md-6': 'md:w-6/12 px-2',
|
|
'col-md-8': 'md:w-8/12 px-2',
|
|
'col-md-12': 'md:w-full px-2',
|
|
|
|
'col-lg-3': 'lg:w-3/12 px-2',
|
|
'col-lg-4': 'lg:w-4/12 px-2',
|
|
'col-lg-6': 'lg:w-6/12 px-2',
|
|
'col-lg-8': 'lg:w-8/12 px-2',
|
|
'col-lg-12': 'lg:w-full px-2',
|
|
|
|
// Display & Flex
|
|
'd-flex': 'flex',
|
|
'd-inline-flex': 'inline-flex',
|
|
'd-block': 'block',
|
|
'd-inline-block': 'inline-block',
|
|
'd-none': 'hidden',
|
|
'd-grid': 'grid',
|
|
|
|
'justify-content-start': 'justify-start',
|
|
'justify-content-end': 'justify-end',
|
|
'justify-content-center': 'justify-center',
|
|
'justify-content-between': 'justify-between',
|
|
'justify-content-around': 'justify-around',
|
|
|
|
'align-items-start': 'items-start',
|
|
'align-items-end': 'items-end',
|
|
'align-items-center': 'items-center',
|
|
'align-items-baseline': 'items-baseline',
|
|
'align-items-stretch': 'items-stretch',
|
|
|
|
'flex-row': 'flex-row',
|
|
'flex-column': 'flex-col',
|
|
'flex-wrap': 'flex-wrap',
|
|
'flex-nowrap': 'flex-nowrap',
|
|
'flex-grow-1': 'flex-grow',
|
|
'flex-shrink-0': 'flex-shrink-0',
|
|
|
|
// Spacing (simplified)
|
|
'm-0': 'm-0',
|
|
'm-1': 'm-1',
|
|
'm-2': 'm-2',
|
|
'm-3': 'm-4',
|
|
'm-4': 'm-6',
|
|
'm-5': 'm-8',
|
|
|
|
'mt-1': 'mt-1',
|
|
'mt-2': 'mt-2',
|
|
'mt-3': 'mt-4',
|
|
'mt-4': 'mt-6',
|
|
'mt-5': 'mt-8',
|
|
|
|
'mb-1': 'mb-1',
|
|
'mb-2': 'mb-2',
|
|
'mb-3': 'mb-4',
|
|
'mb-4': 'mb-6',
|
|
'mb-5': 'mb-8',
|
|
|
|
'ms-1': 'ms-1',
|
|
'ms-2': 'ms-2',
|
|
'ms-3': 'ms-4',
|
|
'ms-auto': 'ms-auto',
|
|
|
|
'me-1': 'me-1',
|
|
'me-2': 'me-2',
|
|
'me-3': 'me-4',
|
|
'me-auto': 'me-auto',
|
|
|
|
'p-0': 'p-0',
|
|
'p-1': 'p-1',
|
|
'p-2': 'p-2',
|
|
'p-3': 'p-4',
|
|
'p-4': 'p-6',
|
|
'p-5': 'p-8',
|
|
|
|
'px-1': 'px-1',
|
|
'px-2': 'px-2',
|
|
'px-3': 'px-4',
|
|
'px-4': 'px-6',
|
|
|
|
'py-1': 'py-1',
|
|
'py-2': 'py-2',
|
|
'py-3': 'py-4',
|
|
'py-4': 'py-6',
|
|
|
|
'gap-1': 'gap-1',
|
|
'gap-2': 'gap-2',
|
|
'gap-3': 'gap-4',
|
|
|
|
// Text
|
|
'text-start': 'text-left',
|
|
'text-end': 'text-right',
|
|
'text-center': 'text-center',
|
|
'text-truncate': 'truncate',
|
|
'text-wrap': 'break-words',
|
|
'text-nowrap': 'whitespace-nowrap',
|
|
|
|
'fw-bold': 'font-bold',
|
|
'fw-semibold': 'font-semibold',
|
|
'fw-normal': 'font-normal',
|
|
'fw-light': 'font-light',
|
|
'fst-italic': 'italic',
|
|
|
|
'text-muted': 'text-gray-500',
|
|
'text-primary': 'text-blue-600',
|
|
'text-success': 'text-green-600',
|
|
'text-danger': 'text-red-600',
|
|
'text-warning': 'text-yellow-600',
|
|
'text-info': 'text-blue-500',
|
|
|
|
'fs-1': 'text-5xl',
|
|
'fs-2': 'text-4xl',
|
|
'fs-3': 'text-3xl',
|
|
'fs-4': 'text-2xl',
|
|
'fs-5': 'text-xl',
|
|
'fs-6': 'text-base',
|
|
'small': 'text-sm',
|
|
|
|
// Background & Colors
|
|
'bg-primary': 'bg-blue-600',
|
|
'bg-secondary': 'bg-gray-500',
|
|
'bg-success': 'bg-green-500',
|
|
'bg-danger': 'bg-red-500',
|
|
'bg-warning': 'bg-yellow-500',
|
|
'bg-info': 'bg-blue-400',
|
|
'bg-light': 'bg-gray-100',
|
|
'bg-dark': 'bg-gray-800',
|
|
'bg-white': 'bg-white',
|
|
'bg-transparent': 'bg-transparent',
|
|
|
|
// Border
|
|
'border': 'border',
|
|
'border-0': 'border-0',
|
|
'border-top': 'border-t',
|
|
'border-end': 'border-e',
|
|
'border-bottom': 'border-b',
|
|
'border-start': 'border-s',
|
|
|
|
'rounded': 'rounded',
|
|
'rounded-0': 'rounded-none',
|
|
'rounded-1': 'rounded-sm',
|
|
'rounded-2': 'rounded',
|
|
'rounded-3': 'rounded-lg',
|
|
'rounded-circle': 'rounded-full',
|
|
|
|
// Sizing
|
|
'w-25': 'w-1/4',
|
|
'w-50': 'w-1/2',
|
|
'w-75': 'w-3/4',
|
|
'w-100': 'w-full',
|
|
'w-auto': 'w-auto',
|
|
|
|
'h-25': 'h-1/4',
|
|
'h-50': 'h-1/2',
|
|
'h-75': 'h-3/4',
|
|
'h-100': 'h-full',
|
|
'h-auto': 'h-auto',
|
|
|
|
// Position
|
|
'position-static': 'static',
|
|
'position-relative': 'relative',
|
|
'position-absolute': 'absolute',
|
|
'position-fixed': 'fixed',
|
|
'position-sticky': 'sticky',
|
|
|
|
// Overflow
|
|
'overflow-auto': 'overflow-auto',
|
|
'overflow-hidden': 'overflow-hidden',
|
|
|
|
// Visibility
|
|
'visible': 'visible',
|
|
'invisible': 'invisible',
|
|
|
|
// Screen readers
|
|
'visually-hidden': 'sr-only',
|
|
'visually-hidden-focusable': 'sr-only focus:not-sr-only',
|
|
};
|
|
|
|
// Component-specific mappings (these need more complex handling)
|
|
const componentMappings = {
|
|
// Table classes - use px360.css hh-table instead
|
|
'table': 'hh-table',
|
|
'table-hover': '', // hh-table has hover built-in
|
|
'table-striped': '', // would need separate class
|
|
'table-bordered': 'border-collapse border',
|
|
'table-sm': 'text-sm',
|
|
'table-responsive': 'overflow-x-auto',
|
|
|
|
// Card classes - use px360.css hh-card instead
|
|
'card': 'hh-card',
|
|
'card-body': 'hh-card-body',
|
|
'card-header': 'hh-card-header',
|
|
'card-footer': 'hh-card-footer',
|
|
'card-title': 'text-lg font-semibold',
|
|
'card-text': 'text-gray-600',
|
|
|
|
// Button classes - use px360.css hh-btn-* instead
|
|
'btn': 'hh-btn',
|
|
'btn-primary': 'hh-btn hh-btn-primary',
|
|
'btn-secondary': 'hh-btn hh-btn-secondary',
|
|
'btn-success': 'hh-btn hh-btn-success',
|
|
'btn-danger': 'hh-btn hh-btn-danger',
|
|
'btn-warning': 'hh-btn hh-btn-primary', // fallback
|
|
'btn-info': 'hh-btn hh-btn-primary', // fallback
|
|
'btn-light': 'hh-btn hh-btn-secondary',
|
|
'btn-dark': 'hh-btn hh-btn-primary',
|
|
'btn-link': 'hh-btn hh-btn-ghost',
|
|
'btn-sm': 'hh-btn-sm',
|
|
'btn-lg': 'hh-btn-lg',
|
|
'btn-block': 'hh-btn-block',
|
|
|
|
// Badge classes - use px360.css hh-badge-* instead
|
|
'badge': 'hh-badge',
|
|
'rounded-pill': 'rounded-full',
|
|
|
|
// Alert classes - use px360.css hh-alert-* instead
|
|
'alert': 'hh-alert',
|
|
'alert-success': 'hh-alert hh-alert-success',
|
|
'alert-danger': 'hh-alert hh-alert-danger',
|
|
'alert-warning': 'hh-alert hh-alert-warning',
|
|
'alert-info': 'hh-alert hh-alert-info',
|
|
'alert-dismissible': '', // would need JS handling
|
|
|
|
// Form classes - use px360.css hh-form-* instead
|
|
'form-control': 'hh-form-input',
|
|
'form-select': 'hh-form-select',
|
|
'form-label': 'hh-form-label',
|
|
'form-text': 'text-sm text-gray-500 mt-1',
|
|
'form-check': 'flex items-center gap-2',
|
|
'form-check-input': 'w-4 h-4',
|
|
'form-check-label': 'text-sm',
|
|
|
|
// Pagination classes - use px360.css hh-pagination instead
|
|
'pagination': 'hh-pagination',
|
|
'page-item': '', // handled by hh-pagination-btn
|
|
'page-link': 'hh-pagination-btn',
|
|
'active': 'active', // combined with pagination class
|
|
'disabled': 'opacity-50 cursor-not-allowed',
|
|
|
|
// List group
|
|
'list-group': 'divide-y divide-gray-200 border rounded-xl',
|
|
'list-group-item': 'p-4',
|
|
'list-group-item-action': 'hover:bg-gray-50 cursor-pointer',
|
|
|
|
// Breadcrumb classes - use px360.css hh-breadcrumb instead
|
|
'breadcrumb': 'hh-breadcrumb',
|
|
'breadcrumb-item': 'hh-breadcrumb-item',
|
|
'active': 'active',
|
|
|
|
// Dropdown - preserve original classes alongside new ones
|
|
'dropdown': 'hh-dropdown',
|
|
'dropdown-menu': 'hh-dropdown-menu dropdown-menu',
|
|
'dropdown-item': 'hh-dropdown-item dropdown-item',
|
|
'dropdown-toggle': 'dropdown-toggle',
|
|
'dropdown-divider': 'hh-dropdown-divider',
|
|
|
|
// Modal
|
|
'modal': 'hh-modal-overlay',
|
|
'modal-dialog': '', // part of overlay
|
|
'modal-content': 'hh-modal',
|
|
'modal-header': 'hh-modal-header',
|
|
'modal-body': 'hh-modal-body',
|
|
'modal-footer': 'hh-modal-footer',
|
|
'modal-title': 'hh-modal-title',
|
|
'fade': '', // handled by CSS
|
|
'show': 'active',
|
|
|
|
// Navbar
|
|
'navbar': 'flex items-center justify-between py-4',
|
|
'navbar-brand': 'text-xl font-bold',
|
|
'navbar-nav': 'flex items-center gap-4',
|
|
'nav-item': '',
|
|
'nav-link': 'text-gray-600 hover:text-gray-900',
|
|
|
|
// Tabs
|
|
'nav-tabs': 'hh-tabs',
|
|
'nav-link': 'hh-tab',
|
|
'active': 'active',
|
|
|
|
// Spinner
|
|
'spinner-border': 'hh-loading',
|
|
'spinner-border-sm': 'w-4 h-4',
|
|
};
|
|
|
|
// Merge all mappings
|
|
const allMappings = { ...bootstrapToTailwind, ...componentMappings };
|
|
|
|
// Function to convert Bootstrap classes to Tailwind
|
|
function convertBootstrapClasses(element) {
|
|
if (!element.classList) return;
|
|
|
|
const classes = Array.from(element.classList);
|
|
const newClasses = [];
|
|
let hasBootstrap = false;
|
|
|
|
classes.forEach(cls => {
|
|
if (allMappings[cls]) {
|
|
hasBootstrap = true;
|
|
if (allMappings[cls]) {
|
|
newClasses.push(...allMappings[cls].split(' ').filter(c => c));
|
|
}
|
|
} else {
|
|
newClasses.push(cls);
|
|
}
|
|
});
|
|
|
|
if (hasBootstrap) {
|
|
element.className = newClasses.join(' ');
|
|
}
|
|
|
|
// Recursively process children
|
|
Array.from(element.children).forEach(child => {
|
|
convertBootstrapClasses(child);
|
|
});
|
|
}
|
|
|
|
// Run conversion after DOM is ready
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
convertBootstrapClasses(document.body);
|
|
});
|
|
} else {
|
|
convertBootstrapClasses(document.body);
|
|
}
|
|
|
|
console.log('[Bootstrap→Tailwind] Migration helper loaded. Bootstrap classes converted to Tailwind/px360.css classes.');
|
|
})();
|