chore: move utils to package

This commit is contained in:
2023-02-10 17:52:50 +01:00
parent 0c829c88c5
commit 3727b6bb2b
26 changed files with 170 additions and 160 deletions

View File

@@ -23,7 +23,8 @@
"ogl": "^0.0.110",
"sanitize.css": "^13.0.0",
"swell-js": "3.19.8",
"tweakpane": "^3.1.4"
"tweakpane": "^3.1.4",
"utils": "workspace:*"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^2.0.0",

View File

@@ -2,7 +2,7 @@
import { page } from '$app/stores'
import { afterUpdate } from 'svelte'
import { fade } from 'svelte/transition'
import { scrollToTop } from '$utils/functions'
import { scrollToTop } from 'utils/scroll'
import { pageLoading } from '$utils/stores'
import { DELAY, DURATION } from '$utils/constants'

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { splitText } from '$utils/functions'
import { splitText } from 'utils/text'
export let text: string
export let mode: string = undefined

View File

@@ -8,7 +8,7 @@
</style>
<script lang="ts">
import { map } from '$utils/functions'
import { map } from 'utils/math'
import reveal from '$animations/reveal'
export let tag: string

View File

@@ -4,7 +4,7 @@
<script lang="ts">
import { addToCart } from '$utils/functions/shop'
import { capitalizeFirstLetter } from '$utils/functions'
import { capitalizeFirstLetter } from 'utils/string'
// Components
import SplitText from '$components/SplitText.svelte'
import Button from '$components/atoms/Button.svelte'

View File

@@ -6,7 +6,7 @@
import { getContext } from 'svelte'
import { spring } from 'svelte/motion'
import dayjs from 'dayjs'
import { lerp } from '$utils/functions'
import { lerp } from 'utils/math'
import { PUBLIC_PREVIEW_COUNT } from '$env/static/public'
import { seenLocations } from '$utils/stores'
// Components

View File

@@ -7,7 +7,8 @@
import { fade, fly as flySvelte } from 'svelte/transition'
import { quartOut } from 'svelte/easing'
import { Globe, type Marker } from '$modules/globe'
import { getRandomItem, debounce } from '$utils/functions'
import { getRandomItem } from 'utils/array'
import { debounce } from 'utils/actions'
import { revealSplit } from '$animations/transitions'
// Components
import SplitText from '$components/SplitText.svelte'

View File

@@ -8,7 +8,7 @@
import { quartOut } from 'svelte/easing'
import reveal from '$animations/reveal'
import { send, receive } from '$animations/crossfade'
import { throttle } from '$utils/functions'
import { throttle } from 'utils/actions'
import { sendEvent } from '$utils/analytics'
// Components
import Button from '$components/atoms/Button.svelte'

View File

@@ -7,7 +7,7 @@
import EmblaCarousel, { type EmblaCarouselType } from 'embla-carousel'
// Components
import Poster from '$components/molecules/Poster.svelte'
import { debounce } from '$utils/functions'
import { debounce } from 'utils/actions'
export let posters: any = []

View File

