UNPKG

@dvcol/neo-svelte

Version:

Neomorphic ui library for svelte 5

84 lines (83 loc) 3.72 kB
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 = 2; export const MinShallowShadowElevation = -2; 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 = [-2, -1, 0, 1, 2]; export const PositiveShadowElevations = [0, 1, 2, 3, 4, 5]; export const PositibeMinMaxElevation = { min: 0, max: MaxShadowElevation }; export const BlurElevations = [1, 2, 3, 4, 5]; export const ShadowFlatRegex = /^.*flat\)?;?$/; export const DefaultSaturation = 3; export const getDefaultElevation = (pressed, fallback = DefaultShadowElevation) => pressed ? DefaultShadowPressedElevation : fallback; export const getDefaultHoverElevation = (pressed, fallback = DefaultShadowHoverElevation) => pressed ? DefaultShadowHoverPressedElevation : fallback; export const 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) { if (!blur || elevation === undefined) return 1; return clamp(coerce(blur ?? elevation), 1, 5); } export const isShadowFlat = (shadow) => ShadowFlatRegex.test(shadow); export const computeElevation = (elevation, { min = MinShadowElevation, max = MaxShadowElevation } = {}) => { if (elevation < min) return min; if (elevation > max) return max; return elevation; }; export const 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 const computeHoverShadowElevation = (elevation, hover, options, minMax = {}) => { if (!hover) return; return computeShadowElevation(elevation + hover, options, minMax); }; export const 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 const 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 }; };