All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.src.utils.ts Maven / Gradle / Ivy

The newest version!
import { TableState, Updater } from './types'

export type PartialKeys = Omit & Partial>
export type RequiredKeys = Omit &
  Required>
export type Overwrite = Omit<
  T,
  keyof U
> &
  U

export type UnionToIntersection = (
  T extends any ? (x: T) => any : never
) extends (x: infer R) => any
  ? R
  : never

export type IsAny = 1 extends 0 & T ? Y : N
export type IsKnown = unknown extends T ? N : Y

type ComputeRange<
  N extends number,
  Result extends Array = []
> = Result['length'] extends N
  ? Result
  : ComputeRange
type Index40 = ComputeRange<40>[number]

// Is this type a tuple?
type IsTuple = T extends readonly any[] & { length: infer Length }
  ? Length extends Index40
    ? T
    : never
  : never

// If this type is a tuple, what indices are allowed?
type AllowedIndexes<
  Tuple extends ReadonlyArray,
  Keys extends number = never
> = Tuple extends readonly []
  ? Keys
  : Tuple extends readonly [infer _, ...infer Tail]
  ? AllowedIndexes
  : Keys

export type DeepKeys = unknown extends T
  ? keyof T
  : object extends T
  ? string
  : T extends readonly any[] & IsTuple
  ? AllowedIndexes | DeepKeysPrefix>
  : T extends any[]
  ? never & 'Dynamic length array indexing is not supported'
  : T extends Date
  ? never
  : T extends object
  ? (keyof T & string) | DeepKeysPrefix
  : never

type DeepKeysPrefix = TPrefix extends keyof T & (number | string)
  ? `${TPrefix}.${DeepKeys & string}`
  : never

export type DeepValue = T extends Record
  ? TProp extends `${infer TBranch}.${infer TDeepProp}`
    ? DeepValue
    : T[TProp & string]
  : never

export type NoInfer = [T][T extends any ? 0 : never]

export type Getter = () => NoInfer

///

export function functionalUpdate(updater: Updater, input: T): T {
  return typeof updater === 'function'
    ? (updater as (input: T) => T)(input)
    : updater
}

export function noop() {
  //
}

export function makeStateUpdater(
  key: K,
  instance: unknown
) {
  return (updater: Updater) => {
    ;(instance as any).setState((old: TTableState) => {
      return {
        ...old,
        [key]: functionalUpdate(updater, (old as any)[key]),
      }
    })
  }
}

type AnyFunction = (...args: any) => any

export function isFunction(d: any): d is T {
  return d instanceof Function
}

export function isNumberArray(d: any): d is number[] {
  return Array.isArray(d) && d.every(val => typeof val === 'number')
}

export function flattenBy(
  arr: TNode[],
  getChildren: (item: TNode) => TNode[]
) {
  const flat: TNode[] = []

  const recurse = (subArr: TNode[]) => {
    subArr.forEach(item => {
      flat.push(item)
      const children = getChildren(item)
      if (children?.length) {
        recurse(children)
      }
    })
  }

  recurse(arr)

  return flat
}

export function memo(
  getDeps: () => [...TDeps],
  fn: (...args: NoInfer<[...TDeps]>) => TResult,
  opts: {
    key: any
    debug?: () => any
    onChange?: (result: TResult) => void
  }
): () => TResult {
  let deps: any[] = []
  let result: TResult | undefined

  return () => {
    let depTime: number
    if (opts.key && opts.debug) depTime = Date.now()

    const newDeps = getDeps()

    const depsChanged =
      newDeps.length !== deps.length ||
      newDeps.some((dep: any, index: number) => deps[index] !== dep)

    if (!depsChanged) {
      return result!
    }

    deps = newDeps

    let resultTime: number
    if (opts.key && opts.debug) resultTime = Date.now()

    result = fn(...newDeps)
    opts?.onChange?.(result)

    if (opts.key && opts.debug) {
      if (opts?.debug()) {
        const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100
        const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100
        const resultFpsPercentage = resultEndTime / 16

        const pad = (str: number | string, num: number) => {
          str = String(str)
          while (str.length < num) {
            str = ' ' + str
          }
          return str
        }

        console.info(
          `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,
          `
            font-size: .6rem;
            font-weight: bold;
            color: hsl(${Math.max(
              0,
              Math.min(120 - 120 * resultFpsPercentage, 120)
            )}deg 100% 31%);`,
          opts?.key
        )
      }
    }

    return result!
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy