@pacem/pacem-foundation 1.0.0-bernoulli → 1.0.0-binet

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,10 +1,11 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  //namespace Pacem {
7
7
  import { NullChecker } from "./null-checker";
8
+ /** Array manipulation utilities. */
8
9
  export class Arrays {
9
10
  static range(min, max, items = 2) {
10
11
  let x = min;
@@ -23,6 +24,12 @@ export class Arrays {
23
24
  }
24
25
  return output;
25
26
  }
27
+ /**
28
+ * Splits an array into chunks of a given size.
29
+ * @param source Array to split.
30
+ * @param size Maximum size of each chunk (must be a positive integer).
31
+ * @returns Array of chunks; an empty array if `source` is null or empty.
32
+ */
26
33
  static chunkify(source, size) {
27
34
  if (NullChecker.isNullOrEmpty(source)) {
28
35
  return [];
package/dist/esm/blobs.js CHANGED
@@ -1,10 +1,16 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  //namespace Pacem {
7
+ /** Conversion utilities between `Blob`, base64/data URLs and plain text. */
7
8
  export class Blobs {
9
+ /**
10
+ * Reads a `Blob` and resolves it as a base64-encoded data URL.
11
+ * @param blob Blob to read.
12
+ * @returns A promise resolving with the data URL string.
13
+ */
8
14
  static blobToDataURL(blob) {
9
15
  return new Promise((resolve, _) => {
10
16
  const a = new FileReader();
@@ -20,10 +26,21 @@ export class Blobs {
20
26
  }
21
27
  return u8arr;
22
28
  }
29
+ /**
30
+ * Converts a base64-encoded string into a `Blob`.
31
+ * @param bstr Base64-encoded string (without the `data:...;base64,` prefix).
32
+ * @param options Blob options (e.g. MIME `type`).
33
+ * @returns The resulting `Blob`.
34
+ */
23
35
  static base64ToBlob(bstr, options) {
24
36
  const u8arr = Blobs._b64ToUint8Array(atob(bstr));
25
37
  return new Blob([u8arr], options);
26
38
  }
39
+ /**
40
+ * Converts a data URL (`data:<mime>;base64,<data>`) into a `Blob`, inferring the MIME type when present.
41
+ * @param dataurl Data URL to convert.
42
+ * @returns The resulting `Blob`.
43
+ */
27
44
  static dataURLToBlob(dataurl) {
28
45
  const coma = dataurl.indexOf(',');
29
46
  if (coma === -1) {
@@ -35,6 +52,12 @@ export class Blobs {
35
52
  return Blobs.base64ToBlob(bstr, { type: mime });
36
53
  }
37
54
  }
55
+ /**
56
+ * Reads a `Blob` and decodes it as text.
57
+ * @param blob Blob to read.
58
+ * @param encoding Text encoding to use for decoding (defaults to the platform's default, typically UTF-8).
59
+ * @returns A promise resolving with the decoded text.
60
+ */
38
61
  static async blobToText(blob, encoding) {
39
62
  const buffer = await blob.arrayBuffer();
40
63
  const decoder = new TextDecoder(encoding, { fatal: false });
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -10,6 +10,11 @@ const browserVersion = (userAgent, regex) => {
10
10
  return match ? match[2] : null;
11
11
  };
12
12
  // https://stackoverflow.com/77095874
13
+ /**
14
+ * Detects the browser name and version from a user-agent string.
15
+ * @param userAgent User-agent string to parse (defaults to `navigator.userAgent`).
16
+ * @returns An object with the detected browser `name` (e.g. `Chrome`, `Firefox`, `Safari`, `Edge`, `IE`, `unknown`, ...) and its `version`.
17
+ */
13
18
  export function detect(userAgent = navigator.userAgent) {
14
19
  let browser = 'unknown';
15
20
  let version = null;
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -142,9 +142,13 @@ function hexify(v) {
142
142
  return v.toString(16).padStart(2, '0');
143
143
  //return Pacem.Strings.leftPad(v.toString(16), 2, '0');
144
144
  }
145
+ /** Color parsing, conversion (RGB/HSL/CIE XYZ) and manipulation utilities. */
145
146
  export class Colors {
147
+ /** Minimum WCAG contrast ratio recommended for large-scale text/graphical objects. */
146
148
  static { this.WCAG_MINIMUM_CONTRAST = 3.0; }
149
+ /** Minimum WCAG (AA) contrast ratio recommended for normal-sized text. */
147
150
  static { this.WCAG_NORMAL_TEXT_CONTRAST = 4.5; }
151
+ /** Minimum WCAG (AAA) contrast ratio recommended for enhanced accessibility. */
148
152
  static { this.WCAG_SAFE_CONTRAST = 7.0; }
149
153
  static _clampRGB(rgb) {
150
154
  const clmp = (n) => Math.min(1.0, Math.max(0, n));
@@ -156,6 +160,11 @@ export class Colors {
156
160
  static _normalize(rgb) {
157
161
  return [rgb[0] / 255.0, rgb[1] / 255.0, rgb[2] / 255.0, rgb[3]];
158
162
  }
163
+ /**
164
+ * Parses a CSS color string (`rgb()`, `rgba()`, `#rrggbb`, `#rgb`, `hsl()` or `hsla()`) into an {@link Rgba} value.
165
+ * @param clr CSS color string.
166
+ * @returns The parsed color, or `undefined` if the string does not match any supported format.
167
+ */
159
168
  static parse(clr) {
160
169
  clr = (clr || '').toLowerCase();
161
170
  /* rgb(255,255,255) */
@@ -192,6 +201,11 @@ export class Colors {
192
201
  return this.rgb(hsla);
193
202
  }
194
203
  }
204
+ /**
205
+ * Converts an {@link Rgba} color into its {@link Hsla} equivalent.
206
+ * @param rgb Color to convert.
207
+ * @returns The converted color.
208
+ */
195
209
  static hsl(rgb) {
196
210
  const l = luminance(rgb), s = saturation(rgb, l), h = hueCircle(rgb);
197
211
  return { h, s, l, a: rgb.a };
package/dist/esm/dates.js CHANGED
@@ -1,11 +1,18 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  //namespace Pacem {
7
7
  const JSON_DATE_PATTERN = /^\/Date\([\d]+\)\/$/i;
8
+ /** Date parsing and arithmetic utilities. */
8
9
  export class Dates {
10
+ /**
11
+ * Parses a value into a `Date`. Accepts ISO/parseable date strings, ASP.NET-style
12
+ * `/Date(ticks)/` JSON date strings, numeric timestamps, or a `Date` instance (returned as-is).
13
+ * @param input Value to parse.
14
+ * @returns The resulting `Date`.
15
+ */
9
16
  static parse(input) {
10
17
  let d;
11
18
  if (typeof input === 'string') {
@@ -21,9 +28,19 @@ export class Dates {
21
28
  else
22
29
  return input;
23
30
  }
31
+ /**
32
+ * Gets whether the given year is a leap year.
33
+ * @param year Year to check.
34
+ */
24
35
  static isLeapYear(year) {
25
36
  return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
26
37
  }
38
+ /**
39
+ * Gets the number of days in a given month of a given year.
40
+ * @param year Year (used to account for leap Februaries).
41
+ * @param month Zero-based month index (0 = January, ..., 11 = December).
42
+ * @returns Number of days in the month.
43
+ */
27
44
  static daysInMonth(year, month) {
28
45
  return [31, (Dates.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
29
46
  }
@@ -41,6 +58,13 @@ export class Dates {
41
58
  static dateOnly(datetime) {
42
59
  return new Date(datetime.getFullYear(), datetime.getMonth(), datetime.getDate());
43
60
  }
61
+ /**
62
+ * Returns a new date obtained by adding a (possibly negative) number of months to `input`,
63
+ * clamping the day-of-month to the target month's length (e.g. Jan 31 + 1 month => Feb 28/29).
64
+ * @param input Starting date.
65
+ * @param value Number of months to add.
66
+ * @returns The resulting date.
67
+ */
44
68
  static addMonths(input, value) {
45
69
  let n = input.getDate(), i = new Date(input), month = i.getMonth() + value, years = 0;
46
70
  while (month < 0) {
@@ -53,9 +77,21 @@ export class Dates {
53
77
  i.setDate(Math.min(n, Dates.daysInMonth(i.getFullYear(), i.getMonth())));
54
78
  return i;
55
79
  }
80
+ /**
81
+ * Returns a new date obtained by adding a (possibly negative) number of days to `input`.
82
+ * @param input Starting date.
83
+ * @param value Number of days to add.
84
+ * @returns The resulting date.
85
+ */
56
86
  static addDays(input, value) {
57
87
  return new Date(input.valueOf() + value * 86400000);
58
88
  }
89
+ /**
90
+ * Computes the number of days (possibly fractional) between two dates.
91
+ * @param start Start date.
92
+ * @param end End date.
93
+ * @returns Number of days between `start` and `end` (negative if `end` precedes `start`).
94
+ */
59
95
  static daysBetween(start, end) {
60
96
  return (end.valueOf() - start.valueOf()) / 86400000;
61
97
  }
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -30,9 +30,18 @@ function deepMerge(target, source) {
30
30
  }
31
31
  return output;
32
32
  }
33
+ /** Deep-merging utility for plain objects. */
33
34
  export class DeepMerger {
34
35
  constructor() {
35
36
  }
37
+ /**
38
+ * Recursively merges `source` into `target`, in place: plain-object properties are merged
39
+ * recursively (into a fresh object, never adopted by reference), arrays are shallow-copied,
40
+ * and any other value overwrites the target's.
41
+ * @param source Object whose properties are merged into `target`.
42
+ * @param target Object to merge into (defaults to, and lazily creates, the global `Pacem` namespace object).
43
+ * @returns The mutated `target`, typed as the union of both inputs.
44
+ */
36
45
  static merge(source, target) {
37
46
  target ??= (globalThis['Pacem'] ??= {});
38
47
  return deepMerge(target, source);
package/dist/esm/geom.js CHANGED
@@ -1,11 +1,16 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  import { NullChecker } from "./null-checker";
7
7
  // 1.7763568394002505e-15 -20.4551920341394 40 40
8
8
  const FLOAT_PATTERN = /[-+]?([\d]+(\.[\d]+(e-[\d]+)?)?|[\d]*(\.[\d]+(e-[\d]+)?))/g;
9
+ /**
10
+ * Extracts all the floating point numbers found in a string (e.g. `"10px 20px"` => `[10, 20]`).
11
+ * @param input String to parse.
12
+ * @returns Array of the numbers found, in order of appearance.
13
+ */
9
14
  export function parseAsNumericalArray(input) {
10
15
  const arr = [];
11
16
  let reg = input.match(FLOAT_PATTERN);
@@ -14,7 +19,12 @@ export function parseAsNumericalArray(input) {
14
19
  }
15
20
  return arr;
16
21
  }
22
+ /** Angle-related utilities. */
17
23
  export class Angle {
24
+ /**
25
+ * Type-guards a value as a valid {@link Angle} object.
26
+ * @param obj Value to check.
27
+ */
18
28
  static isAngle(obj) {
19
29
  return typeof obj === 'object'
20
30
  && 'vertex' in obj && Point.isPoint(obj['vertex'])
@@ -49,7 +59,14 @@ export class Angle {
49
59
  }
50
60
  }
51
61
  ;
62
+ /** Size-related utilities. */
52
63
  export class Size {
64
+ /**
65
+ * Parses a string containing exactly two numbers into a {@link Size}.
66
+ * @param sz String to parse (e.g. `"100 50"`).
67
+ * @returns The parsed size.
68
+ * @throws If `sz` does not contain exactly two numbers.
69
+ */
53
70
  static parse(sz) {
54
71
  let arr = parseAsNumericalArray(sz);
55
72
  if (arr && arr.length === 2) {
@@ -57,13 +74,24 @@ export class Size {
57
74
  }
58
75
  throw new Error(`Cannot parse "${sz}" as a valid Size.`);
59
76
  }
77
+ /**
78
+ * Type-guards a value as a valid {@link Size} object.
79
+ * @param obj Value to check.
80
+ */
60
81
  static isSize(obj) {
61
82
  return typeof obj === 'object'
62
83
  && 'width' in obj && typeof obj['width'] === 'number'
63
84
  && 'height' in obj && typeof obj['height'] === 'number';
64
85
  }
65
86
  }
87
+ /** Point-related utilities. */
66
88
  export class Point {
89
+ /**
90
+ * Parses a string containing exactly two numbers into a {@link Point}.
91
+ * @param pt String to parse (e.g. `"10 20"`).
92
+ * @returns The parsed point.
93
+ * @throws If `pt` does not contain exactly two numbers.
94
+ */
67
95
  static parse(pt) {
68
96
  let arr = parseAsNumericalArray(pt);
69
97
  if (arr && arr.length === 2) {
@@ -71,6 +99,10 @@ export class Point {
71
99
  }
72
100
  throw new Error(`Cannot parse "${pt}" as a valid Point.`);
73
101
  }
102
+ /**
103
+ * Type-guards a value as a valid {@link Point} object.
104
+ * @param obj Value to check.
105
+ */
74
106
  static isPoint(obj) {
75
107
  return typeof obj === 'object'
76
108
  && 'x' in obj && typeof obj['x'] === 'number'
@@ -1,11 +1,15 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  // namespace Pacem {
7
7
  /** Grants undo/redo functionalities for given state. */
8
8
  export class HistoryService {
9
+ /**
10
+ * @param state Initial state.
11
+ * @param maxlength Maximum number of stored states (undo queue + redo stack); unbounded when omitted.
12
+ */
9
13
  constructor(state, maxlength) {
10
14
  this.#current = state;
11
15
  this.#maxlength = maxlength;
@@ -23,9 +27,11 @@ export class HistoryService {
23
27
  get current() {
24
28
  return this.#current;
25
29
  }
30
+ /** Gets whether there is a previous state to revert to. @readonly */
26
31
  get canUndo() {
27
32
  return this.#backwards.length > 0;
28
33
  }
34
+ /** Gets whether there is a subsequent state to reapply. @readonly */
29
35
  get canRedo() {
30
36
  return this.#forwards.length > 0;
31
37
  }
@@ -34,6 +40,7 @@ export class HistoryService {
34
40
  set maxlength(v) {
35
41
  this.#maxlength = v;
36
42
  }
43
+ /** Reverts to the previous state, if any (see {@link canUndo}), moving the current state onto the redo stack. */
37
44
  undo() {
38
45
  if (this.canUndo) {
39
46
  const back = this.#backwards, fore = this.#forwards, current = this.#current;
@@ -41,6 +48,7 @@ export class HistoryService {
41
48
  this.#current = back.pop();
42
49
  }
43
50
  }
51
+ /** Reapplies the next state, if any (see {@link canRedo}), moving the current state onto the undo queue. */
44
52
  redo() {
45
53
  if (this.canRedo) {
46
54
  const back = this.#backwards, fore = this.#forwards, current = this.#current;
@@ -48,6 +56,11 @@ export class HistoryService {
48
56
  this.#current = fore.shift();
49
57
  }
50
58
  }
59
+ /**
60
+ * Pushes a new current state, clearing the redo stack and enqueuing the previous current state for undo.
61
+ * Trims the undo queue to `maxlength`, if set.
62
+ * @param state New current state.
63
+ */
51
64
  push(state) {
52
65
  this.#forwards.splice(0);
53
66
  this.#backwards.push(this.#current);
@@ -57,6 +70,7 @@ export class HistoryService {
57
70
  queue.splice(0, queue.length - max);
58
71
  }
59
72
  }
73
+ /** Clears both the undo queue and the redo stack, leaving the current state untouched. */
60
74
  reset() {
61
75
  this.#forwards.splice(0);
62
76
  this.#backwards.splice(0);
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -12,7 +12,13 @@ const DefaultImagingResizeOptions = {
12
12
  quality: 1,
13
13
  type: 'image/jpeg'
14
14
  };
15
+ /** Image loading and resizing utilities, based on `OffscreenCanvas`. */
15
16
  export class Imaging {
17
+ /**
18
+ * Fetches an image from a URL as a `Blob`.
19
+ * @param url URL of the image to load.
20
+ * @returns A promise resolving with the loaded `Blob`, or `null` if the fetch response was not OK.
21
+ */
16
22
  static async loadImage(url) {
17
23
  const response = await fetch(url);
18
24
  if (!response.ok) {
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,19 +1,33 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  // namespace Pacem {
7
+ /** Unique key/id generation utilities. */
7
8
  export class Keys {
8
9
  static #seed;
10
+ /**
11
+ * Generates a process-wide monotonically increasing numeric id, seeded from the current timestamp.
12
+ * @returns A new unique numeric id.
13
+ */
9
14
  static uniqueId() {
10
15
  let seed = Keys.#seed || Date.now();
11
16
  return Keys.#seed = ++seed;
12
17
  }
18
+ /**
19
+ * Generates a process-wide unique id, base-62 encoded.
20
+ * @returns A new unique string code.
21
+ */
13
22
  static uniqueCode() {
14
23
  const newid = Keys.uniqueId();
15
24
  return newid.toBase62();
16
25
  }
26
+ /**
27
+ * Generates a random base-62 string of at least the given length.
28
+ * @param length Minimum length of the generated string.
29
+ * @returns A random string.
30
+ */
17
31
  static randomString(length) {
18
32
  let retval = '';
19
33
  do {
@@ -1,26 +1,46 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  /// <reference path="geom.ts" />
7
7
  ;
8
+ /** 2D affine matrix ([a b; c d] linear part, [e f] translation) manipulation utilities. */
8
9
  export class Matrix2D {
10
+ /**
11
+ * Returns whether the given matrix is the identity matrix.
12
+ * @param m Matrix to check.
13
+ */
9
14
  static isIdentity(m) {
10
15
  return m.a === 1 && m.d === 1 && m.b === 0 && m.f === 0 && m.c === 0 && m.e === 0;
11
16
  }
17
+ /** Gets a fresh identity matrix. @readonly */
12
18
  static get identity() {
13
19
  return { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
14
20
  }
21
+ /**
22
+ * Returns a shallow copy of the given matrix.
23
+ * @param m Matrix to copy.
24
+ */
15
25
  static copy(m) {
16
26
  return { a: m.a, b: m.b, c: m.c, d: m.d, e: m.e, f: m.f };
17
27
  }
18
28
  static scale(m, sx, sy = sx) {
19
29
  return { a: m.a * sx, b: m.b, c: m.c, d: m.d * sy, e: m.e, f: m.f };
20
30
  }
31
+ /**
32
+ * Returns a copy of `m` translated by the given vector.
33
+ * @param m Matrix to translate.
34
+ * @param t Translation vector.
35
+ */
21
36
  static translate(m, t) {
22
37
  return { a: m.a, b: m.b, c: m.c, d: m.d, e: m.e + t.x, f: m.f + t.y };
23
38
  }
39
+ /**
40
+ * Returns a copy of `m` rotated (about the origin) by the given angle.
41
+ * @param m Matrix to rotate.
42
+ * @param rad Rotation angle, in radians.
43
+ */
24
44
  static rotate(m, rad) {
25
45
  const cos = Math.cos(rad), sin = Math.sin(rad);
26
46
  return Matrix2D.multiply(m, { a: cos, b: sin, c: -sin, d: cos, e: 0, f: 0 });
@@ -48,9 +68,18 @@ export class Matrix2D {
48
68
  f: m1.e * m2.b + m1.f * m2.d + m2.f
49
69
  };
50
70
  }
71
+ /**
72
+ * Computes the determinant of the matrix's linear part.
73
+ * @param m Matrix to compute the determinant of.
74
+ */
51
75
  static det(m) {
52
76
  return m.a * m.d - m.c * m.b;
53
77
  }
78
+ /**
79
+ * Computes the inverse of the given matrix.
80
+ * @param m Matrix to invert.
81
+ * @returns The inverse matrix, or `null` if `m` is singular (determinant is zero).
82
+ */
54
83
  static invert(m) {
55
84
  const det = this.det(m);
56
85
  if (det === 0) {
@@ -74,6 +103,12 @@ export class Matrix2D {
74
103
  f: m.e * m.b - m.a * m.f
75
104
  }, invdet);
76
105
  }
106
+ /**
107
+ * Decomposes a matrix into its scale, rotation and translation components.
108
+ * @param m Matrix to decompose.
109
+ * @param transformOrigin Origin about which the rotation/scale are considered to be applied (defaults to `{x:0, y:0}`).
110
+ * @returns The decomposed `scaleX`, `scaleY`, `rotation` (radians) and `translation`.
111
+ */
77
112
  static toComponents(m, transformOrigin = { x: 0, y: 0 }) {
78
113
  const scaleX = Math.sqrt(m.a * m.a + m.c * m.c);
79
114
  const scaleY = Math.sqrt(m.b * m.b + m.d * m.d);
@@ -1,15 +1,26 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  /// <reference path="dates.ts" />
7
7
  import { Dates } from "./dates";
8
8
  // namespace Pacem {
9
+ /** Null/empty value-checking utilities. */
9
10
  export class NullChecker {
11
+ /**
12
+ * Returns whether the given value is `null` or `undefined`.
13
+ * @param o Value to check.
14
+ */
10
15
  static isNull(o) {
11
16
  return o === null || o === void 0;
12
17
  }
18
+ /**
19
+ * Returns whether the given value is "empty": an empty array, an empty string, or a
20
+ * plain object with no own enumerable keys (dates, regexes and file-system handles are never
21
+ * considered empty).
22
+ * @param o Value to check.
23
+ */
13
24
  static isEmpty(o) {
14
25
  try {
15
26
  return (Array.isArray(o) && o.length === 0)
@@ -21,6 +32,10 @@ export class NullChecker {
21
32
  return false;
22
33
  }
23
34
  }
35
+ /**
36
+ * Returns whether the given value is `null`, `undefined`, or "empty" (see {@link NullChecker.isEmpty}).
37
+ * @param o Value to check.
38
+ */
24
39
  static isNullOrEmpty(o) {
25
40
  return NullChecker.isNull(o) || NullChecker.isEmpty(o);
26
41
  }
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
@@ -1,16 +1,35 @@
1
1
  /*!
2
- * @pacem/pacem-foundation v1.0.0-bernoulli (https://js.pacem.it)
2
+ * @pacem/pacem-foundation v1.0.0-binet (https://js.pacem.it)
3
3
  * Pacem (https://pacem.it)
4
4
  * Licensed under Apache-2.0
5
5
  */
6
6
  // namespace Pacem {
7
+ /** Numeric utilities. */
7
8
  export class Numbers {
9
+ /**
10
+ * Rounds a number to the nearest multiple of `step`.
11
+ * @param x Value to round.
12
+ * @param step Rounding step/increment (defaults to 1).
13
+ * @returns The rounded value.
14
+ */
8
15
  static round(x, step = 1.0) {
9
16
  return Math.round(x / step) * step;
10
17
  }
18
+ /**
19
+ * Computes the logarithm of `x` in an arbitrary `base`.
20
+ * @param x Value to compute the logarithm of.
21
+ * @param base Logarithm base.
22
+ */
11
23
  static log(x, base) {
12
24
  return Math.log10(x) / Math.log10(base);
13
25
  }
26
+ /**
27
+ * Converts a number (or numeric string) from one base to another.
28
+ * @param v Value to convert, expressed in base `from`.
29
+ * @param from Source base (2-36).
30
+ * @param to Target base (2-36).
31
+ * @returns The value re-expressed in base `to`, as a string; `"NaN"` if `v` is not a valid number in base `from`.
32
+ */
14
33
  static rebase(v, from, to) {
15
34
  const vStr = v.toString();
16
35
  const firstPass = parseInt(vStr, from);