diff --git a/packages/dapp-kit-ui/index.html b/packages/dapp-kit-ui/index.html index 4fd8dca5..c2efc80f 100644 --- a/packages/dapp-kit-ui/index.html +++ b/packages/dapp-kit-ui/index.html @@ -8,8 +8,8 @@ - + > diff --git a/packages/dapp-kit-ui/index.js b/packages/dapp-kit-ui/index.js index b5db21c7..e3fdac14 100644 --- a/packages/dapp-kit-ui/index.js +++ b/packages/dapp-kit-ui/index.js @@ -1,6 +1,6 @@ // eslint-disable-next-line eslint-comments/disable-enable-pair /* eslint-disable no-undef */ -import { DAppKit } from './dist'; +import { DAppKitUI } from './dist'; const walletConnectOptions = { projectId: 'a0b855ceaf109dbc8426479a4c3d38d8', @@ -20,4 +20,4 @@ const vechainWalletKitOptions = { usePersistence: true, }; -DAppKit.configure(vechainWalletKitOptions); +DAppKitUI.configure(vechainWalletKitOptions); diff --git a/packages/dapp-kit-ui/package.json b/packages/dapp-kit-ui/package.json index a1a82d5d..002a0f08 100644 --- a/packages/dapp-kit-ui/package.json +++ b/packages/dapp-kit-ui/package.json @@ -28,6 +28,7 @@ "lint": "tsc --noEmit && eslint src --ext .js,.jsx,.ts,.tsx", "purge": "yarn clean && rm -rf node_modules", "test": "vitest run --coverage", + "test:dev": "vitest run ", "watch": "tsup --watch" }, "dependencies": { diff --git a/packages/dapp-kit-ui/src/assets/icons/index.ts b/packages/dapp-kit-ui/src/assets/icons/index.ts index da2a86cc..2ed8f481 100644 --- a/packages/dapp-kit-ui/src/assets/icons/index.ts +++ b/packages/dapp-kit-ui/src/assets/icons/index.ts @@ -2,3 +2,4 @@ export * from './close'; export * from './chevron-left'; export * from './copy'; export * from './check'; +export * from './disconnect'; diff --git a/packages/dapp-kit-ui/src/assets/index.ts b/packages/dapp-kit-ui/src/assets/index.ts index 3ee79948..817aa2d3 100644 --- a/packages/dapp-kit-ui/src/assets/index.ts +++ b/packages/dapp-kit-ui/src/assets/index.ts @@ -1,2 +1,3 @@ export * from './icons'; export * from './images'; +export * from './styles'; diff --git a/packages/dapp-kit-ui/src/assets/styles/button.ts b/packages/dapp-kit-ui/src/assets/styles/button.ts new file mode 100644 index 00000000..e18db360 --- /dev/null +++ b/packages/dapp-kit-ui/src/assets/styles/button.ts @@ -0,0 +1,78 @@ +import { css } from 'lit'; +import { Colors } from '../../constants/colors'; + +export const buttonStyle = css` + button { + font-family: 'Inter', sans-serif; + cursor: pointer; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + border: none; + border-radius: 12px; + padding: 12px; + font-size: 15px; + font-weight: 500; + width: 100%; + gap: 10px; + } + + button.LIGHT { + background-color: ${Colors.XXLightGrey}; + color: ${Colors.LightBlack}; + } + button.LIGHT:hover { + background-color: ${Colors.XLightGrey}; + } + button.LIGHT:active { + background-color: ${Colors.LightGrey}; + } + + button.DARK { + background-color: ${Colors.XXDarkGrey}; + color: ${Colors.XXLightGrey}; + } + button.DARK:hover { + background-color: ${Colors.XDarkGrey}; + } + button.DARK:active { + background-color: ${Colors.DarkGrey}; + } +`; + +export const triggerButtonStyle = css` + button { + font-family: 'Inter', sans-serif; + cursor: pointer; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + border: none; + border-radius: 12px; + padding: 12px; + } + + button.LIGHT { + background-color: ${Colors.XXLightGrey}; + color: ${Colors.LightBlack}; + } + button.LIGHT:hover { + background-color: ${Colors.XLightGrey}; + } + button.LIGHT:active { + background-color: ${Colors.LightGrey}; + } + + button.DARK { + background-color: ${Colors.LightBlack}; + color: ${Colors.XXLightGrey}; + } + button.DARK:hover { + background-color: ${Colors.XLightBlack}; + } + button.DARK:active { + background-color: ${Colors.XXLightBlack}; + } +`; diff --git a/packages/dapp-kit-ui/src/assets/styles/index.ts b/packages/dapp-kit-ui/src/assets/styles/index.ts new file mode 100644 index 00000000..eaf5eea7 --- /dev/null +++ b/packages/dapp-kit-ui/src/assets/styles/index.ts @@ -0,0 +1 @@ +export * from './button'; diff --git a/packages/dapp-kit-ui/src/components/address-badge.ts b/packages/dapp-kit-ui/src/components/address-badge.ts deleted file mode 100644 index 0ebc85ef..00000000 --- a/packages/dapp-kit-ui/src/components/address-badge.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { css, html, LitElement, type TemplateResult } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; -import { Colors, type ThemeMode } from '../constants'; -import { friendlyAddress, getPicassoImage } from '../utils/account'; - -@customElement('vwk-connected-address-badge') -export class AddressBadge extends LitElement { - static override styles = css` - /* Style for the badge */ - - .wallet-badge { - display: flex; - width: fit-content; - flex-direction: row; - align-items: center; - justify-content: center; - padding: 8px; - background-color: #4caf50; - color: #fff; - border-radius: 12px; - } - - .wallet-badge:hover { - opacity: 0.9; - cursor: pointer; - } - - .wallet-badge.DARK { - background-color: ${Colors.Dark}; - color: ${Colors.LightGrey}; - } - - .wallet-badge.LIGHT { - background-color: ${Colors.LightGrey}; - color: ${Colors.Dark}; - } - - /* Style for the wallet address */ - - .wallet-address { - font-size: 14px; - margin-left: 8px; - font-family: monospace; - } - - .address-icon { - width: 23px; - height: 23px; - margin-right: 4px; - border-radius: 50%; - } - `; - - @property() - address?: string; - - @property() - mode: ThemeMode = 'DARK'; - - @property({ type: Function }) - onClick? = undefined; - - render(): TemplateResult { - return html`
- - ${friendlyAddress(this.address ?? '')} -
`; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'vwk-connected-address-badge': AddressBadge; - } -} diff --git a/packages/dapp-kit-ui/src/components/address-badge-with-modal.ts b/packages/dapp-kit-ui/src/components/address-button-with-modal.ts similarity index 83% rename from packages/dapp-kit-ui/src/components/address-badge-with-modal.ts rename to packages/dapp-kit-ui/src/components/address-button-with-modal.ts index 0646046d..cbccb3e5 100644 --- a/packages/dapp-kit-ui/src/components/address-badge-with-modal.ts +++ b/packages/dapp-kit-ui/src/components/address-button-with-modal.ts @@ -3,8 +3,8 @@ import { html, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import type { Theme, ThemeMode } from '../constants'; -@customElement('vwk-connected-address-badge-with-modal') -export class AddressBadgeWithModal extends LitElement { +@customElement('vwk-connected-address-button-with-modal') +export class AddressButtonWithModal extends LitElement { @property({ type: String }) mode: ThemeMode = 'LIGHT'; @@ -24,12 +24,12 @@ export class AddressBadgeWithModal extends LitElement { return html`
- + > + + ${friendlyAddress(this.address ?? '')} + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'vwk-connected-address-button': AddressButton; + } +} diff --git a/packages/dapp-kit-ui/src/components/address-modal.ts b/packages/dapp-kit-ui/src/components/address-modal.ts index f8fa8377..79b000f8 100644 --- a/packages/dapp-kit-ui/src/components/address-modal.ts +++ b/packages/dapp-kit-ui/src/components/address-modal.ts @@ -3,115 +3,114 @@ import { css, html, LitElement, nothing } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import type { SourceInfo } from '../constants'; import { Colors } from '../constants'; -import { DarkCloseSvg, LightCloseSvg } from '../assets'; -import { dispatchCustomEvent, subscribeToCustomEvent } from '../utils'; -import type { Theme, ThemeMode } from '../constants/theme'; -import { friendlyAddress, getPicassoImage } from '../utils/account'; import { + DarkCloseSvg, + LightCloseSvg, + DarkCopySvg, + LightCopySvg, + CheckSvg, DarkDisconnectSvg, LightDisconnectSvg, -} from '../assets/icons/disconnect'; + buttonStyle, +} from '../assets'; +import { dispatchCustomEvent, subscribeToCustomEvent } from '../utils'; +import type { Theme, ThemeMode } from '../constants/theme'; +import { friendlyAddress, getPicassoImage } from '../utils/account'; @customElement('vwk-connected-address-modal') export class AddressModal extends LitElement { - static override styles = css` - .modal-container { - display: flex; - flex-direction: column; - gap: 15px; - padding: 20px; - transition: width 5s, height 4s; - font-family: 'Inter', sans-serif; - } - - .modal-header { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - padding-bottom: 10px; - font-family: 'Inter', sans-serif; - } - - .modal-body { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 20px; - transition: width 2s, height 4s; - } - - .modal-footer { - display: flex; - justify-content: center; - align-items: center; - padding-top: 10px; - font-family: 'Inter', sans-serif; - } - - .close-icon { - position: absolute; - right: 20px; - } - - .icon { - cursor: pointer; - width: 25px; - height: 25px; - } - - .icon.LIGHT:hover { - background-color: ${Colors.LightGrey}; - } - - .icon.DARK:hover { - background-color: ${Colors.DarkGrey}; - } - - button { - cursor: pointer; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - gap: 10px; - border: none; - border-radius: 12px; - padding: 8px 14px; - font-size: 14px; - font-family: 'Inter', sans-serif; - } - - button:hover { - opacity: 0.9; - } - - button.LIGHT { - background-color: ${Colors.LightGrey}; - color: ${Colors.Dark}; - } - - button.DARK { - background-color: ${Colors.DarkGrey}; - color: ${Colors.LightGrey}; - } - - .address-icon { - width: 30%; - margin-right: 4px; - border-radius: 50%; - } - - .title { - font-size: 20px; - font-weight: 600; - } - - .wallet-address { - font-size: 19px; - } - `; + static override styles = [ + buttonStyle, + css` + .modal-container { + display: flex; + flex-direction: column; + gap: 15px; + padding: 20px; + transition: width 5s, height 4s; + font-family: 'Inter', sans-serif; + } + + .modal-header { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding-bottom: 20px; + font-family: 'Inter', sans-serif; + } + + .modal-body { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 40px; + transition: width 2s, height 4s; + } + + .modal-footer { + display: flex; + justify-content: center; + align-items: center; + padding-top: 20px; + font-family: 'Inter', sans-serif; + } + + .close-icon { + position: absolute; + right: 20px; + } + + .icon { + cursor: pointer; + width: 25px; + height: 25px; + padding: 5px; + border-radius: 50%; + } + + .icon.LIGHT:hover { + background-color: ${Colors.XXLightGrey}; + } + + .icon.DARK:hover { + background-color: ${Colors.XXDarkGrey}; + } + + .address-icon { + width: 30%; + margin-right: 4px; + border-radius: 50%; + } + + .disconnect-icon { + width: 18px; + height: 18px; + } + + .title { + font-family: 'Inter', sans-serif; + font-weight: 500; + } + + .wallet-address { + font-size: 18px; + font-weight: 500; + font-family: 'Inter', sans-serif; + display: flex; + flex-direction: row; + justify-content: center; + } + + .copy-icon { + cursor: pointer; + width: 20px; + height: 20px; + margin-left: 10px; + } + `, + ]; @property({ type: Boolean }) open = false; @@ -134,6 +133,9 @@ export class AddressModal extends LitElement { @property() walletConnectQRcode?: string = undefined; + @property() + showCopiedIcon = false; + constructor() { super(); @@ -150,6 +152,10 @@ export class AddressModal extends LitElement { onClose: () => void = () => nothing; override render(): TemplateResult { + let copyIcon = this.mode === 'LIGHT' ? LightCopySvg : DarkCopySvg; + if (this.showCopiedIcon) { + copyIcon = CheckSvg; + } return html` ${friendlyAddress(this.address ?? '')} +
${copyIcon}
@@ -183,7 +192,7 @@ export class AddressModal extends LitElement { class="${this.mode} ${this.theme}" @click=${this.onDisconnectClick} > -
+
${ this.mode === 'LIGHT' ? LightDisconnectSvg @@ -197,6 +206,14 @@ export class AddressModal extends LitElement { `; } + private onCopy = async (): Promise => { + await navigator.clipboard.writeText(this.address || ''); + this.showCopiedIcon = true; + setTimeout(() => { + this.showCopiedIcon = false; + }, 1000); + }; + private onBack = (): void => { dispatchCustomEvent('vwk-close-wc-modal', undefined); }; diff --git a/packages/dapp-kit-ui/src/components/base/modal.ts b/packages/dapp-kit-ui/src/components/base/modal.ts index 8e5e9c55..1feb25bc 100644 --- a/packages/dapp-kit-ui/src/components/base/modal.ts +++ b/packages/dapp-kit-ui/src/components/base/modal.ts @@ -1,4 +1,4 @@ -import type { TemplateResult } from 'lit'; +import type { PropertyValues, TemplateResult } from 'lit'; import { css, html, LitElement } from 'lit'; import { customElement, property, query } from 'lit/decorators.js'; import type { Theme, ThemeMode } from '../../constants'; @@ -8,7 +8,7 @@ import { Breakpoint, Colors } from '../../constants'; export class Modal extends LitElement { static override styles = css` .modal-container { - display: block; + display: flex; position: fixed; top: 0; left: 0; @@ -16,9 +16,9 @@ export class Modal extends LitElement { bottom: 0; width: 100%; height: 100%; - background-color: rgba(0, 0, 0, 0.5); + background-color: rgba(0, 0, 0, 0.3); opacity: 1; - transition: opacity 0.3s; + transition: opacity 0.1s ease-in-out; } .modal-container.hidden { @@ -29,23 +29,22 @@ export class Modal extends LitElement { .modal { position: absolute; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); - transition: height 0.2s, opacity 0.3s; + transition: height 0.1s ease-in-out, transform 0.2s ease-in-out; overflow: hidden; - opacity: 1; } .modal-container.hidden .modal { - opacity: 0; + transform: scale(0.97); } .modal.LIGHT { background-color: ${Colors.White}; - color: ${Colors.Dark}; + color: ${Colors.LightBlack}; } .modal.DARK { - background-color: ${Colors.Dark}; - color: ${Colors.LightGrey}; + background-color: ${Colors.LightBlack}; + color: ${Colors.XXLightGrey}; } @media (max-width: ${Breakpoint.Mobile}px) { @@ -60,11 +59,12 @@ export class Modal extends LitElement { } @media (min-width: ${Breakpoint.Mobile}px) { + .modal-container { + align-items: center; + justify-content: center; + } .modal { width: 350px; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); border-radius: 16px; } } @@ -80,24 +80,23 @@ export class Modal extends LitElement { @property() theme: Theme = 'DEFAULT'; - changeHeightOnResize = (): void => { - if (!this.modalSubContainer) { - return; - } - this.modalHeight = this.modalSubContainer.clientHeight; - new ResizeObserver(() => { - this.modalHeight = this.modalSubContainer?.clientHeight ?? 0; - }).observe(this.modalSubContainer); - }; - - override connectedCallback(): void { - super.connectedCallback(); - addEventListener('load', this.changeHeightOnResize); - } + observer = new ResizeObserver(() => { + this.modalHeight = this.modalSubContainer?.clientHeight ?? 0; + }); - override disconnectedCallback(): void { - super.disconnectedCallback(); - window.removeEventListener('load', this.changeHeightOnResize); + willUpdate(changedProperties: PropertyValues): void { + if (changedProperties.has('open')) { + if (!this.modalSubContainer) { + return; + } + if (this.open) { + this.modalHeight = this.modalSubContainer.clientHeight; + this.observer.observe(this.modalSubContainer); + } else { + this.modalHeight = 0; + this.observer.unobserve(this.modalSubContainer); + } + } } @property({ type: Function }) diff --git a/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts b/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts index ec711ca9..5c16e1dc 100644 --- a/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts +++ b/packages/dapp-kit-ui/src/components/connect-button-with-modal.ts @@ -60,12 +60,12 @@ export class ConnectButtonWithModal extends LitElement {
${this.dappKitContext.address - ? html` ` + >` : html` ` - : html`
` + : html`
` }
Connect Wallet
void = undefined; @@ -69,13 +49,13 @@ export class SourceCard extends LitElement { override render(): TemplateResult { return html` -
this.handleSourceClick()} >
${this.source?.name}
-
+ `; } } diff --git a/packages/dapp-kit-ui/src/components/vechain-dapp-connect-kit.ts b/packages/dapp-kit-ui/src/components/vechain-dapp-connect-kit.ts index 0ed589c7..d4628e7c 100644 --- a/packages/dapp-kit-ui/src/components/vechain-dapp-connect-kit.ts +++ b/packages/dapp-kit-ui/src/components/vechain-dapp-connect-kit.ts @@ -13,7 +13,7 @@ export class VechainDappConnectKit extends LitElement { render(): TemplateResult { return html` `; } diff --git a/packages/dapp-kit-ui/src/components/wallet-connect-qr-code.ts b/packages/dapp-kit-ui/src/components/wallet-connect-qr-code.ts index 316a8ee5..99428b26 100644 --- a/packages/dapp-kit-ui/src/components/wallet-connect-qr-code.ts +++ b/packages/dapp-kit-ui/src/components/wallet-connect-qr-code.ts @@ -3,6 +3,7 @@ import { css, html, LitElement, nothing, svg } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { Colors } from '../constants'; import { + buttonStyle, CheckSvg, DarkCopySvg, LightCopySvg, @@ -13,103 +14,75 @@ import type { Theme, ThemeMode } from '../constants/theme'; @customElement('vwk-wallet-connect-qrcode') export class WalletConnectQrCode extends LitElement { - static override styles = css` - .qrcode-body { - flex-direction: column; - align-items: stretch; - justify-content: center; - display: flex; - } - - .qrcode-container { - margin: 20px auto 20px auto; - background-color: ${Colors.White}; - width: 280px; - padding: 10px; - border: 1px solid ${Colors.Grey}; - border-radius: 20px; - display: flex; - justify-content: center; - align-items: center; - } - - img { - position: absolute; - width: 65px; - height: 65px; - object-fit: contain; - } - - .separator { - display: flex; - align-items: center; - padding-bottom: 20px; - } - - .line { - display: flex; - flex-grow: 1; - height: 1px; - } - - .line.LIGHT { - background-color: ${Colors.Grey}; - } - - .line.DARK { - background-color: ${Colors.Grey}; - } - - .or { - font-family: 'Inter', sans-serif; - font-size: 14px; - padding: 0 12px; - } - - .or.LIGHT { - color: ${Colors.Grey}; - } - - .or.DARK { - color: ${Colors.Grey}; - } - - button { - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - border: none; - border-radius: 16px; - padding: 16px 12px; - font-family: 'Inter', sans-serif; - text-align: center; - } - - button:hover { - opacity: 0.9; - } - - button:active { - opacity: 0.8; - } - - button.LIGHT { - background-color: ${Colors.LightGrey}; - color: ${Colors.Dark}; - } - - button.DARK { - background-color: ${Colors.DarkGrey}; - color: ${Colors.White}; - } - - .icon { - width: 20px; - height: 20px; - margin-right: 10px; - } - `; + static override styles = [ + buttonStyle, + css` + .qrcode-body { + flex-direction: column; + align-items: stretch; + justify-content: center; + display: flex; + } + + .qrcode-container { + margin: 20px auto 20px auto; + background-color: ${Colors.White}; + width: 280px; + padding: 10px; + border: 1px solid ${Colors.Grey}; + border-radius: 20px; + display: flex; + justify-content: center; + align-items: center; + } + + img { + position: absolute; + width: 65px; + height: 65px; + object-fit: contain; + } + + .separator { + display: flex; + align-items: center; + padding-bottom: 20px; + } + + .line { + display: flex; + flex-grow: 1; + height: 1px; + } + + .line.LIGHT { + background-color: ${Colors.Grey}; + } + + .line.DARK { + background-color: ${Colors.Grey}; + } + + .or { + font-family: 'Inter', sans-serif; + font-size: 14px; + padding: 0 12px; + } + + .or.LIGHT { + color: ${Colors.Grey}; + } + + .or.DARK { + color: ${Colors.Grey}; + } + + .icon { + width: 20px; + height: 20px; + } + `, + ]; @property() mode: ThemeMode = 'LIGHT'; @@ -154,7 +127,7 @@ export class WalletConnectQrCode extends LitElement { this.showCopiedIcon = true; setTimeout(() => { this.showCopiedIcon = false; - }, 3000); + }, 1000); }; private svgWCQrCode(uri: string): TemplateResult { diff --git a/packages/dapp-kit-ui/src/constants/colors.ts b/packages/dapp-kit-ui/src/constants/colors.ts index 1d874393..7f6c94e7 100644 --- a/packages/dapp-kit-ui/src/constants/colors.ts +++ b/packages/dapp-kit-ui/src/constants/colors.ts @@ -2,8 +2,14 @@ import { css } from 'lit'; export const Colors = { White: css`#ffffff`, - LightGrey: css`#f2f2f7`, + XXLightGrey: css`#f2f2f2`, + XLightGrey: css`#eeeeee`, + LightGrey: css`#eaeaea`, Grey: css`#888888`, - DarkGrey: css`#333333`, - Dark: css`#222222`, + DarkGrey: css`#4a4a4a`, + XDarkGrey: css`#454545`, + XXDarkGrey: css`#404040`, + XXLightBlack: css`#353535`, + XLightBlack: css`#303030`, + LightBlack: css`#2a2a2a`, }; diff --git a/packages/dapp-kit-ui/src/modal.ts b/packages/dapp-kit-ui/src/modal.ts index cc2cc221..df9cf10e 100644 --- a/packages/dapp-kit-ui/src/modal.ts +++ b/packages/dapp-kit-ui/src/modal.ts @@ -9,13 +9,7 @@ import type { } from '@vechainfoundation/dapp-kit'; import { DAppKitLogger } from '@vechainfoundation/dapp-kit'; import { subscribeKey } from 'valtio/utils'; -import { - dispatchCustomEvent, - isAndroid, - isMobile, - subscribeToCustomEvent, -} from './utils'; -import { ANDROID_STORE_URL, IOS_STORE_URL } from './constants'; +import { dispatchCustomEvent, isMobile, subscribeToCustomEvent } from './utils'; const MODAL_STATE_EVENT = 'vwk-modal-state-change'; @@ -52,19 +46,20 @@ class CustomWalletConnectModal implements WCModal { `veworld://app.veworld?uri=${encodeURIComponent(options.uri)}`, '_self', ); - const linkingTime = new Date().getTime(); - const TIMEOUT = 5000; - setTimeout(() => { - const now = new Date().getTime(); - // avoid redirecting to the store if coming back from the app - if (now - linkingTime < TIMEOUT + 250) { - if (isAndroid()) { - window.open(ANDROID_STORE_URL, '_self'); - } else { - window.open(IOS_STORE_URL, '_self'); - } - } - }, TIMEOUT); + // TODO: commented out for now, as it's not working as expected, maybe a modal item is better + // const linkingTime = new Date().getTime(); + // const TIMEOUT = 5000; + // setTimeout(() => { + // const now = new Date().getTime(); + // // avoid redirecting to the store if coming back from the app + // if (now - linkingTime < TIMEOUT + 250) { + // if (isAndroid()) { + // window.open(ANDROID_STORE_URL, '_self'); + // } else { + // window.open(IOS_STORE_URL, '_self'); + // } + // } + // }, TIMEOUT); } dispatchCustomEvent('vwk-open-wc-modal', options); return Promise.resolve(); diff --git a/packages/dapp-kit-ui/src/utils/account.ts b/packages/dapp-kit-ui/src/utils/account.ts index 7be1cbfa..d54f78c5 100644 --- a/packages/dapp-kit-ui/src/utils/account.ts +++ b/packages/dapp-kit-ui/src/utils/account.ts @@ -16,5 +16,5 @@ export const friendlyAddress = ( ): string => { const before = address.substring(0, lengthBefore); const after = address.substring(address.length - lengthAfter); - return `${before}…${after}`; + return `${before}••••${after}`; }; diff --git a/packages/dapp-kit-ui/src/utils/mobile.ts b/packages/dapp-kit-ui/src/utils/mobile.ts index f7eee6d0..34fcbcc4 100644 --- a/packages/dapp-kit-ui/src/utils/mobile.ts +++ b/packages/dapp-kit-ui/src/utils/mobile.ts @@ -8,16 +8,16 @@ // but the source is this one http://detectmobilebrowsers.com/ export const isMobile = (): boolean => { - const a = + const userAgent = navigator.userAgent || navigator.vendor || ((window as any).opera as string); if ( /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test( - a, + userAgent, ) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( - a.substr(0, 4), + userAgent.substr(0, 4), ) ) { return true; diff --git a/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts b/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts index 232df62a..c6293869 100644 --- a/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts +++ b/packages/dapp-kit-ui/test/connect-button-with-modal.test.ts @@ -1,8 +1,8 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { - AddressBadge, - AddressBadgeWithModal, + AddressButton, + AddressButtonWithModal, AddressModal, ConnectButton, ConnectButtonWithModal, @@ -18,7 +18,7 @@ describe('connect-button-with-modal', () => { DAppKitUI.configure({ nodeUrl: 'https://mainnet.vechain.org/' }); }); - it('Should callback with source when user clicks a wallet and should render the connected address badge once connected', async () => { + it('Should callback with source when user clicks a wallet and should render the connected address button once connected', async () => { const element: ConnectButtonWithModal = window.document.createElement( 'vwk-connect-button-with-modal', ); @@ -59,24 +59,24 @@ describe('connect-button-with-modal', () => { expect(selectedSource).toBeDefined(); - // testing the connected address badge + // testing the connected address button // mock a connection to the wallet by setting the address element.dappKitContext.address = '0x00000'; element.requestUpdate(); - const connectedAddressBadgeWithModal = - (await elementQueries.getConnectedAddressBadgeWithModal()) as AddressBadgeWithModal; + const connectedAddressButtonWithModal = + (await elementQueries.getConnectedAddressButtonWithModal()) as AddressButtonWithModal; - expect(connectedAddressBadgeWithModal).toBeDefined(); + expect(connectedAddressButtonWithModal).toBeDefined(); - const connectedAddressBadge = - (await elementQueries.getConnectedAddressBadge()) as AddressBadge; + const connectedAddressButton = + (await elementQueries.getConnectedAddressButton()) as AddressButton; - expect(connectedAddressBadge).toBeDefined(); + expect(connectedAddressButton).toBeDefined(); // open the connected address modal - connectedAddressBadge.shadowRoot?.querySelector('div')?.click(); + connectedAddressButton.shadowRoot?.querySelector('div')?.click(); const connectedAddressModal = (await elementQueries.getConnectedAddressModal()) as AddressModal; diff --git a/packages/dapp-kit-ui/test/helpers/element-queries.ts b/packages/dapp-kit-ui/test/helpers/element-queries.ts index fd297470..f3c9bc77 100644 --- a/packages/dapp-kit-ui/test/helpers/element-queries.ts +++ b/packages/dapp-kit-ui/test/helpers/element-queries.ts @@ -1,6 +1,6 @@ import { - AddressBadge, - AddressBadgeWithModal, + AddressButton, + AddressButtonWithModal, AddressModal, ConnectButton, ConnectModal, @@ -42,14 +42,14 @@ const getConnectModal = (): Promise => { ); }; -const getConnectedAddressBadgeWithModal = ( +const getConnectedAddressButtonWithModal = ( timeout = 2000, -): Promise => { +): Promise => { return performQueryWithTimeout(timeout, () => window.document.body .querySelector('vwk-connect-button-with-modal') ?.shadowRoot?.querySelector( - 'vwk-connected-address-badge-with-modal', + 'vwk-connected-address-button-with-modal', ), ); }; @@ -64,16 +64,16 @@ const getDappKitContextProvider = (): Promise< ); }; -const getConnectedAddressBadge = ( +const getConnectedAddressButton = ( timeout = 2000, -): Promise => { +): Promise => { return performQueryWithTimeout(timeout, () => window.document.body .querySelector('vwk-connect-button-with-modal') ?.shadowRoot?.querySelector( - 'vwk-connected-address-badge-with-modal', + 'vwk-connected-address-button-with-modal', ) - ?.shadowRoot?.querySelector('vwk-connected-address-badge'), + ?.shadowRoot?.querySelector('vwk-connected-address-button'), ); }; @@ -84,7 +84,7 @@ const getConnectedAddressModal = ( window.document.body .querySelector('vwk-connect-button-with-modal') ?.shadowRoot?.querySelector( - 'vwk-connected-address-badge-with-modal', + 'vwk-connected-address-button-with-modal', ) ?.shadowRoot?.querySelector('vwk-connected-address-modal'), ); @@ -123,8 +123,8 @@ export const elementQueries = { getConnectModal, getAllSourceCards, getWalletConnectQrCode, - getConnectedAddressBadgeWithModal, - getConnectedAddressBadge, + getConnectedAddressButtonWithModal, + getConnectedAddressButton, getConnectedAddressModal, getDappKitContextProvider, }; diff --git a/packages/dapp-kit-ui/test/setup/setup.ts b/packages/dapp-kit-ui/test/setup/setup.ts index d1e924ec..139c0323 100644 --- a/packages/dapp-kit-ui/test/setup/setup.ts +++ b/packages/dapp-kit-ui/test/setup/setup.ts @@ -15,3 +15,14 @@ Object.defineProperty(window, 'matchMedia', { dispatchEvent: vi.fn(), })), }); +global.ResizeObserver = class ResizeObserver { + observe() { + // do nothing + } + unobserve() { + // do nothing + } + disconnect() { + // do nothing + } +}; diff --git a/packages/dapp-kit-ui/test/listeners.test.ts b/packages/dapp-kit-ui/test/utils/listeners.test.ts similarity index 85% rename from packages/dapp-kit-ui/test/listeners.test.ts rename to packages/dapp-kit-ui/test/utils/listeners.test.ts index e0d55d37..189caeb4 100644 --- a/packages/dapp-kit-ui/test/listeners.test.ts +++ b/packages/dapp-kit-ui/test/utils/listeners.test.ts @@ -1,5 +1,5 @@ import { vi } from 'vitest'; -import { addResizeListeners } from '../src/utils/listeners'; // Replace 'yourModule' with the actual module path +import { addResizeListeners } from '../../src/utils/listeners'; // Replace 'yourModule' with the actual module path describe('addResizeListeners', () => { it('should call the callback when the window loads', () => { diff --git a/packages/dapp-kit-ui/test/utils/mobile.test.ts b/packages/dapp-kit-ui/test/utils/mobile.test.ts new file mode 100644 index 00000000..1d6be535 --- /dev/null +++ b/packages/dapp-kit-ui/test/utils/mobile.test.ts @@ -0,0 +1,49 @@ +import { isMobile, isAndroid } from '../../src/utils/mobile'; + +describe('isMobile', () => { + it('should return true for a mobile user agent', () => { + Object.defineProperty(window, 'navigator', { + value: { + userAgent: + 'Mozilla/5.0 (Android; Mobile; rv:40.0) Gecko/40.0 Firefox/40.0', + } as Navigator, + writable: true, + }); + expect(isMobile()).toBe(true); + }); + + it('should return false for a non-mobile user agent', () => { + Object.defineProperty(window, 'navigator', { + value: { + userAgent: + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', + } as Navigator, + writable: true, + }); + expect(isMobile()).toBe(false); + }); +}); + +describe('isAndroid', () => { + it('should return true for an Android user agent', () => { + Object.defineProperty(window, 'navigator', { + value: { + userAgent: + 'Mozilla/5.0 (Linux; Android 10; SM-G960U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36', + } as Navigator, + writable: true, + }); + expect(isAndroid()).toBe(true); + }); + + it('should return false for a non-Android user agent', () => { + Object.defineProperty(window, 'navigator', { + value: { + userAgent: + 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1', + } as Navigator, + writable: true, + }); + expect(isAndroid()).toBe(false); + }); +}); diff --git a/packages/dapp-kit-ui/test/vechain-dapp-connect-kit.test.ts b/packages/dapp-kit-ui/test/vechain-dapp-connect-kit.test.ts index 411e7ee8..8f7b31cd 100644 --- a/packages/dapp-kit-ui/test/vechain-dapp-connect-kit.test.ts +++ b/packages/dapp-kit-ui/test/vechain-dapp-connect-kit.test.ts @@ -12,7 +12,7 @@ describe('connect-button-with-modal', () => { DAppKitUI.configure({ nodeUrl: 'https://mainnet.vechain.org/' }); }); - it('Should callback with source when user clicks a wallet and should render the connected address badge once connected', async () => { + it('Should callback with source when user clicks a wallet and should render the connected address button once connected', async () => { const element: VechainDappConnectKit = window.document.createElement( 'vwk-vechain-dapp-connect-kit', ); diff --git a/packages/dapp-kit-ui/tsconfig.json b/packages/dapp-kit-ui/tsconfig.json index 17cd689c..c401f365 100644 --- a/packages/dapp-kit-ui/tsconfig.json +++ b/packages/dapp-kit-ui/tsconfig.json @@ -4,6 +4,10 @@ "target": "es2021", "experimentalDecorators": true }, - "include": ["src/**/*.ts", "test/listeners.test.ts"], + "include": [ + "src/**/*.ts", + "test/utils/listeners.test.ts", + "test/utils/mobile.test.ts" + ], "exclude": [] }