UNPKG

@ishitatsuyuki/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

336 lines (304 loc) 9.78 kB
/** * +/- function to native math sign */ function signPoly(value: number): number { if (value < 0) return -1 return value > 0 ? 1 : 0 } export const sign = Math.sign || signPoly /** * Checks if the flag is set * @param val * @param flag * @returns {boolean} */ function hasFlag(val: number, flag: number): boolean { return (val & flag) === flag } /** * Native modulo bug with negative numbers * @param n * @param mod * @returns {number} */ function mod(n: number, mod: number): number { return ((n % mod) + mod) % mod } /** * Asserts a value is beetween min and max * @param val * @param min * @param max * @returns {number} */ function bound(val: number, min: number, max: number): number { return Math.max(min, Math.min(max, val)) } export { mod, bound, hasFlag } /** * Get value of an object property/path even if it's nested */ export function getValueByPath(obj: any, path: string, defaultValue = undefined): any { const value = path.split('.').reduce((o, i) => typeof o !== 'undefined' ? o[i] : undefined, obj) return typeof value !== 'undefined' ? value : defaultValue } /** * Set value of an object property/path even if it's nested */ export function setValueByPath(obj: any, path: string, value: any) { const p = path.split('.') if (p.length === 1) { obj[path] = value return } const field = p[0] if (typeof obj[field] === 'undefined') obj[field] = {} return setValueByPath(obj[field], p.slice(1).join('.'), value) } /** * Extension of indexOf method by equality function if specified */ export function indexOf(array: any[], obj: any, fn: Function): number { if (!array) return -1 if (!fn || typeof fn !== 'function') return array.indexOf(obj) for (let i = 0; i < array.length; i++) { if (fn(array[i], obj)) { return i } } return -1 } /** * Merge function to replace Object.assign with deep merging possibility */ const isObject = (item: any) => typeof item === 'object' && !Array.isArray(item) const mergeFn = (target: any, source: any, deep = false) => { if (deep || !Object.assign) { const isDeep = (prop) => isObject(source[prop]) && target !== null && Object.prototype.hasOwnProperty.call(target, prop) && isObject(target[prop]) let replaced if (source === null || typeof source === 'undefined') { replaced = false; } else { replaced = Object.getOwnPropertyNames(source) .map((prop) => ({ [prop]: isDeep(prop) ? mergeFn(target[prop], source[prop], deep) : source[prop] })) .reduce((a, b) => ({ ...a, ...b }), {}) } return { ...target, ...replaced } } else { return Object.assign(target, source) } } export const merge = mergeFn /** * Mobile detection * https://www.abeautifulsite.net/detecting-mobile-devices-with-javascript */ export const isMobile = { Android: function () { return ( typeof window !== 'undefined' && window.navigator.userAgent.match(/Android/i) ) }, BlackBerry: function () { return ( typeof window !== 'undefined' && window.navigator.userAgent.match(/BlackBerry/i) ) }, iOS: function () { return ( typeof window !== 'undefined' && window.navigator.userAgent.match(/iPhone|iPad|iPod/i) ) }, Opera: function () { return ( typeof window !== 'undefined' && window.navigator.userAgent.match(/Opera Mini/i) ) }, Windows: function () { return ( typeof window !== 'undefined' && window.navigator.userAgent.match(/IEMobile/i) ) }, any: function () { return ( isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows() ) } } export function removeElement(el: Element) { if (typeof el.remove !== 'undefined') { el.remove() } else if (typeof el.parentNode !== 'undefined' && el.parentNode !== null) { el.parentNode.removeChild(el) } } export function createAbsoluteElement(el: Element) { const root = document.createElement('div') root.style.position = 'absolute' root.style.left = '0px' root.style.top = '0px' const wrapper = document.createElement('div') root.appendChild(wrapper) wrapper.appendChild(el) document.body.appendChild(root) return root } /** * Escape regex characters * http://stackoverflow.com/a/6969486 */ export function escapeRegExpChars(value: string) { if (!value) return value return value.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&') } export function createNewEvent(eventName: string) { let event: any if (typeof Event === 'function') { event = new Event(eventName) } else { event = document.createEvent('Event') event.initEvent(eventName, true, true) } return event } export function toCssDimension(width: string | number) { return width === undefined ? null : (isNaN(width as number) ? width : width + 'px') } export function blankIfUndefined(value: string) { return typeof value !== 'undefined' && value !== null ? value : '' } export function defaultIfUndefined(value: any, defaultValue: any) { return typeof value !== 'undefined' && value !== null ? value : defaultValue } /** * Return month names according to a specified locale * @param {String} locale A bcp47 localerouter. undefined will use the user browser locale * @param {String} format long (ex. March), short (ex. Mar) or narrow (M) * @return {Array<String>} An array of month names */ type monthType = "numeric" | "2-digit" | "long" | "short" | "narrow" | undefined export function getMonthNames(locale: string = undefined, format: monthType = 'long'): string[] { const dates = [] for (let i = 0; i < 12; i++) { dates.push(new Date(2000, i, 15)) } const dtf = new Intl.DateTimeFormat(locale, { month: format, // timeZone: 'UTC' }) return dates.map((d) => dtf.format(d)) } /** * Return weekday names according to a specified locale * @param {String} locale A bcp47 localerouter. undefined will use the user browser locale * @param {Number} first day of week index * @param {String} format long (ex. Thursday), short (ex. Thu) or narrow (T) * @return {Array<String>} An array of weekday names */ type weekdayType = "long" | "short" | "narrow" | undefined; export function getWeekdayNames(locale: string = undefined, firstDayOfWeek: number = 0, format: weekdayType = 'narrow'): string[] { const dates = [] for (let i = 1, j = 0; j < 7; i++) { const d = new Date(2000, 0, i) const day = d.getDay() if (day === firstDayOfWeek || j > 0) { dates.push(d) j++ } } const dtf = new Intl.DateTimeFormat(locale, { weekday: format, // timeZone: 'UTC' }) return dates.map((d) => dtf.format(d)) } /** * Accept a regex with group names and return an object * ex. matchWithGroups(/((?!=<year>)\d+)\/((?!=<month>)\d+)\/((?!=<day>)\d+)/, '2000/12/25') * will return { year: 2000, month: 12, day: 25 } * @param {String} includes injections of (?!={groupname}) for each group * @param {String} the string to run regex * @return {Object} an object with a property for each group having the group's match as the value */ export function matchWithGroups(pattern: string, str: string): any { const matches = str.match(pattern) return pattern // get the pattern as a string .toString() // suss out the groups .match(/<(.+?)>/g) // remove the braces .map((group) => { const groupMatches = group.match(/<(.+)>/) if (!groupMatches || groupMatches.length <= 0) { return null } return group.match(/<(.+)>/)[1] }) // create an object with a property for each group having the group's match as the value .reduce((acc, curr, index) => { if (matches && matches.length > index) { acc[curr] = matches[index + 1] } else { acc[curr] = null } return acc }, {}) } export function getStyleValue(value: any): any { if (typeof value === 'object') { for (const key in value) { if (value[key]) return key } return '' } return value } export function debounce(func: Function, wait: number, immediate?: boolean) { let timeout: any return function () { const context = this const args = arguments const later = function () { timeout = null if (!immediate) func.apply(context, args) } const callNow = immediate && !timeout clearTimeout(timeout) timeout = setTimeout(later, wait) if (callNow) func.apply(context, args) } } export function endsWith(str: string, suffix: string) { return str.indexOf(suffix, str.length - suffix.length) !== -1; } export const isDefined = (d: any) => d !== undefined /** * Remove accents/diacritics in a string in JavaScript * https://stackoverflow.com/a/37511463 */ export function removeDiacriticsFromString(value: string) { if (!value) return value return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '') } export function isClient() { return typeof window !== 'undefined' }