@dvcol/neo-svelte
Version:
Neomorphic ui library for svelte 5
84 lines (83 loc) • 3.72 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 = 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 };
};