@@ -1,7 +1,7 @@
import { error } from '@sveltejs/kit'
import type { PageServerLoad } from './$types'
import { fetchAPI } from '$utils/api'
import { getRandomItem } from '$utils/functions'
import { getRandomItem } from 'utils/array'
import { fetchSwell } from '$utils/functions/shopServer'
export const load = (async ({ setHeaders }) => {

View File

@@ -3,7 +3,7 @@
import { getContext } from 'svelte'
import { getAssetUrlKey } from '$utils/api'
import { shopCurrentProductSlug } from '$utils/stores/shop'
import { capitalizeFirstLetter } from '$utils/functions'
import { capitalizeFirstLetter } from 'utils/string'
// Components
import PageTransition from '$components/PageTransition.svelte'
import Metas from '$components/Metas.svelte'

View File

@@ -15,7 +15,7 @@
import { getAssetUrlKey } from '$utils/api'
import { previousPage } from '$utils/stores'
import { DELAY } from '$utils/constants'
import { throttle } from '$utils/functions'
import { throttle } from 'utils/actions'
import { swipe } from '$utils/interactions/swipe'
// Components
import Metas from '$components/Metas.svelte'

View File

@@ -1,7 +1,7 @@
import { error } from '@sveltejs/kit'
import type { PageServerLoad } from './$types'
import { fetchAPI } from '$utils/api'
import { getRandomItems } from '$utils/functions'
import { getRandomItems } from 'utils/array'
export const load = (async ({ setHeaders }) => {
try {

View File

@@ -9,9 +9,10 @@
import { fade, fly } from 'svelte/transition'
import type { PageData } from './$types'
import { animate, inView, stagger, timeline } from 'motion'
import { mailtoClipboard, map } from '$utils/functions'
import { mailtoClipboard } from '$utils/functions'
import { getAssetUrlKey } from '$utils/api'
import { DELAY } from '$utils/constants'
import { map } from 'utils/math'
import { sendEvent } from '$utils/analytics'
import { quartOut } from '$animations/easings'
// Components

View File

@@ -13,7 +13,8 @@
import relativeTime from 'dayjs/plugin/relativeTime'
import { stagger, timeline } from 'motion'
import { DELAY } from '$utils/constants'
import { map, lerp, throttle } from '$utils/functions'
import { map, lerp } from 'utils/math'
import { throttle } from 'utils/actions'
import { getAssetUrlKey } from '$utils/api'
import { quartOut } from '$animations/easings'
import { PUBLIC_FILTERS_DEFAULT_COUNTRY, PUBLIC_FILTERS_DEFAULT_SORT, PUBLIC_GRID_INCREMENT } from '$env/static/public'

View File

@@ -1,7 +1,7 @@
import { error } from '@sveltejs/kit'
import type { PageServerLoad } from './$types'
import { fetchAPI } from '$utils/api'
import { getRandomItems } from '$utils/functions'
import { getRandomItems } from 'utils/array'
export const load = (async ({ setHeaders }) => {

View File

@@ -1,150 +1,6 @@
import { sendEvent } from '$utils/analytics'
/**
* Debounce a function with a given amount of time
* @description For scrolling or other resource demanding behaviors
*/
export const debounce = (callback: (...args: any[]) => any, wait: number, immediate = false) => {
let timeout: ReturnType<typeof setTimeout> | number = 0
return (...args: any[]) => {
const callNow: boolean = immediate && !timeout
const next = () => callback(...args)
clearTimeout(timeout)
timeout = setTimeout(next, wait)
if (callNow) next()
}
}
/**
* Throttle a function by a given amount of time
* @description Throttling enforces a maximum number of times a function can be called over time, as in 'execute this function at most once every 100 milliseconds
*/
export const throttle = (fn: (...args: any[]) => any, delay: number) => {
let lastCall = 0
return (...args: unknown[]) => {
const now = performance.now()
if (now - lastCall < delay) return
lastCall = now
requestAnimationFrame(() => fn(...args))
}
}
/**
* Split text
* @description Split a string into words or characters
* @returns string[]
*/
export const splitText = (text: string, mode = 'words'): string[] => {
// Split by words
if (mode === 'words') {
const words = text
.replace(/\\n/g, '\n')
.replace(/\s+/g, m => m.includes('\n') ? '\n ' : ' ')
.trim()
.split(' ')
return words
}
// Split by chars
else if (mode === 'chars') {
const chars = Array.from(text).map(char => char === ' ' ? '\xa0' : char)
return chars
}
}
/**
* Capitalize first letter
*/
export const capitalizeFirstLetter = (string: string) => {
return string[0].toUpperCase() + string.slice(1)
}
/**
* Create a delay
*/
export const sleep = (milliseconds: number) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
/**
* Linear Interpolation
*/
export const lerp = (start: number, end: number, amount: number): number => {
return (1 - amount) * start + amount * end
}
/**
* Re-maps a number from one range to another
* @param value the incoming value to be converted
* @param start1 lower bound of the value's current range
* @param stop1 upper bound of the value's current range
* @param start2 lower bound of the value's target range
* @param stop2 upper bound of the value's target range
* @param [withinBounds] constrain the value to the newly mapped range
* @return remapped number
*/
export const map = (n: number, start1: number, stop1: number, start2: number, stop2: number, withinBounds: boolean): number => {
const value = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2
if (!withinBounds) return value
if (start2 < stop2) {
return clamp(value, start2, stop2)
} else {
return clamp(value, stop2, start2)
}
}
/**
* Clamp a number
*/
export const clamp = (num: number, a: number, b: number) => {
return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b))
}
/**
* Return random elements from an array
*/
export const getRandomItems = <T> (array: T[], amount: number): T[] => {
const shuffled = array.slice()
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]
}
return shuffled.slice(0, amount)
}
/**
* Return a random element from an array
*/
export const getRandomItem = <T extends Array<unknown>> (array: T): T[0] => {
return getRandomItems(array, 1)[0]
}
/**
* Scroll back to top after page transition
*/
export const scrollToTop = (delay?: number) => {
const scroll = () => window.scrollTo(0,0)
if (delay && delay > 0) {
setTimeout(scroll, delay)
} else {
return scroll()
}
}
/**
* Copy mailto links to clipboard and show message
*/

29
packages/utils/actions.ts Normal file
View File

@@ -0,0 +1,29 @@
/**
* Debounce a function with a given amount of time
* @description For scrolling or other resource demanding behaviors
*/
export const debounce = (callback: (...args: any[]) => any, wait: number, immediate = false) => {
let timeout: ReturnType<typeof setTimeout> | number = 0
return (...args: any[]) => {
const callNow: boolean = immediate && !timeout
const next = () => callback(...args)
clearTimeout(timeout)
timeout = setTimeout(next, wait)
if (callNow) next()
}
}
/**
* Throttle a function by a given amount of time
* @description Throttling enforces a maximum number of times a function can be called over time, as in 'execute this function at most once every 100 milliseconds
*/
export const throttle = (fn: (...args: any[]) => any, delay: number) => {
let lastCall = 0
return (...args: unknown[]) => {
const now = performance.now()
if (now - lastCall < delay) return
lastCall = now
requestAnimationFrame(() => fn(...args))
}
}

19
packages/utils/array.ts Normal file
View File

@@ -0,0 +1,19 @@
/**
* Return random elements from an array
*/
export const getRandomItems = <T> (array: T[], amount: number): T[] => {
const shuffled = array.slice()
for (let i = shuffled.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]
}
return shuffled.slice(0, amount)
}
/**
* Return a random element from an array
*/
export const getRandomItem = <T extends Array<unknown>> (array: T): T[0] => {
return getRandomItems(array, 1)[0]
}

17
packages/utils/index.ts Normal file
View File

@@ -0,0 +1,17 @@
/**
* Create a delay
*/
export const sleep = (milliseconds: number) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
}
/**
* Check if an object is empty
*/
export const isEmpty = (obj: Object) => {
if (obj === null || obj === undefined) {
throw new Error('Error: Given object is not an object')
}
return Object.keys(obj).length === 0 && obj.constructor === Object
}

35
packages/utils/math.ts Normal file
View File

@@ -0,0 +1,35 @@
/**
* Linear Interpolation
*/
export const lerp = (start: number, end: number, amount: number): number => {
return (1 - amount) * start + amount * end
}
/**
* Clamp a number
*/
export const clamp = (num: number, a: number, b: number) => {
return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b))
}
/**
* Re-maps a number from one range to another
* @param value the incoming value to be converted
* @param start1 lower bound of the value's current range
* @param stop1 upper bound of the value's current range
* @param start2 lower bound of the value's target range
* @param stop2 upper bound of the value's target range
* @param [withinBounds] constrain the value to the newly mapped range
* @return remapped number
*/
export const map = (n: number, start1: number, stop1: number, start2: number, stop2: number, withinBounds: boolean): number => {
const value = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2
if (!withinBounds) return value
if (start2 < stop2) {
return clamp(value, start2, stop2)
} else {
return clamp(value, stop2, start2)
}
}

