Skip to content
Snippets Groups Projects
Commit e7ba4719 authored by xaralis's avatar xaralis
Browse files

Add flipclock to homepage

parent 77cfac2d
No related branches found
No related tags found
No related merge requests found
Pipeline #794 passed
Showing with 481 additions and 66 deletions
...@@ -41,14 +41,6 @@ function resolvePath(pathInput) { ...@@ -41,14 +41,6 @@ function resolvePath(pathInput) {
/****************************************************** /******************************************************
* COPY TASKS - stream assets from source to destination * COPY TASKS - stream assets from source to destination
******************************************************/ ******************************************************/
// JS copy
gulp.task("pl-copy:js", function (done) {
return gulp
.src("**/*.js", { cwd: resolvePath(paths().source.js) })
.pipe(gulp.dest(resolvePath(paths().public.js)))
.on("end", done);
});
// Images copy // Images copy
gulp.task("pl-copy:img", function (done) { gulp.task("pl-copy:img", function (done) {
return gulp return gulp
...@@ -133,7 +125,6 @@ function build(done) { ...@@ -133,7 +125,6 @@ function build(done) {
gulp.task( gulp.task(
"pl-assets", "pl-assets",
gulp.parallel( gulp.parallel(
"pl-copy:js",
"pl-copy:img", "pl-copy:img",
"pl-copy:favicon", "pl-copy:favicon",
"pl-copy:font", "pl-copy:font",
...@@ -367,7 +358,8 @@ gulp.task( ...@@ -367,7 +358,8 @@ gulp.task(
} }
); );
gulp.task('rollup:build', function () { const buildJSBundle = (env) => {
return function () {
return rollup({ return rollup({
plugins: [ plugins: [
vue({ css: false }), vue({ css: false }),
...@@ -379,7 +371,7 @@ gulp.task('rollup:build', function () { ...@@ -379,7 +371,7 @@ gulp.task('rollup:build', function () {
preferBuiltins: true preferBuiltins: true
}), }),
replace({ replace({
'process.env.NODE_ENV': JSON.stringify('development'), 'process.env.NODE_ENV': JSON.stringify(env),
}) })
], ],
input: resolvePath(paths().source.js) + "/main.js", input: resolvePath(paths().source.js) + "/main.js",
...@@ -390,21 +382,21 @@ gulp.task('rollup:build', function () { ...@@ -390,21 +382,21 @@ gulp.task('rollup:build', function () {
.on('bundle', bundle => { rollupCache = bundle }) .on('bundle', bundle => { rollupCache = bundle })
.pipe(source("main.bundle.js")) .pipe(source("main.bundle.js"))
.pipe(buffer()) .pipe(buffer())
.pipe(addsrc.prepend([ // .pipe(addsrc.prepend([
'./node_modules/vue/dist/vue.js' // './node_modules/vue/dist/vue.js'
])) // ]))
// .pipe(concat("main.bundle.js")) // .pipe(concat("main.bundle.js"))
.pipe(gulp.dest("./public/js")); .pipe(gulp.dest("./public/js"));
}) };
}
gulp.task('rollup:watch', function () {
}); gulp.task('rollup:build', buildJSBundle("development"));
gulp.task('rollup:build:production', buildJSBundle("production"));
/****************************************************** /******************************************************
* COMPOUND TASKS * COMPOUND TASKS
******************************************************/ ******************************************************/
gulp.task("default", gulp.series("tailwind-postcss:build:production")); gulp.task("default", gulp.series("tailwind-postcss:build:production", "rollup:build:production"));
gulp.task("patternlab:watch", gulp.series("tailwind-postcss:build", watch)); gulp.task("patternlab:watch", gulp.series("tailwind-postcss:build", watch));
gulp.task( gulp.task(
"patternlab:serve", "patternlab:serve",
......
<div class="flip-clock __vue-root"
data-app="FlipClock"
data-clockclasses="{{ clockClasses }}"
data-slotclasses="{{ slotClasses }}"
data-deadline="2020-12-10 00:00:00"
{{# units }}data-units="{{ units }}"{{/ units }}
></div>
<aside class="bg-black text-white px-4 py-12 lg:py-32 lg:px-24 {{ classes }}">
<div class="flex flex-col lg:flex-row items-center">
<h1 class="head-alt-md md:head-alt-xl flex-grow text-center lg:text-left mb-8 lg:mb-0">{{ countDownTitle }}{{^ countDownTitle }}Do voleb<br>nám zbývá{{/ countDownTitle }}</h1>
{{> molecules-flip-clock(clockClasses: "text-6xl md:text-7xl lg:text-8xl", slotClasses: "text-2xl md:text-3xl lg:text-4xl", units: "days,hours") }}
</div>
</aside>
...@@ -11,11 +11,11 @@ ...@@ -11,11 +11,11 @@
</nav> </nav>
</section> </section>
<section id="countdown"> <section class="my-8 lg:my-16 container-padding--zero lg:container-padding--auto">
<flip-countdown deadline="2020-12-25 00:00:00"></flip-countdown> {{> organisms-countdown }}
</section> </section>
<section class="py-16"> <section class="my-8 lg:my-16 container-padding--zero lg:container-padding--auto">
{{> molecules-calendar }} {{> molecules-calendar }}
</section> </section>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
&:first-child { &:first-child {
@apply border-l; @apply border-l;
@screen lg { @screen xl {
@apply border-l-0; @apply border-l-0;
} }
} }
......
.flip-clock {
@apply text-center;
perspective: 600px;
}
.flip-clock__piece {
@apply relative inline-flex justify-center mx-1;
}
.flip-clock__slot {
@apply absolute block bottom-0 z-50;
transform: translateY(55%);
text-shadow: 0 0 1.5rem theme('colors.black');
}
.flip-card {
@apply block relative font-alt;
padding-bottom: 0.85em;
/* Additional outline around clock */
&:after {
@apply absolute;
content: "";
position: absolute;
width: 90%;
height: 108%;
top: -4%;
left: 5%;
z-index: -1;
}
}
.flip-card__top,
.flip-card__bottom,
.flip-card__back-bottom,
.flip-card__back:before,
.flip-card__back:after,
.flip-card__top-4digits,
.flip-card__bottom-4digits,
.flip-card__back-bottom-4digits,
.flip-card__back-4digits:before,
.flip-card__back-4digits:after {
@apply block text-white bg-black;
height: 0.85em;
padding: 0.35em 0.1em 0.4em;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
transform-style: preserve-3d;
}
.flip-card:after,
.flip-card__top,
.flip-card__bottom,
.flip-card__back:before,
.flip-card__back:after,
.flip-card__back-bottom,
.flip-card__bottom-4digits,
.flip-card__back-bottom-4digits {
@apply border border-grey-300;
}
.flip-card__top,
.flip-card__back:before,
.flip-card__back:after {
@apply border-b-0;
}
.flip-card__top,
.flip-card__bottom,
.flip-card__back-bottom,
.flip-card__back:before,
.flip-card__back:after {
width: 1.9em;
}
.flip-card__top-4digits,
.flip-card__bottom-4digits,
.flip-card__back-bottom-4digits,
.flip-card__back-4digits:before,
.flip-card__back-4digits:after {
width: 2.4em;
}
.flip-card__bottom,
.flip-card__back-bottom,
.flip-card__bottom-4digits,
.flip-card__back-bottom-4digits {
@apply absolute left-0 pointer-events-none;
left: 0;
pointer-events: none;
overflow: hidden;
z-index: 2;
}
.flip-card__back-bottom,
.flip-card__back-bottom-4digits {
z-index: 1;
}
.flip-card__bottom:after,
.flip-card__back-bottom:after,
.flip-card__bottom-4digits:after,
.flip-card__back-bottom-4digits:after {
@apply block;
margin-top: -0.85em;
}
.flip-card__back:before,
.flip-card__bottom:after,
.flip-card__back-bottom:after,
.flip-card__back-4digits:before,
.flip-card__bottom-4digits:after,
.flip-card__back-bottom-4digits:after {
content: attr(data-value);
}
.flip-card__back,
.flip-card__back-4digits {
@apply absolute top-0 h-full left-0 pointer-events-none;
}
.flip-card__back:before,
.flip-card__back-4digits:before {
@apply relative overflow-hidden;
z-index: -1;
}
.flip .flip-card__back:before,
.flip .flip-card__back-4digits:before {
z-index: 1;
animation: flipTop 0.3s cubic-bezier(0.37, 0.01, 0.94, 0.35);
animation-fill-mode: both;
transform-origin: center bottom;
}
.flip .flip-card__bottom,
.flip .flip-card__bottom-4digits {
transform-origin: center top;
animation-fill-mode: both;
animation: flipBottom 0.6s cubic-bezier(0.15, 0.45, 0.28, 1);
}
@keyframes flipTop {
0% {
transform: rotateX(0deg);
z-index: 2;
}
0%,
99% {
opacity: 1;
}
100% {
transform: rotateX(-90deg);
opacity: 0;
}
}
@keyframes flipBottom {
0%,
50% {
z-index: -1;
transform: rotateX(90deg);
opacity: 0;
}
51% {
opacity: 1;
}
100% {
opacity: 1;
transform: rotateX(0deg);
z-index: 5;
}
}
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
@import "./molecules/candidate-card.pcss"; @import "./molecules/candidate-card.pcss";
@import "./molecules/candidate-table-row.pcss"; @import "./molecules/candidate-table-row.pcss";
@import "./molecules/content-block.pcss"; @import "./molecules/content-block.pcss";
@import "./molecules/flip-clock.pcss";
@import "./molecules/pagination.pcss"; @import "./molecules/pagination.pcss";
@import "./molecules/social-icon-group.pcss"; @import "./molecules/social-icon-group.pcss";
@import "./molecules/switch.pcss"; @import "./molecules/switch.pcss";
......
This diff is collapsed.
<template>
<flip-countdown deadline="2020-12-25 00:00:00"></flip-countdown>
</template>
<script>
import Vue from "vue";
import FlipCountdown from 'vue2-flip-countdown';
export default {
components: { FlipCountdown }
}
</script>
import FlipClock from './apps/flip-clock';
export default {
FlipClock
};
<template>
<div class="flip-clock">
<template v-for="data in timeData" v-show="show">
<span v-bind:key="data.label" class="flip-clock__piece" :id="data.elementId" v-show="data.show">
<span :class="['flip-clock__card', 'flip-card', clockclasses ]">
<b class="flip-card__top">{{ data.current | twoDigits }}</b>
<b class="flip-card__bottom" v-bind:data-value="data.current | twoDigits"></b>
<b class="flip-card__back" v-bind:data-value="data.previous | twoDigits"></b>
<b class="flip-card__back-bottom" v-bind:data-value="data.previous | twoDigits"></b>
</span>
<span :class="['flip-clock__slot', 'font-alt', slotclasses]">{{ data.label }}</span>
</span>
</template>
</div>
</template>
<script>
import Vue from "vue";
import { forEachNode } from "../../utils";
export default {
name: 'flipCountdown',
props: {
deadline: {
type: String,
},
stop: {
type: Boolean,
},
units: {
type: String,
default: 'days,hours,minutes,seconds'
},
clockclasses: {
type: String,
default: 'text-6xl'
},
slotclasses: {
type: String,
default: 'text-3xl'
}
},
data() {
const uuid = Math.floor(Math.random() * 100);
return {
now: Math.trunc(new Date().getTime() / 1000),
date: null,
interval: null,
diff: 0,
show: false,
timeData: [
{
current: 0,
previous: 0,
label: "Dní",
elementId: 'flip-card-days-' + uuid,
show: this.units.indexOf("days") !== -1,
},
{
current: 0,
previous: 0,
label: "Hod",
elementId: 'flip-card-hours-' + uuid,
show: this.units.indexOf("hours") !== -1,
},
{
current: 0,
previous: 0,
label: "Min",
elementId: 'flip-card-minutes-' + uuid,
show: this.units.indexOf("minutes") !== -1,
},
{
current: 0,
previous: 0,
label: "Sek",
elementId: 'flip-card-seconds-' + uuid,
show: this.units.indexOf("seconds") !== -1,
},
],
};
},
created() {
if (!this.deadline) {
throw new Error("Missing props 'deadline'");
}
const endTime = this.deadline;
this.date = Math.trunc(Date.parse(endTime.replace(/-/g, '/')) / 1000);
if (!this.date) {
throw new Error("Invalid props value, correct the 'deadline'");
}
this.interval = setInterval(() => {
this.now = Math.trunc(new Date().getTime() / 1000);
}, 1000);
},
mounted() {
if (this.diff !== 0) {
this.show = true;
}
},
watch: {
deadline(newVal, oldVal) {
const endTime = this.deadline;
this.date = Math.trunc(Date.parse(endTime.replace(/-/g, '/')) / 1000);
if (!this.date) {
throw new Error("Invalid props value, correct the 'deadline'");
}
},
now(value) {
this.diff = this.date - value;
if (this.diff <= 0 || this.stop) {
this.diff = 0;
this.updateTime(3, 0);
} else {
this.updateTime(0, Math.trunc(this.diff / 60 / 60 / 24));
this.updateTime(1, Math.trunc(this.diff / 60 / 60) % 24);
this.updateTime(2, Math.trunc(this.diff / 60) % 60);
this.updateTime(3, Math.trunc(this.diff) % 60);
}
},
},
filters: {
twoDigits(value) {
if (value.toString().length <= 1) {
return '0' + value.toString();
}
return value.toString();
},
},
methods: {
updateTime(idx, newValue) {
if (idx >= this.timeData.length || newValue === undefined) {
return;
}
const applyUpdate = () => {
const d = this.timeData[idx];
const val = newValue < 0 ? 0 : newValue;
const el = document.querySelector(`#${d.elementId}`);
if (val !== d.current) {
d.previous = d.current;
d.current = val;
if (el) {
el.classList.remove('flip');
void el.offsetWidth;
el.classList.add('flip');
}
if (idx === 0) {
const els = el.querySelectorAll('span b');
if (els) {
forEachNode(els, e => {
const cls = e.classList[0];
if (newValue / 1000 >= 1) {
if (!cls.includes('-4digits')) {
const newCls = cls + '-4digits';
e.classList.add(newCls);
e.classList.remove(cls);
}
} else {
if (cls.includes('-4digits')) {
const newCls = cls.replace('-4digits', '');
e.classList.add(newCls);
e.classList.remove(cls);
}
}
});
}
}
}
};
if (window['requestAnimationFrame']) {
this.frame = requestAnimationFrame(applyUpdate);
} else {
applyUpdate();
}
},
},
beforeDestroy() {
if (window['cancelAnimationFrame']) {
cancelAnimationFrame(this.frame);
}
},
destroyed() {
clearInterval(interval);
}
}
</script>
import Vue from 'vue';
import FlipClock from './FlipClock.vue';
const appFactory = (el, attrs) => {
// Bootstrap Vue.js.
new Vue({el, render: h => h(FlipClock, { attrs })});
};
export default appFactory;
import Vue from "vue"; import Vue from "vue";
import FlipClock from "./FlipClock.vue";
import { forEachNode } from "./utils";
import Apps from "./apps";
/**
* Bootstrap Vue.js application at given Element instance.
*
* App properties are passed via data attributes, like:
*
* <div class="__vue-root" data-message="Hello" data-app="SomeApp"></div>
*
* @param {Element} el DOM Element
*/
function renderVueAppElement(el) {
const attrs = Object.assign({}, el.dataset);
document.addEventListener('DOMContentLoaded', function () { if (! attrs.app) {
new Vue({ console.warn(el, 'Cannot bootstrap: missing data-app');
el: '#countdown', return;
render: h => h(FlipClock) }
})
}); const app = Apps[attrs.app];
if (! app) {
console.warn(el, `Cannot bootstrap: unknown app ${attrs.app}`);
return;
}
return app(el, attrs);
}
function init(event) {
// Initialize Vue.js apps.
forEachNode(document.querySelectorAll('.__vue-root'), renderVueAppElement)
}
document.addEventListener('DOMContentLoaded', init);
export const forEachNode = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, array[i]); // passes back stuff we need
}
};
...@@ -54,6 +54,7 @@ module.exports = { ...@@ -54,6 +54,7 @@ module.exports = {
'5xl': '3rem', '5xl': '3rem',
'6xl': '4rem', '6xl': '4rem',
'7xl': '5.6rem', '7xl': '5.6rem',
'8xl': '6.5rem',
}, },
fontWeight: { fontWeight: {
light: 300, light: 300,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment