Random
Random utilities like getRandomString, etc.
Example Usage
import {
getRandomString,
getRandomString2,
getRandomInteger,
getRandomArrayItem,
getRandomColor,
getRandomImage,
getRandomDateInRange,
} from './random';
// getRandomString
getRandomString(); // 1642345678-12345
// getRandomString2
getRandomString2() // 12345
// getRandomInteger(min, max)
getRandomInteger(1, 10); // 1
getRandomInteger(1, 10); // 2
getRandomInteger(1, 10); // 10
// getRandomArrayItem(any[])
getRandomArrayItem([1, 2, 3]); // 2
getRandomArrayItem([1, 2, 3]); // 3
// getRandomColor
getRandomColor(); // total random { h: 120, s: 100, l: 50, hsl: 'hsl(120 100% 50% )' }
getRandomColor({h: 50}); // fixed h { h: 50, s: 100, l: 50, hsl: 'hsl(50 100% 50% )' }
getRandomColor({h: 50, s: 50}); // fixed h and s { h: 50, s: 50, l: 50, hsl: 'hsl(50 50% 50% )' }
getRandomColor({h: 50, l: 50}); // fixed h and l { h: 50, s: 50, l: 50, hsl: 'hsl(50 50% 50% )' }
// getRandomImage
getRandomImage(); // https://picsum.photos/900/700?random=1
getRandomImage({ w: 600, h: 400 }); // https://picsum.photos/600/400?random=2
// getRandomDateInRange
getRandomDateInRange(new Date('2022-01-01'), new Date('2022-12-31')); // Date 2022-08-01
Dependencies
registryhttps://shadcn-registry-ts.vercel.app/r/util-math.json
Auto Install
npx shadcn@latest add https://shadcn-registry-ts.vercel.app/r/util-random.json
Manual Install
random.ts
/**
* Source: http://localhost:3000
*/
import { lerp, clamp } from './math';
/** Get a random string in format `1642345678-12345`. Always 19 characters. */
export const getRandomString = () => `${new Date().valueOf()}-${Math.random().toString(36).substring(3, 8)}`;
/** Get a random string in format `12345`. Always 5 characters. */
export const getRandomString2 = () => Math.random().toString(36).substring(3, 8);
/**
* Get a random integer between min and max. Min andmax are included.
* Result is also clamped.
*/
export const getRandomInteger = (
/** Minumum value passibile. */
min: number,
/** Maximum value possible. */
max: number
) => {
const value = lerp({ min, max, t: Math.random() });
return clamp({ min, max, value: Math.round(value) });
};
/**
* Get a random item from an array
*/
export const getRandomArrayItem = <T>(
/** Array from which you want to get a random item. */
array: T[]
): T => {
const index = getRandomInteger(0, array.length - 1);
return array[index];
};
/**
* Get a random color in HSL format.
* If you provide:
* - nothing, it will generate a random color.
* - `{ h: 20 }`, it will generate a random color with always 20 as hue.
* - `{ s: 60 }`, it will generate a random color with always 60 as saturation.
* - `{ l: 80 }`, it will generate a random color with always 80 as lightness.
* - `{ h: 10, s: 20 }` or `{ h: 10, l: 20 }` or `{ s: 10, l: 20 }`, it will generate a random color with the fixed part you provided. What you don't provide will be random.
*/
export const getRandomColor = ({
h,
s,
l,
}: {
/** Hue. 0-360*/
h?: number,
/** Saturation. 0-100. */
s?: number,
/** Lightness. 0-100. */
l?: number,
} = {}) => {
const _h = h ?? getRandomInteger(0, 360);
const _s = s ?? getRandomInteger(0, 100);
const _l = l ?? getRandomInteger(0, 100);
return {
h: _h,
s: _s,
l: _l,
hsl: `hsl(${_h} ${_s}% ${_l}%)`,
};
};
/**
* Get a random image (for placeholder).
* Internally it builds an URL for Picsum.
* i.e. `https://picsum.photos/200/300?random=234`
*/
export const getRandomImage = ({
w = 900,
h = 700,
}: {
/** Width. Default to 900. */
w?: number,
/** Height. Default to 700. */
h?: number,
} = {}) => {
// https://picsum.photos/200/300?random=234
const url = new URL(`https://picsum.photos/${w}/${h}`);
url.searchParams.append('random', getRandomInteger(0, 1000).toString());
return url.toString();
};
/**
* Get a random `Date` between start and end `Date`.
* Start and end could be included.
*/
export const getRandomDateInRange = (start: Date, end: Date) => {
const DAY_IN_MS = 1000 * 60 * 60 * 24;
const differenceBetweenStartAndEnd_inMs = end.getTime() - start.getTime();
const differenceBetweenStartAndEnd_inDays = differenceBetweenStartAndEnd_inMs / DAY_IN_MS;
const randomNumberOfDays = getRandomInteger(0, differenceBetweenStartAndEnd_inDays);
const randomNumberOfDays_inMs = randomNumberOfDays * DAY_IN_MS;
const randomDate = new Date(start.getTime() + randomNumberOfDays_inMs);
return randomDate;
};
Test
random.test.ts
import { describe, it, expect } from 'vitest';
import { repeatSyncFn } from '../utility-framework/vitest.utils';
import {
getRandomString,
getRandomString2,
getRandomInteger,
getRandomArrayItem,
getRandomColor,
getRandomImage,
getRandomDateInRange,
} from './random';
describe('random - getRandomString', () => {
it('do it', async () => {
repeatSyncFn(10_000, () => {
const value = getRandomString();
expect(value).toBeTypeOf('string');
expect(value.length).toBe(19);
});
});
});
describe('random - getRandomString2', () => {
it('do it', async () => {
repeatSyncFn(10_000, () => {
const value = getRandomString2();
expect(value).toBeTypeOf('string');
expect(value.length).toBe(5);
});
});
});
describe('random - getRandomInteger', () => {
it('do it', async () => {
repeatSyncFn(10_000, () => {
const value = getRandomInteger(0, 100);
expect(value).toBeGreaterThanOrEqual(0);
expect(value).toBeLessThanOrEqual(100);
});
});
});
describe('random - getRandomArrayItem', () => {
it('do it', async () => {
repeatSyncFn(10_000, () => {
const value = getRandomArrayItem([1, 2, 3]);
expect(value).oneOf([1, 2, 3]);
});
});
});
describe('random - getRandomColor', () => {
it('do it', async () => {
// total random
repeatSyncFn(1_000, () => {
const value = getRandomColor();
expect(value.h).toBeGreaterThanOrEqual(0);
expect(value.h).toBeLessThanOrEqual(360);
expect(value.s).toBeGreaterThanOrEqual(0);
expect(value.s).toBeLessThanOrEqual(100);
expect(value.l).toBeGreaterThanOrEqual(0);
expect(value.l).toBeLessThanOrEqual(100);
});
// fixed h
repeatSyncFn(1_000, () => {
const value = getRandomColor({ h: 100 });
expect(value.h).toBe(100);
expect(value.s).toBeGreaterThanOrEqual(0);
expect(value.s).toBeLessThanOrEqual(100);
expect(value.l).toBeGreaterThanOrEqual(0);
expect(value.l).toBeLessThanOrEqual(100);
});
// fixed s
repeatSyncFn(1_000, () => {
const value = getRandomColor({ s: 100 });
expect(value.h).toBeGreaterThanOrEqual(0);
expect(value.h).toBeLessThanOrEqual(360);
expect(value.s).toBe(100);
expect(value.l).toBeGreaterThanOrEqual(0);
expect(value.l).toBeLessThanOrEqual(100);
});
// fixed l
repeatSyncFn(1_000, () => {
const value = getRandomColor({ l: 100 });
expect(value.h).toBeGreaterThanOrEqual(0);
expect(value.h).toBeLessThanOrEqual(360);
expect(value.s).toBeGreaterThanOrEqual(0);
expect(value.s).toBeLessThanOrEqual(100);
expect(value.l).toBe(100);
});
// fixed h, s
repeatSyncFn(1_000, () => {
const value = getRandomColor({ h: 100, s: 100 });
expect(value.h).toBe(100);
expect(value.s).toBe(100);
expect(value.l).toBeGreaterThanOrEqual(0);
expect(value.l).toBeLessThanOrEqual(100);
});
// fixed h, l
repeatSyncFn(1_000, () => {
const value = getRandomColor({ h: 100, l: 100 });
expect(value.h).toBe(100);
expect(value.s).toBeGreaterThanOrEqual(0);
expect(value.s).toBeLessThanOrEqual(100);
expect(value.l).toBe(100);
});
// fixed s, l
repeatSyncFn(1_000, () => {
const value = getRandomColor({ s: 100, l: 100 });
expect(value.h).toBeGreaterThanOrEqual(0);
expect(value.h).toBeLessThanOrEqual(360);
expect(value.s).toBe(100);
expect(value.l).toBe(100);
});
});
});
describe('random - getRandomImage', () => {
it('do it', async () => {
repeatSyncFn(10_000, () => {
const value = getRandomImage();
expect(value).toBeTypeOf('string');
expect(value.startsWith('https://picsum.photos/')).toBe(true);
});
});
});
describe('random - getRandomDateInRange', () => {
it('do it', async () => {
repeatSyncFn(10_000, () => {
const start = new Date('2022-01-01');
const end = new Date('2022-12-31');
const value = getRandomDateInRange(start, end);
expect(value).toBeInstanceOf(Date);
expect(value.getTime()).toBeGreaterThanOrEqual(start.getTime());
expect(value.getTime()).toBeLessThanOrEqual(end.getTime());
});
});
});
Command Palette
Search for a command to run...