@slimr/util
TypeScript icon, indicating that this package has built-in type declarations

3.2.40 • Public • Published

🪶 @slimr/util npm package

A set of slim JS polyfills with tree-shaking support

Context

@slimr is a set of slim React (hence '@slimr') libs. Check them all out on github!

Exports

appendElement, appendLink, appendScript, appendStyle

Append a link, script, style, or ANY element to the head of the document if not already added

areEqualDeep, areNotEqualDeep

Deep compare methods

  • Shallow is faster than deep if it's "good enough" for your use case
  • Dependendencies: ./src/equality-deep.ts, npm:fast-deep-equal
  • Note: Imperfect on Classes
  • Tip: For debugging, try using areEqualDebug/areNotEqualDebug

areEqualShallow, areNotEqualShallow

Shallow compare methods

  • Shallow is faster than deep if it's "good enough" for your use case
  • Dependendencies: ./src/equality-deep.ts, npm:fast-shallow-equal
  • Note: Imperfect on Classes and less perfect than deep
  • Tip: For debugging, try using areEqualDebug/areNotEqualDebug

copy

Deeply copy two objects

  • Is imperfect on classes.
  • Extends npm:copy-anything, which has a full list of options.
const obj1 = [
  {foo: 'bar', arr: [2]},
  {foo: 'bar2', arr: [3]},
]
const obj2 = copy(obj1)

createUid

Generate a random string of 12 characters, provided by npm:nanoid.

const id = createUid()

debounce

Don't call a function until a certain amount of time has passed without it being called.

  • If you want more features, like arg diffing and return values, see @slimr/util/memoize
  • Dependences: ./src/debounce.ts
const fnc = async () => 2
const debounced = debounce(fnc, 250)
debounced()
debounced()
debounced()
await sleep(250)
debounced()
debounced()
debounced()
await sleep(250)
// fnc would only be called twice

diff, addedDiff, deletedDiff, updatedDiff, detailedDiff

Deep compare methods provided by npm:deep-object-diff, which return an object describing the differencees between two objs.

highlightCodeElements

Highlight code elements using highlight.js

  • Is async + lazy loaded to avoid loading highlight.js on pages that don't need it bc is large.
  • Dependendencies: ./src/code-highlight-lazy.ts, npm:highlight.js

formToValues

Extracts form values from a form element, such as e.target from form.onSubmit

  • An alternative to the FormData api, aiming to be more predictable, flexible and less awkward.
    • For example, FormData has not great way to enumerate all fields (even ones with undefined values) or multiple checkboxes or multi selects.
  • Handles text, number, checkboxes, radio buttons, textarea, select
  • Value = array if multiple inputs with same 'name', such as checkboxes
  • Converts US phone numbers to international format
  • Usage: Code Sandbox
  • Limitation: Can't handle complex forms (multipart/form-data encoding)
  • Dependencies: ./src/form-to-values.ts

Why not FormData?

  • FormData returns an iterator, vs formToJson a simple dictionary object
  • For checkbox inputs, FormData returns 'on' when checked and nothing at all when unchecked
  • For number inputs, FormData returns a string instead of a number
  • For array values such as select w/ multiple, FormData returns a seperate key/value for every value instead of key=array of values.

hash32 and hash64

Quickly converts any plain object, string, number, and more to a 32bit/64bit hash number or string

  • Uses a fast and tiny approach, which has higher likelyhood of collision than
  • Best for smaller hash tables
  • Not good enough for UUIDs
  • Dependencies: ./src/hash.ts
hash32('hello world') // 1047750623
hash32('hello world', true) // 'hbsxjz'
hash32({hello: 'world'}) // 141133545
hash64('hello world') // 927946135
hash64('hello world', true) // 'fch3tj'
hash64({hello: 'world'}) // 1139059049

NOTE hash64 is not a true 64 bit hash and has higher collision odds than a true 64 bit hash.

Collisions are possible and likelyhood increases with the number of hashes.

Ideal collision odds:

  • 100 32bit hashes = 1/1,000,000
  • 927 32bit hashes = 1/10,000
  • 1921 64bit hashes = 1/10,000,000,000,000 = 1/10 trillion = ~odds of a meteor hitting your house

References

is-whats

A set of is-type methods to easily check if a value is a type.

  • Is provided by npm:is-what, which has a full list of options.
isPositiveNumber(-2) // false
isFullArray([]) // false
isEmptyArray([]) // true

mapApplyMaxSize

