@simplysm/core-browser 13.0.78 → 13.0.81
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/dist/extensions/element-ext.js +5 -5
- package/dist/extensions/element-ext.js.map +1 -1
- package/dist/utils/fetch.d.ts.map +1 -1
- package/dist/utils/fetch.js +8 -15
- package/dist/utils/fetch.js.map +2 -2
- package/dist/utils/file-dialog.d.ts.map +1 -1
- package/dist/utils/file-dialog.js +3 -0
- package/dist/utils/file-dialog.js.map +1 -1
- package/package.json +3 -2
- package/src/extensions/element-ext.ts +6 -6
- package/src/utils/fetch.ts +3 -11
- package/src/utils/file-dialog.ts +3 -0
- package/README.md +0 -606
|
@@ -79,7 +79,7 @@ async function getBounds(els, timeout = 5e3) {
|
|
|
79
79
|
if (indexMap.size === 0) {
|
|
80
80
|
return [];
|
|
81
81
|
}
|
|
82
|
-
const
|
|
82
|
+
const remaining = new Set(indexMap.keys());
|
|
83
83
|
let observer;
|
|
84
84
|
try {
|
|
85
85
|
return await Promise.race([
|
|
@@ -88,8 +88,8 @@ async function getBounds(els, timeout = 5e3) {
|
|
|
88
88
|
observer = new IntersectionObserver((entries) => {
|
|
89
89
|
for (const entry of entries) {
|
|
90
90
|
const target = entry.target;
|
|
91
|
-
if (
|
|
92
|
-
|
|
91
|
+
if (remaining.has(target)) {
|
|
92
|
+
remaining.delete(target);
|
|
93
93
|
results.push({
|
|
94
94
|
target,
|
|
95
95
|
top: entry.boundingClientRect.top,
|
|
@@ -99,10 +99,10 @@ async function getBounds(els, timeout = 5e3) {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
|
-
if (
|
|
102
|
+
if (remaining.size === 0) {
|
|
103
103
|
observer == null ? void 0 : observer.disconnect();
|
|
104
104
|
resolve(
|
|
105
|
-
results.sort((a, b) =>
|
|
105
|
+
results.sort((a, b) => indexMap.get(a.target) - indexMap.get(b.target))
|
|
106
106
|
);
|
|
107
107
|
}
|
|
108
108
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/extensions/element-ext.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAoF7B,QAAQ,UAAU,UAAU,SAAyC,UAAyB;AAC5F,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,YAAY,GAAI,QAAO,CAAC;AAC5B,SAAO,MAAM,KAAK,KAAK,iBAAsB,OAAO,CAAC;AACvD;AAEA,QAAQ,UAAU,YAAY,SAC5B,UACiB;AACjB,QAAM,UAAU,SAAS,KAAK;AAC9B,MAAI,YAAY,GAAI,QAAO;AAC3B,SAAO,KAAK,cAAmB,OAAO,KAAK;AAC7C;AAEA,QAAQ,UAAU,eAAe,SAA+B,OAAiB;AAC/E,SAAO,KAAK,aAAa,OAAO,KAAK,iBAAiB;AACxD;AAEA,QAAQ,UAAU,aAAa,WAAuB;AACpD,QAAM,SAAoB,CAAC;AAC3B,MAAI,SAAS,KAAK;AAClB,SAAO,WAAW,QAAQ,kBAAkB,SAAS;AACnD,WAAO,KAAK,MAAM;AAClB,aAAS,OAAO;AAAA,EAClB;AACA,SAAO;AACT;AAEA,QAAQ,UAAU,sBAAsB,WAAqC;AAC3E,MAAI,WAAW,KAAK;AACpB,SAAO,aAAa,MAAM;AACxB,QAAI,YAAY,QAAQ,GAAG;AACzB,aAAO;AAAA,IACT;AACA,eAAW,SAAS;AAAA,EACtB;AACA,SAAO;AACT;AAEA,QAAQ,UAAU,0BAA0B,WAAqC;AAC/E,QAAM,SAAS,SAAS,iBAAiB,MAAM,WAAW,YAAY;AACtE,MAAI,OAAO,OAAO,SAAS;AAC3B,SAAO,SAAS,MAAM;AACpB,QAAI,gBAAgB,eAAe,YAAY,IAAI,GAAG;AACpD,aAAO;AAAA,IACT;AACA,WAAO,OAAO,SAAS;AAAA,EACzB;AACA,SAAO;AACT;AAEA,QAAQ,UAAU,kBAAkB,WAAqB;AACvD,SAAO,CAAC,YAAY,YAAY,SAAS,QAAQ,EAAE,SAAS,iBAAiB,IAAI,EAAE,QAAQ;AAC7F;AAEA,QAAQ,UAAU,YAAY,WAAqB;AACjD,QAAM,QAAQ,iBAAiB,IAAI;AACnC,SAAO,KAAK,eAAe,EAAE,SAAS,KAAK,MAAM,eAAe,YAAY,MAAM,YAAY;AAChG;AAWO,SAAS,YAAY,OAA6B;AACvD,QAAM,gBAAgB,MAAM;AAC5B,QAAM,SAAS,MAAM;AACrB,MAAI,iBAAiB,QAAQ,EAAE,kBAAkB,SAAU;AAE3D,QAAM,eAAe,OAAO;AAAA,IAC1B;AAAA,EACF;AACA,MAAI,gBAAgB,MAAM;AACxB,kBAAc,QAAQ,cAAc,aAAa,KAAK;AACtD,UAAM,eAAe;AAAA,EACvB;AACF;AAWO,SAAS,eAAe,OAA6B;AAC1D,QAAM,gBAAgB,MAAM;AAC5B,QAAM,SAAS,MAAM;AACrB,MAAI,iBAAiB,QAAQ,EAAE,kBAAkB,SAAU;AAE3D,QAAM,cAAc,cAAc,QAAQ,YAAY;AAEtD,QAAM,eAAe,OAAO,UAAkD,iBAAiB;AAC/F,MAAI,iBAAiB,QAAW;AAC9B,iBAAa,QAAQ;AACrB,iBAAa,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAK,CAAC,CAAC;AAChE,UAAM,eAAe;AAAA,EACvB;AACF;AASA,eAAsB,UAAU,KAAgB,UAAkB,KAAgC;AAEhG,QAAM,WAAW,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAU,CAAC;AAC7D,MAAI,SAAS,SAAS,GAAG;AACvB,WAAO,CAAC;AAAA,EACV;AAGA,QAAM,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["..\\..\\src\\utils\\fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["..\\..\\src\\utils\\fetch.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAA;CAAE,GAC9D,OAAO,CAAC,UAAU,CAAC,CA4CrB"}
|
package/dist/utils/fetch.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { bytes } from "@simplysm/core-common";
|
|
1
2
|
async function fetchUrlBytes(url, options) {
|
|
2
3
|
var _a, _b;
|
|
3
4
|
const response = await fetch(url);
|
|
@@ -11,32 +12,24 @@ async function fetchUrlBytes(url, options) {
|
|
|
11
12
|
}
|
|
12
13
|
try {
|
|
13
14
|
if (contentLength > 0) {
|
|
14
|
-
const
|
|
15
|
-
let
|
|
15
|
+
const result = new Uint8Array(contentLength);
|
|
16
|
+
let receivedLength = 0;
|
|
16
17
|
while (true) {
|
|
17
18
|
const { done, value } = await reader.read();
|
|
18
19
|
if (done) break;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
(_b = options == null ? void 0 : options.onProgress) == null ? void 0 : _b.call(options, { receivedLength
|
|
20
|
+
result.set(value, receivedLength);
|
|
21
|
+
receivedLength += value.length;
|
|
22
|
+
(_b = options == null ? void 0 : options.onProgress) == null ? void 0 : _b.call(options, { receivedLength, contentLength });
|
|
22
23
|
}
|
|
23
|
-
return
|
|
24
|
+
return result;
|
|
24
25
|
}
|
|
25
26
|
const chunks = [];
|
|
26
|
-
let receivedLength = 0;
|
|
27
27
|
while (true) {
|
|
28
28
|
const { done, value } = await reader.read();
|
|
29
29
|
if (done) break;
|
|
30
30
|
chunks.push(value);
|
|
31
|
-
receivedLength += value.length;
|
|
32
31
|
}
|
|
33
|
-
|
|
34
|
-
let position = 0;
|
|
35
|
-
for (const chunk of chunks) {
|
|
36
|
-
result.set(chunk, position);
|
|
37
|
-
position += chunk.length;
|
|
38
|
-
}
|
|
39
|
-
return result;
|
|
32
|
+
return bytes.concat(chunks);
|
|
40
33
|
} finally {
|
|
41
34
|
reader.releaseLock();
|
|
42
35
|
}
|
package/dist/utils/fetch.js.map
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/fetch.ts"],
|
|
4
|
-
"mappings": "
|
|
5
|
-
"names": [
|
|
4
|
+
"mappings": "AAAA,SAAS,aAAa;AAUtB,eAAsB,cACpB,KACA,SACqB;AAbvB;AAcE,QAAM,WAAW,MAAM,MAAM,GAAG;AAChC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,EAC9E;AAEA,QAAM,gBAAgB,OAAO,SAAS,QAAQ,IAAI,gBAAgB,KAAK,CAAC;AACxE,QAAM,UAAS,cAAS,SAAT,mBAAe;AAC9B,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AAEA,MAAI;AAEF,QAAI,gBAAgB,GAAG;AACrB,YAAM,SAAS,IAAI,WAAW,aAAa;AAC3C,UAAI,iBAAiB;AAErB,aAAO,MAAM;AACX,cAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,YAAI,KAAM;AAEV,eAAO,IAAI,OAAO,cAAc;AAChC,0BAAkB,MAAM;AACxB,iDAAS,eAAT,iCAAsB,EAAE,gBAAgB,cAAc;AAAA,MACxD;AAEA,aAAO;AAAA,IACT;AAGA,UAAM,SAAuB,CAAC;AAE9B,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AAEV,aAAO,KAAK,KAAK;AAAA,IACnB;AAEA,WAAO,MAAM,OAAO,MAAM;AAAA,EAC5B,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AACF;",
|
|
5
|
+
"names": []
|
|
6
6
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-dialog.d.ts","sourceRoot":"","sources":["..\\..\\src\\utils\\file-dialog.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"file-dialog.d.ts","sourceRoot":"","sources":["..\\..\\src\\utils\\file-dialog.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,SAAS,CAAC,CAgB9B"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/file-dialog.ts"],
|
|
4
|
-
"mappings": "AAGO,SAAS,eAAe,SAGC;AAC9B,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,OAAO;AACb,UAAM,YAAW,mCAAS,aAAY;AACtC,SAAI,mCAAS,WAAU,MAAM;AAC3B,YAAM,SAAS,QAAQ;AAAA,IACzB;AACA,UAAM,WAAW,MAAM;AACrB,cAAQ,MAAM,SAAS,QAAQ,MAAM,MAAM,SAAS,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,MAAS;AAAA,IACtF;AACA,UAAM,MAAM;AAAA,EACd,CAAC;AACH;",
|
|
4
|
+
"mappings": "AAGO,SAAS,eAAe,SAGC;AAC9B,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,OAAO;AACb,UAAM,YAAW,mCAAS,aAAY;AACtC,SAAI,mCAAS,WAAU,MAAM;AAC3B,YAAM,SAAS,QAAQ;AAAA,IACzB;AACA,UAAM,WAAW,MAAM;AACrB,cAAQ,MAAM,SAAS,QAAQ,MAAM,MAAM,SAAS,IAAI,CAAC,GAAG,MAAM,KAAK,IAAI,MAAS;AAAA,IACtF;AACA,UAAM,iBAAiB,UAAU,MAAM;AACrC,cAAQ,MAAS;AAAA,IACnB,CAAC;AACD,UAAM,MAAM;AAAA,EACd,CAAC;AACH;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/core-browser",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.81",
|
|
4
4
|
"description": "Simplysm package - Core module (browser)",
|
|
5
5
|
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
|
+
"docs",
|
|
17
18
|
"src",
|
|
18
19
|
"tests"
|
|
19
20
|
],
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
],
|
|
24
25
|
"dependencies": {
|
|
25
26
|
"tabbable": "^6.4.0",
|
|
26
|
-
"@simplysm/core-common": "13.0.
|
|
27
|
+
"@simplysm/core-common": "13.0.81"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"happy-dom": "^20.8.3"
|
|
@@ -204,8 +204,8 @@ export async function getBounds(els: Element[], timeout: number = 5000): Promise
|
|
|
204
204
|
return [];
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
//
|
|
208
|
-
const
|
|
207
|
+
// Set to track remaining elements
|
|
208
|
+
const remaining = new Set(indexMap.keys());
|
|
209
209
|
|
|
210
210
|
let observer: IntersectionObserver | undefined;
|
|
211
211
|
|
|
@@ -217,8 +217,8 @@ export async function getBounds(els: Element[], timeout: number = 5000): Promise
|
|
|
217
217
|
observer = new IntersectionObserver((entries) => {
|
|
218
218
|
for (const entry of entries) {
|
|
219
219
|
const target = entry.target;
|
|
220
|
-
if (
|
|
221
|
-
|
|
220
|
+
if (remaining.has(target)) {
|
|
221
|
+
remaining.delete(target);
|
|
222
222
|
results.push({
|
|
223
223
|
target,
|
|
224
224
|
top: entry.boundingClientRect.top,
|
|
@@ -229,11 +229,11 @@ export async function getBounds(els: Element[], timeout: number = 5000): Promise
|
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
if (
|
|
232
|
+
if (remaining.size === 0) {
|
|
233
233
|
observer?.disconnect();
|
|
234
234
|
// Sort in input order
|
|
235
235
|
resolve(
|
|
236
|
-
results.sort((a, b) =>
|
|
236
|
+
results.sort((a, b) => indexMap.get(a.target)! - indexMap.get(b.target)!),
|
|
237
237
|
);
|
|
238
238
|
}
|
|
239
239
|
});
|
package/src/utils/fetch.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { bytes } from "@simplysm/core-common";
|
|
2
|
+
|
|
1
3
|
export interface DownloadProgress {
|
|
2
4
|
receivedLength: number;
|
|
3
5
|
contentLength: number;
|
|
@@ -41,25 +43,15 @@ export async function fetchUrlBytes(
|
|
|
41
43
|
|
|
42
44
|
// If Content-Length is unknown, collect chunks then merge (chunked encoding)
|
|
43
45
|
const chunks: Uint8Array[] = [];
|
|
44
|
-
let receivedLength = 0;
|
|
45
46
|
|
|
46
47
|
while (true) {
|
|
47
48
|
const { done, value } = await reader.read();
|
|
48
49
|
if (done) break;
|
|
49
50
|
|
|
50
51
|
chunks.push(value);
|
|
51
|
-
receivedLength += value.length;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Merge chunks
|
|
55
|
-
const result = new Uint8Array(receivedLength);
|
|
56
|
-
let position = 0;
|
|
57
|
-
for (const chunk of chunks) {
|
|
58
|
-
result.set(chunk, position);
|
|
59
|
-
position += chunk.length;
|
|
60
52
|
}
|
|
61
53
|
|
|
62
|
-
return
|
|
54
|
+
return bytes.concat(chunks);
|
|
63
55
|
} finally {
|
|
64
56
|
reader.releaseLock();
|
|
65
57
|
}
|
package/src/utils/file-dialog.ts
CHANGED
|
@@ -15,6 +15,9 @@ export function openFileDialog(options?: {
|
|
|
15
15
|
input.onchange = () => {
|
|
16
16
|
resolve(input.files != null && input.files.length > 0 ? [...input.files] : undefined);
|
|
17
17
|
};
|
|
18
|
+
input.addEventListener("cancel", () => {
|
|
19
|
+
resolve(undefined);
|
|
20
|
+
});
|
|
18
21
|
input.click();
|
|
19
22
|
});
|
|
20
23
|
}
|
package/README.md
DELETED
|
@@ -1,606 +0,0 @@
|
|
|
1
|
-
# @simplysm/core-browser
|
|
2
|
-
|
|
3
|
-
Simplysm package - Core module (browser)
|
|
4
|
-
|
|
5
|
-
Browser-only utilities including DOM element extensions, file download helpers, fetch utilities, file dialog helpers, and IndexedDB wrappers.
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
pnpm add @simplysm/core-browser
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Import the package to activate side-effect extensions on `Element` and `HTMLElement`:
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
import "@simplysm/core-browser";
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Element Extensions
|
|
22
|
-
|
|
23
|
-
Extends the global `Element` interface with utility methods. These are activated as side effects when the package is imported.
|
|
24
|
-
|
|
25
|
-
### `element.findAll<TEl>(selector)`
|
|
26
|
-
|
|
27
|
-
Finds all child elements matching a CSS selector.
|
|
28
|
-
|
|
29
|
-
- Returns an empty array if the selector is empty.
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
import "@simplysm/core-browser";
|
|
33
|
-
|
|
34
|
-
const items = containerEl.findAll<HTMLLIElement>("li.active");
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**Signature:**
|
|
38
|
-
|
|
39
|
-
```ts
|
|
40
|
-
findAll<TEl extends Element = Element>(selector: string): TEl[]
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
### `element.findFirst<TEl>(selector)`
|
|
46
|
-
|
|
47
|
-
Finds the first child element matching a CSS selector.
|
|
48
|
-
|
|
49
|
-
- Returns `undefined` if the selector is empty or no match is found.
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
import "@simplysm/core-browser";
|
|
53
|
-
|
|
54
|
-
const input = formEl.findFirst<HTMLInputElement>("input[name='email']");
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**Signature:**
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
findFirst<TEl extends Element = Element>(selector: string): TEl | undefined
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
### `element.prependChild<TEl>(child)`
|
|
66
|
-
|
|
67
|
-
Inserts a child element as the first child of the element.
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
import "@simplysm/core-browser";
|
|
71
|
-
|
|
72
|
-
const newEl = document.createElement("div");
|
|
73
|
-
containerEl.prependChild(newEl);
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
**Signature:**
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
prependChild<TEl extends Element>(child: TEl): TEl
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
### `element.getParents()`
|
|
85
|
-
|
|
86
|
-
Returns all ancestor elements in order from closest to farthest.
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
import "@simplysm/core-browser";
|
|
90
|
-
|
|
91
|
-
const parents = someEl.getParents();
|
|
92
|
-
// parents[0] is the immediate parent, parents[n-1] is the farthest ancestor
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
**Signature:**
|
|
96
|
-
|
|
97
|
-
```ts
|
|
98
|
-
getParents(): Element[]
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
### `element.findFocusableParent()`
|
|
104
|
-
|
|
105
|
-
Finds the first focusable ancestor element using the `tabbable` library's focusability check.
|
|
106
|
-
|
|
107
|
-
- Returns `undefined` if no focusable parent is found.
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
import "@simplysm/core-browser";
|
|
111
|
-
|
|
112
|
-
const focusableParent = someEl.findFocusableParent();
|
|
113
|
-
focusableParent?.focus();
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
**Signature:**
|
|
117
|
-
|
|
118
|
-
```ts
|
|
119
|
-
findFocusableParent(): HTMLElement | undefined
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
### `element.findFirstFocusableChild()`
|
|
125
|
-
|
|
126
|
-
Finds the first focusable descendant element using a `TreeWalker` and the `tabbable` library's focusability check.
|
|
127
|
-
|
|
128
|
-
- Returns `undefined` if no focusable child is found.
|
|
129
|
-
|
|
130
|
-
```ts
|
|
131
|
-
import "@simplysm/core-browser";
|
|
132
|
-
|
|
133
|
-
const firstFocusable = dialogEl.findFirstFocusableChild();
|
|
134
|
-
firstFocusable?.focus();
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
**Signature:**
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
findFirstFocusableChild(): HTMLElement | undefined
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
|
-
### `element.isOffsetElement()`
|
|
146
|
-
|
|
147
|
-
Checks whether the element has a CSS `position` of `relative`, `absolute`, `fixed`, or `sticky`.
|
|
148
|
-
|
|
149
|
-
```ts
|
|
150
|
-
import "@simplysm/core-browser";
|
|
151
|
-
|
|
152
|
-
if (someEl.isOffsetElement()) {
|
|
153
|
-
// element is a positioning context
|
|
154
|
-
}
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
**Signature:**
|
|
158
|
-
|
|
159
|
-
```ts
|
|
160
|
-
isOffsetElement(): boolean
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
### `element.isVisible()`
|
|
166
|
-
|
|
167
|
-
Checks whether the element is visible on screen.
|
|
168
|
-
|
|
169
|
-
Considers:
|
|
170
|
-
- Presence of client rects (`getClientRects().length > 0`)
|
|
171
|
-
- `visibility: hidden`
|
|
172
|
-
- `opacity: 0`
|
|
173
|
-
|
|
174
|
-
```ts
|
|
175
|
-
import "@simplysm/core-browser";
|
|
176
|
-
|
|
177
|
-
if (someEl.isVisible()) {
|
|
178
|
-
// element is visible
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
**Signature:**
|
|
183
|
-
|
|
184
|
-
```ts
|
|
185
|
-
isVisible(): boolean
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
---
|
|
189
|
-
|
|
190
|
-
## HTMLElement Extensions
|
|
191
|
-
|
|
192
|
-
Extends the global `HTMLElement` interface with utility methods. These are activated as side effects when the package is imported.
|
|
193
|
-
|
|
194
|
-
### `htmlElement.repaint()`
|
|
195
|
-
|
|
196
|
-
Forces a browser repaint by triggering a synchronous reflow.
|
|
197
|
-
|
|
198
|
-
Accessing `offsetHeight` forces the browser to flush pending style changes immediately.
|
|
199
|
-
|
|
200
|
-
```ts
|
|
201
|
-
import "@simplysm/core-browser";
|
|
202
|
-
|
|
203
|
-
el.classList.add("animate");
|
|
204
|
-
el.repaint(); // flush styles
|
|
205
|
-
el.classList.add("animate-active");
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
**Signature:**
|
|
209
|
-
|
|
210
|
-
```ts
|
|
211
|
-
repaint(): void
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
### `htmlElement.getRelativeOffset(parent)`
|
|
217
|
-
|
|
218
|
-
Calculates the element's position relative to a parent element, returning coordinates suitable for use directly in CSS `top`/`left` properties.
|
|
219
|
-
|
|
220
|
-
Accounts for:
|
|
221
|
-
- Viewport-relative position (`getBoundingClientRect`)
|
|
222
|
-
- Document scroll position (`window.scrollX/Y`)
|
|
223
|
-
- Parent element internal scroll (`scrollTop/Left`)
|
|
224
|
-
- Border widths of intermediate elements
|
|
225
|
-
- CSS `transform` on element and parent
|
|
226
|
-
|
|
227
|
-
Typical use: positioning dropdowns or popups appended to `document.body`.
|
|
228
|
-
|
|
229
|
-
- `parent` — a reference `HTMLElement` or a CSS selector string (resolved via `closest`)
|
|
230
|
-
- Throws `ArgumentError` if the parent element cannot be found.
|
|
231
|
-
|
|
232
|
-
```ts
|
|
233
|
-
import "@simplysm/core-browser";
|
|
234
|
-
|
|
235
|
-
const popup = document.createElement("div");
|
|
236
|
-
document.body.appendChild(popup);
|
|
237
|
-
const { top, left } = triggerEl.getRelativeOffset(document.body);
|
|
238
|
-
popup.style.top = `${top}px`;
|
|
239
|
-
popup.style.left = `${left}px`;
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
**Signature:**
|
|
243
|
-
|
|
244
|
-
```ts
|
|
245
|
-
getRelativeOffset(parent: HTMLElement | string): { top: number; left: number }
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
---
|
|
249
|
-
|
|
250
|
-
### `htmlElement.scrollIntoViewIfNeeded(target, offset?)`
|
|
251
|
-
|
|
252
|
-
Scrolls the element so that a target position becomes visible, but only if the target is hidden behind an offset area (e.g., a fixed header or fixed column).
|
|
253
|
-
|
|
254
|
-
- Only handles cases where the target is obscured from the top or left. Downward/rightward scrolling relies on the browser's default focus behavior.
|
|
255
|
-
- Typically used with focus events on tables with fixed headers or columns.
|
|
256
|
-
|
|
257
|
-
```ts
|
|
258
|
-
import "@simplysm/core-browser";
|
|
259
|
-
|
|
260
|
-
tableEl.scrollIntoViewIfNeeded(
|
|
261
|
-
{ top: row.offsetTop, left: row.offsetLeft },
|
|
262
|
-
{ top: 48, left: 120 }, // fixed header height and fixed column width
|
|
263
|
-
);
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
**Signature:**
|
|
267
|
-
|
|
268
|
-
```ts
|
|
269
|
-
scrollIntoViewIfNeeded(
|
|
270
|
-
target: { top: number; left: number },
|
|
271
|
-
offset?: { top: number; left: number },
|
|
272
|
-
): void
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## Static Element Utilities
|
|
278
|
-
|
|
279
|
-
Standalone functions exported from `element-ext`.
|
|
280
|
-
|
|
281
|
-
### `copyElement(event)`
|
|
282
|
-
|
|
283
|
-
Copies the value of the first `input` or `textarea` inside the event target element to the clipboard.
|
|
284
|
-
|
|
285
|
-
Intended for use as a `copy` event handler.
|
|
286
|
-
|
|
287
|
-
```ts
|
|
288
|
-
import { copyElement } from "@simplysm/core-browser";
|
|
289
|
-
|
|
290
|
-
someEl.addEventListener("copy", copyElement);
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
**Signature:**
|
|
294
|
-
|
|
295
|
-
```ts
|
|
296
|
-
function copyElement(event: ClipboardEvent): void
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
---
|
|
300
|
-
|
|
301
|
-
### `pasteToElement(event)`
|
|
302
|
-
|
|
303
|
-
Pastes plain-text clipboard content into the first `input` or `textarea` inside the event target element, replacing its entire value.
|
|
304
|
-
|
|
305
|
-
Intended for use as a `paste` event handler. Does not consider cursor position or selection.
|
|
306
|
-
|
|
307
|
-
```ts
|
|
308
|
-
import { pasteToElement } from "@simplysm/core-browser";
|
|
309
|
-
|
|
310
|
-
someEl.addEventListener("paste", pasteToElement);
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
**Signature:**
|
|
314
|
-
|
|
315
|
-
```ts
|
|
316
|
-
function pasteToElement(event: ClipboardEvent): void
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
|
-
### `getBounds(els, timeout?)`
|
|
322
|
-
|
|
323
|
-
Retrieves bounding box information for multiple elements using `IntersectionObserver`. Results are returned in the same order as the input array.
|
|
324
|
-
|
|
325
|
-
- Deduplicates elements internally.
|
|
326
|
-
- Returns an empty array if `els` is empty.
|
|
327
|
-
- Throws `TimeoutError` if results are not received within `timeout` milliseconds (default: `5000`).
|
|
328
|
-
|
|
329
|
-
```ts
|
|
330
|
-
import { getBounds } from "@simplysm/core-browser";
|
|
331
|
-
|
|
332
|
-
const bounds = await getBounds([el1, el2]);
|
|
333
|
-
for (const { target, top, left, width, height } of bounds) {
|
|
334
|
-
console.log(target, top, left, width, height);
|
|
335
|
-
}
|
|
336
|
-
```
|
|
337
|
-
|
|
338
|
-
**Signature:**
|
|
339
|
-
|
|
340
|
-
```ts
|
|
341
|
-
function getBounds(els: Element[], timeout?: number): Promise<ElementBounds[]>
|
|
342
|
-
```
|
|
343
|
-
|
|
344
|
-
---
|
|
345
|
-
|
|
346
|
-
## Download Utilities
|
|
347
|
-
|
|
348
|
-
### `downloadBlob(blob, fileName)`
|
|
349
|
-
|
|
350
|
-
Triggers a file download in the browser for a given `Blob` object.
|
|
351
|
-
|
|
352
|
-
Creates a temporary object URL, simulates an anchor click, and revokes the URL after 1 second.
|
|
353
|
-
|
|
354
|
-
```ts
|
|
355
|
-
import { downloadBlob } from "@simplysm/core-browser";
|
|
356
|
-
|
|
357
|
-
const blob = new Blob(["hello"], { type: "text/plain" });
|
|
358
|
-
downloadBlob(blob, "hello.txt");
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
**Signature:**
|
|
362
|
-
|
|
363
|
-
```ts
|
|
364
|
-
function downloadBlob(blob: Blob, fileName: string): void
|
|
365
|
-
```
|
|
366
|
-
|
|
367
|
-
---
|
|
368
|
-
|
|
369
|
-
## Fetch Utilities
|
|
370
|
-
|
|
371
|
-
### `fetchUrlBytes(url, options?)`
|
|
372
|
-
|
|
373
|
-
Downloads binary data from a URL and returns it as a `Uint8Array`, with optional progress reporting.
|
|
374
|
-
|
|
375
|
-
- When `Content-Length` is known, pre-allocates memory for efficiency.
|
|
376
|
-
- When `Content-Length` is unknown (chunked transfer encoding), collects chunks then merges.
|
|
377
|
-
- Throws an `Error` if the response is not OK or the body is not readable.
|
|
378
|
-
|
|
379
|
-
```ts
|
|
380
|
-
import { fetchUrlBytes } from "@simplysm/core-browser";
|
|
381
|
-
|
|
382
|
-
const bytes = await fetchUrlBytes("https://example.com/file.bin", {
|
|
383
|
-
onProgress: ({ receivedLength, contentLength }) => {
|
|
384
|
-
console.log(`${receivedLength} / ${contentLength}`);
|
|
385
|
-
},
|
|
386
|
-
});
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
**Signature:**
|
|
390
|
-
|
|
391
|
-
```ts
|
|
392
|
-
function fetchUrlBytes(
|
|
393
|
-
url: string,
|
|
394
|
-
options?: { onProgress?: (progress: DownloadProgress) => void },
|
|
395
|
-
): Promise<Uint8Array>
|
|
396
|
-
```
|
|
397
|
-
|
|
398
|
-
---
|
|
399
|
-
|
|
400
|
-
## File Dialog Utilities
|
|
401
|
-
|
|
402
|
-
### `openFileDialog(options?)`
|
|
403
|
-
|
|
404
|
-
Programmatically opens a browser file selection dialog and returns the selected files.
|
|
405
|
-
|
|
406
|
-
- Returns `undefined` if the user cancels or selects no files.
|
|
407
|
-
- `options.accept` — MIME type or file extension filter (e.g., `"image/*"`, `".pdf"`)
|
|
408
|
-
- `options.multiple` — allow selecting multiple files (default: `false`)
|
|
409
|
-
|
|
410
|
-
```ts
|
|
411
|
-
import { openFileDialog } from "@simplysm/core-browser";
|
|
412
|
-
|
|
413
|
-
const files = await openFileDialog({ accept: ".csv", multiple: true });
|
|
414
|
-
if (files) {
|
|
415
|
-
for (const file of files) {
|
|
416
|
-
console.log(file.name);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
**Signature:**
|
|
422
|
-
|
|
423
|
-
```ts
|
|
424
|
-
function openFileDialog(options?: {
|
|
425
|
-
accept?: string;
|
|
426
|
-
multiple?: boolean;
|
|
427
|
-
}): Promise<File[] | undefined>
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
## IndexedDB Store
|
|
433
|
-
|
|
434
|
-
### `IndexedDbStore`
|
|
435
|
-
|
|
436
|
-
A thin wrapper around the browser `IndexedDB` API for typed key-value object stores. Opens a versioned database, auto-creates stores on upgrade, and closes the connection after each operation.
|
|
437
|
-
|
|
438
|
-
```ts
|
|
439
|
-
import { IndexedDbStore } from "@simplysm/core-browser";
|
|
440
|
-
|
|
441
|
-
const db = new IndexedDbStore("my-db", 1, [
|
|
442
|
-
{ name: "users", keyPath: "id" },
|
|
443
|
-
]);
|
|
444
|
-
|
|
445
|
-
await db.put("users", { id: 1, name: "Alice" });
|
|
446
|
-
const user = await db.get<{ id: number; name: string }>("users", 1);
|
|
447
|
-
const all = await db.getAll<{ id: number; name: string }>("users");
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
**Constructor:**
|
|
451
|
-
|
|
452
|
-
```ts
|
|
453
|
-
new IndexedDbStore(
|
|
454
|
-
dbName: string,
|
|
455
|
-
dbVersion: number,
|
|
456
|
-
storeConfigs: StoreConfig[],
|
|
457
|
-
)
|
|
458
|
-
```
|
|
459
|
-
|
|
460
|
-
**Methods:**
|
|
461
|
-
|
|
462
|
-
```ts
|
|
463
|
-
open(): Promise<IDBDatabase>
|
|
464
|
-
|
|
465
|
-
withStore<TResult>(
|
|
466
|
-
storeName: string,
|
|
467
|
-
mode: IDBTransactionMode,
|
|
468
|
-
fn: (store: IDBObjectStore) => Promise<TResult>,
|
|
469
|
-
): Promise<TResult>
|
|
470
|
-
|
|
471
|
-
get<TValue>(storeName: string, key: IDBValidKey): Promise<TValue | undefined>
|
|
472
|
-
|
|
473
|
-
put(storeName: string, value: unknown): Promise<void>
|
|
474
|
-
|
|
475
|
-
getAll<TItem>(storeName: string): Promise<TItem[]>
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
- `open()` — opens the database and returns the raw `IDBDatabase`. Creates missing object stores declared in `storeConfigs`. Rejects if the connection is blocked.
|
|
479
|
-
- `withStore()` — executes `fn` inside a single transaction on `storeName`. Aborts the transaction if `fn` throws. Closes the database when the transaction completes.
|
|
480
|
-
- `get()` — retrieves one record by `key` from `storeName`. Returns `undefined` if not found.
|
|
481
|
-
- `put()` — inserts or updates a record in `storeName`.
|
|
482
|
-
- `getAll()` — retrieves all records from `storeName`.
|
|
483
|
-
|
|
484
|
-
---
|
|
485
|
-
|
|
486
|
-
## IndexedDB Virtual Filesystem
|
|
487
|
-
|
|
488
|
-
### `IndexedDbVirtualFs`
|
|
489
|
-
|
|
490
|
-
A virtual filesystem built on top of `IndexedDbStore`. Each entry is stored as a flat key (slash-separated path string) with a kind (`"file"` or `"dir"`) and optional base64 data payload.
|
|
491
|
-
|
|
492
|
-
```ts
|
|
493
|
-
import { IndexedDbStore, IndexedDbVirtualFs } from "@simplysm/core-browser";
|
|
494
|
-
|
|
495
|
-
const db = new IndexedDbStore("my-fs-db", 1, [
|
|
496
|
-
{ name: "fs", keyPath: "fullKey" },
|
|
497
|
-
]);
|
|
498
|
-
const vfs = new IndexedDbVirtualFs(db, "fs", "fullKey");
|
|
499
|
-
|
|
500
|
-
await vfs.putEntry("/docs/readme.txt", "file", btoa("hello"));
|
|
501
|
-
const entry = await vfs.getEntry("/docs/readme.txt");
|
|
502
|
-
const children = await vfs.listChildren("/docs/");
|
|
503
|
-
await vfs.deleteByPrefix("/docs");
|
|
504
|
-
```
|
|
505
|
-
|
|
506
|
-
**Constructor:**
|
|
507
|
-
|
|
508
|
-
```ts
|
|
509
|
-
new IndexedDbVirtualFs(
|
|
510
|
-
db: IndexedDbStore,
|
|
511
|
-
storeName: string,
|
|
512
|
-
keyField: string,
|
|
513
|
-
)
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
- `db` — an `IndexedDbStore` instance to use for persistence.
|
|
517
|
-
- `storeName` — the object store name within the database.
|
|
518
|
-
- `keyField` — the field name used as the primary key in stored records.
|
|
519
|
-
|
|
520
|
-
**Methods:**
|
|
521
|
-
|
|
522
|
-
```ts
|
|
523
|
-
getEntry(fullKey: string): Promise<VirtualFsEntry | undefined>
|
|
524
|
-
|
|
525
|
-
putEntry(fullKey: string, kind: "file" | "dir", dataBase64?: string): Promise<void>
|
|
526
|
-
|
|
527
|
-
deleteByPrefix(keyPrefix: string): Promise<boolean>
|
|
528
|
-
|
|
529
|
-
listChildren(prefix: string): Promise<{ name: string; isDirectory: boolean }[]>
|
|
530
|
-
|
|
531
|
-
ensureDir(fullKeyBuilder: (path: string) => string, dirPath: string): Promise<void>
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
- `getEntry()` — retrieves the entry for `fullKey`. Returns `undefined` if not found.
|
|
535
|
-
- `putEntry()` — writes or overwrites an entry with the given `kind` and optional base64 data.
|
|
536
|
-
- `deleteByPrefix()` — deletes all entries whose key equals `keyPrefix` or starts with `keyPrefix + "/"`. Returns `true` if at least one entry was deleted.
|
|
537
|
-
- `listChildren()` — lists the immediate children under `prefix`. Each result includes `name` (the path segment) and `isDirectory`.
|
|
538
|
-
- `ensureDir()` — creates directory entries for every path segment in `dirPath` if they do not already exist. `fullKeyBuilder` maps a path string to the full store key.
|
|
539
|
-
|
|
540
|
-
---
|
|
541
|
-
|
|
542
|
-
## Types
|
|
543
|
-
|
|
544
|
-
### `ElementBounds`
|
|
545
|
-
|
|
546
|
-
Bounding box information for an element, returned by `getBounds`.
|
|
547
|
-
|
|
548
|
-
```ts
|
|
549
|
-
interface ElementBounds {
|
|
550
|
-
/** Element that was measured */
|
|
551
|
-
target: Element;
|
|
552
|
-
/** Top position relative to the viewport */
|
|
553
|
-
top: number;
|
|
554
|
-
/** Left position relative to the viewport */
|
|
555
|
-
left: number;
|
|
556
|
-
/** Element width */
|
|
557
|
-
width: number;
|
|
558
|
-
/** Element height */
|
|
559
|
-
height: number;
|
|
560
|
-
}
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
---
|
|
564
|
-
|
|
565
|
-
### `DownloadProgress`
|
|
566
|
-
|
|
567
|
-
Progress information passed to the `onProgress` callback of `fetchUrlBytes`.
|
|
568
|
-
|
|
569
|
-
```ts
|
|
570
|
-
interface DownloadProgress {
|
|
571
|
-
/** Number of bytes received so far */
|
|
572
|
-
receivedLength: number;
|
|
573
|
-
/** Total content length in bytes (0 if unknown) */
|
|
574
|
-
contentLength: number;
|
|
575
|
-
}
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
---
|
|
579
|
-
|
|
580
|
-
### `StoreConfig`
|
|
581
|
-
|
|
582
|
-
Configuration for a single object store within an `IndexedDbStore`.
|
|
583
|
-
|
|
584
|
-
```ts
|
|
585
|
-
interface StoreConfig {
|
|
586
|
-
/** Object store name */
|
|
587
|
-
name: string;
|
|
588
|
-
/** Primary key field path */
|
|
589
|
-
keyPath: string;
|
|
590
|
-
}
|
|
591
|
-
```
|
|
592
|
-
|
|
593
|
-
---
|
|
594
|
-
|
|
595
|
-
### `VirtualFsEntry`
|
|
596
|
-
|
|
597
|
-
A single entry stored in the `IndexedDbVirtualFs`.
|
|
598
|
-
|
|
599
|
-
```ts
|
|
600
|
-
interface VirtualFsEntry {
|
|
601
|
-
/** Entry kind: "file" or "dir" */
|
|
602
|
-
kind: "file" | "dir";
|
|
603
|
-
/** File contents encoded as base64 (only present for file entries) */
|
|
604
|
-
dataBase64?: string;
|
|
605
|
-
}
|
|
606
|
-
```
|