@etsoo/shared 1.2.80 → 1.2.82
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/.github/workflows/main.yml +5 -3
- package/__tests__/Utils.ts +10 -0
- package/lib/cjs/DateUtils.js +1 -1
- package/lib/cjs/DomUtils.js +4 -4
- package/lib/cjs/NumberUtils.js +4 -4
- package/lib/cjs/StorageUtils.js +2 -2
- package/lib/cjs/Utils.d.ts +8 -0
- package/lib/cjs/Utils.js +59 -2
- package/lib/cjs/node/NodeStorage.js +5 -6
- package/lib/cjs/storage/IStorage.d.ts +1 -1
- package/lib/cjs/storage/WindowStorage.d.ts +1 -1
- package/lib/cjs/test/MockDOMRect.js +8 -0
- package/lib/cjs/test/MockResizeObserver.js +2 -2
- package/lib/cjs/types/ContentDisposition.js +3 -0
- package/lib/cjs/types/DataError.js +4 -0
- package/lib/cjs/types/EColor.js +4 -0
- package/lib/cjs/types/EHistory.js +7 -6
- package/lib/cjs/types/EventClass.js +7 -5
- package/lib/mjs/DateUtils.js +1 -1
- package/lib/mjs/DomUtils.js +4 -4
- package/lib/mjs/NumberUtils.js +4 -4
- package/lib/mjs/StorageUtils.js +2 -2
- package/lib/mjs/Utils.d.ts +8 -0
- package/lib/mjs/Utils.js +59 -2
- package/lib/mjs/node/NodeStorage.js +5 -6
- package/lib/mjs/storage/IStorage.d.ts +1 -1
- package/lib/mjs/storage/WindowStorage.d.ts +1 -1
- package/lib/mjs/test/MockDOMRect.js +8 -0
- package/lib/mjs/test/MockResizeObserver.js +2 -2
- package/lib/mjs/types/ContentDisposition.js +3 -0
- package/lib/mjs/types/DataError.js +4 -0
- package/lib/mjs/types/EColor.js +4 -0
- package/lib/mjs/types/EHistory.js +7 -6
- package/lib/mjs/types/EventClass.js +7 -5
- package/package.json +6 -6
- package/src/Utils.ts +67 -3
- package/src/storage/IStorage.ts +1 -1
- package/src/storage/WindowStorage.ts +1 -1
- package/tsconfig.cjs.json +3 -1
- package/tsconfig.json +4 -2
|
@@ -11,6 +11,10 @@ on:
|
|
|
11
11
|
# release:
|
|
12
12
|
# types: [created]
|
|
13
13
|
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write # Required for OIDC
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
14
18
|
jobs:
|
|
15
19
|
# Publish to NPM
|
|
16
20
|
publish-npm:
|
|
@@ -44,6 +48,4 @@ jobs:
|
|
|
44
48
|
|
|
45
49
|
# Publish to npm
|
|
46
50
|
# For scoped package, make it public for free service
|
|
47
|
-
- run: npm publish
|
|
48
|
-
env:
|
|
49
|
-
NODE_AUTH_TOKEN: ${{ secrets.ETSOONpmToken }}
|
|
51
|
+
- run: npm publish
|
package/__tests__/Utils.ts
CHANGED
|
@@ -328,6 +328,16 @@ test("Tests for mergeClasses", () => {
|
|
|
328
328
|
expect(Utils.mergeClasses("a", "", "b ", undefined, "c")).toBe("a b c");
|
|
329
329
|
});
|
|
330
330
|
|
|
331
|
+
test("Tests for formatName", () => {
|
|
332
|
+
expect(Utils.formatName("青岛亿速思维网络科技有限公司", 6)).toBe(
|
|
333
|
+
"青岛亿速思维"
|
|
334
|
+
);
|
|
335
|
+
expect(Utils.formatName("亿速思维(中国)网络科技有限公司", 6)).toBe(
|
|
336
|
+
"亿速思维(中国)"
|
|
337
|
+
);
|
|
338
|
+
expect(Utils.formatName("John Smith", 6)).toBe("John Smith");
|
|
339
|
+
});
|
|
340
|
+
|
|
331
341
|
test("Tests for getNestedValue", () => {
|
|
332
342
|
const obj = { jsonData: { photoSize: [200, 100], supportResizing: true } };
|
|
333
343
|
expect(Utils.getNestedValue(obj, "jsonData.supportResizing")).toBeTruthy();
|
package/lib/cjs/DateUtils.js
CHANGED
|
@@ -74,7 +74,7 @@ var DateUtils;
|
|
|
74
74
|
if (parsed == null)
|
|
75
75
|
return undefined;
|
|
76
76
|
// Default options
|
|
77
|
-
options
|
|
77
|
+
options ??= DateUtils.DayFormat;
|
|
78
78
|
// Default options
|
|
79
79
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
|
|
80
80
|
let opt;
|
package/lib/cjs/DomUtils.js
CHANGED
|
@@ -309,7 +309,7 @@ var DomUtils;
|
|
|
309
309
|
* @returns Result
|
|
310
310
|
*/
|
|
311
311
|
function isWechatClient(data) {
|
|
312
|
-
data
|
|
312
|
+
data ??= parseUserAgent();
|
|
313
313
|
if (!data)
|
|
314
314
|
return false;
|
|
315
315
|
return data.brands.some((item) => item.brand.toLowerCase() === "micromessenger");
|
|
@@ -497,7 +497,7 @@ var DomUtils;
|
|
|
497
497
|
* @returns User agent data
|
|
498
498
|
*/
|
|
499
499
|
function parseUserAgent(ua) {
|
|
500
|
-
ua
|
|
500
|
+
ua ??= globalThis.navigator.userAgent;
|
|
501
501
|
if (!ua) {
|
|
502
502
|
return null;
|
|
503
503
|
}
|
|
@@ -583,7 +583,7 @@ var DomUtils;
|
|
|
583
583
|
*/
|
|
584
584
|
function setFocus(name, container) {
|
|
585
585
|
const elementName = typeof name === "string" ? name : Object.keys(name)[0];
|
|
586
|
-
container
|
|
586
|
+
container ??= document.body;
|
|
587
587
|
const element = container.querySelector(`[name="${elementName}"]`);
|
|
588
588
|
if (element != null)
|
|
589
589
|
element.focus();
|
|
@@ -603,7 +603,7 @@ var DomUtils;
|
|
|
603
603
|
const errorPD = Utils_1.Utils.getResult(preventDefault, errorType) ?? true;
|
|
604
604
|
window.onerror = (message, source, lineNo, colNo, error) => {
|
|
605
605
|
// Default source
|
|
606
|
-
source
|
|
606
|
+
source ||= window.location.href;
|
|
607
607
|
let data;
|
|
608
608
|
if (typeof message === "string") {
|
|
609
609
|
data = {
|
package/lib/cjs/NumberUtils.js
CHANGED
|
@@ -43,14 +43,14 @@ var NumberUtils;
|
|
|
43
43
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
|
|
44
44
|
options.style = "currency";
|
|
45
45
|
options.currency = currency;
|
|
46
|
-
options.currencyDisplay
|
|
46
|
+
options.currencyDisplay ??= "narrowSymbol";
|
|
47
47
|
}
|
|
48
48
|
if (isInteger) {
|
|
49
|
-
options.minimumFractionDigits
|
|
50
|
-
options.maximumFractionDigits
|
|
49
|
+
options.minimumFractionDigits ??= 0;
|
|
50
|
+
options.maximumFractionDigits ??= 0;
|
|
51
51
|
}
|
|
52
52
|
else
|
|
53
|
-
options.minimumFractionDigits
|
|
53
|
+
options.minimumFractionDigits ??= 2;
|
|
54
54
|
return format(input, locale, options);
|
|
55
55
|
}
|
|
56
56
|
NumberUtils.formatMoney = formatMoney;
|
package/lib/cjs/StorageUtils.js
CHANGED
|
@@ -4,8 +4,8 @@ exports.StorageUtils = void 0;
|
|
|
4
4
|
const NodeStorage_1 = require("./node/NodeStorage");
|
|
5
5
|
const Utils_1 = require("./Utils");
|
|
6
6
|
// Mock node
|
|
7
|
-
globalThis.localStorage
|
|
8
|
-
globalThis.sessionStorage
|
|
7
|
+
globalThis.localStorage ??= new NodeStorage_1.NodeStorage();
|
|
8
|
+
globalThis.sessionStorage ??= new NodeStorage_1.NodeStorage();
|
|
9
9
|
/**
|
|
10
10
|
* Storage utilities
|
|
11
11
|
* NodeStorage needs data persistance
|
package/lib/cjs/Utils.d.ts
CHANGED
|
@@ -132,6 +132,14 @@ export declare namespace Utils {
|
|
|
132
132
|
export function excludeAsync<T extends {
|
|
133
133
|
[P in D]: IdType;
|
|
134
134
|
}, D extends string = "id">(items: Promise<T[] | undefined>, field: D, ...excludedValues: T[D][]): Promise<T[] | undefined>;
|
|
135
|
+
/**
|
|
136
|
+
* Format name
|
|
137
|
+
* @param name Input name
|
|
138
|
+
* @param maxChars Max chars
|
|
139
|
+
* @param maxParts Max parts (optional)
|
|
140
|
+
* @returns Formatted name
|
|
141
|
+
*/
|
|
142
|
+
export function formatName(name: string, maxChars: number, maxParts?: number): string;
|
|
135
143
|
/**
|
|
136
144
|
* Format inital character to lower case or upper case
|
|
137
145
|
* @param input Input string
|
package/lib/cjs/Utils.js
CHANGED
|
@@ -139,7 +139,7 @@ var Utils;
|
|
|
139
139
|
*/
|
|
140
140
|
function addBlankItem(options, idField, labelField, blankLabel) {
|
|
141
141
|
// Avoid duplicate blank items
|
|
142
|
-
idField
|
|
142
|
+
idField ??= "id";
|
|
143
143
|
if (options.length === 0 || Reflect.get(options[0], idField) !== "") {
|
|
144
144
|
const blankItem = {
|
|
145
145
|
[idField]: "",
|
|
@@ -207,6 +207,63 @@ var Utils;
|
|
|
207
207
|
return exclude(result, field, ...excludedValues);
|
|
208
208
|
}
|
|
209
209
|
Utils.excludeAsync = excludeAsync;
|
|
210
|
+
/**
|
|
211
|
+
* Format name
|
|
212
|
+
* @param name Input name
|
|
213
|
+
* @param maxChars Max chars
|
|
214
|
+
* @param maxParts Max parts (optional)
|
|
215
|
+
* @returns Formatted name
|
|
216
|
+
*/
|
|
217
|
+
function formatName(name, maxChars, maxParts) {
|
|
218
|
+
name = name.trim();
|
|
219
|
+
const parts = name.split(/\s+/);
|
|
220
|
+
const max = maxParts ?? Math.floor(maxChars / 3);
|
|
221
|
+
const effectiveMax = max < 2 ? 2 : max;
|
|
222
|
+
if (parts.length >= effectiveMax) {
|
|
223
|
+
return parts.slice(0, effectiveMax).join(" ");
|
|
224
|
+
}
|
|
225
|
+
else if (name.length > maxChars) {
|
|
226
|
+
let endIndex = maxChars;
|
|
227
|
+
const brackets = {
|
|
228
|
+
"(": ")",
|
|
229
|
+
"(": ")",
|
|
230
|
+
"[": "]"
|
|
231
|
+
};
|
|
232
|
+
// Count unmatched brackets for each type
|
|
233
|
+
for (const [start, end] of Object.entries(brackets)) {
|
|
234
|
+
let count = 0;
|
|
235
|
+
// Count opening and closing brackets in the substring
|
|
236
|
+
for (let i = 0; i < maxChars; i++) {
|
|
237
|
+
if (name[i] === start)
|
|
238
|
+
count++;
|
|
239
|
+
else if (name[i] === end)
|
|
240
|
+
count--;
|
|
241
|
+
}
|
|
242
|
+
if (count > 0) {
|
|
243
|
+
// Find matching end brackets
|
|
244
|
+
for (let i = maxChars; i < name.length && count > 0; i++) {
|
|
245
|
+
if (name[i] === start) {
|
|
246
|
+
count++;
|
|
247
|
+
}
|
|
248
|
+
else if (name[i] === end) {
|
|
249
|
+
count--;
|
|
250
|
+
if (count === 0) {
|
|
251
|
+
endIndex = i + 1;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if (count === 0) {
|
|
256
|
+
return name.substring(0, endIndex);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return name.substring(0, endIndex);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
return name;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
Utils.formatName = formatName;
|
|
210
267
|
/**
|
|
211
268
|
* Format inital character to lower case or upper case
|
|
212
269
|
* @param input Input string
|
|
@@ -578,7 +635,7 @@ var Utils;
|
|
|
578
635
|
Utils.setLabels = (source, labels, reference) => {
|
|
579
636
|
Object.keys(source).forEach((key) => {
|
|
580
637
|
// Reference key
|
|
581
|
-
const labelKey = reference == null ? key : reference[key] ?? key;
|
|
638
|
+
const labelKey = reference == null ? key : (reference[key] ?? key);
|
|
582
639
|
// Label
|
|
583
640
|
const label = labels[labelKey];
|
|
584
641
|
if (label != null) {
|
|
@@ -6,15 +6,14 @@ exports.NodeStorage = void 0;
|
|
|
6
6
|
* Please take care of the persistence with source property
|
|
7
7
|
*/
|
|
8
8
|
class NodeStorage {
|
|
9
|
+
/**
|
|
10
|
+
* Storage source
|
|
11
|
+
*/
|
|
12
|
+
source = [];
|
|
9
13
|
/**
|
|
10
14
|
* Constructor
|
|
11
15
|
*/
|
|
12
|
-
constructor() {
|
|
13
|
-
/**
|
|
14
|
-
* Storage source
|
|
15
|
-
*/
|
|
16
|
-
this.source = [];
|
|
17
|
-
}
|
|
16
|
+
constructor() { }
|
|
18
17
|
/**
|
|
19
18
|
* Returns the number of key/value pairs currently present in the list
|
|
20
19
|
*/
|
|
@@ -5,9 +5,9 @@ exports.MockResizeObserver = void 0;
|
|
|
5
5
|
* Mock implementation of ResizeObserver for testing purposes
|
|
6
6
|
*/
|
|
7
7
|
class MockResizeObserver {
|
|
8
|
+
callbacks = [];
|
|
9
|
+
elements = [];
|
|
8
10
|
constructor(callback) {
|
|
9
|
-
this.callbacks = [];
|
|
10
|
-
this.elements = [];
|
|
11
11
|
this.callbacks.push(callback);
|
|
12
12
|
}
|
|
13
13
|
observe(element) {
|
|
@@ -7,6 +7,9 @@ const Utils_1 = require("../Utils");
|
|
|
7
7
|
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
|
|
8
8
|
*/
|
|
9
9
|
class ContentDisposition {
|
|
10
|
+
type;
|
|
11
|
+
filename;
|
|
12
|
+
name;
|
|
10
13
|
constructor(type, filename, name) {
|
|
11
14
|
this.type = type;
|
|
12
15
|
this.filename = filename;
|
package/lib/cjs/types/EColor.js
CHANGED
|
@@ -21,6 +21,13 @@ exports.EHistoryNavigateEvent = EHistoryNavigateEvent;
|
|
|
21
21
|
* ETSOO Extended abstract history class
|
|
22
22
|
*/
|
|
23
23
|
class EHistory extends EventClass_1.EventClass {
|
|
24
|
+
maxDepth;
|
|
25
|
+
// Index
|
|
26
|
+
_index = -1;
|
|
27
|
+
/**
|
|
28
|
+
* States
|
|
29
|
+
*/
|
|
30
|
+
states = [];
|
|
24
31
|
/**
|
|
25
32
|
* States length
|
|
26
33
|
*/
|
|
@@ -48,12 +55,6 @@ class EHistory extends EventClass_1.EventClass {
|
|
|
48
55
|
constructor(maxDepth = 20) {
|
|
49
56
|
super();
|
|
50
57
|
this.maxDepth = maxDepth;
|
|
51
|
-
// Index
|
|
52
|
-
this._index = -1;
|
|
53
|
-
/**
|
|
54
|
-
* States
|
|
55
|
-
*/
|
|
56
|
-
this.states = [];
|
|
57
58
|
}
|
|
58
59
|
/**
|
|
59
60
|
* Back to the previous state
|
|
@@ -7,12 +7,17 @@ exports.EventClass = exports.EventBase = void 0;
|
|
|
7
7
|
* D for data
|
|
8
8
|
*/
|
|
9
9
|
class EventBase {
|
|
10
|
+
target;
|
|
11
|
+
type;
|
|
12
|
+
data;
|
|
13
|
+
_propagationStopped = false;
|
|
10
14
|
/**
|
|
11
15
|
* stopImmediatePropagation called
|
|
12
16
|
*/
|
|
13
17
|
get propagationStopped() {
|
|
14
18
|
return this._propagationStopped;
|
|
15
19
|
}
|
|
20
|
+
_timeStamp;
|
|
16
21
|
/**
|
|
17
22
|
* Time stamp
|
|
18
23
|
*/
|
|
@@ -27,7 +32,6 @@ class EventBase {
|
|
|
27
32
|
this.target = target;
|
|
28
33
|
this.type = type;
|
|
29
34
|
this.data = data;
|
|
30
|
-
this._propagationStopped = false;
|
|
31
35
|
this._timeStamp = Date.now();
|
|
32
36
|
}
|
|
33
37
|
/**
|
|
@@ -44,10 +48,8 @@ exports.EventBase = EventBase;
|
|
|
44
48
|
* D for data
|
|
45
49
|
*/
|
|
46
50
|
class EventClass {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.listeners = new Map();
|
|
50
|
-
}
|
|
51
|
+
// Listeners
|
|
52
|
+
listeners = new Map();
|
|
51
53
|
/**
|
|
52
54
|
* Has specific type and callback events
|
|
53
55
|
* @param type Type
|
package/lib/mjs/DateUtils.js
CHANGED
|
@@ -71,7 +71,7 @@ export var DateUtils;
|
|
|
71
71
|
if (parsed == null)
|
|
72
72
|
return undefined;
|
|
73
73
|
// Default options
|
|
74
|
-
options
|
|
74
|
+
options ??= DateUtils.DayFormat;
|
|
75
75
|
// Default options
|
|
76
76
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat
|
|
77
77
|
let opt;
|
package/lib/mjs/DomUtils.js
CHANGED
|
@@ -306,7 +306,7 @@ export var DomUtils;
|
|
|
306
306
|
* @returns Result
|
|
307
307
|
*/
|
|
308
308
|
function isWechatClient(data) {
|
|
309
|
-
data
|
|
309
|
+
data ??= parseUserAgent();
|
|
310
310
|
if (!data)
|
|
311
311
|
return false;
|
|
312
312
|
return data.brands.some((item) => item.brand.toLowerCase() === "micromessenger");
|
|
@@ -494,7 +494,7 @@ export var DomUtils;
|
|
|
494
494
|
* @returns User agent data
|
|
495
495
|
*/
|
|
496
496
|
function parseUserAgent(ua) {
|
|
497
|
-
ua
|
|
497
|
+
ua ??= globalThis.navigator.userAgent;
|
|
498
498
|
if (!ua) {
|
|
499
499
|
return null;
|
|
500
500
|
}
|
|
@@ -580,7 +580,7 @@ export var DomUtils;
|
|
|
580
580
|
*/
|
|
581
581
|
function setFocus(name, container) {
|
|
582
582
|
const elementName = typeof name === "string" ? name : Object.keys(name)[0];
|
|
583
|
-
container
|
|
583
|
+
container ??= document.body;
|
|
584
584
|
const element = container.querySelector(`[name="${elementName}"]`);
|
|
585
585
|
if (element != null)
|
|
586
586
|
element.focus();
|
|
@@ -600,7 +600,7 @@ export var DomUtils;
|
|
|
600
600
|
const errorPD = Utils.getResult(preventDefault, errorType) ?? true;
|
|
601
601
|
window.onerror = (message, source, lineNo, colNo, error) => {
|
|
602
602
|
// Default source
|
|
603
|
-
source
|
|
603
|
+
source ||= window.location.href;
|
|
604
604
|
let data;
|
|
605
605
|
if (typeof message === "string") {
|
|
606
606
|
data = {
|
package/lib/mjs/NumberUtils.js
CHANGED
|
@@ -40,14 +40,14 @@ export var NumberUtils;
|
|
|
40
40
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat
|
|
41
41
|
options.style = "currency";
|
|
42
42
|
options.currency = currency;
|
|
43
|
-
options.currencyDisplay
|
|
43
|
+
options.currencyDisplay ??= "narrowSymbol";
|
|
44
44
|
}
|
|
45
45
|
if (isInteger) {
|
|
46
|
-
options.minimumFractionDigits
|
|
47
|
-
options.maximumFractionDigits
|
|
46
|
+
options.minimumFractionDigits ??= 0;
|
|
47
|
+
options.maximumFractionDigits ??= 0;
|
|
48
48
|
}
|
|
49
49
|
else
|
|
50
|
-
options.minimumFractionDigits
|
|
50
|
+
options.minimumFractionDigits ??= 2;
|
|
51
51
|
return format(input, locale, options);
|
|
52
52
|
}
|
|
53
53
|
NumberUtils.formatMoney = formatMoney;
|
package/lib/mjs/StorageUtils.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { NodeStorage } from "./node/NodeStorage";
|
|
2
2
|
import { Utils } from "./Utils";
|
|
3
3
|
// Mock node
|
|
4
|
-
globalThis.localStorage
|
|
5
|
-
globalThis.sessionStorage
|
|
4
|
+
globalThis.localStorage ??= new NodeStorage();
|
|
5
|
+
globalThis.sessionStorage ??= new NodeStorage();
|
|
6
6
|
/**
|
|
7
7
|
* Storage utilities
|
|
8
8
|
* NodeStorage needs data persistance
|
package/lib/mjs/Utils.d.ts
CHANGED
|
@@ -132,6 +132,14 @@ export declare namespace Utils {
|
|
|
132
132
|
export function excludeAsync<T extends {
|
|
133
133
|
[P in D]: IdType;
|
|
134
134
|
}, D extends string = "id">(items: Promise<T[] | undefined>, field: D, ...excludedValues: T[D][]): Promise<T[] | undefined>;
|
|
135
|
+
/**
|
|
136
|
+
* Format name
|
|
137
|
+
* @param name Input name
|
|
138
|
+
* @param maxChars Max chars
|
|
139
|
+
* @param maxParts Max parts (optional)
|
|
140
|
+
* @returns Formatted name
|
|
141
|
+
*/
|
|
142
|
+
export function formatName(name: string, maxChars: number, maxParts?: number): string;
|
|
135
143
|
/**
|
|
136
144
|
* Format inital character to lower case or upper case
|
|
137
145
|
* @param input Input string
|
package/lib/mjs/Utils.js
CHANGED
|
@@ -136,7 +136,7 @@ export var Utils;
|
|
|
136
136
|
*/
|
|
137
137
|
function addBlankItem(options, idField, labelField, blankLabel) {
|
|
138
138
|
// Avoid duplicate blank items
|
|
139
|
-
idField
|
|
139
|
+
idField ??= "id";
|
|
140
140
|
if (options.length === 0 || Reflect.get(options[0], idField) !== "") {
|
|
141
141
|
const blankItem = {
|
|
142
142
|
[idField]: "",
|
|
@@ -204,6 +204,63 @@ export var Utils;
|
|
|
204
204
|
return exclude(result, field, ...excludedValues);
|
|
205
205
|
}
|
|
206
206
|
Utils.excludeAsync = excludeAsync;
|
|
207
|
+
/**
|
|
208
|
+
* Format name
|
|
209
|
+
* @param name Input name
|
|
210
|
+
* @param maxChars Max chars
|
|
211
|
+
* @param maxParts Max parts (optional)
|
|
212
|
+
* @returns Formatted name
|
|
213
|
+
*/
|
|
214
|
+
function formatName(name, maxChars, maxParts) {
|
|
215
|
+
name = name.trim();
|
|
216
|
+
const parts = name.split(/\s+/);
|
|
217
|
+
const max = maxParts ?? Math.floor(maxChars / 3);
|
|
218
|
+
const effectiveMax = max < 2 ? 2 : max;
|
|
219
|
+
if (parts.length >= effectiveMax) {
|
|
220
|
+
return parts.slice(0, effectiveMax).join(" ");
|
|
221
|
+
}
|
|
222
|
+
else if (name.length > maxChars) {
|
|
223
|
+
let endIndex = maxChars;
|
|
224
|
+
const brackets = {
|
|
225
|
+
"(": ")",
|
|
226
|
+
"(": ")",
|
|
227
|
+
"[": "]"
|
|
228
|
+
};
|
|
229
|
+
// Count unmatched brackets for each type
|
|
230
|
+
for (const [start, end] of Object.entries(brackets)) {
|
|
231
|
+
let count = 0;
|
|
232
|
+
// Count opening and closing brackets in the substring
|
|
233
|
+
for (let i = 0; i < maxChars; i++) {
|
|
234
|
+
if (name[i] === start)
|
|
235
|
+
count++;
|
|
236
|
+
else if (name[i] === end)
|
|
237
|
+
count--;
|
|
238
|
+
}
|
|
239
|
+
if (count > 0) {
|
|
240
|
+
// Find matching end brackets
|
|
241
|
+
for (let i = maxChars; i < name.length && count > 0; i++) {
|
|
242
|
+
if (name[i] === start) {
|
|
243
|
+
count++;
|
|
244
|
+
}
|
|
245
|
+
else if (name[i] === end) {
|
|
246
|
+
count--;
|
|
247
|
+
if (count === 0) {
|
|
248
|
+
endIndex = i + 1;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (count === 0) {
|
|
253
|
+
return name.substring(0, endIndex);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return name.substring(0, endIndex);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
return name;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
Utils.formatName = formatName;
|
|
207
264
|
/**
|
|
208
265
|
* Format inital character to lower case or upper case
|
|
209
266
|
* @param input Input string
|
|
@@ -575,7 +632,7 @@ export var Utils;
|
|
|
575
632
|
Utils.setLabels = (source, labels, reference) => {
|
|
576
633
|
Object.keys(source).forEach((key) => {
|
|
577
634
|
// Reference key
|
|
578
|
-
const labelKey = reference == null ? key : reference[key] ?? key;
|
|
635
|
+
const labelKey = reference == null ? key : (reference[key] ?? key);
|
|
579
636
|
// Label
|
|
580
637
|
const label = labels[labelKey];
|
|
581
638
|
if (label != null) {
|
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
* Please take care of the persistence with source property
|
|
4
4
|
*/
|
|
5
5
|
export class NodeStorage {
|
|
6
|
+
/**
|
|
7
|
+
* Storage source
|
|
8
|
+
*/
|
|
9
|
+
source = [];
|
|
6
10
|
/**
|
|
7
11
|
* Constructor
|
|
8
12
|
*/
|
|
9
|
-
constructor() {
|
|
10
|
-
/**
|
|
11
|
-
* Storage source
|
|
12
|
-
*/
|
|
13
|
-
this.source = [];
|
|
14
|
-
}
|
|
13
|
+
constructor() { }
|
|
15
14
|
/**
|
|
16
15
|
* Returns the number of key/value pairs currently present in the list
|
|
17
16
|
*/
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Mock implementation of ResizeObserver for testing purposes
|
|
3
3
|
*/
|
|
4
4
|
export class MockResizeObserver {
|
|
5
|
+
callbacks = [];
|
|
6
|
+
elements = [];
|
|
5
7
|
constructor(callback) {
|
|
6
|
-
this.callbacks = [];
|
|
7
|
-
this.elements = [];
|
|
8
8
|
this.callbacks.push(callback);
|
|
9
9
|
}
|
|
10
10
|
observe(element) {
|
|
@@ -4,6 +4,9 @@ import { Utils } from "../Utils";
|
|
|
4
4
|
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
|
|
5
5
|
*/
|
|
6
6
|
export class ContentDisposition {
|
|
7
|
+
type;
|
|
8
|
+
filename;
|
|
9
|
+
name;
|
|
7
10
|
constructor(type, filename, name) {
|
|
8
11
|
this.type = type;
|
|
9
12
|
this.filename = filename;
|
package/lib/mjs/types/EColor.js
CHANGED
|
@@ -16,6 +16,13 @@ export class EHistoryNavigateEvent extends EventBase {
|
|
|
16
16
|
* ETSOO Extended abstract history class
|
|
17
17
|
*/
|
|
18
18
|
export class EHistory extends EventClass {
|
|
19
|
+
maxDepth;
|
|
20
|
+
// Index
|
|
21
|
+
_index = -1;
|
|
22
|
+
/**
|
|
23
|
+
* States
|
|
24
|
+
*/
|
|
25
|
+
states = [];
|
|
19
26
|
/**
|
|
20
27
|
* States length
|
|
21
28
|
*/
|
|
@@ -43,12 +50,6 @@ export class EHistory extends EventClass {
|
|
|
43
50
|
constructor(maxDepth = 20) {
|
|
44
51
|
super();
|
|
45
52
|
this.maxDepth = maxDepth;
|
|
46
|
-
// Index
|
|
47
|
-
this._index = -1;
|
|
48
|
-
/**
|
|
49
|
-
* States
|
|
50
|
-
*/
|
|
51
|
-
this.states = [];
|
|
52
53
|
}
|
|
53
54
|
/**
|
|
54
55
|
* Back to the previous state
|
|
@@ -4,12 +4,17 @@
|
|
|
4
4
|
* D for data
|
|
5
5
|
*/
|
|
6
6
|
export class EventBase {
|
|
7
|
+
target;
|
|
8
|
+
type;
|
|
9
|
+
data;
|
|
10
|
+
_propagationStopped = false;
|
|
7
11
|
/**
|
|
8
12
|
* stopImmediatePropagation called
|
|
9
13
|
*/
|
|
10
14
|
get propagationStopped() {
|
|
11
15
|
return this._propagationStopped;
|
|
12
16
|
}
|
|
17
|
+
_timeStamp;
|
|
13
18
|
/**
|
|
14
19
|
* Time stamp
|
|
15
20
|
*/
|
|
@@ -24,7 +29,6 @@ export class EventBase {
|
|
|
24
29
|
this.target = target;
|
|
25
30
|
this.type = type;
|
|
26
31
|
this.data = data;
|
|
27
|
-
this._propagationStopped = false;
|
|
28
32
|
this._timeStamp = Date.now();
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
@@ -40,10 +44,8 @@ export class EventBase {
|
|
|
40
44
|
* D for data
|
|
41
45
|
*/
|
|
42
46
|
export class EventClass {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
this.listeners = new Map();
|
|
46
|
-
}
|
|
47
|
+
// Listeners
|
|
48
|
+
listeners = new Map();
|
|
47
49
|
/**
|
|
48
50
|
* Has specific type and callback events
|
|
49
51
|
* @param type Type
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/shared",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.82",
|
|
4
4
|
"description": "TypeScript shared utilities and functions",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/ETSOO/Shared#readme",
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^
|
|
40
|
-
"@vitejs/plugin-react": "^
|
|
41
|
-
"jsdom": "^
|
|
42
|
-
"typescript": "^
|
|
43
|
-
"vitest": "^4.
|
|
39
|
+
"@types/node": "^25.5.2",
|
|
40
|
+
"@vitejs/plugin-react": "^6.0.1",
|
|
41
|
+
"jsdom": "^29.0.1",
|
|
42
|
+
"typescript": "^6.0.2",
|
|
43
|
+
"vitest": "^4.1.2"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/Utils.ts
CHANGED
|
@@ -355,6 +355,70 @@ export namespace Utils {
|
|
|
355
355
|
return exclude(result, field, ...excludedValues);
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
+
/**
|
|
359
|
+
* Format name
|
|
360
|
+
* @param name Input name
|
|
361
|
+
* @param maxChars Max chars
|
|
362
|
+
* @param maxParts Max parts (optional)
|
|
363
|
+
* @returns Formatted name
|
|
364
|
+
*/
|
|
365
|
+
export function formatName(
|
|
366
|
+
name: string,
|
|
367
|
+
maxChars: number,
|
|
368
|
+
maxParts?: number
|
|
369
|
+
): string {
|
|
370
|
+
name = name.trim();
|
|
371
|
+
|
|
372
|
+
const parts = name.split(/\s+/);
|
|
373
|
+
|
|
374
|
+
const max = maxParts ?? Math.floor(maxChars / 3);
|
|
375
|
+
const effectiveMax = max < 2 ? 2 : max;
|
|
376
|
+
|
|
377
|
+
if (parts.length >= effectiveMax) {
|
|
378
|
+
return parts.slice(0, effectiveMax).join(" ");
|
|
379
|
+
} else if (name.length > maxChars) {
|
|
380
|
+
let endIndex = maxChars;
|
|
381
|
+
const brackets: Record<string, string> = {
|
|
382
|
+
"(": ")",
|
|
383
|
+
"(": ")",
|
|
384
|
+
"[": "]"
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// Count unmatched brackets for each type
|
|
388
|
+
for (const [start, end] of Object.entries(brackets)) {
|
|
389
|
+
let count = 0;
|
|
390
|
+
|
|
391
|
+
// Count opening and closing brackets in the substring
|
|
392
|
+
for (let i = 0; i < maxChars; i++) {
|
|
393
|
+
if (name[i] === start) count++;
|
|
394
|
+
else if (name[i] === end) count--;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (count > 0) {
|
|
398
|
+
// Find matching end brackets
|
|
399
|
+
for (let i = maxChars; i < name.length && count > 0; i++) {
|
|
400
|
+
if (name[i] === start) {
|
|
401
|
+
count++;
|
|
402
|
+
} else if (name[i] === end) {
|
|
403
|
+
count--;
|
|
404
|
+
if (count === 0) {
|
|
405
|
+
endIndex = i + 1;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (count === 0) {
|
|
411
|
+
return name.substring(0, endIndex);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return name.substring(0, endIndex);
|
|
417
|
+
} else {
|
|
418
|
+
return name;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
358
422
|
/**
|
|
359
423
|
* Format inital character to lower case or upper case
|
|
360
424
|
* @param input Input string
|
|
@@ -823,7 +887,7 @@ export namespace Utils {
|
|
|
823
887
|
) => {
|
|
824
888
|
Object.keys(source).forEach((key) => {
|
|
825
889
|
// Reference key
|
|
826
|
-
const labelKey = reference == null ? key : reference[key] ?? key;
|
|
890
|
+
const labelKey = reference == null ? key : (reference[key] ?? key);
|
|
827
891
|
|
|
828
892
|
// Label
|
|
829
893
|
const label = labels[labelKey];
|
|
@@ -963,8 +1027,8 @@ export namespace Utils {
|
|
|
963
1027
|
index1 === -1
|
|
964
1028
|
? index2
|
|
965
1029
|
: index2 === -1
|
|
966
|
-
|
|
967
|
-
|
|
1030
|
+
? index1
|
|
1031
|
+
: Math.min(index1, index2);
|
|
968
1032
|
root = path.substring(0, index + 1);
|
|
969
1033
|
dir = path.substring(0, lastIndex);
|
|
970
1034
|
if (dir === "") dir = root;
|
package/src/storage/IStorage.ts
CHANGED
|
@@ -141,7 +141,7 @@ export class WindowStorage implements IStorage {
|
|
|
141
141
|
* @param key Key name
|
|
142
142
|
* @param data Data, null for removal
|
|
143
143
|
*/
|
|
144
|
-
setPersistedData(key: string, data:
|
|
144
|
+
setPersistedData<T>(key: string, data: T) {
|
|
145
145
|
StorageUtils.setLocalData(key, data);
|
|
146
146
|
}
|
|
147
147
|
}
|
package/tsconfig.cjs.json
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
|
4
|
-
"target": "
|
|
4
|
+
"target": "ES2025",
|
|
5
5
|
"module": "NodeNext",
|
|
6
6
|
"moduleResolution": "NodeNext",
|
|
7
7
|
"isolatedModules": true,
|
|
8
|
+
"rootDir": "./src",
|
|
8
9
|
"outDir": "./lib/cjs",
|
|
9
10
|
"noEmit": false,
|
|
10
11
|
"declaration": true,
|
|
11
12
|
"strict": true,
|
|
12
13
|
"esModuleInterop": true,
|
|
14
|
+
"types": ["node"],
|
|
13
15
|
"skipLibCheck": true,
|
|
14
16
|
"forceConsistentCasingInFileNames": true,
|
|
15
17
|
"lib": ["dom", "dom.iterable", "ESNext"]
|
package/tsconfig.json
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
|
4
|
-
"target": "
|
|
5
|
-
"module": "
|
|
4
|
+
"target": "ES2025",
|
|
5
|
+
"module": "ESNext",
|
|
6
6
|
"moduleResolution": "bundler",
|
|
7
7
|
"isolatedModules": true,
|
|
8
|
+
"rootDir": "./src",
|
|
8
9
|
"outDir": "./lib/mjs",
|
|
9
10
|
"noEmit": false,
|
|
10
11
|
"declaration": true,
|
|
11
12
|
"strict": true,
|
|
12
13
|
"esModuleInterop": true,
|
|
14
|
+
"types": ["node"],
|
|
13
15
|
"skipLibCheck": true,
|
|
14
16
|
"forceConsistentCasingInFileNames": true,
|
|
15
17
|
"lib": ["dom", "dom.iterable", "esnext"]
|