@dvcol/neo-svelte
Version:
Neomorphic ui library for svelte 5
88 lines (87 loc) • 3.77 kB
JavaScript
import { clamp } from '@dvcol/common-utils/common/math';
import { NeoTextButton } from '../buttons/neo-button.model.js';
export const MaxShadowElevation = 5;
export const MinShadowElevation = -5;
export const MaxShallowShadowElevation = 3;
export const MinShallowShadowElevation = -3;
export const DefaultShallowMinMaxElevation = {
max: MaxShallowShadowElevation,
min: MinShallowShadowElevation,
};
export const DefaultShadowElevation = 3;
export const DefaultShadowActiveElevation = -2;
export const DefaultShadowPressedElevation = -2;
export const ShadowElevations = [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5];
export const DefaultShadowHoverElevation = -1;
export const DefaultShadowHoverPressedElevation = 0;
export const ShadowHoverElevations = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
export const DefaultShadowShallowElevation = 2;
export const ShadowShallowElevations = [-3, -2, -1, 0, 1, 2, 3];
export const PositiveShadowElevations = [0, 1, 2, 3, 4, 5];
export const PositiveMinMaxElevation = { min: 0, max: MaxShadowElevation };
export const BlurElevations = [0, 1, 2, 3, 4, 5];
export const ShadowFlatRegex = /^.*flat\)?;?$/;
export const DefaultSaturation = 3;
export function getDefaultElevation(pressed, fallback = DefaultShadowElevation) {
return pressed ? DefaultShadowPressedElevation : fallback;
}
export function getDefaultHoverElevation(pressed, fallback = DefaultShadowHoverElevation) {
return pressed ? DefaultShadowHoverPressedElevation : fallback;
}
export function getDefaultSlideElevation(elevation, fallback = DefaultShadowPressedElevation) {
if (elevation < 0)
return Math.abs(elevation);
return fallback;
}
export function coerce(elevation, { min, max } = {}) {
if (elevation === undefined || elevation === null)
return elevation;
const _elevation = Number(elevation);
if (min !== undefined && _elevation < min)
return min;
if (max !== undefined && _elevation > max)
return max;
return _elevation;
}
export function parseBlur(blur, elevation, minMax = { min: 1, max: 5 }) {
if (!blur || elevation === undefined)
return minMax.min ?? 1;
return coerce(blur ?? elevation, minMax);
}
export const isShadowFlat = (shadow) => ShadowFlatRegex.test(shadow);
export function computeElevation(elevation, { min = MinShadowElevation, max = MaxShadowElevation } = {}) {
if (elevation < min)
return min;
if (elevation > max)
return max;
return elevation;
}
export function computeShadowElevation(elevation, { glass, convex, pressed, active } = {}, minMax = {}) {
const raided = convex ? 'convex' : 'raised';
let inset = 'inset';
if (pressed)
inset = 'pressed';
if (active)
inset = 'active';
let shadow = `var(--neo-${glass ? 'glass-' : ''}box-shadow-`;
const level = computeElevation(elevation, minMax);
if (!level)
return `${shadow}flat)`;
shadow += level < 0 ? inset : raided;
return `${shadow}-${Math.trunc(Math.abs(level))})`;
}
export function computeHoverShadowElevation(elevation, hover, options, minMax = {}) {
if (!hover)
return;
return computeShadowElevation(elevation + hover, options, minMax);
}
export function computeGlassFilter(elevation, glass, { min = 1, max = MaxShadowElevation, saturation = DefaultSaturation } = {}) {
if (!glass)
return;
return `var(--neo-blur-${clamp(Math.abs(elevation), min, max)}) var(--neo-saturate-${saturation})`;
}
export function computeButtonTemplate(elevation, pressed, text) {
if (text || elevation >= 0)
return NeoTextButton;
return { elevation: Math.min(Math.abs(elevation), 3), hover: 0, active: -2, pressed: true, borderless: true };
}