HerrHase 2 days ago
commit 56ef1edcfe

1
.gitignore vendored

@ -0,0 +1 @@
node_modules

@ -0,0 +1,88 @@
# Tiny Components - Validator
Created with [Riot.js](https://riot.js.org)
Validate Form or a Single Form-Field, Error Messages can be show just in time
or after Submit entire Form.
For Validation this Component uses [Validate.js](https://validatejs.org/)
## Install
```bash
npm install @tiny-components/validator --save
```
## You can use it like this
```javascript
<form class="form" onsubmit={ (event) => ( state.validator.submit(event) ) }>>
<div class="field">
<label>
email
<input type="email" name="email" onkeyup={ (event) => { state.validator.handle(event, 'email') }} />
</label>
<field-error errors={ state.validator.errors('email') } ></field-error>
</div>
<div class="field">
<label>
password
<input type="password" name="email" onkeyup={ (event) => { state.validator.handle(event, 'password') }} />
</label>
<field-error errors={ state.validator.errors('password') } ></field-error>
</div>
<button type="submit">Send</button>
</form>
<script>
import Validator from './validator.js'
export default {
state: {
validator: { }
},
onBeforeMount() {
// 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)
})
},
/**
*
*/
handleSuccess(event, data)
{
event.preventDefault()
this.update()
},
/**
*
*/
handleError(event, errors, data)
{
this.update()
}
}
</script>
```

Binary file not shown.

@ -0,0 +1,2 @@
[install.scopes]
"@tiny-components" = "https://gitea.node001.net/api/packages/tiny-components/npm/"

File diff suppressed because one or more lines are too long

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tiny Components | Field Upload</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<link href="/css/styles.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/upload
</h1>
</div>
<div class="bar__main justify-end">
<a class="button button--small m-left-sm-3 m-bottom-0" href="https://git.node001.net/tiny-components/upload" 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>
Upload
</h2>
<form class="form-html" novalidate method="post">
<div class="field-group">
<tiny-field-upload label="Select File" name="file" multiple></tiny-field-upload>
<field-error name="file"></field-error>
</div>
<button class="button" type="submit" disabled>
Send
</button>
</form>
</div>
<div class="col-12">
<h2>
Upload / Max
</h2>
<form class="form-html" novalidate method="post">
<div class="field-group">
<tiny-field-upload label="Select File" name="file" max="2" multiple></tiny-field-upload>
<field-error name="file"></field-error>
</div>
<button class="button" type="submit" disabled>
Send
</button>
</form>
</div>
</div>
</div>
<script type="text/javascript" src="/js/index.js"></script>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
(self.webpackChunk_tiny_components_upload=self.webpackChunk_tiny_components_upload||[]).push([[654],{874:()=>{}}]);

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 66 KiB

@ -0,0 +1,24 @@
{
"name": "@tiny-components/upload",
"version": "0.1.0",
"description": "Upload Field for Riotjs",
"repository": {
"type": "git",
"url": "git@github.com:node001-net/tiny-components/upload.git"
},
"author": "Björn Hase",
"license": "MIT",
"dependencies": {
"@tiny-components/plain-ui": "^0.6.0",
"riot": "^9.4.10"
},
"devDependencies": {
"@riotjs/compiler": "^9.0.7",
"@riotjs/webpack-loader": "^9.0.1",
"@tiny-components/webpack": "^0.2.0"
},
"scripts": {
"build": "webpack --mode production --config webpack.config.js",
"build-dev": "webpack --mode development --config webpack.config.js"
}
}

@ -0,0 +1,6 @@
import * as riot from 'riot'
import FieldUpload from './fieldUpload.riot'
riot.register('tiny-field-upload', FieldUpload)
riot.mount('tiny-field-upload')

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

@ -0,0 +1,140 @@
<tiny-field-upload>
<div class="tiny-field-upload">
<input type="file" class="tiny-field-upload__field" multiple={ props.multiple !== undefined } onchange={ (event) => { handleSelectFile(event) } } />
<button class="button button--info" type="button" onclick={ (event) => { handleOpenFileManager(event) } } disabled={ state.disabled }>
<svg class="icon fill-text-contrast" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-upload"></use>
</svg>
{ props.label }
</button>
<div class="tiny-field-upload__files">
<div class="tiny-field-upload__files-item" each={ file in state.files }>
<div class="panel">
<div class="bar">
<div class="bar__start"></div>
<div class="bar__main">{ file.name }</div>
<div class="bar__end">
<button type="button" class="button button--transparent tiny-field-upload__files-remove" onclick={ (event) => { handleRemoveFile(event, file) } }>
<svg class="icon fill-text-contrast" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-delete"></use>
</svg>
</button>
</div>
</div>
<div class="panel__body">
<input type="file" name="{ props.name }[]" />
<img class="tiny-field-upload__files-media" src={ addSrc(file) } />
</div>
</div>
</div>
</div>
</div>
<script>
/**
*
*
*/
export default {
state:
{
files: [],
field: undefined,
disabled: false
},
onMounted()
{
// getting field for getting files
this.field = this.$('.tiny-field-upload__field')
},
/**
* after update
*
*/
onUpdated(props, state) {
// getting elements
const elements = this.$$('.tiny-field-upload__item input')
let index = 0
// adding for each element a file-input
if (elements.length > 0) {
for (const element of elements) {
const dataTransfer = new DataTransfer()
// adding to each input field a file form files
dataTransfer.items.add(state.files[index++]);
element.files = dataTransfer.files
}
}
},
/**
* getting file and parse it for img-element
*
*/
addSrc(file) {
return URL.createObjectURL(file)
},
/**
* open file manager by button click on field-element
*
*/
handleOpenFileManager(event)
{
this.field.click()
},
/**
* remove file from files
*
*/
handleRemoveFile(event, file)
{
const index = this.state.files.indexOf(file)
this.state.files.splice(index, 1)
this.validateMax()
this.update()
},
/**
*
*
*/
handleSelectFile(event)
{
let index = 0
for (const file of event.target.files) {
if (!this.props.max || (this.props.max && (((index++) + 1) <= this.props.max))) {
this.state.files.push(file)
}
}
this.validateMax()
this.update()
},
/**
*
*/
validateMax()
{
this.state.disabled = false
if (this.props.max && (this.state.files.length >= this.props.max)) {
this.state.disabled = true
}
}
}
</script>
</tiny-field-upload>

@ -0,0 +1,32 @@
/**
*
*
*/
.tiny-field-upload {
// hide all file inputs
input[type="file"] {
display: none;
}
&__files {
display: flex;
flex-wrap: wrap;
margin: 0 -0.5em 0;
}
&__files-item {
width: calc(25% - 1em);
margin: 0 0.5em 1em;
img.tiny-field-upload__files-media {
width: 100%;
}
.panel__body {
line-height: 0;
}
}
}

@ -0,0 +1,24 @@
const tinyComponentsWebpack = require('@tiny-components/webpack')
const riotRules = require('@tiny-components/webpack/rules/riot')
const path = require('path')
module.exports = tinyComponentsWebpack({
index: [
'./src/example.js'
],
styles: [
'./src/example.scss'
],
}, {
publicPath: '/example/',
destination: path.resolve(process.cwd(), 'example'),
rules: [ riotRules ],
svg: {
src: [
'node_modules/@tiny-components/plain-ui/src/icons/mono-icons/svg/*.svg'
]
},
purge: {
src: path.join(__dirname, './**')
}
})
Loading…
Cancel
Save