main
HerrHase 3 years ago
parent b1a30886b0
commit 3d4a35fffb

@ -1,2 +1,34 @@
# notification # Tiny Components - Notification
Created with [Riot.js](https://riot.js.org)
Handle notification by using [Plain-UI](https://plain-ui.com) and [Observable](https://github.com/riot/observable)
## Install
```
npm install @tiny-components\notification --save
```
## You can use it like this
Add to your App once, don't forget to register and mount,
```
<tiny-notification></tiny-notification>
```
Call function anywhere, to run through the store and display a notification.
```
import notificationStore from './@tiny-components/notification/src/notificationStore.js'
notificationStore.danger('Error! Something is wrong')
```
## Options
| attribute | values |
|---|---|
| wrapper-class | |
| timeout | |

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tiny Components | Notification</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link href="/example.css" rel="stylesheet" type="text/css">
</head>
<body>
<header class="header">
<div class="bar">
<div class="bar__start">
<h1 class="m-top-4 m-bottom-4 h4">
@tiny-components/notification
</h1>
</div>
<div class="bar__main justify-end">
<a class="button button--small m-left-sm-3 m-bottom-0" href="https://gitea.node001.net/tiny-components/notification" rel="noopener" target="_blank">
Gitea
<svg class="m-left-3 icon fill-text" aria-hidden="true">
<use xlink:href="symbol-defs.svg#icon-gitea"></use>
</svg>
</a>
<a class="button button--small m-left-sm-3 m-bottom-0" href="https://gitea.node001.net/tiny-components/notification" rel="noopener" target="_blank">
Github
<svg class="m-left-3 icon fill-text" aria-hidden="true">
<use xlink:href="symbol-defs.svg#icon-github"></use>
</svg>
</a>
</div>
</div>
</header>
<div class="container">
<div class="grid">
<div class="col-12">
<div class="m-top-5">
<example-action-button></example-action-button>
</div>
</div>
</div>
</div>
<tiny-notification></tiny-notification>
<script type="text/javascript" src="/example.js"></script>
</body>
</html>

@ -0,0 +1,13 @@
{
"/spritemap.js": "/spritemap.js",
"/example.js": "/example.js",
"/.css": "/.css",
"/IBMPlexMono-Bold.eot": "/IBMPlexMono-Bold.eot",
"/IBMPlexMono-Bold.ttf": "/IBMPlexMono-Bold.ttf",
"/IBMPlexMono-Bold.woff": "/IBMPlexMono-Bold.woff",
"/IBMPlexMono-Bold.woff2": "/IBMPlexMono-Bold.woff2",
"/IBMPlexMono.eot": "/IBMPlexMono.eot",
"/IBMPlexMono.ttf": "/IBMPlexMono.ttf",
"/IBMPlexMono.woff": "/IBMPlexMono.woff",
"/IBMPlexMono.woff2": "/IBMPlexMono.woff2"
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 66 KiB

@ -0,0 +1 @@
(self.webpackChunk_tiny_components_notification=self.webpackChunk_tiny_components_notification||[]).push([[355],{256:()=>{}}]);

@ -0,0 +1,5 @@
{
"/example/spritemap.js": "/example/spritemap.js",
"/example/example.js": "/example/example.js",
"/example/example.css": "/example/example.css"
}

27
package-lock.json generated

@ -4091,6 +4091,12 @@
} }
} }
}, },
"immutable": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0.tgz",
"integrity": "sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==",
"dev": true
},
"import-fresh": { "import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -5880,6 +5886,27 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"dev": true "dev": true
}, },
"sass": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.51.0.tgz",
"integrity": "sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
}
},
"sass-loader": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz",
"integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==",
"dev": true,
"requires": {
"klona": "^2.0.4",
"neo-async": "^2.6.2"
}
},
"schema-utils": { "schema-utils": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",

@ -18,6 +18,8 @@
"@riotjs/webpack-loader": "^6.0.0", "@riotjs/webpack-loader": "^6.0.0",
"laravel-mix": "^6.0.43", "laravel-mix": "^6.0.43",
"laravel-mix-purgecss": "^6.0.0", "laravel-mix-purgecss": "^6.0.0",
"sass": "^1.51.0",
"sass-loader": "^12.6.0",
"svg-spritemap-webpack-plugin": "^4.4.0" "svg-spritemap-webpack-plugin": "^4.4.0"
} }
} }

@ -0,0 +1,42 @@
<example-action-button>
<div class="m-top-4 m-bottom-4">
<button class="button button--danger m-right-md-3" onclick={ (event) => { handleClickDanger(event) } }>
Show Error!
</button>
<button class="button button--success m-left-md-3" onclick={ (event) => { handleClickSuccess(event) } }>
Show Success!
</button>
</div>
<script>
import notificationStore from './notificationStore.js'
export default {
/**
*
*
* @param {Object} event
* @param {Object} item
*
*/
handleClickDanger(event) {
notificationStore.danger('Error!')
},
/**
*
*
* @param {Object} event
* @param {Object} item
*
*/
handleClickSuccess(event) {
notificationStore.success('Success!')
}
}
</script>
</example-action-button>

@ -0,0 +1,10 @@
import * as riot from 'riot'
import TinyNotification from './notification.riot'
import ExampleActionButton from './example-action-button.riot'
riot.register('tiny-notification', TinyNotification)
riot.register('example-action-button', ExampleActionButton)
riot.mount('tiny-notification')
riot.mount('example-action-button')

@ -0,0 +1,2 @@
@import
'../node_modules/@tiny-components/plain-ui/src/scss/plain-ui';

