mirror of
https://github.com/tabler/tabler.git
synced 2026-07-15 01:51:43 +04:00
Merge branch 'dev' of https://github.com/tabler/tabler into fix-1927
This commit is contained in:
+9
-5
@@ -1,6 +1,10 @@
|
||||
>= 1%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
>= 0.5%
|
||||
last 2 major versions
|
||||
not dead
|
||||
safari >= 15.4
|
||||
iOS >= 15.4
|
||||
Chrome >= 120
|
||||
Firefox >= 121
|
||||
iOS >= 15.6
|
||||
Safari >= 15.6
|
||||
not Explorer <= 11
|
||||
Samsung >= 23
|
||||
not kaios <= 2.5
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { sync } from 'glob';
|
||||
import * as prettier from "prettier";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const docs = sync(join(__dirname, '..', 'docs', '**', '*.md'))
|
||||
|
||||
async function formatHTML(htmlString) {
|
||||
try {
|
||||
const formattedHtml = await prettier.format(htmlString, {
|
||||
parser: "html",
|
||||
printWidth: 100,
|
||||
});
|
||||
return formattedHtml;
|
||||
} catch (error) {
|
||||
console.error("Error formatting HTML:", error);
|
||||
return htmlString; // Return original in case of an error
|
||||
}
|
||||
}
|
||||
|
||||
async function replaceAsync(str, regex, asyncFn) {
|
||||
const matches = [...str.matchAll(regex)];
|
||||
|
||||
const replacements = await Promise.all(
|
||||
matches.map(async (match) => asyncFn(...match))
|
||||
);
|
||||
|
||||
let result = str;
|
||||
matches.forEach((match, i) => {
|
||||
result = result.replace(match[0], replacements[i]);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const file of docs) {
|
||||
const oldContent = readFileSync(file, 'utf8')
|
||||
|
||||
// get codeblocks from markdown
|
||||
const content = await replaceAsync(oldContent, /(```([a-z0-9]+).*?\n)(.*?)(```)/gs, async (m, m1, m2, m3, m4) => {
|
||||
if (m2 === 'html') {
|
||||
m3 = await formatHTML(m3);
|
||||
|
||||
// remove empty lines
|
||||
m3 = m3.replace(/^\s*[\r\n]/gm, '');
|
||||
|
||||
return m1 + m3.trim() + "\n" + m4;
|
||||
}
|
||||
return m.trim();
|
||||
})
|
||||
|
||||
if (content !== oldContent) {
|
||||
writeFileSync(file, content, 'utf8')
|
||||
console.log(`Reformatted ${file}`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { readFileSync, writeFileSync } from 'node:fs'
|
||||
import { join, dirname } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { sync } from 'glob'
|
||||
import * as prettier from 'prettier'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const docs: string[] = sync(join(__dirname, '..', 'docs', '**', '*.md'))
|
||||
|
||||
async function formatHTML(htmlString: string): Promise<string> {
|
||||
try {
|
||||
const formattedHtml = await prettier.format(htmlString, {
|
||||
parser: 'html',
|
||||
printWidth: 100,
|
||||
})
|
||||
return formattedHtml
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
console.error('Error formatting HTML:', errorMessage)
|
||||
return htmlString // Return original in case of an error
|
||||
}
|
||||
}
|
||||
|
||||
async function replaceAsync(
|
||||
str: string,
|
||||
regex: RegExp,
|
||||
asyncFn: (...args: string[]) => Promise<string>
|
||||
): Promise<string> {
|
||||
const matches = [...str.matchAll(regex)]
|
||||
|
||||
const replacements = await Promise.all(
|
||||
matches.map(async (match: RegExpMatchArray) => asyncFn(...match))
|
||||
)
|
||||
|
||||
let result = str
|
||||
matches.forEach((match: RegExpMatchArray, i: number) => {
|
||||
result = result.replace(match[0], replacements[i])
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
async function processFiles(): Promise<void> {
|
||||
for (const file of docs) {
|
||||
const oldContent = readFileSync(file, 'utf8')
|
||||
|
||||
// get codeblocks from markdown
|
||||
const content = await replaceAsync(
|
||||
oldContent,
|
||||
/(```([a-z0-9]+).*?\n)(.*?)(```)/gs,
|
||||
async (m: string, m1: string, m2: string, m3: string, m4: string) => {
|
||||
if (m2 === 'html') {
|
||||
let formattedHtml = await formatHTML(m3)
|
||||
|
||||
// remove empty lines
|
||||
formattedHtml = formattedHtml.replace(/^\s*[\r\n]/gm, '')
|
||||
|
||||
return m1 + formattedHtml.trim() + '\n' + m4
|
||||
}
|
||||
return m.trim()
|
||||
}
|
||||
)
|
||||
|
||||
if (content !== oldContent) {
|
||||
writeFileSync(file, content, 'utf8')
|
||||
console.log(`Reformatted ${file}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processFiles().catch((error) => {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
console.error('Error processing files:', errorMessage)
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { defineConfig, type UserConfig } from 'vite'
|
||||
|
||||
interface CreateViteConfigOptions {
|
||||
entry: string
|
||||
name?: string
|
||||
fileName: string | ((format: string) => string)
|
||||
formats: ('es' | 'umd' | 'iife' | 'cjs')[]
|
||||
outDir: string
|
||||
banner?: string
|
||||
minify?: boolean | 'esbuild'
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Vite configuration for building libraries
|
||||
*/
|
||||
export function createViteConfig({
|
||||
entry,
|
||||
name,
|
||||
fileName,
|
||||
formats,
|
||||
outDir,
|
||||
banner,
|
||||
minify = false
|
||||
}: CreateViteConfigOptions): UserConfig {
|
||||
const rollupOutput: {
|
||||
generatedCode: {
|
||||
constBindings: boolean
|
||||
}
|
||||
banner?: string
|
||||
} = {
|
||||
generatedCode: {
|
||||
constBindings: true
|
||||
}
|
||||
}
|
||||
|
||||
// Add banner if provided
|
||||
if (banner) {
|
||||
rollupOutput.banner = banner
|
||||
}
|
||||
|
||||
const config: UserConfig = {
|
||||
build: {
|
||||
lib: {
|
||||
entry: path.resolve(entry),
|
||||
name: name,
|
||||
fileName: typeof fileName === 'function' ? fileName : () => fileName,
|
||||
formats: formats
|
||||
},
|
||||
outDir: path.resolve(outDir),
|
||||
emptyOutDir: false,
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
output: rollupOutput
|
||||
},
|
||||
target: 'es2015',
|
||||
minify: minify
|
||||
},
|
||||
define: {
|
||||
'process.env.NODE_ENV': '"production"'
|
||||
},
|
||||
esbuild: {
|
||||
target: 'es2015',
|
||||
tsconfigRaw: {
|
||||
compilerOptions: {
|
||||
module: 'ES2020',
|
||||
target: 'ES2015'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defineConfig(config)
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import AdmZip from 'adm-zip';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { readFileSync } from 'fs';
|
||||
|
||||
// Get __dirname in ESM
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const pkg = JSON.parse(
|
||||
readFileSync(path.join(__dirname, '../core', 'package.json'), 'utf8')
|
||||
)
|
||||
|
||||
// Create zip instance and add folder
|
||||
const zip = new AdmZip();
|
||||
zip.addLocalFolder(path.join(__dirname, '../preview/dist'), 'dashboard');
|
||||
|
||||
zip.addLocalFile(path.join(__dirname, '../preview/static', 'og.png'), '.', 'preview.png');
|
||||
|
||||
zip.addFile("documentation.url", Buffer.from("[InternetShortcut]\nURL = https://tabler.io/docs"));
|
||||
|
||||
|
||||
// Folder to zip and output path
|
||||
const outputZipPath = path.join(__dirname, '../packages-zip', `tabler-${pkg.version}.zip`);
|
||||
|
||||
// Write the zip file
|
||||
zip.writeZip(outputZipPath);
|
||||
|
||||
console.log(`Zipped folder to ${outputZipPath}`);
|
||||
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import AdmZip from 'adm-zip'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { readFileSync } from 'node:fs'
|
||||
|
||||
// Get __dirname in ESM
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
interface PackageJson {
|
||||
version: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const pkg: PackageJson = JSON.parse(
|
||||
readFileSync(path.join(__dirname, '../core', 'package.json'), 'utf8')
|
||||
)
|
||||
|
||||
// Create zip instance and add folder
|
||||
const zip = new AdmZip()
|
||||
zip.addLocalFolder(path.join(__dirname, '../preview/dist'), 'dashboard')
|
||||
|
||||
zip.addLocalFile(
|
||||
path.join(__dirname, '../preview/static', 'og.png'),
|
||||
'.',
|
||||
'preview.png'
|
||||
)
|
||||
|
||||
zip.addFile(
|
||||
'documentation.url',
|
||||
Buffer.from('[InternetShortcut]\nURL = https://tabler.io/docs')
|
||||
)
|
||||
|
||||
// Folder to zip and output path
|
||||
const outputZipPath = path.join(
|
||||
__dirname,
|
||||
'../packages-zip',
|
||||
`tabler-${pkg.version}.zip`
|
||||
)
|
||||
|
||||
// Write the zip file
|
||||
zip.writeZip(outputZipPath)
|
||||
|
||||
console.log(`Zipped folder to ${outputZipPath}`)
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Pay page with dedicated layout, navigation link, and card/PayPal payment form.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
"@tabler/docs": patch
|
||||
---
|
||||
|
||||
Added background pattern utilities and documentation, including updated preview demos.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Refactored Bootstrap exports to use single source of truth in `bootstrap.js` and removed duplicate exports from `tabler.js` for better maintainability.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed `.btn-icon` to be square by aligning `min-width` calculation with base `.btn` formula.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
---
|
||||
|
||||
Added `.btn-ghost` button variant with transparent background and hover effects.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
---
|
||||
|
||||
Added `.card-gradient` component with gradient variants, direction modifiers, and animated backgrounds.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added new `card-gradients.html` page showcasing various gradient card styles and components.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Change Password modal with current password, new password with strength indicator, confirm password validation, and show/hide password toggles.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added color palette to signing component.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Confirm Delete modal with warning icon, confirmation checkbox, and JavaScript validation to enable delete button only when confirmed.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added new Crypto Dashboard page with cryptocurrency portfolio overview, market data, and order history.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Added crypto markets and orders data files (`crypto-markets.json`, `crypto-orders.json`) for cryptocurrency dashboard functionality.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed icon alignment for `.btn-sm` and `.btn-xl` sizes.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/docs": patch
|
||||
---
|
||||
|
||||
Updated documentation to explain font sizing and system color CSS variables (`--tblr-primary-rgb`, `--tblr-secondary`, `--tblr-tertiary`, `--tblr-link-color`, `--tblr-gray-*`).
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/docs": patch
|
||||
---
|
||||
|
||||
Updated UI component documentation to use singular file names and frontmatter fields (`title`, `summary`, `description`), and added redirects from legacy plural routes.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Edit Profile modal with avatar upload, personal information fields, social links, and date of birth.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Update Tabler Icons to v3.35.0
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated `$border-color-translucent-dark` from `rgba(72, 110, 149, 0.14)` to `rgba(128, 150, 172, 0.2)` to improve visibility of form checkboxes and other form elements in dark mode.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed gray theme custom properties output using SCSS interpolation and updated default `$body-color` to `$gray-500`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed `.input-icon-addon` z-index issue with form validation feedback and added default height.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed status color classes to use CSS variables instead of hardcoded values and include social colors (bitbucket, facebook, etc.) in status class generation.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed white space on left side when scrollbar is present by replacing `margin-inline-start: calc(100vw - 100%)` with `scrollbar-gutter: stable` on `html` element, with `overflow-y: scroll` fallback for unsupported browsers.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated flags and avatars styling for better visual consistency.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed mixed declarations in SCSS.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Update SCSS to use logical properties
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Updated preview templates to replace deprecated `font-weight-*` classes with Bootstrap-compatible `fw-*` utility classes.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/docs": patch
|
||||
---
|
||||
|
||||
Added Geist font family integration.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Implement `border-radius` mixin across various SCSS files
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated `stroke-width` for `.icon-sm` from `1` to `1.5` for better visibility.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added language selector dropdown to navbar with flag indicators for multilingual support.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
Use `.nvmrc` for Node version in CI workflows
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Added `bg-blur` utility and increased `container-tight` width for layout flexibility.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Updated icons to v3.34.1 with 75 new icons.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Added `border-top-left-radius` and `border-top-right-radius` to first and last child elements in `.card-table` for proper corner rounding.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Added `media-print` mixin and print styles to hide interactive components during printing.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Refactored page-menu structure for dashboards and updated navigation menu organization.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Migrated `rgba()` functions to modern CSS color functions (`color-mix()` and `color-transparent()`) for better browser support and cleaner code. Replaced `rgba(var(--#{$prefix}*-rgb), ...)` with `color-mix(in srgb, var(--#{$prefix}*) ..., transparent)`, static percentage `color-mix()` with `color-transparent()`, and `rgba($variable, ...)` with `color-transparent($variable, ...)`.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
"@tabler/docs": minor
|
||||
---
|
||||
|
||||
Migrated build system from Rollup to Vite across all packages. Replaced `rollup.config.mjs` with `vite.config.mjs` and updated build scripts to use `vite build` instead of `rollup`. Build outputs remain identical (UMD and ESM formats) with no breaking changes for end users.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Updated activity messages.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Refactored navbar-side component by consolidating separate include files (apps, language, notifications, theme, user) into a single `navbar-side.html` file for better maintainability.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added New Task modal with fields for task name, description, assigned user, priority, due date, and category tags.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added new onboarding page with progress indicator and navigation layout.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Fixed double bottom border in tables.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Progress Background component with text labels and value display.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
---
|
||||
|
||||
Added `.progress-lg` and `.progress-xl` size variants for the progress component.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Progress Steps component for step-by-step navigation indicators.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Added smooth transitions for progress bar `width` and `background-color` changes.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
"@tabler/preview": patch
|
||||
"@tabler/docs": patch
|
||||
---
|
||||
|
||||
Added `.prose` alias for markdown content and updated preview/docs references and redirects.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Removed redundant nullish coalescing operator from `html` option in popover and tooltip initialization.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Added Driver.js library integration and Tour demo page for interactive product tours and onboarding guides.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated skip-link to use `visually-hidden` for improved accessibility.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added new Task List page with tables showing tasks organized by status (Upcoming, In Progress, Completed) and modal dialog for adding new tasks.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated deprecated global Sass functions to module equivalents (`map.merge`, `string.slice`, `math.percentage`, etc.).
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated Bootstrap to v5.3.8.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Updated trending component to use `arrow-up`/`arrow-down` instead of `trending-up`/`trending-down`.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/docs": patch
|
||||
---
|
||||
|
||||
Fixed Docs search display in dark mode.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Fixed responsive layouts on the Form Elements page.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Updated `@tabler/icons` to v3.36.1.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated shadow tokens (`--tblr-shadow-*`) to use the new `xs`–`2xl` and `overlay` values.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Upgraded `apexcharts` from `3.54.1` to `5.3.6` and added CSS variables (`--chart-{id}-color-{index}`) for dynamic chart colors to fix compatibility with the new version.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Added comprehensive All Elements page with all UI components and Bootstrap elements
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
description: Git Branch Naming Rules
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
## Branch naming
|
||||
|
||||
- Use lowercase branch names.
|
||||
- Use a type prefix and a short description in kebab-case.
|
||||
- Format: `<type>/<short-description>` or `<type>/<issue-id>-<short-description>`
|
||||
- Use `gh-123` as the issue id format (avoid `#` in branch names).
|
||||
|
||||
### Allowed types
|
||||
|
||||
- `feat` - new features
|
||||
- `fix` - bug fixes
|
||||
- `docs` - documentation changes
|
||||
- `chore` - maintenance / tooling
|
||||
- `refactor` - code refactoring (no behavior change)
|
||||
- `test` - tests only
|
||||
- `build` - build system changes
|
||||
- `ci` - CI changes
|
||||
- `perf` - performance improvements
|
||||
- `style` - formatting / lint-only changes
|
||||
- `revert` - reverting prior changes
|
||||
|
||||
### Examples
|
||||
|
||||
- `feat/gh-123-add-stepper-component`
|
||||
- `fix/markdown-table-overflow`
|
||||
- `docs/gh-45-update-contributing`
|
||||
- `chore/update-pnpm-lock`
|
||||
|
||||
### Notes
|
||||
|
||||
- Branch off `dev` by default (unless maintainers request otherwise).
|
||||
- Avoid spaces, uppercase letters, and special characters other than `/` and `-`.
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
description: Cursor Rules for Tabler Changesets
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
|
||||
### File Structure
|
||||
|
||||
- Each change must be in a separate changeset file in `.changeset/` directory
|
||||
- Use descriptive kebab-case filenames (e.g., `progress-sizes.md`, `button-ghost.md`)
|
||||
- Follow the standard changeset format with frontmatter and description
|
||||
|
||||
### Change Description Format
|
||||
|
||||
- **One sentence per changeset** - keep descriptions concise and focused
|
||||
- Use **backticks for code elements**: classes (`.btn-ghost`), properties (`stroke-width`), values (`1.5`), icons (`arrow-up`)
|
||||
- Start with action verbs: "Added", "Updated", "Fixed", "Removed"
|
||||
- Be specific about what was changed
|
||||
|
||||
### Version Bump Guidelines
|
||||
|
||||
- **Major**: Breaking changes, complete rewrites
|
||||
- **Minor**: New features, new components, new pages, significant enhancements
|
||||
- **Patch**: Bug fixes, small improvements, style updates, accessibility fixes
|
||||
|
||||
### Package Selection
|
||||
|
||||
- `"@tabler/core"`: Changes to SCSS, core functionality, CSS classes
|
||||
- `"@tabler/preview"`: New pages, demo updates, preview-specific changes
|
||||
- `"@tabler/docs"`: Documentation updates
|
||||
- Use multiple packages when change affects multiple areas
|
||||
|
||||
### Examples
|
||||
|
||||
#### New Feature (Minor)
|
||||
|
||||
```md
|
||||
---
|
||||
"@tabler/core": minor
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Progress Steps component for step-by-step navigation indicators.
|
||||
```
|
||||
|
||||
#### Bug Fix (Patch)
|
||||
|
||||
```md
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Updated `stroke-width` for `.icon-sm` from `1` to `1.5` for better visibility.
|
||||
```
|
||||
|
||||
#### New Page (Minor)
|
||||
|
||||
```md
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added new onboarding page with progress indicator and navigation layout.
|
||||
```
|
||||
|
||||
#### Style Enhancement (Patch)
|
||||
|
||||
```md
|
||||
---
|
||||
"@tabler/core": patch
|
||||
---
|
||||
|
||||
Added smooth transitions for progress bar width and background color changes.
|
||||
```
|
||||
|
||||
### Code Formatting Rules
|
||||
|
||||
- Class names: `.btn-ghost`, `.progress-lg`, `.icon-sm`
|
||||
- CSS properties: `stroke-width`, `background-color`, `width`
|
||||
- Values: `1.5`, `transparent`, `100%`
|
||||
- Icon names: `arrow-up`, `arrow-down`, `trending-up`
|
||||
- HTML attributes: `aria-label`, `role`, `data-*`
|
||||
- JavaScript functions: `addEventListener()`, `querySelector()`
|
||||
|
||||
### Common Patterns
|
||||
|
||||
- **Component additions**: "Added [ComponentName] component for [purpose]"
|
||||
- **Size variants**: "Added [size] size variant for [component] (`.class-size`)"
|
||||
- **Style fixes**: "Fixed [issue] in [component/element]"
|
||||
- **Icon updates**: "Updated [component] to use `new-icon` instead of `old-icon`"
|
||||
- **Accessibility**: "Improved accessibility by [specific change]"
|
||||
|
||||
### Commit Message Format
|
||||
|
||||
Use English for commit messages following conventional commit format when possible:
|
||||
|
||||
- `feat: add progress steps component`
|
||||
- `fix: update icon stroke width for better visibility`
|
||||
- `style: add smooth transitions to progress bars`
|
||||
@@ -0,0 +1,341 @@
|
||||
---
|
||||
description: Markdown documentation writing standards for docs pages
|
||||
globs: docs/content/**/*.md
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Markdown Documentation Rules
|
||||
|
||||
## Scope
|
||||
|
||||
- Apply these rules when creating or editing Markdown documentation files.
|
||||
- Write technical documentation in English.
|
||||
- Use simple English: short sentences, common words, and direct instructions.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
- Use static YAML frontmatter only (no Liquid in frontmatter).
|
||||
- Include `title`, `summary`, and `description` for docs pages in `docs/content/**`.
|
||||
- For component docs, use singular naming in frontmatter and filename:
|
||||
`title: Card`, `summary` and `description` written with a singular component form, and filename `card.md` (not `cards.md`).
|
||||
- Add optional frontmatter `related` entries (instead of a `Related` content section).
|
||||
- In `related`, always use absolute docs paths in `url` (without `./`), for example:
|
||||
`ui/components/breadcrumb`.
|
||||
- Use this structure:
|
||||
```yaml
|
||||
related:
|
||||
- name: Pagination
|
||||
url: ui/components/pagination
|
||||
- name: Dropdowns
|
||||
url: ui/components/dropdowns
|
||||
```
|
||||
- If documentation describes a component defined in SCSS, add `source-scss` with a relative path
|
||||
inside `core/scss/` (for example: `source-scss: ui/buttons.scss`).
|
||||
- If a component extends a Bootstrap component, add `bootstrap-url: components/<name>` in frontmatter
|
||||
(for example: `bootstrap-url: components/buttons`).
|
||||
- Add versioning notes for API and class lifecycle changes using fields like
|
||||
`added-in: 1.4.0` and `deprecated-in: 1.2.0`.
|
||||
- If documentation introduces a new component, add a changeset with a `minor` version bump.
|
||||
- Components should include an optional `classnames` section in frontmatter.
|
||||
- Add only groups that exist for a given component. Do not include empty or irrelevant groups.
|
||||
- `classnames` entries must match classes that exist in the relevant SCSS source files.
|
||||
- Do not document classes that are not defined in SCSS, deprecated, or internal-only.
|
||||
- You can add `status` to class entries: `stable`, `deprecated`, or `experimental`.
|
||||
- If `status` is not provided, treat the class as `stable` by default.
|
||||
- Allowed `classnames` groups and meanings:
|
||||
- `component`: Main component class.
|
||||
- `modifier`: Modifies behavior of component or part.
|
||||
- `part`: Part of a component.
|
||||
- `style`: Visual style of component or part.
|
||||
- `behavior`: Behavioural style of component or part.
|
||||
- `color`: Color of component or part.
|
||||
- `size`: Size of component or part.
|
||||
- `placement`: Placement of component or part.
|
||||
- `direction`: Direction of component or part.
|
||||
- `variable`: CSS variable.
|
||||
- `variant`: Use like `variant:utility` to apply a utility conditionally.
|
||||
- Use this structure:
|
||||
|
||||
```yaml
|
||||
classnames:
|
||||
component:
|
||||
- class: btn
|
||||
desc: Main button class
|
||||
part:
|
||||
- class: btn-group
|
||||
desc: Group container for buttons
|
||||
modifier:
|
||||
- class: btn-block
|
||||
desc: Full width button
|
||||
status: stable
|
||||
style:
|
||||
- class: btn-outline
|
||||
desc: Outline style button
|
||||
behavior:
|
||||
- class: btn-disabled
|
||||
desc: Disabled visual state
|
||||
status: deprecated
|
||||
color:
|
||||
- class: btn-primary
|
||||
desc: Primary color button
|
||||
size:
|
||||
- class: btn-sm
|
||||
desc: Small size button
|
||||
placement:
|
||||
- class: dropdown-menu-end
|
||||
desc: Align dropdown menu to end
|
||||
direction:
|
||||
- class: carousel-vertical
|
||||
desc: Vertical carousel direction
|
||||
variable:
|
||||
- class: --tblr-btn-padding-x
|
||||
desc: Horizontal button padding variable
|
||||
variant:
|
||||
- class: hover:bg-primary
|
||||
desc: Apply background color on hover
|
||||
status: experimental
|
||||
```
|
||||
|
||||
|
||||
## Structure and readability
|
||||
|
||||
- Start with a short purpose statement, then explain usage and variants.
|
||||
- Keep heading hierarchy consistent (`##` then `###`), without skipping levels.
|
||||
- Keep core documentation sections as `H2` headings in this order:
|
||||
`Overview`, `Installation` (optional), `Variants` (for components that support variants or `Usage` for components that don't support variants), `Accessibility`,
|
||||
`Examples` (optional), `SCSS variables` (optional), `Migration notes` (optional).
|
||||
- In `Overview`, add one visual component preview without code (`hide-code=true`).
|
||||
- Use descriptive section headings that are stable for linking.
|
||||
- Vary intro phrasing across pages; avoid repeating the same sentence pattern.
|
||||
|
||||
## Markdown style
|
||||
|
||||
- Follow `.markdownlint.json` conventions (ATX headings, `-` lists, fenced code blocks).
|
||||
- Keep line length within 120 characters where practical.
|
||||
- Keep examples aligned with current API/classes and practical usage.
|
||||
- Use active voice and direct verbs (`Use`, `Add`, `Set`).
|
||||
- Keep one main idea per sentence.
|
||||
- Do not add meta authoring notes in docs text (for example: "this snippet is copy-paste ready").
|
||||
|
||||
## Terminology and section naming
|
||||
|
||||
- Use consistent terminology across pages; one term per concept.
|
||||
- Use clear and consistent section names across component docs.
|
||||
- Prefer shared section labels such as `Overview`, `Accessibility`, `Examples` (optional), and `Migration notes`.
|
||||
- You can add an `SCSS variables` section for components with documented SCSS tokens/variables.
|
||||
|
||||
### Recommended section order
|
||||
|
||||
```md
|
||||
## Overview
|
||||
## Installation (optional)
|
||||
## Variants or Usage/API
|
||||
## Accessibility
|
||||
## Examples (optional)
|
||||
## SCSS variables (optional)
|
||||
## Migration notes (optional)
|
||||
```
|
||||
|
||||
## Project-specific docs patterns
|
||||
|
||||
- In docs examples, prefer `{% capture html %}...{% endcapture %}` and, when needed, add `{% capture code %}...{% endcapture %}` for code snippets.
|
||||
- Use `{% include "docs/example.html" ... %}` to render visual component previews in any relevant section
|
||||
(`Overview`, `Variants`, `Usage/API`, or `Examples`).
|
||||
- Before each `{% include "docs/example.html" ... %}`, add 1-2 short sentences that describe
|
||||
the component state or behavior shown in the preview.
|
||||
- For examples with explicit source snippets, use `{% include "docs/example.html" html=html code=code %}`.
|
||||
- For visual-only examples, use `{% include "docs/example.html" html=html hide-code=true %}`.
|
||||
- If an example shows multiple elements as a list, use `separated` to display items with clean spacing:
|
||||
`{% include "docs/example.html" html=html separated %}`.
|
||||
- Add `centered` when the example should be centered (for example, a list of buttons):
|
||||
`{% include "docs/example.html" html=html separated centered %}`.
|
||||
- If elements are wide, you can stack them vertically with `vertical` (for example):
|
||||
`{% include "docs/example.html" html=html centered vertical %}`.
|
||||
- Use `raw` when you need to render the example without extra preview wrappers
|
||||
(no padding, no centering), for example full page layout previews:
|
||||
`{% include "docs/example.html" html=html raw %}`.
|
||||
- Use `column` to render content in a narrow column (about 25rem), useful for components
|
||||
commonly presented in columns (for example stat cards):
|
||||
`{% include "docs/example.html" html=html column %}`.
|
||||
- For `SCSS variables` sections, use:
|
||||
`{% scss-docs "alert-variables" "ui/_alerts.scss" %}`.
|
||||
- This renders the fragment between `// scss-docs-start alert-variables` and `// scss-docs-end`
|
||||
from the given SCSS file (path relative to `core/scss/`).
|
||||
- If an SCSS file contains a `scss-docs-start` block, it should be included in documentation
|
||||
via a matching `{% scss-docs %}` entry.
|
||||
- Use `hide-code=true` only when source markup is not useful to the reader.
|
||||
- If an example needs a different background, set it with the include attribute `bg="surface-primary"`.
|
||||
- Treat `html` as the visual preview layer and `code` as the clean source layer shown to users.
|
||||
- Keep `code` concise and practical: include only the essential markup needed to explain usage.
|
||||
- Do not duplicate visual wrapper-only structure in `code` when it exists only to style the preview.
|
||||
- Do not promote deprecated patterns; when needed, mention the replacement.
|
||||
- Add accessibility attributes (for example `aria-label`) in interactive examples.
|
||||
|
||||
## Publishing checklist
|
||||
|
||||
- Verify that examples render correctly.
|
||||
- Verify that internal and external links work.
|
||||
- Verify heading hierarchy and section naming consistency.
|
||||
- Verify code snippets are accurate and minimal for the documented use case.
|
||||
- Validate documented classes against SCSS files before publishing.
|
||||
- Ensure every class in `classnames` maps to a real SCSS class or variable.
|
||||
- Ensure every class listed in `classnames` appears at least once in page content or examples.
|
||||
- For interactive components, add a short accessibility mini-check (`aria-label`, keyboard focus, semantic markup).
|
||||
|
||||
## Documentation structure examples
|
||||
|
||||
### Minimal component page structure
|
||||
|
||||
```md
|
||||
---
|
||||
title: Component name
|
||||
summary: Short one-sentence summary of what this component does.
|
||||
description: Practical description of when and why to use this component.
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
One short paragraph explaining purpose and primary use case.
|
||||
|
||||
Show the component in its default state so users can recognize it immediately.
|
||||
Keep this first example focused on appearance and context.
|
||||
|
||||
{% capture html -%}
|
||||
<button class="btn btn-primary">Primary button</button>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html hide-code=true %}
|
||||
|
||||
## Variants
|
||||
|
||||
### Outline
|
||||
|
||||
The outline variant presents a lighter visual emphasis than a filled primary action.
|
||||
Use it for secondary actions in dense interfaces.
|
||||
|
||||
{% capture html -%}
|
||||
<button class="btn">Secondary</button>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html %}
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Use clear labels for interactive controls.
|
||||
- Add `aria-label` for icon-only buttons.
|
||||
|
||||
## Examples (optional, visual usage)
|
||||
|
||||
### Default
|
||||
|
||||
The default variant represents the primary action style.
|
||||
Use it as a baseline before introducing additional variants.
|
||||
|
||||
{% capture html -%}
|
||||
<button class="btn btn-primary">Save</button>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html %}
|
||||
```
|
||||
|
||||
### Visual preview patterns (usable in any section)
|
||||
|
||||
```md
|
||||
## Variants
|
||||
|
||||
### Default
|
||||
|
||||
The default variant represents the primary action style.
|
||||
Use it as a baseline before introducing additional variants.
|
||||
|
||||
{% capture html -%}
|
||||
<button class="btn btn-primary">Primary button</button>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html %}
|
||||
|
||||
### With icon
|
||||
|
||||
This variant combines a leading icon with a text label.
|
||||
Use it for actions that benefit from an additional visual cue.
|
||||
|
||||
{% capture html -%}
|
||||
<button class="btn btn-primary">
|
||||
{% include "ui/icon.html" icon="plus" %}
|
||||
Add item
|
||||
</button>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html %}
|
||||
|
||||
### Custom background
|
||||
|
||||
This variant presents the component on a dark background surface.
|
||||
Use it to verify contrast and visual hierarchy.
|
||||
|
||||
{% capture html -%}
|
||||
<button class="btn btn-light">Light button on dark preview</button>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html bg="dark" %}
|
||||
```
|
||||
|
||||
```md
|
||||
## Usage
|
||||
|
||||
Use this pattern in any section when source markup should be shown together with the visual output.
|
||||
Use `code` for clean implementation markup without preview-only wrappers.
|
||||
|
||||
### Card with footer actions
|
||||
|
||||
This example presents a card layout with footer actions in a realistic container.
|
||||
Show `html` for rendered context and `code` for implementation markup.
|
||||
|
||||
{% capture html -%}
|
||||
<div class="p-4 border rounded bg-light">
|
||||
<div class="card">
|
||||
<div class="card-body">Content</div>
|
||||
<div class="card-footer">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endcapture %}
|
||||
|
||||
{% capture code -%}
|
||||
<div class="card">
|
||||
<div class="card-body">Content</div>
|
||||
<div class="card-footer">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html code=code %}
|
||||
```
|
||||
|
||||
```md
|
||||
## Accessibility
|
||||
|
||||
Use this pattern in any section only for visual comparison cases where raw markup is not useful,
|
||||
for example screenshots, behavior notes, or before/after UI states.
|
||||
|
||||
This pattern highlights visual state communication without extra source details.
|
||||
Use it for quick comparisons such as status, before/after states, or behavior notes.
|
||||
|
||||
{% capture html -%}
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge bg-green"></span>
|
||||
<span>Active status</span>
|
||||
</div>
|
||||
{% endcapture %}
|
||||
{% include "docs/example.html" html=html hide-code=true %}
|
||||
|
||||
### Do
|
||||
|
||||
- Explain what changed and why it matters.
|
||||
- Link to a related practical example if available.
|
||||
|
||||
### Don't
|
||||
|
||||
- Do not replace all practical examples with image-only examples.
|
||||
- Do not omit practical markup examples for core use cases.
|
||||
```
|
||||
|
||||
- Do not move core documentation content (for example API details, states, accessibility rules,
|
||||
migration notes) into `Examples`.
|
||||
- Keep core sections as normal documentation; `Examples` is an optional showcase section,
|
||||
while visual preview blocks can be used across multiple sections.
|
||||
@@ -0,0 +1,171 @@
|
||||
---
|
||||
description: Tabler Project HTML Elements Guidelines
|
||||
globs: ["**/*.html", "**/*.liquid", "**/*.md"]
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
## HTML Elements Guidelines
|
||||
|
||||
### 1. Icons
|
||||
|
||||
When you need to use an icon, always use the Tabler icon include syntax:
|
||||
|
||||
```html
|
||||
{% include "ui/icon.html" icon="ICON_NAME" %}
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
|
||||
- `{% include "ui/icon.html" icon="home" %}`
|
||||
- `{% include "ui/icon.html" icon="building-community" %}`
|
||||
- `{% include "ui/icon.html" icon="map-pin" %}`
|
||||
|
||||
### 2. Page Links
|
||||
|
||||
When linking to other pages, always use the relative page syntax:
|
||||
|
||||
```html
|
||||
href="{{ page | relative }}/url.html"
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
|
||||
- `href="{{ page | relative }}/job-post.html"`
|
||||
- `href="{{ page | relative }}/job-listing.html"`
|
||||
- `href="{{ page | relative }}/marketing/index.html"`
|
||||
|
||||
### 3. Static Generation
|
||||
|
||||
All pages are statically generated to HTML using Eleventy (11ty). Keep this in mind when:
|
||||
|
||||
- Writing frontmatter (must be static YAML, no Liquid templating)
|
||||
- Creating dynamic content (use Liquid templating in the body, not frontmatter)
|
||||
- Linking between pages (use relative paths)
|
||||
|
||||
### 4. Additional Guidelines
|
||||
|
||||
#### Frontmatter Rules
|
||||
|
||||
- Frontmatter must be static YAML
|
||||
- Cannot use Liquid templating in frontmatter
|
||||
- Use static values for title, permalink, etc.
|
||||
|
||||
#### Liquid Templating
|
||||
|
||||
- Use Liquid templating only in the HTML body
|
||||
- Access data using `{{ variable }}` syntax
|
||||
- Use `{% for %}` loops for dynamic content
|
||||
- Use `{% if %}` conditions for conditional rendering
|
||||
|
||||
#### File Structure
|
||||
|
||||
- Pages go in `preview/pages/`
|
||||
- Includes go in `shared/includes/`
|
||||
- Data files go in `shared/data/`
|
||||
- Documentation goes in `docs/content/`
|
||||
|
||||
#### CSS Classes
|
||||
|
||||
- Use Bootstrap 5 classes
|
||||
- Use Tabler's custom CSS classes
|
||||
- Follow the pattern: `--#{$prefix}component-property`
|
||||
|
||||
#### Accessibility
|
||||
|
||||
- Include proper ARIA labels
|
||||
- Use semantic HTML elements
|
||||
- Ensure proper heading hierarchy
|
||||
- Add alt text for images
|
||||
|
||||
### 5. Component Usage
|
||||
|
||||
#### Cards
|
||||
|
||||
- Use `card` class for main containers
|
||||
- Use `card-body` for content areas
|
||||
- Use `card-header` for card headers
|
||||
- Use `card-title` for card title
|
||||
|
||||
#### Buttons
|
||||
|
||||
- Use `btn` class for all buttons
|
||||
- Use `btn-primary` for primary actions
|
||||
- Use `btn` for secondary actions, don't use `btn-outline-secondary`
|
||||
- Use `btn-sm` for smaller buttons
|
||||
- Use `w-100` for full-width buttons
|
||||
|
||||
#### Forms
|
||||
|
||||
- Use `form-control` for input fields
|
||||
- Use `form-label` for labels
|
||||
- Use `form-check` for checkboxes/radio buttons
|
||||
- Use `form-select` for dropdowns
|
||||
|
||||
#### Layout
|
||||
|
||||
- Use Bootstrap grid system (`row`, `col-*`)
|
||||
- Use `container-xl` for main containers
|
||||
- Use `page-wrapper` for page structure
|
||||
- Use `page-body` for main content area
|
||||
|
||||
#### Badges
|
||||
|
||||
- Use `badge` class for badges
|
||||
- Don't use `badge-outline` for badges, use `badge` class instead
|
||||
- Don't use `badge-primary` for badges, use `badge` class instead
|
||||
- Don't change the text color of badges
|
||||
|
||||
#### Markdown
|
||||
|
||||
- Use `markdown` class for markdown content
|
||||
- Apply to containers that render markdown content
|
||||
- Example: `<div class="markdown">...</div>`
|
||||
|
||||
#### Rest of the rules
|
||||
|
||||
- Read the rest of the rules in the `docs/content/ui/` folder
|
||||
|
||||
### 6. Data Integration
|
||||
|
||||
#### Using JSON Data
|
||||
|
||||
```liquid
|
||||
{% for item in items %}
|
||||
<div>{{ item.name }}</div>
|
||||
{% endfor %}
|
||||
```
|
||||
|
||||
#### Conditional Rendering
|
||||
|
||||
```liquid
|
||||
{% if condition %}
|
||||
<div>Content</div>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
#### Including Components
|
||||
|
||||
```liquid
|
||||
{% include "ui/button.html" color="primary" text="Click me" %}
|
||||
```
|
||||
|
||||
### 7. Best Practices
|
||||
|
||||
#### Performance
|
||||
|
||||
- Minimize nested loops
|
||||
- Use `limit` filters when iterating large datasets
|
||||
- Optimize images for web use
|
||||
|
||||
#### Code Organization
|
||||
|
||||
- Keep components modular and reusable
|
||||
- Use consistent naming conventions
|
||||
- Comment complex logic
|
||||
- Group related functionality together
|
||||
|
||||
#### Error Handling
|
||||
|
||||
- Always check if data exists before using it
|
||||
- Provide fallback content for missing data
|
||||
- Use `{% if %}` guards for optional content
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
description: Pull Request Title & Description Rules
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
## Pull request title
|
||||
|
||||
- Write PR titles in **English**.
|
||||
- Start the title with a **capital letter**.
|
||||
- Use **present tense** and keep it concise (ideally <= 72 chars).
|
||||
- Avoid a trailing period.
|
||||
|
||||
### Examples
|
||||
|
||||
- `Improve markdown table overflow handling`
|
||||
- `Clarify contributing branch naming`
|
||||
- `Add onboarding stepper page`
|
||||
|
||||
## Pull request description
|
||||
|
||||
- Write PR descriptions in **English**.
|
||||
- Focus on **why** the change is needed and what user-visible effect it has.
|
||||
- Keep it skimmable: bullets, short paragraphs, clear headings.
|
||||
|
||||
### Recommended template
|
||||
|
||||
```md
|
||||
## Summary
|
||||
- <1–3 bullets describing the change and why>
|
||||
|
||||
## Changes
|
||||
- <key implementation notes, non-obvious decisions>
|
||||
```
|
||||
|
||||
### Notes
|
||||
|
||||
- If you changed SCSS or any package behavior, add a **changeset** describing it (one sentence, with backticks for code elements).
|
||||
- If a PR is WIP, mark it as draft and prefix the title with `WIP:` only while it is not ready for review.
|
||||
@@ -1,67 +0,0 @@
|
||||
name: Argos Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
pull_request:
|
||||
paths:
|
||||
- 'preview/**/*.js'
|
||||
- 'preview/**/*.html'
|
||||
- 'preview/**/*.scss'
|
||||
- 'core/**/*.js'
|
||||
- 'core/**/*.scss'
|
||||
|
||||
env:
|
||||
NODE: 20
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
# if: github.event.pull_request.draft == false
|
||||
if: false
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache turbo build setup
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .turbo
|
||||
key: ${{ runner.os }}-turbo-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-turbo-
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "${{ env.NODE }}"
|
||||
|
||||
- name: Install PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Get installed Playwright version
|
||||
id: playwright-version
|
||||
run: echo "PLAYWRIGHT_VERSION=$(node -e "console.log(require('./package.json').devDependencies['@playwright/test'])")" >> $GITHUB_ENV
|
||||
|
||||
- name: Cache playwright binaries
|
||||
uses: actions/cache@v4
|
||||
id: playwright-cache
|
||||
with:
|
||||
path: |
|
||||
~/.cache/ms-playwright
|
||||
key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}
|
||||
|
||||
- name: Install pnpm dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: pnpm exec playwright install --with-deps
|
||||
if: steps.playwright-cache.outputs.cache-hit != 'true'
|
||||
|
||||
- name: Run Playwright tests
|
||||
run: pnpm run playwright
|
||||
@@ -9,7 +9,6 @@ on:
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 2
|
||||
NODE: 20
|
||||
|
||||
jobs:
|
||||
bundlewatch:
|
||||
@@ -17,24 +16,25 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cache turbo build setup
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .turbo
|
||||
key: ${{ runner.os }}-turbo-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-turbo-
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "${{ env.NODE }}"
|
||||
|
||||
- name: Install PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Set up Bundler
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
pull-requests: write
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
days-before-issue-stale: 360
|
||||
days-before-issue-close: 14
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request: null
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install pnpm dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Lint Markdown
|
||||
run: pnpm run lint
|
||||
@@ -12,9 +12,9 @@ jobs:
|
||||
name: Verify lock file integrity
|
||||
steps:
|
||||
- name: Clone Tabler
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
- name: Prevent lock file change
|
||||
uses: xalvarez/prevent-file-change-action@v2
|
||||
uses: xalvarez/prevent-file-change-action@v3
|
||||
with:
|
||||
githubToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
pattern: Gemfile.lock|pnpm-lock.json|pnpm-lock.yaml
|
||||
|
||||
@@ -21,16 +21,17 @@ jobs:
|
||||
pull-requests: write # to create pull request
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js 18
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm install
|
||||
|
||||
|
||||
@@ -3,9 +3,6 @@ name: Test build
|
||||
on:
|
||||
pull_request: null
|
||||
|
||||
env:
|
||||
NODE: 20
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -14,24 +11,25 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cache turbo build setup
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .turbo
|
||||
key: ${{ runner.os }}-turbo-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-turbo-
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "${{ env.NODE }}"
|
||||
|
||||
- name: Install PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'pnpm'
|
||||
|
||||
- run: node --version
|
||||
|
||||
- name: Install pnpm dependencies
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Type Check
|
||||
|
||||
on:
|
||||
pull_request: null
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
type-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cache turbo build setup
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .turbo
|
||||
key: ${{ runner.os }}-turbo-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-turbo-
|
||||
|
||||
- name: Install PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install pnpm dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Run type-check
|
||||
run: pnpm run type-check
|
||||
|
||||
+6
-1
@@ -36,4 +36,9 @@ package-lock.json
|
||||
demo/
|
||||
dist/
|
||||
packages-zip/
|
||||
.env
|
||||
.env
|
||||
sri.json
|
||||
|
||||
# TypeScript
|
||||
*.tsbuildinfo
|
||||
.tsbuildinfo
|
||||
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"default": true,
|
||||
"MD001": {
|
||||
"level": 2
|
||||
},
|
||||
"MD003": {
|
||||
"style": "atx"
|
||||
},
|
||||
"MD004": {
|
||||
"style": "dash"
|
||||
},
|
||||
"MD007": {
|
||||
"indent": 2
|
||||
},
|
||||
"MD009": {
|
||||
"br_spaces": 2
|
||||
},
|
||||
"MD010": false,
|
||||
"MD012": {
|
||||
"maximum": 2
|
||||
},
|
||||
"MD013": {
|
||||
"line_length": 120,
|
||||
"code_blocks": false,
|
||||
"tables": false,
|
||||
"headings": false,
|
||||
"headings_line_length": 120
|
||||
},
|
||||
"MD022": true,
|
||||
"MD025": {
|
||||
"front_matter_title": ""
|
||||
},
|
||||
"MD026": {
|
||||
"punctuation": ".,;:!"
|
||||
},
|
||||
"MD030": {
|
||||
"ul_single": 1,
|
||||
"ul_multi": 1,
|
||||
"ol_single": 1,
|
||||
"ol_multi": 1
|
||||
},
|
||||
"MD031": true,
|
||||
"MD032": true,
|
||||
"MD033": false,
|
||||
"MD034": false,
|
||||
"MD035": {
|
||||
"style": "---"
|
||||
},
|
||||
"MD036": false,
|
||||
"MD037": true,
|
||||
"MD038": true,
|
||||
"MD039": true,
|
||||
"MD040": true,
|
||||
"MD041": {
|
||||
"front_matter_title": ""
|
||||
},
|
||||
"MD046": {
|
||||
"style": "fenced"
|
||||
},
|
||||
"MD047": true
|
||||
}
|
||||
+12
-2
@@ -4,7 +4,17 @@
|
||||
"printWidth": 320,
|
||||
"proseWrap": "always",
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"singleQuote": true,
|
||||
"quoteProps": "consistent",
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "all"
|
||||
"useTabs": false,
|
||||
"trailingComma": "all",
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.scss",
|
||||
"options": {
|
||||
"parser": "scss"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2025 The Tabler Authors
|
||||
Copyright (c) 2018-2026 The Tabler Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -28,13 +28,13 @@ A premium and open source dashboard template with a responsive and high-quality
|
||||
<p align="center">Browser testing via:</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.lambdatest.com/" target="_blank">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/14dd2a0a-bafe-436e-a6cb-29636278c781">
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/d3dede5a-d702-47c3-bb66-4d887948ed83">
|
||||
<img src="https://github.com/user-attachments/assets/d3dede5a-d702-47c3-bb66-4d887948ed83" alt="labmdatest" width="296">
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://www.testmuai.com/?utm_medium=sponsor&utm_source=tabler" target="_blank">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/user-attachments/assets/f0967860-31ad-4078-850b-40b0abc95582" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://github.com/user-attachments/assets/55ac290a-6729-44aa-bbc3-4c5e909facbf" />
|
||||
<img src="https://github.com/user-attachments/assets/86bcbe29-eb8d-4273-a381-5ce17d4ca92d" alt="TestMu AI" width="296">
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 🔎 Preview
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
import { readFileSync, writeFileSync } from 'node:fs';
|
||||
import { join, dirname, basename } from 'node:path';
|
||||
import { readFileSync, writeFileSync } from 'node:fs'
|
||||
import { join, dirname, basename } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { sync } from 'glob';
|
||||
import banner from '../../shared/banner/index.mjs';
|
||||
import { sync } from 'glob'
|
||||
import banner from '../../shared/banner/index.mjs'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const styles = sync(join(__dirname, '..', 'dist', 'css', '*.css'))
|
||||
const styles: string[] = sync(join(__dirname, '..', 'dist', 'css', '*.css'))
|
||||
|
||||
const plugins = {
|
||||
interface Plugins {
|
||||
[key: string]: string
|
||||
}
|
||||
|
||||
const plugins: Plugins = {
|
||||
'tabler-flags': 'Flags',
|
||||
'tabler-flags.rtl': 'Flags RTL',
|
||||
'tabler-marketing': 'Marketing',
|
||||
@@ -25,22 +27,24 @@ const plugins = {
|
||||
'tabler-vendors.rtl': 'Vendors RTL',
|
||||
}
|
||||
|
||||
styles.forEach((file, i) => {
|
||||
styles.forEach((file: string) => {
|
||||
const content = readFileSync(file, 'utf8')
|
||||
const filename = basename(file)
|
||||
const pluginKey = Object.keys(plugins).find(plugin => filename.includes(plugin))
|
||||
const plugin = plugins[pluginKey]
|
||||
const pluginKey = Object.keys(plugins).find((plugin: string) => filename.includes(plugin))
|
||||
const plugin = pluginKey ? plugins[pluginKey] : undefined
|
||||
const regex = /^(@charset ['"][a-zA-Z0-9-]+['"];?)\n?/i
|
||||
|
||||
let newContent = ''
|
||||
const bannerText = banner(plugin)
|
||||
|
||||
if (content.match(regex)) {
|
||||
newContent = content.replace(regex, (m, m1) => {
|
||||
return `${m1}\n${banner(plugin)}\n`
|
||||
newContent = content.replace(regex, (m: string, m1: string) => {
|
||||
return `${m1}\n${bannerText}\n`
|
||||
})
|
||||
} else {
|
||||
newContent = `${banner(plugin)}\n${content}`
|
||||
newContent = `${bannerText}\n${content}`
|
||||
}
|
||||
|
||||
writeFileSync(file, newContent, 'utf8')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
// Get __dirname in ES modules
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
|
||||
// File paths (relative to core/.build directory)
|
||||
const bootstrapPath = path.join(__dirname, '../node_modules/bootstrap/scss/_variables.scss')
|
||||
const tablerPath = path.join(__dirname, '../scss/_variables.scss')
|
||||
|
||||
// Function to extract variable names from SCSS file
|
||||
function extractVariables(filePath: string): Set<string> {
|
||||
const content = readFileSync(filePath, 'utf8')
|
||||
const variables = new Set<string>()
|
||||
|
||||
// Regex to find SCSS variables
|
||||
// Looks for patterns like: $variable-name: value
|
||||
// Includes variables in maps and lists
|
||||
const variableRegex = /\$([a-zA-Z0-9_-]+)\s*[:=]/g
|
||||
|
||||
let match: RegExpExecArray | null
|
||||
while ((match = variableRegex.exec(content)) !== null) {
|
||||
const varName = match[1]
|
||||
variables.add(varName)
|
||||
}
|
||||
|
||||
return variables
|
||||
}
|
||||
|
||||
// Main function
|
||||
function compareVariables(): void {
|
||||
console.log('Analyzing Bootstrap variables...')
|
||||
const bootstrapVars = extractVariables(bootstrapPath)
|
||||
console.log(`Found ${bootstrapVars.size} variables in Bootstrap\n`)
|
||||
|
||||
console.log('Analyzing Tabler variables...')
|
||||
const tablerVars = extractVariables(tablerPath)
|
||||
console.log(`Found ${tablerVars.size} variables in Tabler\n`)
|
||||
|
||||
// Find variables that are in Bootstrap but not in Tabler
|
||||
const missingInTabler: string[] = []
|
||||
for (const varName of bootstrapVars) {
|
||||
if (!tablerVars.has(varName)) {
|
||||
missingInTabler.push(varName)
|
||||
}
|
||||
}
|
||||
|
||||
// Sort alphabetically
|
||||
missingInTabler.sort()
|
||||
|
||||
console.log('='.repeat(60))
|
||||
console.log(`Variables in Bootstrap that are missing in Tabler: ${missingInTabler.length}`)
|
||||
console.log('='.repeat(60))
|
||||
|
||||
if (missingInTabler.length === 0) {
|
||||
console.log('All Bootstrap variables are present in Tabler!')
|
||||
} else {
|
||||
console.log('\nList of missing variables:\n')
|
||||
missingInTabler.forEach((varName: string, index: number) => {
|
||||
console.log(`${(index + 1).toString().padStart(4)}. $${varName}`)
|
||||
})
|
||||
}
|
||||
|
||||
// Optionally: show statistics
|
||||
console.log('\n' + '='.repeat(60))
|
||||
console.log('Statistics:')
|
||||
console.log(` Bootstrap: ${bootstrapVars.size} variables`)
|
||||
console.log(` Tabler: ${tablerVars.size} variables`)
|
||||
console.log(` Missing: ${missingInTabler.length} variables`)
|
||||
console.log(` Coverage: ${((1 - missingInTabler.length / bootstrapVars.size) * 100).toFixed(1)}%`)
|
||||
console.log('='.repeat(60))
|
||||
}
|
||||
|
||||
// Run analysis
|
||||
try {
|
||||
compareVariables()
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
console.error('Error during analysis:', errorMessage)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
import { existsSync, mkdirSync, lstatSync } from 'fs'
|
||||
import { existsSync, mkdirSync } from 'node:fs'
|
||||
import { emptyDirSync, copySync } from 'fs-extra/esm'
|
||||
import libs from '../libs.json' with { type: 'json' }
|
||||
import { fileURLToPath } from 'url'
|
||||
import { join, dirname } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { join, dirname } from 'node:path'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
interface LibConfig {
|
||||
npm?: string
|
||||
js?: string[]
|
||||
css?: string[]
|
||||
head?: boolean
|
||||
}
|
||||
|
||||
interface Libs {
|
||||
[key: string]: LibConfig
|
||||
}
|
||||
|
||||
const libsData = libs as Libs
|
||||
|
||||
emptyDirSync(join(__dirname, '..', 'dist/libs'))
|
||||
|
||||
for(const name in libs) {
|
||||
const { npm } = libs[name]
|
||||
for (const name in libsData) {
|
||||
const { npm } = libsData[name]
|
||||
|
||||
if (npm) {
|
||||
const from = join(__dirname, '..', `node_modules/${npm}`)
|
||||
@@ -23,11 +34,12 @@ for(const name in libs) {
|
||||
if (!existsSync(to)) {
|
||||
mkdirSync(to, { recursive: true })
|
||||
}
|
||||
|
||||
|
||||
copySync(from, to, {
|
||||
dereference: true,
|
||||
})
|
||||
|
||||
|
||||
console.log(`Successfully copied ${npm}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
const crypto = require('node:crypto');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const sh = require('shelljs');
|
||||
import * as crypto from 'node:crypto'
|
||||
import { readFileSync, writeFileSync } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
sh.config.fatal = true
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const configFile = path.join(__dirname, '../../shared/data/sri.json')
|
||||
|
||||
const files = [
|
||||
interface FileConfig {
|
||||
file: string
|
||||
configPropertyName: string
|
||||
}
|
||||
|
||||
const files: FileConfig[] = [
|
||||
{
|
||||
file: 'dist/css/tabler.min.css',
|
||||
configPropertyName: 'css'
|
||||
@@ -80,28 +85,37 @@ const files = [
|
||||
file: 'dist/js/tabler-theme.min.js',
|
||||
configPropertyName: 'js-theme'
|
||||
},
|
||||
// {
|
||||
// file: 'dist/preview/css/demo.min.css',
|
||||
// configPropertyName: 'demo-css'
|
||||
// },
|
||||
// {
|
||||
// file: 'dist/preview/js/demo.min.js',
|
||||
// configPropertyName: 'demo-js'
|
||||
// },
|
||||
]
|
||||
|
||||
for (const { file, configPropertyName } of files) {
|
||||
fs.readFile(path.join(__dirname, '..', file), 'utf8', (error, data) => {
|
||||
if (error) {
|
||||
function generateSRI(): void {
|
||||
const sriData: Record<string, string> = {}
|
||||
|
||||
for (const { file, configPropertyName } of files) {
|
||||
try {
|
||||
const filePath = path.join(__dirname, '..', file)
|
||||
const data = readFileSync(filePath, 'utf8')
|
||||
|
||||
const algorithm = 'sha384'
|
||||
const hash = crypto.createHash(algorithm).update(data, 'utf8').digest('base64')
|
||||
const integrity = `${algorithm}-${hash}`
|
||||
|
||||
console.log(`${configPropertyName}: ${integrity}`)
|
||||
|
||||
sriData[configPropertyName] = integrity
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error)
|
||||
console.error(`Error processing ${file}:`, errorMessage)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const algorithm = 'sha384'
|
||||
const hash = crypto.createHash(algorithm).update(data, 'utf8').digest('base64')
|
||||
const integrity = `${algorithm}-${hash}`
|
||||
writeFileSync(configFile, JSON.stringify(sriData, null, 2) + '\n', 'utf8')
|
||||
}
|
||||
|
||||
console.log(`${configPropertyName}: ${integrity}`)
|
||||
try {
|
||||
generateSRI()
|
||||
} catch (error) {
|
||||
console.error('Failed to generate SRI:', error)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
sh.sed('-i', new RegExp(`^(\\s+"${configPropertyName}":\\s+["'])\\S*(["'])`), `$1${integrity}$2`, configFile)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { existsSync, mkdirSync } from 'node:fs'
|
||||
import { copySync } from 'fs-extra/esm'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { join, dirname } from 'node:path'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const fromDir = join(__dirname, '..', 'node_modules/geist/dist/fonts')
|
||||
const toDir = join(__dirname, '..', 'fonts')
|
||||
|
||||
// Create fonts directory if it doesn't exist
|
||||
if (!existsSync(toDir)) {
|
||||
mkdirSync(toDir, { recursive: true })
|
||||
}
|
||||
|
||||
// Copy geist-mono fonts
|
||||
const monoFrom = join(fromDir, 'geist-mono')
|
||||
const monoTo = join(toDir, 'geist-mono')
|
||||
|
||||
if (existsSync(monoFrom)) {
|
||||
if (!existsSync(monoTo)) {
|
||||
mkdirSync(monoTo, { recursive: true })
|
||||
}
|
||||
|
||||
copySync(monoFrom, monoTo, {
|
||||
dereference: true,
|
||||
})
|
||||
|
||||
console.log(`Successfully copied geist-mono fonts`)
|
||||
} else {
|
||||
console.warn(`Warning: geist-mono fonts not found at ${monoFrom}`)
|
||||
}
|
||||
|
||||
// Copy geist-sans fonts
|
||||
const sansFrom = join(fromDir, 'geist-sans')
|
||||
const sansTo = join(toDir, 'geist-sans')
|
||||
|
||||
if (existsSync(sansFrom)) {
|
||||
if (!existsSync(sansTo)) {
|
||||
mkdirSync(sansTo, { recursive: true })
|
||||
}
|
||||
|
||||
copySync(sansFrom, sansTo, {
|
||||
dereference: true,
|
||||
})
|
||||
|
||||
console.log(`Successfully copied geist-sans fonts`)
|
||||
} else {
|
||||
console.warn(`Warning: geist-sans fonts not found at ${sansFrom}`)
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { babel } from '@rollup/plugin-babel'
|
||||
import { nodeResolve } from '@rollup/plugin-node-resolve'
|
||||
import replace from '@rollup/plugin-replace'
|
||||
import banner from '../../shared/banner/index.mjs'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const ESM = process.env.ESM === 'true'
|
||||
const THEME = process.env.THEME === 'true'
|
||||
|
||||
const external = []
|
||||
const plugins = [
|
||||
babel({
|
||||
exclude: 'node_modules/**',
|
||||
babelHelpers: 'bundled'
|
||||
})
|
||||
]
|
||||
|
||||
plugins.push(
|
||||
replace({
|
||||
'process.env.NODE_ENV': '"production"',
|
||||
preventAssignment: true
|
||||
}),
|
||||
nodeResolve()
|
||||
)
|
||||
|
||||
const destinationFile = `tabler${THEME ? '-theme' : ''}${ESM ? '.esm' : ''}`
|
||||
const rollupConfig = {
|
||||
input: path.resolve(__dirname, `../js/tabler${THEME ? '-theme' : ''}.js`),
|
||||
output: {
|
||||
banner: banner(),
|
||||
file: path.resolve(__dirname, `../dist/js/${destinationFile}.js`),
|
||||
format: ESM ? 'esm' : 'umd',
|
||||
generatedCode: 'es2015'
|
||||
},
|
||||
external,
|
||||
plugins
|
||||
}
|
||||
|
||||
if (!ESM) {
|
||||
rollupConfig.output.name = `tabler${THEME ? '-theme' : ''}`
|
||||
}
|
||||
|
||||
export default rollupConfig
|
||||
@@ -0,0 +1,30 @@
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { createViteConfig } from '../../.build/vite.config.helper'
|
||||
import getBanner from '../../shared/banner/index.mjs'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const baseName = process.env.BASE_NAME || 'tabler'
|
||||
const entryFile = baseName
|
||||
const libraryName = baseName
|
||||
|
||||
const bannerText = getBanner()
|
||||
|
||||
const entryPath = path.resolve(__dirname, `../js/${entryFile}`)
|
||||
const entry = `${entryPath}.ts`
|
||||
|
||||
export default createViteConfig({
|
||||
entry: entry,
|
||||
name: libraryName,
|
||||
fileName: (format) => {
|
||||
const esmSuffix = format === 'es' ? '.esm' : ''
|
||||
return `${baseName}${esmSuffix}.js`
|
||||
},
|
||||
formats: ['es', 'umd'],
|
||||
outDir: path.resolve(__dirname, '../dist/js'),
|
||||
banner: bannerText,
|
||||
minify: false
|
||||
})
|
||||
|
||||
@@ -106,7 +106,6 @@
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- a2640e2: Add Playwright configuration and visual regression tests
|
||||
- d3ae77c: Enable `scrollSpy` in `countup` module
|
||||
- bd3d959: Refactor SCSS files to replace divide function with calc
|
||||
- cb278c7: Add Segmented Control component
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user