shelving 1.48.1 → 1.49.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/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "state-management",
12
12
  "query-builder"
13
13
  ],
14
- "version": "1.48.1",
14
+ "version": "1.49.0",
15
15
  "repository": "https://github.com/dhoulb/shelving",
16
16
  "author": "Dave Houlbrooke <dave@shax.com>",
17
17
  "license": "0BSD",
package/util/date.d.ts CHANGED
@@ -1,17 +1,3 @@
1
- /** One second in millseconds. */
2
- export declare const SECOND = 1000;
3
- /** One minute in millseconds. */
4
- export declare const MINUTE: number;
5
- /** One hour in millseconds. */
6
- export declare const HOUR: number;
7
- /** One day in millseconds. */
8
- export declare const DAY: number;
9
- /** One week in millseconds. */
10
- export declare const WEEK: number;
11
- /** One month in millseconds. */
12
- export declare const MONTH: number;
13
- /** One year in millseconds. */
14
- export declare const YEAR: number;
15
1
  /** Is a value a date? */
16
2
  export declare const isDate: (v: unknown) => v is Date;
17
3
  /** Value that can possibly be converted to a `Date` instance. */
@@ -77,9 +63,9 @@ export declare const getWeeksUntil: (target: PossibleDate, current?: PossibleDat
77
63
  /** Count the number of weeks ago a date was. */
78
64
  export declare const getWeeksAgo: (target: PossibleDate, current?: PossibleDate | undefined) => number;
79
65
  /** 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;
66
+ export declare const formatFullDuration: (ms: number, maxPrecision?: number | undefined, minPrecision?: number | undefined) => string;
81
67
  /** 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;
68
+ export declare const formatDuration: (ms: number, maxPrecision?: number | undefined, minPrecision?: number | undefined) => string;
83
69
  /**
84
70
  * Return full description of the gap between two dates, e.g. `in 10 days` or `2 hours ago`
85
71
  *
@@ -87,13 +73,6 @@ export declare function formatDuration(ms: number): string;
87
73
  * @param current Today's date (or a different date to measure from).
88
74
  */
89
75
  export declare function formatFullWhen(target: PossibleDate, current?: PossibleDate): string;
90
- /**
91
- * Return full description of when a date happened, e.g. `10 days` or `2 hours` or `-1 week`
92
- *
93
- * @param target The date when the thing will happen.
94
- * @param current Today's date (or a different date to measure from).
95
- */
96
- export declare const formatFullUntil: (target: PossibleDate, current?: PossibleDate | undefined) => string;
97
76
  /**
98
77
  * Return full description of when a date will happen, e.g. `10 days` or `2 hours` or `-1 week`
99
78
  *
package/util/date.js CHANGED
@@ -1,19 +1,5 @@
1
1
  import { AssertionError } from "../error/index.js";
2
- import { formatFullQuantity, formatQuantity } from "./number.js";
3
- /** One second in millseconds. */
4
- export const SECOND = 1000;
5
- /** One minute in millseconds. */
6
- export const MINUTE = 60 * SECOND;
7
- /** One hour in millseconds. */
8
- export const HOUR = 60 * MINUTE;
9
- /** One day in millseconds. */
10
- export const DAY = 24 * HOUR;
11
- /** One week in millseconds. */
12
- export const WEEK = 7 * DAY;
13
- /** One month in millseconds. */
14
- export const MONTH = 30 * DAY;
15
- /** One year in millseconds. */
16
- export const YEAR = 365 * DAY;
2
+ import { DAY, HOUR, MINUTE, MONTH, SECOND, WEEK, YEAR, formatUnits, formatFullUnits } from "./units.js";
17
3
  /** Is a value a date? */
18
4
  export const isDate = (v) => v instanceof Date;
19
5
  /**
@@ -124,40 +110,26 @@ export const getDaysAgo = (target, current) => 0 - getDaysUntil(target, current)
124
110
  export const getWeeksUntil = (target, current) => Math.floor(getDaysUntil(target, current) / 7);
125
111
  /** Count the number of weeks ago a date was. */
126
112
  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) {
113
+ function _formatDuration(formatter, ms, maxPrecision = 0, minPrecision) {
129
114
  const abs = Math.abs(ms);
130
115
  if (abs <= 99 * SECOND)
131
- return formatFullQuantity(ms, "second", "seconds", 0); // Up to 99 seconds, e.g. '22 seconds ago'
116
+ return formatter(ms, "second", maxPrecision, minPrecision); // Up to 99 seconds, e.g. '22 seconds ago'
132
117
  if (abs <= HOUR)
133
- return formatFullQuantity(ms / MINUTE, "minute", "minutes", 0); // Up to one hour — show minutes, e.g. '18 minutes ago'
118
+ return formatter(ms / MINUTE, "minute", maxPrecision, minPrecision); // Up to one hour — show minutes, e.g. '18 minutes ago'
134
119
  if (abs <= DAY)
135
- return formatFullQuantity(ms / HOUR, "hour", "hours", 0); // Up to one day — show hours, e.g. '23 hours ago'
120
+ return formatter(ms / HOUR, "hour", maxPrecision, minPrecision); // Up to one day — show hours, e.g. '23 hours ago'
136
121
  if (abs <= 2 * WEEK)
137
- return formatFullQuantity(ms / DAY, "day", "days", 0); // Up to 2 weeks — show days, e.g. '13 days ago'
122
+ return formatter(ms / DAY, "day", maxPrecision, minPrecision); // Up to 2 weeks — show days, e.g. '13 days ago'
138
123
  if (abs <= 10 * WEEK)
139
- return formatFullQuantity(ms / WEEK, "week", "weeks", 0); // Up to 2 months — show weeks, e.g. '6 weeks ago'
124
+ return formatter(ms / WEEK, "week", maxPrecision, minPrecision); // Up to 2 months — show weeks, e.g. '6 weeks ago'
140
125
  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'
126
+ return formatter(ms / MONTH, "month", maxPrecision, minPrecision); // Up to 18 months — show months, e.g. '6 months ago'
127
+ return formatter(ms / YEAR, "year", maxPrecision, minPrecision); // Above 18 months — show years, e.g. '2 years ago'
143
128
  }
129
+ /** 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`. */
130
+ export const formatFullDuration = (ms, maxPrecision, minPrecision) => _formatDuration(formatFullUnits, ms, maxPrecision, minPrecision);
144
131
  /** 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'
160
- }
132
+ export const formatDuration = (ms, maxPrecision, minPrecision) => _formatDuration(formatUnits, ms, maxPrecision, minPrecision);
161
133
  /**
162
134
  * Return full description of the gap between two dates, e.g. `in 10 days` or `2 hours ago`
163
135
  *
@@ -170,13 +142,6 @@ export function formatFullWhen(target, current) {
170
142
  const duration = formatFullDuration(abs);
171
143
  return abs < 10 * SECOND ? "just now" : ms > 0 ? `in ${duration}` : `${duration} ago`;
172
144
  }
173
- /**
174
- * Return full description of when a date happened, e.g. `10 days` or `2 hours` or `-1 week`
175
- *
176
- * @param target The date when the thing will happen.
177
- * @param current Today's date (or a different date to measure from).
178
- */
179
- export const formatFullUntil = (target, current) => formatFullDuration(getDuration(target, current));
180
145
  /**
181
146
  * Return full description of when a date will happen, e.g. `10 days` or `2 hours` or `-1 week`
182
147
  *
package/util/number.d.ts CHANGED
@@ -59,9 +59,9 @@ export declare const truncateNumber: (num: number, precision?: number) => number
59
59
  * @returns The number formatted as a string in the browser's current locale.
60
60
  */
61
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). */
62
+ /** Format a number with a short suffix. */
63
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). */
64
+ /** Format a number with a longer full-word suffix. */
65
65
  export declare function formatFullQuantity(num: number, singular: string, plural: string, maxPrecision?: number, minPrecision?: number): string;
