src/lib/utils.sass
// Easings
$in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53)
$in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19)
$in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22)
$in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06)
$in-sine: cubic-bezier(0.47, 0, 0.745, 0.715)
$in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035)
$in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335)
$in-back: cubic-bezier(0.6, -0.28, 0.735, 0.045)
$out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94)
$out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1)
$out-quart: cubic-bezier(0.165, 0.84, 0.44, 1)
$out-quint: cubic-bezier(0.23, 1, 0.32, 1)
$out-sine: cubic-bezier(0.39, 0.575, 0.565, 1)
$out-expo: cubic-bezier(0.19, 1.00, 0.22, 1)
$out-circ: cubic-bezier(0.075, 0.82, 0.165, 1)
$out-back: cubic-bezier(0.175, 0.885, 0.32, 1.275)
$in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955)
$in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1)
$in-out-quart: cubic-bezier(0.77, 0, 0.175, 1)
$in-out-quint: cubic-bezier(0.86, 0, 0.07, 1)
$in-out-sine: cubic-bezier(0.445, 0.05, 0.55, 0.95)
$in-out-expo: cubic-bezier(1, 0, 0, 1)
$in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86)
$in-out-back: cubic-bezier(0.68, -0.55, 0.265, 1.55)

=positionals($prefix: '', $args)
	$top: nth($args, 1)
	$right: if(length($args) > 1, nth($args, 2), $top)
	$bottom: if(length($args) > 2, nth($args, 3), $top)
	$left: if(length($args) > 3, nth($args, 4), $right)

	@if $top != _
		#{$prefix}top: $top
	@if $right != _
		#{$prefix}right: $right
	@if $bottom != _
		#{$prefix}bottom: $bottom
	@if $left != _
		#{$prefix}left: $left

=margin($args)
	+positionals(margin-, $args)

=padding($args)
	+positionals(padding-, $args)

=absolute($args)
	position: absolute
	+positionals($args: $args)

=relative($args)
	position: relative
	+positionals($args: $args)

=fixed($args)
	position: fixed
	+positionals($args: $args)

=sticky($args)
	position: sticky
	+positionals($args: $args)

=size($args)
	width: nth($args, 1)
	height: if(length($args) > 1, nth($args, 2), nth($args, 1))

=min-size($args)
	min-width: nth($args, 1)
	min-height: if(length($args) > 1, nth($args, 2), nth($args, 1))

=max-size($args)
	max-width: nth($args, 1)
	max-height: if(length($args) > 1, nth($args, 2), nth($args, 1))

=ellipsis($lines: 1, $direction: right)
	overflow: hidden
	text-overflow: ellipsis

	@if $lines > 1
		display: -webkit-box
		-webkit-line-clamp: $lines
		-webkit-box-orient: vertical
	@else
		white-space: nowrap

	@if $direction == left
		direction: rtl
		text-align: left

		&:before
			// Flips text back to rtl to fix stuff like slashes
			// being moved from beginning to end of the string
			content: '\00202D'

// Subtracts width of the scrollbar from desired right padding
@function subScrollbar($spacing: var(--spacing))
	@return calc(#{$spacing} - var(--scrollbar-size))

=rightSpacingScrollable($spacing: var(--spacing), $offset: 2px)
	margin-right: calc(#{$spacing} - var(--scrollbar-size) - #{$offset})
	padding-right: $offset

=hSpacingScrollable($spacing: var(--spacing), $offset: 2px)
	padding-left: $spacing
	+rightSpacingScrollable($spacing, $offset)

=autogrid($minItemWidth: 25em)
	display: grid
	grid-template-columns: repeat(auto-fit, minmax(min(#{$minItemWidth}, 100%), 1fr))
	grid-auto-rows: min-content

// Allows selecting text
=selectable()
	user-select: text
	cursor: initial

// Adds elevation shadows. Use increments of: 2,4,8,16,24
=elevate($n: 2)
	box-shadow: 0 #{0.5 * $n}px #{$n}px rgba(0, 0, 0, var(--f2-shadow-1a)), 0 #{0.5 * $n}px #{$n}px rgba(0, 0, 0, var(--f2-shadow-2a))

=fadein()
	animation: 300ms fade-in

// Element fading masks
=addFadeMask($mask, $subtractScrollbar)
	$-scrollbarMask: linear-gradient(to left, black var(--scrollbar-size), transparent var(--scrollbar-size))
	@if $subtractScrollbar
		mask-image: $mask, $-scrollbarMask
	@else
		mask-image: $mask

=fadeTop($size: 1rem, $subtractScrollbar: false)
	+addFadeMask(linear-gradient(to bottom, #0003 5px, black #{$size}), $subtractScrollbar)

=fadeBottom($size: 1rem, $subtractScrollbar: false)
	+addFadeMask(linear-gradient(to bottom, black calc(100% - #{$size}), #0003 calc(100% - 5px)), $subtractScrollbar)

=fadeTopBottom($size: 1rem, $subtractScrollbar: false)
	+addFadeMask(linear-gradient(to bottom, #0003 5px, black #{$size}, black calc(100% - #{$size}), #0003 calc(100% - 5px)), $subtractScrollbar)

=fadeLeft($size: 1rem, $subtractScrollbar: false)
	+addFadeMask(linear-gradient(to right, #0003 5px, black #{$size}), $subtractScrollbar)

=fadeRight($size: 1rem, $subtractScrollbar: false)
	+addFadeMask(linear-gradient(to right, black calc(100% - #{$size}), #0003 calc(100% - 5px)), $subtractScrollbar)

=fadeLeftRight($size: 1rem, $subtractScrollbar: false)
	+addFadeMask(linear-gradient(to right, #0003 5px, black #{$size}, black calc(100% - #{$size}), #0003 calc(100% - 5px)), $subtractScrollbar)

// Hide element from view/layout, but not from screen readers.
=visuallyHidden()
	width: 1px
	height: 1px
	overflow: hidden
	opacity: 0
	position: fixed
	top: 0
	left: 0
	pointer-events: none

// Used as a background/overlay for disabled elements
=disabledStripes($size: 1em, $fg: #0002, $bg: #fff2)
	background-image: linear-gradient(135deg, $fg 25%, $bg 25%, $bg 50%, $fg 50%, $fg 75%, $bg 75%, $bg 100%)
	background-size: $size $size

=disabledMask($size: 1em, $fg: #000a, $bg: #fff)
	mask-image: linear-gradient(135deg, $fg 25%, $bg 25%, $bg 50%, $fg 50%, $fg 75%, $bg 75%, $bg 100%)
	mask-size: $size $size

// Animations
@keyframes fade-in
	from
		opacity: 0
	to
		opacity: 1

@keyframes slidein-from-left
	from
		opacity: 0
		transform: translateX(-100px)
	to
		opacity: 1
		transform: translateX(0px)

@keyframes slidein-from-right
	from
		opacity: 0
		transform: translateX(100px)
	to
		opacity: 1
		transform: translateX(0px)

@keyframes slidein-from-top
	from
		opacity: 0
		transform: translateY(-100px)
	to
		opacity: 1
		transform: translateY(0px)

@keyframes slidein-from-bottom
	from
		opacity: 0
		transform: translateY(100px)
	to
		opacity: 1
		transform: translateY(0px)
