Skip to content

Commit

Permalink
docs: add examples for wc-toast using script tag
Browse files Browse the repository at this point in the history
  • Loading branch information
abdmmar committed Feb 25, 2024
1 parent 6cb49e3 commit 79c2c3e
Show file tree
Hide file tree
Showing 9 changed files with 876 additions and 0 deletions.
41 changes: 41 additions & 0 deletions examples/wc-toast-script/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>wc-toast using script</title>
<script type="module" src="./src/wc-toast/index.js"></script>
<style>
.root {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}

.cheers {
border: none;
padding: 0.7rem 1rem;
color: white;
background-color: cornflowerblue;
border-radius: 4px;
}
</style>
</head>
<body>
<wc-toast></wc-toast>
<div class="root">
<button class="cheers">Cheers</button>
</div>
</body>
<script type="module">
import { toast } from "./src/wc-toast/index.js";

document.querySelector(".cheers").addEventListener("click", () => {
console.log("Cheers");
toast("Cheers!");
});
</script>
<!-- Use src if you want to separate the javascript code from the html -->
<!-- <script type="module" src="./index.js"></script> -->
</html>
6 changes: 6 additions & 0 deletions examples/wc-toast-script/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { toast } from "./src/wc-toast/index.js";

document.querySelector(".cheers").addEventListener("click", () => {
console.log("Cheers");
toast("Cheers!");
});
8 changes: 8 additions & 0 deletions examples/wc-toast-script/src/wc-toast/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import toast from './toast.js';
import WCToast from './wc-toast.js';
import WCToastItem from './wc-toast-item.js';
import WCToastIcon from './wc-toast-icon.js';
import WCToastContent from './wc-toast-content.js';
import WCToastCloseButton from './wc-toast-close-button.js';

export { toast, WCToast, WCToastItem, WCToastContent, WCToastIcon, WCToastCloseButton };
189 changes: 189 additions & 0 deletions examples/wc-toast-script/src/wc-toast/toast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/**
* Generate an id
* @returns {string} id
*/
const generateId = (function () {
let count = 0;
return function () {
return (++count).toString();
};
})();

function createToast(
message,
type = 'blank',
options = {
icon: { type: '', content: '' },
duration: '',
closeable: false,
theme: { type: 'light', style: { background: '', color: '', stroke: '' } }
}
) {
const id = generateId();
const toastItem = createToastItem(id, type, options);
const toastIcon = createToastIcon(type, options);
const toastContent = createToastContent(message);

toastItem.appendChild(toastIcon);
toastItem.appendChild(toastContent);

if (options.closeable) toastItem.appendChild(createToastCloseButton(toastItem));

document.querySelector('wc-toast').appendChild(toastItem);

return {
id,
type,
message,
...options
};
}

function createToastItem(id, type, options) {
const { duration, theme } = options;
const toastItem = document.createElement('wc-toast-item');
const isDarkTheme = window?.matchMedia && window.matchMedia('(prefers-color-scheme: dark)');
const prefersTheme = isDarkTheme?.matches ? 'dark' : 'light';

toastItem.setAttribute('type', type);
toastItem.setAttribute('duration', duration ? duration : '');
toastItem.setAttribute('data-toast-item-id', id);
toastItem.setAttribute('theme', theme?.type ? theme.type : prefersTheme);

if (theme?.type === 'custom' && theme?.style) {
const { background, stroke, color } = theme.style;
toastItem.style.setProperty('--wc-toast-background', background);
toastItem.style.setProperty('--wc-toast-stroke', stroke);
toastItem.style.setProperty('--wc-toast-color', color);
}

return toastItem;
}

function createToastIcon(type, options) {
const { icon } = options;
const toastIcon = document.createElement('wc-toast-icon');

toastIcon.setAttribute('type', icon?.type ? icon.type : type);
toastIcon.setAttribute('icon', icon?.content && icon?.type === 'custom' ? icon.content : '');
if (icon?.type === 'svg') toastIcon.innerHTML = icon?.content ? icon.content : '';

return toastIcon;
}

function createToastContent(message) {
const toastContent = document.createElement('wc-toast-content');
toastContent.setAttribute('message', message);
return toastContent;
}

function createToastCloseButton(toastItem) {
const toastCloseButton = document.createElement('wc-toast-close-button');
toastCloseButton.addEventListener('click', () => {
toastItem.classList.add('dismiss-with-close-button');
});
return toastCloseButton;
}

/**
* Create toast from type
* @param {'blank' | 'success' | 'loading' | 'error' | 'custom'} type
*/
function createHandler(type) {
/**
* @param {string} message
* @param {ToastOptions} [options]
* @returns {string}
*/
return function (message, options) {
const toast = createToast(message, type, options);
return toast.id;
};
}