66
66
  /**
67
67
  * Cram a large whole numbers into a space efficient format, e.g. `14.7M`
@@ -103,6 +103,13 @@ export declare const isBetween: (num: number, start: number, end: number) => boo
103
103
  * @param end The end of the range, e.g. `20`
104
104
  */
105
105
  export declare const getBetween: (num: number, start: number, end: number) => number;
106
+ /**
107
+ * Get a number as a percentage of another number.
108
+ *
109
+ * @param numerator Number representing the amount of progress.
110
+ * @param denumerator The number representing the whole amount.
111
+ */
112
+ export declare const getPercent: (numerator: number, denumerator: number) => number;
106
113
  /** Sum an iterable set of numbers and return the total. */
107
114
  export declare function sumNumbers(nums: Iterable<number>): number;
108
115
  /** Find the number that's closest to a target in an iterable set of numbers. */
package/util/number.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { AssertionError } from "../error/index.js";
2
- import { NBSP, NNBSP } from "./string.js";
3
2
  // Constants.
4
3
  export const TRILLION = 1000000000000;
5
4
  export const BILLION = 1000000000;
@@ -76,12 +75,12 @@ export const truncateNumber = (num, precision = 0) => Math.trunc(num * 10 ** pre
76
75
  * @returns The number formatted as a string in the browser's current locale.
77
76
  */
78
77
  export const formatNumber = (num, maxPrecision = 4, minPrecision = 0) => new Intl.NumberFormat(undefined, { maximumFractionDigits: maxPrecision, minimumFractionDigits: minPrecision }).format(num);
79
- /** Format a number with a short suffix (number and suffix are separated by a non-breaking narrow space). */
80
- export const formatQuantity = (num, suffix, maxPrecision, minPrecision) => `${formatNumber(num, maxPrecision, minPrecision)}${NNBSP}${suffix}`;
81
- /** Format a number with a longer full-word suffix (number and suffix are separated by a non-breaking space). */
78
+ /** Format a number with a short suffix. */
79
+ export const formatQuantity = (num, suffix, maxPrecision, minPrecision) => `${formatNumber(num, maxPrecision, minPrecision)}${suffix}`;
80
+ /** Format a number with a longer full-word suffix. */
82
81
  export function formatFullQuantity(num, singular, plural, maxPrecision, minPrecision) {
83
82
  const qty = formatNumber(num, maxPrecision, minPrecision);
84
- return `${qty}${NBSP}${qty === "1" ? singular : plural}`;
83
+ return `${qty} ${qty === "1" ? singular : plural}`;
85
84
  }
86
85
  /**
87
86
  * Cram a large whole numbers into a space efficient format, e.g. `14.7M`
@@ -138,6 +137,13 @@ export const isBetween = (num, start, end) => num >= start && num <= end;
138
137
  * @param end The end of the range, e.g. `20`
139
138
  */
140
139
  export const getBetween = (num, start, end) => Math.max(start, Math.min(end, num));
140
+ /**
141
+ * Get a number as a percentage of another number.
142
+ *
143
+ * @param numerator Number representing the amount of progress.
144
+ * @param denumerator The number representing the whole amount.
145
+ */
146
+ export const getPercent = (numerator, denumerator) => Math.max(0, Math.min(100, (100 / denumerator) * numerator));
141
147
  /** Sum an iterable set of numbers and return the total. */
142
148
  export function sumNumbers(nums) {
143
149
  let sum = 0;
package/util/units.d.ts CHANGED
@@ -1,9 +1,25 @@
1
+ /** One second in millseconds. */
2
+ export declare const SECOND = 1000;
3
+ /** One minute in millseconds. */
4
+ export declare const MINUTE: number;
5
+ /** One hour in millseconds. */
6
+ export declare const HOUR: number;
7
+ /** One day in millseconds. */
8
+ export declare const DAY: number;
9
+ /** One week in millseconds. */
10
+ export declare const WEEK: number;
11
+ /** One month in millseconds. */
12
+ export declare const MONTH: number;
13
+ /** One year in millseconds. */
14
+ export declare const YEAR: number;
1
15
  /** Valid information about a unit of measure. */
2
16
  export declare type UnitData = {
3
- /** Plural name for a unit, e.g. `feet` */
4
- readonly plural?: string;
5
17
  /** Type of a unit. */
6
18
  readonly type: UnitType;
19
+ /** Singular name for a unit, e.g. `foot` (only needed if different from reference). */
20
+ readonly singular?: string;
21
+ /** Plural name for a unit, e.g. `feet` */
22
+ readonly plural?: string;
7
23
  /** Short suffix for this unit, e.g. `km` */
8
24
  readonly suffix: string;
9
25
  /** All units must specify their 'base' unit, e.g. `meter` for for distance units and `liter` for volume units. */
@@ -14,7 +30,7 @@ export declare type UnitData = {
14
30
  /** Valid system of measurement reference. */
15
31
  export declare type UnitType = "percentage" | "angle" | "temperature" | "length" | "speed" | "pace" | "mass" | "time" | "volume";
16
32
  /** Valid unit of measurement reference (correspond to units allowed in `Intl.NumberFormat`, but not all). */
17
- export declare type UnitReference = "percent" | "degree" | "millimeter" | "centimeter" | "meter" | "kilometer" | "mile" | "yard" | "foot" | "inch" | "liter" | "milliliter" | "gallon" | "fluid-ounce" | "milligram" | "gram" | "kilogram" | "pound" | "stone" | "ounce" | "millisecond" | "second" | "minute" | "day" | "hour" | "week" | "month" | "year";
33
+ export declare type UnitReference = "percent" | "permille" | "permyriad" | "ppm" | "percentage-point" | "basis-point" | "degree" | "millimeter" | "centimeter" | "meter" | "kilometer" | "mile" | "yard" | "foot" | "inch" | "liter" | "milliliter" | "gallon" | "fluid-ounce" | "milligram" | "gram" | "kilogram" | "pound" | "stone" | "ounce" | "millisecond" | "second" | "minute" | "day" | "hour" | "week" | "month" | "year";
18
34
  /** List of units. */
19
35
  export declare const UNITS: {
20
36
  [K in UnitReference]: UnitData;
package/util/units.js CHANGED
@@ -1,37 +1,55 @@
1
1
  import { AssertionError } from "../error/index.js";
2
- import { DAY, HOUR, MINUTE, MONTH, SECOND, WEEK, YEAR } from "./date.js";
3
- import { formatFullQuantity, formatQuantity } from "./number.js";
2
+ import { formatFullQuantity, formatQuantity, MILLION } from "./number.js";
4
3
  import { NNBSP } from "./string.js";
4
+ /** One second in millseconds. */
5
+ export const SECOND = 1000;
6
+ /** One minute in millseconds. */
7
+ export const MINUTE = 60 * SECOND;
8
+ /** One hour in millseconds. */
9
+ export const HOUR = 60 * MINUTE;
10
+ /** One day in millseconds. */
11
+ export const DAY = 24 * HOUR;
12
+ /** One week in millseconds. */
13
+ export const WEEK = 7 * DAY;
14
+ /** One month in millseconds. */
15
+ export const MONTH = 30 * DAY;
16
+ /** One year in millseconds. */
17
+ export const YEAR = 365 * DAY;
5
18
  /** List of units. */
6
19
  export const UNITS = {
7
20
  "percent": { type: "percentage", base: 1, suffix: "%" },
8
- "degree": { type: "angle", base: 1, suffix: "deg" },
9
- "millimeter": { type: "length", base: 1, suffix: "mm" },
10
- "centimeter": { type: "length", base: 10, suffix: "cm" },
11
- "meter": { type: "length", base: 1000, centimeter: 100, millimeter: 1000, suffix: "m" },
12
- "kilometer": { type: "length", base: 1000000, centimeter: 100000, millimeter: 1000000, suffix: "km" },
13
- "inch": { type: "length", base: 25.4, suffix: "in" },
14
- "foot": { type: "length", base: 304.8, inch: 12, suffix: "ft", plural: "feet" },
15
- "yard": { type: "length", base: 914.4, inch: 36, foot: 3, suffix: "yd" },
16
- "mile": { type: "length", base: 1609344, yard: 1760, foot: 5280, inch: 63360, suffix: "mi" },
17
- "milliliter": { type: "volume", base: 1, suffix: "ml" },
18
- "liter": { type: "volume", base: 1000, suffix: "l" },
19
- "fluid-ounce": { type: "volume", base: 29.5735295625, gallon: 128, suffix: `fl${NNBSP}oz` },
20
- "gallon": { type: "volume", base: 3785.411784, suffix: "gal" },
21
- "milligram": { type: "mass", base: 1, suffix: "mg" },
22
- "gram": { type: "mass", base: 1000, suffix: "g" },
23
- "kilogram": { type: "mass", base: 1000000, suffix: "kg" },
24
- "ounce": { type: "mass", base: 28349.523125, pound: 0.0625, suffix: "oz" },
25
- "pound": { type: "mass", base: 453592.37, ounce: 16, suffix: "lb" },
26
- "stone": { type: "mass", base: 6350293.18, pound: 14, ounce: 224, suffix: "st", plural: "stone" },
27
- "millisecond": { type: "time", base: 1, suffix: "ms" },
28
- "second": { type: "time", base: SECOND, suffix: "s" },
29
- "minute": { type: "time", base: MINUTE, suffix: "m" },
30
- "hour": { type: "time", base: HOUR, suffix: "h" },
31
- "day": { type: "time", base: DAY, suffix: "d" },
32
- "week": { type: "time", base: WEEK, suffix: "w" },
33
- "month": { type: "time", base: MONTH, suffix: "m" },
34
- "year": { type: "time", base: YEAR, suffix: "y" },
21
+ "permille": { type: "percentage", base: 10, suffix: `${NNBSP}‰` },
22
+ "permyriad": { type: "percentage", base: 100, suffix: `${NNBSP}‱` },
23
+ "ppm": { type: "percentage", base: MILLION, suffix: `${NNBSP}ppm`, singular: "part per million", plural: "parts per million" },
24
+ "percentage-point": { type: "percentage", base: 1, suffix: `${NNBSP}pp`, singular: "percentage point", plural: "percentage points" },
25
+ "basis-point": { type: "percentage", base: 10000, suffix: `${NNBSP}bp`, singular: "basis point", plural: "basis points" },
26
+ "degree": { type: "angle", base: 1, suffix: `${NNBSP}deg` },
27
+ "millimeter": { type: "length", base: 1, suffix: `${NNBSP}mm` },
28
+ "centimeter": { type: "length", base: 10, suffix: `${NNBSP}cm` },
29
+ "meter": { type: "length", base: 1000, centimeter: 100, millimeter: 1000, suffix: `${NNBSP}m` },
30
+ "kilometer": { type: "length", base: 1000000, centimeter: 100000, millimeter: 1000000, suffix: `${NNBSP}km` },
31
+ "inch": { type: "length", base: 25.4, suffix: `${NNBSP}in` },
32
+ "foot": { type: "length", base: 304.8, inch: 12, suffix: `${NNBSP}ft`, plural: "feet" },
33
+ "yard": { type: "length", base: 914.4, inch: 36, foot: 3, suffix: `${NNBSP}yd` },
34
+ "mile": { type: "length", base: 1609344, yard: 1760, foot: 5280, inch: 63360, suffix: `${NNBSP}mi` },
35
+ "milliliter": { type: "volume", base: 1, suffix: `${NNBSP}ml` },
36
+ "liter": { type: "volume", base: 1000, suffix: `${NNBSP}l` },
37
+ "fluid-ounce": { type: "volume", base: 29.5735295625, gallon: 128, suffix: `${NNBSP}fl${NNBSP}oz`, singular: "fluid ounce", plural: "fluid ounces" },
38
+ "gallon": { type: "volume", base: 3785.411784, suffix: `${NNBSP}gal` },
39
+ "milligram": { type: "mass", base: 1, suffix: `${NNBSP}mg` },
40
+ "gram": { type: "mass", base: 1000, suffix: `${NNBSP}g` },
41
+ "kilogram": { type: "mass", base: 1000000, suffix: `${NNBSP}kg` },
42
+ "ounce": { type: "mass", base: 28349.523125, pound: 0.0625, suffix: `${NNBSP}oz` },
43
+ "pound": { type: "mass", base: 453592.37, ounce: 16, suffix: `${NNBSP}lb` },
44
+ "stone": { type: "mass", base: 6350293.18, pound: 14, ounce: 224, suffix: `${NNBSP}st`, plural: "stone" },
45
+ "millisecond": { type: "time", base: 1, suffix: `${NNBSP}ms` },
46
+ "second": { type: "time", base: SECOND, suffix: `${NNBSP}s` },
47
+ "minute": { type: "time", base: MINUTE, suffix: `${NNBSP}m` },
48
+ "hour": { type: "time", base: HOUR, suffix: `${NNBSP}h` },
49
+ "day": { type: "time", base: DAY, suffix: `${NNBSP}d` },
50
+ "week": { type: "time", base: WEEK, suffix: `${NNBSP}w` },
51
+ "month": { type: "time", base: MONTH, suffix: `${NNBSP}m` },
52
+ "year": { type: "time", base: YEAR, suffix: `${NNBSP}y` },
35
53
  };
36
54
  /** Convert between two units of the same type. */
37
55
  export function convertUnits(num, from, to) {
@@ -61,4 +79,4 @@ export const formatUnits = (num, unit, maxPrecision, minPrecision) => formatQuan
61
79
  * @param unit String reference for a unit of measure e.g. `kilometer`
62
80
  * @param maxPrecision Number of decimal places to round the number to e.g. `2`
63
81
  */
64
- export const formatFullUnits = (num, unit, maxPrecision, minPrecision) => formatFullQuantity(num, unit, UNITS[unit].plural || `${unit}s`, maxPrecision, minPrecision);
82
+ export const formatFullUnits = (num, unit, maxPrecision, minPrecision) => formatFullQuantity(num, UNITS[unit].singular || unit, UNITS[unit].plural || `${unit}s`, maxPrecision, minPrecision);