@versini/ui-fingerprint 1.1.1 → 1.1.3
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/README.md +29 -1
- package/dist/index.js +60 -62
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
1
|
# @versini/ui-fingerprint
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@versini/ui-fingerprint)
|
|
4
|
+
|
|
5
|
+
> A React component for generating unique visual fingerprints built with TypeScript and TailwindCSS.
|
|
6
|
+
|
|
7
|
+
The Fingerprint component creates unique visual patterns for user identification, data visualization, or decorative purposes.
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Features](#features)
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Usage](#usage)
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @versini/ui-fingerprint
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
> **Note**: This component requires TailwindCSS and the `@versini/ui-styles` plugin for proper styling. See the [installation documentation](https://versini-org.github.io/ui-components/?path=/docs/getting-started-installation--docs) for complete setup instructions.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { Fingerprint } from "@versini/ui-fingerprint";
|
|
27
|
+
|
|
28
|
+
function App() {
|
|
29
|
+
return <Fingerprint seed="unique-identifier" />;
|
|
30
|
+
}
|
|
31
|
+
```
|
package/dist/index.js
CHANGED
|
@@ -1,52 +1,50 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
@versini/ui-fingerprint v1.1.
|
|
2
|
+
@versini/ui-fingerprint v1.1.3
|
|
3
3
|
© 2025 gizmette.com
|
|
4
4
|
*/
|
|
5
5
|
try {
|
|
6
6
|
window.__VERSINI_UI_FINGERPRINT__ || (window.__VERSINI_UI_FINGERPRINT__ = {
|
|
7
|
-
version: "1.1.
|
|
8
|
-
buildTime: "
|
|
7
|
+
version: "1.1.3",
|
|
8
|
+
buildTime: "08/23/2025 10:08 AM EDT",
|
|
9
9
|
homepage: "https://github.com/aversini/ui-components",
|
|
10
10
|
license: "MIT"
|
|
11
11
|
});
|
|
12
12
|
} catch {
|
|
13
13
|
}
|
|
14
|
-
const D = (t) => Array.from(t).map((e) => e.toString(16).padStart(2, "0")).join(""),
|
|
14
|
+
const D = (t) => Array.from(t).map((e) => e.toString(16).padStart(2, "0")).join(""), w = async (t) => {
|
|
15
15
|
if (t === "")
|
|
16
16
|
return "";
|
|
17
17
|
const e = new TextEncoder().encode(t), o = await crypto.subtle.digest("SHA-256", e);
|
|
18
|
-
return Array.from(new Uint8Array(o)).map((
|
|
18
|
+
return Array.from(new Uint8Array(o)).map((s) => s.toString(16).padStart(2, "0")).join("");
|
|
19
19
|
};
|
|
20
|
-
function
|
|
20
|
+
function y(t, n) {
|
|
21
21
|
return new Promise((e) => setTimeout(e, t, n));
|
|
22
22
|
}
|
|
23
23
|
async function T(t, n, e = 50) {
|
|
24
|
-
var a, c, d;
|
|
25
24
|
const o = document;
|
|
26
25
|
for (; !o.body; )
|
|
27
|
-
await
|
|
26
|
+
await y(e);
|
|
28
27
|
const r = o.createElement("iframe");
|
|
29
28
|
try {
|
|
30
|
-
for (await new Promise((
|
|
31
|
-
let
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
}, p = (
|
|
35
|
-
|
|
29
|
+
for (await new Promise((a, s) => {
|
|
30
|
+
let l = !1;
|
|
31
|
+
const m = () => {
|
|
32
|
+
l = !0, a();
|
|
33
|
+
}, p = (f) => {
|
|
34
|
+
l = !0, s(f);
|
|
36
35
|
};
|
|
37
|
-
r.onload =
|
|
36
|
+
r.onload = m, r.onerror = p;
|
|
38
37
|
const { style: u } = r;
|
|
39
38
|
u.setProperty("display", "block", "important"), u.position = "absolute", u.top = "0", u.left = "0", u.visibility = "hidden", r.src = "about:blank", o.body.appendChild(r);
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
g || (((l = (s = r.contentWindow) == null ? void 0 : s.document) == null ? void 0 : l.readyState) === "complete" ? f() : setTimeout(i, 10));
|
|
39
|
+
const g = () => {
|
|
40
|
+
l || (r.contentWindow?.document?.readyState === "complete" ? m() : setTimeout(g, 10));
|
|
43
41
|
};
|
|
44
|
-
|
|
45
|
-
}); !
|
|
46
|
-
await
|
|
42
|
+
g();
|
|
43
|
+
}); !r.contentWindow?.document?.body; )
|
|
44
|
+
await y(e);
|
|
47
45
|
return await t(r, r.contentWindow);
|
|
48
46
|
} finally {
|
|
49
|
-
|
|
47
|
+
r.parentNode?.removeChild(r);
|
|
50
48
|
}
|
|
51
49
|
}
|
|
52
50
|
const x = {
|
|
@@ -56,16 +54,16 @@ const x = {
|
|
|
56
54
|
maxChannels: 0,
|
|
57
55
|
channelCountMode: ""
|
|
58
56
|
}
|
|
59
|
-
},
|
|
57
|
+
}, H = async (t) => new Promise((n) => {
|
|
60
58
|
try {
|
|
61
59
|
const e = new window.OfflineAudioContext(1, 5e3, 44100), o = e.createBufferSource(), r = e.createOscillator();
|
|
62
60
|
r.frequency.value = 1e3;
|
|
63
61
|
const a = e.createDynamicsCompressor();
|
|
64
|
-
a.threshold.value = -50, a.knee.value = 40, a.ratio.value = 12, a.attack.value = 0, a.release.value = 0.2, r.connect(a), a.connect(e.destination), r.start(), e.startRendering(), e.oncomplete = (
|
|
65
|
-
const
|
|
62
|
+
a.threshold.value = -50, a.knee.value = 40, a.ratio.value = 12, a.attack.value = 0, a.release.value = 0.2, r.connect(a), a.connect(e.destination), r.start(), e.startRendering(), e.oncomplete = (s) => {
|
|
63
|
+
const l = s.renderedBuffer.getChannelData(0);
|
|
66
64
|
r.disconnect(), a.disconnect(), n({
|
|
67
65
|
audio: {
|
|
68
|
-
sampleHash: D(
|
|
66
|
+
sampleHash: D(l),
|
|
69
67
|
oscillator: r.type,
|
|
70
68
|
maxChannels: e.destination.maxChannelCount,
|
|
71
69
|
channelCountMode: o.channelCountMode
|
|
@@ -82,7 +80,7 @@ const x = {
|
|
|
82
80
|
}
|
|
83
81
|
});
|
|
84
82
|
}
|
|
85
|
-
}),
|
|
83
|
+
}), v = { browser: "" }, P = async (t) => typeof navigator > "u" ? v : { browser: navigator.userAgent }, E = {
|
|
86
84
|
canvas: {
|
|
87
85
|
data: ""
|
|
88
86
|
}
|
|
@@ -94,11 +92,11 @@ const x = {
|
|
|
94
92
|
), r = N(o, 300, 30);
|
|
95
93
|
return {
|
|
96
94
|
canvas: {
|
|
97
|
-
data: (await
|
|
95
|
+
data: (await w(r.data.toString())).toString()
|
|
98
96
|
}
|
|
99
97
|
};
|
|
100
98
|
} catch (o) {
|
|
101
|
-
return t && (console.error("Error creating canvas fingerprint"), console.info(o)),
|
|
99
|
+
return t && (console.error("Error creating canvas fingerprint"), console.info(o)), E;
|
|
102
100
|
}
|
|
103
101
|
}, _ = (t, n) => {
|
|
104
102
|
const e = document.createElement("canvas"), o = e.getContext("2d");
|
|
@@ -121,15 +119,15 @@ const x = {
|
|
|
121
119
|
return e;
|
|
122
120
|
}, N = (t, n, e) => {
|
|
123
121
|
const o = [];
|
|
124
|
-
for (let
|
|
125
|
-
const
|
|
122
|
+
for (let s = 0; s < t[0].data.length; s++) {
|
|
123
|
+
const l = [];
|
|
126
124
|
for (let m = 0; m < t.length; m++)
|
|
127
|
-
|
|
128
|
-
o.push(F(
|
|
125
|
+
l.push(t[m].data[s]);
|
|
126
|
+
o.push(F(l));
|
|
129
127
|
}
|
|
130
128
|
const r = o, a = new Uint8ClampedArray(r);
|
|
131
129
|
return new ImageData(a, n, e);
|
|
132
|
-
}, G = [], L = "mmMwWLliI0O&1", k = "48px", h = ["monospace", "sans-serif", "serif"],
|
|
130
|
+
}, G = [], L = "mmMwWLliI0O&1", k = "48px", h = ["monospace", "sans-serif", "serif"], S = [
|
|
133
131
|
"sans-serif-thin",
|
|
134
132
|
"ARNO PRO",
|
|
135
133
|
"Agency FB",
|
|
@@ -172,33 +170,33 @@ const x = {
|
|
|
172
170
|
o.style.fontSize = k;
|
|
173
171
|
const r = e.createElement("div");
|
|
174
172
|
r.style.setProperty("visibility", "hidden", "important");
|
|
175
|
-
const a = {},
|
|
176
|
-
const
|
|
177
|
-
return
|
|
178
|
-
}, m = (i,
|
|
173
|
+
const a = {}, s = {}, l = (i) => {
|
|
174
|
+
const c = e.createElement("span"), { style: d } = c;
|
|
175
|
+
return d.position = "absolute", d.top = "0", d.left = "0", d.fontFamily = i, c.textContent = L, r.appendChild(c), c;
|
|
176
|
+
}, m = (i, c) => l(`'${i}',${c}`), p = () => h.map(l), u = () => {
|
|
179
177
|
const i = {};
|
|
180
|
-
for (const
|
|
181
|
-
i[
|
|
182
|
-
(
|
|
178
|
+
for (const c of S)
|
|
179
|
+
i[c] = h.map(
|
|
180
|
+
(d) => m(c, d)
|
|
183
181
|
);
|
|
184
182
|
return i;
|
|
185
|
-
},
|
|
186
|
-
(
|
|
187
|
-
),
|
|
183
|
+
}, g = (i) => h.some(
|
|
184
|
+
(c, d) => i[d].offsetWidth !== a[c] || i[d].offsetHeight !== s[c]
|
|
185
|
+
), f = p(), I = u();
|
|
188
186
|
o.appendChild(r);
|
|
189
187
|
for (let i = 0; i < h.length; i++)
|
|
190
|
-
a[h[i]] =
|
|
191
|
-
return
|
|
192
|
-
}),
|
|
188
|
+
a[h[i]] = f[i].offsetWidth, s[h[i]] = f[i].offsetHeight;
|
|
189
|
+
return S.filter((i) => g(I[i]));
|
|
190
|
+
}), C = {
|
|
193
191
|
vendor: "",
|
|
194
192
|
vendorUnmasked: "",
|
|
195
193
|
renderer: "",
|
|
196
194
|
rendererUnmasked: "",
|
|
197
195
|
version: "",
|
|
198
196
|
shadingLanguageVersion: ""
|
|
199
|
-
},
|
|
197
|
+
}, A = {
|
|
200
198
|
hardware: {
|
|
201
|
-
videocard:
|
|
199
|
+
videocard: C,
|
|
202
200
|
architecture: 0,
|
|
203
201
|
deviceMemory: "undefined",
|
|
204
202
|
jsHeapSizeLimit: 0
|
|
@@ -217,7 +215,7 @@ function U() {
|
|
|
217
215
|
shadingLanguageVersion: (n.getParameter(n.SHADING_LANGUAGE_VERSION) || "").toString()
|
|
218
216
|
};
|
|
219
217
|
}
|
|
220
|
-
return
|
|
218
|
+
return C;
|
|
221
219
|
}
|
|
222
220
|
function B() {
|
|
223
221
|
const t = new Float32Array(1), n = new Uint8Array(t.buffer);
|
|
@@ -237,7 +235,7 @@ const W = () => navigator.deviceMemory || 0, V = () => window.performance && win
|
|
|
237
235
|
}
|
|
238
236
|
});
|
|
239
237
|
} catch (e) {
|
|
240
|
-
t && (console.error("Error getting hardware data"), console.info(e)), n(
|
|
238
|
+
t && (console.error("Error getting hardware data"), console.info(e)), n(A);
|
|
241
239
|
}
|
|
242
240
|
}), j = {
|
|
243
241
|
locales: {
|
|
@@ -251,7 +249,7 @@ const W = () => navigator.deviceMemory || 0, V = () => window.performance && win
|
|
|
251
249
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
252
250
|
}
|
|
253
251
|
});
|
|
254
|
-
}),
|
|
252
|
+
}), M = {
|
|
255
253
|
screen: {
|
|
256
254
|
colorDepth: 0,
|
|
257
255
|
pixelDepth: 0,
|
|
@@ -272,7 +270,7 @@ const W = () => navigator.deviceMemory || 0, V = () => window.performance && win
|
|
|
272
270
|
};
|
|
273
271
|
n(o);
|
|
274
272
|
} catch (e) {
|
|
275
|
-
t && (console.error("Error creating screen fingerprint"), console.info(e)), n(
|
|
273
|
+
t && (console.error("Error creating screen fingerprint"), console.info(e)), n(M);
|
|
276
274
|
}
|
|
277
275
|
});
|
|
278
276
|
function J() {
|
|
@@ -314,9 +312,9 @@ const K = async (t) => {
|
|
|
314
312
|
}
|
|
315
313
|
};
|
|
316
314
|
} catch (n) {
|
|
317
|
-
return t && (console.error("Error getting system data"), console.info(n)),
|
|
315
|
+
return t && (console.error("Error getting system data"), console.info(n)), b;
|
|
318
316
|
}
|
|
319
|
-
},
|
|
317
|
+
}, b = {
|
|
320
318
|
system: {
|
|
321
319
|
platform: "",
|
|
322
320
|
cookieEnabled: !1,
|
|
@@ -326,8 +324,8 @@ const K = async (t) => {
|
|
|
326
324
|
}, Z = async (t) => {
|
|
327
325
|
try {
|
|
328
326
|
return Promise.all([
|
|
329
|
-
|
|
330
|
-
|
|
327
|
+
H(t),
|
|
328
|
+
P(),
|
|
331
329
|
R(t),
|
|
332
330
|
O(),
|
|
333
331
|
z(t),
|
|
@@ -338,19 +336,19 @@ const K = async (t) => {
|
|
|
338
336
|
} catch {
|
|
339
337
|
return [
|
|
340
338
|
x,
|
|
339
|
+
v,
|
|
341
340
|
E,
|
|
342
|
-
C,
|
|
343
341
|
G,
|
|
344
|
-
b,
|
|
345
|
-
j,
|
|
346
342
|
A,
|
|
347
|
-
|
|
343
|
+
j,
|
|
344
|
+
M,
|
|
345
|
+
b
|
|
348
346
|
];
|
|
349
347
|
}
|
|
350
348
|
}, Q = async (t) => {
|
|
351
349
|
try {
|
|
352
350
|
const n = await Z(t);
|
|
353
|
-
return await
|
|
351
|
+
return await w(JSON.stringify(n));
|
|
354
352
|
} catch (n) {
|
|
355
353
|
return t && (console.error("Error getting fingerprint hash"), console.info(n)), "";
|
|
356
354
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@versini/ui-fingerprint",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Arno Versini",
|
|
6
6
|
"publishConfig": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"main": "dist/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
17
|
"files": [
|
|
18
|
-
"dist"
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
19
20
|
],
|
|
20
21
|
"scripts": {
|
|
21
22
|
"build:check": "tsc",
|
|
@@ -27,10 +28,11 @@
|
|
|
27
28
|
"dev:types": "tsup --watch src",
|
|
28
29
|
"dev": "npm-run-all clean --parallel dev:js dev:types",
|
|
29
30
|
"lint": "biome lint src",
|
|
31
|
+
"lint:fix": "biome check src --write --no-errors-on-unmatched",
|
|
30
32
|
"prettier": "biome check --write --no-errors-on-unmatched",
|
|
31
33
|
"start": "static-server dist --port 5173",
|
|
32
34
|
"test:watch": "vitest",
|
|
33
35
|
"test": "vitest run"
|
|
34
36
|
},
|
|
35
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "a1afd6e4613b1da7abf61d10a72614611521fb39"
|
|
36
38
|
}
|