/**
* Author: Timo Lins
* License: MIT
* Source: https://github.com/timolins/react-hot-toast/blob/main/src/core/toast.ts
*/

/**
* @typedef {Object} ToastOptions
* @property {object} [icon]
* @property {string} [icon.type]
* @property {string} [icon.content]
* @property {number} [duration=3500]
* @property {object} [theme]
* @property {'light' | 'dark' | 'custom'} [theme.type="light"]
* @property {object} [theme.style]
* @property {string} [theme.style.background]
* @property {string} [theme.style.color]
* @property {string} [theme.style.stroke]
* @property {boolean} [closeable=false]
*/

/**
* Create blank toast
* @param {string} message
* @param {ToastOptions} [options]
* @returns {string}
*/
function toast(message, options) {
return createHandler('blank')(message, options);
}

toast.loading = createHandler('loading');
toast.success = createHandler('success');
toast.error = createHandler('error');

/**
* Dismiss toast by id
* @param {string} id
* @returns {void}
* @example
* const id = toast.loading('Loading...')
* ...
* toast.dismiss(id);
*/
toast.dismiss = function (toastId) {
const toastItems = document.querySelectorAll('wc-toast-item');

for (const toastItem of toastItems) {
const dataId = toastItem.getAttribute('data-toast-item-id');

if (toastId === dataId) {
toastItem.classList.add('dismiss');
}
}
};

/**
* Automatically add loading toast, success or error toast in promise
* @param {Promise} promise
* @param {object} message
* @param {string} message.loading
* @param {string} message.success
* @param {string} message.error
* @param {ToastOptions} [options]
* @returns {Promise}
*/
toast.promise = async function (
promise,
message = { loading: '', success: '', error: '' },
options
) {
const id = toast.loading(message.loading, { ...options });

try {
const result = await promise;
toast.dismiss(id);
toast.success(message.success, { ...options });
return result;
} catch (error) {
toast.dismiss(id);
toast.error(message.error, { ...options });
return error;
}
};

export default toast;
56 changes: 56 additions & 0 deletions examples/wc-toast-script/src/wc-toast/wc-toast-close-button.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* @cssprop [--wc-toast-stroke=#2a2a32] - stroke. Default is #2a2a32;
*
* @summary - button to dismiss toast item
*
* @tag wc-toast-close-button
*/
export default class WCToastCloseButton extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.template = document.createElement('template');
this.template.innerHTML = WCToastCloseButton.template();
this.shadowRoot.append(this.template.content.cloneNode(true));
}

static template() {
return `
<style>
:host {
width: 20px;
opacity: 1;
height: 20px;
border-radius: 2px;
border: 1px solid #dadce0;
background: var(--wc-toast-background);
position: relative;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
margin-left: 5px;
}
svg {
stroke: var(--wc-toast-stroke, #2a2a32);
}
</style>
<svg
focusable="false"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
`;
}
}

customElements.define('wc-toast-close-button', WCToastCloseButton);
47 changes: 47 additions & 0 deletions examples/wc-toast-script/src/wc-toast/wc-toast-content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**
* @attr {string} message - message to be displayed in toast item
*
* @slot content - add your custom content such as HTMLElement to toast item
*
* @cssprop [--wc-toast-content-margin='4px 10px'] - margin of toast content
* @cssprop [--wc-toast-color="#000"] - color. Default is #000
* @cssprop [--wc-toast-font-family="'Roboto', 'Amiri', sans-serif"] - font-family. Default is 'Roboto', 'Amiri', sans-serif;
* @cssprop [--wc-toast-font-size="16px"] - font-size. Default is 16px
*
* @summary - message or content to be displayed in toast item
*
* @tag wc-toast-content
*/
export default class WCToastContent extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.template = document.createElement('template');
this.template.innerHTML = WCToastContent.template();
this.shadowRoot.append(this.template.content.cloneNode(true));
}

connectedCallback() {
this.message = this.getAttribute('message');
this.shadowRoot.querySelector('slot[name="content"]').innerHTML = this.message;
}

static template() {
return `
<style>
:host {
display: flex;
justify-content: center;
flex: 1 1 auto;
margin: var(--wc-toast-content-margin) !important;
color: var(--wc-toast-color, #000);
font-family: var(--wc-toast-font-family);
font-size: var(--wc-toast-font-size);
}
</style>
<slot name="content"></slot>
`;
}
}

customElements.define('wc-toast-content', WCToastContent);
Loading

0 comments on commit 79c2c3e

Please sign in to comment.