Compare commits

..

No commits in common. 'main' and 'feature/field-error' have entirely different histories.

@ -1,4 +1,4 @@
# Tiny Components - Validator # Tiny Validator
Created with [Riot.js](https://riot.js.org) Created with [Riot.js](https://riot.js.org)
@ -10,13 +10,13 @@ For Validation this Component uses [Validate.js](https://validatejs.org/)
## Install ## Install
```bash ```bash
npm install @tiny-components/validator --save npm install tiny-validator --save
``` ```
## You can use it like this ## How to use
```javascript ```javascript
<form class="form" onsubmit={ (event) => ( state.validator.submit(event) ) }>> <form onsubmit={ (event) => { state.validator.handle(event) }} novalidate>
<div class="field"> <div class="field">
<label> <label>
email email
@ -38,51 +38,17 @@ npm install @tiny-components/validator --save
import Validator from './validator.js' import Validator from './validator.js'
export default { export default {
state: {
validator: { }
},
onBeforeMount() { onBeforeMount() {
// creating formValidator this.state.validator = new Validator({
this.state.validator = new FormValidator(this.$('.form'), { email: {
'email': { presence: true
'presence': true, email: true
'email': true
}, },
'password': { password: {
'presence': true presence: true
} }
}) }, this)
// adding on success
this.state.validator.onSuccess((event, data) => {
this.handleSuccess(event, data)
})
// adding on error
this.state.validator.onError((event, errors, data) => {
this.handleError(event, errors, data)
})
},
/**
*
*/
handleSuccess(event, data)
{
event.preventDefault()
this.update()
},
/**
*
*/
handleError(event, errors, data)
{
this.update()
} }
} }
</script> </script>
``` ```

@ -0,0 +1 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}

File diff suppressed because one or more lines are too long

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Demo | Tiny Validator</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link href="styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<form class="form" novalidate>
<div class="field">
<label>
email
<input type="email" name="email" />
</label>
<field-error name="email"></field-error>
</div>
<div class="field">
<label>
password
<input type="password" name="password" />
</label>
<field-error name="password"></field-error>
</div>
<button type="submit">Send</button>
</form>
<script type="text/javascript" src="demo.js"></script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,85 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tiny Components | Validator</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/validator
</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/validator" 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>
</div>
</div>
</header>
<div class="container">
<div class="grid">
<div class="col-12">
<h2>
Form
</h2>
<form class="form-html" novalidate method="post">
<div class="field-group">
<label class="field-label">
email
<input type="email" class="field-text" name="email" />
</label>
<field-error name="email"></field-error>
</div>
<div class="field-group">
<label class="field-label">
password
<input type="password" class="field-text" name="password" />
</label>
<field-error name="password"></field-error>
</div>
<button class="button" type="submit">
Send
</button>
</form>
<div id="result" class="panel color-text-contrast background-color-success hidden">
<div class="panel__body">
<div class="content m-bottom-last-child-0">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="grid">
<div class="col-12">
<h2>
Form - Inside a Riot Component
</h2>
<form-component></form-component>
</div>
</div>
</div>
<script type="text/javascript" src="/example.js"></script>
</body>
</html>

@ -0,0 +1,4 @@
{
"/demo/demo.js": "/demo/demo.js",
"/demo/demo.css": "/demo/demo.css"
}

