mirror of
https://github.com/tabler/tabler.git
synced 2026-01-25 12:26:30 +00:00
Compare commits
33 Commits
dev-layout
...
dev-shiki
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6126649bcd | ||
|
|
e4e1ff40c1 | ||
|
|
938e9d35cc | ||
|
|
82e3c39585 | ||
|
|
eac69eb35b | ||
|
|
684f40e7c1 | ||
|
|
f6414b3c94 | ||
|
|
c3e6aa1bd3 | ||
|
|
8e3cddb70f | ||
|
|
857988dd44 | ||
|
|
a24d5cab13 | ||
|
|
0c654c61f0 | ||
|
|
8e73f57140 | ||
|
|
f0fb9c66c0 | ||
|
|
29d9d4b5df | ||
|
|
84c31d1383 | ||
|
|
41fd82b388 | ||
|
|
abac36c580 | ||
|
|
301e77898c | ||
|
|
a14425792b | ||
|
|
48dbd1ed1b | ||
|
|
ee8875deb6 | ||
|
|
c0a93b8611 | ||
|
|
42081245b4 | ||
|
|
d56e1a2bac | ||
|
|
c6e8879bb6 | ||
|
|
a811fdb662 | ||
|
|
63a35a849c | ||
|
|
94e1a95ffb | ||
|
|
83ec6f8bcc | ||
|
|
e3d86c519b | ||
|
|
f9d6076014 | ||
|
|
f264470d8f |
@@ -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}`)
|
||||
}
|
||||
}
|
||||
79
.build/reformat-mdx.ts
Normal file
79
.build/reformat-mdx.ts
Normal 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)
|
||||
})
|
||||
|
||||
76
.build/vite.config.helper.ts
Normal file
76
.build/vite.config.helper.ts
Normal file
@@ -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}`);
|
||||
46
.build/zip-package.ts
Normal file
46
.build/zip-package.ts
Normal file
@@ -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}`)
|
||||
|
||||
5
.changeset/add-shiki-highlight.md
Normal file
5
.changeset/add-shiki-highlight.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/core": minor
|
||||
---
|
||||
|
||||
Added Shiki code highlighting for `pre code` blocks with `language-*` classes.
|
||||
5
.changeset/docs-css-variables-font-sizes.md
Normal file
5
.changeset/docs-css-variables-font-sizes.md
Normal file
@@ -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-*`).
|
||||
5
.changeset/highlight-component.md
Normal file
5
.changeset/highlight-component.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@tabler/preview": minor
|
||||
---
|
||||
|
||||
Added Highlight page with examples using the `ui/highlight` component.
|
||||
6
.changeset/migrate-rgba-to-color-mix.md
Normal file
6
.changeset/migrate-rgba-to-color-mix.md
Normal file
@@ -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, ...)`.
|
||||
|
||||
8
.changeset/migrate-rollup-to-vite.md
Normal file
8
.changeset/migrate-rollup-to-vite.md
Normal file
@@ -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.
|
||||
|
||||
7
.changeset/silly-crabs-walk.md
Normal file
7
.changeset/silly-crabs-walk.md
Normal file
@@ -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.
|
||||
|
||||
6
.changeset/update-icons-3.36.1.md
Normal file
6
.changeset/update-icons-3.36.1.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@tabler/preview": patch
|
||||
---
|
||||
|
||||
Updated `@tabler/icons` to v3.36.1.
|
||||
|
||||
7
.changeset/upgrade-apexcharts.md
Normal file
7
.changeset/upgrade-apexcharts.md
Normal file
@@ -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.
|
||||
|
||||
38
.cursor/rules/branch-naming.mdc
Normal file
38
.cursor/rules/branch-naming.mdc
Normal file
@@ -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 `-`.
|
||||
39
.cursor/rules/pull-request.mdc
Normal file
39
.cursor/rules/pull-request.mdc
Normal file
@@ -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.
|
||||
68
.github/workflows/argos.yml
vendored
68
.github/workflows/argos.yml
vendored
@@ -1,68 +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@v5
|
||||
|
||||
- name: Cache turbo build setup
|
||||
uses: actions/cache@v4
|
||||
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: "${{ env.NODE }}"
|
||||
cache: 'pnpm'
|
||||
|
||||
- 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
|
||||
6
.github/workflows/bundlewatch.yml
vendored
6
.github/workflows/bundlewatch.yml
vendored
@@ -9,7 +9,7 @@ on:
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 2
|
||||
NODE: 20
|
||||
NODE: 22
|
||||
|
||||
jobs:
|
||||
bundlewatch:
|
||||
@@ -17,10 +17,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v5
|
||||
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 }}
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
|
||||
32
.github/workflows/lint.yml
vendored
Normal file
32
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request: null
|
||||
|
||||
env:
|
||||
NODE: 22
|
||||
|
||||
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: "${{ env.NODE }}"
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install pnpm dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Lint Markdown
|
||||
run: pnpm run lint
|
||||
2
.github/workflows/lockfiles.yaml
vendored
2
.github/workflows/lockfiles.yaml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
name: Verify lock file integrity
|
||||
steps:
|
||||
- name: Clone Tabler
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
- name: Prevent lock file change
|
||||
uses: xalvarez/prevent-file-change-action@v3
|
||||
with:
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
pull-requests: write # to create pull request
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install PNPM
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -4,7 +4,7 @@ on:
|
||||
pull_request: null
|
||||
|
||||
env:
|
||||
NODE: 20
|
||||
NODE: 22
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -14,10 +14,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone repository
|
||||
uses: actions/checkout@v5
|
||||
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 }}
|
||||
|
||||
45
.github/workflows/type-check.yml
vendored
Normal file
45
.github/workflows/type-check.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
name: Type Check
|
||||
|
||||
on:
|
||||
pull_request: null
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
env:
|
||||
NODE: 20
|
||||
|
||||
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@v4
|
||||
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: "${{ env.NODE }}"
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install pnpm dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Run type-check
|
||||
run: pnpm run type-check
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -36,4 +36,9 @@ package-lock.json
|
||||
demo/
|
||||
dist/
|
||||
packages-zip/
|
||||
.env
|
||||
.env
|
||||
sri.json
|
||||
|
||||
# TypeScript
|
||||
*.tsbuildinfo
|
||||
.tsbuildinfo
|
||||
61
.markdownlint.json
Normal file
61
.markdownlint.json
Normal file
@@ -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
|
||||
}
|
||||
2
LICENSE
2
LICENSE
@@ -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
|
||||
|
||||
14
README.md
14
README.md
@@ -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.testmu.ai" 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')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from '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) {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
const variables = new Set();
|
||||
|
||||
// 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;
|
||||
while ((match = variableRegex.exec(content)) !== null) {
|
||||
const varName = match[1];
|
||||
variables.add(varName);
|
||||
}
|
||||
|
||||
return variables;
|
||||
}
|
||||
|
||||
// Main function
|
||||
function compareVariables() {
|
||||
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 = [];
|
||||
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, index) => {
|
||||
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) {
|
||||
console.error('Error during analysis:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
84
core/.build/compare-variables.ts
Normal file
84
core/.build/compare-variables.ts
Normal file
@@ -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)
|
||||
})
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
import { existsSync, mkdirSync } from 'fs'
|
||||
import { existsSync, mkdirSync } from 'node:fs'
|
||||
import { copySync } from 'fs-extra/esm'
|
||||
import { fileURLToPath } from 'url'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { join, dirname } from 'node:path'
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||
@@ -25,11 +23,11 @@ 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}`)
|
||||
@@ -43,11 +41,11 @@ 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
|
||||
30
core/.build/vite.config.mts
Normal file
30
core/.build/vite.config.mts
Normal file
@@ -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
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="16" fill="none"><mask id="a" width="21" height="16" x="0" y="0" mask-type="alpha" maskUnits="userSpaceOnUse"><path fill="#fff" d="M.001.927h20v15h-20z"/></mask><g mask="url(#a)"><path fill="#F7FCFF" fill-rule="evenodd" d="M.001.927v15h20v-15h-20Z" clip-rule="evenodd"/><mask id="b" width="21" height="16" x="0" y="0" mask-type="alpha" maskUnits="userSpaceOnUse"><path fill="#fff" fill-rule="evenodd" d="M.001.927v15h20v-15h-20Z" clip-rule="evenodd"/></mask><g fill-rule="evenodd" clip-rule="evenodd" mask="url(#b)"><path fill="#3D58DB" d="M.001.927v15h20v-15h-20Z"/><path fill="#FFD018" d="m9.407 3.137-.14.818L10 3.57l.735.386-.14-.818.594-.64h-.821L10 1.695l-.367.804h-.822l.595.639Zm0 10.855-.14.819.734-.387.735.387-.14-.819.594-.639h-.821L10 12.55l-.367.804h-.822l.595.64ZM3.484 9.438l.14-.818-.594-.64h.822l.367-.803.367.804h.822l-.595.639.14.818-.734-.386-.735.386Zm1.352 1.77-.14.818.734-.386.735.386-.14-.818.594-.64h-.821l-.368-.803-.367.804H4.24l.595.639Zm9.009.818.14-.818-.595-.64h.822l.367-.803.368.804h.821l-.594.639.14.818-.735-.386-.734.386Zm-9.01-6.062-.14.818.735-.386.735.386-.14-.818.594-.639h-.821l-.368-.804-.367.804H4.24l.595.64Zm9.01.818.14-.818-.595-.639h.822l.367-.804.368.804h.821l-.594.64.14.817-.735-.386-.734.386ZM6.66 13.29l-.14.819.735-.387.734.386-.14-.818.595-.639h-.822l-.367-.804-.368.804h-.821l.594.64Zm5.418.819.14-.819-.594-.639h.821l.367-.804.368.804h.821l-.594.64.14.817-.735-.386-.734.386ZM6.52 4.666l.735-.387.734.387-.14-.818.595-.64h-.822l-.367-.804-.368.804h-.821l.594.64-.14.818Zm5.558 0 .14-.818-.594-.64h.821l.367-.804.368.804h.821l-.594.64.14.818-.735-.387-.734.387Zm3.062 3.879-.14.818.735-.386.735.386-.14-.818.593-.64h-.82l-.368-.803-.368.804h-.821l.594.639Z"/></g></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="15" fill="none" viewBox="0 0 20 15"><path fill="#3d58db" fill-rule="evenodd" d="M0 0v15h20V0z" clip-rule="evenodd"/><path fill="#ffd018" fill-rule="evenodd" d="m9.407 2.442-.14.818.733-.385.735.386-.14-.818.594-.64h-.821L10 1l-.367.804h-.822zm0 10.855-.14.819.734-.387.735.387-.14-.819.594-.639h-.821L10 11.855l-.367.804h-.822l.595.64zM3.484 8.743l.14-.818-.594-.64h.822l.367-.803.367.804h.822l-.595.639.14.818-.734-.386zm1.352 1.77-.14.818.734-.386.735.386-.14-.818.594-.64h-.821L5.43 9.07l-.367.804H4.24zm9.009.818.14-.818-.595-.64h.822l.367-.803.368.804h.821l-.594.639.14.818-.735-.386zm-9.01-6.062-.14.818.735-.386.735.386-.14-.818.594-.639h-.821l-.368-.804-.367.804H4.24zm9.01.818.14-.818-.595-.639h.822l.367-.804.368.804h.821l-.594.64.14.817-.735-.386zM6.66 12.595l-.14.819.735-.387.734.386-.14-.818.595-.639h-.822l-.367-.804-.368.804h-.821zm5.418.819.14-.819-.594-.639h.821l.367-.804.368.804h.821l-.594.64.14.817-.735-.386zM6.52 3.971l.735-.387.734.387-.14-.818.595-.64h-.822l-.367-.804-.368.804h-.821l.594.64zm5.558 0 .14-.818-.594-.64h.821l.367-.804.368.804h.821l-.594.64.14.818-.735-.387zM15.14 7.85l-.14.818.735-.386.735.386-.14-.818.593-.64h-.82l-.368-.803-.368.804h-.821z" clip-rule="evenodd"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,8 +0,0 @@
|
||||
// Autosize plugin
|
||||
const elements = document.querySelectorAll('[data-bs-toggle="autosize"]')
|
||||
|
||||
if (elements.length) {
|
||||
elements.forEach(function (element) {
|
||||
window.autosize && window.autosize(element)
|
||||
})
|
||||
}
|
||||
10
core/js/src/autosize.ts
Normal file
10
core/js/src/autosize.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
// Autosize plugin
|
||||
const autosizeElements: NodeListOf<HTMLElement> = document.querySelectorAll<HTMLElement>('[data-bs-toggle="autosize"]')
|
||||
|
||||
if (autosizeElements.length) {
|
||||
autosizeElements.forEach(function (element: HTMLElement) {
|
||||
if (window.autosize) {
|
||||
window.autosize(element)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,20 +1,7 @@
|
||||
export * as Popper from '@popperjs/core'
|
||||
|
||||
// Export all Bootstrap components directly for consistent usage
|
||||
export {
|
||||
Alert,
|
||||
Button,
|
||||
Carousel,
|
||||
Collapse,
|
||||
Dropdown,
|
||||
Modal,
|
||||
Offcanvas,
|
||||
Popover,
|
||||
ScrollSpy,
|
||||
Tab,
|
||||
Toast,
|
||||
Tooltip
|
||||
} from 'bootstrap'
|
||||
export { Alert, Button, Carousel, Collapse, Dropdown, Modal, Offcanvas, Popover, ScrollSpy, Tab, Toast, Tooltip } from 'bootstrap'
|
||||
|
||||
// Re-export everything as namespace for backward compatibility
|
||||
export * as bootstrap from 'bootstrap'
|
||||
@@ -1,17 +1,19 @@
|
||||
const elements = document.querySelectorAll('[data-countup]')
|
||||
const countupElements: NodeListOf<HTMLElement> = document.querySelectorAll<HTMLElement>('[data-countup]')
|
||||
|
||||
if (elements.length) {
|
||||
elements.forEach(function (element) {
|
||||
let options = {}
|
||||
if (countupElements.length) {
|
||||
countupElements.forEach(function (element: HTMLElement) {
|
||||
let options: Record<string, any> = {}
|
||||
try {
|
||||
const dataOptions = element.getAttribute('data-countup') ? JSON.parse(element.getAttribute('data-countup')) : {}
|
||||
const dataOptions = element.getAttribute('data-countup') ? JSON.parse(element.getAttribute('data-countup')!) : {}
|
||||
options = Object.assign(
|
||||
{
|
||||
enableScrollSpy: true,
|
||||
},
|
||||
dataOptions,
|
||||
)
|
||||
} catch (error) {}
|
||||
} catch (error) {
|
||||
// ignore invalid JSON
|
||||
}
|
||||
|
||||
const value = parseInt(element.innerHTML, 10)
|
||||
|
||||
@@ -3,9 +3,9 @@ import { Dropdown } from './bootstrap'
|
||||
/*
|
||||
Core dropdowns
|
||||
*/
|
||||
let dropdownTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="dropdown"]'))
|
||||
dropdownTriggerList.map(function (dropdownTriggerEl) {
|
||||
let options = {
|
||||
const dropdownTriggerList: HTMLElement[] = [].slice.call(document.querySelectorAll<HTMLElement>('[data-bs-toggle="dropdown"]'))
|
||||
dropdownTriggerList.map(function (dropdownTriggerEl: HTMLElement) {
|
||||
const options = {
|
||||
boundary: dropdownTriggerEl.getAttribute('data-bs-boundary') === 'viewport' ? document.querySelector('.btn') : 'clippingParents',
|
||||
}
|
||||
return new Dropdown(dropdownTriggerEl, options)
|
||||
23
core/js/src/global.d.ts
vendored
Normal file
23
core/js/src/global.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// Global type declarations for window properties
|
||||
|
||||
interface Window {
|
||||
autosize?: (element: HTMLElement | HTMLTextAreaElement) => void
|
||||
countUp?: {
|
||||
CountUp: new (target: HTMLElement, endVal: number, options?: any) => {
|
||||
error: boolean
|
||||
start: () => void
|
||||
}
|
||||
}
|
||||
IMask?: new (element: HTMLElement, options: { mask: string; lazy?: boolean }) => any
|
||||
Sortable?: new (element: HTMLElement, options?: any) => any
|
||||
}
|
||||
|
||||
declare module 'shiki/bundle/web' {
|
||||
export const createHighlighter: (options: {
|
||||
langs: string[]
|
||||
themes: string[]
|
||||
}) => Promise<{
|
||||
codeToHtml: (code: string, options: { lang: string; theme: string }) => string
|
||||
}>
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Input mask plugin
|
||||
|
||||
var maskElementList = [].slice.call(document.querySelectorAll('[data-mask]'))
|
||||
maskElementList.map(function (maskEl) {
|
||||
const maskElementList: HTMLElement[] = [].slice.call(document.querySelectorAll<HTMLElement>('[data-mask]'))
|
||||
maskElementList.map(function (maskEl: HTMLElement) {
|
||||
window.IMask &&
|
||||
new window.IMask(maskEl, {
|
||||
mask: maskEl.dataset.mask,
|
||||
@@ -3,9 +3,9 @@ import { Popover } from './bootstrap'
|
||||
/*
|
||||
Core popovers
|
||||
*/
|
||||
let popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
|
||||
popoverTriggerList.map(function (popoverTriggerEl) {
|
||||
let options = {
|
||||
const popoverTriggerList: HTMLElement[] = [].slice.call(document.querySelectorAll<HTMLElement>('[data-bs-toggle="popover"]'))
|
||||
popoverTriggerList.map(function (popoverTriggerEl: HTMLElement) {
|
||||
const options = {
|
||||
delay: { show: 50, hide: 50 },
|
||||
html: popoverTriggerEl.getAttribute('data-bs-html') === 'true',
|
||||
placement: popoverTriggerEl.getAttribute('data-bs-placement') ?? 'auto',
|
||||
84
core/js/src/shiki.ts
Normal file
84
core/js/src/shiki.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
type ShikiHighlighter = {
|
||||
codeToHtml: (code: string, options: { lang: string; theme: string }) => string
|
||||
}
|
||||
|
||||
const shikiSelector = 'pre code[class*="language-"], pre code[data-language]'
|
||||
const shikiCodeBlocks = Array.from(document.querySelectorAll<HTMLElement>(shikiSelector))
|
||||
|
||||
const getShikiLanguage = (codeBlock: HTMLElement): string => {
|
||||
const dataLanguage = codeBlock.dataset.language
|
||||
if (dataLanguage) {
|
||||
return dataLanguage
|
||||
}
|
||||
|
||||
const languageClass = Array.from(codeBlock.classList).find((className) => className.startsWith('language-'))
|
||||
return languageClass ? languageClass.replace('language-', '') : 'text'
|
||||
}
|
||||
|
||||
const getShikiTheme = (codeBlock: HTMLElement): string => {
|
||||
return codeBlock.dataset.shikiTheme || codeBlock.closest<HTMLElement>('[data-shiki-theme]')?.dataset.shikiTheme || 'github-dark'
|
||||
}
|
||||
|
||||
const getShikiBlocksToHighlight = (codeBlocks: HTMLElement[]): HTMLElement[] => {
|
||||
return codeBlocks.filter((codeBlock) => {
|
||||
const pre = codeBlock.closest('pre')
|
||||
return pre && !pre.classList.contains('shiki') && pre.dataset.shikiProcessed !== 'true'
|
||||
})
|
||||
}
|
||||
|
||||
const highlightShikiBlocks = async (codeBlocks: HTMLElement[]) => {
|
||||
if (!codeBlocks.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const languages = new Set<string>(['text'])
|
||||
|
||||
codeBlocks.forEach((codeBlock) => {
|
||||
languages.add(getShikiLanguage(codeBlock))
|
||||
})
|
||||
|
||||
const { createHighlighter, createCssVariablesTheme } = await import('shiki')
|
||||
|
||||
const theme = createCssVariablesTheme({
|
||||
name: 'css-variables',
|
||||
variablePrefix: '--shiki-',
|
||||
variableDefaults: {},
|
||||
fontStyle: true
|
||||
})
|
||||
|
||||
const highlighter = (await createHighlighter({
|
||||
langs: Array.from(languages).filter(Boolean),
|
||||
themes: [theme],
|
||||
})) as ShikiHighlighter
|
||||
|
||||
codeBlocks.forEach((codeBlock) => {
|
||||
const pre = codeBlock.closest('pre')
|
||||
if (!pre || pre.dataset.shikiProcessed === 'true') {
|
||||
return
|
||||
}
|
||||
|
||||
const language = getShikiLanguage(codeBlock)
|
||||
const code = codeBlock.textContent || ''
|
||||
|
||||
let highlightedHtml = ''
|
||||
try {
|
||||
highlightedHtml = highlighter.codeToHtml(code, { lang: language, theme: 'css-variables' })
|
||||
} catch (error) {
|
||||
highlightedHtml = highlighter.codeToHtml(code, { lang: 'text', theme: 'css-variables' })
|
||||
}
|
||||
|
||||
const wrapper = document.createElement('div')
|
||||
wrapper.innerHTML = highlightedHtml
|
||||
const highlightedPre = wrapper.firstElementChild
|
||||
|
||||
if (highlightedPre) {
|
||||
pre.dataset.shikiProcessed = 'true'
|
||||
pre.replaceWith(highlightedPre)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const shikiBlocksToHighlight = getShikiBlocksToHighlight(shikiCodeBlocks)
|
||||
if (shikiBlocksToHighlight.length) {
|
||||
void highlightShikiBlocks(shikiBlocksToHighlight)
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
// Initializes Sortable on elements marked with [data-sortable]
|
||||
// Allows options via JSON in data attribute: data-sortable='{"animation":150}'
|
||||
|
||||
const sortableElements = document.querySelectorAll('[data-sortable]')
|
||||
const sortableElements: NodeListOf<HTMLElement> = document.querySelectorAll<HTMLElement>('[data-sortable]')
|
||||
|
||||
if (sortableElements.length) {
|
||||
sortableElements.forEach(function (element) {
|
||||
let options = {}
|
||||
sortableElements.forEach(function (element: HTMLElement) {
|
||||
let options: Record<string, any> = {}
|
||||
|
||||
try {
|
||||
const rawOptions = element.getAttribute('data-sortable')
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
Switch icons
|
||||
*/
|
||||
let switchesTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="switch-icon"]'))
|
||||
switchesTriggerList.map(function (switchTriggerEl) {
|
||||
switchTriggerEl.addEventListener('click', (e) => {
|
||||
e.stopPropagation()
|
||||
|
||||
switchTriggerEl.classList.toggle('active')
|
||||
})
|
||||
})
|
||||
11
core/js/src/switch-icon.ts
Normal file
11
core/js/src/switch-icon.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
Switch icons
|
||||
*/
|
||||
const switchesTriggerList: HTMLElement[] = [].slice.call(document.querySelectorAll<HTMLElement>('[data-bs-toggle="switch-icon"]'))
|
||||
switchesTriggerList.map(function (switchTriggerEl: HTMLElement) {
|
||||
switchTriggerEl.addEventListener('click', (e: MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
|
||||
switchTriggerEl.classList.toggle('active')
|
||||
})
|
||||
})
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Tab } from './bootstrap'
|
||||
|
||||
export const EnableActivationTabsFromLocationHash = () => {
|
||||
const locationHash = window.location.hash
|
||||
|
||||
if (locationHash) {
|
||||
const tabsList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tab"]'))
|
||||
const matchedTabs = tabsList.filter((tab) => tab.hash === locationHash)
|
||||
|
||||
matchedTabs.map((tab) => {
|
||||
new Tab(tab).show()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
EnableActivationTabsFromLocationHash()
|
||||
16
core/js/src/tab.ts
Normal file
16
core/js/src/tab.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Tab } from './bootstrap'
|
||||
|
||||
export const EnableActivationTabsFromLocationHash = (): void => {
|
||||
const locationHash: string = window.location.hash
|
||||
|
||||
if (locationHash) {
|
||||
const tabsList: HTMLAnchorElement[] = [].slice.call(document.querySelectorAll<HTMLAnchorElement>('[data-bs-toggle="tab"]'))
|
||||
const matchedTabs = tabsList.filter((tab: HTMLAnchorElement) => tab.hash === locationHash)
|
||||
|
||||
matchedTabs.map((tab: HTMLAnchorElement) => {
|
||||
new Tab(tab).show()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
EnableActivationTabsFromLocationHash()
|
||||
@@ -1,12 +1,12 @@
|
||||
export const prefix = 'tblr-'
|
||||
export const prefix: string = 'tblr-'
|
||||
|
||||
export const hexToRgba = (hex, opacity) => {
|
||||
export const hexToRgba = (hex: string, opacity: number): string | null => {
|
||||
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
|
||||
|
||||
return result ? `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, ${opacity})` : null
|
||||
}
|
||||
|
||||
export const getColor = (color, opacity = 1) => {
|
||||
export const getColor = (color: string, opacity: number = 1): string | null => {
|
||||
const c = getComputedStyle(document.body).getPropertyValue(`--${prefix}${color}`).trim()
|
||||
|
||||
if (opacity !== 1) {
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Toast } from './bootstrap'
|
||||
|
||||
/*
|
||||
Toasts
|
||||
*/
|
||||
let toastsTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="toast"]'))
|
||||
toastsTriggerList.map(function (toastTriggerEl) {
|
||||
if (!toastTriggerEl.hasAttribute('data-bs-target')) {
|
||||
return
|
||||
}
|
||||
|
||||
const toastEl = new Toast(toastTriggerEl.getAttribute('data-bs-target'))
|
||||
|
||||
toastTriggerEl.addEventListener('click', () => {
|
||||
toastEl.show()
|
||||
})
|
||||
})
|
||||
18
core/js/src/toast.ts
Normal file
18
core/js/src/toast.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Toast } from './bootstrap'
|
||||
|
||||
/*
|
||||
Toasts
|
||||
*/
|
||||
const toastsTriggerList: HTMLElement[] = [].slice.call(document.querySelectorAll<HTMLElement>('[data-bs-toggle="toast"]'))
|
||||
toastsTriggerList.map(function (toastTriggerEl: HTMLElement) {
|
||||
const target = toastTriggerEl.getAttribute('data-bs-target')
|
||||
if (target === null) {
|
||||
return
|
||||
}
|
||||
|
||||
const toastEl = new Toast(target)
|
||||
|
||||
toastTriggerEl.addEventListener('click', () => {
|
||||
toastEl.show()
|
||||
})
|
||||
})
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Tooltip } from './bootstrap'
|
||||
|
||||
let tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
let options = {
|
||||
const tooltipTriggerList: HTMLElement[] = [].slice.call(document.querySelectorAll<HTMLElement>('[data-bs-toggle="tooltip"]'))
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl: HTMLElement) {
|
||||
const options = {
|
||||
delay: { show: 50, hide: 50 },
|
||||
html: tooltipTriggerEl.getAttribute('data-bs-html') === 'true',
|
||||
placement: tooltipTriggerEl.getAttribute('data-bs-placement') ?? 'auto',
|
||||
@@ -3,7 +3,15 @@
|
||||
* to ensure we switch to the chosen dark/light theme as fast as possible.
|
||||
* This will prevent any flashes of the light theme (default) before switching.
|
||||
*/
|
||||
const themeConfig = {
|
||||
interface ThemeConfig {
|
||||
'theme': string
|
||||
'theme-base': string
|
||||
'theme-font': string
|
||||
'theme-primary': string
|
||||
'theme-radius': string
|
||||
}
|
||||
|
||||
const themeConfig: ThemeConfig = {
|
||||
'theme': 'light',
|
||||
'theme-base': 'gray',
|
||||
'theme-font': 'sans-serif',
|
||||
@@ -12,22 +20,22 @@ const themeConfig = {
|
||||
}
|
||||
|
||||
const params = new Proxy(new URLSearchParams(window.location.search), {
|
||||
get: (searchParams, prop) => searchParams.get(prop),
|
||||
get: (searchParams: URLSearchParams, prop: string): string | null => searchParams.get(prop),
|
||||
})
|
||||
|
||||
for (const key in themeConfig) {
|
||||
const param = params[key]
|
||||
let selectedValue
|
||||
let selectedValue: string
|
||||
|
||||
if (!!param) {
|
||||
localStorage.setItem('tabler-' + key, param)
|
||||
selectedValue = param
|
||||
} else {
|
||||
const storedTheme = localStorage.getItem('tabler-' + key)
|
||||
selectedValue = storedTheme ? storedTheme : themeConfig[key]
|
||||
selectedValue = storedTheme ? storedTheme : themeConfig[key as keyof ThemeConfig]
|
||||
}
|
||||
|
||||
if (selectedValue !== themeConfig[key]) {
|
||||
if (selectedValue !== themeConfig[key as keyof ThemeConfig]) {
|
||||
document.documentElement.setAttribute('data-bs-' + key, selectedValue)
|
||||
} else {
|
||||
document.documentElement.removeAttribute('data-bs-' + key)
|
||||
@@ -8,8 +8,9 @@ import './src/switch-icon'
|
||||
import './src/tab'
|
||||
import './src/toast'
|
||||
import './src/sortable'
|
||||
import './src/shiki'
|
||||
|
||||
// Re-export everything from bootstrap.js (single source of truth)
|
||||
// Re-export everything from bootstrap.ts (single source of truth)
|
||||
export * from './src/bootstrap'
|
||||
|
||||
// Re-export tabler namespace
|
||||
@@ -166,5 +166,14 @@
|
||||
"dist/turbo.es2017-umd.js"
|
||||
],
|
||||
"head": true
|
||||
},
|
||||
"driver.js": {
|
||||
"npm": "driver.js",
|
||||
"js": [
|
||||
"dist/driver.js.iife.js"
|
||||
],
|
||||
"css": [
|
||||
"dist/driver.css"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,41 +5,39 @@
|
||||
"homepage": "https://tabler.io",
|
||||
"scripts": {
|
||||
"dev": "pnpm run clean && pnpm run copy && pnpm run watch",
|
||||
"build": "pnpm run clean && pnpm run css && pnpm run js && pnpm run copy && pnpm run generate-sri",
|
||||
"build": "pnpm run clean && pnpm run build-assets && pnpm run copy && pnpm run generate-sri",
|
||||
"build-assets": "concurrently \"pnpm run css\" \"pnpm run js\"",
|
||||
"clean": "shx rm -rf dist demo",
|
||||
"css": "pnpm run css-compile && pnpm run css-prefix && pnpm run css-rtl && pnpm run css-minify && pnpm run css-banner",
|
||||
"css-compile": "sass --no-source-map --load-path=node_modules --style expanded scss/:dist/css/",
|
||||
"css-banner": "node .build/add-banner.mjs",
|
||||
"css": "pnpm run css-build && pnpm run css-prefix && pnpm run css-rtl && pnpm run css-minify && pnpm run css-banner",
|
||||
"css-build": "sass --no-source-map --load-path=node_modules --style expanded scss/:dist/css/",
|
||||
"css-banner": "tsx .build/add-banner.ts",
|
||||
"css-prefix": "postcss --config .build/postcss.config.mjs --replace \"dist/css/*.css\" \"!dist/css/*.rtl*.css\" \"!dist/css/*.min.css\"",
|
||||
"css-rtl": "cross-env NODE_ENV=RTL postcss --config .build/postcss.config.mjs --dir \"dist/css\" --ext \".rtl.css\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*.rtl.css\"",
|
||||
"css-minify": "pnpm run css-minify-main && pnpm run css-minify-rtl",
|
||||
"css-minify": "concurrently \"pnpm run css-minify-main\" \"pnpm run css-minify-rtl\"",
|
||||
"css-minify-main": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*.css\" \"!dist/css/*.min.css\" \"!dist/css/*rtl*.css\"",
|
||||
"css-minify-rtl": "cleancss -O1 --format breakWith=lf --with-rebase --source-map --source-map-inline-sources --output dist/css/ --batch --batch-suffix \".min\" \"dist/css/*rtl.css\" \"!dist/css/*.min.css\"",
|
||||
"css-lint": "pnpm run css-lint-variables",
|
||||
"css-lint-variables": "find-unused-sass-variables scss/ node_modules/bootstrap/scss/",
|
||||
"js": "pnpm run js-compile && pnpm run js-minify",
|
||||
"js-compile": "pnpm run js-compile-standalone && pnpm run js-compile-standalone-esm && pnpm run js-compile-theme && pnpm run js-compile-theme-esm",
|
||||
"js-compile-theme-esm": "rollup --environment THEME:true --environment ESM:true --config .build/rollup.config.mjs --sourcemap",
|
||||
"js-compile-theme": "rollup --environment THEME:true --config .build/rollup.config.mjs --sourcemap",
|
||||
"js-compile-standalone": "rollup --config .build/rollup.config.mjs --sourcemap",
|
||||
"js-compile-standalone-esm": "rollup --environment ESM:true --config .build/rollup.config.mjs --sourcemap",
|
||||
"js-minify": "pnpm run js-minify-standalone && pnpm run js-minify-standalone-esm && pnpm run js-minify-theme && pnpm run js-minify-theme-esm",
|
||||
"js-minify-standalone": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/tabler.js.map,includeSources,url=tabler.min.js.map\" --output dist/js/tabler.min.js dist/js/tabler.js",
|
||||
"js-minify-standalone-esm": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/tabler.esm.js.map,includeSources,url=tabler.esm.min.js.map\" --output dist/js/tabler.esm.min.js dist/js/tabler.esm.js",
|
||||
"js-minify-theme": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/tabler-theme.js.map,includeSources,url=tabler-theme.min.js.map\" --output dist/js/tabler-theme.min.js dist/js/tabler-theme.js",
|
||||
"js-minify-theme-esm": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/js/tabler-theme.esm.js.map,includeSources,url=tabler-theme.esm.min.js.map\" --output dist/js/tabler-theme.esm.min.js dist/js/tabler-theme.esm.js",
|
||||
"copy": "pnpm run copy-img && pnpm run copy-libs && pnpm run copy-fonts",
|
||||
"js": "pnpm run js-build && pnpm run js-build-min",
|
||||
"js-build": "concurrently \"pnpm run js-build-standalone\" \"pnpm run js-build-theme\"",
|
||||
"js-build-theme": "cross-env BASE_NAME=tabler-theme vite build --config .build/vite.config.mts",
|
||||
"js-build-standalone": "cross-env BASE_NAME=tabler vite build --config .build/vite.config.mts",
|
||||
"js-build-min": "concurrently \"pnpm run js-build-min-standalone\" \"pnpm run js-build-min-theme\"",
|
||||
"js-build-min-standalone": "concurrently \"terser dist/js/tabler.js --compress --mangle --comments '/@license|@preserve|^!/' --source-map \\\"content=dist/js/tabler.js.map,filename=dist/js/tabler.min.js.map,url=tabler.min.js.map\\\" -o dist/js/tabler.min.js\" \"terser dist/js/tabler.esm.js --module --compress --mangle --comments '/@license|@preserve|^!/' --source-map \\\"content=dist/js/tabler.esm.js.map,filename=dist/js/tabler.esm.min.js.map,url=tabler.esm.min.js.map\\\" -o dist/js/tabler.esm.min.js\"",
|
||||
"js-build-min-theme": "concurrently \"terser dist/js/tabler-theme.js --compress --mangle --comments '/@license|@preserve|^!/' --source-map \\\"content=dist/js/tabler-theme.js.map,filename=dist/js/tabler-theme.min.js.map,url=tabler-theme.min.js.map\\\" -o dist/js/tabler-theme.min.js\" \"terser dist/js/tabler-theme.esm.js --module --compress --mangle --comments '/@license|@preserve|^!/' --source-map \\\"content=dist/js/tabler-theme.esm.js.map,filename=dist/js/tabler-theme.esm.min.js.map,url=tabler-theme.esm.min.js.map\\\" -o dist/js/tabler-theme.esm.min.js\"",
|
||||
"copy": "concurrently \"pnpm run copy-img\" \"pnpm run copy-libs\" \"pnpm run copy-fonts\"",
|
||||
"copy-img": "shx mkdir -p dist/img && shx cp -rf img/* dist/img",
|
||||
"copy-libs": "node .build/copy-libs.mjs",
|
||||
"copy-libs": "tsx .build/copy-libs.ts",
|
||||
"copy-fonts": "shx mkdir -p dist/fonts && shx cp -rf fonts/* dist/fonts",
|
||||
"import-fonts": "node .build/import-fonts.mjs",
|
||||
"import-fonts": "tsx .build/import-fonts.ts",
|
||||
"watch": "concurrently \"pnpm run watch-css\" \"pnpm run watch-js\"",
|
||||
"watch-css": "nodemon --watch scss/ --ext scss --exec \"pnpm run css-compile && pnpm run css-prefix\"",
|
||||
"watch-js": "nodemon --watch js/ --ext js --exec \"pnpm run js-compile\"",
|
||||
"watch-css": "nodemon --watch scss/ --ext scss --exec \"pnpm run css-build && pnpm run css-prefix\"",
|
||||
"watch-js": "nodemon --watch js/ --ext ts,js --exec \"pnpm run js-build\"",
|
||||
"bundlewatch": "bundlewatch",
|
||||
"generate-sri": "node .build/generate-sri.js",
|
||||
"format:check": "prettier --check \"scss/**/*.scss\" \"js/**/*.js\" --cache",
|
||||
"format:write": "prettier --write \"scss/**/*.scss\" \"js/**/*.js\" --cache"
|
||||
"generate-sri": "tsx .build/generate-sri.ts",
|
||||
"format:check": "prettier --check \"scss/**/*.scss\" \"js/**/*.{js,ts}\" --cache",
|
||||
"format:write": "prettier --write \"scss/**/*.scss\" \"js/**/*.{js,ts}\" --cache",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -69,7 +67,7 @@
|
||||
"files": [
|
||||
"docs/**/*",
|
||||
"dist/**/*",
|
||||
"js/**/*.{js,map}",
|
||||
"js/**/*.{ts,js,map}",
|
||||
"img/**/*.{svg}",
|
||||
"scss/**/*.scss",
|
||||
"libs.json"
|
||||
@@ -155,7 +153,8 @@
|
||||
"devDependencies": {
|
||||
"@hotwired/turbo": "^8.0.18",
|
||||
"@melloware/coloris": "^0.25.0",
|
||||
"apexcharts": "3.54.1",
|
||||
"@types/node": "^22.0.0",
|
||||
"apexcharts": "^5.3.6",
|
||||
"autosize": "^6.0.1",
|
||||
"choices.js": "^11.1.0",
|
||||
"clipboard": "^2.0.11",
|
||||
@@ -177,7 +176,10 @@
|
||||
"sortablejs": "^1.15.6",
|
||||
"star-rating.js": "^4.3.1",
|
||||
"tom-select": "^2.4.3",
|
||||
"typed.js": "^2.1.0"
|
||||
"typed.js": "^2.1.0",
|
||||
"shiki": "^3.13.0",
|
||||
"typescript": "^5.9.3",
|
||||
"driver.js": "^1.0.0"
|
||||
},
|
||||
"directories": {
|
||||
"doc": "docs"
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
/** Theme colors */
|
||||
@each $name, $color in map.merge($theme-colors, $social-colors) {
|
||||
@debug contrast-ratio($color, white), $name, $min-contrast-ratio;
|
||||
--#{$prefix}#{$name}: #{$color};
|
||||
--#{$prefix}#{$name}-rgb: #{to-rgb($color)};
|
||||
--#{$prefix}#{$name}-fg: #{if(contrast-ratio($color) > $min-contrast-ratio, var(--#{$prefix}light), var(--#{$prefix}dark))};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,12 +33,7 @@ $enable-deprecation-messages: true !default;
|
||||
$enable-important-utilities: true !default;
|
||||
|
||||
// Escaped Characters
|
||||
$escaped-characters: (
|
||||
('<', '%3c'),
|
||||
('>', '%3e'),
|
||||
('#', '%23'),
|
||||
('(', '%28'),
|
||||
(')', '%29')) !default;
|
||||
$escaped-characters: (('<', '%3c'), ('>', '%3e'), ('#', '%23'), ('(', '%28'), (')', '%29')) !default;
|
||||
|
||||
// Dark Mode
|
||||
$color-mode-type: data !default;
|
||||
@@ -500,6 +495,11 @@ $line-heights: (
|
||||
h4: $h4-line-height,
|
||||
h5: $h5-line-height,
|
||||
h6: $h6-line-height,
|
||||
|
||||
base: $line-height-base,
|
||||
sm: $line-height-sm,
|
||||
lg: $line-height-lg,
|
||||
xl: $line-height-xl,
|
||||
) !default;
|
||||
|
||||
$display-font-sizes: (
|
||||
@@ -560,11 +560,6 @@ $text-secondary-opacity: 0.7 !default;
|
||||
$text-secondary-light-opacity: 0.4 !default;
|
||||
$text-secondary-dark-opacity: 0.8 !default;
|
||||
|
||||
$border-opacity: 0.16 !default;
|
||||
$border-light-opacity: 0.08 !default;
|
||||
$border-dark-opacity: 0.24 !default;
|
||||
$border-active-opacity: 0.58 !default;
|
||||
|
||||
$bg-surface: var(--#{$prefix}white) !default;
|
||||
$bg-surface-secondary: var(--#{$prefix}gray-100) !default;
|
||||
$bg-surface-tertiary: var(--#{$prefix}gray-50) !default;
|
||||
@@ -572,12 +567,8 @@ $bg-surface-dark: var(--#{$prefix}dark) !default;
|
||||
|
||||
$body-text-align: null !default;
|
||||
$body-bg: $gray-50 !default;
|
||||
$body-color: $dark !default;
|
||||
$body-color: $gray-800 !default;
|
||||
$body-emphasis-color: $gray-700 !default;
|
||||
$body-secondary-color: rgba($body-color, 0.75) !default;
|
||||
$body-secondary-bg: $gray-200 !default;
|
||||
$body-tertiary-color: rgba($body-color, 0.5) !default;
|
||||
$body-tertiary-bg: $gray-100 !default;
|
||||
|
||||
$color-contrast-dark: $body-color !default;
|
||||
$color-contrast-light: $light !default;
|
||||
@@ -587,20 +578,27 @@ $text-secondary: $gray-500 !default;
|
||||
$text-secondary-light: $gray-400 !default;
|
||||
$text-secondary-dark: $gray-600 !default;
|
||||
|
||||
$border-color: $gray-200 !default;
|
||||
$border-color-translucent: rgba(4, 32, 69, 0.1);
|
||||
$border-light-color: var(--#{$prefix}gray-200) !default;
|
||||
$border-light-opacity: 4.7% !default;
|
||||
$border-light-color-translucent: color-mix(in srgb, var(--#{$prefix}gray-800) #{$border-light-opacity}, transparent) !default;
|
||||
|
||||
$border-dark-color: $gray-400 !default;
|
||||
$border-dark-color-translucent: rgba(4, 32, 69, 0.27);
|
||||
$border-color: var(--#{$prefix}gray-200) !default;
|
||||
$border-opacity: 11.9% !default;
|
||||
$border-color-translucent: color-mix(in srgb, var(--#{$prefix}gray-800) #{$border-opacity}, transparent) !default;
|
||||
|
||||
$border-active-color: color.mix($text-secondary, #ffffff, math.percentage($border-active-opacity)) !default;
|
||||
$border-active-color-translucent: rgba($text-secondary, $border-active-opacity) !default;
|
||||
$border-dark-color: var(--#{$prefix}gray-300) !default;
|
||||
$border-dark-opacity: 20.7% !default;
|
||||
$border-dark-color-translucent: color-mix(in srgb, var(--#{$prefix}gray-800) #{$border-dark-opacity}, transparent) !default;
|
||||
|
||||
$active-bg: rgba(var(--#{$prefix}primary-rgb), 0.04) !default;
|
||||
$border-active-color: var(--#{$prefix}gray-400) !default;
|
||||
$border-active-opacity: 44.8% !default;
|
||||
$border-active-color-translucent: color-mix(in srgb, var(--#{$prefix}gray-800) #{$border-active-opacity}, transparent) !default;
|
||||
|
||||
$active-bg: color-transparent(var(--#{$prefix}primary), 0.04) !default;
|
||||
$active-color: var(--#{$prefix}primary) !default;
|
||||
$active-border-color: var(--#{$prefix}primary) !default;
|
||||
|
||||
$hover-bg: rgba(var(--#{$prefix}secondary-rgb), 0.08) !default;
|
||||
$hover-bg: color-transparent(var(--#{$prefix}secondary), 0.08) !default;
|
||||
|
||||
$disabled-bg: var(--#{$prefix}bg-surface-secondary) !default;
|
||||
$disabled-color: color-transparent(var(--#{$prefix}body-color), 0.4) !default;
|
||||
@@ -880,7 +878,7 @@ $avatar-sizes: (
|
||||
brand-size: 2rem,
|
||||
),
|
||||
) !default;
|
||||
$avatar-border-radius: var(--#{$prefix}border-radius) !default;
|
||||
$avatar-border-radius: var(--#{$prefix}border-radius-pill) !default;
|
||||
$avatar-font-size: $h4-font-size !default;
|
||||
$avatar-box-shadow: var(--#{$prefix}shadow-border) !default;
|
||||
$avatar-list-spacing: -0.5;
|
||||
@@ -988,14 +986,14 @@ $aspect-ratios: (
|
||||
) !default;
|
||||
|
||||
// Shadows
|
||||
$box-shadow: rgba(var(--#{$prefix}body-color-rgb), 0.04) 0 2px 4px 0 !default;
|
||||
$box-shadow: color-transparent(var(--#{$prefix}body-color), 0.04) 0 2px 4px 0 !default;
|
||||
$box-shadow-sm: 0 0.125rem 0.25rem rgba($black, 0.075) !default;
|
||||
$box-shadow-lg: 0 1rem 3rem rgba($black, 0.175) !default;
|
||||
$box-shadow-transparent: 0 0 0 0 transparent !default;
|
||||
$box-shadow-border: inset 0 0 0 1px var(--#{$prefix}border-color-translucent) !default;
|
||||
$box-shadow-input: 0 1px 1px rgba(var(--#{$prefix}body-color-rgb), 0.06) !default;
|
||||
$box-shadow-card: 0 0 4px rgba(var(--#{$prefix}body-color-rgb), 0.04) !default;
|
||||
$box-shadow-card-hover: rgba(var(--#{$prefix}body-color-rgb), 0.16) 0 2px 16px 0 !default;
|
||||
$box-shadow-input: 0 1px 1px color-transparent(var(--#{$prefix}body-color), 0.06) !default;
|
||||
$box-shadow-card: 0px 1px 3px rgba(0, 0, 0, 0.08) !default;
|
||||
$box-shadow-card-hover: color-transparent(var(--#{$prefix}body-color), 0.16) 0 2px 16px 0 !default;
|
||||
$box-shadow-dropdown:
|
||||
0 16px 24px 2px rgba(0, 0, 0, 0.07),
|
||||
0 6px 30px 5px rgba(0, 0, 0, 0.06),
|
||||
@@ -1020,7 +1018,7 @@ $component-active-bg: $primary !default;
|
||||
// Focus
|
||||
$focus-ring-width: 0.25rem !default;
|
||||
$focus-ring-opacity: 0.25 !default;
|
||||
$focus-ring-color: rgba(var(--#{$prefix}primary-rgb), $focus-ring-opacity) !default;
|
||||
$focus-ring-color: color-mix(in srgb, var(--#{$prefix}primary) #{percentage($focus-ring-opacity)}, transparent) !default;
|
||||
$focus-ring-blur: 0 !default;
|
||||
$focus-ring-box-shadow: 0 0 $focus-ring-blur $focus-ring-width $focus-ring-color !default;
|
||||
|
||||
@@ -1166,9 +1164,9 @@ $btn-padding-y-lg: $input-btn-padding-y-lg !default;
|
||||
$btn-padding-x-lg: $input-btn-padding-x-lg !default;
|
||||
|
||||
// Inputs
|
||||
$input-bg: var(--#{$prefix}body-bg) !default;
|
||||
$input-bg: var(--#{$prefix}bg-forms) !default;
|
||||
$input-disabled-color: null !default;
|
||||
$input-disabled-bg: var(--#{$prefix}secondary-bg) !default;
|
||||
$input-disabled-bg: var(--#{$prefix}bg-surface-secondary) !default;
|
||||
$input-disabled-border-color: null !default;
|
||||
|
||||
$input-height: null !default;
|
||||
@@ -1517,9 +1515,9 @@ $navbar-light-active-color: var(--#{$prefix}body-color) !default;
|
||||
$navbar-light-hover-color: var(--#{$prefix}body-color) !default;
|
||||
$navbar-light-disabled-color: var(--#{$prefix}disabled-color) !default;
|
||||
$navbar-light-active-bg: rgba(0, 0, 0, 0.2) !default;
|
||||
$navbar-light-icon-color: rgba($body-color, 0.75) !default;
|
||||
$navbar-light-icon-color: color-transparent(var(--#{$prefix}body-color), 0.75) !default;
|
||||
$navbar-light-toggler-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke='#{$navbar-light-icon-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
|
||||
$navbar-light-toggler-border-color: rgba(var(--#{$prefix}emphasis-color-rgb), 0.15) !default;
|
||||
$navbar-light-toggler-border-color: color-transparent(var(--#{$prefix}emphasis-color), 0.15) !default;
|
||||
$navbar-light-brand-hover-color: $navbar-light-active-color !default;
|
||||
|
||||
$navbar-dark-color: rgba($white, $text-secondary-opacity) !default;
|
||||
@@ -1694,7 +1692,7 @@ $table-active-bg: var(--#{$prefix}active-bg) !default;
|
||||
|
||||
$table-hover-color: $table-color !default;
|
||||
$table-hover-bg-factor: 0.075 !default;
|
||||
$table-hover-bg: rgba(var(--#{$prefix}emphasis-color-rgb), $table-hover-bg-factor) !default;
|
||||
$table-hover-bg: color-mix(in srgb, var(--#{$prefix}emphasis-color) #{percentage($table-hover-bg-factor)}, transparent) !default;
|
||||
|
||||
$table-caption-color: var(--#{$prefix}secondary-color) !default;
|
||||
|
||||
@@ -1729,7 +1727,7 @@ $toast-box-shadow: var(--#{$prefix}box-shadow) !default;
|
||||
$toast-spacing: $container-padding-x !default;
|
||||
|
||||
$toast-header-color: var(--#{$prefix}gray-500) !default;
|
||||
$toast-header-background-color: rgba(var(--#{$prefix}body-bg-rgb), 0.85) !default;
|
||||
$toast-header-background-color: color-transparent(var(--#{$prefix}body-bg), 0.85) !default;
|
||||
$toast-header-border-color: $toast-border-color !default;
|
||||
|
||||
// Tracking
|
||||
@@ -1774,8 +1772,6 @@ $list-group-action-active-color: var(--#{$prefix}body-color) !default;
|
||||
$list-group-action-active-bg: var(--#{$prefix}secondary-bg) !default;
|
||||
|
||||
// Forms
|
||||
|
||||
$input-bg: var(--#{$prefix}bg-forms) !default;
|
||||
$input-disabled-bg: $disabled-bg !default;
|
||||
$input-border-color: var(--#{$prefix}border-color) !default;
|
||||
$input-border-color-translucent: var(--#{$prefix}border-color-translucent) !default;
|
||||
@@ -1865,16 +1861,16 @@ $form-select-font-size-lg: $input-font-size-lg !default;
|
||||
$form-select-border-radius-lg: $input-border-radius-lg !default;
|
||||
$form-select-transition: $input-transition !default;
|
||||
|
||||
$form-switch-color: rgba($black, 0.25) !default;
|
||||
$form-switch-color: white !default;
|
||||
$form-switch-width: 2rem !default;
|
||||
$form-switch-height: 1.25rem !default;
|
||||
$form-switch-padding-start: $form-switch-width + 0.5rem !default;
|
||||
$form-switch-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$border-color}'/></svg>") !default;
|
||||
$form-switch-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-color}'/></svg>") !default;
|
||||
$form-switch-border-radius: $form-switch-width !default;
|
||||
$form-switch-transition: background-position 0.15s ease-in-out !default;
|
||||
$form-switch-focus-color: $input-focus-border-color !default;
|
||||
$form-switch-focus-color: white !default;
|
||||
$form-switch-focus-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-focus-color}'/></svg>") !default;
|
||||
$form-switch-checked-color: $component-active-color !default;
|
||||
$form-switch-checked-color: white !default;
|
||||
$form-switch-checked-bg-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$form-switch-checked-color}'/></svg>") !default;
|
||||
$form-switch-checked-bg-position: right center !default;
|
||||
$form-switch-bg-size: auto !default;
|
||||
@@ -1960,7 +1956,7 @@ $form-validation-states: (
|
||||
'icon': $form-feedback-icon-valid,
|
||||
'tooltip-color': #fff,
|
||||
'tooltip-bg-color': var(--#{$prefix}success),
|
||||
'focus-box-shadow': 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}success-rgb), $input-btn-focus-color-opacity),
|
||||
'focus-box-shadow': 0 0 $input-btn-focus-blur $input-focus-width color-mix(in srgb, var(--#{$prefix}success) #{percentage($input-btn-focus-color-opacity)}, transparent),
|
||||
'border-color': var(--#{$prefix}form-valid-border-color),
|
||||
),
|
||||
'invalid': (
|
||||
@@ -1968,7 +1964,7 @@ $form-validation-states: (
|
||||
'icon': $form-feedback-icon-invalid,
|
||||
'tooltip-color': #fff,
|
||||
'tooltip-bg-color': var(--#{$prefix}danger),
|
||||
'focus-box-shadow': 0 0 $input-btn-focus-blur $input-focus-width rgba(var(--#{$prefix}danger-rgb), $input-btn-focus-color-opacity),
|
||||
'focus-box-shadow': 0 0 $input-btn-focus-blur $input-focus-width color-mix(in srgb, var(--#{$prefix}danger) #{percentage($input-btn-focus-color-opacity)}, transparent),
|
||||
'border-color': var(--#{$prefix}form-invalid-border-color),
|
||||
),
|
||||
) !default;
|
||||
|
||||
@@ -1,184 +1,203 @@
|
||||
// Geist Sans Font Family
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-Thin.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Thin.ttf') format('truetype');
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Thin.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Thin.ttf') format('truetype');
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-UltraLight.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-UltraLight.ttf') format('truetype');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-UltraLight.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-UltraLight.ttf') format('truetype');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-Light.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Light.ttf') format('truetype');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Light.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Light.ttf') format('truetype');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-Regular.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Regular.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-Medium.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Medium.ttf') format('truetype');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Medium.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Medium.ttf') format('truetype');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-SemiBold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-SemiBold.ttf') format('truetype');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-SemiBold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-SemiBold.ttf') format('truetype');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-Bold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Bold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-Black.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Black.ttf') format('truetype');
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Black.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Black.ttf') format('truetype');
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-UltraBlack.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-UltraBlack.ttf') format('truetype');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-UltraBlack.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-UltraBlack.ttf') format('truetype');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
// Geist Sans Variable Font
|
||||
@font-face {
|
||||
font-family: 'Geist';
|
||||
src: url('#{$assets-base}/fonts/geist-sans/Geist-Variable.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Variable.ttf') format('truetype');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Variable.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-sans/Geist-Variable.ttf') format('truetype');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
// Geist Mono Font Family
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-Thin.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Thin.ttf') format('truetype');
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Thin.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Thin.ttf') format('truetype');
|
||||
font-weight: 100;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraLight.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraLight.ttf') format('truetype');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraLight.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraLight.ttf') format('truetype');
|
||||
font-weight: 200;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-Light.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Light.ttf') format('truetype');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Light.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Light.ttf') format('truetype');
|
||||
font-weight: 300;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-Regular.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Regular.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-Medium.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Medium.ttf') format('truetype');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Medium.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Medium.ttf') format('truetype');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-SemiBold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-SemiBold.ttf') format('truetype');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-SemiBold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-SemiBold.ttf') format('truetype');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-Bold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Bold.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-Black.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Black.ttf') format('truetype');
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Black.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Black.ttf') format('truetype');
|
||||
font-weight: 800;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraBlack.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraBlack.ttf') format('truetype');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraBlack.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-UltraBlack.ttf') format('truetype');
|
||||
font-weight: 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
// Geist Mono Variable Font
|
||||
@font-face {
|
||||
font-family: 'Geist Mono';
|
||||
src: url('#{$assets-base}/fonts/geist-mono/GeistMono-Variable.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Variable.ttf') format('truetype');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
font-family: 'Geist Mono';
|
||||
src:
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Variable.woff2') format('woff2'),
|
||||
url('#{$assets-base}/fonts/geist-mono/GeistMono-Variable.ttf') format('truetype');
|
||||
font-weight: 100 900;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
content: '';
|
||||
}
|
||||
|
||||
>* {
|
||||
> * {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
@@ -141,4 +141,4 @@
|
||||
outline: 0;
|
||||
// By default, there is no `--bs-focus-ring-x`, `--bs-focus-ring-y`, or `--bs-focus-ring-blur`, but we provide CSS variables with fallbacks to initial `0` values
|
||||
box-shadow: var(--#{$prefix}focus-ring-x, 0) var(--#{$prefix}focus-ring-y, 0) var(--#{$prefix}focus-ring-blur, 0) var(--#{$prefix}focus-ring-width) var(--#{$prefix}focus-ring-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
.nav-item.active:after {
|
||||
border-bottom-width: 0;
|
||||
border-inline-start-width: 3px;
|
||||
inset-inline-end: auto;
|
||||
inset-inline-end: auto;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
@@ -118,7 +118,7 @@ Navbar
|
||||
.badge {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
inset-inline-end: 0.5rem;
|
||||
inset-inline-end: 0.5rem;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
}
|
||||
@@ -151,8 +151,8 @@ Navbar
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: -0.25rem;
|
||||
border: 0 var(--#{$prefix}border-style) var(--#{$prefix}navbar-active-border-color);
|
||||
border-bottom-width: 2px;
|
||||
@@ -235,7 +235,7 @@ Navbar toggler
|
||||
border-radius: inherit;
|
||||
background: inherit;
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
@include transition(inherit);
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ Navbar vertical
|
||||
width: $sidebar-width;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
bottom: 0;
|
||||
z-index: $zindex-fixed;
|
||||
align-items: start;
|
||||
@@ -323,8 +323,8 @@ Navbar vertical
|
||||
|
||||
&.navbar-right,
|
||||
&.navbar-end {
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: 0;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
@@ -384,8 +384,8 @@ Navbar vertical
|
||||
height: $navbar-overlap-height;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
background: inherit;
|
||||
z-index: -1;
|
||||
box-shadow: inherit;
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
background-image: $overlay-gradient;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,10 @@
|
||||
--#{$prefix}border-color-translucent: #{$border-color-translucent};
|
||||
--#{$prefix}border-dark-color: #{$border-dark-color};
|
||||
--#{$prefix}border-dark-color-translucent: #{$border-dark-color-translucent};
|
||||
--#{$prefix}border-light-color: #{$border-light-color};
|
||||
--#{$prefix}border-light-color-translucent: #{$border-light-color-translucent};
|
||||
--#{$prefix}border-active-color: #{$border-active-color};
|
||||
--#{$prefix}border-active-color-translucent: #{$border-active-color-translucent};
|
||||
|
||||
--#{$prefix}icon-color: #{$icon-color};
|
||||
|
||||
|
||||
@@ -144,12 +144,12 @@
|
||||
// stylelint-disable scss/dollar-variable-pattern
|
||||
@function rgba-css-var($identifier, $target) {
|
||||
@if $identifier == 'body' and $target == 'bg' {
|
||||
@return rgba(var(--#{$prefix}#{$identifier}-bg-rgb), var(--#{$prefix}#{$target}-opacity));
|
||||
@return color-mix(in srgb, var(--#{$prefix}#{$identifier}-bg) calc(var(--#{$prefix}#{$target}-opacity) * 100%), transparent);
|
||||
}
|
||||
@if $identifier == 'body' and $target == 'text' {
|
||||
@return rgba(var(--#{$prefix}#{$identifier}-color-rgb), var(--#{$prefix}#{$target}-opacity));
|
||||
@return color-mix(in srgb, var(--#{$prefix}#{$identifier}-color) calc(var(--#{$prefix}#{$target}-opacity) * 100%), transparent);
|
||||
} @else {
|
||||
@return rgba(var(--#{$prefix}#{$identifier}-rgb), var(--#{$prefix}#{$target}-opacity));
|
||||
@return color-mix(in srgb, var(--#{$prefix}#{$identifier}) calc(var(--#{$prefix}#{$target}-opacity) * 100%), transparent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,10 +59,10 @@
|
||||
|
||||
@mixin focus-ring($show-border: false) {
|
||||
outline: 0;
|
||||
box-shadow: 0 0 $focus-ring-blur $focus-ring-width rgba(var(--#{$prefix}primary-rgb), 0.25);
|
||||
box-shadow: 0 0 $focus-ring-blur $focus-ring-width color-transparent(var(--#{$prefix}primary), 0.25);
|
||||
|
||||
@if ($show-border) {
|
||||
border-color: rgba(var(--#{$prefix}primary-rgb), 0.25);
|
||||
border-color: color-transparent(var(--#{$prefix}primary), 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,17 +15,17 @@
|
||||
}
|
||||
|
||||
[data-bs-theme-base='gray'] {
|
||||
--#{$prefix}gray-50: #f9fafb;
|
||||
--#{$prefix}gray-100: #f3f4f6;
|
||||
--#{$prefix}gray-200: #e5e7eb;
|
||||
--#{$prefix}gray-300: #d1d5db;
|
||||
--#{$prefix}gray-400: #9ca3af;
|
||||
--#{$prefix}gray-500: #6b7280;
|
||||
--#{$prefix}gray-600: #4b5563;
|
||||
--#{$prefix}gray-700: #374151;
|
||||
--#{$prefix}gray-800: #1f2937;
|
||||
--#{$prefix}gray-900: #111827;
|
||||
--#{$prefix}gray-950: #030712;
|
||||
--#{$prefix}gray-50: $gray-50;
|
||||
--#{$prefix}gray-100: $gray-100;
|
||||
--#{$prefix}gray-200: $gray-200;
|
||||
--#{$prefix}gray-300: $gray-300;
|
||||
--#{$prefix}gray-400: $gray-400;
|
||||
--#{$prefix}gray-500: $gray-500;
|
||||
--#{$prefix}gray-600: $gray-600;
|
||||
--#{$prefix}gray-700: $gray-700;
|
||||
--#{$prefix}gray-800: $gray-800;
|
||||
--#{$prefix}gray-900: $gray-900;
|
||||
--#{$prefix}gray-950: $gray-950;
|
||||
}
|
||||
|
||||
[data-bs-theme-base='zinc'] {
|
||||
|
||||
@@ -14,3 +14,4 @@
|
||||
@import 'vendor/typed';
|
||||
@import 'vendor/turbo';
|
||||
@import 'vendor/fullcalendar';
|
||||
@import 'vendor/shiki';
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
.alert {
|
||||
--#{$prefix}alert-color: var(--#{$prefix}body-color);
|
||||
--#{$prefix}alert-bg: #{color-transparent(var(--#{$prefix}alert-color), 0.1)};
|
||||
--#{$prefix}alert-variant-color: var(--#{$prefix}body-color);
|
||||
--#{$prefix}alert-color: var(--#{$prefix}alert-variant-color);
|
||||
--#{$prefix}alert-bg: #{color-transparent(var(--#{$prefix}alert-variant-color), 0.16, var(--#{$prefix}bg-surface))};
|
||||
--#{$prefix}alert-padding-x: #{$alert-padding-x};
|
||||
--#{$prefix}alert-padding-y: #{$alert-padding-y};
|
||||
--#{$prefix}alert-margin-bottom: #{$alert-margin-bottom};
|
||||
--#{$prefix}alert-border-color: #{color-transparent(var(--#{$prefix}alert-color), 0.2)};
|
||||
--#{$prefix}alert-border-color: #{color-transparent(var(--#{$prefix}alert-variant-color), 0.2, var(--#{$prefix}bg-surface))};
|
||||
--#{$prefix}alert-border-color: var(--#{$prefix}border-color);
|
||||
--#{$prefix}alert-border: var(--#{$prefix}border-width) solid var(--#{$prefix}alert-border-color);
|
||||
--#{$prefix}alert-border-radius: var(--#{$prefix}border-radius);
|
||||
--#{$prefix}alert-link-color: inherit;
|
||||
@@ -16,6 +18,8 @@
|
||||
background-color: color-mix(in srgb, var(--#{$prefix}alert-bg), var(--#{$prefix}bg-surface));
|
||||
border-radius: var(--#{$prefix}alert-border-radius);
|
||||
border: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}alert-border-color);
|
||||
box-shadow: var(--#{$prefix}box-shadow);
|
||||
color: var(--#{$prefix}alert-color);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
@@ -66,15 +70,14 @@
|
||||
.btn-close {
|
||||
position: absolute;
|
||||
top: calc(var(--#{$prefix}alert-padding-x) / 2 - 1px);
|
||||
inset-inline-end: calc(var(--#{$prefix}alert-padding-y) / 2 - 1px);
|
||||
inset-inline-end: calc(var(--#{$prefix}alert-padding-y) / 2 - 1px);
|
||||
z-index: 1;
|
||||
padding: calc(var(--#{$prefix}alert-padding-y) * 1.25) var(--#{$prefix}alert-padding-x);
|
||||
}
|
||||
}
|
||||
|
||||
.alert-important {
|
||||
border-color: var(--#{$prefix}alert-color);
|
||||
background-color: var(--#{$prefix}alert-color);
|
||||
background-color: var(--#{$prefix}alert-variant-color);
|
||||
color: var(--#{$prefix}white);
|
||||
|
||||
.alert-description {
|
||||
@@ -93,6 +96,6 @@
|
||||
|
||||
@each $name, $color in $theme-colors {
|
||||
.alert-#{$name} {
|
||||
--#{$prefix}alert-color: var(--#{$prefix}#{$name});
|
||||
--#{$prefix}alert-variant-color: var(--#{$prefix}#{$name});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
--#{$prefix}avatar-font-size: #{$avatar-font-size};
|
||||
--#{$prefix}avatar-icon-size: #{$avatar-icon-size};
|
||||
--#{$prefix}avatar-brand-size: #{$avatar-brand-size};
|
||||
--#{$prefix}avatar-border-radius: #{$avatar-border-radius};
|
||||
position: relative;
|
||||
width: var(--#{$prefix}avatar-size);
|
||||
height: var(--#{$prefix}avatar-size);
|
||||
@@ -24,7 +25,7 @@
|
||||
vertical-align: bottom;
|
||||
user-select: none;
|
||||
background: var(--#{$prefix}avatar-bg) no-repeat center/cover;
|
||||
border-radius: $avatar-border-radius;
|
||||
border-radius: var(--#{$prefix}avatar-border-radius);
|
||||
box-shadow: var(--#{$prefix}avatar-box-shadow);
|
||||
transition:
|
||||
color $transition-time,
|
||||
@@ -38,7 +39,7 @@
|
||||
|
||||
.badge {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
border-radius: $border-radius-pill;
|
||||
box-shadow: 0 0 0 calc(var(--#{$prefix}avatar-status-size) / 4) $card-bg;
|
||||
@@ -58,6 +59,10 @@
|
||||
border-radius: $border-radius-pill;
|
||||
}
|
||||
|
||||
.avatar-square {
|
||||
border-radius: var(--#{$prefix}border-radius);
|
||||
}
|
||||
|
||||
@each $avatar-size, $size in $avatar-sizes {
|
||||
.avatar-#{$avatar-size} {
|
||||
--#{$prefix}avatar-size: #{map.get($size, size)};
|
||||
@@ -66,14 +71,14 @@
|
||||
--#{$prefix}avatar-icon-size: #{map.get($size, icon-size)};
|
||||
--#{$prefix}avatar-brand-size: #{map.get($size, brand-size)};
|
||||
|
||||
@if map.has-key($size, border-radius) {
|
||||
border-radius: map.get($size, border-radius);
|
||||
}
|
||||
|
||||
.badge:empty {
|
||||
width: map.get($size, status-size);
|
||||
height: map.get($size, status-size);
|
||||
}
|
||||
|
||||
&.avatar-square {
|
||||
--#{$prefix}avatar-border-radius: #{map.get($size, border-radius)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,10 +101,13 @@
|
||||
--#{$prefix}list-gap: 0;
|
||||
|
||||
.avatar {
|
||||
margin-inline-end: calc(#{$avatar-list-spacing} * var(--#{$prefix}avatar-size)) !important;
|
||||
box-shadow:
|
||||
var(--#{$prefix}avatar-box-shadow),
|
||||
0 0 0 2px var(--#{$prefix}card-bg, var(--#{$prefix}bg-surface));
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-inline-start: calc(#{$avatar-list-spacing} * var(--#{$prefix}avatar-size)) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,15 @@
|
||||
//
|
||||
// Button color variations
|
||||
//
|
||||
.btn-ghost {
|
||||
--#{$prefix}btn-bg: transparent;
|
||||
--#{$prefix}btn-border-color: transparent;
|
||||
--#{$prefix}btn-box-shadow: none;
|
||||
--#{$prefix}btn-hover-bg: var(--#{$prefix}bg-surface-secondary);
|
||||
--#{$prefix}btn-hover-border-color: transparent;
|
||||
--#{$prefix}btn-hover-color: var(--#{$prefix}body-color);
|
||||
}
|
||||
|
||||
@each $color, $value in map.merge($theme-colors, $social-colors) {
|
||||
.btn-#{$color} {
|
||||
@if $color == 'dark' {
|
||||
@@ -114,15 +123,6 @@
|
||||
--#{$prefix}btn-disabled-border-color: var(--#{$prefix}#{$color});
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
--#{$prefix}btn-bg: transparent;
|
||||
--#{$prefix}btn-border-color: transparent;
|
||||
--#{$prefix}btn-box-shadow: none;
|
||||
--#{$prefix}btn-hover-bg: var(--#{$prefix}bg-surface-secondary);
|
||||
--#{$prefix}btn-hover-border-color: transparent;
|
||||
--#{$prefix}btn-hover-color: var(--#{$prefix}body-color);
|
||||
}
|
||||
|
||||
.btn-ghost-#{$color},
|
||||
.btn-ghost.btn-#{$color} {
|
||||
--#{$prefix}btn-color: var(--#{$prefix}#{$color});
|
||||
@@ -250,7 +250,7 @@
|
||||
position: absolute;
|
||||
width: var(--#{$prefix}btn-icon-size);
|
||||
height: var(--#{$prefix}btn-icon-size);
|
||||
inset-inline-start: calc(50% - var(--#{$prefix}btn-icon-size) / 2);
|
||||
inset-inline-start: calc(50% - var(--#{$prefix}btn-icon-size) / 2);
|
||||
top: calc(50% - var(--#{$prefix}btn-icon-size) / 2);
|
||||
animation: spinner-border 0.75s linear infinite;
|
||||
}
|
||||
|
||||
@@ -77,11 +77,11 @@
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
height: 1.4rem;
|
||||
content: '';
|
||||
background: rgba(var(--#{$prefix}primary-rgb), 0.1);
|
||||
background: color-transparent(var(--#{$prefix}primary), 0.1);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
@@ -95,10 +95,10 @@
|
||||
}
|
||||
|
||||
&.range-start:before {
|
||||
inset-inline-start: 50%;
|
||||
inset-inline-start: 50%;
|
||||
}
|
||||
|
||||
&.range-end:before {
|
||||
inset-inline-end: 50%;
|
||||
inset-inline-end: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
|
||||
// Card borderless
|
||||
.card-borderless {
|
||||
|
||||
&,
|
||||
.card-header,
|
||||
.card-footer {
|
||||
@@ -48,6 +47,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Card dashed
|
||||
.card-dashed {
|
||||
border: var(--#{$prefix}border-width) dashed var(--#{$prefix}border-color);
|
||||
}
|
||||
|
||||
// Card transparent
|
||||
.card-transparent {
|
||||
background: transparent;
|
||||
border: var(--#{$prefix}border-width) dashed var(--#{$prefix}border-color);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
// Card stamp
|
||||
.card-stamp {
|
||||
--#{$prefix}stamp-size: 7rem;
|
||||
@@ -141,7 +152,7 @@
|
||||
background: $active-bg;
|
||||
}
|
||||
|
||||
&+& {
|
||||
& + & {
|
||||
border-inline-start: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color);
|
||||
}
|
||||
}
|
||||
@@ -340,17 +351,17 @@ Stacked card
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.card-sm>& {
|
||||
.card-sm > & {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.card-md>& {
|
||||
.card-md > & {
|
||||
@include media-breakpoint-up(md) {
|
||||
padding: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.card-lg>& {
|
||||
.card-lg > & {
|
||||
@include media-breakpoint-up(md) {
|
||||
padding: 2rem;
|
||||
}
|
||||
@@ -364,7 +375,7 @@ Stacked card
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&+& {
|
||||
& + & {
|
||||
border-top: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color);
|
||||
}
|
||||
}
|
||||
@@ -427,7 +438,6 @@ Card table
|
||||
margin-bottom: 0 !important;
|
||||
|
||||
tr {
|
||||
|
||||
td,
|
||||
th {
|
||||
&:first-child {
|
||||
@@ -456,11 +466,11 @@ Card table
|
||||
tfoot {
|
||||
&:last-child {
|
||||
tr:last-child {
|
||||
>*:last-child {
|
||||
> *:last-child {
|
||||
border-end-end-radius: calc(var(--#{$prefix}card-border-radius) - var(--#{$prefix}card-border-width));
|
||||
}
|
||||
|
||||
>*:first-child {
|
||||
> *:first-child {
|
||||
border-end-start-radius: calc(var(--#{$prefix}card-border-radius) - var(--#{$prefix}card-border-width));
|
||||
}
|
||||
}
|
||||
@@ -496,7 +506,7 @@ Card table
|
||||
}
|
||||
}
|
||||
|
||||
.card-body+& {
|
||||
.card-body + & {
|
||||
border-top: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}table-border-color);
|
||||
}
|
||||
}
|
||||
@@ -541,7 +551,7 @@ Card avatar
|
||||
Card list group
|
||||
*/
|
||||
.card-list-group {
|
||||
.card-body+& {
|
||||
.card-body + & {
|
||||
border-top: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color);
|
||||
}
|
||||
|
||||
@@ -600,7 +610,7 @@ Card list group
|
||||
}
|
||||
}
|
||||
|
||||
+.nav-item {
|
||||
+ .nav-item {
|
||||
margin-inline-start: calc(-1 * #{$card-border-width});
|
||||
}
|
||||
}
|
||||
@@ -640,7 +650,7 @@ Card list group
|
||||
border-end-start-radius: 0;
|
||||
}
|
||||
|
||||
.nav-tabs+.tab-content .card {
|
||||
.nav-tabs + .tab-content .card {
|
||||
border-end-start-radius: var(--#{$prefix}card-border-radius);
|
||||
border-start-start-radius: 0;
|
||||
}
|
||||
@@ -654,7 +664,6 @@ Card note
|
||||
--#{$prefix}card-border-color: #fff1c9;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Card gradient
|
||||
*/
|
||||
@@ -663,10 +672,10 @@ Card gradient
|
||||
--#{$prefix}card-gradient-opacity: 86%;
|
||||
--#{$prefix}card-gradient: var(--tblr-primary), var(--tblr-primary);
|
||||
|
||||
background: radial-gradient(ellipse at center, var(--#{$prefix}card-bg) 0%, color-mix(in srgb, var(--#{$prefix}card-bg) 0%, transparent) 80%) border-box,
|
||||
linear-gradient(var(--#{$prefix}card-gradient-direction), color-mix(in srgb, var(--#{$prefix}card-bg) var(--#{$prefix}card-gradient-opacity), transparent) 0%, var(--#{$prefix}card-bg) 40%) border-box,
|
||||
linear-gradient(calc(270deg + var(--#{$prefix}card-gradient-direction)), var(--#{$prefix}card-gradient)) border-box;
|
||||
|
||||
background:
|
||||
radial-gradient(ellipse at center, var(--#{$prefix}card-bg) 0%, color-mix(in srgb, var(--#{$prefix}card-bg) 0%, transparent) 80%) border-box,
|
||||
linear-gradient(var(--#{$prefix}card-gradient-direction), color-mix(in srgb, var(--#{$prefix}card-bg) var(--#{$prefix}card-gradient-opacity), transparent) 0%, var(--#{$prefix}card-bg) 40%) border-box,
|
||||
linear-gradient(calc(270deg + var(--#{$prefix}card-gradient-direction)), var(--#{$prefix}card-gradient)) border-box;
|
||||
}
|
||||
|
||||
@each $name, $color in map.merge($colors, $theme-colors) {
|
||||
@@ -676,14 +685,7 @@ Card gradient
|
||||
}
|
||||
|
||||
.card-gradient-rainbow {
|
||||
--#{$prefix}card-gradient: #78C5D6,
|
||||
#459BA8,
|
||||
#79C267,
|
||||
#C5D647,
|
||||
#F5D63D,
|
||||
#F08B33,
|
||||
#E868A2,
|
||||
#BE61A5;
|
||||
--#{$prefix}card-gradient: #78c5d6, #459ba8, #79c267, #c5d647, #f5d63d, #f08b33, #e868a2, #be61a5;
|
||||
}
|
||||
|
||||
.card-gradient-sun {
|
||||
@@ -695,7 +697,7 @@ Card gradient
|
||||
}
|
||||
|
||||
.card-gradient-ocean {
|
||||
--#{$prefix}card-gradient: #1CB5E0, #000851;
|
||||
--#{$prefix}card-gradient: #1cb5e0, #000851;
|
||||
}
|
||||
|
||||
.card-gradient-mellow {
|
||||
@@ -703,7 +705,7 @@ Card gradient
|
||||
}
|
||||
|
||||
.card-gradient-disco {
|
||||
--#{$prefix}card-gradient: #FC466B, #3F5EFB;
|
||||
--#{$prefix}card-gradient: #fc466b, #3f5efb;
|
||||
}
|
||||
|
||||
.card-gradient-psychedelic {
|
||||
@@ -715,7 +717,7 @@ Card gradient
|
||||
}
|
||||
|
||||
.card-gradient-gold {
|
||||
--#{$prefix}card-gradient: #9d4100, #bf7122, #f59f00, #FFD700;
|
||||
--#{$prefix}card-gradient: #9d4100, #bf7122, #f59f00, #ffd700;
|
||||
}
|
||||
|
||||
.card-gradient-animated {
|
||||
@@ -732,4 +734,4 @@ Card gradient
|
||||
|
||||
.card-gradient-start {
|
||||
--#{$prefix}card-gradient-direction: 90deg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -0.25rem;
|
||||
inset-inline-start: 0.75rem;
|
||||
inset-inline-start: 0.75rem;
|
||||
display: block;
|
||||
background: inherit;
|
||||
width: 14px;
|
||||
@@ -90,8 +90,8 @@
|
||||
|
||||
&.dropdown-menu-end {
|
||||
&:before {
|
||||
inset-inline-end: 0.75rem;
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: 0.75rem;
|
||||
inset-inline-start: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: '';
|
||||
@@ -33,8 +33,8 @@ Dimmer
|
||||
.loader {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
display: none;
|
||||
margin: 0 auto;
|
||||
transform: translateY(-50%);
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
$markdown-font-size: var(--#{$prefix}font-size-h3) !default;
|
||||
$markdown-line-height: var(--#{$prefix}line-height-lg) !default;
|
||||
|
||||
/**
|
||||
Markdown
|
||||
*/
|
||||
.markdown {
|
||||
line-height: $line-height-xl;
|
||||
line-height: $markdown-line-height;
|
||||
font-size: $markdown-font-size;
|
||||
|
||||
> :first-child {
|
||||
margin-top: 0;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
> .btn-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-end: 0;
|
||||
width: $modal-header-height;
|
||||
height: $modal-header-height;
|
||||
margin: 0;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
@keyframes progress-indeterminate {
|
||||
0% {
|
||||
inset-inline-end: 100%;
|
||||
inset-inline-start: -35%;
|
||||
inset-inline-end: 100%;
|
||||
inset-inline-start: -35%;
|
||||
}
|
||||
|
||||
100%,
|
||||
60% {
|
||||
inset-inline-end: -90%;
|
||||
inset-inline-start: 100%;
|
||||
inset-inline-end: -90%;
|
||||
inset-inline-start: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ Progress bar
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
content: '';
|
||||
background-color: inherit;
|
||||
will-change: left, right;
|
||||
@@ -93,6 +93,8 @@ Progressbg
|
||||
.progressbg-text {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@include text-truncate;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 100%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
|
||||
&.bg-#{$color}-lt {
|
||||
border-color: rgba(var(--#{$prefix}#{$color}-rgb), 0.1) !important;
|
||||
border-color: color-transparent(var(--#{$prefix}#{$color}), 0.1) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
&:before {
|
||||
top: 0;
|
||||
inset-inline-end: 100%;
|
||||
inset-inline-end: 100%;
|
||||
bottom: auto;
|
||||
border-color: inherit;
|
||||
border-top-color: transparent;
|
||||
@@ -73,13 +73,13 @@
|
||||
}
|
||||
|
||||
&.ribbon-start {
|
||||
inset-inline-end: auto;
|
||||
inset-inline-start: 0.75rem;
|
||||
inset-inline-end: auto;
|
||||
inset-inline-start: 0.75rem;
|
||||
|
||||
&:before {
|
||||
top: 0;
|
||||
inset-inline-end: 100%;
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: 100%;
|
||||
inset-inline-start: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@
|
||||
&:before {
|
||||
top: auto;
|
||||
bottom: 100%;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
border-color: inherit;
|
||||
border-top-color: transparent;
|
||||
border-inline-start-color: transparent;
|
||||
@@ -111,7 +111,7 @@
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-end: 100%;
|
||||
inset-inline-end: 100%;
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
@@ -127,8 +127,8 @@
|
||||
padding-inline-end: 0.5rem;
|
||||
|
||||
&:after {
|
||||
inset-inline-end: auto;
|
||||
inset-inline-start: 100%;
|
||||
inset-inline-end: auto;
|
||||
inset-inline-start: 100%;
|
||||
border-inline-end-color: transparent;
|
||||
|
||||
border-inline-end-width: 0.5rem;
|
||||
@@ -144,8 +144,8 @@
|
||||
|
||||
&:after {
|
||||
top: 100%;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: 0;
|
||||
border-color: inherit;
|
||||
border-width: 1rem;
|
||||
border-top-width: 0;
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
padding: 0.25rem 0.75rem;
|
||||
gap: 0.5rem;
|
||||
color: var(--#{$prefix}status-color);
|
||||
background: rgba(var(--#{$prefix}status-color-rgb), 0.1);
|
||||
background: color-transparent(var(--#{$prefix}status-color), 0.1);
|
||||
font-size: $font-size-base;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
&:not(:last-child):after {
|
||||
position: absolute;
|
||||
inset-inline-start: 50%;
|
||||
inset-inline-start: 50%;
|
||||
width: 100%;
|
||||
content: '';
|
||||
transform: translateY(-50%);
|
||||
@@ -67,7 +67,7 @@
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 50%;
|
||||
inset-inline-start: 50%;
|
||||
z-index: 1;
|
||||
box-sizing: content-box;
|
||||
display: flex;
|
||||
@@ -137,7 +137,7 @@
|
||||
|
||||
&:before {
|
||||
top: var(--#{$prefix}steps-dot-offset);
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
content: '';
|
||||
transform: translateX(-50%);
|
||||
top: var(--#{$prefix}steps-dot-offset);
|
||||
inset-inline-start: calc(var(--#{$prefix}steps-dot-size) * 0.5);
|
||||
inset-inline-start: calc(var(--#{$prefix}steps-dot-size) * 0.5);
|
||||
width: var(--#{$prefix}steps-border-width);
|
||||
height: calc(100% + 1rem);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
.switch-icon-b {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: var(--#{$prefix}timeline-icon-size);
|
||||
inset-inline-start: calc(var(--#{$prefix}timeline-icon-size) / 2);
|
||||
inset-inline-start: calc(var(--#{$prefix}timeline-icon-size) / 2);
|
||||
bottom: calc(-1 * var(--#{$prefix}page-padding));
|
||||
width: var(--#{$prefix}border-width);
|
||||
background-color: var(--#{$prefix}border-color);
|
||||
|
||||
@@ -82,4 +82,4 @@ Form switch
|
||||
.form-check-label {
|
||||
padding-top: 0.125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ Color Input
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: '';
|
||||
|
||||
@@ -31,7 +31,7 @@ Icon input
|
||||
font-size: 1.2em;
|
||||
|
||||
&:last-child {
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: 0;
|
||||
inset-inline-start: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ Image check
|
||||
&:before {
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
inset-inline-start: 0.25rem;
|
||||
inset-inline-start: 0.25rem;
|
||||
z-index: 1;
|
||||
display: block;
|
||||
width: $form-check-input-width;
|
||||
|
||||
4
core/scss/vendor/_coloris.scss
vendored
4
core/scss/vendor/_coloris.scss
vendored
@@ -53,8 +53,8 @@ input.clr-color {
|
||||
button {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
inset-inline-start: 6px;
|
||||
inset-inline-end: auto;
|
||||
inset-inline-start: 6px;
|
||||
inset-inline-end: auto;
|
||||
border-radius: var(--#{$prefix}border-radius);
|
||||
|
||||
&:after {
|
||||
|
||||
2
core/scss/vendor/_dropzone.scss
vendored
2
core/scss/vendor/_dropzone.scss
vendored
@@ -5,7 +5,7 @@
|
||||
|
||||
&.dz-drag-hover {
|
||||
border: var(--#{$prefix}border-width) dashed var(--#{$prefix}primary);
|
||||
background: rgba(var(--#{$prefix}primary-rgb), 0.01);
|
||||
background: color-transparent(var(--#{$prefix}primary), 0.01);
|
||||
color: var(--#{$prefix}primary);
|
||||
|
||||
.dz-message {
|
||||
|
||||
47
core/scss/vendor/_shiki.scss
vendored
Normal file
47
core/scss/vendor/_shiki.scss
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
:root {
|
||||
--shiki-foreground: var(--#{$prefix}light);
|
||||
--shiki-background: var(--#{$prefix}bg-surface-dark);
|
||||
|
||||
--shiki-token-constant: #79b8ff;
|
||||
--shiki-token-string: #9ecbff;
|
||||
--shiki-token-comment: #6a737d;
|
||||
--shiki-token-keyword: #f97583;
|
||||
--shiki-token-parameter: #e1e4e8;
|
||||
--shiki-token-function: #b392f0;
|
||||
--shiki-token-string-expression: #79b8ff;
|
||||
--shiki-token-punctuation: #9ecbff;
|
||||
--shiki-token-link: #79b8ff;
|
||||
|
||||
--shiki-ansi-black: #000000;
|
||||
--shiki-ansi-black-dim: #00000080;
|
||||
--shiki-ansi-red: #bb0000;
|
||||
--shiki-ansi-red-dim: #bb000080;
|
||||
--shiki-ansi-green: #00bb00;
|
||||
--shiki-ansi-green-dim: #00bb0080;
|
||||
--shiki-ansi-yellow: #bbbb00;
|
||||
--shiki-ansi-yellow-dim: #bbbb0080;
|
||||
--shiki-ansi-blue: #0000bb;
|
||||
--shiki-ansi-blue-dim: #0000bb80;
|
||||
--shiki-ansi-magenta: #ff00ff;
|
||||
--shiki-ansi-magenta-dim: #ff00ff80;
|
||||
--shiki-ansi-cyan: #00bbbb;
|
||||
--shiki-ansi-cyan-dim: #00bbbb80;
|
||||
--shiki-ansi-white: #eeeeee;
|
||||
--shiki-ansi-white-dim: #eeeeee80;
|
||||
--shiki-ansi-bright-black: #555555;
|
||||
--shiki-ansi-bright-black-dim: #55555580;
|
||||
--shiki-ansi-bright-red: #ff5555;
|
||||
--shiki-ansi-bright-red-dim: #ff555580;
|
||||
--shiki-ansi-bright-green: #00ff00;
|
||||
--shiki-ansi-bright-green-dim: #00ff0080;
|
||||
--shiki-ansi-bright-yellow: #ffff55;
|
||||
--shiki-ansi-bright-yellow-dim: #ffff5580;
|
||||
--shiki-ansi-bright-blue: #5555ff;
|
||||
--shiki-ansi-bright-blue-dim: #5555ff80;
|
||||
--shiki-ansi-bright-magenta: #ff55ff;
|
||||
--shiki-ansi-bright-magenta-dim: #ff55ff80;
|
||||
--shiki-ansi-bright-cyan: #55ffff;
|
||||
--shiki-ansi-bright-cyan-dim: #55ffff80;
|
||||
--shiki-ansi-bright-white: #ffffff;
|
||||
--shiki-ansi-bright-white-dim: #ffffff80;
|
||||
}
|
||||
30
core/tsconfig.json
Normal file
30
core/tsconfig.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2015",
|
||||
"module": "ES2020",
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"moduleResolution": "bundler",
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": false,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"declaration": false,
|
||||
"declarationMap": false,
|
||||
"sourceMap": true,
|
||||
"allowJs": true
|
||||
},
|
||||
"include": [
|
||||
"js/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import path from 'node:path'
|
||||
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 dotenv from "rollup-plugin-dotenv"
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const external = []
|
||||
const plugins = [
|
||||
dotenv({
|
||||
cwd: path.resolve(__dirname, '../..'),
|
||||
}),
|
||||
babel({
|
||||
exclude: 'node_modules/**',
|
||||
babelHelpers: 'bundled'
|
||||
}),
|
||||
replace({
|
||||
'process.env.NODE_ENV': '"production"',
|
||||
preventAssignment: true
|
||||
}),
|
||||
nodeResolve()
|
||||
]
|
||||
|
||||
const rollupConfig = {
|
||||
input: [
|
||||
path.resolve(__dirname, `../js/docs.js`)
|
||||
],
|
||||
output: {
|
||||
name: 'docs',
|
||||
dir: path.resolve(__dirname, `../dist/js`),
|
||||
format: 'esm',
|
||||
generatedCode: 'es2015'
|
||||
},
|
||||
external,
|
||||
plugins
|
||||
}
|
||||
|
||||
export default rollupConfig
|
||||
20
docs/.build/vite.config.mts
Normal file
20
docs/.build/vite.config.mts
Normal file
@@ -0,0 +1,20 @@
|
||||
import path from 'node:path'
|
||||
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 entryPath = path.resolve(__dirname, '../js/docs')
|
||||
const entry = `${entryPath}.ts`
|
||||
|
||||
export default createViteConfig({
|
||||
entry: entry,
|
||||
name: 'docs',
|
||||
fileName: () => 'docs.js',
|
||||
formats: ['es'],
|
||||
outDir: path.resolve(__dirname, '../dist/js'),
|
||||
banner: undefined,
|
||||
minify: false
|
||||
})
|
||||
|
||||
@@ -5,9 +5,12 @@ order: 2
|
||||
description: Over 5000 pixel-perfect icons for web design and development
|
||||
---
|
||||
|
||||
## Browse icons
|
||||
# Browse icons
|
||||
|
||||
Tabler Icons is a comprehensive icon library that features {{ iconsCount }} high-quality icons. These icons are designed with a clean and modern aesthetic, making them suitable for a wide range of applications.
|
||||
Tabler Icons is a comprehensive icon library that features {{ iconsCount }} high-quality icons.
|
||||
These icons are designed with a clean and modern aesthetic, making them suitable for a wide range of applications.
|
||||
|
||||
To use Tabler Icons, you can visit their website at https://tabler-icons.io. From there, you can browse the full collection of icons by category or search for a specific icon using the search bar. Once you have found an icon you like, you can download it in various file formats, including SVG, PNG, and Icon Font.
|
||||
To use Tabler Icons, you can visit their website at https://tabler-icons.io.
|
||||
From there, you can browse the full collection of icons by category or search for a specific icon using the search bar.
|
||||
|
||||
Once you have found an icon you like, you can download it in various file formats, including SVG, PNG, and Icon Font.
|
||||
|
||||
@@ -5,7 +5,6 @@ description: Download Tabler Icons in EPS format.
|
||||
|
||||

|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
{% include "docs/tabs-package.html" name="@tabler/icons-eps" %}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user