mirror of
https://github.com/tabler/tabler.git
synced 2026-08-29 13:21:29 +04:00
Add screenshots package and fix card-gradient minify bug (#2793)
Co-authored-by: Bartek <xbartoszdobija@gmail.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
---
|
||||
// .bg-pattern-{type} utility (core/scss/ui/_patterns.scss) as a component;
|
||||
// combine with a theme color and/or size, e.g. <BackgroundPattern pattern="dots" color="primary" size="lg" />.
|
||||
|
||||
interface Props {
|
||||
pattern: 'diagonal' | 'diagonal-2' | 'dots' | 'rectangles' | 'lines' | 'lines-vertical' | 'grid' | 'grid-diagonal' | 'blueprint' | 'cross-dots' | 'circles' | 'diagonal-stripes' | 'diagonal-stripes-2' | 'zigzag' | 'vertical-stripes' | 'horizontal-stripes'
|
||||
/** theme color the pattern ramps up to, e.g. 'primary' */
|
||||
color?: string
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl'
|
||||
/** element to render instead of div */
|
||||
as?: string
|
||||
class?: string
|
||||
/** remaining attributes (style, data-*, …) are forwarded to the element */
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const { pattern, color, size, as: Element = 'div', class: className, ...rest } = Astro.props
|
||||
---
|
||||
|
||||
<Element class:list={[`bg-pattern-${pattern}`, color && `bg-pattern-${color}`, size && `bg-pattern-${size}`, className]} {...rest}>
|
||||
<slot />
|
||||
</Element>
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
// Self-contained carousel (.carousel). Default slot holds the .carousel-item elements
|
||||
// (the caller marks the first one "active" — see CarouselCard.astro / hero/Side.astro);
|
||||
// indicators/controls are generated from props. A "controls" slot overrides the default
|
||||
// icon-span controls with custom markup (e.g. an <Icon>-based pair).
|
||||
|
||||
interface Props {
|
||||
id?: string
|
||||
/** slide count, used to generate indicator buttons */
|
||||
slideCount: number
|
||||
fade?: boolean
|
||||
/** data-bs-interval in ms, or false to disable autoplay */
|
||||
interval?: number | false
|
||||
indicators?: boolean
|
||||
indicatorsVariant?: 'dot' | 'thumb'
|
||||
indicatorsVertical?: boolean
|
||||
/** ratio ratio-4x3 on each indicator button, typically paired with indicatorsVariant="thumb" */
|
||||
indicatorsThumbRatio?: boolean
|
||||
/** background-image per slide, used when indicatorsVariant="thumb" */
|
||||
indicatorsImages?: string[]
|
||||
controls?: boolean
|
||||
class?: string
|
||||
/** remaining attributes forwarded to the element */
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
const { id, slideCount, fade, interval, indicators, indicatorsVariant, indicatorsVertical, indicatorsThumbRatio, indicatorsImages, controls, class: className, ...rest } = Astro.props
|
||||
|
||||
const target = id ? `#${id}` : undefined
|
||||
const slideIndexes = Array.from({ length: slideCount }, (_, i) => i)
|
||||
const hasCustomControls = Astro.slots.has('controls')
|
||||
---
|
||||
|
||||
<div id={id} class:list={['carousel', 'slide', fade && 'carousel-fade', className]} data-bs-ride="carousel" data-bs-interval={interval === false ? 'false' : interval} {...rest}>
|
||||
{
|
||||
indicators && (
|
||||
<div class:list={['carousel-indicators', indicatorsVertical && 'carousel-indicators-vertical', indicatorsVariant === 'dot' && 'carousel-indicators-dot', indicatorsVariant === 'thumb' && 'carousel-indicators-thumb']}>
|
||||
{slideIndexes.map((i) => (
|
||||
<button type="button" data-bs-target={target} data-bs-slide-to={i} class:list={[indicatorsThumbRatio && 'ratio ratio-4x3', i === 0 && 'active']} style={indicatorsVariant === 'thumb' && indicatorsImages?.[i] ? `background-image: url(${indicatorsImages[i]})` : undefined} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<div class="carousel-inner">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
{
|
||||
hasCustomControls ? (
|
||||
<slot name="controls" />
|
||||
) : (
|
||||
controls && (
|
||||
<Fragment>
|
||||
<a class="carousel-control-prev" href={target} role="button" data-bs-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true" />
|
||||
<span class="visually-hidden">Previous</span>
|
||||
</a>
|
||||
<a class="carousel-control-next" href={target} role="button" data-bs-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true" />
|
||||
<span class="visually-hidden">Next</span>
|
||||
</a>
|
||||
</Fragment>
|
||||
)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
@@ -50,11 +50,42 @@ const elementId = `chart-${id}`;
|
||||
<script define:vars={{ chartKey, elementId, config, xFormatterExpr }}>
|
||||
window.tabler_chart ??= {};
|
||||
|
||||
// Heatmap shades each cell by computing off the literal base color in JS
|
||||
// (light -> full color-mix by value), unlike other chart types where the
|
||||
// SVG `fill` attribute just holds `var(--chart-...)` and the browser paints
|
||||
// it directly. A raw var()/color-mix() string can't be parsed by that color
|
||||
// math, so it falls back to gray — and ApexCharts' heatmap parser only
|
||||
// accepts hex, not rgb()/rgba() either. Probing a real element's computed
|
||||
// `color` resolves var()/color-mix() (Chromium serializes it as a CSS Color 4
|
||||
// `color(srgb ...)` string), then a 1x1 canvas round-trip converts that to hex.
|
||||
function resolveCssVar(value) {
|
||||
if (typeof value !== 'string' || !value.includes('var(')) return value;
|
||||
const probe = document.createElement('span');
|
||||
probe.style.cssText = 'position:absolute;visibility:hidden';
|
||||
probe.style.color = value;
|
||||
document.body.appendChild(probe);
|
||||
const resolved = getComputedStyle(probe).color;
|
||||
probe.remove();
|
||||
if (!resolved) return value;
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = canvas.height = 1;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.fillStyle = resolved;
|
||||
ctx.fillRect(0, 0, 1, 1);
|
||||
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
|
||||
return `#${[r, g, b].map((c) => c.toString(16).padStart(2, '0')).join('')}`;
|
||||
}
|
||||
|
||||
function initChart() {
|
||||
if (xFormatterExpr && config.xaxis?.labels) {
|
||||
config.xaxis.labels.formatter = new Function('val', `return (${xFormatterExpr})`);
|
||||
}
|
||||
|
||||
if (config.chart?.type === 'heatmap' && Array.isArray(config.colors)) {
|
||||
config.colors = config.colors.map(resolveCssVar);
|
||||
}
|
||||
|
||||
window.ApexCharts &&
|
||||
(window.tabler_chart[chartKey] = new ApexCharts(document.getElementById(elementId), config)).render();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
// Data grid container (.datagrid); holds DatagridItem children.
|
||||
|
||||
interface Props {
|
||||
class?: string
|
||||
}
|
||||
|
||||
const { class: className } = Astro.props
|
||||
---
|
||||
|
||||
<div class:list={['datagrid', className]}>
|
||||
<slot />
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
// A single label/value pair (.datagrid-item); slot renders the value.
|
||||
|
||||
interface Props {
|
||||
title: string
|
||||
class?: string
|
||||
}
|
||||
|
||||
const { title, class: className } = Astro.props
|
||||
---
|
||||
|
||||
<div class:list={['datagrid-item', className]}>
|
||||
<div class="datagrid-title">{title}</div>
|
||||
<div class="datagrid-content">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
// A single legend item: a colored .legend dot + label, e.g. the "This year" /
|
||||
// "Last year" chart legend in SalesOverview.astro.
|
||||
interface Props {
|
||||
color?: string
|
||||
class?: string
|
||||
}
|
||||
|
||||
const { color = 'primary', class: className } = Astro.props
|
||||
---
|
||||
|
||||
<div class:list={['d-flex align-items-center gap-2', className]}>
|
||||
<span class={`legend bg-${color}`}></span>
|
||||
<span class="text-secondary"><slot /></span>
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
// "Less -> More" gradient legend, e.g. for a choropleth map's color scale.
|
||||
interface Props {
|
||||
/** number of swatches */
|
||||
steps?: number
|
||||
/** theme color the swatches ramp up to, e.g. 'primary' */
|
||||
color?: string
|
||||
minLabel?: string
|
||||
maxLabel?: string
|
||||
class?: string
|
||||
}
|
||||
|
||||
const { steps = 10, color = 'primary', minLabel = 'Less', maxLabel = 'More', class: className } = Astro.props
|
||||
|
||||
const items = Array.from({ length: steps }, (_, i) => i + 1)
|
||||
---
|
||||
|
||||
<div class:list={['d-flex align-items-center gap-2', className]}>
|
||||
<div class="text-secondary">{minLabel}</div>
|
||||
<div class="d-flex gap-1">
|
||||
{items.map((step) => <span class="legend" style={`background: color-mix(in srgb, transparent, var(--tblr-${color}) ${(step / steps) * 100}%);`} />)}
|
||||
</div>
|
||||
<div class="text-secondary">{maxLabel}</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user