@ -1,9 +1,9 @@
<tiny-notification> <tiny-notification>
<div class="toast-wrapper toast-wrapper--right" if={ state.items.length > 0 }> <div class="toast-wrapper { state.wrapperClass }" if={ state.items.length > 0 }>
<div <div
id={ state.prefixId + item.id } class={ item.classes.join(' ') } id={ item.id } class={ item.classes.join(' ') }
each={ item in state.items } each={ item in state.items }
onclick={ (event) => { this.handleClick(event, item) } }> onclick={ (event) => { handleClick(event, item) } }>
<div class="toast__body"> <div class="toast__body">
{ item.message } { item.message }
@ -14,7 +14,7 @@
<script> <script>
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import notificationStore from './../stores/notification' import notificationStore from './notificationStore.js'
/** /**
* notification * notification
@ -30,15 +30,16 @@
state: { state: {
items: [], items: [],
timeout: 3000, timeout: 5000,
prefixId: 'tiny-notification-' prefixId: 'tiny-notification-',
wrapperClass: ''
}, },
/** /**
* on mounted * on mounted
* *
* @param {object} props * @param {Object} props
* @param {object} state * @param {Object} state
* *
*/ */
onMounted(props, state) { onMounted(props, state) {
@ -48,28 +49,38 @@
state.timeout = props.timeout state.timeout = props.timeout
} }
// change timeout by props
if (props.wrapperClass) {
state.wrapperClass = props.wrapperClass
}
// adding service for notifications and listen to "update" // adding service for notifications and listen to "update"
notificationStore.on('append', (item) => { notificationStore.on('append', (item) => {
// adding attributes // adding attributes
item.id = 'toast-' + uuidv4() item.id = this.state.prefixId + 'toast-' + uuidv4()
item.classes = [
'toast',
'toast--' + item.type
]
// create timeout to remove notification // create timeout to remove notification
item.timeout = setTimeout(() => { item.timeout = setTimeout(() => {
this.removeItem(item) this.removeItem(item)
}, this.state.timeout) }, this.state.timeout)
item.classes = [
'toast',
'toast--' + item.type
]
this.state.items.push(item) this.state.items.push(item)
this.update() this.update()
// add animation setTimeout(() => {
requestAnimationFrame(() => { for (let i = 0; i < this.state.items.length; i++) {
this.$('#' + state.prefixId + item.id).classList.add('toast--animation') if (this.state.items[i].id === item.id) {
}) this.state.items[i].classes.push('toast--animation')
this.update()
}
}
}, 10)
}) })
}, },
@ -77,38 +88,46 @@
* remove single item * remove single item
* *
* *
* @param {object} item * @param {Object} item
* *
*/ */
removeItem(item) { removeItem(item) {
// adding event if animationend remove html element // set event transitionend only to item that has to removed
this.$('#' + this.state.prefixId + item.id).addEventListener('transitionend', () => { // after animation is complete search for cleartimeout and remove it
// form items
this.$('#' + item.id).addEventListener('transitionend', () => {
const items = []
// find item in state and remove it
for (let i = 0; i < this.state.items.length; i++) { for (let i = 0; i < this.state.items.length; i++) {
if (this.state.items[i].id === item.id) { if (this.state.items[i].id === item.id) {
clearTimeout(this.state.items[i].timeout) clearTimeout(this.state.items[i].timeout)
this.state.items.splice(i, 1) } else {
items.push(this.state.items[i])
break;
} }
} }
this.state.items = items
this.update() this.update()
}) })
// add animation // remove class animation and update
requestAnimationFrame(() => { requestAnimationFrame(() => {
this.$('#' + this.state.prefixId + item.id).classList.remove('toast--animation') for (let i = 0; i < this.state.items.length; i++) {
if (this.state.items[i].id === item.id) {
this.state.items[i].classes.pop('toast--animation')
this.update()
}
}
}) })
}, },
/** /**
* remove item by clicked on it * remove item by clicked on it
* *
* @param {object} event * @param {Object} event
* @param {object} item * @param {Object} item
* *
*/ */
handleClick(event, item) { handleClick(event, item) {

@ -0,0 +1,80 @@
const mix = require('laravel-mix')
const path = require('path')
require('laravel-mix-purgecss')
// plugins
const SvgSpritemapPlugin = require('svg-spritemap-webpack-plugin')
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel applications. By default, we are compiling the CSS
| file for the application as well as bundling up all the JS files.
|
*/
mix.webpackConfig({
module: {
rules: [{
test: /\.riot$/,
use: [{
loader: '@riotjs/webpack-loader',
options: {
hot: false
}
}]
}
]},
plugins: [
new SvgSpritemapPlugin('node_modules/@tiny-components/plain-ui/src/icons/mono-icons/svg/*.svg', {
output: {
filename: 'public/symbol-defs.svg',
chunk: {
keep: true
},
svgo: {
plugins: [{
name: 'convertStyleToAttrs',
active: true
},{
name: 'removeStyleElement',
active: true
}, {
name: 'removeAttrs',
params: {
attrs: 'fill'
}
}]
}
},
sprite: {
prefix: 'icon-'
}
})
]
})
mix
.setPublicPath('./example')
.js('src/example.js', 'example')
.sass('src/example.scss', 'example')
.purgeCss({
extend: {
content: [
path.join(__dirname, 'src/**.riot'),
path.join(__dirname, 'example/index.html')
]
}
})
.options({
terser: {
extractComments: false,
},
processCssUrls: false
})
.copyDirectory('node_modules/@tiny-components/plain-ui/src/fonts/IBM*', 'example')
Loading…
Cancel
Save