Limit the size of a map by evicting the least-recently-used (aka LRU) items. Works by monkey-patching the get and set of a map instance

  • Dependencies: ./src/map-apply-max-size.ts, ./src/stringify.ts
const t = mapApplyMaxSize(new Map(), 2)
t.set('a', 1)
t.set('b', 2)
t.set('a', 3) // refreshes 'a'
t.set('c', 3) // should evict 'b'
expect(t.get('b')).toBeUndefined()
t.set('d', 4) // should evict 'a'
expect(t.get('a')).toBeUndefined()
t.get('c')
t.set('e', 5) // should evict 'd'
expect(t.get('d')).toBeUndefined()

memoize

A memoization wrapper with ttl expiration for cache hits.

  • Aka a feature rich debounce. If you only need basic debounce, see @slimr/util/debounce.
  • Compared to other memoization algs (fast-memoize, nano-memoize), is much simpler, shorter, easier to fork/enhance while less perfect and slower for primitive args.
  • Dependences: ./src/memoize.ts

merge, mergeAndCompare, mergeAndConcat

Deeply merge objects or arrays in a familiar pattern to Object.assign

merge({foo: 'bar', arr: [2]}, {foo: 'bar2', arr: [3]}) // {foo: bar2, arr: [3]}
mergeAndConcat({foo: 'bar', arr: [2]}, {foo: 'bar2', arr: [3]}) // {foo: bar2, arr: [2, 3]}

mergeAndCompare(concatStrings, {name: 'John'}, {name: 'Simth'})
// returns { name: 'JohnSmith' }

function concatStrings(originVal, newVal, key) {
  if (typeof originVal === 'string' && typeof newVal === 'string') {
    // concat logic
    return `${originVal}${newVal}`
  }
  // always return newVal as fallback!!
  return newVal
}

numericStringMask

Applies a mask to a string of numbers, helpful for phone numbers

Grabs all of the numbers out of str into an array, then assembles the mask and replaces the '#' with the numbers in order

numericStringMask('1234567890', '(###) ### - ####') // (123) 456 - 7890
numericStringMask('1234567890', '(###) ### - ####') // (123) 456 - 7890
numericStringMask('(123)abc45678-90', '(###) ### - ####') // (123) 456 - 7890
numericStringMask('1234567890', '(###) ###-####') // (123) 456-7890
numericStringMask('11900567890', '(##) #####-####') // (11) 90056-7890

// react input usage
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  e.currentTarget.value = numericStringMask(e.target.value, '(###) ###-####')
    // Replaces so we don't add characters past the end of the string,
    // and so the user can delete characters
    .replace(/-$/, '') // changes '(123) 456-' to '(123) 456'
    .replace(/\) $/, '') // changes '(11)' to '(11'
    .replace(/\($/, '') // changes '(' to ''
}

setPageMeta

Allows setting common page attrs.

  • Intelligently use the attrs, only setting if changed
  • Resets back to initial if omitted, based on initial introspection
  • Stores element handles in memory to remove need to query the dom on every update

Note: Set window.setPageMetaSkip=true to disable setPageMeta for testing

Parameters:

  • title - Sets title, meta:og:title. Is postfixed by ' - {siteName}'
  • siteName - Sets meta:og:site_name
  • description - Sets meta:description
  • image - Sets meta:og:image
  • locale - Sets meta:og:local

Assumption: The page should already have the following meta tags, to be used as defaults:

<title>React Template</title>
<meta property="og:title" content="React template" />
<meta property="og:site_name" content="React Template" />
<meta property="og:locale" content="en_US" />
<link rel="canonical" href="https://react-template.com" />
<meta name="description" content="A template to build tiny Preact applications" />
<meta property="og:description" content="A template to build tiny React applications" />
<meta property="og:url" content="https://github.com/bdombro/react-template" />
<meta property="og:image" content="https://preact-template.com/apple-touch-icon.png" />

Usage:

const {description} = setPageMeta({
  title: `Hello World`,
  description: 'This page is awesome',
})

stringify

A safe JSON.stringify wrapper that limits recursion

  • Dependencies: ./src/stringify.ts

toCamelCase

Convert a string to camelCase

toCamelCase('hello_world') // helloWorld

toKebabCase

Convert a string to kebab-case

toCamelCase('hello_world') // hello-world

Readme

Keywords

none

Package Sidebar

Install

npm i @slimr/util

Weekly Downloads

11

Version

3.2.40

License

ISC

Unpacked Size

243 kB

Total Files

247

Last publish

Collaborators

  • bdombro