diff --git a/packages/vue-identicon/src/Identicon.ts b/packages/vue-identicon/src/Identicon.ts index 72d159fd..bf39aff6 100644 --- a/packages/vue-identicon/src/Identicon.ts +++ b/packages/vue-identicon/src/Identicon.ts @@ -3,7 +3,7 @@ import type { Prefix } from '@polkadot/util-crypto/address/types'; -import Vue from 'vue'; +import Vue, { VNode } from 'vue'; import { isHex, isU8a, u8aToHex } from '@polkadot/util'; import { decodeAddress, encodeAddress } from '@polkadot/util-crypto'; @@ -18,6 +18,7 @@ interface Account { interface Data { address: string; iconSize: number; + isAlternative: boolean; publicKey: string; type: 'beachball' | 'empty' | 'jdenticon' | 'polkadot' | 'substrate'; } @@ -59,6 +60,7 @@ export const Identicon = Vue.extend({ return { address: '', iconSize: DEFAULT_SIZE, + isAlternative: false, publicKey: '0x', type: 'empty' }; @@ -78,22 +80,21 @@ export const Identicon = Vue.extend({ } }, props: ['prefix', 'isAlternative', 'size', 'theme', 'value'], - // FIXME These nested divs are not correct, would like a different way - // here so we don't create a div wrapped for the div wrapper of the icon - template: ` -
- -
-
- -
-
- -
-
- -
- `, + render (h): VNode { + const { address, iconSize, isAlternative, publicKey, type } = this.$data as Data; + + if (type === 'empty') { + return h('Empty', { attrs: { key: address, size: iconSize } }, []); + } else if (type === 'jdenticon') { + return h('Jdenticon', { attrs: { key: address, publicKey, size: iconSize } }, []); + } else { + // handles: beachball and polkadot + // TODO: substrate + const cmp = type.charAt(0).toUpperCase() + type.slice(1); + + return h(cmp, { attrs: { address, isAlternative, key: address, size: iconSize } }, []); + } + }, watch: { value: function (): void { this.recodeAddress(); diff --git a/packages/vue-identicon/src/icons/Beachball.ts b/packages/vue-identicon/src/icons/Beachball.ts index 5c1bcf57..5aa4e5f7 100644 --- a/packages/vue-identicon/src/icons/Beachball.ts +++ b/packages/vue-identicon/src/icons/Beachball.ts @@ -1,14 +1,14 @@ // Copyright 2017-2022 @polkadot/vue-identicon authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { Options } from '@polkadot/ui-shared/icons/types'; - -import Vue from 'vue'; +import Vue, { VNode } from 'vue'; import { beachballIcon } from '@polkadot/ui-shared'; -interface Data { - html: string; +type propsType = { + address: string; + size: number; + isAlternative: boolean; } /** @@ -16,21 +16,12 @@ interface Data { * @description The Beachball identicon */ export const Beachball = Vue.extend({ - created: function (): void { - this.createHtml(); - }, - data: function (): Data { - return { - // eslint-disable-next-line quotes - html: `
` - }; - }, - methods: { - createHtml: function (): void { - this.html = beachballIcon(this.address as string, this.size as Options).outerHTML; - } - }, - props: ['address', 'size'], + props: ['address', 'size', 'isAlternative'], // eslint-disable-next-line quotes - template: `
` + render (h): VNode { + const { address, isAlternative, size } = this.$props as propsType; + const bb = beachballIcon(address, { isAlternative, size }); + + return h(Vue.component('VCBeachball', { template: bb.outerHTML })); + } }); diff --git a/packages/vue-identicon/src/icons/Jdenticon.ts b/packages/vue-identicon/src/icons/Jdenticon.ts index 0690cdb2..1e109a05 100644 --- a/packages/vue-identicon/src/icons/Jdenticon.ts +++ b/packages/vue-identicon/src/icons/Jdenticon.ts @@ -2,10 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 import * as jdenticon from 'jdenticon'; -import Vue from 'vue'; +import Vue, { VNode } from 'vue'; -interface Data { - svgHtml: string; +type propsType = { + publicKey: string, + size: number } /** @@ -13,21 +14,12 @@ interface Data { * @description The substrate default via Jdenticon */ export const Jdenticon = Vue.extend({ - created: function (): void { - this.createSvgHtml(); - }, - data: function (): Data { - return { - // eslint-disable-next-line quotes - svgHtml: `` - }; - }, - methods: { - createSvgHtml: function (): void { - this.svgHtml = jdenticon.toSvg((this.publicKey as string).substr(2), this.size as number); - } - }, props: ['publicKey', 'size'], // eslint-disable-next-line quotes - template: `
` + render (h): VNode { + const { publicKey, size } = this.$props as propsType; + const cmp = Vue.component('CJdenticon', { template: jdenticon.toSvg(publicKey.substring(2), size) }); + + return h(cmp); + } }); diff --git a/packages/vue-identicon/src/icons/Polkadot.ts b/packages/vue-identicon/src/icons/Polkadot.ts index 233df52b..04ed02e4 100644 --- a/packages/vue-identicon/src/icons/Polkadot.ts +++ b/packages/vue-identicon/src/icons/Polkadot.ts @@ -1,17 +1,14 @@ // Copyright 2017-2022 @polkadot/vue-identicon authors & contributors // SPDX-License-Identifier: Apache-2.0 -import Vue from 'vue'; +import Vue, { VNode } from 'vue'; import { polkadotIcon } from '@polkadot/ui-shared'; -interface Data { - svgHtml: string; -} - -interface This { +type propsType = { address: string; - isAlternative?: boolean; + isAlternative: boolean; + size: number; } /** @@ -19,25 +16,20 @@ interface This { * @description The Polkadot default identicon */ export const Polkadot = Vue.extend({ - created: function (): void { - this.createSvgHtml(); - }, - data: function (): Data { - return { - // eslint-disable-next-line quotes - svgHtml: `` - }; - }, - methods: { - createSvgHtml: function (): void { - const circles = polkadotIcon(this.address as string, { isAlternative: (this as This).isAlternative || false }).map(({ cx, cy, fill, r }) => - `` - ).join(''); - - this.svgHtml = `${circles}`; - } - }, props: ['address', 'isAlternative', 'size'], // eslint-disable-next-line quotes - template: `
` + render (h): VNode { + const { address, isAlternative, size } = this.$props as propsType; + const circles = polkadotIcon(address, { + isAlternative: isAlternative || false + }).map(({ cx, + cy, + fill, + r }) => { + return h('circle', { attrs: { cx, cy, fill, r } }, []); + } + ); + + return h('svg', { attrs: { height: size, viewBox: '0 0 64 64', width: size } }, circles); + } });