You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.9 KiB
92 lines
2.9 KiB
<script lang="ts">
|
|
/**
|
|
* Eidos `<Display>` — hero / oversize typography primitive.
|
|
*
|
|
* Always uses the foundation's `--style-hero-*` tokens. Smaller scope
|
|
* than Heading — for the page's "display" title above an `<h1>`
|
|
* headline. Default tag is `<h1>` so it slots into the heading
|
|
* hierarchy; `as` switches to non-heading tags when needed.
|
|
*
|
|
* <Display>Welcome to UIX.</Display>
|
|
* <Display size="xxxl" weight="bold">Big.</Display>
|
|
* <Display tracking="tight" align="center">Spread.</Display>
|
|
*
|
|
* The `[data-display]` marker is the canonical selector for the recipe.
|
|
*/
|
|
import { ActiveEidos } from '$uix/eidos';
|
|
import type { DisplayProps } from './types';
|
|
|
|
let {
|
|
size,
|
|
family,
|
|
weight,
|
|
color,
|
|
align,
|
|
tracking,
|
|
italic = false,
|
|
underline = false,
|
|
truncate = false,
|
|
clamp,
|
|
as = 'h1',
|
|
tagStyle,
|
|
class: className,
|
|
children,
|
|
...restProps
|
|
}: DisplayProps = $props();
|
|
|
|
const eidos = ActiveEidos.require();
|
|
|
|
const TRACKING_VALUE: Record<string, string> = {
|
|
tight: '-0.02em',
|
|
normal: '0',
|
|
wide: '0.02em'
|
|
};
|
|
|
|
function pushVar(decls: string[], name: string, value: string | number | undefined): void {
|
|
if (value === undefined || value === null || value === '') return;
|
|
decls.push(`${name}: ${value};`);
|
|
}
|
|
|
|
const inlineStyle = $derived.by(() => {
|
|
const decls: string[] = [];
|
|
const sizeKey = eidos.resolve(size);
|
|
const familyKey = eidos.resolve(family);
|
|
const weightKey = eidos.resolve(weight);
|
|
const colorKey = eidos.resolve(color);
|
|
const alignKey = eidos.resolve(align);
|
|
const trackingKey = eidos.resolve(tracking);
|
|
|
|
if (sizeKey) {
|
|
pushVar(decls, '--_display-font-size', `var(--font-size-${sizeKey})`);
|
|
pushVar(decls, '--_display-line-height', `var(--font-line-height-${sizeKey})`);
|
|
pushVar(decls, '--_display-letter-spacing', `var(--font-letter-spacing-${sizeKey})`);
|
|
}
|
|
if (familyKey) pushVar(decls, '--_display-font-family', `var(--font-family-${familyKey})`);
|
|
if (weightKey) pushVar(decls, '--_display-font-weight', `var(--font-weight-${weightKey})`);
|
|
if (colorKey) pushVar(decls, '--_display-color', `var(--color-content-${colorKey})`);
|
|
if (alignKey) pushVar(decls, '--_display-align', alignKey);
|
|
if (trackingKey && trackingKey in TRACKING_VALUE) {
|
|
pushVar(decls, '--_display-letter-spacing', TRACKING_VALUE[trackingKey]);
|
|
}
|
|
if (typeof clamp === 'number' && clamp > 0) pushVar(decls, '--_display-clamp', String(clamp));
|
|
|
|
const inline = decls.join(' ');
|
|
return [inline, tagStyle].filter(Boolean).join(' ');
|
|
});
|
|
</script>
|
|
|
|
<svelte:element
|
|
this={as}
|
|
{...restProps}
|
|
class={className}
|
|
data-display=""
|
|
data-tracking={tracking ? eidos.resolve(tracking) : undefined}
|
|
data-italic={italic ? '' : undefined}
|
|
data-underline={underline ? '' : undefined}
|
|
data-truncate={truncate ? '' : undefined}
|
|
data-clamp={typeof clamp === 'number' && clamp > 0 ? '' : undefined}
|
|
style={inlineStyle}
|
|
>
|
|
{@render children?.()}
|
|
</svelte:element>
|