Tldraw/packages/editor/src/lib/utils/data.ts

98 wiersze
2.1 KiB
TypeScript

import { isPlainObject } from 'is-plain-object'
import { nanoid } from 'nanoid'
/**
* Generate a unique id.
*
* @example
*
* ```ts
* const id = uniqueId()
* ```
*
* @public
*/
export function uniqueId() {
return nanoid()
}
const serializableTypes = new Set(['string', 'number', 'boolean', 'undefined'])
/**
* Get whether a value is serializable.
*
* @example
*
* ```ts
* const A = isSerializable(1) // true
* const B = isSerializable('a') // true
* const C = isSerializable(true) // true
* const D = isSerializable(undefined) // false
* ```
*
* @param value - The value to check.
* @public
*/
export function isSerializable(value: any): boolean {
if (serializableTypes.has(typeof value) || value === null) return true
if (Array.isArray(value)) return value.every(isSerializable)
if (isPlainObject(value)) return Object.values(value).every(isSerializable)
return false
}
/**
* Convert a file to base64.
*
* @example
*
* ```ts
* const A = fileToBase64('./test.png')
* ```
*
* @param value - The file as a blob.
* @public
*/
export function fileToBase64(file: Blob): Promise<string> {
return new Promise((resolve, reject) => {
if (file) {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result as string)
reader.onerror = (error) => reject(error)
reader.onabort = (error) => reject(error)
}
})
}
/**
* Get an incremented name (e.g. New page (2)) from a name (e.g. New page), based on an array of
* existing names.
*
* @param name - The name to increment.
* @param others - The array of existing names.
* @public
*/
export function getIncrementedName(name: string, others: string[]) {
let result = name
const set = new Set(others)
while (set.has(result)) {
result = /^.*(\d+)$/.exec(result)?.[1]
? result.replace(/(\d+)(?=\D?)$/, (m) => {
return (+m + 1).toString()
})
: `${result} 1`
}
return result
}
/** @public */
export const checkFlag = (flag: boolean | (() => boolean) | undefined) =>
typeof flag === 'boolean' ? flag : flag?.()
/** @public */
export function snapToGrid(n: number, gridSize: number) {
return Math.round(n / gridSize) * gridSize
}