View File

@@ -0,0 +1,6 @@
{
"name": "utils",
"version": "0.0.0",
"private": true,
"module": "index.ts"
}

12
packages/utils/scroll.ts Normal file
View File

@@ -0,0 +1,12 @@
/**
* Scroll back to top after page transition
*/
export const scrollToTop = (delay?: number) => {
const scroll = () => window.scrollTo(0,0)
if (delay && delay > 0) {
return setTimeout(scroll, delay)
} else {
return scroll()
}
}

6
packages/utils/string.ts Normal file
View File

@@ -0,0 +1,6 @@
/**
* Capitalize first letter
*/
export const capitalizeFirstLetter = (string: string) => {
return string[0].toUpperCase() + string.slice(1)
}

24
packages/utils/text.ts Normal file
View File

@@ -0,0 +1,24 @@
/**
* Split text
* @description Split a string into words or characters
* @returns string[]
*/
export const splitText = (text: string, mode = 'words'): string[] => {
// Split by words
if (mode === 'words') {
const words = text
.replace(/\\n/g, '\n')
.replace(/\s+/g, m => m.includes('\n') ? '\n ' : ' ')
.trim()
.split(' ')
return words
}
// Split by chars
else if (mode === 'chars') {
const chars = Array.from(text).map(char => char === ' ' ? '\xa0' : char)
return chars
}
return []
}

2
pnpm-lock.yaml generated
View File

@@ -53,6 +53,7 @@ importers:
tslib: ^2.5.0
tweakpane: ^3.1.4
typescript: ^4.9.5
utils: workspace:*
vite: ^4.1.1
dependencies:
'@studio-freight/lenis': 0.2.28
@@ -64,6 +65,7 @@ importers:
sanitize.css: 13.0.0
swell-js: 3.19.8
tweakpane: 3.1.4
utils: link:../../packages/utils
devDependencies:
'@sveltejs/adapter-auto': 2.0.0_@sveltejs+kit@1.5.3
'@sveltejs/adapter-cloudflare': 2.0.1_@sveltejs+kit@1.5.3