@kano/web-components
Version:
Shared web-components for the Kano ecosystem.
347 lines (336 loc) • 11.7 kB
JavaScript
import '@polymer/polymer/polymer-legacy.js';
import '@polymer/iron-flex-layout/iron-flex-layout.js';
import '@polymer/iron-image/iron-image.js';
import { APIClient } from '../kano-api-client-behavior/kano-api-client-behavior.js';
import '../kano-lightboard-preview/kano-lightboard-preview.js';
import '../kano-share-stats/kano-share-stats.js';
import '../kano-style/kano-style.js';
import '../kano-icons/parts.js';
import '../kano-share-wrapper/kano-share-wrapper-behavior.js';
import { ShareBehavior } from '../kano-share/kano-share-behavior.js';
import { Polymer } from '@polymer/polymer/lib/legacy/polymer-fn.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js';
Polymer({
_template: html`
<style>
:host {
box-sizing: border-box;
display: block;
}
:host([mode="detailed"]) .wrapper {
padding: 0 20px 32px 20px;
}
:host([mode="summary"]) .wrapper {
padding: 16px 20px;
}
:host([mode="summary"]) .inner {
@apply --layout-horizontal;
}
:host #cover {
background-color: var(--color-stone);
}
:host #cover,
:host kano-lightboard-preview {
cursor: pointer;
}
:host([mode="detailed"]) .cover-wrapper {
height: 0;
overflow: hidden;
padding-bottom: 54%;
position: relative;
max-width: 300px;
width: 100%;
}
:host([mode="detailed"]) #cover,
:host([mode="detailed"]) kano-lightboard-preview {
height: 100%;
position: absolute;
left: 0;
top: 0;
width: 100%;
}
:host([mode="summary"]) .cover-wrapper {
border-radius: 3px;
flex: none;
height: 64px;
overflow: hidden;
position: relative;
width: 64px;
}
:host([mode="summary"]) #cover,
:host([mode="summary"]) kano-lightboard-preview {
display: block;
height: 64px;
position: relative;
transform: translateX(-25%);
width: 128px;
}
:host .content {
@apply --layout-flex;
position: relative;
/**
* Prevents overflowing text breaking the layout. See:
* https://css-tricks.com/flexbox-truncated-text/
*/
min-width: 0;
}
:host([mode="detailed"]) #user {
left: 0;
padding-left: 16px;
position: absolute;
top: -32px;
}
:host([mode="detailed"]) .avatar-wrapper {
overflow: hidden;
height: 40px;
width: 40px;
border-radius: 100%;
background-color: var(--color-sky);
border: 4px solid white;
position: relative;
cursor: pointer;
}
:host([mode="detailed"]) #avatar {
margin-top: 5px;
height: auto;
width: 100%;
border-radius: 100%;
overflow: hidden;
}
:host([mode="detailed"]) .username {
background-color: white;
border-radius: 3px;
box-shadow: 0 2px 2px rgba(0,0,0,0.2);
color: var(--color-black);
display: none;
font-size: 14px;
font-weight: bold;
left: 36px;
margin: auto;
padding: 13px 30px;
position: absolute;
top: -100%;
transform: translate(-50%, -20%);
}
:host([mode="detailed"]) .username::after {
bottom: -8px;
color: white;
content: '◢';
font-size: 16px;
height: 16px;
left: 0;
line-height: 16px;
margin: auto;
position: absolute;
right: 0;
text-shadow: 0 2px 2px rgba(0,0,0,0.2);
transform: rotate(45deg);
width: 16px;
}
:host([mode="detailed"]) #user:hover .username {
display: block;
}
:host([mode="detailed"]) .details {
padding: 16px 0 0 0;
}
:host([mode="summary"]) .details {
@apply --layout-vertical;
@apply --layout-start;
@apply --layout-center-justified;
padding: 0 0 0 15px;
}
:host .title {
@apply --layout-horizontal;
@apply --layout-start-justified;
@apply --layout-center;
cursor: pointer;
font-size: 20px;
line-height: 20px;
margin: 0 0 6px 0;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
}
:host([mode="detailed"]) .title {
height: 28px;
}
:host([mode="summary"]) .title {
height: 24px;
}
:host .icon {
flex: none;
}
:host([mode="detailed"]) .icon {
height: 28px;
margin-top: -10px;
width: 28px;
}
:host([mode="summary"]) .icon {
height: 24px;
margin-top: -8px;
width: 24px;
}
:host .title-text {
height: 20px;
overflow: hidden;
padding-bottom: 2px;
text-overflow: ellipsis;
white-space: nowrap;
}
@media all and (max-width: 680px) {
:host {
width: 50%;
}
}
@media all and (min-width: 681px) {
:host([mode="detailed"]) {
width: 300px;
}
:host([mode="detailed"]) .inner {
max-width: 300px;
}
:host([mode="summary"]) {
width: 50%;
}
}
:host([tombstone]) #cover {
background: var(--color-stone);
color: transparent;
}
:host([tombstone]) #avatar {
background: var(--color-stone);
border-radius: 100%;
color: transparent;
}
:host([tombstone]) .title {
width: 50%;
height: 20px;
margin-top: 8px;
background-color: var(--color-stone);
color: transparent;
}
:host([tombstone]) .title-text {
display: none;
}
:host([tombstone]) * {
cursor: default ;
}
:host([tombstone]) .username {
display: none ;
}
:host *[hidden] {
display: none ;
}
</style>
<div class="wrapper">
<div class="inner">
<div class="cover-wrapper">
<dom-if>
<template is="dom-if" if="[[defaultShare]]">
<iron-image id="cover" src="[[selectedShare.cover_url]]" sizing="cover" preload="" fade="" on-tap="_selectShare"></iron-image>
</template>
</dom-if>
<dom-if>
<template is="dom-if" if="[[lightboardShare]]">
<kano-lightboard-preview src="[[selectedShare.attachments.lightboard_spritesheet_url]]" width="[[coverWidth]]" on-tap="_selectShare"></kano-lightboard-preview>
</template>
</dom-if>
</div>
<div class="content">
<div class="details">
<dom-if>
<template is="dom-if" if="[[displayUser]]">
<div id="user" on-tap="_userTapped">
<div class="avatar-wrapper">
<img id="avatar" src\$="[[_computeAvatar(selectedShare)]]">
</div>
<span class="username">[[selectedShare.user.username]]</span>
</div>
</template>
</dom-if>
<h3 class="title" on-tap="_selectShare">
<iron-icon icon="parts:light-animation" class="icon animation" hidden\$="[[!_shareContainsAnimation(selectedShare)]]"></iron-icon>
<span class="title-text">[[selectedShare.title]]</span>
</h3>
<kano-share-stats id="stats" app-integration="[[appIntegration]]" hardware-integration="[[hardwareIntegration]]" liked="[[liked]]" likes="[[numberOfLikes]]" saved-to-device="[[savedToDevice]]" shared-by-user="[[sharedByUser]]" tombstone\$="[[!selectedShare]]" on-like-tapped="_onLikeAction" on-remix="_remix" on-update-device-action="_updateDevice">
</kano-share-stats>
</div>
</div>
</div>
</div>
`,
is: 'kano-share-card',
behaviors: [
APIClient,
ShareBehavior,
Kano.Behaviors.ShareWrapper
],
properties: {
coverWidth: {
type: Number,
computed: '_coverWidth(mode)'
},
defaultAvatar: {
type: String,
value: 'https://s3.amazonaws.com/kano-avatars/judoka-standard.png'
},
defaultShare: {
type: Boolean,
computed: '_defaultShare(selectedShare)'
},
displayUser: {
type: Boolean,
computed: '_displayUser(mode)'
},
lightboardShare: {
type: Boolean,
computed: '_lightboardShare(selectedShare)'
},
mode: {
type: String,
reflectToAttribute: true,
value: 'detailed'
},
token: {
type: String
},
user: {
type: Object
}
},
_coverWidth (mode) {
return mode === 'summary' ? 128 : 288;
},
_defaultShare (share) {
if (!share) {
return true;
}
return !share.attachments || !share.attachments.lightboard_spritesheet_url;
},
_displayUser (mode) {
return mode === 'detailed';
},
_lightboardShare (share) {
if (!share) {
return false;
}
return share.attachments && share.attachments.lightboard_spritesheet_url;
},
_remix (e) {
var item = this.selectedShare;
this.fire('remix-action', {
id: item.id,
slug: item.slug,
type: item.app
});
},
_selectShare () {
if (!this.selectedShare) {
return;
}
this.fire('select-share', this.selectedShare);
},
_userTapped () {
this.fire('view-user', { id: this.selectedShare.user.id });
}
});