Skip to content

Commit

Permalink
Code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel-Knights committed Feb 14, 2021
1 parent 0cf795d commit 072dc3c
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 76 deletions.
145 changes: 77 additions & 68 deletions src/lib/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,97 +5,112 @@ import { validateLocalOptions } from './validate'

const toastQueue: Array<[Element, Element]> = []

function renderToast(app: App, options: Options): void {
// Render toast container
const container = document.createElement('div')
const mobileContainer = document.createElement('div')
function formatAndMountContainer(el: Element, className: string, target: Element): void {
const attributes = [
['role', 'status'],
['aria-live', 'polite'],
['aria-atomic', 'false']
]

attributes.forEach((attr) => {
el.setAttribute(attr[0], attr[1])
})

el.className = className
target.appendChild(el)
}

// Set container attributes
container.className = 'dk__toast-container'
container.setAttribute('role', 'status')
container.setAttribute('aria-live', 'polite')
container.setAttribute('aria-atomic', 'false')
function formatToastFromOptions(
text: string,
options: Options,
localOptions: LocalOptions,
duration?: number | false
): Element {
const toast = document.createElement('div')
const left = localOptions.slotLeft
const right = localOptions.slot || localOptions.slotRight

// Add classes
toast.className = 'dk__toast'
if (options.class) toast.classList.add(options.class)
if (localOptions.class) toast.classList.add(localOptions.class)
if (localOptions.type) toast.classList.add(`dk__${localOptions.type}`)

// If text
if (text) toast.textContent = text
// If left slot
if (left) {
toast.innerHTML = `<div class="dk__icon-left">${left}</div>` + toast.innerHTML
}
// If right slot
if (right) {
toast.innerHTML += `<div class="dk__icon-right">${right}</div>`
}
// If slot only
if (!text && (left || right)) toast.classList.add('dk__icon-only')

mobileContainer.className = 'dk__toast-mobile-container'
mobileContainer.setAttribute('role', 'status')
mobileContainer.setAttribute('aria-live', 'polite')
mobileContainer.setAttribute('aria-atomic', 'false')
const styles = localOptions.styles ? localOptions.styles : options.styles
toast.setAttribute('style', formatCssProperties(styles, duration))

// Append
document.body.appendChild(container)
document.body.appendChild(mobileContainer)
if (localOptions.disableClick) {
// Prevent hover styling
toast.style.cursor = 'default'
toast.style.opacity = '1'
}

function DKToast(text: string, localOptions?: LocalOptions): void {
if (!localOptions) localOptions = {}
const toast = document.createElement('div')
const left = localOptions.slotLeft
const right = localOptions.slot || localOptions.slotRight
let clicked: boolean
return toast
}

function toastPlugin(app: App, options: Options): void {
const container = document.createElement('div')
const mobileContainer = document.createElement('div')

formatAndMountContainer(container, 'dk__toast-container', document.body)
formatAndMountContainer(mobileContainer, 'dk__toast-mobile-container', document.body)

function renderToast(text: string, localOptions?: LocalOptions): void {
if (!localOptions) localOptions = {}
if (!validateLocalOptions(text, localOptions)) return

const positions = {
y: localOptions.positionY || options.positionY,
x: localOptions.positionX || options.positionX
}

// Render toast section
const section =
document.querySelector(`.dk__toast-${positions.y}-${positions.x}`) ||
document.createElement('div')
const toastCount = document.querySelectorAll('.dk__toast').length / 2

// Remove oldest toast if max limit is reached
if (options.max && toastCount >= options.max) {
toastQueue[0][0].parentElement?.removeChild(toastQueue[0][0])
toastQueue[0][1].parentElement?.removeChild(toastQueue[0][1])
toastQueue.shift()
}

// If section doesn't exist, format and mount
if (!section.className) {
// Set section attributes
section.className = `dk__toast-section dk__toast-${positions.y}-${positions.x}`
section.setAttribute('role', 'status')
section.setAttribute('aria-live', 'polite')
section.setAttribute('aria-atomic', 'false')

// Append
container.appendChild(section)
}

toast.className = 'dk__toast'
if (options.class) toast.classList.add(options.class)
if (localOptions.class) toast.classList.add(localOptions.class)
if (localOptions.type) toast.classList.add(`dk__${localOptions.type}`)
const className = `dk__toast-section dk__toast-${positions.y}-${positions.x}`

// If text
if (text) toast.textContent = text
// If left slot
if (left) {
toast.innerHTML = `<div class="dk__icon-left">${left}</div>` + toast.innerHTML
formatAndMountContainer(section, className, container)
}
// If right slot
if (right) {
toast.innerHTML += `<div class="dk__icon-right">${right}</div>`
}
// If slot only
if (!text && (left || right)) toast.classList.add('dk__icon-only')

// Determine if duration is a number or false, local or global
const duration =
localOptions.duration || localOptions.duration === false
? localOptions.duration
: options.duration
const styles = localOptions.styles ? localOptions.styles : options.styles

toast.setAttribute('style', formatCssProperties(styles, duration))
const toast = formatToastFromOptions(text, options, localOptions, duration)
const mobileClone = toast.cloneNode(true)

if (localOptions.disableClick) {
toast.style.cursor = 'default'
toast.style.opacity = '1'
}
// Prevent attempting to remove toast if it's been removed by click
let clicked: boolean

const mobileClone = toast.cloneNode(true)
function removeToastPair(e?: Event): void {
if (e) clicked = true

function removeToastPair(): void {
if ([...section.children].includes(toast)) {
section.removeChild(toast)
}
Expand All @@ -104,16 +119,10 @@ function renderToast(app: App, options: Options): void {
}
}

function clickHandler(): void {
clicked = true

removeToastPair()
}

// Remove toast on click
if (!options.disableClick && !localOptions.disableClick) {
toast.addEventListener('click', clickHandler)
mobileClone.addEventListener('click', clickHandler)
// Remove toast on click
toast.addEventListener('click', removeToastPair)
mobileClone.addEventListener('click', removeToastPair)
}

toastQueue.push([toast, mobileClone as Element])
Expand All @@ -129,8 +138,8 @@ function renderToast(app: App, options: Options): void {
}, duration)
}

app.config.globalProperties.$toast = DKToast
app.provide('$toast', DKToast)
app.config.globalProperties.$toast = renderToast
app.provide('$toast', renderToast)
}

export default renderToast
export default toastPlugin
6 changes: 3 additions & 3 deletions src/lib/styles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Options } from './types'

// Minify CSS
/** Minify CSS */
function minify(styles: string): string {
let selector = false
let value = false
Expand Down Expand Up @@ -33,7 +33,7 @@ function minify(styles: string): string {
return minified
}

// Format CSS from camelCase
/** Format CSS from camelCase */
export function formatCssProperties(
styles?: Record<string, string>,
duration?: number | false
Expand Down Expand Up @@ -72,7 +72,7 @@ export function formatCssProperties(
return formatted
}

// Append minified stylesheet to document head
/** Append minified stylesheet to document head */
export function appendStylesheet(options: Options): void {
const { duration, styles, positionY } = options
// Format style properties/values
Expand Down
5 changes: 3 additions & 2 deletions src/lib/toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import renderToast from './render'
*
* ---
* **Options:**
* @property `class` - CSS class to be added to every toast.
* @property `disableClick?: boolean`
* @property `duration` - Time in milliseconds before hiding the toast notification.
* @property `max` - Max number of toasts allowed per-section at any one time.
* @property `positionX` - 'left', 'right' or 'center'.
* @property `positionY` - 'top' or 'bottom'.
* @property `styles` - CSS key/value pairs.
* @property `class` - CSS class to be added to every toast.
* @property `max` - Max number of toasts allowed per-section at any one time.
*/
const toastPlugin = {
install: (app: App, options: Options): void => {
Expand Down
4 changes: 1 addition & 3 deletions todo.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
disable click option
check local options has priority over global options
unit-tests
code cleanup
unit-tests

0 comments on commit 072dc3c

Please sign in to comment.