Package Exports
- js-shared
- js-shared/dist/build.common.js
- js-shared/dist/build.esm.js
- js-shared/dist/build.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (js-shared) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
js-shared
Lightweight JavaScript / TypeScript utility toolkit for browser & Node.js
Features
| Module | Description |
|---|---|
| Browser | User-agent detection — platform, OS, browser |
| Clipboard | Async clipboard read / write |
| Collection | Array helpers (dedup, etc.) |
| Color | System-aware color palette |
| Cookie | Simple cookie CRUD |
| Date | Formatting, ranges, arithmetic, validation |
| Graphics | Canvas drawing utilities |
| Misc | Runtime detection & globals |
| Random | Integers, sampling, HSL color generation |
| Template | Handlebars-based HTML templating |
| Types | Type checking helpers |
Installation
npm install js-sharedQuick Start
import { Browser, Collection, Date } from 'js-shared';
// Detect the current browser
const info = Browser.parse(navigator.userAgent);
console.log(info.browserName); // => 'Chrome'
// Remove duplicates
Collection.unique(['a', 'b', 'a']); // => ['a', 'b']
// Format today's date
Date.format('YYYY-MM-DD'); // => '2020-03-20'API
Browser
Detect platform, OS and browser from the user-agent string.
import { Browser } from 'js-shared';
Browser.parse(navigator.userAgent);
// => { platform: 'mobile', osName: 'Android', osVersion: 9, browserName: 'Chrome' }Clipboard
Read from and write to the system clipboard.
import { Clipboard } from 'js-shared';
await Clipboard.save('Hello, World!');Collection
Handy array operations.
import { Collection } from 'js-shared';
Collection.unique(['green', 'red', 'green', 'blue', 'red']);
// => ['green', 'red', 'blue']Color
System-aware color values that adapt to accessibility settings.

import { Color } from 'js-shared';
Color.blue; // rgb(0,122,255)
Color.darkBlue; // rgb(10,132,255)
Color.accessibleBlue; // rgb(0,64,221)
Color.accessibleDarkBlue; // rgb(64,156,255)Cookie
Simple cookie management.
import { Cookie } from 'js-shared';
Cookie.set('token', 'abc123');
Cookie.get('token'); // => 'abc123'
Cookie.remove('token');Date
Full-featured date utilities — formatting, ranges, arithmetic, and validation.
import { Date } from 'js-shared';Format
Date.format();
// => '2020-03-20T12:17:34+09:00'
Date.format('dddd, MMMM Do YYYY, h:mm:ss a');
// => 'Friday, March 20th 2020, 12:17:34 pm'
Date.format('2020-01-01', 'ddd, hA');
// => 'Wed, 12AM'Time slots
Date.timesOneDay();
// => ['00:00', '01:00', ... '23:00', '00:00']
Date.timesOneDay(9, 'LT');
// => ['9:00 AM', '10:00 AM', ... '8:00 AM', '9:00 AM']Days in month
Date.daysInMonth();
// => ['1', '2', ... '31']
Date.daysInMonth('2020-01', 'MMM D');
// => ['Jan 1', 'Jan 2', ... 'Jan 31']Range
Generate consecutive dates at regular intervals.
Date.range(7, 'days', '3/1', '3/31', 'M/D');
// => ['3/1', '3/8', '3/15', '3/22', '3/29']
Date.range(30, 'minutes', '3/1, 9:00', '3/1, 12:00', 'H:mm');
// => ['9:00', '9:30', '10:00', '10:30', '11:00', '11:30', '12:00']Arithmetic
Date.add('2020/3/21', 1, 'months', 'M/D/Y'); // => '4/21/2020'
Date.add('2020/3/21', 1, 'weeks', 'M/D/Y'); // => '3/28/2020'
Date.add('2020/3/21, 9:00:00', 1, 'hours', 'M/D/Y, H:mm:ss');
// => '3/21/2020, 10:00:00'
Date.subtract('2020/3/21', 7, 'days', 'M/D/Y'); // => '3/14/2020'Validation
Date.isValid('2012-05-25', 'YYYY-MM-DD', true); // => true
Date.isValid('2012.05.25', 'YYYY-MM-DD', true); // => false
Date.isValid('2010 2 29', 'YYYY MM DD'); // => false (not a leap year)Graphics
Canvas drawing utilities.

