@talismn/orb 0.0.0-pr771-20230519010247
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 +15 -0
- package/README.md +25 -0
- package/dist/declarations/src/components/TalismanOrb.d.ts +19 -0
- package/dist/declarations/src/components/index.d.ts +1 -0
- package/dist/declarations/src/index.d.ts +1 -0
- package/dist/talismn-orb.cjs.d.ts +1 -0
- package/dist/talismn-orb.cjs.dev.js +152 -0
- package/dist/talismn-orb.cjs.js +7 -0
- package/dist/talismn-orb.cjs.prod.js +152 -0
- package/dist/talismn-orb.esm.js +142 -0
- package/package.json +44 -0
- package/src/components/TalismanOrb.tsx +118 -0
- package/src/components/index.ts +1 -0
- package/src/index.ts +1 -0
- package/tsconfig.json +8 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @talismn/orb
|
|
2
|
+
|
|
3
|
+
## 0.0.0-pr771-20230519010247
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 254d37f2: init
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [f7aca48b]
|
|
12
|
+
- Updated dependencies [01bf239b]
|
|
13
|
+
- Updated dependencies [48f0222e]
|
|
14
|
+
- Updated dependencies [01bf239b]
|
|
15
|
+
- @talismn/util@0.0.0-pr771-20230519010247
|
package/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# @talismn/orb
|
|
2
|
+
|
|
3
|
+
Display Talisman orbs in any dapp !
|
|
4
|
+
|
|
5
|
+
## Setup in a dapp (or extension) to use this library
|
|
6
|
+
|
|
7
|
+
Install :
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# for npm
|
|
11
|
+
npm install @talismn/orb
|
|
12
|
+
|
|
13
|
+
# for yarn
|
|
14
|
+
yarn add @talismn/orb
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { TalismanOrb } from "@talismn/orb"
|
|
21
|
+
|
|
22
|
+
const Avatar: FC<{ address: string }> = ({ address }) => {
|
|
23
|
+
return <TalismanOrb seed={address} />
|
|
24
|
+
}
|
|
25
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
declare type TalismanOrbProps = {
|
|
3
|
+
seed: string;
|
|
4
|
+
width?: number;
|
|
5
|
+
height?: number;
|
|
6
|
+
className?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const useTalismanOrb: (seed: string) => {
|
|
9
|
+
id: string;
|
|
10
|
+
bgColor1: string;
|
|
11
|
+
bgColor2: string;
|
|
12
|
+
glowColor: string;
|
|
13
|
+
transform: string;
|
|
14
|
+
cx: number;
|
|
15
|
+
cy: number;
|
|
16
|
+
isEthereum: boolean;
|
|
17
|
+
};
|
|
18
|
+
export declare const TalismanOrb: FC<TalismanOrbProps>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./TalismanOrb";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./components";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./declarations/src/index";
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var util = require('@talismn/util');
|
|
6
|
+
var md5 = require('blueimp-md5');
|
|
7
|
+
var Color = require('color');
|
|
8
|
+
var nanoid = require('nanoid');
|
|
9
|
+
var react = require('react');
|
|
10
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
+
|
|
12
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
13
|
+
|
|
14
|
+
var md5__default = /*#__PURE__*/_interopDefault(md5);
|
|
15
|
+
var Color__default = /*#__PURE__*/_interopDefault(Color);
|
|
16
|
+
|
|
17
|
+
const djb2 = str => {
|
|
18
|
+
let hash = 5381;
|
|
19
|
+
for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash + str.charCodeAt(i);
|
|
20
|
+
return hash;
|
|
21
|
+
};
|
|
22
|
+
const valueFromHash = (hash, max) => {
|
|
23
|
+
return (max + djb2(hash)) % max;
|
|
24
|
+
};
|
|
25
|
+
const colorFromHash = hash => {
|
|
26
|
+
const hue = valueFromHash(hash, 360);
|
|
27
|
+
return Color__default["default"].hsv(hue, 100, 100);
|
|
28
|
+
};
|
|
29
|
+
const rotateText = (text, nbChars = 0) => text.slice(nbChars) + text.slice(0, nbChars);
|
|
30
|
+
const useTalismanOrb = seed => {
|
|
31
|
+
return react.useMemo(() => {
|
|
32
|
+
const isEthereum = seed?.startsWith("0x");
|
|
33
|
+
try {
|
|
34
|
+
// seed may be specific to a ss58 prefix, get the base address
|
|
35
|
+
// eslint-disable-next-line no-var
|
|
36
|
+
var address = isEthereum ? seed : util.encodeAnyAddress(seed);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
address = seed;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// derive 3 hashs from the seed, used to generate the 3 colors
|
|
42
|
+
const hash1 = md5__default["default"](address);
|
|
43
|
+
const hash2 = rotateText(hash1, 1);
|
|
44
|
+
const hash3 = rotateText(hash1, 2);
|
|
45
|
+
|
|
46
|
+
// the 2 darkest ones will be used as gradient BG
|
|
47
|
+
// the lightest one will be used as gradient circle, to mimic a 3D lighting effect
|
|
48
|
+
const colors = [colorFromHash(hash1), colorFromHash(hash2), colorFromHash(hash3)].sort((c1, c2) => c1.lightness() - c2.lightness());
|
|
49
|
+
|
|
50
|
+
// random location in top left corner, avoid beeing to close from the center
|
|
51
|
+
const dotX = 10 + valueFromHash(hash1, 10);
|
|
52
|
+
const dotY = 10 + valueFromHash(hash2, 10);
|
|
53
|
+
|
|
54
|
+
// global rotation
|
|
55
|
+
const rotation = valueFromHash(hash1, 360);
|
|
56
|
+
return {
|
|
57
|
+
id: nanoid.nanoid(),
|
|
58
|
+
//multiple avatars should cohabit on the same pageaa
|
|
59
|
+
bgColor1: colors[0].hex(),
|
|
60
|
+
bgColor2: colors[1].hex(),
|
|
61
|
+
glowColor: colors[2].hex(),
|
|
62
|
+
transform: `rotate(${rotation} 32 32)`,
|
|
63
|
+
cx: dotX,
|
|
64
|
+
cy: dotY,
|
|
65
|
+
isEthereum
|
|
66
|
+
};
|
|
67
|
+
}, [seed]);
|
|
68
|
+
};
|
|
69
|
+
const TalismanOrb = ({
|
|
70
|
+
seed,
|
|
71
|
+
width = "1em",
|
|
72
|
+
height = "1em",
|
|
73
|
+
className
|
|
74
|
+
}) => {
|
|
75
|
+
const {
|
|
76
|
+
id,
|
|
77
|
+
bgColor1,
|
|
78
|
+
bgColor2,
|
|
79
|
+
transform,
|
|
80
|
+
glowColor,
|
|
81
|
+
cx,
|
|
82
|
+
cy,
|
|
83
|
+
isEthereum
|
|
84
|
+
} = useTalismanOrb(seed);
|
|
85
|
+
return /*#__PURE__*/jsxRuntime.jsxs("svg", {
|
|
86
|
+
width: width,
|
|
87
|
+
height: height,
|
|
88
|
+
viewBox: `0 0 64 64`,
|
|
89
|
+
className: className,
|
|
90
|
+
version: "1.1",
|
|
91
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
92
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs("defs", {
|
|
93
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs("linearGradient", {
|
|
94
|
+
id: `${id}-bg`,
|
|
95
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
96
|
+
offset: "20%",
|
|
97
|
+
stopColor: bgColor1
|
|
98
|
+
}), /*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
99
|
+
offset: "100%",
|
|
100
|
+
stopColor: bgColor2
|
|
101
|
+
})]
|
|
102
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("radialGradient", {
|
|
103
|
+
id: `${id}-circle`,
|
|
104
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
105
|
+
offset: "10%",
|
|
106
|
+
stopColor: glowColor
|
|
107
|
+
}), /*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
108
|
+
offset: "100%",
|
|
109
|
+
stopColor: "transparent"
|
|
110
|
+
})]
|
|
111
|
+
}), /*#__PURE__*/jsxRuntime.jsx("clipPath", {
|
|
112
|
+
id: `${id}-clip`,
|
|
113
|
+
children: /*#__PURE__*/jsxRuntime.jsx("circle", {
|
|
114
|
+
cx: "32",
|
|
115
|
+
cy: "32",
|
|
116
|
+
r: "32"
|
|
117
|
+
})
|
|
118
|
+
})]
|
|
119
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("g", {
|
|
120
|
+
clipPath: `url(#${id}-clip)`,
|
|
121
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs("g", {
|
|
122
|
+
transform: transform,
|
|
123
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("rect", {
|
|
124
|
+
fill: `url(#${id}-bg)`,
|
|
125
|
+
x: 0,
|
|
126
|
+
y: 0,
|
|
127
|
+
width: 64,
|
|
128
|
+
height: 64
|
|
129
|
+
}), /*#__PURE__*/jsxRuntime.jsx("circle", {
|
|
130
|
+
fill: `url(#${id}-circle)`,
|
|
131
|
+
cx: cx,
|
|
132
|
+
cy: cy,
|
|
133
|
+
r: 45,
|
|
134
|
+
opacity: 0.7
|
|
135
|
+
})]
|
|
136
|
+
}), isEthereum && /*#__PURE__*/jsxRuntime.jsxs("g", {
|
|
137
|
+
opacity: "0.75",
|
|
138
|
+
transform: "scale(0.7) translate(14 14)",
|
|
139
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
140
|
+
d: "M12.8101 32.76L32.0001 44.62L51.1901 32.76L32.0001 -0.0699997L12.8101 32.76Z",
|
|
141
|
+
fill: "white"
|
|
142
|
+
}), /*#__PURE__*/jsxRuntime.jsx("path", {
|
|
143
|
+
d: "M12.8101 36.48L32.0001 48.43L51.1901 36.48L32.0001 63.93L12.8101 36.48Z",
|
|
144
|
+
fill: "white"
|
|
145
|
+
})]
|
|
146
|
+
})]
|
|
147
|
+
})]
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
exports.TalismanOrb = TalismanOrb;
|
|
152
|
+
exports.useTalismanOrb = useTalismanOrb;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var util = require('@talismn/util');
|
|
6
|
+
var md5 = require('blueimp-md5');
|
|
7
|
+
var Color = require('color');
|
|
8
|
+
var nanoid = require('nanoid');
|
|
9
|
+
var react = require('react');
|
|
10
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
11
|
+
|
|
12
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
13
|
+
|
|
14
|
+
var md5__default = /*#__PURE__*/_interopDefault(md5);
|
|
15
|
+
var Color__default = /*#__PURE__*/_interopDefault(Color);
|
|
16
|
+
|
|
17
|
+
const djb2 = str => {
|
|
18
|
+
let hash = 5381;
|
|
19
|
+
for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash + str.charCodeAt(i);
|
|
20
|
+
return hash;
|
|
21
|
+
};
|
|
22
|
+
const valueFromHash = (hash, max) => {
|
|
23
|
+
return (max + djb2(hash)) % max;
|
|
24
|
+
};
|
|
25
|
+
const colorFromHash = hash => {
|
|
26
|
+
const hue = valueFromHash(hash, 360);
|
|
27
|
+
return Color__default["default"].hsv(hue, 100, 100);
|
|
28
|
+
};
|
|
29
|
+
const rotateText = (text, nbChars = 0) => text.slice(nbChars) + text.slice(0, nbChars);
|
|
30
|
+
const useTalismanOrb = seed => {
|
|
31
|
+
return react.useMemo(() => {
|
|
32
|
+
const isEthereum = seed?.startsWith("0x");
|
|
33
|
+
try {
|
|
34
|
+
// seed may be specific to a ss58 prefix, get the base address
|
|
35
|
+
// eslint-disable-next-line no-var
|
|
36
|
+
var address = isEthereum ? seed : util.encodeAnyAddress(seed);
|
|
37
|
+
} catch (err) {
|
|
38
|
+
address = seed;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// derive 3 hashs from the seed, used to generate the 3 colors
|
|
42
|
+
const hash1 = md5__default["default"](address);
|
|
43
|
+
const hash2 = rotateText(hash1, 1);
|
|
44
|
+
const hash3 = rotateText(hash1, 2);
|
|
45
|
+
|
|
46
|
+
// the 2 darkest ones will be used as gradient BG
|
|
47
|
+
// the lightest one will be used as gradient circle, to mimic a 3D lighting effect
|
|
48
|
+
const colors = [colorFromHash(hash1), colorFromHash(hash2), colorFromHash(hash3)].sort((c1, c2) => c1.lightness() - c2.lightness());
|
|
49
|
+
|
|
50
|
+
// random location in top left corner, avoid beeing to close from the center
|
|
51
|
+
const dotX = 10 + valueFromHash(hash1, 10);
|
|
52
|
+
const dotY = 10 + valueFromHash(hash2, 10);
|
|
53
|
+
|
|
54
|
+
// global rotation
|
|
55
|
+
const rotation = valueFromHash(hash1, 360);
|
|
56
|
+
return {
|
|
57
|
+
id: nanoid.nanoid(),
|
|
58
|
+
//multiple avatars should cohabit on the same pageaa
|
|
59
|
+
bgColor1: colors[0].hex(),
|
|
60
|
+
bgColor2: colors[1].hex(),
|
|
61
|
+
glowColor: colors[2].hex(),
|
|
62
|
+
transform: `rotate(${rotation} 32 32)`,
|
|
63
|
+
cx: dotX,
|
|
64
|
+
cy: dotY,
|
|
65
|
+
isEthereum
|
|
66
|
+
};
|
|
67
|
+
}, [seed]);
|
|
68
|
+
};
|
|
69
|
+
const TalismanOrb = ({
|
|
70
|
+
seed,
|
|
71
|
+
width = "1em",
|
|
72
|
+
height = "1em",
|
|
73
|
+
className
|
|
74
|
+
}) => {
|
|
75
|
+
const {
|
|
76
|
+
id,
|
|
77
|
+
bgColor1,
|
|
78
|
+
bgColor2,
|
|
79
|
+
transform,
|
|
80
|
+
glowColor,
|
|
81
|
+
cx,
|
|
82
|
+
cy,
|
|
83
|
+
isEthereum
|
|
84
|
+
} = useTalismanOrb(seed);
|
|
85
|
+
return /*#__PURE__*/jsxRuntime.jsxs("svg", {
|
|
86
|
+
width: width,
|
|
87
|
+
height: height,
|
|
88
|
+
viewBox: `0 0 64 64`,
|
|
89
|
+
className: className,
|
|
90
|
+
version: "1.1",
|
|
91
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
92
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs("defs", {
|
|
93
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs("linearGradient", {
|
|
94
|
+
id: `${id}-bg`,
|
|
95
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
96
|
+
offset: "20%",
|
|
97
|
+
stopColor: bgColor1
|
|
98
|
+
}), /*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
99
|
+
offset: "100%",
|
|
100
|
+
stopColor: bgColor2
|
|
101
|
+
})]
|
|
102
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("radialGradient", {
|
|
103
|
+
id: `${id}-circle`,
|
|
104
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
105
|
+
offset: "10%",
|
|
106
|
+
stopColor: glowColor
|
|
107
|
+
}), /*#__PURE__*/jsxRuntime.jsx("stop", {
|
|
108
|
+
offset: "100%",
|
|
109
|
+
stopColor: "transparent"
|
|
110
|
+
})]
|
|
111
|
+
}), /*#__PURE__*/jsxRuntime.jsx("clipPath", {
|
|
112
|
+
id: `${id}-clip`,
|
|
113
|
+
children: /*#__PURE__*/jsxRuntime.jsx("circle", {
|
|
114
|
+
cx: "32",
|
|
115
|
+
cy: "32",
|
|
116
|
+
r: "32"
|
|
117
|
+
})
|
|
118
|
+
})]
|
|
119
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("g", {
|
|
120
|
+
clipPath: `url(#${id}-clip)`,
|
|
121
|
+
children: [/*#__PURE__*/jsxRuntime.jsxs("g", {
|
|
122
|
+
transform: transform,
|
|
123
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("rect", {
|
|
124
|
+
fill: `url(#${id}-bg)`,
|
|
125
|
+
x: 0,
|
|
126
|
+
y: 0,
|
|
127
|
+
width: 64,
|
|
128
|
+
height: 64
|
|
129
|
+
}), /*#__PURE__*/jsxRuntime.jsx("circle", {
|
|
130
|
+
fill: `url(#${id}-circle)`,
|
|
131
|
+
cx: cx,
|
|
132
|
+
cy: cy,
|
|
133
|
+
r: 45,
|
|
134
|
+
opacity: 0.7
|
|
135
|
+
})]
|
|
136
|
+
}), isEthereum && /*#__PURE__*/jsxRuntime.jsxs("g", {
|
|
137
|
+
opacity: "0.75",
|
|
138
|
+
transform: "scale(0.7) translate(14 14)",
|
|
139
|
+
children: [/*#__PURE__*/jsxRuntime.jsx("path", {
|
|
140
|
+
d: "M12.8101 32.76L32.0001 44.62L51.1901 32.76L32.0001 -0.0699997L12.8101 32.76Z",
|
|
141
|
+
fill: "white"
|
|
142
|
+
}), /*#__PURE__*/jsxRuntime.jsx("path", {
|
|
143
|
+
d: "M12.8101 36.48L32.0001 48.43L51.1901 36.48L32.0001 63.93L12.8101 36.48Z",
|
|
144
|
+
fill: "white"
|
|
145
|
+
})]
|
|
146
|
+
})]
|
|
147
|
+
})]
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
exports.TalismanOrb = TalismanOrb;
|
|
152
|
+
exports.useTalismanOrb = useTalismanOrb;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { encodeAnyAddress } from '@talismn/util';
|
|
2
|
+
import md5 from 'blueimp-md5';
|
|
3
|
+
import Color from 'color';
|
|
4
|
+
import { nanoid } from 'nanoid';
|
|
5
|
+
import { useMemo } from 'react';
|
|
6
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
const djb2 = str => {
|
|
9
|
+
let hash = 5381;
|
|
10
|
+
for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash + str.charCodeAt(i);
|
|
11
|
+
return hash;
|
|
12
|
+
};
|
|
13
|
+
const valueFromHash = (hash, max) => {
|
|
14
|
+
return (max + djb2(hash)) % max;
|
|
15
|
+
};
|
|
16
|
+
const colorFromHash = hash => {
|
|
17
|
+
const hue = valueFromHash(hash, 360);
|
|
18
|
+
return Color.hsv(hue, 100, 100);
|
|
19
|
+
};
|
|
20
|
+
const rotateText = (text, nbChars = 0) => text.slice(nbChars) + text.slice(0, nbChars);
|
|
21
|
+
const useTalismanOrb = seed => {
|
|
22
|
+
return useMemo(() => {
|
|
23
|
+
const isEthereum = seed?.startsWith("0x");
|
|
24
|
+
try {
|
|
25
|
+
// seed may be specific to a ss58 prefix, get the base address
|
|
26
|
+
// eslint-disable-next-line no-var
|
|
27
|
+
var address = isEthereum ? seed : encodeAnyAddress(seed);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
address = seed;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// derive 3 hashs from the seed, used to generate the 3 colors
|
|
33
|
+
const hash1 = md5(address);
|
|
34
|
+
const hash2 = rotateText(hash1, 1);
|
|
35
|
+
const hash3 = rotateText(hash1, 2);
|
|
36
|
+
|
|
37
|
+
// the 2 darkest ones will be used as gradient BG
|
|
38
|
+
// the lightest one will be used as gradient circle, to mimic a 3D lighting effect
|
|
39
|
+
const colors = [colorFromHash(hash1), colorFromHash(hash2), colorFromHash(hash3)].sort((c1, c2) => c1.lightness() - c2.lightness());
|
|
40
|
+
|
|
41
|
+
// random location in top left corner, avoid beeing to close from the center
|
|
42
|
+
const dotX = 10 + valueFromHash(hash1, 10);
|
|
43
|
+
const dotY = 10 + valueFromHash(hash2, 10);
|
|
44
|
+
|
|
45
|
+
// global rotation
|
|
46
|
+
const rotation = valueFromHash(hash1, 360);
|
|
47
|
+
return {
|
|
48
|
+
id: nanoid(),
|
|
49
|
+
//multiple avatars should cohabit on the same pageaa
|
|
50
|
+
bgColor1: colors[0].hex(),
|
|
51
|
+
bgColor2: colors[1].hex(),
|
|
52
|
+
glowColor: colors[2].hex(),
|
|
53
|
+
transform: `rotate(${rotation} 32 32)`,
|
|
54
|
+
cx: dotX,
|
|
55
|
+
cy: dotY,
|
|
56
|
+
isEthereum
|
|
57
|
+
};
|
|
58
|
+
}, [seed]);
|
|
59
|
+
};
|
|
60
|
+
const TalismanOrb = ({
|
|
61
|
+
seed,
|
|
62
|
+
width = "1em",
|
|
63
|
+
height = "1em",
|
|
64
|
+
className
|
|
65
|
+
}) => {
|
|
66
|
+
const {
|
|
67
|
+
id,
|
|
68
|
+
bgColor1,
|
|
69
|
+
bgColor2,
|
|
70
|
+
transform,
|
|
71
|
+
glowColor,
|
|
72
|
+
cx,
|
|
73
|
+
cy,
|
|
74
|
+
isEthereum
|
|
75
|
+
} = useTalismanOrb(seed);
|
|
76
|
+
return /*#__PURE__*/jsxs("svg", {
|
|
77
|
+
width: width,
|
|
78
|
+
height: height,
|
|
79
|
+
viewBox: `0 0 64 64`,
|
|
80
|
+
className: className,
|
|
81
|
+
version: "1.1",
|
|
82
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
83
|
+
children: [/*#__PURE__*/jsxs("defs", {
|
|
84
|
+
children: [/*#__PURE__*/jsxs("linearGradient", {
|
|
85
|
+
id: `${id}-bg`,
|
|
86
|
+
children: [/*#__PURE__*/jsx("stop", {
|
|
87
|
+
offset: "20%",
|
|
88
|
+
stopColor: bgColor1
|
|
89
|
+
}), /*#__PURE__*/jsx("stop", {
|
|
90
|
+
offset: "100%",
|
|
91
|
+
stopColor: bgColor2
|
|
92
|
+
})]
|
|
93
|
+
}), /*#__PURE__*/jsxs("radialGradient", {
|
|
94
|
+
id: `${id}-circle`,
|
|
95
|
+
children: [/*#__PURE__*/jsx("stop", {
|
|
96
|
+
offset: "10%",
|
|
97
|
+
stopColor: glowColor
|
|
98
|
+
}), /*#__PURE__*/jsx("stop", {
|
|
99
|
+
offset: "100%",
|
|
100
|
+
stopColor: "transparent"
|
|
101
|
+
})]
|
|
102
|
+
}), /*#__PURE__*/jsx("clipPath", {
|
|
103
|
+
id: `${id}-clip`,
|
|
104
|
+
children: /*#__PURE__*/jsx("circle", {
|
|
105
|
+
cx: "32",
|
|
106
|
+
cy: "32",
|
|
107
|
+
r: "32"
|
|
108
|
+
})
|
|
109
|
+
})]
|
|
110
|
+
}), /*#__PURE__*/jsxs("g", {
|
|
111
|
+
clipPath: `url(#${id}-clip)`,
|
|
112
|
+
children: [/*#__PURE__*/jsxs("g", {
|
|
113
|
+
transform: transform,
|
|
114
|
+
children: [/*#__PURE__*/jsx("rect", {
|
|
115
|
+
fill: `url(#${id}-bg)`,
|
|
116
|
+
x: 0,
|
|
117
|
+
y: 0,
|
|
118
|
+
width: 64,
|
|
119
|
+
height: 64
|
|
120
|
+
}), /*#__PURE__*/jsx("circle", {
|
|
121
|
+
fill: `url(#${id}-circle)`,
|
|
122
|
+
cx: cx,
|
|
123
|
+
cy: cy,
|
|
124
|
+
r: 45,
|
|
125
|
+
opacity: 0.7
|
|
126
|
+
})]
|
|
127
|
+
}), isEthereum && /*#__PURE__*/jsxs("g", {
|
|
128
|
+
opacity: "0.75",
|
|
129
|
+
transform: "scale(0.7) translate(14 14)",
|
|
130
|
+
children: [/*#__PURE__*/jsx("path", {
|
|
131
|
+
d: "M12.8101 32.76L32.0001 44.62L51.1901 32.76L32.0001 -0.0699997L12.8101 32.76Z",
|
|
132
|
+
fill: "white"
|
|
133
|
+
}), /*#__PURE__*/jsx("path", {
|
|
134
|
+
d: "M12.8101 36.48L32.0001 48.43L51.1901 36.48L32.0001 63.93L12.8101 36.48Z",
|
|
135
|
+
fill: "white"
|
|
136
|
+
})]
|
|
137
|
+
})]
|
|
138
|
+
})]
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
export { TalismanOrb, useTalismanOrb };
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@talismn/orb",
|
|
3
|
+
"version": "0.0.0-pr771-20230519010247",
|
|
4
|
+
"author": "Talisman",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"directory": "packages/balances-react",
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/talismansociety/talisman.git"
|
|
13
|
+
},
|
|
14
|
+
"main": "dist/talismn-orb.cjs.js",
|
|
15
|
+
"module": "dist/talismn-orb.esm.js",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./src/index.ts",
|
|
18
|
+
"./package.json": "./package.json"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"lint": "eslint src --max-warnings 0",
|
|
22
|
+
"clean": "rm -rf dist && rm -rf .turbo rm -rf node_modules"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@talismn/util": "0.0.0-pr771-20230519010247",
|
|
26
|
+
"blueimp-md5": "2.19.0",
|
|
27
|
+
"color": "4.2.3",
|
|
28
|
+
"nanoid": "3.3.6"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@talismn/eslint-config": "0.0.0-pr771-20230519010247",
|
|
32
|
+
"@talismn/tsconfig": "0.0.2",
|
|
33
|
+
"@types/react": "18.0.14",
|
|
34
|
+
"@types/react-dom": "18.0.5",
|
|
35
|
+
"eslint": "^8.15.0",
|
|
36
|
+
"react": "18.2.0",
|
|
37
|
+
"react-dom": "18.2.0",
|
|
38
|
+
"typescript": "4.6.4"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"react": "*",
|
|
42
|
+
"react-dom": "*"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { encodeAnyAddress } from "@talismn/util"
|
|
2
|
+
import md5 from "blueimp-md5"
|
|
3
|
+
import Color from "color"
|
|
4
|
+
import { nanoid } from "nanoid"
|
|
5
|
+
import { FC, useMemo } from "react"
|
|
6
|
+
|
|
7
|
+
const djb2 = (str: string) => {
|
|
8
|
+
let hash = 5381
|
|
9
|
+
for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash + str.charCodeAt(i)
|
|
10
|
+
return hash
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const valueFromHash = (hash: string, max: number) => {
|
|
14
|
+
return (max + djb2(hash)) % max
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const colorFromHash = (hash: string) => {
|
|
18
|
+
const hue = valueFromHash(hash, 360)
|
|
19
|
+
return Color.hsv(hue, 100, 100)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const rotateText = (text: string, nbChars = 0) => text.slice(nbChars) + text.slice(0, nbChars)
|
|
23
|
+
|
|
24
|
+
type TalismanOrbProps = { seed: string; width?: number; height?: number; className?: string }
|
|
25
|
+
|
|
26
|
+
export const useTalismanOrb = (seed: string) => {
|
|
27
|
+
return useMemo(() => {
|
|
28
|
+
const isEthereum = seed?.startsWith("0x")
|
|
29
|
+
try {
|
|
30
|
+
// seed may be specific to a ss58 prefix, get the base address
|
|
31
|
+
// eslint-disable-next-line no-var
|
|
32
|
+
var address = isEthereum ? seed : encodeAnyAddress(seed)
|
|
33
|
+
} catch (err) {
|
|
34
|
+
address = seed
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// derive 3 hashs from the seed, used to generate the 3 colors
|
|
38
|
+
const hash1 = md5(address)
|
|
39
|
+
const hash2 = rotateText(hash1, 1)
|
|
40
|
+
const hash3 = rotateText(hash1, 2)
|
|
41
|
+
|
|
42
|
+
// the 2 darkest ones will be used as gradient BG
|
|
43
|
+
// the lightest one will be used as gradient circle, to mimic a 3D lighting effect
|
|
44
|
+
const colors = [colorFromHash(hash1), colorFromHash(hash2), colorFromHash(hash3)].sort(
|
|
45
|
+
(c1, c2) => c1.lightness() - c2.lightness()
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
// random location in top left corner, avoid beeing to close from the center
|
|
49
|
+
const dotX = 10 + valueFromHash(hash1, 10)
|
|
50
|
+
const dotY = 10 + valueFromHash(hash2, 10)
|
|
51
|
+
|
|
52
|
+
// global rotation
|
|
53
|
+
const rotation = valueFromHash(hash1, 360)
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
id: nanoid(), //multiple avatars should cohabit on the same pageaa
|
|
57
|
+
bgColor1: colors[0].hex(),
|
|
58
|
+
bgColor2: colors[1].hex(),
|
|
59
|
+
glowColor: colors[2].hex(),
|
|
60
|
+
transform: `rotate(${rotation} 32 32)`,
|
|
61
|
+
cx: dotX,
|
|
62
|
+
cy: dotY,
|
|
63
|
+
isEthereum,
|
|
64
|
+
}
|
|
65
|
+
}, [seed])
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const TalismanOrb: FC<TalismanOrbProps> = ({
|
|
69
|
+
seed,
|
|
70
|
+
width = "1em",
|
|
71
|
+
height = "1em",
|
|
72
|
+
className,
|
|
73
|
+
}) => {
|
|
74
|
+
const { id, bgColor1, bgColor2, transform, glowColor, cx, cy, isEthereum } = useTalismanOrb(seed)
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<svg
|
|
78
|
+
width={width}
|
|
79
|
+
height={height}
|
|
80
|
+
viewBox={`0 0 64 64`}
|
|
81
|
+
className={className}
|
|
82
|
+
version="1.1"
|
|
83
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
84
|
+
>
|
|
85
|
+
<defs>
|
|
86
|
+
<linearGradient id={`${id}-bg`}>
|
|
87
|
+
<stop offset="20%" stopColor={bgColor1} />
|
|
88
|
+
<stop offset="100%" stopColor={bgColor2} />
|
|
89
|
+
</linearGradient>
|
|
90
|
+
<radialGradient id={`${id}-circle`}>
|
|
91
|
+
<stop offset="10%" stopColor={glowColor} />
|
|
92
|
+
<stop offset="100%" stopColor="transparent" />
|
|
93
|
+
</radialGradient>
|
|
94
|
+
<clipPath id={`${id}-clip`}>
|
|
95
|
+
<circle cx="32" cy="32" r="32" />
|
|
96
|
+
</clipPath>
|
|
97
|
+
</defs>
|
|
98
|
+
<g clipPath={`url(#${id}-clip)`}>
|
|
99
|
+
<g transform={transform}>
|
|
100
|
+
<rect fill={`url(#${id}-bg)`} x={0} y={0} width={64} height={64} />
|
|
101
|
+
<circle fill={`url(#${id}-circle)`} cx={cx} cy={cy} r={45} opacity={0.7} />
|
|
102
|
+
</g>
|
|
103
|
+
{isEthereum && (
|
|
104
|
+
<g opacity="0.75" transform="scale(0.7) translate(14 14)">
|
|
105
|
+
<path
|
|
106
|
+
d="M12.8101 32.76L32.0001 44.62L51.1901 32.76L32.0001 -0.0699997L12.8101 32.76Z"
|
|
107
|
+
fill="white"
|
|
108
|
+
/>
|
|
109
|
+
<path
|
|
110
|
+
d="M12.8101 36.48L32.0001 48.43L51.1901 36.48L32.0001 63.93L12.8101 36.48Z"
|
|
111
|
+
fill="white"
|
|
112
|
+
/>
|
|
113
|
+
</g>
|
|
114
|
+
)}
|
|
115
|
+
</g>
|
|
116
|
+
</svg>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./TalismanOrb"
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./components"
|