@tspro/ts-utils-lib 1.18.0 → 1.19.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.19.0] - 2025-10-27
4
+ ### Added
5
+ - SignedIndexArray.toArray(), IndexArray.toArray(), IndexArray.length;
6
+ - Set1 and DeepSet.
7
+ - DefaultArray.
8
+ - Stack functions.
9
+
3
10
  ## [1.18.0] - 2025-10-24
4
11
  ### Changed
5
12
  - Deprecated `DivRect` properties `centerX` and `centerY`, replaced with `anchorX` and `anchorY`.
package/dist/index.d.mts CHANGED
@@ -143,15 +143,60 @@ declare namespace index$7 {
143
143
  export { type index$7_ErrorConstructor as ErrorConstructor, index$7_array_elem as array_elem, index$7_array_id as array_id, index$7_assert as assert, index$7_assertEnum as assertEnum, index$7_eq as eq, index$7_even as even, index$7_fail as fail, index$7_finite as finite, index$7_in_group as in_group, index$7_int as int, index$7_int_between as int_between, index$7_int_between_exclusive as int_between_exclusive, index$7_int_eq as int_eq, index$7_int_gt as int_gt, index$7_int_gte as int_gte, index$7_int_lt as int_lt, index$7_int_lte as int_lte, index$7_interrupt as interrupt, isArray$1 as isArray, isArrayIndex$1 as isArrayIndex, isArrayOrUndefined$1 as isArrayOrUndefined, isBoolean$1 as isBoolean, isBooleanOrUndefined$1 as isBooleanOrUndefined, isDeepEqual$1 as isDeepEqual, isEmptyArray$1 as isEmptyArray, isEmptyArrayOrUndefined$1 as isEmptyArrayOrUndefined, isEmptyString$1 as isEmptyString, isEmptyStringOrUndefined$1 as isEmptyStringOrUndefined, isEnumValue$1 as isEnumValue, isEnumValueOrUndefined$1 as isEnumValueOrUndefined, isEqual$1 as isEqual, isEvenNumber$1 as isEvenNumber, isFalse$1 as isFalse, isFalseOrUndefined$1 as isFalseOrUndefined, isFinite$1 as isFinite, isFunction$1 as isFunction, isFunctionOrUndefined$1 as isFunctionOrUndefined, isIncluded$1 as isIncluded, isInfinity$1 as isInfinity, isInteger$1 as isInteger, isIntegerBetween$1 as isIntegerBetween, isIntegerBetweenExclusive$1 as isIntegerBetweenExclusive, isIntegerEq$1 as isIntegerEq, isIntegerGt$1 as isIntegerGt, isIntegerGte$1 as isIntegerGte, isIntegerLt$1 as isIntegerLt, isIntegerLte$1 as isIntegerLte, isIntegerOrUndefined$1 as isIntegerOrUndefined, isNaNValue$1 as isNaNValue, isNegInfinity$1 as isNegInfinity, isNonEmptyArray$1 as isNonEmptyArray, isNonEmptyArrayOrUndefined$1 as isNonEmptyArrayOrUndefined, isNonEmptyString$1 as isNonEmptyString, isNonEmptyStringOrUndefined$1 as isNonEmptyStringOrUndefined, isNull$1 as isNull, isNullish$1 as isNullish, isNumber$1 as isNumber, isNumberBetween$1 as isNumberBetween, isNumberBetweenExclusive$1 as isNumberBetweenExclusive, isNumberOrUndefined$1 as isNumberOrUndefined, isObject$1 as isObject, isObjectOrUndefined$1 as isObjectOrUndefined, isOddNumber$1 as isOddNumber, isPosInfinity$1 as isPosInfinity, isString$1 as isString, isStringOrUndefined$1 as isStringOrUndefined, isThrowing$1 as isThrowing, isTrue$1 as isTrue, isTrueOrUndefined$1 as isTrueOrUndefined, isTypedObject$1 as isTypedObject, isUndefined$1 as isUndefined, index$7_odd as odd, index$7_require as require, index$7_requireDefined as requireDefined, index$7_setErrorClass as setErrorClass };
144
144
  }
145
145
 
146
+ /**
147
+ * Set expiration time for cookies.
148
+ * @param days - Number of days until cookies expire.
149
+ */
146
150
  declare function setExpireDays(days: number): void;
151
+ /**
152
+ * Is consent pending (cookies not yet accepted)?
153
+ * @returns
154
+ */
147
155
  declare function isConsentPending(): boolean;
156
+ /**
157
+ * Consent cookies.
158
+ */
148
159
  declare function accept(): void;
160
+ /**
161
+ * Decline cookies. This will reject all cookies than a single flags that cookies have been declined.
162
+ */
149
163
  declare function decline(): void;
164
+ /**
165
+ * Save a cookie.
166
+ * @param name - Cookie name.
167
+ * @param value - Cookie value, can be string, number or boolean.
168
+ * @returns - Returns given value.
169
+ */
150
170
  declare function save<T extends string | number | boolean>(name: string, value: T): T;
171
+ /**
172
+ * Read a string cookie.
173
+ * @param name - Cookie name.
174
+ * @param defaultValue - Default value returned when cookie with given name was not found.
175
+ * @returns - String cookie value.
176
+ */
151
177
  declare function read(name: string, defaultValue: string): string;
178
+ /**
179
+ * Read an integer cookie.
180
+ * @param name - Cookie name.
181
+ * @param defaultValue - Default value returned when cookie with given name was not found.
182
+ * @returns - Integer cookie valus.
183
+ */
152
184
  declare function readInt(name: string, defaultValue: number): number;
185
+ /**
186
+ * Read a boolean cookie.
187
+ * @param name - Cookie name.
188
+ * @param defaultValue - Default value returned when cookie with given name was not found.
189
+ * @returns - Boolean cookie value.
190
+ */
153
191
  declare function readBool(name: string, defaultValue: boolean): boolean;
192
+ /**
193
+ * Erase cookie.
194
+ * @param name - Name of cookie to be erased.
195
+ */
154
196
  declare function erase(name: string): void;
197
+ /**
198
+ * Erase all cookies.
199
+ */
155
200
  declare function eraseAll(): void;
156
201
 
157
202
  declare const cookies_accept: typeof accept;
@@ -168,15 +213,39 @@ declare namespace cookies {
168
213
  export { cookies_accept as accept, cookies_decline as decline, cookies_erase as erase, cookies_eraseAll as eraseAll, cookies_isConsentPending as isConsentPending, cookies_read as read, cookies_readBool as readBool, cookies_readInt as readInt, cookies_save as save, cookies_setExpireDays as setExpireDays };
169
214
  }
170
215
 
216
+ /** Devices dots per inch. */
171
217
  declare const DPI: number;
218
+ /** Devices pixels per millimeter. */
172
219
  declare const PxPerMm: number;
220
+ /** Browsers scroll bar width. */
173
221
  declare const ScrollbarWidth: number;
222
+ /** Browsers system font size. */
174
223
  declare const FontSize: number;
224
+ /** Is touch device? */
175
225
  declare const IsTouchDevice: boolean;
226
+ /** Is mobile device? */
176
227
  declare const IsMobileDevice: boolean;
228
+ /** Host address. */
177
229
  declare const HostAddress: string;
230
+ /**
231
+ * Convert pixels to millimeters on a device.
232
+ * @param px - Pixels.
233
+ * @returns - Millimeters.
234
+ */
178
235
  declare function pxToMm(px: number): number;
236
+ /**
237
+ * Convert millimeters to pixels on a device.
238
+ * @param mm - Millimeters.
239
+ * @returns - Pixels.
240
+ */
179
241
  declare function mmToPx(mm: number): number;
242
+ /**
243
+ * Convert input to pixels on a device. Input value is in html style form containing number
244
+ * followed by unit (e.g. "10px"). Supported units are "mm", "cm", "in", "inch", "em" and "px".
245
+ *
246
+ * @param input - Input value.
247
+ * @returns - Pixels.
248
+ */
180
249
  declare function toPx(input: string | number): number;
181
250
 
182
251
  declare const device_DPI: typeof DPI;
