@lukso/web-components 1.2.2 → 1.3.1
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 +23 -0
- package/README.md +4 -0
- package/dist/components/index.d.ts +5 -0
- package/dist/components/index.js +1597 -527
- package/dist/components/index.umd.cjs +159 -40
- package/dist/components/lukso-button/index.d.ts +1 -0
- package/dist/components/lukso-button/index.js +131 -127
- package/dist/components/lukso-button/index.umd.cjs +16 -16
- package/dist/components/lukso-card/index.d.ts +19 -0
- package/dist/components/lukso-card/index.js +1541 -0
- package/dist/components/lukso-card/index.umd.cjs +144 -0
- package/dist/components/lukso-navbar/index.js +2 -2
- package/dist/components/lukso-navbar/index.umd.cjs +2 -2
- package/dist/components/lukso-profile/index.d.ts +25 -0
- package/dist/components/lukso-profile/index.js +1423 -0
- package/dist/components/lukso-profile/index.umd.cjs +90 -0
- package/dist/components/lukso-sanitize/index.d.ts +12 -0
- package/dist/components/lukso-sanitize/index.js +1626 -0
- package/dist/components/lukso-sanitize/index.umd.cjs +61 -0
- package/dist/components/lukso-tag/index.d.ts +20 -0
- package/dist/components/lukso-tag/index.js +1209 -0
- package/dist/components/lukso-tag/index.umd.cjs +67 -0
- package/dist/components/lukso-test/index.js +154 -154
- package/dist/components/lukso-test/index.umd.cjs +22 -22
- package/dist/components/lukso-username/index.d.ts +34 -0
- package/dist/components/lukso-username/index.js +1256 -0
- package/dist/components/lukso-username/index.umd.cjs +75 -0
- package/dist/components/lukso-wizard/index.js +2 -2
- package/dist/components/lukso-wizard/index.umd.cjs +8 -8
- package/dist/index.js +1597 -527
- package/dist/index.umd.cjs +159 -40
- package/dist/sass/typography.scss +6 -6
- package/dist/shared/tailwind-element/index.js +1 -1
- package/dist/shared/tailwind-element/index.umd.cjs +1 -1
- package/dist/shared/tailwind-element.js +1 -1
- package/dist/shared/tailwind-element.umd.cjs +1 -1
- package/dist/shared/utils/sliceAddress.d.ts +9 -0
- package/dist/styles/main.css +6 -6
- package/package.json +30 -2
- package/src/components/index.ts +5 -0
- package/src/components/lukso-button/index.ts +4 -0
- package/src/components/lukso-button/lukso-button.stories.ts +64 -5
- package/src/components/lukso-card/index.ts +118 -0
- package/src/components/lukso-card/lukso-card.stories.ts +135 -0
- package/src/components/lukso-navbar/index.ts +1 -1
- package/src/components/lukso-navbar/lukso-navbar.stories.ts +13 -4
- package/src/components/lukso-profile/index.ts +100 -0
- package/src/components/lukso-profile/lukso-profile.stories.ts +87 -0
- package/src/components/lukso-sanitize/index.ts +28 -0
- package/src/components/lukso-sanitize/lukso-sanitize.stories.ts +26 -0
- package/src/components/lukso-tag/index.ts +68 -0
- package/src/components/lukso-tag/lukso-tag.stories.ts +107 -0
- package/src/components/lukso-username/index.ts +105 -0
- package/src/components/lukso-username/lukso-username.stories.ts +90 -0
- package/src/components/lukso-wizard/index.ts +1 -1
- package/src/components/lukso-wizard/lukso-wizard.stories.ts +6 -2
- package/src/shared/styles/typography.scss +6 -6
- package/src/shared/utils/__tests__/sliceAddress.spec.ts +15 -0
- package/src/shared/utils/sliceAddress.ts +30 -0
|
@@ -5,7 +5,7 @@ import { expect } from '@storybook/jest'
|
|
|
5
5
|
import '../lukso-button'
|
|
6
6
|
|
|
7
7
|
export default {
|
|
8
|
-
title: 'Design System/
|
|
8
|
+
title: 'Design System/Components/Button',
|
|
9
9
|
component: 'lukso-button',
|
|
10
10
|
argTypes: {
|
|
11
11
|
variant: {
|
|
@@ -22,12 +22,16 @@ export default {
|
|
|
22
22
|
control: { type: 'select' },
|
|
23
23
|
options: ['small', 'medium'],
|
|
24
24
|
},
|
|
25
|
+
isFullWidth: {
|
|
26
|
+
control: { type: 'boolean' },
|
|
27
|
+
},
|
|
25
28
|
},
|
|
26
29
|
args: {
|
|
27
30
|
text: 'Hello World',
|
|
28
31
|
disabled: false,
|
|
29
32
|
size: 'medium',
|
|
30
33
|
variant: 'primary',
|
|
34
|
+
isFullWidth: false,
|
|
31
35
|
},
|
|
32
36
|
parameters: {
|
|
33
37
|
controls: {
|
|
@@ -39,21 +43,76 @@ export default {
|
|
|
39
43
|
'linkStyles',
|
|
40
44
|
'mediumSize',
|
|
41
45
|
'smallSize',
|
|
46
|
+
'is-full-width',
|
|
42
47
|
],
|
|
43
48
|
},
|
|
44
49
|
},
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
const Template = ({ variant, disabled, text, size }) =>
|
|
48
|
-
html`<lukso-button
|
|
52
|
+
const Template = ({ variant, disabled, text, size, isFullWidth }) =>
|
|
53
|
+
html`<lukso-button
|
|
54
|
+
variant=${variant}
|
|
55
|
+
?disabled=${disabled}
|
|
56
|
+
size=${size}
|
|
57
|
+
?is-full-width=${isFullWidth}
|
|
49
58
|
>${text}</lukso-button
|
|
50
59
|
>`
|
|
51
60
|
|
|
52
|
-
export const
|
|
61
|
+
export const Primary = Template.bind({})
|
|
62
|
+
Primary.parameters = {
|
|
63
|
+
design: {
|
|
64
|
+
type: 'figma',
|
|
65
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=743%3A9778&t=AGmdbG8fXRENuU3o-4',
|
|
66
|
+
},
|
|
67
|
+
}
|
|
53
68
|
|
|
54
|
-
|
|
69
|
+
Primary.play = async ({ canvasElement }) => {
|
|
55
70
|
const canvas = within(canvasElement)
|
|
56
71
|
|
|
57
72
|
// 👇 Assert DOM structure
|
|
58
73
|
expect(canvas.getByText('Hello World')).toBeInTheDocument()
|
|
59
74
|
}
|
|
75
|
+
|
|
76
|
+
export const Secondary = Template.bind({})
|
|
77
|
+
Secondary.args = {
|
|
78
|
+
variant: 'secondary',
|
|
79
|
+
}
|
|
80
|
+
Secondary.parameters = {
|
|
81
|
+
design: {
|
|
82
|
+
type: 'figma',
|
|
83
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=743%3A9745&t=AGmdbG8fXRENuU3o-4',
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const Landing = Template.bind({})
|
|
88
|
+
Landing.args = {
|
|
89
|
+
variant: 'landing',
|
|
90
|
+
}
|
|
91
|
+
Landing.parameters = {
|
|
92
|
+
design: {
|
|
93
|
+
type: 'figma',
|
|
94
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=743%3A9912&t=AGmdbG8fXRENuU3o-4',
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export const Link = Template.bind({})
|
|
99
|
+
Link.args = {
|
|
100
|
+
variant: 'link',
|
|
101
|
+
}
|
|
102
|
+
Link.parameters = {
|
|
103
|
+
design: {
|
|
104
|
+
type: 'figma',
|
|
105
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=743%3A9822&t=AGmdbG8fXRENuU3o-4',
|
|
106
|
+
},
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export const FullWidth = Template.bind({})
|
|
110
|
+
FullWidth.args = {
|
|
111
|
+
isFullWidth: true,
|
|
112
|
+
}
|
|
113
|
+
FullWidth.parameters = {
|
|
114
|
+
design: {
|
|
115
|
+
type: 'figma',
|
|
116
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=743%3A9778&t=AGmdbG8fXRENuU3o-4',
|
|
117
|
+
},
|
|
118
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { html } from 'lit'
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
3
|
+
import { styleMap } from 'lit/directives/style-map.js'
|
|
4
|
+
|
|
5
|
+
import { TailwindElement } from '@/shared/tailwind-element'
|
|
6
|
+
import { customClassMap } from '@/shared/directives'
|
|
7
|
+
import '@/components/lukso-profile'
|
|
8
|
+
|
|
9
|
+
export type CardVariants = 'basic' | 'with-header' | 'profile'
|
|
10
|
+
|
|
11
|
+
@customElement('lukso-card')
|
|
12
|
+
export class LuksoCard extends TailwindElement {
|
|
13
|
+
@property({ type: String })
|
|
14
|
+
variant: CardVariants = 'basic'
|
|
15
|
+
|
|
16
|
+
@property({ type: String, attribute: 'background-url' })
|
|
17
|
+
backgroundUrl = ''
|
|
18
|
+
|
|
19
|
+
@property({ type: String, attribute: 'profile-url' })
|
|
20
|
+
profileUrl = ''
|
|
21
|
+
|
|
22
|
+
@property({ type: String, attribute: 'profile-address' })
|
|
23
|
+
profileAddress = ''
|
|
24
|
+
|
|
25
|
+
private defaultStyles = `rounded-3xl w-[362px] min-h-[534px] shadow-pink-drop-shadow-2xl`
|
|
26
|
+
|
|
27
|
+
basicTemplate() {
|
|
28
|
+
return html`
|
|
29
|
+
<div
|
|
30
|
+
data-testid="card"
|
|
31
|
+
class="bg-neutral-100 ${customClassMap({
|
|
32
|
+
[this.defaultStyles]: true,
|
|
33
|
+
})}"
|
|
34
|
+
>
|
|
35
|
+
<slot name="content"></slot>
|
|
36
|
+
</div>
|
|
37
|
+
`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
withHeaderTemplate() {
|
|
41
|
+
return html`
|
|
42
|
+
<div
|
|
43
|
+
data-testid="card"
|
|
44
|
+
class="bg-neutral-98 grid grid-rows-[auto,1fr] ${customClassMap({
|
|
45
|
+
[this.defaultStyles]: true,
|
|
46
|
+
})}"
|
|
47
|
+
>
|
|
48
|
+
<div>
|
|
49
|
+
<slot name="header"></slot>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="bg-neutral-100 shadow-neutral-above-shadow-1xl rounded-3xl">
|
|
52
|
+
<slot name="content"></slot>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
profileTemplate() {
|
|
59
|
+
return html`
|
|
60
|
+
<div
|
|
61
|
+
data-testid="card"
|
|
62
|
+
class="bg-neutral-98 grid grid-rows-[auto,1fr] ${customClassMap({
|
|
63
|
+
[this.defaultStyles]: true,
|
|
64
|
+
})}"
|
|
65
|
+
>
|
|
66
|
+
<div
|
|
67
|
+
style=${styleMap({
|
|
68
|
+
backgroundImage: `url(${this.backgroundUrl})`,
|
|
69
|
+
})}
|
|
70
|
+
class="min-h-[129px] -mb-6 bg-center bg-cover rounded-[24px_24px_0_0] relative"
|
|
71
|
+
>
|
|
72
|
+
<div
|
|
73
|
+
class="min-h-full min-w-full rounded-[24px_24px_0_0] bg-neutral-10 absolute opacity-10"
|
|
74
|
+
></div>
|
|
75
|
+
</div>
|
|
76
|
+
<div
|
|
77
|
+
class="bg-neutral-100 shadow-neutral-above-shadow-1xl rounded-3xl relative"
|
|
78
|
+
>
|
|
79
|
+
<lukso-profile
|
|
80
|
+
profile-url=${this.profileUrl}
|
|
81
|
+
size="large"
|
|
82
|
+
profile-address=${this.profileAddress}
|
|
83
|
+
has-identicon
|
|
84
|
+
class="absolute -top-[40px] left-[calc(50%_-_40px)] z-10"
|
|
85
|
+
></lukso-profile>
|
|
86
|
+
<div
|
|
87
|
+
class="overflow-hidden w-[153px] h-[70px] -top-[70px] relative mx-auto flex items-end justify-center"
|
|
88
|
+
>
|
|
89
|
+
<div
|
|
90
|
+
class="bg-neutral-100 rounded-[103px_103px_0_0] w-[96px] h-[48px]
|
|
91
|
+
shadow-neutral-above-shadow-1xl"
|
|
92
|
+
></div>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<slot name="content"></slot>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
`
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
render() {
|
|
102
|
+
switch (this.variant) {
|
|
103
|
+
case 'with-header':
|
|
104
|
+
return this.withHeaderTemplate()
|
|
105
|
+
case 'profile':
|
|
106
|
+
return this.profileTemplate()
|
|
107
|
+
|
|
108
|
+
default:
|
|
109
|
+
return this.basicTemplate()
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
declare global {
|
|
115
|
+
interface HTMLElementTagNameMap {
|
|
116
|
+
'lukso-card': LuksoCard
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { html } from 'lit-html'
|
|
2
|
+
import './index'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Design System/Components/Card',
|
|
6
|
+
component: 'lukso-card',
|
|
7
|
+
argTypes: {
|
|
8
|
+
variant: {
|
|
9
|
+
control: { type: 'select' },
|
|
10
|
+
options: ['basic', 'with-header', 'profile'],
|
|
11
|
+
},
|
|
12
|
+
content: { control: { type: 'text' } },
|
|
13
|
+
header: {
|
|
14
|
+
control: { type: 'text' },
|
|
15
|
+
if: { arg: 'variant', eq: 'with-header' },
|
|
16
|
+
},
|
|
17
|
+
backgroundUrl: {
|
|
18
|
+
control: { type: 'text' },
|
|
19
|
+
if: { arg: 'variant', eq: 'profile' },
|
|
20
|
+
},
|
|
21
|
+
profileUrl: {
|
|
22
|
+
control: { type: 'text' },
|
|
23
|
+
if: { arg: 'variant', eq: 'profile' },
|
|
24
|
+
},
|
|
25
|
+
profileAddress: {
|
|
26
|
+
control: { type: 'text' },
|
|
27
|
+
if: { arg: 'variant', eq: 'profile' },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
args: {
|
|
31
|
+
variant: 'basic',
|
|
32
|
+
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
|
|
33
|
+
header: 'Dolor sit amet',
|
|
34
|
+
backgroundUrl: 'images/sample-background.jpg',
|
|
35
|
+
profileUrl: 'images/sample-avatar.png',
|
|
36
|
+
profileAddress: '0x9671Db683406EE0817B1f5cB6A3b3BD111477457',
|
|
37
|
+
},
|
|
38
|
+
parameters: {
|
|
39
|
+
controls: {
|
|
40
|
+
exclude: [
|
|
41
|
+
'defaultStyles',
|
|
42
|
+
'background-url',
|
|
43
|
+
'profile-url',
|
|
44
|
+
'profile-address',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const DefaultTemplate = ({ variant, content, header }) =>
|
|
51
|
+
html`
|
|
52
|
+
<lukso-card variant=${variant}>
|
|
53
|
+
<div slot="header" class="p-6">${header}</div>
|
|
54
|
+
<div slot="content" class="p-6">${content}</div>
|
|
55
|
+
</lukso-card>
|
|
56
|
+
`
|
|
57
|
+
|
|
58
|
+
const CustomHeaderTemplate = ({ variant, content, header }) =>
|
|
59
|
+
html`
|
|
60
|
+
<lukso-card variant=${variant}>
|
|
61
|
+
<div slot="header" class="p-6 relative overflow-hidden min-h-[200px]">
|
|
62
|
+
<div
|
|
63
|
+
class="w-[876px] h-[200px] -left-[257px] top-[72px] bg-neutral-95 rounded-[50%] absolute"
|
|
64
|
+
></div>
|
|
65
|
+
${header}
|
|
66
|
+
</div>
|
|
67
|
+
<div slot="content" class="p-6">${content}</div>
|
|
68
|
+
</lukso-card>
|
|
69
|
+
`
|
|
70
|
+
|
|
71
|
+
const ProfileTemplate = ({
|
|
72
|
+
variant,
|
|
73
|
+
content,
|
|
74
|
+
backgroundUrl,
|
|
75
|
+
profileUrl,
|
|
76
|
+
profileAddress,
|
|
77
|
+
}) =>
|
|
78
|
+
html`
|
|
79
|
+
<lukso-card
|
|
80
|
+
variant=${variant}
|
|
81
|
+
background-url=${backgroundUrl}
|
|
82
|
+
profile-url=${profileUrl}
|
|
83
|
+
profile-address=${profileAddress}
|
|
84
|
+
>
|
|
85
|
+
<div slot="content" class="p-6">${content}</div>
|
|
86
|
+
</lukso-card>
|
|
87
|
+
`
|
|
88
|
+
|
|
89
|
+
export const DefaultCard = DefaultTemplate.bind({})
|
|
90
|
+
DefaultCard.parameters = {
|
|
91
|
+
design: {
|
|
92
|
+
type: 'figma',
|
|
93
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=1332%3A18025&t=AGmdbG8fXRENuU3o-4',
|
|
94
|
+
},
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const CardWithHeader = DefaultTemplate.bind({})
|
|
98
|
+
CardWithHeader.args = {
|
|
99
|
+
variant: 'with-header',
|
|
100
|
+
}
|
|
101
|
+
CardWithHeader.parameters = {
|
|
102
|
+
design: {
|
|
103
|
+
type: 'figma',
|
|
104
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=1332%3A18028&t=AGmdbG8fXRENuU3o-4',
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export const CardWithCustomHeader = CustomHeaderTemplate.bind({})
|
|
109
|
+
CardWithCustomHeader.args = {
|
|
110
|
+
variant: 'with-header',
|
|
111
|
+
}
|
|
112
|
+
CardWithCustomHeader.parameters = {
|
|
113
|
+
design: {
|
|
114
|
+
type: 'figma',
|
|
115
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=1332%3A18026&t=AGmdbG8fXRENuU3o-4',
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const ProfileCard = ProfileTemplate.bind({})
|
|
120
|
+
ProfileCard.args = {
|
|
121
|
+
variant: 'profile',
|
|
122
|
+
parameters: {
|
|
123
|
+
design: {
|
|
124
|
+
type: 'figma',
|
|
125
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=1096%3A14641&t=AGmdbG8fXRENuU3o-4',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
ProfileCard.parameters = {
|
|
131
|
+
design: {
|
|
132
|
+
type: 'figma',
|
|
133
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=1332%3A18027&t=AGmdbG8fXRENuU3o-4',
|
|
134
|
+
},
|
|
135
|
+
}
|
|
@@ -19,7 +19,7 @@ export class LuksoNavbar extends TailwindElement {
|
|
|
19
19
|
|
|
20
20
|
private centerStyles = `justify-center`
|
|
21
21
|
|
|
22
|
-
private stickyStyles = `sticky top-0 z-
|
|
22
|
+
private stickyStyles = `sticky top-0 z-[1000]`
|
|
23
23
|
|
|
24
24
|
_onBrandClick() {
|
|
25
25
|
const event = new CustomEvent('click-brand', {
|
|
@@ -2,7 +2,7 @@ import { html } from 'lit-html'
|
|
|
2
2
|
import './index'
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
|
-
title: 'Design System/
|
|
5
|
+
title: 'Design System/Components/Navbar',
|
|
6
6
|
component: 'lukso-navbar',
|
|
7
7
|
argTypes: {
|
|
8
8
|
title: {
|
|
@@ -31,14 +31,23 @@ PROFILES`,
|
|
|
31
31
|
'is-sticky',
|
|
32
32
|
],
|
|
33
33
|
},
|
|
34
|
+
design: {
|
|
35
|
+
type: 'figma',
|
|
36
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=1097%3A14669&t=AGmdbG8fXRENuU3o-4',
|
|
37
|
+
},
|
|
34
38
|
},
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
const Template = ({ title, isCenter, isSticky }) =>
|
|
38
42
|
html`<lukso-navbar
|
|
39
43
|
title=${title}
|
|
40
|
-
?is-center
|
|
41
|
-
?is-sticky
|
|
44
|
+
?is-center=${isCenter}
|
|
45
|
+
?is-sticky=${isSticky}
|
|
42
46
|
></lukso-navbar>`
|
|
43
47
|
|
|
44
|
-
export const
|
|
48
|
+
export const DefaultNavbar = Template.bind({})
|
|
49
|
+
|
|
50
|
+
export const CenterNavbar = Template.bind({})
|
|
51
|
+
CenterNavbar.args = {
|
|
52
|
+
isCenter: true,
|
|
53
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { html } from 'lit'
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
3
|
+
import { styleMap } from 'lit/directives/style-map.js'
|
|
4
|
+
import makeBlockie from 'ethereum-blockies-base64'
|
|
5
|
+
|
|
6
|
+
import { TailwindElement } from '@/shared/tailwind-element'
|
|
7
|
+
|
|
8
|
+
export type ProfileSize = 'x-small' | 'small' | 'medium' | 'large' | 'x-large'
|
|
9
|
+
type SizeDef = { identiconSize?: number; profileImageSize: number }
|
|
10
|
+
|
|
11
|
+
@customElement('lukso-profile')
|
|
12
|
+
export class LuksoProfile extends TailwindElement {
|
|
13
|
+
@property({ type: String, attribute: 'profile-url' })
|
|
14
|
+
profileUrl = ''
|
|
15
|
+
|
|
16
|
+
@property({ type: String, attribute: 'profile-address' })
|
|
17
|
+
profileAddress = ''
|
|
18
|
+
|
|
19
|
+
@property({ type: Boolean, attribute: 'has-identicon' })
|
|
20
|
+
hasIdenticon = false
|
|
21
|
+
|
|
22
|
+
@property({ type: String })
|
|
23
|
+
size: ProfileSize = 'large'
|
|
24
|
+
|
|
25
|
+
sizes: Record<ProfileSize, SizeDef> = {
|
|
26
|
+
'x-small': {
|
|
27
|
+
identiconSize: undefined,
|
|
28
|
+
profileImageSize: 24,
|
|
29
|
+
},
|
|
30
|
+
small: {
|
|
31
|
+
identiconSize: 16,
|
|
32
|
+
profileImageSize: 40,
|
|
33
|
+
},
|
|
34
|
+
medium: {
|
|
35
|
+
identiconSize: 20,
|
|
36
|
+
profileImageSize: 56,
|
|
37
|
+
},
|
|
38
|
+
large: {
|
|
39
|
+
identiconSize: 24,
|
|
40
|
+
profileImageSize: 80,
|
|
41
|
+
},
|
|
42
|
+
'x-large': {
|
|
43
|
+
identiconSize: 28,
|
|
44
|
+
profileImageSize: 96,
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private profileImageSize = () => this.sizes[this.size].profileImageSize
|
|
49
|
+
private identiconSize = () => this.sizes[this.size].identiconSize
|
|
50
|
+
private defaultProfileUrl = 'assets/images/profile-default.png'
|
|
51
|
+
|
|
52
|
+
private identicon = () => {
|
|
53
|
+
return this.hasIdenticon && this.profileAddress && this.identiconSize()
|
|
54
|
+
? makeBlockie(this.profileAddress)
|
|
55
|
+
: ''
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
render() {
|
|
59
|
+
return html`
|
|
60
|
+
<div
|
|
61
|
+
data-testid="profile"
|
|
62
|
+
style=${styleMap({
|
|
63
|
+
backgroundImage: `url(${this.defaultProfileUrl})`,
|
|
64
|
+
width: `${this.profileImageSize()}px`,
|
|
65
|
+
height: `${this.profileImageSize()}px`,
|
|
66
|
+
})}
|
|
67
|
+
class="rounded-full bg-[50%] bg-no-repeat bg-cover bg-neutral-90
|
|
68
|
+
outline outline-2 outline-neutral-100"
|
|
69
|
+
>
|
|
70
|
+
<div
|
|
71
|
+
style=${styleMap({
|
|
72
|
+
backgroundImage: `url(${this.profileUrl})`,
|
|
73
|
+
width: `${this.profileImageSize()}px`,
|
|
74
|
+
height: `${this.profileImageSize()}px`,
|
|
75
|
+
})}
|
|
76
|
+
class="rounded-full bg-[50%] bg-no-repeat bg-cover relative
|
|
77
|
+
"
|
|
78
|
+
>
|
|
79
|
+
${this.identicon()
|
|
80
|
+
? html`<img
|
|
81
|
+
src=${this.identicon()}
|
|
82
|
+
class="absolute shadow-shadow-1xl rounded-full
|
|
83
|
+
outline outline-2 outline-neutral-100 right-0 bottom-0"
|
|
84
|
+
style=${styleMap({
|
|
85
|
+
width: `${this.identiconSize()}px`,
|
|
86
|
+
height: `${this.identiconSize()}px`,
|
|
87
|
+
})}
|
|
88
|
+
/>`
|
|
89
|
+
: ''}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
`
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declare global {
|
|
97
|
+
interface HTMLElementTagNameMap {
|
|
98
|
+
'lukso-profile': LuksoProfile
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { html } from 'lit-html'
|
|
2
|
+
import './index'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Design System/Components/Profile',
|
|
6
|
+
component: 'lukso-profile',
|
|
7
|
+
argTypes: {
|
|
8
|
+
profileUrl: {
|
|
9
|
+
control: { type: 'text' },
|
|
10
|
+
},
|
|
11
|
+
size: {
|
|
12
|
+
control: {
|
|
13
|
+
type: 'select',
|
|
14
|
+
},
|
|
15
|
+
options: ['x-small', 'small', 'medium', 'large', 'x-large'],
|
|
16
|
+
},
|
|
17
|
+
profileAddress: {
|
|
18
|
+
control: { type: 'text' },
|
|
19
|
+
},
|
|
20
|
+
hasIdenticon: {
|
|
21
|
+
control: { type: 'boolean' },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
args: {
|
|
25
|
+
profileUrl: 'images/sample-avatar.png',
|
|
26
|
+
size: 'x-large',
|
|
27
|
+
profileAddress: '0x9671Db683406EE0817B1f5cB6A3b3BD111477457',
|
|
28
|
+
hasIdenticon: true,
|
|
29
|
+
},
|
|
30
|
+
parameters: {
|
|
31
|
+
controls: {
|
|
32
|
+
exclude: [
|
|
33
|
+
'sizes',
|
|
34
|
+
'profile-url',
|
|
35
|
+
'profileImageSize',
|
|
36
|
+
'identiconSize',
|
|
37
|
+
'identicon',
|
|
38
|
+
'profile-address',
|
|
39
|
+
'has-identicon',
|
|
40
|
+
'defaultProfileUrl',
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
design: {
|
|
44
|
+
type: 'figma',
|
|
45
|
+
url: 'https://www.figma.com/file/NFCh20xAq3Jg2g8A0DNC9I/UI-Library?node-id=378%3A3395&t=AGmdbG8fXRENuU3o-4',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const Template = ({ profileUrl, size, profileAddress, hasIdenticon }) =>
|
|
51
|
+
html`<lukso-profile
|
|
52
|
+
profile-url=${profileUrl}
|
|
53
|
+
size=${size}
|
|
54
|
+
profile-address=${profileAddress}
|
|
55
|
+
?has-identicon=${hasIdenticon}
|
|
56
|
+
></lukso-profile>`
|
|
57
|
+
|
|
58
|
+
export const XLarge = Template.bind({})
|
|
59
|
+
XLarge.args = {
|
|
60
|
+
size: 'x-large',
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const Large = Template.bind({})
|
|
64
|
+
Large.args = {
|
|
65
|
+
size: 'large',
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const Medium = Template.bind({})
|
|
69
|
+
Medium.args = {
|
|
70
|
+
size: 'medium',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const Small = Template.bind({})
|
|
74
|
+
Small.args = {
|
|
75
|
+
size: 'small',
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const XSmall = Template.bind({})
|
|
79
|
+
XSmall.args = {
|
|
80
|
+
size: 'x-small',
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export const Unknown = Template.bind({})
|
|
84
|
+
Unknown.args = {
|
|
85
|
+
profileUrl: '',
|
|
86
|
+
hasIdenticon: false,
|
|
87
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { html } from 'lit'
|
|
2
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
3
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js'
|
|
4
|
+
import DOMPurify from 'dompurify'
|
|
5
|
+
|
|
6
|
+
import { TailwindElement } from '@/shared/tailwind-element'
|
|
7
|
+
|
|
8
|
+
@customElement('lukso-sanitize')
|
|
9
|
+
export class LuksoSanitize extends TailwindElement {
|
|
10
|
+
@property({ type: String, attribute: 'html-content' })
|
|
11
|
+
htmlContent = ''
|
|
12
|
+
|
|
13
|
+
sanitize = () => {
|
|
14
|
+
return DOMPurify.sanitize(this.htmlContent)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
render() {
|
|
18
|
+
// in order to show HTML we need to use unsafeHTML directive.
|
|
19
|
+
// This is safe since we already sanitized content
|
|
20
|
+
return html`${unsafeHTML(this.sanitize())}`
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare global {
|
|
25
|
+
interface HTMLElementTagNameMap {
|
|
26
|
+
'lukso-sanitize': LuksoSanitize
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { html } from 'lit-html'
|
|
2
|
+
import './index'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Design System/Components/Sanitize',
|
|
6
|
+
component: 'lukso-sanitize',
|
|
7
|
+
argTypes: {
|
|
8
|
+
htmlContent: {
|
|
9
|
+
control: { type: 'text' },
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
args: {
|
|
13
|
+
htmlContent:
|
|
14
|
+
'This is sample text containing html tags like <b>bold</b> or <a class="text-sky-64" href="/">link</a>.',
|
|
15
|
+
},
|
|
16
|
+
parameters: {
|
|
17
|
+
controls: {
|
|
18
|
+
exclude: ['sanitize', 'html-content'],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const Template = ({ htmlContent }) =>
|
|
24
|
+
html`<lukso-sanitize html-content=${htmlContent}></lukso-sanitize>`
|
|
25
|
+
|
|
26
|
+
export const Sanitize = Template.bind({})
|