import { Graphics } from 'js-shared';
const canvas = document.querySelector('#myCanvas');
// Stroke only
Graphics.drawRectangle(canvas, 50, 80, 100, 20, {
lineColor: 'blue',
});
// Filled & rotated
Graphics.drawRectangle(canvas, 50, 80, 100, 20, {
fill: 'gold',
degree: 45,
lineWidth: 0,
});Misc
Runtime environment helpers.
import { Misc } from 'js-shared';
Misc.isNodeEnvironment(); // => false (in browser)
Misc.getGlobal(); // => window | globalRandom
Random number generation, sampling, and color creation.
import { Random } from 'js-shared';
Random.randInt(3, 9); // integer between 3-9
Random.sample(['apple', 'banana']); // random pick
// Vibrant colors
Random.randHSL({ smin: 80, smax: 100, lmin: 45, lmax: 55 });
// Soft pastels
Random.randHSL({ smin: 10, smax: 100, lmin: 50, lmax: 95 });Template
Handlebars-powered template engine with built-in helpers.
import { Template } from 'js-shared';Basic interpolation
Template.compile(`
<p>Hello, my name is {{name}}.</p>
<ul>
{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}
</ul>
`)({ name: 'Alan', kids: [{ name: 'Jimmy', age: '12' }, { name: 'Sally', age: '4' }] });Conditionals
Template.compile(`
{{#if author}}
<h1>{{firstName}} {{lastName}}</h1>
{{else}}
<h1>Unknown Author</h1>
{{/if}}
`)({ author: true, firstName: 'Yehuda', lastName: 'Katz' });
// => '<h1>Yehuda Katz</h1>'Iteration
// Array of strings
Template.compile(`
<ul>
{{#each people}}<li>{{this}}</li>{{/each}}
</ul>
`)({ people: ['Yehuda Katz', 'Alan Johnson', 'Charles Jolley'] });
// Array of objects
Template.compile(`
<ul>
{{#each persons}}<li>{{name}} ({{country}})</li>{{/each}}
</ul>
`)({ persons: [{ name: 'Nils', country: 'Germany' }, { name: 'Yehuda', country: 'USA' }] });HTML escaping
Template.compile('raw: {{{specialChars}}} | escaped: {{specialChars}}')({
specialChars: '& < > " \' ` =',
});
// => 'raw: & < > " \' ` = | escaped: & < > ...'Math helpers — round / ceil / floor
Template.compile('{{round value}}')({ value: 1.5 }); // => '2'
Template.compile('{{ceil 2 value}}')({ value: 1.014 }); // => '1.02'
Template.compile('{{floor 2 value}}')({ value: 1.016 }); // => '1.01'Comparison operators
eq ne lt gt le ge and or
Template.compile('{{#if (gt value 10)}}big{{else}}small{{/if}}')({ value: 3 });
// => 'small'
Template.compile('{{#if (and value1 value2)}}both{{else}}nope{{/if}}')({
value1: true, value2: false,
});
// => 'nope'Moment helpers
Template.compile('{{moment}}')();
// => '2020-07-20T03:34:29+09:00'
Template.compile('{{moment d "DD/MM/YYYY"}}')({ d: '7/21/2020' });
// => '21/07/2020'
Template.compile('{{moment d add="days" amount="7"}}')({ d: '7/21/2020' });
// => '2020-07-28T00:00:00+09:00'
Template.compile('{{moment d "fromNow"}}')({ d: '7/20/2020' });
// => '4 hours ago'Types
Runtime type checking.
import { Types } from 'js-shared';
async function myAsyncFn() {}
function myFn() {}
Types.isAsync(myFn); // => false
Types.isAsync(myAsyncFn); // => trueChangelog
See CHANGELOG.md for release history.