@@ -310,8 +379,9 @@ declare namespace Guard {
310
379
 
311
380
  declare function toArray<T>(a: T | T[]): Array<T>;
312
381
  declare function duplicate<T>(a: T[] | undefined): T[] | undefined;
313
- declare function removeDuplicates<T>(a: T[]): T[];
314
- declare function removeDuplicatesCmp<T>(arr: ReadonlyArray<T>, cmp: (t1: T, t2: T) => boolean): T[];
382
+ declare function removeDuplicates<T>(arr: T[], compareFn?: (a: T, b: T) => boolean): T[];
383
+ /** @deprecated - Use {@link removeDuplicates} with compareFn instead. */
384
+ declare function removeDuplicatesCmp<T>(arr: ReadonlyArray<T>, compareFn: (t1: T, t2: T) => boolean): T[];
315
385
  declare function fillArray<T>(fillValue: T, fillCount: number): T[];
316
386
  declare function mapSequenceArray<T>(len: number, fn: (i: number) => T): T[];
317
387
  declare function getSequenceArray(len: number): number[];
@@ -545,18 +615,33 @@ declare namespace index {
545
615
  export { index$6 as Arr, index$5 as Dom, index$8 as Enum, index_Is as Is, index$4 as Map, index$3 as Math, index$2 as Obj, index$1 as Str };
546
616
  }
547
617
 
618
+ /**
619
+ * This is a stack data structure.
620
+ */
548
621
  declare class Stack<T> {
549
- private readonly list;
550
- push(e: T): T;
622
+ private readonly data;
623
+ private assertId;
624
+ get length(): number;
625
+ push(el: T): T;
551
626
  pop(): T;
627
+ popOrUndef(): T | undefined;
628
+ popOr(defaultValueOrCreator: T | (() => T)): T;
552
629
  top(): T;
630
+ topOrUndef(): T | undefined;
631
+ topOr(defaultValueOrCreator: T | (() => T)): T;
632
+ peek(depth?: number): T;
633
+ peekOrUndef(depth?: number): T | undefined;
634
+ peekOr(depth: number | undefined, defaultValueOrCreator: T | (() => T)): T;
635
+ values(): IterableIterator<T>;
636
+ [Symbol.iterator](): IterableIterator<T>;
553
637
  toArray(): T[];
554
- get length(): number;
638
+ isEmpty(): boolean;
555
639
  clear(): void;
640
+ toString(): string;
556
641
  }
557
642
 
558
643
  /**
559
- * Vector class.
644
+ * `Vec` is a generic vector class with two or more coordinates.
560
645
  *
561
646
  * ```ts
562
647
  * // Example usage:
@@ -606,7 +691,7 @@ declare class Vec {
606
691
  }
607
692
 
608
693
  /**
609
- * DivRect class, left, top, right, bottom rectangle divided into four sections by anchorX, anchorY.
694
+ * DivRect class is a rectangle (left, top, right, bottom) with an anchor point (anchorX, anchorY).
610
695
  */
611
696
  declare class DivRect {
612
697
  left: number;
@@ -830,7 +915,7 @@ declare class DivRect {
830
915
  }
831
916
 
832
917
  /**
833
- * LRUCache class: Least Recently Used cache with a fixed capacity
918
+ * LRUCache is an implementation of least recently used cache with a fixed capacity.
834
919
  */
835
920
  declare class LRUCache<K extends string, V> {
836
921
  private cache;
@@ -867,7 +952,8 @@ interface KVComponent<K extends any[], VALUE> {
867
952
  }
868
953
 
869
954
  /**
870
- * An array-like structure for non-negative indexes.
955
+ * `IndexArray` is a sparse array with non-negative indexes. It stores values
956
+ * to indexes, and each index also has flag telling it has a value.
871
957
  */
872
958
  declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
873
959
  private static validateIndex;
@@ -879,6 +965,8 @@ declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
879
965
  constructor(entries: Iterable<[number, VALUE]>);
880
966
  private get posLen();
881
967
  get size(): number;
968
+ get length(): number;
969
+ private trimRight;
882
970
  isEmpty(): boolean;
883
971
  has(id: number): boolean;
884
972
  set(id: number, value: VALUE): void;
@@ -898,7 +986,7 @@ declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
898
986
  kvKeys(): IterableIterator<[number]>;
899
987
  kvValues(): IterableIterator<VALUE>;
900
988
  kvEntries(): IterableIterator<[[number], VALUE]>;
901
- [Symbol.iterator](): Generator<[number, VALUE], void, any>;
989
+ [Symbol.iterator](): IterableIterator<[number, VALUE]>;
902
990
  clone(): IndexArray<VALUE>;
903
991
  merge(other: IndexArray<VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, id: number) => VALUE): this;
904
992
  some(fn: (value: VALUE, id: number) => boolean): boolean;
@@ -911,11 +999,13 @@ declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
911
999
  map<R = VALUE>(fn: (value: VALUE, key1: number) => R): IndexArray<R>;
912
1000
  equals(other: IndexArray<VALUE>): boolean;
913
1001
  equals(other: IndexArray<VALUE>, eq: (a: VALUE, b: VALUE) => boolean): boolean;
1002
+ toArray(): VALUE[];
914
1003
  toString(): string;
915
1004
  }
916
1005
 
917
1006
  /**
918
- * An array-like structure for signed indexes, including negatives.
1007
+ * `IndexArray` is a sparse array with positive and negative indexes. It stores
1008
+ * values to indexes, and each index also has flag telling it has a value.
919
1009
  */
920
1010
  declare class SignedIndexArray<VALUE> implements KVComponent<[number], VALUE> {
921
1011
  private static toNegIndex;
@@ -950,7 +1040,7 @@ declare class SignedIndexArray<VALUE> implements KVComponent<[number], VALUE> {
950
1040
  kvKeys(): IterableIterator<[number]>;
951
1041
  kvValues(): IterableIterator<VALUE>;
952
1042
  kvEntries(): IterableIterator<[[number], VALUE]>;
953
- [Symbol.iterator](): Generator<[number, VALUE], void, any>;
1043
+ [Symbol.iterator](): IterableIterator<[number, VALUE]>;
954
1044
  clone(): SignedIndexArray<VALUE>;
955
1045
  merge(other: SignedIndexArray<VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, id: number) => VALUE): this;
956
1046
  some(fn: (value: VALUE, id: number) => boolean): boolean;
@@ -963,9 +1053,13 @@ declare class SignedIndexArray<VALUE> implements KVComponent<[number], VALUE> {
963
1053
  map<R = VALUE>(fn: (value: VALUE, key1: number) => R): SignedIndexArray<R>;
964
1054
  equals(other: SignedIndexArray<VALUE>): boolean;
965
1055
  equals(other: SignedIndexArray<VALUE>, eq: (a: VALUE, b: VALUE) => boolean): boolean;
1056
+ toArray(): VALUE[];
966
1057
  toString(): string;
967
1058
  }
968
1059
 
1060
+ /**
1061
+ * A Map implementation mapping a single key to a value.
1062
+ */
969
1063
  declare class Map1<KEY1, VALUE> implements KVComponent<[KEY1], VALUE> {
970
1064
  private map1;
971
1065
  constructor();
@@ -991,7 +1085,7 @@ declare class Map1<KEY1, VALUE> implements KVComponent<[KEY1], VALUE> {
991
1085
  kvKeys(): IterableIterator<[KEY1]>;
992
1086
  kvValues(): IterableIterator<VALUE>;
993
1087
  kvEntries(): IterableIterator<[[KEY1], VALUE]>;
994
- [Symbol.iterator](): Generator<[KEY1, VALUE], void, any>;
1088
+ [Symbol.iterator](): IterableIterator<[KEY1, VALUE]>;
995
1089
  clone(): Map1<KEY1, VALUE>;
996
1090
  merge(other: Map1<KEY1, VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, key1: KEY1) => VALUE): this;
997
1091
  some(fn: (value: VALUE, key1: KEY1) => boolean): boolean;
@@ -1006,6 +1100,9 @@ declare class Map1<KEY1, VALUE> implements KVComponent<[KEY1], VALUE> {
1006
1100
  toString(): string;
1007
1101
  }
1008
1102
 
1103
+ /**
1104
+ * A Map implementation mapping a double key to a value.
1105
+ */
1009
1106
  declare class Map2<KEY1, KEY2, VALUE> implements KVComponent<[KEY1, KEY2], VALUE> {
1010
1107
  private map1;
1011
1108
  constructor();
@@ -1032,7 +1129,7 @@ declare class Map2<KEY1, KEY2, VALUE> implements KVComponent<[KEY1, KEY2], VALUE
1032
1129
  kvKeys(): IterableIterator<[KEY1, KEY2]>;
1033
1130
  kvValues(): IterableIterator<VALUE>;
1034
1131
  kvEntries(): IterableIterator<[[KEY1, KEY2], VALUE]>;
1035
- [Symbol.iterator](): Generator<[KEY1, KEY2, VALUE], void, any>;
1132
+ [Symbol.iterator](): IterableIterator<[KEY1, KEY2, VALUE]>;
1036
1133
  clone(): Map2<KEY1, KEY2, VALUE>;
1037
1134
  merge(other: Map2<KEY1, KEY2, VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, key1: KEY1, key2: KEY2) => VALUE): this;
1038
1135
  some(fn: (value: VALUE, key1: KEY1, key2: KEY2) => boolean): boolean;
@@ -1047,6 +1144,9 @@ declare class Map2<KEY1, KEY2, VALUE> implements KVComponent<[KEY1, KEY2], VALUE
1047
1144
  toString(): string;
1048
1145
  }
1049
1146
 
1147
+ /**
1148
+ * A Map implementation mapping a triple key to a value.
1149
+ */
1050
1150
  declare class Map3<KEY1, KEY2, KEY3, VALUE> implements KVComponent<[KEY1, KEY2, KEY3], VALUE> {
1051
1151
  private map1;
1052
1152
  constructor();
@@ -1074,7 +1174,7 @@ declare class Map3<KEY1, KEY2, KEY3, VALUE> implements KVComponent<[KEY1, KEY2,
1074
1174
  kvKeys(): IterableIterator<[KEY1, KEY2, KEY3]>;
1075
1175
  kvValues(): IterableIterator<VALUE>;
1076
1176
  kvEntries(): IterableIterator<[[KEY1, KEY2, KEY3], VALUE]>;
1077
- [Symbol.iterator](): Generator<[KEY1, KEY2, KEY3, VALUE], void, any>;
1177
+ [Symbol.iterator](): IterableIterator<[KEY1, KEY2, KEY3, VALUE]>;
1078
1178
  clone(): Map3<KEY1, KEY2, KEY3, VALUE>;
1079
1179
  merge(other: Map3<KEY1, KEY2, KEY3, VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, key1: KEY1, key2: KEY2, key3: KEY3) => VALUE): this;
1080
1180
  some(fn: (value: VALUE, key1: KEY1, key2: KEY2, key3: KEY3) => boolean): boolean;
@@ -1089,6 +1189,9 @@ declare class Map3<KEY1, KEY2, KEY3, VALUE> implements KVComponent<[KEY1, KEY2,
1089
1189
  toString(): string;
1090
1190
  }
1091
1191
 
1192
+ /**
1193
+ * Wrapper class of a key-value container that contain array values.
1194
+ */
1092
1195
  declare class MultiContainer<K extends any[], V> {
1093
1196
  private readonly base;
1094
1197
  constructor(base: KVComponent<K, V[]>);
@@ -1105,10 +1208,14 @@ declare class MultiContainer<K extends any[], V> {
1105
1208
  toString(): string;
1106
1209
  }
1107
1210
  /**
1211
+ * Create a multi-container.
1212
+ *
1108
1213
  * ```ts
1109
1214
  * // Usage:
1110
1215
  * const multi = asMulti(new Map2<string, string, number[]>());
1111
- * multi.add("A", "B", 5);
1216
+ * multi.add("a", "b", 5);
1217
+ * multi.add("a", "b", 10);
1218
+ * multi.add("a", "c", 15);
1112
1219
  * ```
1113
1220
  * @param base
1114
1221
  * @returns
package/dist/index.d.ts CHANGED
@@ -143,15 +143,60 @@ declare namespace index$7 {
143
143
  export { type index$7_ErrorConstructor as ErrorConstructor, index$7_array_elem as array_elem, index$7_array_id as array_id, index$7_assert as assert, index$7_assertEnum as assertEnum, index$7_eq as eq, index$7_even as even, index$7_fail as fail, index$7_finite as finite, index$7_in_group as in_group, index$7_int as int, index$7_int_between as int_between, index$7_int_between_exclusive as int_between_exclusive, index$7_int_eq as int_eq, index$7_int_gt as int_gt, index$7_int_gte as int_gte, index$7_int_lt as int_lt, index$7_int_lte as int_lte, index$7_interrupt as interrupt, isArray$1 as isArray, isArrayIndex$1 as isArrayIndex, isArrayOrUndefined$1 as isArrayOrUndefined, isBoolean$1 as isBoolean, isBooleanOrUndefined$1 as isBooleanOrUndefined, isDeepEqual$1 as isDeepEqual, isEmptyArray$1 as isEmptyArray, isEmptyArrayOrUndefined$1 as isEmptyArrayOrUndefined, isEmptyString$1 as isEmptyString, isEmptyStringOrUndefined$1 as isEmptyStringOrUndefined, isEnumValue$1 as isEnumValue, isEnumValueOrUndefined$1 as isEnumValueOrUndefined, isEqual$1 as isEqual, isEvenNumber$1 as isEvenNumber, isFalse$1 as isFalse, isFalseOrUndefined$1 as isFalseOrUndefined, isFinite$1 as isFinite, isFunction$1 as isFunction, isFunctionOrUndefined$1 as isFunctionOrUndefined, isIncluded$1 as isIncluded, isInfinity$1 as isInfinity, isInteger$1 as isInteger, isIntegerBetween$1 as isIntegerBetween, isIntegerBetweenExclusive$1 as isIntegerBetweenExclusive, isIntegerEq$1 as isIntegerEq, isIntegerGt$1 as isIntegerGt, isIntegerGte$1 as isIntegerGte, isIntegerLt$1 as isIntegerLt, isIntegerLte$1 as isIntegerLte, isIntegerOrUndefined$1 as isIntegerOrUndefined, isNaNValue$1 as isNaNValue, isNegInfinity$1 as isNegInfinity, isNonEmptyArray$1 as isNonEmptyArray, isNonEmptyArrayOrUndefined$1 as isNonEmptyArrayOrUndefined, isNonEmptyString$1 as isNonEmptyString, isNonEmptyStringOrUndefined$1 as isNonEmptyStringOrUndefined, isNull$1 as isNull, isNullish$1 as isNullish, isNumber$1 as isNumber, isNumberBetween$1 as isNumberBetween, isNumberBetweenExclusive$1 as isNumberBetweenExclusive, isNumberOrUndefined$1 as isNumberOrUndefined, isObject$1 as isObject, isObjectOrUndefined$1 as isObjectOrUndefined, isOddNumber$1 as isOddNumber, isPosInfinity$1 as isPosInfinity, isString$1 as isString, isStringOrUndefined$1 as isStringOrUndefined, isThrowing$1 as isThrowing, isTrue$1 as isTrue, isTrueOrUndefined$1 as isTrueOrUndefined, isTypedObject$1 as isTypedObject, isUndefined$1 as isUndefined, index$7_odd as odd, index$7_require as require, index$7_requireDefined as requireDefined, index$7_setErrorClass as setErrorClass };
144
144
  }
145
145
 
146
+ /**
147
+ * Set expiration time for cookies.
148
+ * @param days - Number of days until cookies expire.
149
+ */
146
150
  declare function setExpireDays(days: number): void;
151
+ /**
152
+ * Is consent pending (cookies not yet accepted)?
153
+ * @returns
154
+ */
147
155
  declare function isConsentPending(): boolean;
156
+ /**
157
+ * Consent cookies.
158
+ */
148
159
  declare function accept(): void;
160
+ /**
161
+ * Decline cookies. This will reject all cookies than a single flags that cookies have been declined.
162
+ */
149
163
  declare function decline(): void;
164
+ /**
165
+ * Save a cookie.
166
+ * @param name - Cookie name.
167
+ * @param value - Cookie value, can be string, number or boolean.
168
+ * @returns - Returns given value.
169
+ */
150
170
  declare function save<T extends string | number | boolean>(name: string, value: T): T;
171
+ /**
172
+ * Read a string cookie.
173
+ * @param name - Cookie name.
174
+ * @param defaultValue - Default value returned when cookie with given name was not found.
175
+ * @returns - String cookie value.
176
+ */
151
177
  declare function read(name: string, defaultValue: string): string;
178
+ /**
179
+ * Read an integer cookie.
180
+ * @param name - Cookie name.
181
+ * @param defaultValue - Default value returned when cookie with given name was not found.
182
+ * @returns - Integer cookie valus.
183
+ */
152
184
  declare function readInt(name: string, defaultValue: number): number;
185
+ /**
186
+ * Read a boolean cookie.
187
+ * @param name - Cookie name.
188
+ * @param defaultValue - Default value returned when cookie with given name was not found.
189
+ * @returns - Boolean cookie value.
190
+ */
153
191
  declare function readBool(name: string, defaultValue: boolean): boolean;
192
+ /**
193
+ * Erase cookie.
194
+ * @param name - Name of cookie to be erased.
195
+ */
154
196
  declare function erase(name: string): void;
197
+ /**
198
+ * Erase all cookies.
199
+ */
155
200
  declare function eraseAll(): void;
156
201
 
157
202
  declare const cookies_accept: typeof accept;
@@ -168,15 +213,39 @@ declare namespace cookies {
168
213
  export { cookies_accept as accept, cookies_decline as decline, cookies_erase as erase, cookies_eraseAll as eraseAll, cookies_isConsentPending as isConsentPending, cookies_read as read, cookies_readBool as readBool, cookies_readInt as readInt, cookies_save as save, cookies_setExpireDays as setExpireDays };
169
214
  }
170
215
 
216
+ /** Devices dots per inch. */
171
217
  declare const DPI: number;
218
+ /** Devices pixels per millimeter. */
172
219
  declare const PxPerMm: number;
220
+ /** Browsers scroll bar width. */
173
221
  declare const ScrollbarWidth: number;
222
+ /** Browsers system font size. */
174
223
  declare const FontSize: number;
224
+ /** Is touch device? */
175
225
  declare const IsTouchDevice: boolean;
226
+ /** Is mobile device? */
176
227
  declare const IsMobileDevice: boolean;
228
+ /** Host address. */
177
229
  declare const HostAddress: string;
230
+ /**
231
+ * Convert pixels to millimeters on a device.
232
+ * @param px - Pixels.
233
+ * @returns - Millimeters.
234
+ */
178
235
  declare function pxToMm(px: number): number;
236
+ /**
237
+ * Convert millimeters to pixels on a device.
238
+ * @param mm - Millimeters.
239
+ * @returns - Pixels.
240
+ */
179
241
  declare function mmToPx(mm: number): number;
242
+ /**
243
+ * Convert input to pixels on a device. Input value is in html style form containing number
244
+ * followed by unit (e.g. "10px"). Supported units are "mm", "cm", "in", "inch", "em" and "px".
245
+ *
246
+ * @param input - Input value.
247
+ * @returns - Pixels.
248
+ */
180
249
  declare function toPx(input: string | number): number;
181
250
 
182
251
  declare const device_DPI: typeof DPI;
@@ -310,8 +379,9 @@ declare namespace Guard {
310
379
 
311
380
  declare function toArray<T>(a: T | T[]): Array<T>;
312
381
  declare function duplicate<T>(a: T[] | undefined): T[] | undefined;
313
- declare function removeDuplicates<T>(a: T[]): T[];
314
- declare function removeDuplicatesCmp<T>(arr: ReadonlyArray<T>, cmp: (t1: T, t2: T) => boolean): T[];
382
+ declare function removeDuplicates<T>(arr: T[], compareFn?: (a: T, b: T) => boolean): T[];
383
+ /** @deprecated - Use {@link removeDuplicates} with compareFn instead. */
384
+ declare function removeDuplicatesCmp<T>(arr: ReadonlyArray<T>, compareFn: (t1: T, t2: T) => boolean): T[];
315
385
  declare function fillArray<T>(fillValue: T, fillCount: number): T[];
316
386
  declare function mapSequenceArray<T>(len: number, fn: (i: number) => T): T[];
317
387
  declare function getSequenceArray(len: number): number[];
@@ -545,18 +615,33 @@ declare namespace index {
545
615
  export { index$6 as Arr, index$5 as Dom, index$8 as Enum, index_Is as Is, index$4 as Map, index$3 as Math, index$2 as Obj, index$1 as Str };
546
616
  }
547
617
 
618
+ /**
619
+ * This is a stack data structure.
620
+ */
548
621
  declare class Stack<T> {
549
- private readonly list;
550
- push(e: T): T;
622
+ private readonly data;
623
+ private assertId;
624
+ get length(): number;
625
+ push(el: T): T;
551
626
  pop(): T;
627
+ popOrUndef(): T | undefined;
628
+ popOr(defaultValueOrCreator: T | (() => T)): T;
552
629
  top(): T;
630
+ topOrUndef(): T | undefined;
631
+ topOr(defaultValueOrCreator: T | (() => T)): T;
632
+ peek(depth?: number): T;
633
+ peekOrUndef(depth?: number): T | undefined;
634
+ peekOr(depth: number | undefined, defaultValueOrCreator: T | (() => T)): T;
635
+ values(): IterableIterator<T>;
636
+ [Symbol.iterator](): IterableIterator<T>;
553
637
  toArray(): T[];
554
- get length(): number;
638
+ isEmpty(): boolean;
555
639
  clear(): void;
640
+ toString(): string;
556
641
  }
557
642
 
558
643
  /**
559
- * Vector class.
644
+ * `Vec` is a generic vector class with two or more coordinates.
560
645
  *
561
646
  * ```ts
562
647
  * // Example usage:
@@ -606,7 +691,7 @@ declare class Vec {
606
691
  }
607
692
 
608
693
  /**
609
- * DivRect class, left, top, right, bottom rectangle divided into four sections by anchorX, anchorY.
694
+ * DivRect class is a rectangle (left, top, right, bottom) with an anchor point (anchorX, anchorY).
610
695
  */
611
696
  declare class DivRect {
612
697
  left: number;
@@ -830,7 +915,7 @@ declare class DivRect {
830
915
  }
831
916
 
832
917
  /**
833
- * LRUCache class: Least Recently Used cache with a fixed capacity
918
+ * LRUCache is an implementation of least recently used cache with a fixed capacity.
834
919
  */
835
920
  declare class LRUCache<K extends string, V> {
836
921
  private cache;
@@ -867,7 +952,8 @@ interface KVComponent<K extends any[], VALUE> {
867
952
  }
868
953
 
869
954
  /**
870
- * An array-like structure for non-negative indexes.
955
+ * `IndexArray` is a sparse array with non-negative indexes. It stores values
956
+ * to indexes, and each index also has flag telling it has a value.
871
957
  */
872
958
  declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
873
959
  private static validateIndex;
@@ -879,6 +965,8 @@ declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
879
965
  constructor(entries: Iterable<[number, VALUE]>);
880
966
  private get posLen();
881
967
  get size(): number;
968
+ get length(): number;
969
+ private trimRight;
882
970
  isEmpty(): boolean;
883
971
  has(id: number): boolean;
884
972
  set(id: number, value: VALUE): void;
@@ -898,7 +986,7 @@ declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
898
986
  kvKeys(): IterableIterator<[number]>;
899
987
  kvValues(): IterableIterator<VALUE>;
900
988
  kvEntries(): IterableIterator<[[number], VALUE]>;
901
- [Symbol.iterator](): Generator<[number, VALUE], void, any>;
989
+ [Symbol.iterator](): IterableIterator<[number, VALUE]>;
902
990
  clone(): IndexArray<VALUE>;
903
991
  merge(other: IndexArray<VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, id: number) => VALUE): this;
904
992
  some(fn: (value: VALUE, id: number) => boolean): boolean;
@@ -911,11 +999,13 @@ declare class IndexArray<VALUE> implements KVComponent<[number], VALUE> {
911
999
  map<R = VALUE>(fn: (value: VALUE, key1: number) => R): IndexArray<R>;
912
1000
  equals(other: IndexArray<VALUE>): boolean;
913
1001
  equals(other: IndexArray<VALUE>, eq: (a: VALUE, b: VALUE) => boolean): boolean;
1002
+ toArray(): VALUE[];
914
1003
  toString(): string;
915
1004
  }
916
1005
 
917
1006
  /**
918
- * An array-like structure for signed indexes, including negatives.
1007
+ * `IndexArray` is a sparse array with positive and negative indexes. It stores
1008
+ * values to indexes, and each index also has flag telling it has a value.
919
1009
  */
920
1010
  declare class SignedIndexArray<VALUE> implements KVComponent<[number], VALUE> {
921
1011
  private static toNegIndex;
@@ -950,7 +1040,7 @@ declare class SignedIndexArray<VALUE> implements KVComponent<[number], VALUE> {
950
1040
  kvKeys(): IterableIterator<[number]>;
951
1041
  kvValues(): IterableIterator<VALUE>;
952
1042
  kvEntries(): IterableIterator<[[number], VALUE]>;
953
- [Symbol.iterator](): Generator<[number, VALUE], void, any>;
1043
+ [Symbol.iterator](): IterableIterator<[number, VALUE]>;
954
1044
  clone(): SignedIndexArray<VALUE>;
955
1045
  merge(other: SignedIndexArray<VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, id: number) => VALUE): this;
956
1046
  some(fn: (value: VALUE, id: number) => boolean): boolean;
@@ -963,9 +1053,13 @@ declare class SignedIndexArray<VALUE> implements KVComponent<[number], VALUE> {
963
1053
  map<R = VALUE>(fn: (value: VALUE, key1: number) => R): SignedIndexArray<R>;
964
1054
  equals(other: SignedIndexArray<VALUE>): boolean;
965
1055
  equals(other: SignedIndexArray<VALUE>, eq: (a: VALUE, b: VALUE) => boolean): boolean;
1056
+ toArray(): VALUE[];
966
1057
  toString(): string;
967
1058
  }
968
1059
 
1060
+ /**
1061
+ * A Map implementation mapping a single key to a value.
1062
+ */
969
1063
  declare class Map1<KEY1, VALUE> implements KVComponent<[KEY1], VALUE> {
970
1064
  private map1;
971
1065
  constructor();
@@ -991,7 +1085,7 @@ declare class Map1<KEY1, VALUE> implements KVComponent<[KEY1], VALUE> {
991
1085
  kvKeys(): IterableIterator<[KEY1]>;
992
1086
  kvValues(): IterableIterator<VALUE>;
993
1087
  kvEntries(): IterableIterator<[[KEY1], VALUE]>;
994
- [Symbol.iterator](): Generator<[KEY1, VALUE], void, any>;
1088
+ [Symbol.iterator](): IterableIterator<[KEY1, VALUE]>;
995
1089
  clone(): Map1<KEY1, VALUE>;
996
1090
  merge(other: Map1<KEY1, VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, key1: KEY1) => VALUE): this;
997
1091
  some(fn: (value: VALUE, key1: KEY1) => boolean): boolean;
@@ -1006,6 +1100,9 @@ declare class Map1<KEY1, VALUE> implements KVComponent<[KEY1], VALUE> {
1006
1100
  toString(): string;
1007
1101
  }
1008
1102
 
1103
+ /**
1104
+ * A Map implementation mapping a double key to a value.
1105
+ */
1009
1106
  declare class Map2<KEY1, KEY2, VALUE> implements KVComponent<[KEY1, KEY2], VALUE> {
1010
1107
  private map1;
1011
1108
  constructor();
@@ -1032,7 +1129,7 @@ declare class Map2<KEY1, KEY2, VALUE> implements KVComponent<[KEY1, KEY2], VALUE
1032
1129
  kvKeys(): IterableIterator<[KEY1, KEY2]>;
1033
1130
  kvValues(): IterableIterator<VALUE>;
1034
1131
  kvEntries(): IterableIterator<[[KEY1, KEY2], VALUE]>;
1035
- [Symbol.iterator](): Generator<[KEY1, KEY2, VALUE], void, any>;
1132
+ [Symbol.iterator](): IterableIterator<[KEY1, KEY2, VALUE]>;
1036
1133
  clone(): Map2<KEY1, KEY2, VALUE>;
1037
1134
  merge(other: Map2<KEY1, KEY2, VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, key1: KEY1, key2: KEY2) => VALUE): this;
1038
1135
  some(fn: (value: VALUE, key1: KEY1, key2: KEY2) => boolean): boolean;
@@ -1047,6 +1144,9 @@ declare class Map2<KEY1, KEY2, VALUE> implements KVComponent<[KEY1, KEY2], VALUE
1047
1144
  toString(): string;
1048
1145
  }
1049
1146
 
1147
+ /**
1148
+ * A Map implementation mapping a triple key to a value.
1149
+ */
1050
1150
  declare class Map3<KEY1, KEY2, KEY3, VALUE> implements KVComponent<[KEY1, KEY2, KEY3], VALUE> {
1051
1151
  private map1;
1052
1152
  constructor();
@@ -1074,7 +1174,7 @@ declare class Map3<KEY1, KEY2, KEY3, VALUE> implements KVComponent<[KEY1, KEY2,
1074
1174
  kvKeys(): IterableIterator<[KEY1, KEY2, KEY3]>;
1075
1175
  kvValues(): IterableIterator<VALUE>;
1076
1176
  kvEntries(): IterableIterator<[[KEY1, KEY2, KEY3], VALUE]>;
1077
- [Symbol.iterator](): Generator<[KEY1, KEY2, KEY3, VALUE], void, any>;
1177
+ [Symbol.iterator](): IterableIterator<[KEY1, KEY2, KEY3, VALUE]>;
1078
1178
  clone(): Map3<KEY1, KEY2, KEY3, VALUE>;
1079
1179
  merge(other: Map3<KEY1, KEY2, KEY3, VALUE>, conflictResolver?: (oldValue: VALUE, newValue: VALUE, key1: KEY1, key2: KEY2, key3: KEY3) => VALUE): this;
1080
1180
  some(fn: (value: VALUE, key1: KEY1, key2: KEY2, key3: KEY3) => boolean): boolean;
@@ -1089,6 +1189,9 @@ declare class Map3<KEY1, KEY2, KEY3, VALUE> implements KVComponent<[KEY1, KEY2,
1089
1189
  toString(): string;
1090
1190
  }
1091
1191
 
1192
+ /**
1193
+ * Wrapper class of a key-value container that contain array values.
1194
+ */
1092
1195
  declare class MultiContainer<K extends any[], V> {
1093
1196
  private readonly base;
1094
1197
  constructor(base: KVComponent<K, V[]>);
@@ -1105,10 +1208,14 @@ declare class MultiContainer<K extends any[], V> {
1105
1208
  toString(): string;
1106
1209
  }
1107
1210
  /**
1211
+ * Create a multi-container.
1212
+ *
1108
1213
  * ```ts
1109
1214
  * // Usage:
1110
1215
  * const multi = asMulti(new Map2<string, string, number[]>());
1111
- * multi.add("A", "B", 5);
1216
+ * multi.add("a", "b", 5);
1217
+ * multi.add("a", "b", 10);
1218
+ * multi.add("a", "c", 15);
1112
1219
  * ```
1113
1220
  * @param base
1114
1221
  * @returns
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /* TsUtilsLib v1.18.0 | (c) 2023 PahkaSoft | Licensed under the MIT License */
1
+ /* TsUtilsLib v1.19.0 | (c) 2023 PahkaSoft | Licensed under the MIT License */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -516,21 +516,6 @@ var _consent;
516
516
  var _expires;
517
517
  var str = _read(ConsentCookieName);
518
518
  _consent = str === "accept" /* Accept */ || str === "decline" /* Decline */ ? str : void 0;
519
- function setExpireDays(days) {
520
- _expires = /* @__PURE__ */ new Date();
521
- _expires.setDate(_expires.getDate() + days);
522
- }
523
- function isConsentPending() {
524
- return _consent === void 0;
525
- }
526
- function accept() {
527
- _consent = "accept" /* Accept */;
528
- _save(ConsentCookieName, _consent);
529
- }
530
- function decline() {
531
- _consent = "decline" /* Decline */;
532
- _save(ConsentCookieName, _consent);
533
- }
534
519
  function _getList() {
535
520
  let s = document.cookie;
536
521
  return s.split(";").map((c) => c.trim());
@@ -550,18 +535,31 @@ function _read(name, defaultValue) {
550
535
  function _erase(name) {
551
536
  document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 UTC;";
552
537
  }
538
+ function setExpireDays(days) {
539
+ _expires = /* @__PURE__ */ new Date();
540
+ _expires.setDate(_expires.getDate() + days);
541
+ }
542
+ function isConsentPending() {
543
+ return _consent === void 0;
544
+ }
545
+ function accept() {
546
+ _consent = "accept" /* Accept */;
547
+ _save(ConsentCookieName, _consent);
548
+ }
549
+ function decline() {
550
+ _consent = "decline" /* Decline */;
551
+ _save(ConsentCookieName, _consent);
552
+ }
553
553
  function save(name, value) {
554
- if (_consent === "accept" /* Accept */) {
554
+ if (_consent === "accept" /* Accept */)
555
555
  _save(name, value);
556
- }
557
556
  return value;
558
557
  }
559
558
  function read(name, defaultValue) {
560
- if (_consent === "accept" /* Accept */) {
561
- return _read(name, defaultValue) || defaultValue;
562
- } else {
559
+ if (_consent === "accept" /* Accept */)
560
+ return _read(name, defaultValue) ?? defaultValue;
561
+ else
563
562
  return defaultValue;
564
- }
565
563
  }
566
564
  function readInt(name, defaultValue) {
567
565
  if (_consent === "accept" /* Accept */) {
@@ -580,9 +578,8 @@ function readBool(name, defaultValue) {
580
578
  }
581
579
  }
582
580
  function erase(name) {
583
- if (_consent === "accept" /* Accept */ || name === ConsentCookieName) {
581
+ if (_consent === "accept" /* Accept */ || name === ConsentCookieName)
584
582
  _erase(name);
585
- }
586
583
  }
587
584
  function eraseAll() {
588
585
  document.cookie.split(";").forEach((c) => erase(c.trim().split("=")[0]));
@@ -690,7 +687,7 @@ function toPx(input) {
690
687
  } else {
691
688
  value = parseFloat(input);
692
689
  }
693
- assert_exports.finite(value, "value in function toPx");
690
+ assert_exports.isFinite(value, "value in function toPx");
694
691
  switch (unit) {
695
692
  case "mm":
696
693
  return mmToPx(value);
@@ -1038,11 +1035,11 @@ function toArray(a) {
1038
1035
  function duplicate(a) {
1039
1036
  return a === void 0 ? a : a.slice();
1040
1037
  }
1041
- function removeDuplicates(a) {
1042
- return a.filter((item, pos, arr) => arr.indexOf(item) === pos);
1038
+ function removeDuplicates(arr, compareFn) {
1039
+ return compareFn !== void 0 ? arr.filter((a, id, self) => id === self.findIndex((b) => compareFn(a, b))) : arr.filter((a, id, self) => id === self.indexOf(a));
1043
1040
  }
1044
- function removeDuplicatesCmp(arr, cmp2) {
1045
- return arr.filter((t1, index, self) => index === self.findIndex((t2) => cmp2(t1, t2)));
1041
+ function removeDuplicatesCmp(arr, compareFn) {
1042
+ return arr.filter((a, id, self) => id === self.findIndex((b) => compareFn(a, b)));
1046
1043
  }
1047
1044
  function fillArray(fillValue, fillCount) {
1048
1045
  if (!isInteger2(fillCount) || fillCount < 0) {
@@ -1505,30 +1502,83 @@ function makeSentenceFromPascal(PascalString) {
1505
1502
  // src/utils/index.ts
1506
1503
  var Is = guard_exports;
1507
1504
 
1505
+ // src/core/format-value.ts
1506
+ function formatValue(value) {
1507
+ if (isString2(value)) {
1508
+ return `"${value}"`;
1509
+ } else if (isArray2(value)) {
1510
+ return `[ ${value.map((e) => formatValue(e)).join(", ")} ]`.replaceAll(" ", " ");
1511
+ } else if (isFunction2(value.toString)) {
1512
+ return value.toString();
1513
+ } else {
1514
+ return JSON.stringify(value);
1515
+ }
1516
+ }
1517
+
1508
1518
  // src/core/stack.ts
1509
1519
  var Stack = class {
1510
1520
  constructor() {
1511
- __publicField(this, "list", []);
1521
+ __publicField(this, "data", []);
1522
+ }
1523
+ assertId(id) {
1524
+ assert_exports.isIntegerBetween(id, 0, this.length - 1, `Stack index ${id} out of range.`);
1525
+ return id;
1512
1526
  }
1513
- push(e) {
1514
- this.list.push(e);
1515
- return e;
1527
+ get length() {
1528
+ return this.data.length;
1529
+ }
1530
+ push(el) {
1531
+ this.data.push(el);
1532
+ return el;
1516
1533
  }
1517
1534
  pop() {
1518
- assert_exports.int_gt(this.list.length, 0);
1519
- return this.list.pop();
1535
+ this.assertId(this.length - 1);
1536
+ return this.data.pop();
1537
+ }
1538
+ popOrUndef() {
1539
+ return this.data.pop();
1540
+ }
1541
+ popOr(defaultValueOrCreator) {
1542
+ return this.isEmpty() ? isFunction2(defaultValueOrCreator) ? defaultValueOrCreator() : defaultValueOrCreator : this.data.pop();
1520
1543
  }
1521
1544
  top() {
1522
- return assert_exports.array_elem(this.list, this.list.length - 1, "Stack is empty!");
1545
+ return this.data[this.assertId(this.length - 1)];
1546
+ }
1547
+ topOrUndef() {
1548
+ return this.data[this.length - 1];
1549
+ }
1550
+ topOr(defaultValueOrCreator) {
1551
+ return this.isEmpty() ? isFunction2(defaultValueOrCreator) ? defaultValueOrCreator() : defaultValueOrCreator : this.data[this.length - 1];
1552
+ }
1553
+ peek(depth = 0) {
1554
+ return this.data[this.assertId(this.data.length - 1 - depth)];
1555
+ }
1556
+ peekOrUndef(depth = 0) {
1557
+ return this.data[this.data.length - 1 - depth];
1558
+ }
1559
+ peekOr(depth = 0, defaultValueOrCreator) {
1560
+ const id = this.data.length - 1 - depth;
1561
+ const value = id < 0 ? void 0 : this.data[id];
1562
+ return value === void 0 ? isFunction2(defaultValueOrCreator) ? defaultValueOrCreator() : defaultValueOrCreator : value;
1563
+ }
1564
+ *values() {
1565
+ for (let id = this.data.length - 1; id >= 0; id--)
1566
+ yield this.data[id];
1567
+ }
1568
+ *[Symbol.iterator]() {
1569
+ yield* this.values();
1523
1570
  }
1524
1571
  toArray() {
1525
- return this.list;
1572
+ return [...this.data];
1526
1573
  }
1527
- get length() {
1528
- return this.list.length;
1574
+ isEmpty() {
1575
+ return this.length === 0;
1529
1576
  }
1530
1577
  clear() {
1531
- this.list.length = 0;
1578
+ this.data.length = 0;
1579
+ }
1580
+ toString() {
1581
+ return `Stack(${this.length})${formatValue(this.data)}`;
1532
1582
  }
1533
1583
  };
1534
1584
 
@@ -2112,6 +2162,14 @@ var IndexArray = class _IndexArray {
2112
2162
  get size() {
2113
2163
  return this.valCount;
2114
2164
  }
2165
+ get length() {
2166
+ return this.hasPos.length;
2167
+ }
2168
+ trimRight() {
2169
+ let newLength = this.length;
2170
+ while (newLength > 0 && this.hasPos[newLength - 1] !== true) newLength--;
2171
+ if (newLength < this.length) this.posVal.length = this.hasPos.length = newLength;
2172
+ }
2115
2173
  isEmpty() {
2116
2174
  return this.size === 0;
2117
2175
  }
@@ -2146,6 +2204,7 @@ var IndexArray = class _IndexArray {
2146
2204
  this.posVal[id] = void 0;
2147
2205
  this.hasPos[id] = false;
2148
2206
  this.valCount--;
2207
+ this.trimRight();
2149
2208
  return true;
2150
2209
  }
2151
2210
  clear() {
@@ -2282,10 +2341,12 @@ var IndexArray = class _IndexArray {
2282
2341
  }
2283
2342
  return true;
2284
2343
  }
2344
+ toArray() {
2345
+ return this.valuesArray();
2346
+ }
2285
2347
  toString() {
2286
- if (this.size === 0) return `IndexArray[ ]`;
2287
- const entries = this.entriesArray().map(([id, value]) => `${id}: ${value}`).join(", ");
2288
- return `IndexArray[ ${entries} ]`;
2348
+ const entries = this.entriesArray().map(([id, v]) => `${formatValue(id)}: ${formatValue(v)}`).join(", ");
2349
+ return `IndexArray[ ${entries} ]`.replaceAll(" ", " ");
2289
2350
  }
2290
2351
  };
2291
2352
 
@@ -2543,10 +2604,12 @@ var SignedIndexArray = class _SignedIndexArray {
2543
2604
  }
2544
2605
  return true;
2545
2606
  }
2607
+ toArray() {
2608
+ return this.valuesArray();
2609
+ }
2546
2610
  toString() {
2547
- if (this.size === 0) return `SignedIndexArray[ ]`;
2548
- const entries = this.entriesArray().map(([id, value]) => `${id}: ${value}`).join(", ");
2549
- return `SignedIndexArray[ ${entries} ]`;
2611
+ const entries = this.entriesArray().map(([id, v]) => `${formatValue(id)}: ${formatValue(v)}`).join(", ");
2612
+ return `SignedIndexArray[ ${entries} ]`.replaceAll(" ", " ");
2550
2613
  }
2551
2614
  };
2552
2615
 
@@ -2703,8 +2766,8 @@ var Map1 = class _Map1 {
2703
2766
  return new Map(this.map1);
2704
2767
  }
2705
2768
  toString() {
2706
- const entries = [...this.map1].map(([k, v]) => `${k} => ${v}`).join(", ");
2707
- return entries.length === 0 ? `Map1(0){ }` : `Map1(${this.size}){ ${entries} }`;
2769
+ const entries = [...this.map1].map(([k, v]) => `${formatValue(k)} => ${formatValue(v)}`).join(", ");
2770
+ return `Map1(${this.size}){ ${entries} }`.replaceAll(" ", " ");
2708
2771
  }
2709
2772
  };
2710
2773
 
@@ -2897,10 +2960,10 @@ var Map2 = class _Map2 {
2897
2960
  toString() {
2898
2961
  const entries = [];
2899
2962
  for (const [key1, map2] of this.map1) {
2900
- const inner = [...map2].map(([key2, v]) => `${key2} => ${v}`).join(", ");
2901
- entries.push(`${key1} => { ${inner} }`);
2963
+ const inner = [...map2].map(([key2, v]) => `${formatValue(key2)} => ${formatValue(v)}`).join(", ");
2964
+ entries.push(`${formatValue(key1)} => { ${inner} }`);
2902
2965
  }
2903
- return entries.length === 0 ? `Map2(0){ }` : `Map2(${this.size}){ ${entries} }`;
2966
+ return `Map2(${this.size}){ ${entries} }`.replaceAll(" ", " ");
2904
2967
  }
2905
2968
  };
2906
2969
 
@@ -3125,11 +3188,11 @@ var Map3 = class _Map3 {
3125
3188
  const entries = [];
3126
3189
  for (const [key1, map2] of this.map1) {
3127
3190
  for (const [key2, map3] of map2) {
3128
- const inner = [...map3].map(([key3, v]) => `${key3} => ${v}`).join(", ");
3129
- entries.push(`${key1} => ${key2} => { ${inner} }`);
3191
+ const inner = [...map3].map(([key3, v]) => `${formatValue(key3)} => ${formatValue(v)}`).join(", ");
3192
+ entries.push(`${formatValue(key1)} => ${formatValue(key2)} => { ${inner} }`);
3130
3193
  }
3131
3194
  }
3132
- return entries.length === 0 ? `Map3(0){ }` : `Map3(${this.size}){ ${entries.join(", ")} }`;
3195
+ return `Map3(${this.size}){ ${entries.join(", ")} }`.replaceAll(" ", " ");
3133
3196
  }
3134
3197
  };
3135
3198
 
@@ -3191,11 +3254,11 @@ var MultiContainer = class {
3191
3254
  const entries = [];
3192
3255
  for (const keys of this.keys()) {
3193
3256
  const arr = this.getAll(...keys);
3194
- const keyStr = Array.isArray(keys) ? `[${keys.map((k) => JSON.stringify(k)).join(", ")}]` : `[${JSON.stringify(keys)}]`;
3195
- const valuesStr = Array.isArray(arr) ? `[${arr.map((v) => JSON.stringify(v)).join(", ")}]` : "[]";
3257
+ const keyStr = Array.isArray(keys) ? formatValue(keys) : "[ ]";
3258
+ const valuesStr = Array.isArray(arr) ? formatValue(arr) : "[ ]";
3196
3259
  entries.push(`${keyStr} => ${valuesStr}`);
3197
3260
  }
3198
- return `MultiContainer{ ${entries.join(", ")} }`;
3261
+ return `MultiContainer{ ${entries.join(", ")} }`.replaceAll(" ", " ");
3199
3262
  }
3200
3263
  };
3201
3264
  function asMulti(base) {
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- /* TsUtilsLib v1.18.0 | (c) 2023 PahkaSoft | Licensed under the MIT License */
1
+ /* TsUtilsLib v1.19.0 | (c) 2023 PahkaSoft | Licensed under the MIT License */
2
2
  var __defProp = Object.defineProperty;
3
3
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
4
  var __export = (target, all) => {
@@ -479,21 +479,6 @@ var _consent;
479
479
  var _expires;
480
480
  var str = _read(ConsentCookieName);
481
481
  _consent = str === "accept" /* Accept */ || str === "decline" /* Decline */ ? str : void 0;
482
- function setExpireDays(days) {
483
- _expires = /* @__PURE__ */ new Date();
484
- _expires.setDate(_expires.getDate() + days);
485
- }
486
- function isConsentPending() {
487
- return _consent === void 0;
488
- }
489
- function accept() {
490
- _consent = "accept" /* Accept */;
491
- _save(ConsentCookieName, _consent);
492
- }
493
- function decline() {
494
- _consent = "decline" /* Decline */;
495
- _save(ConsentCookieName, _consent);
496
- }
497
482
  function _getList() {
498
483
  let s = document.cookie;
499
484
  return s.split(";").map((c) => c.trim());
@@ -513,18 +498,31 @@ function _read(name, defaultValue) {
513
498
  function _erase(name) {
514
499
  document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 UTC;";
515
500
  }
501
+ function setExpireDays(days) {
502
+ _expires = /* @__PURE__ */ new Date();
503
+ _expires.setDate(_expires.getDate() + days);
504
+ }
505
+ function isConsentPending() {
506
+ return _consent === void 0;
507
+ }
508
+ function accept() {
509
+ _consent = "accept" /* Accept */;
510
+ _save(ConsentCookieName, _consent);
511
+ }
512
+ function decline() {
513
+ _consent = "decline" /* Decline */;
514
+ _save(ConsentCookieName, _consent);
515
+ }
516
516
  function save(name, value) {
517
- if (_consent === "accept" /* Accept */) {
517
+ if (_consent === "accept" /* Accept */)
518
518
  _save(name, value);
519
- }
520
519
  return value;
521
520
  }
522
521
  function read(name, defaultValue) {
523
- if (_consent === "accept" /* Accept */) {
524
- return _read(name, defaultValue) || defaultValue;
525
- } else {
522
+ if (_consent === "accept" /* Accept */)
523
+ return _read(name, defaultValue) ?? defaultValue;
524
+ else
526
525
  return defaultValue;
527
- }
528
526
  }
529
527
  function readInt(name, defaultValue) {
530
528
  if (_consent === "accept" /* Accept */) {
@@ -543,9 +541,8 @@ function readBool(name, defaultValue) {
543
541
  }
544
542
  }
545
543
  function erase(name) {
546
- if (_consent === "accept" /* Accept */ || name === ConsentCookieName) {
544
+ if (_consent === "accept" /* Accept */ || name === ConsentCookieName)
547
545
  _erase(name);
548
- }
549
546
  }
550
547
  function eraseAll() {
551
548
  document.cookie.split(";").forEach((c) => erase(c.trim().split("=")[0]));
@@ -653,7 +650,7 @@ function toPx(input) {
653
650
  } else {
654
651
  value = parseFloat(input);
655
652
  }
656
- assert_exports.finite(value, "value in function toPx");
653
+ assert_exports.isFinite(value, "value in function toPx");
657
654
  switch (unit) {
658
655
  case "mm":
659
656
  return mmToPx(value);
@@ -1001,11 +998,11 @@ function toArray(a) {
1001
998
  function duplicate(a) {
1002
999
  return a === void 0 ? a : a.slice();
1003
1000
  }
1004
- function removeDuplicates(a) {
1005
- return a.filter((item, pos, arr) => arr.indexOf(item) === pos);
1001
+ function removeDuplicates(arr, compareFn) {
1002
+ return compareFn !== void 0 ? arr.filter((a, id, self) => id === self.findIndex((b) => compareFn(a, b))) : arr.filter((a, id, self) => id === self.indexOf(a));
1006
1003
  }
1007
- function removeDuplicatesCmp(arr, cmp2) {
1008
- return arr.filter((t1, index, self) => index === self.findIndex((t2) => cmp2(t1, t2)));
1004
+ function removeDuplicatesCmp(arr, compareFn) {
1005
+ return arr.filter((a, id, self) => id === self.findIndex((b) => compareFn(a, b)));
1009
1006
  }
1010
1007
  function fillArray(fillValue, fillCount) {
1011
1008
  if (!isInteger2(fillCount) || fillCount < 0) {
@@ -1468,30 +1465,83 @@ function makeSentenceFromPascal(PascalString) {
1468
1465
  // src/utils/index.ts
1469
1466
  var Is = guard_exports;
1470
1467
 
1468
+ // src/core/format-value.ts
1469
+ function formatValue(value) {
1470
+ if (isString2(value)) {
1471
+ return `"${value}"`;
1472
+ } else if (isArray2(value)) {
1473
+ return `[ ${value.map((e) => formatValue(e)).join(", ")} ]`.replaceAll(" ", " ");
1474
+ } else if (isFunction2(value.toString)) {
1475
+ return value.toString();
1476
+ } else {
1477
+ return JSON.stringify(value);
1478
+ }
1479
+ }
1480
+
1471
1481
  // src/core/stack.ts
1472
1482
  var Stack = class {
1473
1483
  constructor() {
1474
- __publicField(this, "list", []);
1484
+ __publicField(this, "data", []);
1485
+ }
1486
+ assertId(id) {
1487
+ assert_exports.isIntegerBetween(id, 0, this.length - 1, `Stack index ${id} out of range.`);
1488
+ return id;
1475
1489
  }
1476
- push(e) {
1477
- this.list.push(e);
1478
- return e;
1490
+ get length() {
1491
+ return this.data.length;
1492
+ }
1493
+ push(el) {
1494
+ this.data.push(el);
1495
+ return el;
1479
1496
  }
1480
1497
  pop() {
1481
- assert_exports.int_gt(this.list.length, 0);
1482
- return this.list.pop();
1498
+ this.assertId(this.length - 1);
1499
+ return this.data.pop();
1500
+ }
1501
+ popOrUndef() {
1502
+ return this.data.pop();
1503
+ }
1504
+ popOr(defaultValueOrCreator) {
1505
+ return this.isEmpty() ? isFunction2(defaultValueOrCreator) ? defaultValueOrCreator() : defaultValueOrCreator : this.data.pop();
1483
1506
  }
1484
1507
  top() {
1485
- return assert_exports.array_elem(this.list, this.list.length - 1, "Stack is empty!");
1508
+ return this.data[this.assertId(this.length - 1)];
1509
+ }
1510
+ topOrUndef() {
1511
+ return this.data[this.length - 1];
1512
+ }
1513
+ topOr(defaultValueOrCreator) {
1514
+ return this.isEmpty() ? isFunction2(defaultValueOrCreator) ? defaultValueOrCreator() : defaultValueOrCreator : this.data[this.length - 1];
1515
+ }
1516
+ peek(depth = 0) {
1517
+ return this.data[this.assertId(this.data.length - 1 - depth)];
1518
+ }
1519
+ peekOrUndef(depth = 0) {
1520
+ return this.data[this.data.length - 1 - depth];
1521
+ }
1522
+ peekOr(depth = 0, defaultValueOrCreator) {
1523
+ const id = this.data.length - 1 - depth;
1524
+ const value = id < 0 ? void 0 : this.data[id];
1525
+ return value === void 0 ? isFunction2(defaultValueOrCreator) ? defaultValueOrCreator() : defaultValueOrCreator : value;
1526
+ }
1527
+ *values() {
1528
+ for (let id = this.data.length - 1; id >= 0; id--)
1529
+ yield this.data[id];
1530
+ }
1531
+ *[Symbol.iterator]() {
1532
+ yield* this.values();
1486
1533
  }
1487
1534
  toArray() {
1488
- return this.list;
1535
+ return [...this.data];
1489
1536
  }
1490
- get length() {
1491
- return this.list.length;
1537
+ isEmpty() {
1538
+ return this.length === 0;
1492
1539
  }
1493
1540
  clear() {
1494
- this.list.length = 0;
1541
+ this.data.length = 0;
1542
+ }
1543
+ toString() {
1544
+ return `Stack(${this.length})${formatValue(this.data)}`;
1495
1545
  }
1496
1546
  };
1497
1547
 
@@ -2075,6 +2125,14 @@ var IndexArray = class _IndexArray {
2075
2125
  get size() {
2076
2126
  return this.valCount;
2077
2127
  }
2128
+ get length() {
2129
+ return this.hasPos.length;
2130
+ }
2131
+ trimRight() {
2132
+ let newLength = this.length;
2133
+ while (newLength > 0 && this.hasPos[newLength - 1] !== true) newLength--;
2134
+ if (newLength < this.length) this.posVal.length = this.hasPos.length = newLength;
2135
+ }
2078
2136
  isEmpty() {
2079
2137
  return this.size === 0;
2080
2138
  }
@@ -2109,6 +2167,7 @@ var IndexArray = class _IndexArray {
2109
2167
  this.posVal[id] = void 0;
2110
2168
  this.hasPos[id] = false;
2111
2169
  this.valCount--;
2170
+ this.trimRight();
2112
2171
  return true;
2113
2172
  }
2114
2173
  clear() {
@@ -2245,10 +2304,12 @@ var IndexArray = class _IndexArray {
2245
2304
  }
2246
2305
  return true;
2247
2306
  }
2307
+ toArray() {
2308
+ return this.valuesArray();
2309
+ }
2248
2310
  toString() {
2249
- if (this.size === 0) return `IndexArray[ ]`;
2250
- const entries = this.entriesArray().map(([id, value]) => `${id}: ${value}`).join(", ");
2251
- return `IndexArray[ ${entries} ]`;
2311
+ const entries = this.entriesArray().map(([id, v]) => `${formatValue(id)}: ${formatValue(v)}`).join(", ");
2312
+ return `IndexArray[ ${entries} ]`.replaceAll(" ", " ");
2252
2313
  }
2253
2314
  };
2254
2315
 
@@ -2506,10 +2567,12 @@ var SignedIndexArray = class _SignedIndexArray {
2506
2567
  }
2507
2568
  return true;
2508
2569
  }
2570
+ toArray() {
2571
+ return this.valuesArray();
2572
+ }
2509
2573
  toString() {
2510
- if (this.size === 0) return `SignedIndexArray[ ]`;
2511
- const entries = this.entriesArray().map(([id, value]) => `${id}: ${value}`).join(", ");
2512
- return `SignedIndexArray[ ${entries} ]`;
2574
+ const entries = this.entriesArray().map(([id, v]) => `${formatValue(id)}: ${formatValue(v)}`).join(", ");
2575
+ return `SignedIndexArray[ ${entries} ]`.replaceAll(" ", " ");
2513
2576
  }
2514
2577
  };
2515
2578
 
@@ -2666,8 +2729,8 @@ var Map1 = class _Map1 {
2666
2729
  return new Map(this.map1);
2667
2730
  }
2668
2731
  toString() {
2669
- const entries = [...this.map1].map(([k, v]) => `${k} => ${v}`).join(", ");
2670
- return entries.length === 0 ? `Map1(0){ }` : `Map1(${this.size}){ ${entries} }`;
2732
+ const entries = [...this.map1].map(([k, v]) => `${formatValue(k)} => ${formatValue(v)}`).join(", ");
2733
+ return `Map1(${this.size}){ ${entries} }`.replaceAll(" ", " ");
2671
2734
  }
2672
2735
  };
2673
2736
 
@@ -2860,10 +2923,10 @@ var Map2 = class _Map2 {
2860
2923
  toString() {
2861
2924
  const entries = [];
2862
2925
  for (const [key1, map2] of this.map1) {
2863
- const inner = [...map2].map(([key2, v]) => `${key2} => ${v}`).join(", ");
2864
- entries.push(`${key1} => { ${inner} }`);
2926
+ const inner = [...map2].map(([key2, v]) => `${formatValue(key2)} => ${formatValue(v)}`).join(", ");
2927
+ entries.push(`${formatValue(key1)} => { ${inner} }`);
2865
2928
  }
2866
- return entries.length === 0 ? `Map2(0){ }` : `Map2(${this.size}){ ${entries} }`;
2929
+ return `Map2(${this.size}){ ${entries} }`.replaceAll(" ", " ");
2867
2930
  }
2868
2931
  };
2869
2932
 
@@ -3088,11 +3151,11 @@ var Map3 = class _Map3 {
3088
3151
  const entries = [];
3089
3152
  for (const [key1, map2] of this.map1) {
3090
3153
  for (const [key2, map3] of map2) {
3091
- const inner = [...map3].map(([key3, v]) => `${key3} => ${v}`).join(", ");
3092
- entries.push(`${key1} => ${key2} => { ${inner} }`);
3154
+ const inner = [...map3].map(([key3, v]) => `${formatValue(key3)} => ${formatValue(v)}`).join(", ");
3155
+ entries.push(`${formatValue(key1)} => ${formatValue(key2)} => { ${inner} }`);
3093
3156
  }
3094
3157
  }
3095
- return entries.length === 0 ? `Map3(0){ }` : `Map3(${this.size}){ ${entries.join(", ")} }`;
3158
+ return `Map3(${this.size}){ ${entries.join(", ")} }`.replaceAll(" ", " ");
3096
3159
  }
3097
3160
  };
3098
3161
 
@@ -3154,11 +3217,11 @@ var MultiContainer = class {
3154
3217
  const entries = [];
3155
3218
  for (const keys of this.keys()) {
3156
3219
  const arr = this.getAll(...keys);
3157
- const keyStr = Array.isArray(keys) ? `[${keys.map((k) => JSON.stringify(k)).join(", ")}]` : `[${JSON.stringify(keys)}]`;
3158
- const valuesStr = Array.isArray(arr) ? `[${arr.map((v) => JSON.stringify(v)).join(", ")}]` : "[]";
3220
+ const keyStr = Array.isArray(keys) ? formatValue(keys) : "[ ]";
3221
+ const valuesStr = Array.isArray(arr) ? formatValue(arr) : "[ ]";
3159
3222
  entries.push(`${keyStr} => ${valuesStr}`);
3160
3223
  }
3161
- return `MultiContainer{ ${entries.join(", ")} }`;
3224
+ return `MultiContainer{ ${entries.join(", ")} }`.replaceAll(" ", " ");
3162
3225
  }
3163
3226
  };
3164
3227
  function asMulti(base) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tspro/ts-utils-lib",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "author": "PahkaSoft",
5
5
  "license": "MIT",
6
6
  "private": false,