25561
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,24 +1,25 @@
{ {
"name": "@tiny-components/validator", "name": "@tentakelfabrik/tiny-validator",
"version": "0.3.0", "version": "1.0.0",
"description": "Form Validation with Riotjs", "description": "Form Validator with validator.js for riotjs",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git@git.node001.net:tiny-components/validator.git" "url": "git@github.com:tentakelfabrik/tiny-validator.git"
}, },
"author": "Björn Hase <herrhase@node001.net>", "author": "Björn Hase",
"license": "GPLV3", "license": "MIT",
"dependencies": { "dependencies": {
"@tiny-components/plain-ui": "^0.6.0",
"form-serialize": "^0.7.2", "form-serialize": "^0.7.2",
"riot": "^10.1.4", "riot": "^5.1.2",
"validate.js": "^0.13.1" "validate.js": "^0.13.1"
}, },
"devDependencies": { "devDependencies": {
"@riotjs/webpack-loader": "^10.0.0", "@riotjs/compiler": "^5.1.3",
"@tiny-components/webpack": "^0.6.0" "@riotjs/webpack-loader": "^5.0.0",
}, "cross-env": "^7.0.3",
"scripts": { "laravel-mix": "^6.0.5",
"build": "webpack --mode development --config webpack.config.js" "postcss": "^8.2.1",
"sass": "^1.32.0",
"sass-loader": "^8.0.2"
} }
} }

@ -1,6 +0,0 @@
{
"/js/spritemap.js": "/js/spritemap.js?version=b725f521ce46904ca4235a981dcc41cc",
"/symbol-defs.svg": "/symbol-defs.svg?version=286109f83fb513b8a93efe3ce8275708",
"/js/index.js": "/js/index.js?version=fb77e305492f2775d0e8190a850d8172",
"/css/styles.css": "/css/styles.css?version=20a3f6b9e3a6fee16ca52e289f00a5af"
}

@ -1,852 +0,0 @@
/*!**************************************************************************************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js??ruleSet[1].rules[0].use[1]!./node_modules/sass-loader/dist/cjs.js!./src/styles.scss ***!
\**************************************************************************************************************************************/
@charset "UTF-8";
@font-face {
font-family: "IBM Plex Mono";
src: url("IBMPlexMono.eot");
src: url("IBMPlexMono.eot?#iefix") format("embedded-opentype"), url("IBMPlexMono.woff2") format("woff2"), url("IBMPlexMono.woff") format("woff"), url("IBMPlexMono.ttf") format("truetype");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "IBM Plex Mono";
src: url("IBMPlexMono-Bold.eot");
src: url("IBMPlexMono-Bold.eot?#iefix") format("embedded-opentype"), url("IBMPlexMono-Bold.woff2") format("woff2"), url("IBMPlexMono-Bold.woff") format("woff"), url("IBMPlexMono-Bold.ttf") format("truetype");
font-weight: bold;
font-style: normal;
font-display: swap;
}
/**
* functions
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* strip unit from value
*
* @param {mixed} $value
* @return {number}
*
*/
/**
*
*
* https://css-tricks.com/snippets/sass/str-replace-function/
*
*/
/**
* get value of key "default" in map
*
* @param {map} $value
* @return {boolean|unit}
*
*/
/**
* factor
*
*
*
* @param {integer} $x
* @return {float}
*
*/
/**
* mixins
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* Clear Floats
*
*
*
*/
/**
* clear styles from list
*
*
*/
/**
* media-queries as mixins
* based on breakpoints from variables
*
*
*
*/
/**
* Set property and his value for each Breakpoint
*
* (
* $md: 10px
* )
*
*
* @param {css} $property
* @param {map} $breakpoints
* @param {Boolean} $important [false]
*
*/
/**
* Set property and his value with an factor for each Breakpoint
*
* (
* $md: 10px
* )
*
* @param {css} $property
* @param {number} $factor
* @param {map} $breakpoints
* @param {Boolean} $important [false]
*
*/
/**
* Set font-size from Breakpoints, use for calculating difference from font-size and default font-size
*
* (
* $md: 1rem
* )
*
* @param {map} $breakpoints
* @param {unit} $font-size
* @param {unit} $default
* @param {Boolean} $important [false]
*
*/
/**
* adding overlay with z-index and color
*
* @param {z-index}
* @param {color}
*
*/
/**
* variables
*
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* grid
*
*/
:root {
--grid-columns: 12;
--grid-grid-spacing: 15px;
--grid-xs: 576px;
--grid-sm: 768px;
--grid-md: 992px;
--grid-lg: 1200px;
--grid-xlg: 1600px;
--grid-xxs-max: 575px;
--grid-xs-max: 767px;
--grid-sm-max: 991px;
--grid-md-max: 1199px;
--grid-lg-max: 1599px;
}
/**
* fonts
*
*/
/**
* colors
*
*
*/
/**
* margin
*
*/
/**
* padding
*
*/
/**
* border
*
*/
/**
* normalize
*
* Thanks to https://necolas.github.io/normalize.css/, use a lot from them
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
:root {
--body: #f9f9f9;
--text: #363636;
--text-contrast: #ffffff;
--primary: #3e3e3e;
--primary-contrast: #3e3e3e;
--active: #717171;
--active-contrast: #ffffff;
--link: #363636;
--link-hover: #d95959;
--danger: #d95959;
--danger-contrast: #ecacac;
--info: #0090d4;
--info-constrast: rgb(59, 192.1320754717, 255);
--success: #64ac64;
--success-contrast: rgb(166.4285714286, 207.5714285714, 166.4285714286);
--warning: #f0ad4e;
--warning-contrast: rgb(247.96875, 216.5625, 172.03125);
--background: #3e3e3e;
--background-contrast: #ffffff;
--background-alpha: rgba(0, 0, 0, 0.7);
--border: #3e3e3e;
--border-contrast: #ffffff;
--font-family: IBM Plex Mono, sans-serif;
}
*,
*::after,
*::before {
box-sizing: inherit;
}
/**
* form elements
*
*
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
/**
* hr
*
*/
/**
* Content
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* Heading
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* add font-size for heading as class and element
*
*
*/
/**
* <span class="badge">
* A
* </span>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* Button
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
*
*
*/
/**
*
*
*/
/**
*
*
*/
/**
*
* fields
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* field-choice
*
*
*/
/**
* radio & checkbox
*
* <div class="field">
* <label for="field__checkbox__1" class="field__label">
* <input class="field__choice" type="checkbox" name="field__checkbox__1" value="true" />
* <svg class="icon field__choice__unchecked" aria-hidden="true">
* <use xlink:href="symbol-defs.svg#icon-minus"></use>
* </svg>
* <svg class="icon field__choice__checked" aria-hidden="true">
* <use xlink:href="symbol-defs.svg#icon-checked"></use>
* </svg>
* checkbox 1
* </label>
* </div>
*
*/
/**
*
*
*/
/**
* display error for fields
*
*/
/**
*
* <div class="group">
* <span class="group__item">
* A
* </span>
* </div>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* <div class="hero">
* <img src="image.png" alt="image" />
* </div>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
*
* tabs
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* <div class="progress">
* <div class="progress__inner" style="width: 20%"></div>
* </div>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* <figure class="media-figure">
* <img class="media__img" src="https://via.placeholder.com/150" />
* <figcaption class="media-figure__caption">
* food truck yr franzen pabst
* </figcaption>
* </figure>
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
*
* table
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* <div class="bar">
* <div class="bar__start">
* </div>
* <div class="bar__main">
* </div>
* <div class="bar__end">
* </div>
* </div>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* <figure class="media-figure">
* <img class="media__img" src="https://via.placeholder.com/150" />
* <figcaption class="media-figure__caption">
* food truck yr franzen pabst
* </figcaption>
* </figure>
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* <div class="loading">
* <span></span>
* <span></span>
* <span></span>
* </div>
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
@keyframes loading-animation {
0% {
height: 60px;
}
50% {
height: 40px;
}
100% {
height: 60px;
}
}
/**
* <div class="sidebar">
* <div class="sidebar__inner">
* <div class="sidebar__body">
* </div>
* <div class="sidebar__footer">
* </div>
* </div>
* </div>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* <div class="toast-wrapper">
* <div class="toast">
* <div class="toast__icon">
* <svg class="icon fill-text-contrast" aria-hidden="true">
* <use xlink:href="/symbol-defs.svg#icon-warning"></use>
* </svg>
* </div>
* <div class="toast__body">
*
* </div>
* <div class="toast__button">
* <svg class="icon fill-text-contrast" aria-hidden="true">
* <use xlink:href="/symbol-defs.svg#icon-close"></use>
* </svg>
* </div>
* </div>
* </div>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* masonry
*
* <div class="masonry">
* <div class="mansonry__iten">
*
* </div>
* </div>
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* slider
*
* <div class="slider">
* <div class="slider__inner">
* <div class="slider__item w-10"></div>
* </div>
* </div>
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* grid
*
* This Grid is mainly the Reflex Grid from Lee Gordon https://reflexgrid.com/, he has
* done a great work, for i few changes it was needed to integrated
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* grid: mixin
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* order class generation mixins
*
*/
/**
* offset class generation mixins
*
*/
/**
* modifier mixins
*
*/
/**
* justify-content
*
* Uses "text-align" for the fallback inline-block grid
* "text-align" is globally supported and works on all rows except the last
* "text-align-last", where supported, handles the last line (and, happily, grids with only one row)
*
*/
/**
* Responsible Visibility
*
*/
/**
* Breakpoint viewport sizes and media queries
*
* Breakpoints are defined as a map of (name: minimum width), order from small to large:
* (xs: 576px, sm: 768px, md: 992px)
* The map defined in the `$reflex-breakpoints` global variable is used as the `$breakpoints` argument by default.
* Name of the next breakpoint, or null for the last breakpoint.
* >> breakpoint-next(sm) -> md
* >> breakpoint-next(sm, $breakpoints: (xs: 576px, sm: 768px, md: 992px)) -> md
* >> breakpoint-next(sm, $breakpoint-names: (xs sm md)) -> md
*
*/
/**
* Minimum breakpoint width. Null for the smallest (first) breakpoint.
* breakpoint-min(sm, (xs: 576px, sm: 768px, md: 992px)) -> 768px
*
*/
/**
* Media of at most the maximum breakpoint width. No query for the largest breakpoint.
* Makes the @content apply to the given breakpoint and narrower.
*
*/
/**
* Media between the breakpoint's minimum and maximum widths.
* No minimum for the smallest breakpoint, and no maximum for the largest one.
* Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
*
*/
/**
* grid: helpers
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* flex-direction
*
*/
/**
* align items (cross axis)
*
*/
/**
* align content (cross axis)
*
*/
/**
* align-self
*
*/
/**
* justify-content (main axis)
*
*/
/**
* cosmetic grid modifiers
*
*/
/**
* col modifiers
*
*/
/**
* col-grid contents
*
*/
/**
* Responsive visibility modifiers
*
*/
/**
* grid generation
*
*
*/
/**
* col-auto
*
*
*/
/**
* order helpers generation
*
*
*/
/**
* offset helpers generation
*
*
*/
/**
* core
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* z-index
*
*
*/
/**
* floating
*
*
*/
/**
* position
*
*
*/
/**
*
*
*/
/**
*
*
*/
/**
* Sizing
*
* Width and Height Classes,
* Sizes with percentage will calculate with the Reflex Grid
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* mixin: sizing
*
*/
/**
* mixin: sizing for each breakpoint
*
*
*/
/**
* Spacing
*
* creates margin and padding for each direction and for each breakpont
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* mixin: spacing for single padding or margin
*
*
*/
/**
* mixin: spacing for each breakpoint
*
*
*/
/**
*
*
*
*/
/**
* colors
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* typography
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* font-sizes
*
*
*/
/**
* white-space
*
*
*/
/**
* visibility
*
*
* @author Björn Hase, me@herr-hase.wtf
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/plain-ui.git
*
*/
/**
* display
*
*
*/
/**
* for hidden-xs etc, show https://reflexgrid.com/#visibility-helpers
*
* @TODO full integration of reflexgrid will change this part
*
*/
/**
* Visibility
*
*/
/**
* Opacity
*
*
*/
/**
*
*
*/
/*# sourceMappingURL=styles.css.map */

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(self.webpackChunk_tiny_components_validator=self.webpackChunk_tiny_components_validator||[]).push([["spritemap"],{"?4e0c"(){eval("{\n\n//# sourceURL=webpack://@tiny-components/validator/spritemap-dummy-module?\n}")}}]);

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 66 KiB

@ -0,0 +1,117 @@
import validate from 'validate.js'
import serialize from 'form-serialize'
/**
* Form Validator with RiotJS Components
*
*
*
*
*/
class FormValidator
{
/**
*
* @param {[type]} formSelector [description]
* @param {[type]} constraits [description]
*/
constructor(formSelector, constraits)
{
// getting selector to find form-element
this.formSelector = formSelector
// constraits for validate.js
this.constraits = constraits
// get form and elements
this.form = document.querySelector(this.formSelector)
this.elements = this.form.querySelectorAll('field-error')
// adding submit event
this.form.addEventListener('submit', (event) => {
this.onSubmit(event)
})
// adding event if a element is updated
this.form.addEventListener('field-update', (event) => {
this.onFieldUpdate(event)
})
}
/**
*
* @param {[type]} event [description]
* @return {[type]} [description]
*/
onSubmit(event)
{
let errors = validate(serialize(event.target, {
hash: true
}), this.constraits, {
fullMessages: false
})
if (errors) {
event.preventDefault()
// send each element a event
this.elements.forEach((element) => {
let elementErrors = false
// check for errors by name
if (errors[element.attributes.name.nodeValue]) {
elementErrors = errors[element.attributes.name.nodeValue]
}
this.dispatchCustomEvent(elementErrors, element)
})
}
}
/**
*
*
* @param {Event} event
*
*/
onFieldUpdate(event)
{
// workaround, make sure that value for single is undefined if it is empty
if (event.detail.value == '') {
event.detail.value = undefined
}
let errors = validate.single(event.detail.value, this.constraits[event.detail.name])
// search for element by name and dispatch event
this.elements.forEach((element) => {
if (element.attributes.name.nodeValue == event.detail.name) {
this.dispatchCustomEvent(errors, element)
}
})
}
/**
* dispatch event to single element
*
* @param {Array} errors
* @param {Element} element
*
*/
dispatchCustomEvent(errors, element)
{
let detail = false
if (errors) {
detail = errors
}
const formValidationEvent = new CustomEvent('form-validation', {
'detail': detail
})
element.dispatchEvent(formValidationEvent)
}
}
export default FormValidator

@ -0,0 +1,17 @@
import * as riot from 'riot'
import FormValidator from './../FormValidator'
import FieldError from './../field-error.riot'
riot.register('field-error', FieldError)
riot.mount('field-error')
const formValidation = new FormValidator('form', {
'email': {
'presence': true,
'email': true
},
'password': {
'presence': true
}
})

@ -0,0 +1,6 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
/*# sourceMappingURL=normalize.min.css.map */
body {
}

@ -1,31 +0,0 @@
import * as riot from 'riot'
import FormValidator from './formValidator'
import FieldError from './fieldError.riot'
import FormComponent from './formComponent.riot'
// register & mount riot component
riot.register('field-error', FieldError)
riot.mount('field-error')
// creating formValidation
const formValidation = new FormValidator(document.querySelector('.form-html'), {
'email': {
'presence': true,
'email': true
},
'password': {
'presence': true
}
}, true)
formValidation.onSuccess((event, data) => {
event.preventDefault()
// show message and content of data from form
document.querySelector('#result .content').innerHTML = '<p>' + JSON.stringify(data) + '</p>'
document.querySelector('#result').classList.remove('hidden')
})
riot.register('form-component', FormComponent)
riot.mount('form-component')

@ -1,6 +0,0 @@
@import
'../node_modules/@tiny-components/plain-ui/src/scss/plain-ui';
.hidden {
display: none;
}

