shelving 1.40.0 → 1.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/db/Database.d.ts +14 -16
- package/db/Database.js +37 -49
- package/db/Operation.d.ts +82 -0
- package/db/Operation.js +132 -0
- package/db/index.d.ts +1 -1
- package/db/index.js +1 -1
- package/package.json +6 -6
- package/react/useDocument.js +2 -2
- package/react/useQuery.js +3 -3
- package/update/ArrayUpdate.d.ts +4 -4
- package/update/ArrayUpdate.js +4 -4
- package/update/DataUpdate.d.ts +1 -1
- package/update/DataUpdate.js +1 -1
- package/update/ObjectUpdate.d.ts +4 -4
- package/update/ObjectUpdate.js +4 -4
- package/util/async.d.ts +28 -4
- package/util/async.js +36 -3
- package/util/date.d.ts +49 -18
- package/util/date.js +92 -85
- package/util/number.d.ts +56 -9
- package/util/number.js +76 -13
- package/util/string.d.ts +6 -0
- package/util/string.js +6 -0
- package/util/units.d.ts +37 -9
- package/util/units.js +60 -89
- package/db/Write.d.ts +0 -50
- package/db/Write.js +0 -73
package/update/DataUpdate.js
CHANGED
|
@@ -10,7 +10,7 @@ export class DataUpdate extends Update {
|
|
|
10
10
|
return transformProps(existing, this.updates);
|
|
11
11
|
}
|
|
12
12
|
/** Return a new object with the specified additional transform for a prop. */
|
|
13
|
-
|
|
13
|
+
with(key, value) {
|
|
14
14
|
if (isNullish(key))
|
|
15
15
|
return this;
|
|
16
16
|
return { __proto__: Object.getPrototypeOf(this), ...this, updates: { ...this.updates, [key]: value } };
|
package/update/ObjectUpdate.d.ts
CHANGED
|
@@ -5,17 +5,17 @@ export declare type EntryUpdates<T> = ImmutableObject<T | Update<T>>;
|
|
|
5
5
|
/** Update that can be applied to a map-like object to add/remove/update its entries. */
|
|
6
6
|
export declare class ObjectUpdate<T> extends Update<ImmutableObject<T>> implements Iterable<Entry<T | Update<T> | undefined>> {
|
|
7
7
|
/** Return an object update with a specific entry marked for update. */
|
|
8
|
-
static
|
|
8
|
+
static with<X>(key: string | undefined | null, value: X | Update<X>): ObjectUpdate<X>;
|
|
9
9
|
/** Return an object update with a specific entry marked for deletion. */
|
|
10
|
-
static
|
|
10
|
+
static without<X>(key: string | undefined | null): ObjectUpdate<X>;
|
|
11
11
|
readonly updates: EntryUpdates<T>;
|
|
12
12
|
readonly deletes: ImmutableArray<string>;
|
|
13
13
|
constructor(updates?: EntryUpdates<T>, deletes?: ImmutableArray<string>);
|
|
14
14
|
transform(existing: unknown): ImmutableObject<T>;
|
|
15
15
|
/** Return an object update with a specific entry marked for update. */
|
|
16
|
-
|
|
16
|
+
with(key: Nullish<string>, value: T | Update<T>): this;
|
|
17
17
|
/** Return an object update with a specific entry marked for deletion. */
|
|
18
|
-
|
|
18
|
+
without(key: Nullish<string>): this;
|
|
19
19
|
/**
|
|
20
20
|
* Iterate over the changes in this object.
|
|
21
21
|
* - Updates are yielded first, then deletes.
|
package/update/ObjectUpdate.js
CHANGED
|
@@ -8,11 +8,11 @@ export class ObjectUpdate extends Update {
|
|
|
8
8
|
this.deletes = deletes;
|
|
9
9
|
}
|
|
10
10
|
/** Return an object update with a specific entry marked for update. */
|
|
11
|
-
static
|
|
11
|
+
static with(key, value) {
|
|
12
12
|
return new ObjectUpdate(isNullish(key) ? {} : { [key]: value });
|
|
13
13
|
}
|
|
14
14
|
/** Return an object update with a specific entry marked for deletion. */
|
|
15
|
-
static
|
|
15
|
+
static without(key) {
|
|
16
16
|
return new ObjectUpdate({}, isNullish(key) ? [] : [key]);
|
|
17
17
|
}
|
|
18
18
|
transform(existing) {
|
|
@@ -20,13 +20,13 @@ export class ObjectUpdate extends Update {
|
|
|
20
20
|
return transformEntries(existingObject, this.updates, this.deletes);
|
|
21
21
|
}
|
|
22
22
|
/** Return an object update with a specific entry marked for update. */
|
|
23
|
-
|
|
23
|
+
with(key, value) {
|
|
24
24
|
if (isNullish(key))
|
|
25
25
|
return this;
|
|
26
26
|
return { __proto__: Object.getPrototypeOf(this), ...this, sets: { ...this.updates, [key]: value } };
|
|
27
27
|
}
|
|
28
28
|
/** Return an object update with a specific entry marked for deletion. */
|
|
29
|
-
|
|
29
|
+
without(key) {
|
|
30
30
|
if (isNullish(key))
|
|
31
31
|
return this;
|
|
32
32
|
return { __proto__: Object.getPrototypeOf(this), ...this, deletes: [...this.deletes, key] };
|
package/util/async.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { ImmutableArray } from "./array.js";
|
|
2
|
+
import type { Arguments, Dispatcher } from "./function.js";
|
|
1
3
|
import { DONE } from "./constants.js";
|
|
2
4
|
import { Handler } from "./error.js";
|
|
3
|
-
import type { Arguments, Dispatcher } from "./function.js";
|
|
4
5
|
/**
|
|
5
6
|
* Throw the value if it's an async (promised) value.
|
|
6
7
|
* @returns Synchronous (not promised) value.
|
|
@@ -9,9 +10,32 @@ import type { Arguments, Dispatcher } from "./function.js";
|
|
|
9
10
|
export declare function throwAsync<T>(asyncValue: T | PromiseLike<T>): T;
|
|
10
11
|
/** Is a value an async (promised) value. */
|
|
11
12
|
export declare const isAsync: <T>(v: T | PromiseLike<T>) => v is PromiseLike<T>;
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Call a callback with an item.
|
|
15
|
+
* - If neither `callback` or `item` are async then the value returned will be synchronous.
|
|
16
|
+
*
|
|
17
|
+
* @param callback The sync or async function to call.
|
|
18
|
+
* @param item The first argument for `callback` (if this value is async it will be awaited before `callback` is called).
|
|
19
|
+
* @param ...args Additional arguments for `callback`
|
|
20
|
+
*/
|
|
21
|
+
export declare const callAsync: <I, O, A extends Arguments = []>(callback: (v: I, ...a: A) => O | PromiseLike<O>, item: I | PromiseLike<I>, ...args: A) => O | PromiseLike<O>;
|
|
22
|
+
export declare const _awaitCallAsync: <I, O, A extends Arguments>(callback: (v: I, ...a: A) => O | PromiseLike<O>, item: PromiseLike<I>, args: A) => Promise<O>;
|
|
23
|
+
/**
|
|
24
|
+
* Call a callback for a set of items in series.
|
|
25
|
+
*
|
|
26
|
+
* @param callback The sync or async function to call for each item.
|
|
27
|
+
* @param items The set of first arguments for `callback` (if this value is async it will be awaited before `callback` is called).
|
|
28
|
+
* @param ...args Additional arguments for `callback`
|
|
29
|
+
*/
|
|
30
|
+
export declare function callAsyncSeries<I, O, A extends Arguments = []>(callback: (item: I, ...a: A) => O | PromiseLike<O>, items: Iterable<I | PromiseLike<I>>, ...args: A): Promise<ImmutableArray<O>>;
|
|
31
|
+
/**
|
|
32
|
+
* Call a callback for a set of items in parallel.
|
|
33
|
+
*
|
|
34
|
+
* @param callback The sync or async function to call for each item.
|
|
35
|
+
* @param items The set of first arguments for `callback` (if this value is async it will be awaited before `callback` is called).
|
|
36
|
+
* @param ...args Additional arguments for `callback`
|
|
37
|
+
*/
|
|
38
|
+
export declare function callAsyncParallel<I, O, A extends Arguments = []>(callback: (item: I, ...a: A) => O | PromiseLike<O>, items: Iterable<I | PromiseLike<I>>, ...args: A): Promise<ImmutableArray<O>>;
|
|
15
39
|
/** Type of `Promise` with its `resolve()` and `reject()` methods exposed publicly. */
|
|
16
40
|
export declare class Deferred<T> extends Promise<T> {
|
|
17
41
|
static get [Symbol.species](): PromiseConstructor;
|
package/util/async.js
CHANGED
|
@@ -11,9 +11,42 @@ export function throwAsync(asyncValue) {
|
|
|
11
11
|
}
|
|
12
12
|
/** Is a value an async (promised) value. */
|
|
13
13
|
export const isAsync = (v) => typeof v === "object" && v !== null && typeof v.then === "function";
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
/**
|
|
15
|
+
* Call a callback with an item.
|
|
16
|
+
* - If neither `callback` or `item` are async then the value returned will be synchronous.
|
|
17
|
+
*
|
|
18
|
+
* @param callback The sync or async function to call.
|
|
19
|
+
* @param item The first argument for `callback` (if this value is async it will be awaited before `callback` is called).
|
|
20
|
+
* @param ...args Additional arguments for `callback`
|
|
21
|
+
*/
|
|
22
|
+
export const callAsync = (callback, item, ...args) => isAsync(item) ? _awaitCallAsync(callback, item, args) : callback(item, ...args);
|
|
23
|
+
export const _awaitCallAsync = async (callback, item, args) => callback(await item, ...args);
|
|
24
|
+
/**
|
|
25
|
+
* Call a callback for a set of items in series.
|
|
26
|
+
*
|
|
27
|
+
* @param callback The sync or async function to call for each item.
|
|
28
|
+
* @param items The set of first arguments for `callback` (if this value is async it will be awaited before `callback` is called).
|
|
29
|
+
* @param ...args Additional arguments for `callback`
|
|
30
|
+
*/
|
|
31
|
+
export async function callAsyncSeries(callback, items, ...args) {
|
|
32
|
+
const outputs = [];
|
|
33
|
+
for (const item of items)
|
|
34
|
+
outputs.push(await callback(await item, ...args));
|
|
35
|
+
return outputs;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Call a callback for a set of items in parallel.
|
|
39
|
+
*
|
|
40
|
+
* @param callback The sync or async function to call for each item.
|
|
41
|
+
* @param items The set of first arguments for `callback` (if this value is async it will be awaited before `callback` is called).
|
|
42
|
+
* @param ...args Additional arguments for `callback`
|
|
43
|
+
*/
|
|
44
|
+
export async function callAsyncParallel(callback, items, ...args) {
|
|
45
|
+
const outputs = [];
|
|
46
|
+
for (const item of await Promise.all(items))
|
|
47
|
+
outputs.push(callback(item, ...args));
|
|
48
|
+
return Promise.all(outputs);
|
|
49
|
+
}
|
|
17
50
|
// Internal way for us to save `resolve()` and `reject()` from a new Promise used by `Deferred` and `ExtendablePromise`
|
|
18
51
|
let resolve; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
19
52
|
let reject;
|
package/util/date.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** One second in millseconds. */
|
|
2
|
+
export declare const SECOND = 1000;
|
|
1
3
|
/** One minute in millseconds. */
|
|
2
4
|
export declare const MINUTE: number;
|
|
3
5
|
/** One hour in millseconds. */
|
|
@@ -6,6 +8,8 @@ export declare const HOUR: number;
|
|
|
6
8
|
export declare const DAY: number;
|
|
7
9
|
/** One week in millseconds. */
|
|
8
10
|
export declare const WEEK: number;
|
|
11
|
+
/** One month in millseconds. */
|
|
12
|
+
export declare const MONTH: number;
|
|
9
13
|
/** One year in millseconds. */
|
|
10
14
|
export declare const YEAR: number;
|
|
11
15
|
/** Is a value a date? */
|
|
@@ -53,46 +57,73 @@ export declare function getMonday(target?: PossibleDate): Date;
|
|
|
53
57
|
export declare function addDays(change: number, target?: PossibleDate): Date;
|
|
54
58
|
/** Return a new date that increase or decreases the number of hours based on an input date. */
|
|
55
59
|
export declare function addHours(change: number, target?: PossibleDate): Date;
|
|
60
|
+
/**
|
|
61
|
+
* Get the duration (in milliseconds) between two dates.
|
|
62
|
+
*
|
|
63
|
+
* @param target The date when the thing will happen or did happen.
|
|
64
|
+
* @param current Today's date (or a different date to measure from).
|
|
65
|
+
*/
|
|
66
|
+
export declare const getDuration: (target?: PossibleDate | undefined, current?: PossibleDate | undefined) => number;
|
|
56
67
|
/** Count the number of seconds until a date. */
|
|
57
|
-
export declare const
|
|
68
|
+
export declare const getSecondsUntil: (target: PossibleDate, current?: PossibleDate | undefined) => number;
|
|
58
69
|
/** Count the number of days ago a date was. */
|
|
59
|
-
export declare const
|
|
70
|
+
export declare const getSecondsAgo: (target: PossibleDate, current?: PossibleDate | undefined) => number;
|
|
60
71
|
/** Count the number of days until a date. */
|
|
61
|
-
export declare const
|
|
72
|
+
export declare const getDaysUntil: (target: PossibleDate, current?: PossibleDate | undefined) => number;
|
|
62
73
|
/** Count the number of days ago a date was. */
|
|
63
|
-
export declare const
|
|
74
|
+
export declare const getDaysAgo: (target: PossibleDate, current?: PossibleDate | undefined) => number;
|
|
64
75
|
/** Count the number of weeks until a date. */
|
|
65
|
-
export declare const
|
|
76
|
+
export declare const getWeeksUntil: (target: PossibleDate, current?: PossibleDate | undefined) => number;
|
|
66
77
|
/** Count the number of weeks ago a date was. */
|
|
67
|
-
export declare const
|
|
68
|
-
/**
|
|
69
|
-
export declare function
|
|
78
|
+
export declare const getWeeksAgo: (target: PossibleDate, current?: PossibleDate | undefined) => number;
|
|
79
|
+
/** Format a full description of a duration of time using the most reasonable units e.g. `5 years` or `1 week` or `4 minutes` or `12 milliseconds`. */
|
|
80
|
+
export declare function formatFullDuration(ms: number): string;
|
|
81
|
+
/** Format a description of a duration of time using the most reasonable units e.g. `5y` or `4m` or `12ms`. */
|
|
82
|
+
export declare function formatDuration(ms: number): string;
|
|
70
83
|
/**
|
|
71
|
-
* Return
|
|
72
|
-
*
|
|
84
|
+
* Return full description of the gap between two dates, e.g. `in 10 days` or `2 hours ago`
|
|
85
|
+
*
|
|
86
|
+
* @param target The date when the thing will happen or did happen.
|
|
73
87
|
* @param current Today's date (or a different date to measure from).
|
|
74
88
|
*/
|
|
75
|
-
export declare function
|
|
89
|
+
export declare function formatFullWhen(target: PossibleDate, current?: PossibleDate): string;
|
|
76
90
|
/**
|
|
77
|
-
* Return
|
|
91
|
+
* Return full description of when a date happened, e.g. `10 days` or `2 hours` or `-1 week`
|
|
92
|
+
*
|
|
78
93
|
* @param target The date when the thing will happen.
|
|
79
94
|
* @param current Today's date (or a different date to measure from).
|
|
80
95
|
*/
|
|
81
|
-
export declare
|
|
96
|
+
export declare const formatFullUntil: (target: PossibleDate, current?: PossibleDate | undefined) => string;
|
|
82
97
|
/**
|
|
83
|
-
* Return when a date will happen, e.g. `10 days` or `2 hours` or `-1 week`
|
|
98
|
+
* Return full description of when a date will happen, e.g. `10 days` or `2 hours` or `-1 week`
|
|
99
|
+
*
|
|
84
100
|
* @param target The date when the thing happened.
|
|
85
101
|
* @param current Today's date (or a different date to measure from).
|
|
86
102
|
*/
|
|
87
|
-
export declare
|
|
103
|
+
export declare const formatFullAgo: (target: PossibleDate, current?: PossibleDate | undefined) => string;
|
|
88
104
|
/**
|
|
89
|
-
*
|
|
105
|
+
* Compact how long until a date happens, e.g. `in 10d` or `2h ago` or `in 1w`
|
|
106
|
+
*
|
|
107
|
+
* @param target The date when the thing will happen.
|
|
108
|
+
* @param current Today's date (or a different date to measure from).
|
|
109
|
+
*/
|
|
110
|
+
export declare function formatWhen(target: PossibleDate, current?: PossibleDate): string;
|
|
111
|
+
/**
|
|
112
|
+
* Return short description of when a date happened, e.g. `10d` or `2h` or `-1w`
|
|
113
|
+
*
|
|
114
|
+
* @param target The date when the thing will happen.
|
|
115
|
+
* @param current Today's date (or a different date to measure from).
|
|
116
|
+
*/
|
|
117
|
+
export declare const formatUntil: (target: PossibleDate, current?: PossibleDate | undefined) => string;
|
|
118
|
+
/**
|
|
119
|
+
* Return short description of when a date will happen, e.g. `10d` or `2h` or `-1w`
|
|
120
|
+
*
|
|
90
121
|
* @param target The date when the thing happened.
|
|
91
122
|
* @param current Today's date (or a different date to measure from).
|
|
92
123
|
*/
|
|
93
|
-
export declare
|
|
124
|
+
export declare const formatAgo: (target: PossibleDate, current?: PossibleDate | undefined) => string;
|
|
94
125
|
/** Format a date in the browser locale. */
|
|
95
|
-
export declare
|
|
126
|
+
export declare const formatDate: (date: PossibleDate) => string;
|
|
96
127
|
/** Is a date in the past? */
|
|
97
128
|
export declare const isPast: (target: PossibleDate, current?: PossibleDate | undefined) => boolean;
|
|
98
129
|
/** Is a date in the future? */
|
package/util/date.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { AssertionError } from "../error/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { formatFullQuantity, formatQuantity } from "./number.js";
|
|
3
|
+
/** One second in millseconds. */
|
|
4
|
+
export const SECOND = 1000;
|
|
3
5
|
/** One minute in millseconds. */
|
|
4
|
-
export const MINUTE = 60 *
|
|
6
|
+
export const MINUTE = 60 * SECOND;
|
|
5
7
|
/** One hour in millseconds. */
|
|
6
|
-
export const HOUR =
|
|
8
|
+
export const HOUR = 60 * MINUTE;
|
|
7
9
|
/** One day in millseconds. */
|
|
8
|
-
export const DAY =
|
|
10
|
+
export const DAY = 24 * HOUR;
|
|
9
11
|
/** One week in millseconds. */
|
|
10
|
-
export const WEEK =
|
|
12
|
+
export const WEEK = 7 * DAY;
|
|
13
|
+
/** One month in millseconds. */
|
|
14
|
+
export const MONTH = 30 * DAY;
|
|
11
15
|
/** One year in millseconds. */
|
|
12
|
-
export const YEAR =
|
|
16
|
+
export const YEAR = 365 * DAY;
|
|
13
17
|
/** Is a value a date? */
|
|
14
18
|
export const isDate = (v) => v instanceof Date;
|
|
15
19
|
/**
|
|
@@ -101,111 +105,114 @@ export function addHours(change, target) {
|
|
|
101
105
|
date.setHours(date.getHours() + change);
|
|
102
106
|
return date;
|
|
103
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Get the duration (in milliseconds) between two dates.
|
|
110
|
+
*
|
|
111
|
+
* @param target The date when the thing will happen or did happen.
|
|
112
|
+
* @param current Today's date (or a different date to measure from).
|
|
113
|
+
*/
|
|
114
|
+
export const getDuration = (target, current) => getDate(target).getTime() - getDate(current).getTime();
|
|
104
115
|
/** Count the number of seconds until a date. */
|
|
105
|
-
export const
|
|
116
|
+
export const getSecondsUntil = (target, current) => getDuration(target, current) / 1000;
|
|
106
117
|
/** Count the number of days ago a date was. */
|
|
107
|
-
export const
|
|
118
|
+
export const getSecondsAgo = (target, current) => 0 - getSecondsUntil(target, current);
|
|
108
119
|
/** Count the number of days until a date. */
|
|
109
|
-
export const
|
|
120
|
+
export const getDaysUntil = (target, current) => Math.round((getMidnight(target).getTime() - getMidnight(current).getTime()) / 86400000);
|
|
110
121
|
/** Count the number of days ago a date was. */
|
|
111
|
-
export const
|
|
122
|
+
export const getDaysAgo = (target, current) => 0 - getDaysUntil(target, current);
|
|
112
123
|
/** Count the number of weeks until a date. */
|
|
113
|
-
export const
|
|
124
|
+
export const getWeeksUntil = (target, current) => Math.floor(getDaysUntil(target, current) / 7);
|
|
114
125
|
/** Count the number of weeks ago a date was. */
|
|
115
|
-
export const
|
|
116
|
-
/**
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (abs
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
return [num, num === 1 ? "minute" : "minutes"];
|
|
133
|
-
}
|
|
134
|
-
// Up to 24 hours — show hours, e.g. '23 hours ago'
|
|
135
|
-
if (abs < 86400) {
|
|
136
|
-
const num = Math.round(seconds / 3600);
|
|
137
|
-
return [num, num === 1 ? "hour" : "hours"];
|
|
138
|
-
}
|
|
139
|
-
// Up to 2 weeks — show days, e.g. '13 days ago'
|
|
140
|
-
if (abs < 1209600) {
|
|
141
|
-
const num = Math.round(seconds / 86400);
|
|
142
|
-
return [num, num === 1 ? "day" : "days"];
|
|
143
|
-
}
|
|
144
|
-
// Up to 2 months — show weeks, e.g. '6 weeks ago'
|
|
145
|
-
if (abs < 5184000) {
|
|
146
|
-
const num = Math.round(seconds / 604800);
|
|
147
|
-
return [num, num === 1 ? "week" : "weeks"];
|
|
148
|
-
}
|
|
149
|
-
// Up to 18 months — show months, e.g. '6 months ago'
|
|
150
|
-
if (abs < 46656000) {
|
|
151
|
-
const num = Math.round(seconds / 2592000);
|
|
152
|
-
return [num, num === 1 ? "month" : "months"];
|
|
153
|
-
}
|
|
154
|
-
// Above 18 months — show years, e.g. '2 years ago'
|
|
155
|
-
return [Math.round(seconds / 31536000), "year"];
|
|
126
|
+
export const getWeeksAgo = (target, current) => 0 - getWeeksUntil(target, current);
|
|
127
|
+
/** Format a full description of a duration of time using the most reasonable units e.g. `5 years` or `1 week` or `4 minutes` or `12 milliseconds`. */
|
|
128
|
+
export function formatFullDuration(ms) {
|
|
129
|
+
const abs = Math.abs(ms);
|
|
130
|
+
if (abs <= 99 * SECOND)
|
|
131
|
+
return formatFullQuantity(ms, "second", "seconds", 0); // Up to 99 seconds, e.g. '22 seconds ago'
|
|
132
|
+
if (abs <= HOUR)
|
|
133
|
+
return formatFullQuantity(ms / MINUTE, "minute", "minutes", 0); // Up to one hour — show minutes, e.g. '18 minutes ago'
|
|
134
|
+
if (abs <= DAY)
|
|
135
|
+
return formatFullQuantity(ms / HOUR, "hour", "hours", 0); // Up to one day — show hours, e.g. '23 hours ago'
|
|
136
|
+
if (abs <= 2 * WEEK)
|
|
137
|
+
return formatFullQuantity(ms / DAY, "day", "days", 0); // Up to 2 weeks — show days, e.g. '13 days ago'
|
|
138
|
+
if (abs <= 10 * WEEK)
|
|
139
|
+
return formatFullQuantity(ms / WEEK, "week", "weeks", 0); // Up to 2 months — show weeks, e.g. '6 weeks ago'
|
|
140
|
+
if (abs <= 18 * MONTH)
|
|
141
|
+
return formatFullQuantity(ms / MONTH, "month", "months", 0); // Up to 18 months — show months, e.g. '6 months ago'
|
|
142
|
+
return formatFullQuantity(ms / YEAR, "year", "years", 0); // Above 18 months — show years, e.g. '2 years ago'
|
|
156
143
|
}
|
|
157
|
-
/**
|
|
158
|
-
export function
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
144
|
+
/** Format a description of a duration of time using the most reasonable units e.g. `5y` or `4m` or `12ms`. */
|
|
145
|
+
export function formatDuration(ms) {
|
|
146
|
+
const abs = Math.abs(ms);
|
|
147
|
+
if (abs <= 99 * SECOND)
|
|
148
|
+
return formatQuantity(ms, "s", 0); // Up to 99 seconds, e.g. '22 seconds ago'
|
|
149
|
+
if (abs <= HOUR)
|
|
150
|
+
return formatQuantity(ms / MINUTE, "m", 0); // Up to one hour — show minutes, e.g. '18 minutes ago'
|
|
151
|
+
if (abs <= DAY)
|
|
152
|
+
return formatQuantity(ms / HOUR, "h", 0); // Up to one day — show hours, e.g. '23 hours ago'
|
|
153
|
+
if (abs <= 2 * WEEK)
|
|
154
|
+
return formatQuantity(ms / DAY, "d", 0); // Up to 2 weeks — show days, e.g. '13 days ago'
|
|
155
|
+
if (abs <= 10 * WEEK)
|
|
156
|
+
return formatQuantity(ms / WEEK, "w", 0); // Up to 2 months — show weeks, e.g. '6 weeks ago'
|
|
157
|
+
if (abs <= 18 * MONTH)
|
|
158
|
+
return formatQuantity(ms / MONTH, "m", 0); // Up to 18 months — show months, e.g. '6 months ago'
|
|
159
|
+
return formatQuantity(ms / YEAR, "y", 0); // Above 18 months — show years, e.g. '2 years ago'
|
|
168
160
|
}
|
|
169
161
|
/**
|
|
170
|
-
* Return
|
|
171
|
-
*
|
|
162
|
+
* Return full description of the gap between two dates, e.g. `in 10 days` or `2 hours ago`
|
|
163
|
+
*
|
|
164
|
+
* @param target The date when the thing will happen or did happen.
|
|
172
165
|
* @param current Today's date (or a different date to measure from).
|
|
173
166
|
*/
|
|
174
|
-
export function
|
|
175
|
-
const
|
|
176
|
-
|
|
167
|
+
export function formatFullWhen(target, current) {
|
|
168
|
+
const ms = getDuration(target, current);
|
|
169
|
+
const abs = Math.abs(ms);
|
|
170
|
+
const duration = formatFullDuration(abs);
|
|
171
|
+
return abs < 10 * SECOND ? "just now" : ms > 0 ? `in ${duration}` : `${duration} ago`;
|
|
177
172
|
}
|
|
178
173
|
/**
|
|
179
|
-
* Return
|
|
174
|
+
* Return full description of when a date happened, e.g. `10 days` or `2 hours` or `-1 week`
|
|
175
|
+
*
|
|
180
176
|
* @param target The date when the thing will happen.
|
|
181
177
|
* @param current Today's date (or a different date to measure from).
|
|
182
178
|
*/
|
|
183
|
-
export
|
|
184
|
-
const [amount, units] = diffDates(target, current);
|
|
185
|
-
return `${formatNumber(amount)}${units.substr(0, 1)}`;
|
|
186
|
-
}
|
|
179
|
+
export const formatFullUntil = (target, current) => formatFullDuration(getDuration(target, current));
|
|
187
180
|
/**
|
|
188
|
-
* Return when a date will happen, e.g. `10 days` or `2 hours` or `-1 week`
|
|
181
|
+
* Return full description of when a date will happen, e.g. `10 days` or `2 hours` or `-1 week`
|
|
182
|
+
*
|
|
189
183
|
* @param target The date when the thing happened.
|
|
190
184
|
* @param current Today's date (or a different date to measure from).
|
|
191
185
|
*/
|
|
192
|
-
export
|
|
193
|
-
|
|
194
|
-
|
|
186
|
+
export const formatFullAgo = (target, current) => formatFullDuration(getDuration(current, target));
|
|
187
|
+
/**
|
|
188
|
+
* Compact how long until a date happens, e.g. `in 10d` or `2h ago` or `in 1w`
|
|
189
|
+
*
|
|
190
|
+
* @param target The date when the thing will happen.
|
|
191
|
+
* @param current Today's date (or a different date to measure from).
|
|
192
|
+
*/
|
|
193
|
+
export function formatWhen(target, current) {
|
|
194
|
+
const ms = getDuration(target, current);
|
|
195
|
+
const abs = Math.abs(ms);
|
|
196
|
+
const duration = formatDuration(abs);
|
|
197
|
+
return abs < 10 * SECOND ? "just now" : ms > 0 ? `in ${duration}` : `${duration} ago`;
|
|
195
198
|
}
|
|
196
199
|
/**
|
|
197
|
-
* Return
|
|
200
|
+
* Return short description of when a date happened, e.g. `10d` or `2h` or `-1w`
|
|
201
|
+
*
|
|
202
|
+
* @param target The date when the thing will happen.
|
|
203
|
+
* @param current Today's date (or a different date to measure from).
|
|
204
|
+
*/
|
|
205
|
+
export const formatUntil = (target, current) => formatDuration(getDuration(target, current));
|
|
206
|
+
/**
|
|
207
|
+
* Return short description of when a date will happen, e.g. `10d` or `2h` or `-1w`
|
|
208
|
+
*
|
|
198
209
|
* @param target The date when the thing happened.
|
|
199
210
|
* @param current Today's date (or a different date to measure from).
|
|
200
211
|
*/
|
|
201
|
-
export
|
|
202
|
-
const [amount, units] = diffDates(current, target);
|
|
203
|
-
return `${formatNumber(amount)}${units.substr(0, 1)}`;
|
|
204
|
-
}
|
|
212
|
+
export const formatAgo = (target, current) => formatDuration(getDuration(current, target));
|
|
205
213
|
/** Format a date in the browser locale. */
|
|
206
|
-
export
|
|
207
|
-
|
|
208
|
-
}
|
|
214
|
+
export const formatDate = (date) => _formatter.format(getDate(date));
|
|
215
|
+
const _formatter = new Intl.DateTimeFormat(undefined, {});
|
|
209
216
|
/** Is a date in the past? */
|
|
210
217
|
export const isPast = (target, current) => getDate(target) < getDate(current);
|
|
211
218
|
/** Is a date in the future? */
|
package/util/number.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
export declare const TRILLION = 1000000000000;
|
|
2
|
+
export declare const BILLION = 1000000000;
|
|
3
|
+
export declare const MILLION = 1000000;
|
|
1
4
|
/** Is a value a number? */
|
|
2
5
|
export declare const isNumber: (v: unknown) => v is number;
|
|
3
6
|
/**
|
|
@@ -21,25 +24,69 @@ export declare function getNumber(value: unknown): number;
|
|
|
21
24
|
*
|
|
22
25
|
* @param num The number to round.
|
|
23
26
|
* @param step The rounding to round to, e.g. `2` or `0.1` (defaults to `1`, i.e. round numbers).
|
|
24
|
-
*
|
|
27
|
+
*
|
|
28
|
+
* @returns The number rounded to the specified step.
|
|
25
29
|
*/
|
|
26
|
-
export declare
|
|
30
|
+
export declare const roundStep: (num: number, step?: number) => number;
|
|
27
31
|
/**
|
|
28
32
|
* Round a number to a specified set of decimal places.
|
|
29
|
-
* -
|
|
33
|
+
* - Better than `Math.round()` because it allows a `precision` argument.
|
|
34
|
+
* - Better than `num.toFixed()` because it trims excess `0` zeroes.
|
|
30
35
|
*
|
|
31
|
-
* @param num The number to
|
|
32
|
-
* @param precision Maximum of digits shown after the decimal point (defaults to 10)
|
|
33
|
-
*
|
|
36
|
+
* @param num The number to round.
|
|
37
|
+
* @param precision Maximum number of digits shown after the decimal point (defaults to 10).
|
|
38
|
+
*
|
|
39
|
+
* @returns The number rounded to the specified precision.
|
|
40
|
+
*/
|
|
41
|
+
export declare const roundNumber: (num: number, precision?: number) => number;
|
|
42
|
+
/**
|
|
43
|
+
* Truncate a number to a specified set of decimal places.
|
|
44
|
+
* - Better than `Math.trunc()` because it allows a `precision` argument.
|
|
45
|
+
*
|
|
46
|
+
* @param num The number to truncate.
|
|
47
|
+
* @param precision Maximum number of digits shown after the decimal point (defaults to 10).
|
|
48
|
+
*
|
|
49
|
+
* @returns The number truncated to the specified precision.
|
|
34
50
|
*/
|
|
35
|
-
export declare const
|
|
51
|
+
export declare const truncateNumber: (num: number, precision?: number) => number;
|
|
36
52
|
/**
|
|
37
53
|
* Format a number (based on the user's browser settings).
|
|
54
|
+
*
|
|
38
55
|
* @param num The number to format.
|
|
39
|
-
* @param
|
|
56
|
+
* @param maxPrecision Maximum number of digits shown after the decimal point (defaults to 2).
|
|
57
|
+
* @param minPrecision Minimum number of digits shown after the decimal point (defaults to 0).
|
|
58
|
+
*
|
|
40
59
|
* @returns The number formatted as a string in the browser's current locale.
|
|
41
60
|
*/
|
|
42
|
-
export declare const formatNumber: (num: number,
|
|
61
|
+
export declare const formatNumber: (num: number, maxPrecision?: number, minPrecision?: number) => string;
|
|
62
|
+
/** Format a number with a short suffix (number and suffix are separated by a non-breaking narrow space). */
|
|
63
|
+
export declare const formatQuantity: (num: number, suffix: string, maxPrecision?: number | undefined, minPrecision?: number | undefined) => string;
|
|
64
|
+
/** Format a number with a longer full-word suffix (number and suffix are separated by a non-breaking space). */
|
|
65
|
+
export declare function formatFullQuantity(num: number, singular: string, plural: string, maxPrecision?: number, minPrecision?: number): string;
|
|
66
|
+
/**
|
|
67
|
+
* Cram a large whole numbers into a space efficient format, e.g. `14.7M`
|
|
68
|
+
* - Improves glanceability.
|
|
69
|
+
* - Keeps number of characters under five if possible.
|
|
70
|
+
*
|
|
71
|
+
* - Numbers over 100 trillion: `157T`
|
|
72
|
+
* - Numbers over 10 trillion: `15.7T` (includes zero e.g. `40.0T` for consistency).
|
|
73
|
+
* - Numbers over 1 trillion: `1.57T` (includes zeros e.g. `4.00T` for consistency).
|
|
74
|
+
* - Numbers over 100 billion: `157B`
|
|
75
|
+
* - Numbers over 10 billion: `15.7B` (includes zero e.g. `40.0B` for consistency).
|
|
76
|
+
* - Numbers over 1 billion: `1.57B` (includes zeros e.g. `4.00B` for consistency).
|
|
77
|
+
* - Numbers over 100 million: `157M`
|
|
78
|
+
* - Numbers over 10 million: `15.7M` (includes zero e.g. `40.0M` for consistency).
|
|
79
|
+
* - Numbers over 1 million: `1.57M` (includes zeros e.g. `4.00M` for consistency).
|
|
80
|
+
* - Numbers over 100,000: `157K`
|
|
81
|
+
* - Numbers over 10,000: `15.7K` (includes zero e.g. `14.0K` for consistency).
|
|
82
|
+
* - Smaller numbers: `1570` and `157` and `15.7` and `1.6`
|
|
83
|
+
*
|
|
84
|
+
* @param num The number to format.
|
|
85
|
+
* @param precision Maximum number of digits shown after the decimal point (defaults to 10, only used for numbers under 10,000).
|
|
86
|
+
*
|
|
87
|
+
* @returns The number formatted as a crammed string.
|
|
88
|
+
*/
|
|
89
|
+
export declare function cramNumber(num: number): string;
|
|
43
90
|
/**
|
|
44
91
|
* Is a number within a specified range?
|
|
45
92
|
*
|