@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.
Files changed (59) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +4 -0
  3. package/dist/components/index.d.ts +5 -0
  4. package/dist/components/index.js +1597 -527
  5. package/dist/components/index.umd.cjs +159 -40
  6. package/dist/components/lukso-button/index.d.ts +1 -0
  7. package/dist/components/lukso-button/index.js +131 -127
  8. package/dist/components/lukso-button/index.umd.cjs +16 -16
  9. package/dist/components/lukso-card/index.d.ts +19 -0
  10. package/dist/components/lukso-card/index.js +1541 -0
  11. package/dist/components/lukso-card/index.umd.cjs +144 -0
  12. package/dist/components/lukso-navbar/index.js +2 -2
  13. package/dist/components/lukso-navbar/index.umd.cjs +2 -2
  14. package/dist/components/lukso-profile/index.d.ts +25 -0
  15. package/dist/components/lukso-profile/index.js +1423 -0
  16. package/dist/components/lukso-profile/index.umd.cjs +90 -0
  17. package/dist/components/lukso-sanitize/index.d.ts +12 -0
  18. package/dist/components/lukso-sanitize/index.js +1626 -0
  19. package/dist/components/lukso-sanitize/index.umd.cjs +61 -0
  20. package/dist/components/lukso-tag/index.d.ts +20 -0
  21. package/dist/components/lukso-tag/index.js +1209 -0
  22. package/dist/components/lukso-tag/index.umd.cjs +67 -0
  23. package/dist/components/lukso-test/index.js +154 -154
  24. package/dist/components/lukso-test/index.umd.cjs +22 -22
  25. package/dist/components/lukso-username/index.d.ts +34 -0
  26. package/dist/components/lukso-username/index.js +1256 -0
  27. package/dist/components/lukso-username/index.umd.cjs +75 -0
  28. package/dist/components/lukso-wizard/index.js +2 -2
  29. package/dist/components/lukso-wizard/index.umd.cjs +8 -8
  30. package/dist/index.js +1597 -527
  31. package/dist/index.umd.cjs +159 -40
  32. package/dist/sass/typography.scss +6 -6
  33. package/dist/shared/tailwind-element/index.js +1 -1
  34. package/dist/shared/tailwind-element/index.umd.cjs +1 -1
  35. package/dist/shared/tailwind-element.js +1 -1
  36. package/dist/shared/tailwind-element.umd.cjs +1 -1
  37. package/dist/shared/utils/sliceAddress.d.ts +9 -0
  38. package/dist/styles/main.css +6 -6
  39. package/package.json +30 -2
  40. package/src/components/index.ts +5 -0
  41. package/src/components/lukso-button/index.ts +4 -0
  42. package/src/components/lukso-button/lukso-button.stories.ts +64 -5
  43. package/src/components/lukso-card/index.ts +118 -0
  44. package/src/components/lukso-card/lukso-card.stories.ts +135 -0
  45. package/src/components/lukso-navbar/index.ts +1 -1
  46. package/src/components/lukso-navbar/lukso-navbar.stories.ts +13 -4
  47. package/src/components/lukso-profile/index.ts +100 -0
  48. package/src/components/lukso-profile/lukso-profile.stories.ts +87 -0
  49. package/src/components/lukso-sanitize/index.ts +28 -0
  50. package/src/components/lukso-sanitize/lukso-sanitize.stories.ts +26 -0
  51. package/src/components/lukso-tag/index.ts +68 -0
  52. package/src/components/lukso-tag/lukso-tag.stories.ts +107 -0
  53. package/src/components/lukso-username/index.ts +105 -0
  54. package/src/components/lukso-username/lukso-username.stories.ts +90 -0
  55. package/src/components/lukso-wizard/index.ts +1 -1
  56. package/src/components/lukso-wizard/lukso-wizard.stories.ts +6 -2
  57. package/src/shared/styles/typography.scss +6 -6
  58. package/src/shared/utils/__tests__/sliceAddress.spec.ts +15 -0
  59. 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/Atoms/Button',
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 variant=${variant} ?disabled=${disabled} size=${size}
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 Button = Template.bind({})
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
- Button.play = async ({ canvasElement }) => {
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-10`
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/Atoms/Navbar',
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="${isCenter}"
41
- ?is-sticky="${isSticky}"
44
+ ?is-center=${isCenter}
45
+ ?is-sticky=${isSticky}
42
46
  ></lukso-navbar>`
43
47
 
44
- export const Navbar = Template.bind({})
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({})