@js4y/dialog

1.1.1 • Public • Published

Dialog

none dependencies npm npm bundle size license

A tiny dependency-free javascript library built on a dialog element with minimal configuration, yet sufficiently variable.

Live Demo: https://bukacekd.github.io/dialog

Features

Installation

Npm

npm install @js4y/dialog

CDN

<script src="https://unpkg.com/@js4y/dialog/dist/index.js"></script>

Usage

Npm

import {Dialog} from '@js4y/dialog';

new Dialog({
    content: 'Hello world!'
});

CDN

<script src="https://unpkg.com/@js4y/dialog/dist/index.js"></script>

<script>
    new js4y.components.Dialog({
        content: 'Hello world!'
    });
<script>

Configuration

The library offers a set of configuration items. Below is an overview of them.

new Dialog({
    className?: string,
    close?: Function,
    constructableSheets?: Array<CSSStyleSheet>,
    content: string | AsyncFunction | Function | HTMLElement,
    id?: string,
    open?: Function,
    styleSheets?: Array<string>
});

className

required: false, type: string

CSS class of dialog.

new Dialog({
    className: 'my-dialog'
});

id

required: false, type: string

CSS Identifier of dialog. If you try to create multiple dialogs with the same identifier, only one will appear on the page - this prevents possible duplicates on the page.

const dialog1 = new Dialog({
    id: 'my-dialog',
    content: 'old content'
});

const dialog2 = new Dialog({
    id: 'my-dialog',
    content: 'new content'
});

dialog1 === dialog2;

According to the example above, only the dialog with the content "new-content" is displayed in the page.

content

required: true, type: string | AsyncFunction | Function | HTMLElement

The content that will be displayed.

new Dialog({
    content: 'Hello <b>world</b>!'
});

new Dialog({
    content: document.querySelector('template'),
});

new Dialog({
    content: async (e, signal) => {
        const response = await fetch('<url>', {signal}),
              data     = await response.text();

        e.content(data);
    }
});

The first parameter of the callback function corresponds to the dialog instance and the second to the AbortSignal object.

open

required: false, type: Function

The function is fired when the dialog is opened. The function parameter corresponds to the dialog instance.

new Dialog({
    open: dialog => console.log('opened', dialog)
});

close

required: false, type: Function

The function is fired when the dialog is closed. The function parameter corresponds to the dialog instance.

new Dialog({
    close: => console.log('closed', dialog)
});

constructableSheets

required: false, type: Array<CSSStyleSheet>

List of constructable stylesheets. Can only be used if the browser supports constructable stylesheets and adoptedStyleSheets.

const sheet = new CSSStyleSheet();
sheet.replaceSync('<any style rules>');

new Dialog({
    constructableSheets: [sheet]
});

If your browser supports import attributes, then you can use:

import sheet from '/dialog.css' with { type: 'css' };

new Dialog({
    constructableSheets: [sheet]
});

styleSheets

required: false, type: Array<string>

List of url addresses of external css styles. Styles are loaded asynchronously

new Dialog({
    styleSheets: ['/dialog.css']
});

Styles can be loaded directly as dialog content.

new Dialog({
    content: `
        <link href="/dialog.css" rel="stylesheet">
        Hello <b>world</b>!
    `
});

In both cases, the dialog only appears when all css styles are loaded or fail to load.

Properties

element: HTMLDialogElement

An instance of the dialog element on the page.

new Dialog({
    content: async e => {
        await e.content('<button data-dialog-action="close">close</button>');

        e.element.querySelector('button').addEventListener('click', () => {
            console.log('was clicked');
        });
    }
});

Methods

abort()

Cancels the display of the dialog if its content is loaded by the fetch api extended by AbortSignal and has not yet been displayed.

const dialog = new Dialog({
    content: async (e, signal) => {
        const response = await fetch('<url>', {signal}),
              data     = await response.text();

        e.content(data);
    }
});

dialog.abort();

open(delay?: number): Promise

Opens the dialog immediately or with a delay.

dialog.open();

close(delay?: number): Promise

Close the dialog immediately or with a delay.

dialog.close(3000);

content(value: string | AsyncFunction | Function | HTMLElement, delay?: number): Promise

Changes the content of the dialog - immediately or with a delay.

dialog.content('🎉');

The use of the method can be useful in the case of displaying the loader during a long-running request.

new Dialog({
    content: async (e, signal) => {
        e.content('please wait...');

        const response = await fetch('<url>', {signal}),
              data     = await response.text();

        await e.content(data);
    }
});

resolve(value?: any): Promise

Executes the callback function of then method. The then method is always executed only once regardless of the number of calls to the resolve method.

dialog.resolve('😀');

reject(reason?: any): Promise

Executes the callback function of catch method. The catch method is always executed only once regardless of the number of calls to the reject method.

dialog.reject('😢');

then(callback: AsyncFunction | Function): Dialog

Callback function that is executed after calling the resolve method.

dialog.then(value => console.log(value));
dialog.resolve('😀');

catch(callback: AsyncFunction | Function): Dialog

Callback function that is executed after calling the catch method.

dialog.catch(reason => console.log(reason));
dialog.reject('😢');

Actions

Html elements inside the dialog can call some methods - the prerequisite is the existence of the corresponding data attribute:

Selector Description
[data-dialog-action="close"] Closes the dialog.
[data-dialog-state="resolve"] Executes the callback function of then method.
[data-dialog-state="reject"] Executes the callback function of reject method.

Actions can be combined with each other.

new Dialog({
    content: `
        Are you sure?
        <button data-dialog-action="resolve close">Yes</button>
        <button data-dialog-action="reject close">No</button>
    `
})
.then(() => console.log('resolve'))
.catch(() => console.log('reject'));

Styling

By default, the dialog cannot be closed by clicking on the backdrop. However, this can be easily changed by adding the css style below to your application.

dialog::backdrop {
    pointer-events: none;
}

The dialog does not contain any styles, except for the basic styles specific to each browser. Two css selectors are available for animation purposes:

Selector Description
[data-dialog-state="open"] State indicating the opening of a dialog.
[data-dialog-state="close"] State indicating the closing of a dialog.

Examples of animated dialogs:

dialog,
dialog::backdrop {
    opacity: 0;
    transition: opacity .3s;
}

[data-dialog-state="open"],
[data-dialog-state="open"]::backdrop {
    opacity: 1;
}

// or

dialog {
    translate: 0 15%;
}

dialog,
dialog::backdrop {
    opacity: 0;
    transition: opacity .3s, translate .3s;
}

[data-dialog-state="open"],
[data-dialog-state="open"]::backdrop {
    opacity: 1;
    translate: none;
}

[data-dialog-state="close"] {
    translate: 0 -15%;
}

Browser support

alt chrome alt edge alt firefox alt opera alt safari
Chrome 84+ Edge 84+ Firefox 98+ Opera 70+ Safari 15.4+

License

The project is licensed under MIT license.

Related

  • CountUp - A tiny dependency-free JavaSript library for animating numeric values.
  • Loader - A tiny dependency-free javascript loading spinner component with minimal configuration.
  • lockScroll - A set of methods to lock scrolling within an element or an entire page.

Package Sidebar

Install

npm i @js4y/dialog

Weekly Downloads

13

Version

1.1.1

License

MIT

Unpacked Size

29.9 kB

Total Files

10

Last publish

Collaborators

  • d.a.v.e.