main
HerrHase 1 year ago
parent 7fb1f4ba14
commit 9eb3c0a92f

@ -1,6 +1,6 @@
MIT License
Copyright (c) <year> <copyright holders>
Copyright (c) 2023 Björn Hase, me@herr-hase.wtf
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

@ -1,2 +1,70 @@
# slider
# Tiny Components - Slider
Created with [Riot.js](https://riot.js.org)
Handle UI of Slider by using [Plain-UI](https://plain-ui.com)
Source: [https://gitea.node001.net/tiny-components/raw](https://gitea.node001.net/tiny-components/raw)
Mirror: [https://github.com/node001-net/tiny-components-raw](https://github.com/node001-net/tiny-components-raw)
## Installation
Setup this registry in your project .npmrc file:
```
@tiny-components:registry=https://gitea.node001.net/api/packages/tiny-components/npm/
```
Install with npm or yarn
```
npm i --save @tiny-components/slider
yarn add @tiny-components/slider
```
# Using
```
<tiny-slider></tiny-slider>
<script defer>
window.addEventListener('DOMContentLoaded', (event) => {
riot.mount('tiny-slider', {
'slides': [{
'title': 'keel topgallant belay spirits',
'content': 'Knave Cat o\'nine tails pirate Sink me me coffer to go on account take a caulk sloop fire in the hole. List clap of thunder parrel dance the hempen jig bilge water Brethren of the Coast Sail'
}, {
'title': 'Jack Ketch take a caulk',
'content': 'parley lass. Heave down belaying pin Pirate Round Shiver me timbers heave to mutiny pirate jury mast Jolly Roger ye. Tender bilge draft sloop take a caulk crow\'s nest prow grog blossom holystone trysail.'
}]
})
})
</script>
```
# Customize
Extends your Component with mixin.js.
```
<your-slider>
<div class="your-slider">
// your markup
</div>
<script>
// mixin
import sliderMixin from '@tiny-components/slider/src/mixin.js'
export default () => {
return {
...sliderMixin
}
}
</script>
</your-slider>
```

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 it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tiny Components | Slider</title>
<link rel="icon" href="data:,">
<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/slider
</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 m-top-6">
<div class="grid">
<div class="col-12">
<tiny-slider></tiny-slider>
</div>
</div>
</div>
<script defer src="/example.js"></script>
<script defer>
window.addEventListener('DOMContentLoaded', (event) => {
riot.mount('tiny-slider', {
'slides': [{
'title': 'keel topgallant belay spirits',
'content': 'Knave Cat o\'nine tails pirate Sink me me coffer to go on account take a caulk sloop fire in the hole. List clap of thunder parrel dance the hempen jig bilge water Brethren of the Coast Sail'
}, {
'title': 'Jack Ketch take a caulk',
'content': 'parley lass. Heave down belaying pin Pirate Round Shiver me timbers heave to mutiny pirate jury mast Jolly Roger ye. Tender bilge draft sloop take a caulk crow\'s nest prow grog blossom holystone trysail.'
}]
})
})
</script>
</body>
</html>

@ -0,0 +1,14 @@
{
"/spritemap.js": "/spritemap.js",
"/symbol-defs.svg": "/symbol-defs.svg",
"/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"
}

@ -0,0 +1,13 @@
(self["webpackChunk_tiny_components_slider"] = self["webpackChunk_tiny_components_slider"] || []).push([["spritemap"],{
/***/ "?c20d":
/*!******************************!*\
!*** spritemap-dummy-module ***!
\******************************/
/***/ (() => {
/***/ })
}]);

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 66 KiB

16548
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,25 @@
{
"name": "@tiny-components/slider",
"version": "0.1.0",
"description": "Small fast slider for Desktop and Mobile",
"repository": {
"type": "git",
"url": "git@github.com:node001-net/tiny-components-slider.git"
},
"author": "Björn Hase",
"license": "MIT",
"dependencies": {
"@tiny-components/plain-ui": "^0.6.0",
"@tiny-components/raw": "^0.1.0",
"hammerjs": "^2.0.8",
"riot": "^7.1.0"
},
"devDependencies": {
"@riotjs/webpack-loader": "^6.0.0",
"laravel-mix": "^6.0.43",
"laravel-mix-purgecss": "^6.0.0",
"sass": "^1.51.0",
"sass-loader": "^12.6.0",
"svg-spritemap-webpack-plugin": "^4.4.0"
}
}

@ -0,0 +1,55 @@
.tiny-slider {
overflow-x: hidden;
&__inner {
position: relative;
transition: transform 0.3s ease-in-out;
}
&__item {
max-width: 100%;
}
&__button {
display: none;
border: none;
background: transparent;
width: 150px;
padding: 10px;
.icon {
font-size: 3rem;
}
@include media-md() {
display: block;
}
&:hover {
cursor: pointer;
}
}
&__select {
padding: 1em;
justify-content: center;
&-item {
height: 25px;
width: 25px;
border: 1px solid var(--background);
background-color: var(--background-contrast);
margin: 0 0.5em;
transition: background-color 0.3s ease-in-out;
&:hover {
cursor: pointer;
}
&--current {
background-color: var(--background);
}
}
}
}

@ -0,0 +1,24 @@
import * as riot from 'riot'
import Slider from './slider.riot'
riot.register('tiny-slider', Slider)
/**
* Convert object attributes constructs into strings
*
* @param {Object} attributes - style attributes as object
* @returns {string} a string with all the attributes and their values
*/
function styles(attributes) {
return Object.entries(attributes).reduce((acc, item) => {
const [key, value] = item;
return [...acc, `${key}: ${value}`];
}, []).join(';');
}
riot.install(function(component) {
component.styles = styles
return component
})
window.riot = riot

@ -0,0 +1,8 @@
@import
'../node_modules/@tiny-components/plain-ui/src/scss/plain-ui',
'slider';
.overflow-hidden {
overflow: hidden;
}

@ -0,0 +1,224 @@
import * as Hammer from 'hammerjs'
/**
* Mixin for extends Riot-Component
*
* @author Björn Hase
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/slider
*
*/
export default {
/**
*
*
*/
state: {
position: 0,
max: 0,
slides: undefined,
classes: {
item: 'tiny-slider__item'
}
},
/**
*
*
*/
onMounted() {
if (this.props.slides) {
this.state.slides = this.props.slides
}
// start and add resize listener
window.addEventListener('resize', this.update.bind(this))
setTimeout(() => {
this.update()
}, 100)
// Create a manager to manager the element
const manager = new Hammer(this.root)
manager.on('swipe', (event) => {
if (event.direction === 4) {
this.handlePrevious(event)
} else if (event.direction === 2) {
this.handleNext(event)
}
})
},
/**
* remove resize listener before unmount
*
*/
onBeforeUnmount() {
window.removeEventListener('resize', this.update.bind(this))
},
/**
* before update view, calculate values
*
* @param {object} props
* @param {object} state
*
*/
onBeforeUpdate(props, state) {
// getting current max
const max = this.state.max
// setting max to show visible
this.state.max = 0
this.state.width = this.$('.' + this.state.classes.item).offsetWidth
// check how many elements can visible in element
this.$$('.' + this.state.classes.item).forEach((element, index) => {
if (element.offsetLeft < this.root.offsetWidth) {
this.state.max++;
}
})
// change position to fit new max value
const value = Math.abs(this.state.max - max)
// @TODO check this, at 0 it makes me mad
if (this.state.position >= value && this.state.position > 1) {
this.state.position -= value
}
},
/**
* set current position
*
*
*/
handleSelect(event, position) {
event.preventDefault()
if (this.state.position !== position) {
this.update({
position: position
})
}
},
/**
* set next postion
*
*
*/
handlePrevious(event) {
event.preventDefault()
if (this.state.position > 0) {
this.update({
position: --this.state.position
})
}
},
/**
* set next postion
*
*
* @param {object} event
*
*/
handleNext(event) {
event.preventDefault()
if (this.state.position < (this.props.slides.length - 1)) {
this.update({
position: ++this.state.position
})
}
},
/**
* getting classes for next-button,
* show button only
*
*
* @return {string}
*
*/
getPreviousClasses() {
const classes = [
'tiny-slider__button',
'tiny-slider__button--previous'
]
if (this.state.position > 0) {
classes.push('visibility-visible')
} else {
classes.push('visibility-hidden')
}
return classes.join(' ')
},
/**
* getting classes for next-button,
* show button unless length is smaller then max
*
* @return {string}
*
*/
getNextClasses() {
const classes = [
'tiny-slider__button',
'tiny-slider__button--next'
]
if (this.state.position <= (this.props.slides.length - this.state.max)) {
classes.push('visibility-visible')
} else {
classes.push('visibility-hidden')
}
return classes.join(' ')
},
/**
* getting classes for select,
* adding current-class if postion and state.postion are equal
*
* @param {integer} position
* @return {string}
*
*/
getSelectClasses(position) {
const classes = [
'tiny-slider__select-item'
]
if (this.state.position === position) {
classes.push('tiny-slider__select-item--current')
}
return classes.join(' ')
},
/**
* set translate with position and witdh
*
*
* @return {string}
*
*/
getContentStyles() {
// getting value for position
const value = (-(this.state.position * this.state.width));
return this.styles({
transform: 'translate(' + value + 'px, 0px)'
})
}
}

@ -0,0 +1,67 @@
<tiny-slider>
<div class="slider tiny-slider">
<div class="display-flex">
<button class="{ getPreviousClasses() }" onclick={ (event) => { handlePrevious(event) } }>
<svg class="icon">
<use xlink:href="/symbol-defs.svg#icon-previous" />
</svg>
</button>
<div class="overflow-hidden">
<div class="slider__inner tiny-slider__inner" style={ getContentStyles() }>
<div class="slider__item tiny-slider__item" each={ slide in state.slides }>
<h3 class="tiny-slider__title">
{ slide.title }
</h3>
<figure class="tiny-slider__figure" if={ slide.media }>
<img class="tiny-slider__media" loading="lazy" src="{ slide.media.url }" alt="{ slide.media.description }" />
</figure>
<div class="tiny-slider__content">
<div class="content">
<tiny-raw html={ slide.content }></tiny-raw>
</div>
</div>
</div>
</div>
</div>
<button class="{ getNextClasses() }" onclick={ (event) => { handleNext(event) }}>
<svg class="icon">
<use xlink:href="/symbol-defs.svg#icon-next" />
</svg>
</button>
</div>
<div class="tiny-slider__select display-flex m-top-4">
<span class="{ getSelectClasses(position) }" each={ (slide, position) in state.slides } onclick={ (event) => { handleSelect(event, position) }}></span>
</div>
</div>
<script>
// riot
import * as riot from 'riot'
// mixin
import sliderMixin from './mixin.js'
// tiny-raw & riot
import raw from '@tiny-components/raw/src/raw.riot'
riot.register('tiny-raw', raw)
/**
* Markup for slider, extends from sliderMixin.js
*
* @author Björn Hase
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/tiny-components/slider
*
*/
export default () => {
return {
...sliderMixin
}
}
</script>
</tiny-slider>

@ -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: '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