@ -1,5 +1,5 @@
<field-error> <field-error>
<div class="field-error" if={ state.errors.length > 0 }> <div class="field__error" if={ state.errors.length > 0 }>
<ul> <ul>
<li each={ error in state.errors }> <li each={ error in state.errors }>
{ error } { error }
@ -9,13 +9,12 @@
<script> <script>
/** /**
*
* Shows errors of Validation and raise a element to * Shows errors of Validation and raise a element to
* trigger single validation of field * trigger single validation of field
* *
* <field-error name="name" closest="<optional>" nofieldupdate></field-error> * <field-error name="name" nofieldupdate></field-error>
* *
* @author Björn Hase, me@herr-hase.wtf * @author Björn Hase, Tentakelfabrik, me@tentakelfabrik.de
* *
*/ */
@ -25,39 +24,22 @@
errors: [ errors: [
], ],
// css class for
closest: '.field-group',
},
/**
*
*
* @param {Object} props
* @param {Object} state
*
*/
onBeforeMounted(props, state)
{
if (props.closest) {
state.closest = props.closest
}
}, },
/** /**
* *
* *
* @param {Object} props * @param {Object} props [description]
* @param {Object} state * @param {Object} state [description]
* *
*/ */
onMounted(props, state) onMounted(props, state)
{ {
// getting parent element for entire field // getting parent element for entire field
const parent = this.root.closest(state.closest) const parent = this.root.closest('.field')
// getting current element by name // getting current element by name
const element = parent.querySelector('[name="' + props.name + '"]') const element = document.querySelector('[name="' + props.name + '"]')
// getting form // getting form
const form = element.closest('form') const form = element.closest('form')

@ -1,108 +0,0 @@
<form-component>
<div>
<form class="form" novalidate method="post" onsubmit={ (event) => ( state.validator.submit(event) ) }>
<div class="field-group">
<label class="field-label">
email
<input type="email" class="field-text" name="email" />
</label>
<field-error name="email"></field-error>
</div>
<div class="field-group">
<label class="field-label">
password
<input type="password" class="field-text" name="password" />
</label>
<field-error name="password"></field-error>
</div>
<button class="button" type="submit">
Send
</button>
</form>
<div class="loading" if={ state.isLoading }>
<span></span>
<span></span>
<span></span>
</div>
<div if={ state.result } class="panel color-text-contrast { state.class }">
<div class="panel__body">
<div class="content m-bottom-last-child-0">
{ state.result }
</div>
</div>
</div>
</div>
<script>
import * as riot from 'riot'
import FormValidator from './formValidator.js'
export default {
state:
{
result: undefined,
validator: undefined,
class: undefined
},
onMounted()
{
// creating formValidator
this.state.validator = new FormValidator(this.$('.form'), {
'email': {
'presence': true,
'email': true
},
'password': {
'presence': true
}
})
// adding on success
this.state.validator.onSuccess((event, data) => {
this.handleSuccess(event, data)
})
// adding on error
this.state.validator.onError((event, errors, data) => {
this.handleError(event, errors, data)
})
},
/**
*
* @param {object} event
* @param {array} data
*
*/
handleSuccess(event, data)
{
event.preventDefault()
this.state.class = 'background-color-success'
this.state.result = JSON.stringify(data)
this.update()
},
/**
*
*
* @param {object} event
* @param {array} errors
* @param {array} data
*
*/
handleError(event, errors, data)
{
this.state.class = 'background-color-danger'
this.state.result = JSON.stringify(errors)
this.update()
}
}
</script>
</form-component>

@ -1,197 +0,0 @@
import validate from 'validate.js'
import serialize from 'form-serialize'
/**
* Form Validator with RiotJS Components
*
*
* @author HerrHase
*
*/
class FormValidator
{
/**
*
* @param {[type]} formSelector [description]
* @param {[type]} constraits [description]
*/
constructor(formElement, constraits, addSubmitEvent = false)
{
// constraits for validate.js
this.constraits = constraits
// get form and elements
this.formElement = formElement
// if form not found
if (!this.formElement) {
console.error('FormValidator: form not found!')
}
this.elements = this.formElement.querySelectorAll('field-error')
// adding event if a element is updated
this.formElement.addEventListener('field-update', (event) => {
this._onFieldUpdate(event)
})
// adding submit event
if (addSubmitEvent) {
this.formElement.addEventListener('submit', (event) => {
this._onSubmit(event)
})
}
}
/**
* trigger submit
*
* @param {object} event
*
*/
submit(event)
{
this._onSubmit(event)
}
/**
*
* @param {function} onError
*
*/
onError(onError)
{
this._onError = onError
}
/**
* settin onSuccess callback and add submit-event on form
*
* @param {function} onSuccess
*
*/
onSuccess(onSuccess)
{
// adding onSuccess
this._onSuccess = onSuccess
}
/**
*
* @param {function} onError
*
*/
onBeforeSubmit(onBeforeSubmit)
{
this._onBeforeSubmit = onBeforeSubmit
}
/**
*
*/
setConstraits(rules)
{
this.rules = rules
}
/**
* handle submit
*
*
* @param {Event} event
*
*/
_onSubmit(event)
{
// getting data from target of submit event
const data = serialize(event.target, {
hash: true
})
// options for validate.js
const options = {
fullMessages: false
}
if (this._onBeforeSubmit) {
this._onBeforeSubmit()
}
// check form and getting errors
validate.async(data, this.constraits, options).then(
() => {
this._onSuccess(event, data)
},
(errors) => {
event.preventDefault()
// if onError is set, tha
if (this._onError) {
this._onError(event, errors, data)
}
// send each element a event
this.elements.forEach((element) => {
let elementErrors = false
// check for errors by name
if (errors[element.attributes.name.nodeValue]) {
elementErrors = errors[element.attributes.name.nodeValue]
}
this._dispatchCustomEvent(elementErrors, element)
})
}
)
}
/**
* send update to fields
*
*
* @param {Event} event
*
*/
_onFieldUpdate(event)
{
// workaround, make sure that value for single is undefined if it is empty
if (event.detail.value == '') {
event.detail.value = undefined
}
let errors = validate.single(event.detail.value, this.constraits[event.detail.name])
// search for element by name and dispatch event
this.elements.forEach((element) => {
if (element.attributes.name.nodeValue == event.detail.name) {
this._dispatchCustomEvent(errors, element)
}
})
}
/**
* dispatch event to single element
*
* @param {Array} errors
* @param {Element} element
*
*/
_dispatchCustomEvent(errors, element)
{
let detail = false
if (errors) {
detail = errors
}
const formValidationEvent = new CustomEvent('form-validation', {
'detail': detail
})
element.dispatchEvent(formValidationEvent)
}
}
export default FormValidator

@ -1,6 +0,0 @@
@import
'../node_modules/@tiny-components/plain-ui/src/scss/plain-ui';
.hidden {
display: none;
}

@ -1,18 +0,0 @@
const tinyComponentsWebpack = require('@tiny-components/webpack')
const riotRules = require('@tiny-components/webpack/rules/riot')
module.exports = tinyComponentsWebpack({
index: [
'./src/example.js'
],
styles: [
'./src/styles.scss'
],
}, {
svg: {
src: [
'./node_modules/@tiny-components/plain-ui/src/icons/mono-icons/svg/*.svg'
]
},
rules: [ riotRules ]
})

@ -0,0 +1,36 @@
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel application. By default, we are compiling the Sass
| file for your application, as well as bundling up your JS files.
|
*/
mix.webpackConfig({
module: {
rules: [{
test: /\.riot$/,
exclude: '/node_modules/',
use: [{
loader: '@riotjs/webpack-loader',
options: {
hot: false
}
}]
}]
}
})
mix.js('src/demo/demo.js', 'demo')
.sass('src/demo/demo.scss', 'demo')
.options({
terser: {
extractComments: false,
},
processCssUrls: false
})
Loading…
Cancel
Save