diff --git a/CHANGELOG.md b/CHANGELOG.md index 48e3dd31..76640313 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- [Added custom notification support](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/21) + ## [[0.0.0-alpha.1](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/16)] - 2025-01-20 - [Updated formatAmount component and removed dependencies](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/17) -- [Updated formatAmount component](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/15) \ No newline at end of file +- [Updated formatAmount component](https://github.com/multiversx/mx-sdk-dapp-core-ui/pull/15) diff --git a/src/assets/notification.js b/src/assets/notification.js index 1a32cb53..fc2614b7 100644 --- a/src/assets/notification.js +++ b/src/assets/notification.js @@ -67,7 +67,7 @@ function showNotification() { newToast.toastId = notificationId.toString(); newToast.transactions = [{ hash: 'erd1...8ctr', status: 'success' }]; - const transactionListElement = document.getElementById('transaction-list'); + const transactionListElement = document.getElementById('toast-list'); if (transactionListElement) { transactionListElement.appendChild(newToast); } diff --git a/src/components.d.ts b/src/components.d.ts index ed5b58d4..06cb9e0a 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -5,19 +5,21 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; +import { CustomToastType, IComponentToast, ISimpleToast } from "./components/toasts-list/components/transaction-toast/transaction-toast.type"; import { LocalJSX as JSX, VNode } from "@stencil/core"; import { ILedgerConnectModalData } from "./components/ledger-connect-modal/ledger-connect-modal.types"; import { IEventBus } from "./utils/EventBus"; import { IPendingTransactionsModalData } from "./components/pending-transactions-modal/pending-transactions-modal.types"; import { ISignTransactionsModalData } from "./components/sign-transactions-modal/sign-transactions-modal.types"; -import { IToastDataState, ITransaction, ITransactionProgressState, ITransactionToast } from "./components/transaction-toast/transaction-toast.type"; +import { CustomToastType as CustomToastType1, IToastDataState, ITransaction, ITransactionProgressState, ITransactionToast } from "./components/toasts-list/components/transaction-toast/transaction-toast.type"; import { IWalletConnectModalData } from "./components/wallet-connect-modal/wallet-connect-modal.types"; +export { CustomToastType, IComponentToast, ISimpleToast } from "./components/toasts-list/components/transaction-toast/transaction-toast.type"; export { LocalJSX as JSX, VNode } from "@stencil/core"; export { ILedgerConnectModalData } from "./components/ledger-connect-modal/ledger-connect-modal.types"; export { IEventBus } from "./utils/EventBus"; export { IPendingTransactionsModalData } from "./components/pending-transactions-modal/pending-transactions-modal.types"; export { ISignTransactionsModalData } from "./components/sign-transactions-modal/sign-transactions-modal.types"; -export { IToastDataState, ITransaction, ITransactionProgressState, ITransactionToast } from "./components/transaction-toast/transaction-toast.type"; +export { CustomToastType as CustomToastType1, IToastDataState, ITransaction, ITransactionProgressState, ITransactionToast } from "./components/toasts-list/components/transaction-toast/transaction-toast.type"; export { IWalletConnectModalData } from "./components/wallet-connect-modal/wallet-connect-modal.types"; export namespace Components { interface BalanceComponent { @@ -26,6 +28,9 @@ export namespace Components { "ticker": string; "usdValue"?: string; } + interface CustomToast { + "toast": IComponentToast; + } interface FormatAmount { "class"?: string; "dataTestId"?: string; @@ -45,6 +50,9 @@ export namespace Components { } interface GenericSpinner { } + interface GenericToast { + "toast": CustomToastType; + } interface LedgerConnectModal { "data": ILedgerConnectModalData; "getEventBus": () => Promise; @@ -74,6 +82,14 @@ export namespace Components { "data": ISignTransactionsModalData; "getEventBus": () => Promise; } + interface SimpleToast { + "toast": ISimpleToast; + } + interface ToastList { + "customToasts": CustomToastType1[]; + "getEventBus": () => Promise; + "transactionToasts": ITransactionToast[]; + } interface TokenComponent { } interface TransactionToast { @@ -99,10 +115,6 @@ export namespace Components { "status"?: string; "transactionClass"?: string; } - interface TransactionToastList { - "data": ITransactionToast[]; - "getEventBus": () => Promise; - } interface TransactionToastProgress { "currentRemaining"?: number; "progressClass": string; @@ -116,6 +128,18 @@ export namespace Components { "getEventBus": () => Promise; } } +export interface CustomToastCustomEvent extends CustomEvent { + detail: T; + target: HTMLCustomToastElement; +} +export interface GenericToastCustomEvent extends CustomEvent { + detail: T; + target: HTMLGenericToastElement; +} +export interface SimpleToastCustomEvent extends CustomEvent { + detail: T; + target: HTMLSimpleToastElement; +} export interface TransactionToastCustomEvent extends CustomEvent { detail: T; target: HTMLTransactionToastElement; @@ -131,6 +155,23 @@ declare global { prototype: HTMLBalanceComponentElement; new (): HTMLBalanceComponentElement; }; + interface HTMLCustomToastElementEventMap { + "handleDeleteToast": string; + } + interface HTMLCustomToastElement extends Components.CustomToast, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLCustomToastElement, ev: CustomToastCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLCustomToastElement, ev: CustomToastCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLCustomToastElement: { + prototype: HTMLCustomToastElement; + new (): HTMLCustomToastElement; + }; interface HTMLFormatAmountElement extends Components.FormatAmount, HTMLStencilElement { } var HTMLFormatAmountElement: { @@ -155,6 +196,23 @@ declare global { prototype: HTMLGenericSpinnerElement; new (): HTMLGenericSpinnerElement; }; + interface HTMLGenericToastElementEventMap { + "handleDeleteToast": string; + } + interface HTMLGenericToastElement extends Components.GenericToast, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLGenericToastElement, ev: GenericToastCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLGenericToastElement, ev: GenericToastCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLGenericToastElement: { + prototype: HTMLGenericToastElement; + new (): HTMLGenericToastElement; + }; interface HTMLLedgerConnectModalElement extends Components.LedgerConnectModal, HTMLStencilElement { } var HTMLLedgerConnectModalElement: { @@ -185,6 +243,29 @@ declare global { prototype: HTMLSignTransactionsModalElement; new (): HTMLSignTransactionsModalElement; }; + interface HTMLSimpleToastElementEventMap { + "handleDeleteToast": void; + } + interface HTMLSimpleToastElement extends Components.SimpleToast, HTMLStencilElement { + addEventListener(type: K, listener: (this: HTMLSimpleToastElement, ev: SimpleToastCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLSimpleToastElement, ev: SimpleToastCustomEvent) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; + removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; + } + var HTMLSimpleToastElement: { + prototype: HTMLSimpleToastElement; + new (): HTMLSimpleToastElement; + }; + interface HTMLToastListElement extends Components.ToastList, HTMLStencilElement { + } + var HTMLToastListElement: { + prototype: HTMLToastListElement; + new (): HTMLToastListElement; + }; interface HTMLTokenComponentElement extends Components.TokenComponent, HTMLStencilElement { } var HTMLTokenComponentElement: { @@ -237,12 +318,6 @@ declare global { prototype: HTMLTransactionToastDetailsBodyElement; new (): HTMLTransactionToastDetailsBodyElement; }; - interface HTMLTransactionToastListElement extends Components.TransactionToastList, HTMLStencilElement { - } - var HTMLTransactionToastListElement: { - prototype: HTMLTransactionToastListElement; - new (): HTMLTransactionToastListElement; - }; interface HTMLTransactionToastProgressElement extends Components.TransactionToastProgress, HTMLStencilElement { } var HTMLTransactionToastProgressElement: { @@ -263,21 +338,24 @@ declare global { }; interface HTMLElementTagNameMap { "balance-component": HTMLBalanceComponentElement; + "custom-toast": HTMLCustomToastElement; "format-amount": HTMLFormatAmountElement; "fungible-component": HTMLFungibleComponentElement; "generic-modal": HTMLGenericModalElement; "generic-spinner": HTMLGenericSpinnerElement; + "generic-toast": HTMLGenericToastElement; "ledger-connect-modal": HTMLLedgerConnectModalElement; "my-component": HTMLMyComponentElement; "pending-transactions-modal": HTMLPendingTransactionsModalElement; "sign-transaction-component": HTMLSignTransactionComponentElement; "sign-transactions-modal": HTMLSignTransactionsModalElement; + "simple-toast": HTMLSimpleToastElement; + "toast-list": HTMLToastListElement; "token-component": HTMLTokenComponentElement; "transaction-toast": HTMLTransactionToastElement; "transaction-toast-content": HTMLTransactionToastContentElement; "transaction-toast-details": HTMLTransactionToastDetailsElement; "transaction-toast-details-body": HTMLTransactionToastDetailsBodyElement; - "transaction-toast-list": HTMLTransactionToastListElement; "transaction-toast-progress": HTMLTransactionToastProgressElement; "transaction-toast-wrapper": HTMLTransactionToastWrapperElement; "wallet-connect-modal": HTMLWalletConnectModalElement; @@ -290,6 +368,10 @@ declare namespace LocalJSX { "ticker"?: string; "usdValue"?: string; } + interface CustomToast { + "onHandleDeleteToast"?: (event: CustomToastCustomEvent) => void; + "toast"?: IComponentToast; + } interface FormatAmount { "class"?: string; "dataTestId"?: string; @@ -309,6 +391,10 @@ declare namespace LocalJSX { } interface GenericSpinner { } + interface GenericToast { + "onHandleDeleteToast"?: (event: GenericToastCustomEvent) => void; + "toast"?: CustomToastType; + } interface LedgerConnectModal { "data"?: ILedgerConnectModalData; } @@ -335,6 +421,14 @@ declare namespace LocalJSX { interface SignTransactionsModal { "data"?: ISignTransactionsModalData; } + interface SimpleToast { + "onHandleDeleteToast"?: (event: SimpleToastCustomEvent) => void; + "toast"?: ISimpleToast; + } + interface ToastList { + "customToasts"?: CustomToastType1[]; + "transactionToasts"?: ITransactionToast[]; + } interface TokenComponent { } interface TransactionToast { @@ -362,9 +456,6 @@ declare namespace LocalJSX { "status"?: string; "transactionClass"?: string; } - interface TransactionToastList { - "data"?: ITransactionToast[]; - } interface TransactionToastProgress { "currentRemaining"?: number; "progressClass"?: string; @@ -378,21 +469,24 @@ declare namespace LocalJSX { } interface IntrinsicElements { "balance-component": BalanceComponent; + "custom-toast": CustomToast; "format-amount": FormatAmount; "fungible-component": FungibleComponent; "generic-modal": GenericModal; "generic-spinner": GenericSpinner; + "generic-toast": GenericToast; "ledger-connect-modal": LedgerConnectModal; "my-component": MyComponent; "pending-transactions-modal": PendingTransactionsModal; "sign-transaction-component": SignTransactionComponent; "sign-transactions-modal": SignTransactionsModal; + "simple-toast": SimpleToast; + "toast-list": ToastList; "token-component": TokenComponent; "transaction-toast": TransactionToast; "transaction-toast-content": TransactionToastContent; "transaction-toast-details": TransactionToastDetails; "transaction-toast-details-body": TransactionToastDetailsBody; - "transaction-toast-list": TransactionToastList; "transaction-toast-progress": TransactionToastProgress; "transaction-toast-wrapper": TransactionToastWrapper; "wallet-connect-modal": WalletConnectModal; @@ -403,21 +497,24 @@ declare module "@stencil/core" { export namespace JSX { interface IntrinsicElements { "balance-component": LocalJSX.BalanceComponent & JSXBase.HTMLAttributes; + "custom-toast": LocalJSX.CustomToast & JSXBase.HTMLAttributes; "format-amount": LocalJSX.FormatAmount & JSXBase.HTMLAttributes; "fungible-component": LocalJSX.FungibleComponent & JSXBase.HTMLAttributes; "generic-modal": LocalJSX.GenericModal & JSXBase.HTMLAttributes; "generic-spinner": LocalJSX.GenericSpinner & JSXBase.HTMLAttributes; + "generic-toast": LocalJSX.GenericToast & JSXBase.HTMLAttributes; "ledger-connect-modal": LocalJSX.LedgerConnectModal & JSXBase.HTMLAttributes; "my-component": LocalJSX.MyComponent & JSXBase.HTMLAttributes; "pending-transactions-modal": LocalJSX.PendingTransactionsModal & JSXBase.HTMLAttributes; "sign-transaction-component": LocalJSX.SignTransactionComponent & JSXBase.HTMLAttributes; "sign-transactions-modal": LocalJSX.SignTransactionsModal & JSXBase.HTMLAttributes; + "simple-toast": LocalJSX.SimpleToast & JSXBase.HTMLAttributes; + "toast-list": LocalJSX.ToastList & JSXBase.HTMLAttributes; "token-component": LocalJSX.TokenComponent & JSXBase.HTMLAttributes; "transaction-toast": LocalJSX.TransactionToast & JSXBase.HTMLAttributes; "transaction-toast-content": LocalJSX.TransactionToastContent & JSXBase.HTMLAttributes; "transaction-toast-details": LocalJSX.TransactionToastDetails & JSXBase.HTMLAttributes; "transaction-toast-details-body": LocalJSX.TransactionToastDetailsBody & JSXBase.HTMLAttributes; - "transaction-toast-list": LocalJSX.TransactionToastList & JSXBase.HTMLAttributes; "transaction-toast-progress": LocalJSX.TransactionToastProgress & JSXBase.HTMLAttributes; "transaction-toast-wrapper": LocalJSX.TransactionToastWrapper & JSXBase.HTMLAttributes; "wallet-connect-modal": LocalJSX.WalletConnectModal & JSXBase.HTMLAttributes; diff --git a/src/components/format-amount/format-amount.tsx b/src/components/format-amount/format-amount.tsx index 5fc26b39..0f819fcb 100644 --- a/src/components/format-amount/format-amount.tsx +++ b/src/components/format-amount/format-amount.tsx @@ -4,7 +4,7 @@ import { DataTestIdsEnum } from 'constants/dataTestIds.enum'; @Component({ tag: 'format-amount', styleUrl: 'format-amount.css', - shadow: true + shadow: true, }) export class FormatAmount { @Prop() class?: string; @@ -15,7 +15,6 @@ export class FormatAmount { @Prop() valueDecimal: string; @Prop() valueInteger: string; - render() { return this.isValid ? this.renderValid() : this.renderInvalid(); } @@ -23,7 +22,7 @@ export class FormatAmount { private renderInvalid() { return ( - + ... @@ -33,19 +32,19 @@ export class FormatAmount { private renderValid() { return ( - + {this.valueInteger} {this.valueDecimal && ( - + .{this.valueDecimal} )} {this.label && ( @@ -55,5 +54,4 @@ export class FormatAmount { ); } - } diff --git a/src/components/toasts-list/components/custom-toast/components/custom-create-toast/custom-toast.css b/src/components/toasts-list/components/custom-toast/components/custom-create-toast/custom-toast.css new file mode 100644 index 00000000..1e90d4e5 --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/components/custom-create-toast/custom-toast.css @@ -0,0 +1,35 @@ +.toast-wrapper { + border-radius: 0.25rem; + box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.1); + margin-bottom: 0.7rem; + padding: 0.5rem; + background-color: #fff; + position: relative; +} + +.icon-close { + position: absolute; + right: 16px; + top: 16px; + cursor: pointer; + font-size: 1.5rem; + font-weight: 700; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.5; + padding: 0; + background-color: rgba(0, 0, 0, 0); + border: 0; + display: flex; + align-items: center; + margin: 0 0.5rem; + width: 12px; +} + +.toast-body { + display: flex; + align-items: center; + flex: 1; + font-size: 16px; +} diff --git a/src/components/toasts-list/components/custom-toast/components/custom-create-toast/custom-toast.tsx b/src/components/toasts-list/components/custom-toast/components/custom-create-toast/custom-toast.tsx new file mode 100644 index 00000000..43f63b63 --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/components/custom-create-toast/custom-toast.tsx @@ -0,0 +1,35 @@ +import { faTimes } from '@fortawesome/free-solid-svg-icons'; +import { Component, Prop, Event, h, EventEmitter } from '@stencil/core'; +import { IComponentToast } from 'components/toasts-list/components/transaction-toast/transaction-toast.type'; +import { getIconHtmlFromIconDefinition } from 'utils/icons/getIconHtmlFromIconDefinition'; + +@Component({ + tag: 'custom-toast', + styleUrl: 'custom-toast.css', + shadow: true, +}) +export class CustomToast { + @Prop() toast: IComponentToast; + @Event() handleDeleteToast: EventEmitter; + + render() { + const customToast = ( +
+ +
this.initializeToast(container)}>
+
+ ); + return customToast; + } + + private initializeToast(container: HTMLElement) { + if (!container || container.hasChildNodes()) { + return; + } + const customElement = this.toast.instantiateToastElement(); + if (!customElement) { + return; + } + container.appendChild(customElement); + } +} diff --git a/src/components/toasts-list/components/custom-toast/components/custom-create-toast/readme.md b/src/components/toasts-list/components/custom-toast/components/custom-create-toast/readme.md new file mode 100644 index 00000000..b979b9eb --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/components/custom-create-toast/readme.md @@ -0,0 +1,37 @@ +# custom-create-toast + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| -------- | --------- | ----------- | ----------------- | ----------- | +| `toast` | -- | | `IComponentToast` | `undefined` | + + +## Events + +| Event | Description | Type | +| ------------------- | ----------- | --------------------- | +| `handleDeleteToast` | | `CustomEvent` | + + +## Dependencies + +### Used by + + - [generic-toast](../..) + +### Graph +```mermaid +graph TD; + generic-toast --> custom-toast + style custom-toast fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/src/components/toasts-list/components/custom-toast/components/simple-toast/readme.md b/src/components/toasts-list/components/custom-toast/components/simple-toast/readme.md new file mode 100644 index 00000000..c2ed4ed1 --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/components/simple-toast/readme.md @@ -0,0 +1,42 @@ +# simple-toast + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| -------- | --------- | ----------- | -------------- | ----------- | +| `toast` | -- | | `ISimpleToast` | `undefined` | + + +## Events + +| Event | Description | Type | +| ------------------- | ----------- | ------------------- | +| `handleDeleteToast` | | `CustomEvent` | + + +## Dependencies + +### Used by + + - [generic-toast](../..) + +### Depends on + +- [transaction-toast-wrapper](../../../transaction-toast/components/transaction-toast-wrapper) + +### Graph +```mermaid +graph TD; + simple-toast --> transaction-toast-wrapper + generic-toast --> simple-toast + style simple-toast fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/src/components/toasts-list/components/custom-toast/components/simple-toast/simple-toast.css b/src/components/toasts-list/components/custom-toast/components/simple-toast/simple-toast.css new file mode 100644 index 00000000..97750e38 --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/components/simple-toast/simple-toast.css @@ -0,0 +1,102 @@ +.content { + display: flex; + align-items: center; +} + +.content-left { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding-left: 0.5rem; + padding-right: 0.75rem; + + &.no-icon { + display: none; + } +} + +.content-icon { + display: flex; + align-items: center; + justify-content: center; + width: 3rem; + height: 3rem; + border-radius: 50%; + + svg { + height: auto; + width: 20px; + + path { + fill: white; + } + } +} + +.icon-close { + position: absolute; + right: 16px; + top: 16px; + font-size: 1.5rem; + font-weight: 700; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.5; + padding: 0; + background-color: rgba(0, 0, 0, 0); + border: 0; + display: flex; + align-items: center; + margin: 0 0.5rem; + width: 12px; +} + +.content-right { + display: flex; + flex-direction: column; + justify-content: center; + width: 100%; +} + +.content-heading { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.25rem; + + h5 { + margin: 0; + margin-bottom: 0.5rem; + font-weight: 500; + line-height: 1.2; + font-size: 1.25rem; + } +} + +.content-message { + margin-top: 0.25rem; + font-size: 1rem; + &.no-margin { + margin-top: 0rem; + } +} + +.subtitle { + font-size: 0.9rem; + font-weight: 500; + color: #6c757d; +} + +.success { + background-color: #5cb85c; +} + +.warning { + background-color: #ffc107; +} + +.danger { + background-color: #d9534f; +} diff --git a/src/components/toasts-list/components/custom-toast/components/simple-toast/simple-toast.tsx b/src/components/toasts-list/components/custom-toast/components/simple-toast/simple-toast.tsx new file mode 100644 index 00000000..8683733b --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/components/simple-toast/simple-toast.tsx @@ -0,0 +1,56 @@ +import { faTimes } from '@fortawesome/free-solid-svg-icons'; +import { Component, EventEmitter, Prop, Event, h } from '@stencil/core'; +import classNames from 'classnames'; +import { ISimpleToast } from 'components/toasts-list/components/transaction-toast/transaction-toast.type'; +import { DataTestIdsEnum } from 'constants/dataTestIds.enum'; +import { getIconHtmlFromIconDefinition } from 'utils/icons/getIconHtmlFromIconDefinition'; +import { getIconHtmlFromIconName } from 'utils/icons/getIconHtmlFromIconName'; + +@Component({ + tag: 'simple-toast', + styleUrl: 'simple-toast.css', + shadow: true, +}) +export class SimpleToast { + @Prop() toast: ISimpleToast; + @Event() handleDeleteToast: EventEmitter; + + render() { + const { icon, iconClassName, title, message, subtitle } = this.toast; + + let iconHtml = null; + if (typeof icon === 'string') { + iconHtml = getIconHtmlFromIconName(icon); + } + if (icon instanceof HTMLElement) { + iconHtml = icon.outerHTML; + } + + return ( + +
+ {iconHtml && ( +
+
+
+ )} + +
+ {title && ( +
+
+ {title} +
+
+ )} + + + + {subtitle &&
{subtitle}
} + {message &&
{message}
} +
+
+
+ ); + } +} diff --git a/src/components/toasts-list/components/custom-toast/generic-toast.tsx b/src/components/toasts-list/components/custom-toast/generic-toast.tsx new file mode 100644 index 00000000..bbcf1ac7 --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/generic-toast.tsx @@ -0,0 +1,19 @@ +import { Component, Prop, Event, h, EventEmitter } from '@stencil/core'; +import { IComponentToast, CustomToastType, ISimpleToast } from 'components/toasts-list/components/transaction-toast/transaction-toast.type'; + +@Component({ + tag: 'generic-toast', +}) +export class GenericToast { + @Prop() toast: CustomToastType; + @Event() handleDeleteToast: EventEmitter; + + render() { + const isComponentToast = 'instantiateToastElement' in this.toast; + if (isComponentToast) { + return this.handleDeleteToast.emit(this.toast.toastId)} />; + } + + return this.handleDeleteToast.emit(this.toast.toastId)} />; + } +} diff --git a/src/components/toasts-list/components/custom-toast/readme.md b/src/components/toasts-list/components/custom-toast/readme.md new file mode 100644 index 00000000..4558a9fa --- /dev/null +++ b/src/components/toasts-list/components/custom-toast/readme.md @@ -0,0 +1,45 @@ +# custom-toast + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| -------- | --------- | ----------- | --------------------------------- | ----------- | +| `toast` | -- | | `IComponentToast \| ISimpleToast` | `undefined` | + + +## Events + +| Event | Description | Type | +| ------------------- | ----------- | --------------------- | +| `handleDeleteToast` | | `CustomEvent` | + + +## Dependencies + +### Used by + + - [toast-list](../..) + +### Depends on + +- [custom-toast](./components/custom-create-toast) +- [simple-toast](./components/simple-toast) + +### Graph +```mermaid +graph TD; + generic-toast --> custom-toast + generic-toast --> simple-toast + simple-toast --> transaction-toast-wrapper + toast-list --> generic-toast + style generic-toast fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/src/components/transaction-toast/components/transaction-toast-content/readme.md b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-content/readme.md similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-content/readme.md rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-content/readme.md diff --git a/src/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.css b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.css similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.css rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.css diff --git a/src/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.tsx b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.tsx similarity index 96% rename from src/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.tsx rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.tsx index 38252c1d..798765d6 100644 --- a/src/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.tsx +++ b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-content/transaction-toast-content.tsx @@ -1,10 +1,10 @@ -import { Component, EventEmitter, Prop, Event, h, JSX } from '@stencil/core'; import { faTimes } from '@fortawesome/free-solid-svg-icons'; +import { Component, EventEmitter, Prop, Event, h, JSX } from '@stencil/core'; import classNames from 'classnames'; -import { IToastDataState, ITransaction } from '../../transaction-toast.type'; -import { getIconHtmlFromIconName } from 'utils/icons/getIconHtmlFromIconName'; -import { getIconHtmlFromIconDefinition } from 'utils/icons/getIconHtmlFromIconDefinition'; import { DataTestIdsEnum } from 'constants/dataTestIds.enum'; +import { getIconHtmlFromIconDefinition } from 'utils/icons/getIconHtmlFromIconDefinition'; +import { getIconHtmlFromIconName } from 'utils/icons/getIconHtmlFromIconName'; +import { IToastDataState, ITransaction } from '../..//transaction-toast.type'; @Component({ tag: 'transaction-toast-content', diff --git a/src/components/transaction-toast/components/transaction-toast-details/components/readme.md b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/components/readme.md similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-details/components/readme.md rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/components/readme.md diff --git a/src/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.css b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.css similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.css rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.css diff --git a/src/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.tsx b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.tsx similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.tsx rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/components/transaction-toast-details-body.tsx diff --git a/src/components/transaction-toast/components/transaction-toast-details/readme.md b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/readme.md similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-details/readme.md rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/readme.md diff --git a/src/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.css b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.css similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.css rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.css diff --git a/src/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.tsx b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.tsx similarity index 92% rename from src/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.tsx rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.tsx index d84b8475..03a2e4da 100644 --- a/src/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.tsx +++ b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-details/transaction-toast-details.tsx @@ -1,5 +1,5 @@ import { Component, Fragment, JSX, Prop, h } from '@stencil/core'; -import { ITransaction } from './../../transaction-toast.type'; +import { ITransaction } from '../../transaction-toast.type'; @Component({ tag: 'transaction-toast-details', diff --git a/src/components/transaction-toast/components/transaction-toast-progress/readme.md b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-progress/readme.md similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-progress/readme.md rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-progress/readme.md diff --git a/src/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.css b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.css similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.css rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.css diff --git a/src/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.tsx b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.tsx similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.tsx rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-progress/transaction-toast-progress.tsx diff --git a/src/components/transaction-toast/components/transaction-toast-wrapper/readme.md b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-wrapper/readme.md similarity index 87% rename from src/components/transaction-toast/components/transaction-toast-wrapper/readme.md rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-wrapper/readme.md index 47851473..209bbe02 100644 --- a/src/components/transaction-toast/components/transaction-toast-wrapper/readme.md +++ b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-wrapper/readme.md @@ -17,11 +17,13 @@ ### Used by + - [simple-toast](../../../custom-toast/components/simple-toast) - [transaction-toast](../..) ### Graph ```mermaid graph TD; + simple-toast --> transaction-toast-wrapper transaction-toast --> transaction-toast-wrapper style transaction-toast-wrapper fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/src/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.css b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.css similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.css rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.css diff --git a/src/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.tsx b/src/components/toasts-list/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.tsx similarity index 100% rename from src/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.tsx rename to src/components/toasts-list/components/transaction-toast/components/transaction-toast-wrapper/transaction-toast-wrapper.tsx diff --git a/src/components/transaction-toast/readme.md b/src/components/toasts-list/components/transaction-toast/readme.md similarity index 94% rename from src/components/transaction-toast/readme.md rename to src/components/toasts-list/components/transaction-toast/readme.md index bf492c3a..0cbd140a 100644 --- a/src/components/transaction-toast/readme.md +++ b/src/components/toasts-list/components/transaction-toast/readme.md @@ -28,7 +28,7 @@ ### Used by - - [transaction-toast-list](./components/transaction-toast-list) + - [toast-list](../..) ### Depends on @@ -44,7 +44,7 @@ graph TD; transaction-toast --> transaction-toast-content transaction-toast-content --> transaction-toast-details transaction-toast-details --> transaction-toast-details-body - transaction-toast-list --> transaction-toast + toast-list --> transaction-toast style transaction-toast fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/src/components/transaction-toast/transaction-toast.tsx b/src/components/toasts-list/components/transaction-toast/transaction-toast.tsx similarity index 100% rename from src/components/transaction-toast/transaction-toast.tsx rename to src/components/toasts-list/components/transaction-toast/transaction-toast.tsx diff --git a/src/components/toasts-list/components/transaction-toast/transaction-toast.type.ts b/src/components/toasts-list/components/transaction-toast/transaction-toast.type.ts new file mode 100644 index 00000000..8310656f --- /dev/null +++ b/src/components/toasts-list/components/transaction-toast/transaction-toast.type.ts @@ -0,0 +1,67 @@ +// match these interfaces with src/path-to-file.type.ts from sdk-dapp +import { IconName } from '@fortawesome/free-solid-svg-icons'; +import { JSX } from '@stencil/core'; + +export interface IToastDataState { + id: string; + icon: IconName | string | JSX.Element; + hasCloseButton: boolean; + title: string; + iconClassName: string; +} + +export interface ITransactionProgressState { + progressClass?: string; + currentRemaining: number; +} + +export interface ITransaction { + hash: string; + status: string; +} + +export interface ITransactionToast { + toastId: string; + wrapperClass: string; + processedTransactionsStatus: string | JSX.Element; + transactions: ITransaction[]; + toastDataState: IToastDataState; + transactionProgressState?: ITransactionProgressState; +} + +interface ISharedCustomToast { + toastId: string; + type?: string; + onClose?: () => void; +} + +export interface ISimpleToast extends ISharedCustomToast { + icon: IconName | string | JSX.Element; + iconClassName?: string; + title?: string; + message?: string; + /** + * Use `subtitle` to display a row of information between `title` and `message` + */ + subtitle?: string; + instantiateToastElement?: never; +} + +export interface IComponentToast extends ISharedCustomToast { + /** + * A function that creates a custom toast component. + * + * Use `instantiateToastElement` to display a custom agnostic component. + * + * @returns {HTMLElement | null} The custom toast component to be displayed, or `null` if no component is created. + * + * **⚠️ Warning**: Toasts with components will not be persisted on page reload because agnostic components are not serializable. + */ + instantiateToastElement: (() => HTMLElement) | null; + icon?: never; + iconClassName?: never; + title?: never; + message?: never; + subtitle?: never; +} +export type CustomToastType = ISimpleToast | IComponentToast; diff --git a/src/components/toasts-list/readme.md b/src/components/toasts-list/readme.md new file mode 100644 index 00000000..18dd09ee --- /dev/null +++ b/src/components/toasts-list/readme.md @@ -0,0 +1,52 @@ +# transaction-toast-list + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| ------------------- | --------- | ----------- | --------------------- | ----------- | +| `customToasts` | -- | | `CustomToastType[]` | `undefined` | +| `transactionToasts` | -- | | `ITransactionToast[]` | `undefined` | + + +## Methods + +### `getEventBus() => Promise` + + + +#### Returns + +Type: `Promise` + + + + +## Dependencies + +### Depends on + +- [generic-toast](./components/custom-toast) +- [transaction-toast](./components/transaction-toast) + +### Graph +```mermaid +graph TD; + toast-list --> generic-toast + toast-list --> transaction-toast + generic-toast --> custom-toast + generic-toast --> simple-toast + simple-toast --> transaction-toast-wrapper + transaction-toast --> transaction-toast-wrapper + transaction-toast --> transaction-toast-progress + transaction-toast --> transaction-toast-content + transaction-toast-content --> transaction-toast-details + transaction-toast-details --> transaction-toast-details-body + style toast-list fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.css b/src/components/toasts-list/toast-list.css similarity index 81% rename from src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.css rename to src/components/toasts-list/toast-list.css index c6eabc99..5f4bbedb 100644 --- a/src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.css +++ b/src/components/toasts-list/toast-list.css @@ -1,4 +1,4 @@ -.transaction-list { +.toast-list { position: fixed; bottom: 1rem; left: 1rem; @@ -6,7 +6,7 @@ z-index: 9999; } @media (min-width: 760px) { - .transaction-list { + .toast-list { right: 2rem; bottom: 2rem; width: 22.5rem; diff --git a/src/components/toasts-list/toast-list.tsx b/src/components/toasts-list/toast-list.tsx new file mode 100644 index 00000000..9a4d57f9 --- /dev/null +++ b/src/components/toasts-list/toast-list.tsx @@ -0,0 +1,45 @@ +import { Component, h, Prop, Method, forceUpdate } from '@stencil/core'; +import { EventBus, IEventBus } from 'utils/EventBus'; +import { CustomToastType, ITransactionToast } from './components/transaction-toast/transaction-toast.type'; +import { ToastEventsEnum } from './toast-list.types'; +@Component({ + tag: 'toast-list', + styleUrl: 'toast-list.css', +}) +export class ToastList { + private eventBus: IEventBus = new EventBus(); + @Prop() transactionToasts: ITransactionToast[]; + @Prop() customToasts: CustomToastType[]; + + @Method() async getEventBus() { + return this.eventBus; + } + + render() { + return ( +
+ {this.customToasts?.map(toast => ( + this.eventBus.publish(ToastEventsEnum.CLOSE_TOAST, toast.toastId)}> + ))} + {this.transactionToasts?.map(toast => ( + this.eventBus.publish(ToastEventsEnum.CLOSE_TOAST, toast.toastId)}> + ))} +
+ ); + } + + private transactionToastUpdate(payload: ITransactionToast[]) { + this.transactionToasts = [...payload]; + forceUpdate(this); + } + + private customToastsUpdate(payload: CustomToastType[]) { + this.customToasts = [...payload]; + forceUpdate(this); + } + + componentDidLoad() { + this.eventBus.subscribe(ToastEventsEnum.TRANSACTION_TOAST_DATA_UPDATE, this.transactionToastUpdate.bind(this)); + this.eventBus.subscribe(ToastEventsEnum.CUSTOM_TOAST_DATA_UPDATE, this.customToastsUpdate.bind(this)); + } +} diff --git a/src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.types.ts b/src/components/toasts-list/toast-list.types.ts similarity index 53% rename from src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.types.ts rename to src/components/toasts-list/toast-list.types.ts index 0c0eba90..23f2b163 100644 --- a/src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.types.ts +++ b/src/components/toasts-list/toast-list.types.ts @@ -1,4 +1,5 @@ -export enum TransactionToastEventsEnum { +export enum ToastEventsEnum { 'CLOSE_TOAST' = 'CLOSE_TOAST', 'TRANSACTION_TOAST_DATA_UPDATE' = 'TRANSACTION_TOAST_DATA_UPDATE', + 'CUSTOM_TOAST_DATA_UPDATE' = 'CUSTOM_TOAST_DATA_UPDATE', } diff --git a/src/components/transaction-toast/components/transaction-toast-list/readme.md b/src/components/transaction-toast/components/transaction-toast-list/readme.md deleted file mode 100644 index 6b490528..00000000 --- a/src/components/transaction-toast/components/transaction-toast-list/readme.md +++ /dev/null @@ -1,48 +0,0 @@ -# transaction-toast-list - - - - - - -## Properties - -| Property | Attribute | Description | Type | Default | -| -------- | --------- | ----------- | --------------------- | ----------- | -| `data` | -- | | `ITransactionToast[]` | `undefined` | - - -## Methods - -### `getEventBus() => Promise` - - - -#### Returns - -Type: `Promise` - - - - -## Dependencies - -### Depends on - -- [transaction-toast](../..) - -### Graph -```mermaid -graph TD; - transaction-toast-list --> transaction-toast - transaction-toast --> transaction-toast-wrapper - transaction-toast --> transaction-toast-progress - transaction-toast --> transaction-toast-content - transaction-toast-content --> transaction-toast-details - transaction-toast-details --> transaction-toast-details-body - style transaction-toast-list fill:#f9f,stroke:#333,stroke-width:4px -``` - ----------------------------------------------- - -*Built with [StencilJS](https://stenciljs.com/)* diff --git a/src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.tsx b/src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.tsx deleted file mode 100644 index 78df12f8..00000000 --- a/src/components/transaction-toast/components/transaction-toast-list/transaction-toast-list.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, h, Prop, Method, forceUpdate } from '@stencil/core'; -import { ITransactionToast } from '../../transaction-toast.type'; -import { EventBus, IEventBus } from 'utils/EventBus'; -import { TransactionToastEventsEnum } from './transaction-toast-list.types'; -@Component({ - tag: 'transaction-toast-list', - styleUrl: 'transaction-toast-list.css', -}) -export class TransactionToastList { - private eventBus: IEventBus = new EventBus(); - @Prop() data: ITransactionToast[]; - - @Method() async getEventBus() { - return this.eventBus; - } - - render() { - return ( -
- {this.data?.map(toast => ( - this.eventBus.publish(TransactionToastEventsEnum.CLOSE_TOAST, toast.toastId)}> - ))} -
- ); - } - - private dataUpdate(payload: ITransactionToast[]) { - this.data = [...payload]; - forceUpdate(this); - } - - componentDidLoad() { - this.eventBus.subscribe(TransactionToastEventsEnum.TRANSACTION_TOAST_DATA_UPDATE, this.dataUpdate.bind(this)); - } -} diff --git a/src/components/transaction-toast/transaction-toast.type.ts b/src/components/transaction-toast/transaction-toast.type.ts deleted file mode 100644 index a92c7fcd..00000000 --- a/src/components/transaction-toast/transaction-toast.type.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { IconName } from '@fortawesome/free-solid-svg-icons'; -import { JSX } from '@stencil/core'; - -export interface IToastDataState { - id: string; - icon: IconName | string | JSX.Element; - hasCloseButton: boolean; - title: string; - iconClassName: string; -} - -export interface ITransactionProgressState { - progressClass?: string; - currentRemaining: number; -} - -export interface ITransaction { - hash: string; - status: string; -} - -export interface ITransactionToast { - toastId: string; - wrapperClass: string; - processedTransactionsStatus: string | JSX.Element; - transactions: ITransaction[]; - toastDataState: IToastDataState; - transactionProgressState?: ITransactionProgressState; -}