Added basic onboarding steps
This commit is contained in:
@@ -191,6 +191,7 @@ Schemas.Character = new SimpleSchema({
|
||||
"settings.exportFeatures": {type: Boolean, defaultValue: true},
|
||||
"settings.exportAttacks": {type: Boolean, defaultValue: true},
|
||||
"settings.exportDescription": {type: Boolean, defaultValue: true},
|
||||
"settings.newUserExperience": {type: Boolean, optional: true},
|
||||
});
|
||||
|
||||
Characters.attachSchema(Schemas.Character);
|
||||
@@ -554,6 +555,10 @@ if (Meteor.isServer){
|
||||
});
|
||||
Characters.before.insert(function(userId, doc) {
|
||||
doc.urlName = getSlug(doc.name, {maintainCase: true}) || "-";
|
||||
// The first character a user creates should have the new user experience
|
||||
if (!Characters.find({owner: userId}).count()){
|
||||
doc.settings.newUserExperience = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
17
rpg-docs/client/style/bounce.css
Normal file
17
rpg-docs/client/style/bounce.css
Normal file
@@ -0,0 +1,17 @@
|
||||
@keyframes bounce {
|
||||
from {
|
||||
transform: translate(0px,0px);
|
||||
}
|
||||
to {
|
||||
transform: translate(0px,-16px);
|
||||
}
|
||||
}
|
||||
|
||||
.bounce{
|
||||
animation-name: bounce;
|
||||
animation-duration: 0.3s;
|
||||
animation-direction: alternate;
|
||||
animation-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||
animation-delay: 0s;
|
||||
animation-iteration-count: infinite;
|
||||
}
|
||||
@@ -44,17 +44,18 @@
|
||||
</div>
|
||||
<div bottom-item>
|
||||
<paper-tabs id="characterSheetTabs" selected={{selectedTab}} class="{{colorClass}}">
|
||||
<paper-tab name="stats">Stats</paper-tab>
|
||||
<paper-tab name="features">Features</paper-tab>
|
||||
<paper-tab name="stats" class="{{#if shouldBounce 0}}bounce{{/if}}">Stats</paper-tab>
|
||||
<paper-tab name="features" class="{{#if shouldBounce 1}}bounce{{/if}}">Features</paper-tab>
|
||||
<paper-tab name="inventory">Inventory</paper-tab>
|
||||
{{#unless hideSpellcasting}}
|
||||
<paper-tab name="spells">Spells</paper-tab>
|
||||
{{/unless}}
|
||||
<paper-tab name="persona">Persona</paper-tab>
|
||||
<paper-tab name="journal">Journal</paper-tab>
|
||||
<paper-tab name="journal" class="{{#if shouldBounce 5}}bounce{{/if}}">Journal</paper-tab>
|
||||
</paper-tabs>
|
||||
</div>
|
||||
</app-toolbar>
|
||||
{{#if session "showNewUserExperience"}}{{> newUserStepper}}{{/if}}
|
||||
</app-header>
|
||||
<div class="flex" style="position: relative;">
|
||||
<iron-pages id="tabPages" class="fit" selected={{selectedTab}}>
|
||||
|
||||
@@ -29,7 +29,17 @@ Template.characterSheet.onRendered(function() {
|
||||
tabFabMenus = _.times(6, (n) =>
|
||||
tabPages[n].find(".mini-holder")
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
// New user experience starts on the features tab
|
||||
var settings = Characters.findOne(this.data._id, {
|
||||
fields: {settings: 1}
|
||||
}).settings;
|
||||
if (settings && settings.newUserExperience){
|
||||
Session.set(this.data._id + ".selectedTab", "1");
|
||||
Session.set("showNewUserExperience", true);
|
||||
Session.set("newUserExperienceStep", 0);
|
||||
}
|
||||
|
||||
//watch this character and make sure their encumbrance is updated
|
||||
//trackEncumbranceConditions(this.data._id, this);
|
||||
@@ -172,6 +182,20 @@ Template.characterSheet.helpers({
|
||||
var char = Characters.findOne(this._id);
|
||||
return char && char.settings.hideSpellcasting;
|
||||
},
|
||||
newUserExperience: function(){
|
||||
var char = Characters.findOne(this._id);
|
||||
return char && char.settings.newUserExperience;
|
||||
},
|
||||
shouldBounce: function(tab){
|
||||
console.log(this._id);
|
||||
const selected = Session.get(this._id + ".selectedTab")
|
||||
const step = Session.get("newUserExperienceStep");
|
||||
console.log({selected, step, tab});
|
||||
if (selected == tab) return false;
|
||||
return (tab === 1 && step === 0) ||
|
||||
(tab === 5 && step === 1) ||
|
||||
(tab === 0 && step === 2);
|
||||
},
|
||||
});
|
||||
|
||||
Template.characterSheet.events({
|
||||
|
||||
@@ -42,9 +42,20 @@
|
||||
</template>
|
||||
|
||||
<template name="featureEdit">
|
||||
{{#if showNewUserExperience}}
|
||||
{{# infoBox}}
|
||||
<p>
|
||||
Features represent all the permanent things your character can do.
|
||||
</p><p>
|
||||
A feature can change a character's stats with effects,
|
||||
or give the character proficiencies, attacks, and buffs.
|
||||
</p><p>
|
||||
Give the feature a name, and close it to continue.
|
||||
</p>
|
||||
{{/infoBox}}
|
||||
{{/if}}
|
||||
<!--name-->
|
||||
<paper-input id="featureNameInput" class="fullwidth" label="Name" value={{name}}></paper-input>
|
||||
|
||||
<div class="layout horizontal center wrap justified">
|
||||
<paper-dropdown-menu class=flex label="Enable Feature" style="flex-basis: 150px; max-width: 200px;">
|
||||
<dicecloud-selector selected={{enabledSelection}} class="dropdown-content enabled-dropdown">
|
||||
|
||||
@@ -47,6 +47,9 @@ Template.featureDetails.events({
|
||||
});
|
||||
|
||||
Template.featureEdit.helpers({
|
||||
showNewUserExperience: function(){
|
||||
return Session.get("newUserExperienceStep") === 0;
|
||||
},
|
||||
usesSet: function(){
|
||||
return _.isString(this.uses);
|
||||
},
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
</div>
|
||||
{{#if canEditCharacter _id}}
|
||||
<paper-fab id="addFeature"
|
||||
class="floatyButton"
|
||||
class="floatyButton {{#if shouldFloatyButtonBounce}}bounce{{/if}}"
|
||||
icon="add">
|
||||
<paper-tooltip position="left">Add Feature</paper-tooltip>
|
||||
</paper-fab>
|
||||
|
||||
@@ -59,6 +59,10 @@ Template.features.helpers({
|
||||
hasCharacters: function(string){
|
||||
return string && string.match(/\S/);
|
||||
},
|
||||
shouldFloatyButtonBounce: function(){
|
||||
const step = Session.get("newUserExperienceStep");
|
||||
return step === 0 && Features.find({charId: this._id}).count() <= 1;
|
||||
},
|
||||
});
|
||||
|
||||
Template.features.events({
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</div>
|
||||
<div class="bottom list">
|
||||
<div class="item-slot">
|
||||
<div class="item race layout horizontal center">
|
||||
<div class="item race layout horizontal center {{#if shouldRaceBounce}}bounce{{/if}}">
|
||||
{{race}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,6 +50,9 @@ Template.journal.helpers({
|
||||
var char = Characters.findOne(this._id, {fields: {race: 1}});
|
||||
return char && char.race;
|
||||
},
|
||||
shouldRaceBounce: function(){
|
||||
return Session.get("newUserExperienceStep") === 1;
|
||||
},
|
||||
});
|
||||
|
||||
Template.journal.events({
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.newUserStepper {
|
||||
height: 300px !important;
|
||||
}
|
||||
|
||||
.newUserStepper paper-step .invalid-step-message {
|
||||
color: #d13b2e;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.newUserStepper paper-step[invalid] .invalid-step-message {
|
||||
visibility: visible;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<template name="newUserStepper">
|
||||
<paper-stepper linear selected="0" class="newUserStepper">
|
||||
<paper-step id="step0" label="Add a feature">
|
||||
<p>
|
||||
To get started, add a feature
|
||||
</p>
|
||||
</paper-step>
|
||||
<paper-step id="step1" label="Add an effect">
|
||||
<p>
|
||||
Add a racial effect to set your speed
|
||||
</p>
|
||||
</paper-step>
|
||||
<paper-step id="step2" label="See the effect in action">
|
||||
<p>
|
||||
View your speed stat
|
||||
</p>
|
||||
</paper-step>
|
||||
<paper-step id="step3" label="Finish">
|
||||
If you get stuck, be sure to check out the guide, or ask for help using the feedback form.
|
||||
</paper-step>
|
||||
</paper-stepper>
|
||||
</template>
|
||||
|
||||
<template name="newUserStepperPlaceholder">
|
||||
<div style="height: 300px"></div>
|
||||
</template>
|
||||
@@ -0,0 +1,41 @@
|
||||
Template.newUserStepper.onRendered(function(){
|
||||
let stepper = this.find("paper-stepper");
|
||||
this.autorun((c) => {
|
||||
var step = Session.get("newUserExperienceStep");
|
||||
var hasFeatures = Features.find({charId: this.data._id}).count() > 1
|
||||
if (step === 0 && hasFeatures){
|
||||
stepper.continue();
|
||||
c.stop();
|
||||
}
|
||||
});
|
||||
this.autorun((c) => {
|
||||
var step = Session.get("newUserExperienceStep");
|
||||
var hasEffect = !!Effects.find({
|
||||
charId: this.data._id,
|
||||
stat: "speed",
|
||||
}).count();
|
||||
if (step === 1 && hasEffect){
|
||||
stepper.continue();
|
||||
c.stop();
|
||||
}
|
||||
});
|
||||
this.autorun((c) => {
|
||||
var step = Session.get("newUserExperienceStep");
|
||||
if (step === 2 && Session.get("viewedSpeed")){
|
||||
stepper.continue();
|
||||
c.stop();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.newUserStepper.events({
|
||||
"paper-stepper-progressed paper-stepper": function(event, template){
|
||||
const step = template.find("paper-stepper").selected;
|
||||
Session.set("newUserExperienceStep", step);
|
||||
},
|
||||
"paper-stepper-completed paper-stepper": function(event, template){
|
||||
Session.set("newUserExperienceStep", undefined);
|
||||
Session.set("showNewUserExperience", undefined);
|
||||
Characters.update(this._id, {$unset: {"settings.newUserExperience": 1}});
|
||||
},
|
||||
});
|
||||
15
rpg-docs/client/views/paperTemplates/infoBox/infoBox.css
Normal file
15
rpg-docs/client/views/paperTemplates/infoBox/infoBox.css
Normal file
@@ -0,0 +1,15 @@
|
||||
.infoBox iron-icon {
|
||||
color: #747474;
|
||||
color: rgba(0,0,0,0.54);
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.infoBox > div > p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.infoBox > div > p + p {
|
||||
margin-top: 10px;
|
||||
}
|
||||
10
rpg-docs/client/views/paperTemplates/infoBox/infoBox.html
Normal file
10
rpg-docs/client/views/paperTemplates/infoBox/infoBox.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<template name="infoBox">
|
||||
<div class="layout horizontal center infoBox">
|
||||
<div>
|
||||
<iron-icon icon="info-outline"></iron-icon>
|
||||
</div>
|
||||
<div class="flex">
|
||||
{{> Template.contentBlock}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -49,6 +49,7 @@
|
||||
"/custom_components/dicecloud-wrapper/dicecloud-wrapper.html",
|
||||
"/custom_components/paper-checkbox/paper-checkbox.html",
|
||||
"/custom_components/paper-diff-slider/paper-diff-slider.html",
|
||||
"/custom_components/paper-stepper/paper-stepper.html",
|
||||
"/custom_components/app-theme.html"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ AccountsTemplates.configure({
|
||||
//behaviour
|
||||
confirmPassword: true,
|
||||
enablePasswordChange: true,
|
||||
enforceEmailVerification: true,
|
||||
enforceEmailVerification: false,
|
||||
overrideLoginErrors: false,
|
||||
sendVerificationEmail: true,
|
||||
lowercaseUsername: true,
|
||||
@@ -21,35 +21,35 @@ AccountsTemplates.configure({
|
||||
|
||||
AccountsTemplates.configureRoute("changePwd", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
AccountsTemplates.configureRoute("enrollAccount", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
AccountsTemplates.configureRoute("forgotPwd", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
AccountsTemplates.configureRoute("resetPwd", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
AccountsTemplates.configureRoute("signIn", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
AccountsTemplates.configureRoute("signUp", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
AccountsTemplates.configureRoute("verifyEmail", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
AccountsTemplates.configureRoute("resendVerificationEmail", {
|
||||
template: "titledAtForm",
|
||||
layoutTemplate: 'layout',
|
||||
layoutTemplate: "layout",
|
||||
});
|
||||
|
||||
if (Meteor.isServer){
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
|
||||
<link rel="import" href="../../../components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../components/neon-animation/neon-animation-behavior.html">
|
||||
<link rel="import" href="../../../components/neon-animation/web-animations.html">
|
||||
|
||||
<script>
|
||||
|
||||
Polymer({
|
||||
|
||||
is: 'fade-in-slide-from-left-animation',
|
||||
|
||||
behaviors: [
|
||||
Polymer.NeonAnimationBehavior
|
||||
],
|
||||
|
||||
configure: function(config) {
|
||||
var node = config.node;
|
||||
|
||||
this._effect = new KeyframeEffect(node, [
|
||||
{'transform': 'translateX(-100%)', 'opacity': '0'},
|
||||
{'transform': 'translateX(-50%)', 'opacity': '0'},
|
||||
{'transform': 'none', 'opacity': '1'}
|
||||
], this.timingFromConfig(config));
|
||||
|
||||
if (config.transformOrigin) {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', config.transformOrigin);
|
||||
} else {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', '0 50%');
|
||||
}
|
||||
|
||||
return this._effect;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,45 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
|
||||
<link rel="import" href="../../../components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../components/neon-animation/neon-animation-behavior.html">
|
||||
<link rel="import" href="../../../components/neon-animation/web-animations.html">
|
||||
|
||||
<script>
|
||||
|
||||
Polymer({
|
||||
|
||||
is: 'fade-in-slide-from-right-animation',
|
||||
|
||||
behaviors: [
|
||||
Polymer.NeonAnimationBehavior
|
||||
],
|
||||
|
||||
configure: function(config) {
|
||||
var node = config.node;
|
||||
|
||||
this._effect = new KeyframeEffect(node, [
|
||||
{'transform': 'translateX(100%)', 'opacity': '0'},
|
||||
{'transform': 'translateX(50%)', 'opacity': '0'},
|
||||
{'transform': 'none', 'opacity': '1'}
|
||||
], this.timingFromConfig(config));
|
||||
|
||||
if (config.transformOrigin) {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', config.transformOrigin);
|
||||
} else {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', '0 50%');
|
||||
}
|
||||
|
||||
return this._effect;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,45 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
|
||||
<link rel="import" href="../../../components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../components/neon-animation/neon-animation-behavior.html">
|
||||
<link rel="import" href="../../../components/neon-animation/web-animations.html">
|
||||
|
||||
<script>
|
||||
|
||||
Polymer({
|
||||
|
||||
is: 'fade-out-slide-left-animation',
|
||||
|
||||
behaviors: [
|
||||
Polymer.NeonAnimationBehavior
|
||||
],
|
||||
|
||||
configure: function(config) {
|
||||
var node = config.node;
|
||||
|
||||
this._effect = new KeyframeEffect(node, [
|
||||
{'transform': 'none', 'opacity': '1'},
|
||||
{'transform': 'translateX(-50%)', 'opacity': '0'},
|
||||
{'transform': 'translateX(-100%)', 'opacity': '0'},
|
||||
], this.timingFromConfig(config));
|
||||
|
||||
if (config.transformOrigin) {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', config.transformOrigin);
|
||||
} else {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', '0 50%');
|
||||
}
|
||||
|
||||
return this._effect;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,45 @@
|
||||
<!--
|
||||
@license
|
||||
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
-->
|
||||
|
||||
<link rel="import" href="../../../components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../components/neon-animation/neon-animation-behavior.html">
|
||||
<link rel="import" href="../../../components/neon-animation/web-animations.html">
|
||||
|
||||
<script>
|
||||
|
||||
Polymer({
|
||||
|
||||
is: 'fade-out-slide-right-animation',
|
||||
|
||||
behaviors: [
|
||||
Polymer.NeonAnimationBehavior
|
||||
],
|
||||
|
||||
configure: function(config) {
|
||||
var node = config.node;
|
||||
|
||||
this._effect = new KeyframeEffect(node, [
|
||||
{'transform': 'none', 'opacity': '1'},
|
||||
{'transform': 'translateX(50%)', 'opacity': '1'},
|
||||
{'transform': 'translateX(100%)', 'opacity': '0'}
|
||||
], this.timingFromConfig(config));
|
||||
|
||||
if (config.transformOrigin) {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', config.transformOrigin);
|
||||
} else {
|
||||
this.setPrefixedProperty(node, 'transformOrigin', '0 50%');
|
||||
}
|
||||
|
||||
return this._effect;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
48
rpg-docs/public/custom_components/paper-stepper/bower.json
Normal file
48
rpg-docs/public/custom_components/paper-stepper/bower.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "paper-stepper",
|
||||
"version": "2.0-beta.5",
|
||||
"authors": [
|
||||
"Zecat <jullienfelix@gmail.com>"
|
||||
],
|
||||
"description": "Material paper-stepper element.",
|
||||
"keywords": [
|
||||
"web-component",
|
||||
"polymer",
|
||||
"seed"
|
||||
],
|
||||
"main": "paper-stepper.html",
|
||||
"license": "http://polymer.github.io/LICENSE.txt",
|
||||
"homepage": "https://github.com/zecat/paper-stepper/",
|
||||
"ignore": [
|
||||
"/.*",
|
||||
"/test/"
|
||||
],
|
||||
"dependencies": {
|
||||
"polymer": "Polymer/polymer#^1.2.0",
|
||||
"paper-button": "PolymerElements/paper-button#^1.0.11",
|
||||
"iron-icons": "PolymerElements/iron-icons#^1.1.3",
|
||||
"paper-styles": "PolymerElements/paper-styles#^1.1.4",
|
||||
"paper-ripple": "PolymerElements/paper-ripple#^1.0.5",
|
||||
"iron-selector": "PolymerElements/iron-selector#^1.3.0",
|
||||
"iron-icon": "PolymerElements/iron-icon#^1.0.8",
|
||||
"iron-flex-layout": "PolymerElements/iron-flex-layout#^1.3.1",
|
||||
"neon-animation": "PolymerElements/neon-animation#^1.1.1",
|
||||
"iron-validatable-behavior": "PolymerElements/iron-validatable-behavior#^1.0.5",
|
||||
"iron-collapse": "PolymerElements/iron-collapse#^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"paper-input": "PolymerElements/paper-input#^1.1.10",
|
||||
"paper-material": "PolymerElements/paper-material#^1.0.6",
|
||||
"iron-component-page": "PolymerElements/iron-component-page#^1.0.0",
|
||||
"web-component-tester": "*",
|
||||
"iron-form": "PolymerElements/iron-form#^1.0.16",
|
||||
"iron-demo-helpers": "PolymerElements/iron-demo-helpers#^1.2.2",
|
||||
"paper-toggle-button": "PolymerElements/paper-toggle-button#^1.2.0",
|
||||
"app-layout": "PolymerElements/app-layout#^0.10.2",
|
||||
"paper-menu": "PolymerElements/paper-menu#^1.2.2",
|
||||
"iron-scroll-spy": "Zecat/iron-scroll-spy#^2.1.0",
|
||||
"paper-item": "PolymerElements/paper-item#^1.2.1",
|
||||
"paper-toast": "PolymerElements/paper-toast#^1.3.0",
|
||||
"paper-checkbox": "PolymerElements/paper-checkbox#^1.4.0"
|
||||
}
|
||||
}
|
||||
27
rpg-docs/public/custom_components/paper-stepper/hero.svg
Normal file
27
rpg-docs/public/custom_components/paper-stepper/hero.svg
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 225 126" enable-background="new 0 0 225 126" xml:space="preserve">
|
||||
<g id="background" display="none">
|
||||
<rect display="inline" fill="#B0BEC5" width="225" height="126"/>
|
||||
</g>
|
||||
<g id="label">
|
||||
</g>
|
||||
<g id="art">
|
||||
<g id="ic_x5F_add_x0D_">
|
||||
</g>
|
||||
<circle cx="78" cy="98" r="4"/>
|
||||
<circle cx="171" cy="90" r="4"/>
|
||||
<circle cx="132" cy="61" r="4"/>
|
||||
<circle cx="53" cy="61" r="4"/>
|
||||
<circle cx="126" cy="28" r="4"/>
|
||||
<circle cx="91" cy="67" r="4"/>
|
||||
<circle cx="132" cy="90" r="4"/>
|
||||
<circle cx="65" cy="32" r="4"/>
|
||||
<path d="M77.7,99.4L51.9,61.1L64.3,31l64.1-4.2L92.6,66.7l16.1,9l23.3-16L174,91h-42.3l-23-12.9L77.7,99.4z M54.1,60.9l24.1,35.7
|
||||
L106.8,77l-17.4-9.8l34.2-38.1L65.7,33L54.1,60.9z M132.3,89H168l-36-26.8l-21.4,14.6L132.3,89z"/>
|
||||
</g>
|
||||
<g id="Guides">
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
424
rpg-docs/public/custom_components/paper-stepper/paper-step.html
Normal file
424
rpg-docs/public/custom_components/paper-stepper/paper-step.html
Normal file
@@ -0,0 +1,424 @@
|
||||
<link rel="import" href="../../components/iron-validatable-behavior/iron-validatable-behavior.html">
|
||||
<link rel="import" href="../../components/paper-item/paper-item-behavior.html">
|
||||
<link rel="import" href="../../components/paper-behaviors/paper-ripple-behavior.html">
|
||||
<link rel="import" href="../../components/neon-animation/neon-animatable-behavior.html">
|
||||
<link rel="import" href="../../components/paper-styles/default-theme.html">
|
||||
<link rel="import" href="step-horizontal-label.html">
|
||||
<link rel="import" href="step-vertical.html">
|
||||
<link rel="import" href="../../components/polymer/polymer.html">
|
||||
|
||||
<!--
|
||||
Missing Doc
|
||||
@element paper-step
|
||||
@demo demo/index.html
|
||||
@hero hero.svg
|
||||
-->
|
||||
<dom-module id="paper-step">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
outline: 0;
|
||||
}
|
||||
:host(:not([vertical])) {
|
||||
overflow: hidden;
|
||||
@apply(--layout);
|
||||
@apply(--layout-flex);
|
||||
}
|
||||
:host(:not([vertical])[opened]){
|
||||
overflow: visible;
|
||||
}
|
||||
:host(:not([opened]):not(.neon-animating)) #slideshowViewport{
|
||||
display: none;
|
||||
}
|
||||
#slideshowViewport {
|
||||
position: absolute;
|
||||
bottom: 42px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
#contentWrapper {
|
||||
padding: 16px 0 16px 16px;
|
||||
@apply(--layout-scroll);
|
||||
@apply(--layout-fit);
|
||||
pointer-events: auto;
|
||||
}
|
||||
:host(:focus:not([opened]):not([saved])) step-horizontal-label ::content #badge {
|
||||
background: var(--paper-step-selectable-hovered-badge-background, --paper-grey-500);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- horizontal step layout -->
|
||||
|
||||
<template is="dom-if" if="[[!vertical]]">
|
||||
<step-horizontal-label id="horizontalStepLabel" editable="[[editable]]" label="[[label]]"
|
||||
alternative-label="[[_alternativeLabel]]" optional="[[optional]]"
|
||||
opened="[[opened]]" selectable="[[selectable]]" index="[[index]]"
|
||||
saved="[[saved]]" stepper-data="[[_stepperData]]">
|
||||
</step-horizontal-label>
|
||||
<div id="slideshowViewport">
|
||||
<div id="contentWrapper">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- vertical step layout -->
|
||||
|
||||
<template is="dom-if" if="[[vertical]]">
|
||||
<step-vertical id="verticalStepLabel" editable="[[editable]]" label="[[label]]"
|
||||
optional="[[optional]]" opened="[[opened]]"
|
||||
selectable="[[selectable]]" stepper-data="[[_stepperData]]" index="[[index]]"
|
||||
saved="[[saved]]" _attr-for-primary-button-text="[[_attrForPrimaryButtonText]]"
|
||||
can-skip="[[_canSkip]]" has-back-step="[[_hasBackStep]]">
|
||||
</step-vertical>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
Polymer({
|
||||
|
||||
is: 'paper-step',
|
||||
|
||||
behaviors: [
|
||||
Polymer.IronValidatableBehavior,
|
||||
Polymer.NeonAnimatableBehavior,
|
||||
Polymer.PaperItemBehavior,
|
||||
Polymer.PaperRippleBehavior
|
||||
],
|
||||
|
||||
/**
|
||||
* Fired when the step has been saved.
|
||||
*
|
||||
* @event paper-step-saved
|
||||
*/
|
||||
/**
|
||||
* Fired when the step has been updated
|
||||
*
|
||||
* @event paper-step-updated
|
||||
*/
|
||||
properties: {
|
||||
/**
|
||||
* MISSING Doc
|
||||
*/
|
||||
saved: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
notify: true,
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
editable: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
index: {
|
||||
type: Number,
|
||||
notify: true,
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
_previousSaved: {
|
||||
type: Boolean,
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
optional: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
selectable: {
|
||||
type: Boolean,
|
||||
computed: '_computeSelectable(_stepperData.linear, saved, editable, _previousSaved)',
|
||||
reflectToAttribute: true,
|
||||
notify: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
disabled: {
|
||||
computed: '_computeDisabled(selectable)'
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
label: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
opened: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
animationConfig: {
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
entryAnimation: {
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
exitAnimation: {
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
readOnly: true,
|
||||
reflectToAttribute: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
horizontalHigherEntryAnimation: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
horizontalHigherExitAnimation: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
horizontalLowerEntryAnimation: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
horizontalLowerExitAnimation: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
_alternativeLabel: {
|
||||
type: Boolean,
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
_optionalText: {
|
||||
type: Boolean,
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
_attrForPrimaryButtonText: {
|
||||
type: String,
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* A reference to the parent stepper
|
||||
*/
|
||||
_stepper: {
|
||||
type: Object,
|
||||
readOnly: true
|
||||
},
|
||||
_stepperData: {
|
||||
type: Object,
|
||||
readOnly: true
|
||||
},
|
||||
_canSkip: {
|
||||
type: Boolean,
|
||||
readOnly: true
|
||||
},
|
||||
_hasBackStep: {
|
||||
type: Boolean,
|
||||
readOnly: true
|
||||
}
|
||||
},
|
||||
|
||||
listeners: {
|
||||
'paper-step-vertical-skip-tapped': 'skip',
|
||||
'paper-step-vertical-back-tapped': 'back',
|
||||
'paper-step-vertical-continue-tapped': 'continue',
|
||||
'tap': '_tapHandler'
|
||||
},
|
||||
|
||||
observers: [
|
||||
'_toggleClassPosition(index, _stepperData.stepNumber, vertical)',
|
||||
'_updateSlideshowViewportTop(optional, _alternativeLabel, vertical)',
|
||||
'_verticalChange(vertical)',
|
||||
'_focusedChanged(receivedFocusFromKeyboard)',
|
||||
'_labelElementChanged(_labelElement)'
|
||||
],
|
||||
|
||||
_focusedChanged: function(receivedFocusFromKeyboard) {
|
||||
if (receivedFocusFromKeyboard) {
|
||||
this.ensureRipple();
|
||||
// generate a ripple effect from the center of the badge
|
||||
var badge = Polymer.dom(this._rippleContainer).querySelector('#badge');
|
||||
var badgePos = badge.getBoundingClientRect();
|
||||
var rippleX = badgePos.left + 12;
|
||||
var rippleY = badgePos.top + 12;
|
||||
this._ripple.downAction({detail: {x: rippleX, y: rippleY}});
|
||||
}
|
||||
if (this.hasRipple()) {
|
||||
this._ripple.holdDown = receivedFocusFromKeyboard;
|
||||
}
|
||||
},
|
||||
|
||||
_tapHandler: function(e) {
|
||||
var rootTarget = Polymer.dom(e).rootTarget;
|
||||
if (rootTarget !== this && rootTarget !== this._rippleContainer) {
|
||||
e.stopImmediatePropagation();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
skip: function() {
|
||||
// would it be better to send an event?
|
||||
this._stepper.progress();
|
||||
},
|
||||
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
back: function() {
|
||||
// would it be better to send an event?
|
||||
this._stepper.back();
|
||||
},
|
||||
|
||||
/**
|
||||
* Mark the step as saved and fire `paper-step-saved` if it is valid.
|
||||
* @return {Boolean} True if the step has been saved.
|
||||
*/
|
||||
save: function() {
|
||||
if ((!this.saved || this.editable) && this.validate()) {
|
||||
if (this.saved) {
|
||||
this.fire('paper-step-updated');
|
||||
} else {
|
||||
this._setSaved(true);
|
||||
this.fire('paper-step-saved');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Atempte to save the step and select and to progress into the stepper.
|
||||
* @return {Boolean} True if the step is valid for saving.
|
||||
*/
|
||||
continue: function() {
|
||||
if (this.save()) {
|
||||
// would it be better to send an event?
|
||||
this._stepper.progress();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_removeAnimatingClass: function() {
|
||||
if (this._animationCanceled) {
|
||||
this._set_animationCanceled(false);
|
||||
} else {
|
||||
this.toggleClass('neon-animating', false);
|
||||
}
|
||||
},
|
||||
|
||||
_cancelAnimation: function() {
|
||||
this._set_animationCanceled(true);
|
||||
this.toggleClass('neon-animating', false);
|
||||
},
|
||||
|
||||
_updateSlideshowViewportTop: function(optional, _alternativeLabel, vertical) {
|
||||
if (!vertical) {
|
||||
this.async(function() {
|
||||
this.$$('#slideshowViewport').style.top = this.clientHeight+'px';
|
||||
this.fire('step-horizontal-label-resize');
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
_toggleClassPosition: function(index, stepNumber, vertical) {
|
||||
this.async(function() {
|
||||
var stepLabel = this.$$(vertical ? '#verticalStepLabel' : '#horizontalStepLabel');
|
||||
this.toggleClass('first-step', (index == 1), stepLabel);
|
||||
this.toggleClass('last-step', (index == stepNumber), stepLabel);
|
||||
});
|
||||
},
|
||||
|
||||
_updateAnimationConfig: function() {
|
||||
/* TODO: call this method when horizontalHigher/LowerEntry/ExitAnimation change */
|
||||
var animatedNode = this.$$('#contentWrapper');
|
||||
this._setAnimationConfig({
|
||||
'higher-step-entry': {
|
||||
node: animatedNode,
|
||||
name: this.horizontalHigherEntryAnimation
|
||||
},
|
||||
'higher-step-exit': {
|
||||
node: animatedNode,
|
||||
name: this.horizontalHigherExitAnimation
|
||||
},
|
||||
'lower-step-entry': {
|
||||
node: animatedNode,
|
||||
name: this.horizontalLowerEntryAnimation
|
||||
},
|
||||
'lower-step-exit': {
|
||||
node: animatedNode,
|
||||
name: this.horizontalLowerExitAnimation
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_verticalChange: function(vertical) {
|
||||
this.async(function() {
|
||||
// move or create the content tag
|
||||
Polymer.dom(this.$$(vertical ? '#verticalStepLabel' : '#contentWrapper')).appendChild(this.$$('content') || this.create('content'));
|
||||
// reset the ripple
|
||||
this._ripple = false;
|
||||
this._rippleContainer = vertical ? this.$$('#verticalStepLabel').$.label : this.$$('#horizontalStepLabel').$.label;
|
||||
if (!vertical) {
|
||||
this._updateAnimationConfig();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_computeSelectable: function(linear, saved, editable, previousSaved) {
|
||||
// TODO: factorize the expression
|
||||
return (!linear || previousSaved) && (!saved || editable) || (editable && saved);
|
||||
},
|
||||
|
||||
_computeDisabled: function(selectable) {
|
||||
// disabled is used by IronMenuBehavior in paper-stepper
|
||||
// TODO: remove selectable attribute and use disabled instead
|
||||
return !selectable;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</dom-module>
|
||||
@@ -0,0 +1,735 @@
|
||||
<link rel="import" href="../../components/iron-flex-layout/iron-flex-layout.html">
|
||||
<link rel="import" href="../../components/iron-selector/iron-selectable.html">
|
||||
<link rel="import" href="../../components/iron-menu-behavior/iron-menu-behavior.html">
|
||||
<link rel="import" href="../../components/neon-animation/neon-animation-runner-behavior.html">
|
||||
<link rel="import" href="../../components/paper-button/paper-button.html">
|
||||
<link rel="import" href="../../components/paper-styles/default-theme.html">
|
||||
<link rel="import" href="../../components/paper-styles/shadow.html">
|
||||
<link rel="import" href="../../components/iron-collapse/iron-collapse.html">
|
||||
<link rel="import" href="../../components/iron-resizable-behavior/iron-resizable-behavior.html">
|
||||
<link rel="import" href="../../components/polymer/polymer.html">
|
||||
<link rel="import" href="animations/fade-in-slide-from-right-animation.html">
|
||||
<link rel="import" href="animations/fade-out-slide-right-animation.html">
|
||||
<link rel="import" href="animations/fade-in-slide-from-left-animation.html">
|
||||
<link rel="import" href="animations/fade-out-slide-left-animation.html">
|
||||
<link rel="import" href="paper-step.html">
|
||||
|
||||
<!--
|
||||
Missing Doc
|
||||
|
||||
|
||||
## Styling
|
||||
|
||||
The default color values respect the material specifications. For basic configuration, just defines the `--primary-color` for your app.
|
||||
|
||||
The stepper has a complexe interface so many custom properties are available, use them this way :
|
||||
|
||||
```html
|
||||
<style is="custom-style">
|
||||
|
||||
paper-stepper {
|
||||
--paper-stepper-custom-property: value;
|
||||
}
|
||||
|
||||
paper-step {
|
||||
--paper-step-custom-property: value;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<paper-stepper>
|
||||
<paper-step></paper-step>
|
||||
<paper-step></paper-step>
|
||||
</paper-stepper>
|
||||
```
|
||||
|
||||
Note, for sizing the stepper and steps depending on the layout, use the following instead of setting 'height' and 'max-height' :
|
||||
- `--paper-stepper-horizontal-opened-height`
|
||||
- `--paper-stepper-vertical-max-height`
|
||||
- `--paper-vertical-step-max-height`
|
||||
|
||||
### Stepper
|
||||
|
||||
Custom property | Description | Default
|
||||
------|-------------|----------
|
||||
`--paper-stepper-horizontal-opened-height` | The horizontal opened stepper height | 450px
|
||||
`--paper-stepper-horizontal-opening-transition-duration`| The horizontal stepper opening transition duration (ms) | 500
|
||||
`--paper-stepper-vertical-max-height`| The vertical stepper max height so it has a scrollable area | undefined
|
||||
|
||||
### Step
|
||||
|
||||
Custom property | Description | Default
|
||||
------|-------------|----------
|
||||
`--paper-step-connector-line-background` | The connector lines background color. | `--divider-color`
|
||||
`--paper-step-label-hover-background` | The steps label background when hovered. | rgba(0,0,0,0.04)
|
||||
`--paper-step-ink-color` | The steps ripple effect ink color. | `--divider-color`
|
||||
|
||||
### Step text label
|
||||
|
||||
Custom property | Description | Default
|
||||
------|-------------|----------
|
||||
`--paper-step-disabled-label-text-color` | The no-selectable steps label text color. | `--paper-grey-400`
|
||||
`--paper-step-selectable-label-text-color` | The selectable steps label text color. | `--paper-grey-600`
|
||||
`--paper-step-opened-label-text-color` | The opened steps label text color. | `--light-theme-text-color`
|
||||
`--paper-step-label-text-font-size` | The steps label text font size. | 14px
|
||||
`--paper-step-label-optional-text-font-size` | The steps label optional text font size. | 12px
|
||||
|
||||
### Step badge
|
||||
|
||||
Custom property | Description | Default
|
||||
------|-------------|----------
|
||||
`--paper-step-badge-background` | The badge background. | `--paper-grey-300`
|
||||
`--paper-step-badge-color` | The badge color. | `--dark-theme-text-color`
|
||||
`--paper-step-badge-icon-width` | The badge icon width. | 16px
|
||||
`--paper-step-badge-icon-height` | The badge icon height. | 16px
|
||||
`--paper-step-opened-badge-background` | The opened steps badge background. | `--primary-color`
|
||||
`--paper-step-saved-badge-background` | The saved steps badge background. | `--primary-color`
|
||||
`--paper-step-selectable-hovered-badge-background` | The no-opened no-saved selectable steps badge background. | `--paper-grey-500`
|
||||
|
||||
### Vertical step
|
||||
|
||||
Custom property | Description | Default
|
||||
------|-------------|----------
|
||||
`--paper-vertical-step-continue-button-background` | The continue button background. | `--primary-color`
|
||||
`--paper-vertical-step-continue-button-color` | The continue button background. | `--dark-theme-text-color`
|
||||
`--paper-vertical-step-max-height` | The unrolled step content max-height. | 400px
|
||||
`--paper-vertical-step-transition-duration` | The step opening transition duration | 500ms
|
||||
|
||||
|
||||
@element paper-stepper
|
||||
@demo demo/index.html
|
||||
@hero hero.svg
|
||||
-->
|
||||
<dom-module id="paper-stepper">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
@apply(--layout-vertical);
|
||||
@apply(--shadow-elevation-2dp);
|
||||
background: white;
|
||||
border-radius: 1px;
|
||||
}
|
||||
#verticalResponsiveWidth {
|
||||
width: var(--paper-stepper-vertical-responsive-width, 0px);
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/* Horizontal layout styles */
|
||||
|
||||
:host([vertical]) {
|
||||
padding: 4px 0;
|
||||
@apply(--layout-scroll);
|
||||
max-height: var(--paper-stepper-vertical-max-height);
|
||||
}
|
||||
:host(:not([vertical])) {
|
||||
position: relative;
|
||||
/* Note: this variable is updated by the stepper itself, don't use it on user side */
|
||||
height: var(--label-wrapper-height);
|
||||
max-height: var(--label-wrapper-height);
|
||||
transition: max-height var(--paper-stepper-horizontal-opening-transition-duration, 300ms), box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
:host(:not([vertical]):not([opened]):not(.collapsing)) {
|
||||
@apply(--shadow-none);
|
||||
}
|
||||
:host(:not([vertical])[opened]) {
|
||||
max-height: var(--paper-stepper-horizontal-opened-height, 450px);
|
||||
}
|
||||
:host(:not([vertical])[opened]), :host(:not([vertical]).collapsing) {
|
||||
height: var(--paper-stepper-horizontal-opened-height, 450px);
|
||||
}
|
||||
:host(:not([vertical])) #content-wrapper {
|
||||
@apply(--shadow-elevation-2dp);
|
||||
@apply(--layout-horizontal);
|
||||
@apply(--layout-flex-none);
|
||||
@apply(--layout-justified);
|
||||
background: var(--paper-stepper-horizontal-label-wrapper-background, --primary-background-color);
|
||||
border-radius: 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.flex {
|
||||
@apply(--layout-flex);
|
||||
}
|
||||
#buttonsWrapper {
|
||||
@apply(--layout-horizontal);
|
||||
overflow: hidden;
|
||||
}
|
||||
#continueButton:not([disabled]) {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
paper-button[disabled] {
|
||||
background-color: transparent;
|
||||
}
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
:host(:not[vertical]) #content-wrapper ::content paper-step[opened] {
|
||||
overflow: visible;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Hidden block with width equals to the responsive threshold -->
|
||||
<div id="verticalResponsiveWidth"></div>
|
||||
|
||||
<!-- This wrapper contains the horizontal stepper header or the full vertical stepper -->
|
||||
<div id="content-wrapper">
|
||||
<content select="[[selectable]]"></content>
|
||||
</div>
|
||||
|
||||
<!-- Slideshow and buttons area for horizontal layout -->
|
||||
<template is="dom-if" if="[[!vertical]]">
|
||||
<div class="flex"></div>
|
||||
<div id="buttonsWrapper">
|
||||
<paper-button hidden$="[[!hasBackButton]]" disabled=[[!_hasBackStep]] on-tap="back">[[backText]]</paper-button>
|
||||
<span class="flex"></span>
|
||||
<paper-button hidden$="[[!hasSkipButton]]" disabled="[[!_canSkip]]" on-tap="progress">[[skipText]]</paper-button>
|
||||
<!--
|
||||
<paper-button id="continueButton" on-tap="continue">{{_choosePrimaryButtonText(_attrForSelectedStepPrimaryButtonText, finishText, continueText, updateText)}}</paper-button>
|
||||
-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
Polymer({
|
||||
|
||||
is: 'paper-stepper',
|
||||
|
||||
behaviors: [
|
||||
Polymer.IronMenuBehavior,
|
||||
Polymer.NeonAnimationRunnerBehavior,
|
||||
Polymer.IronResizableBehavior
|
||||
],
|
||||
|
||||
/**
|
||||
* Fired when the stepper progress.
|
||||
*
|
||||
* @event paper-stepper-progressed
|
||||
*/
|
||||
/**
|
||||
* Fired when all the steps are saved.
|
||||
*
|
||||
* @event paper-stepper-completed
|
||||
*/
|
||||
properties: {
|
||||
opened: {
|
||||
type: Boolean,
|
||||
computed: '_computeOpened(_selectedIndex)',
|
||||
observer: '_openedChanged',
|
||||
notify: true,
|
||||
reflectToAttribute: true
|
||||
},
|
||||
alternativeLabel: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
reflectToAttribute: true
|
||||
},
|
||||
backText: {
|
||||
type: String,
|
||||
value: 'BACK'
|
||||
},
|
||||
finishText: {
|
||||
type: String,
|
||||
value: 'FINISH'
|
||||
},
|
||||
continueText: {
|
||||
type: String,
|
||||
value: 'CONTINUE'
|
||||
},
|
||||
skipText: {
|
||||
type: String,
|
||||
value: 'SKIP'
|
||||
},
|
||||
optionalText: {
|
||||
type: String,
|
||||
value: 'Optional'
|
||||
},
|
||||
updateText: {
|
||||
type: String,
|
||||
value: 'UPDATE'
|
||||
},
|
||||
linear: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
completed: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
notify: true,
|
||||
computed: '_computeCompleted(stepNumber, savedStepNumber)'
|
||||
},
|
||||
hasSkipButton: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
hasBackButton: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
stepNumber: {
|
||||
type: Number,
|
||||
notify: true,
|
||||
computed: '_computeStepNumber(items.length)'
|
||||
},
|
||||
savedStepNumber: {
|
||||
type: Number,
|
||||
notify: true,
|
||||
readOnly: true
|
||||
},
|
||||
selectedAttribute: {
|
||||
value: 'opened',
|
||||
readOnly: true
|
||||
},
|
||||
/**
|
||||
* Note: if you decide to change this attribute, take care to only include `<paper-step>` elements in your `<paper-stepper>`
|
||||
*/
|
||||
selectable: {
|
||||
value: 'paper-step'
|
||||
},
|
||||
/**
|
||||
* Multi mode is not allowed for now in paper-stepper.
|
||||
*/
|
||||
mutli: {
|
||||
value: false,
|
||||
readOnly: true
|
||||
},
|
||||
responsiveCheckFrequence: {
|
||||
type: Number,
|
||||
value: 200
|
||||
},
|
||||
animateInitialSelection: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
horizontalHigherEntryAnimation: {
|
||||
type: String,
|
||||
value: 'fade-in-slide-from-right-animation'
|
||||
},
|
||||
horizontalHigherExitAnimation: {
|
||||
type: String,
|
||||
value: 'fade-out-slide-right-animation'
|
||||
},
|
||||
horizontalLowerEntryAnimation: {
|
||||
type: String,
|
||||
value: 'fade-in-slide-from-left-animation'
|
||||
},
|
||||
horizontalLowerExitAnimation: {
|
||||
type: String,
|
||||
value: 'fade-out-slide-left-animation'
|
||||
},
|
||||
_skipStepIndex: {
|
||||
type: Number,
|
||||
computed: '_compute_skipStepIndex(_selectedIndex)'
|
||||
},
|
||||
_canSkip: {
|
||||
type: Boolean,
|
||||
notify: true,
|
||||
computed: '_isntNull(_skipStepIndex)'
|
||||
},
|
||||
_backStepIndex: {
|
||||
type: Number,
|
||||
computed: '_compute_backStepIndex(_selectedIndex)'
|
||||
},
|
||||
_hasBackStep: {
|
||||
type: Boolean,
|
||||
computed: '_isntNull(_backStepIndex)'
|
||||
},
|
||||
_selectedIndex: {
|
||||
type: Number,
|
||||
observer: '_selectedIndexChanged',
|
||||
readOnly: true,
|
||||
value: -1
|
||||
},
|
||||
_attrForSelectedStepPrimaryButtonText: {
|
||||
type: String,
|
||||
computed: '_compute__attrForSelectedStepPrimaryButtonText(_selectedIndex, stepNumber)'
|
||||
},
|
||||
_previousAnimatedStep: {
|
||||
type: Object,
|
||||
value: null,
|
||||
readOnly: true
|
||||
},
|
||||
_previousSelected: {
|
||||
type: Object,
|
||||
readOnly: true
|
||||
}
|
||||
},
|
||||
|
||||
keyBindings: {
|
||||
'left': '_onLeftKey',
|
||||
'right': '_onRightKey'
|
||||
},
|
||||
|
||||
listeners: {
|
||||
'iron-items-changed': '_initializeSteps',
|
||||
'paper-step-saved': '_stepSaved',
|
||||
'transitionend': '_transitionEnd',
|
||||
'step-horizontal-label-resize': '_updateStepperClosedMaxHeight',
|
||||
'iron-resize': '_resizeHandler',
|
||||
'neon-animation-finish': '_onNeonAnimationFinish'
|
||||
},
|
||||
|
||||
observers: [
|
||||
'_forwardCanSkip(_canSkip, selectedItem)',
|
||||
'_forwardHasBackStep(_hasBackStep, selectedItem)',
|
||||
'_forwardVertical(vertical)',
|
||||
'_forwardAlternativeLabel(alternativeLabel)',
|
||||
'_forwardStepperData(linear, backText, optionalText, finishText, continueText, skipText, updateText, hasSkipButton, hasBackButton)'
|
||||
],
|
||||
|
||||
attached: function() {
|
||||
this._responsiveCheck();
|
||||
},
|
||||
|
||||
/**
|
||||
* Missing Doc
|
||||
*/
|
||||
back: function() {
|
||||
this.selectIndex(this._backStepIndex);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {Boolean} Try to continue the current step (if no step opened, use the first one).
|
||||
*/
|
||||
continue: function() {
|
||||
if (this.selectedItem) {
|
||||
if (this.selectedItem.save()) {
|
||||
this.progress();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Loops around the steps from the current (if no step opened, from the first one)
|
||||
* in order to open the next selectable unsaved step. Returns true if a step has been opened.
|
||||
*/
|
||||
progress: function() {
|
||||
if (!this.stepNumber) {
|
||||
return false;
|
||||
}
|
||||
if (this.completed) {
|
||||
this.selected = null;
|
||||
return true;
|
||||
}
|
||||
for (var i = (this._selectedIndex+1)%this.stepNumber; i != this._selectedIndex; i = (i+1)%this.stepNumber) {
|
||||
if (this.items[i].selectable && !this.items[i].saved) {
|
||||
this.selectIndex(i);
|
||||
this.fire('paper-stepper-progressed');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/* Deselect and set the steps as unsaved*/
|
||||
reset: function() {
|
||||
this._setSavedStepNumber(0);
|
||||
this.selected = null;
|
||||
if (!this.items.length) {
|
||||
return;
|
||||
}
|
||||
this.items.map(function(step) {
|
||||
step._setSaved(false);
|
||||
step._set_previousSaved(false);
|
||||
});
|
||||
this.items[0]._set_previousSaved(true);
|
||||
},
|
||||
|
||||
get _isRTL() {
|
||||
return window.getComputedStyle(this)['direction'] === 'rtl';
|
||||
},
|
||||
|
||||
_onLeftKey: function(event) {
|
||||
if (this._isRTL) {
|
||||
this._focusNext();
|
||||
} else {
|
||||
this._focusPrevious();
|
||||
}
|
||||
event.detail.keyboardEvent.preventDefault();
|
||||
},
|
||||
|
||||
_onRightKey: function(event) {
|
||||
if (this._isRTL) {
|
||||
this._focusPrevious();
|
||||
} else {
|
||||
this._focusNext();
|
||||
}
|
||||
event.detail.keyboardEvent.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
* Work around: Override the method from IronSelectableBehavior to only allow the selection of selectable step. https://github.com/PolymerElements/iron-selector/issues/99
|
||||
*/
|
||||
_selectSelected: function(selected) {
|
||||
var item = this._valueToItem(this.selected);
|
||||
if (item) {
|
||||
var selectable = item.selectable;
|
||||
if (selectable == undefined) {
|
||||
// if selectable isn't define it means the step is not yet ready for selection
|
||||
// and this method will be recalled by the initialization method.
|
||||
return;
|
||||
} else if (!selectable) {
|
||||
//reset previous selected if non null and selectable or deselect
|
||||
if (this._previousSelected && this._previousSelected.selectable) {
|
||||
this.selected = this._valueForItem(this.previousSelected);
|
||||
} else {
|
||||
this.selected = null;
|
||||
}
|
||||
this._set_previousSelected(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._selection.select(item);
|
||||
this._set_previousSelected(item);
|
||||
this._set_selectedIndex(this.indexOf(item));
|
||||
// Check for items, since this array is populated only when attached
|
||||
// Since Number(0) is falsy, explicitly check for undefined
|
||||
if (this.fallbackSelection && this.items.length && (this._selection.get() === undefined)) {
|
||||
this.selected = this.fallbackSelection;
|
||||
}
|
||||
},
|
||||
|
||||
_updateStepperClosedMaxHeight: function() {
|
||||
this.debounce('updateStepperClosedMaxHeight', function() {
|
||||
this.customStyle['--label-wrapper-height'] = this.$$('#content-wrapper').clientHeight + 'px';
|
||||
this.updateStyles('--label-wrapper-height');
|
||||
});
|
||||
},
|
||||
|
||||
_openedChanged: function(newValue, oldValue) {
|
||||
if (!this.vertical && oldValue != undefined) {
|
||||
this.toggleClass('collapsing', true);
|
||||
}
|
||||
},
|
||||
|
||||
_transitionEnd: function(e) {
|
||||
// check to ignore event fired by paper-ripple
|
||||
if (e.propertyName == 'max-height') {
|
||||
this.toggleClass('collapsing', false);
|
||||
}
|
||||
},
|
||||
|
||||
_computeOpened: function(_selectedIndex) {
|
||||
return _selectedIndex >= 0;
|
||||
},
|
||||
|
||||
_stepSaved: function(e) {
|
||||
var previousStep = this.items[this.indexOf(e.target)+1];
|
||||
if (previousStep) {
|
||||
previousStep._set_previousSaved(true);
|
||||
}
|
||||
this._setSavedStepNumber(this.savedStepNumber+1);
|
||||
},
|
||||
|
||||
_forwardVertical: function(vertical) {
|
||||
if (this.stepNumber) {
|
||||
this.items.map(function(step) {
|
||||
step._setVertical(vertical);
|
||||
});
|
||||
}
|
||||
this.setAttribute('role', vertical ? 'menu': 'menubar');
|
||||
},
|
||||
|
||||
_forwardStepperData: function(linear, backText, optionalText, finishText, continueText, skipText, updateText, hasSkipButton, hasBackButton) {
|
||||
if (this.stepNumber) {
|
||||
this.items.map(function(step) {
|
||||
step._set_stepperData({
|
||||
linear: linear,
|
||||
backText: backText,
|
||||
optionalText: optionalText,
|
||||
finishText: finishText,
|
||||
continueText: continueText,
|
||||
skipText: skipText,
|
||||
updateText: updateText,
|
||||
hasSkipButton: hasSkipButton,
|
||||
hasBackButton: hasBackButton,
|
||||
stepNumber: this.stepNumber
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
},
|
||||
|
||||
_forwardAlternativeLabel: function(alternativeLabel) {
|
||||
if (this.stepNumber) {
|
||||
this.items.map(function(step) {
|
||||
step._set_alternativeLabel(alternativeLabel);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_computeStepNumber: function(length) {
|
||||
return length;
|
||||
},
|
||||
|
||||
_selectedIndexChanged: function(newValue, oldValue) {
|
||||
if (!this.vertical && newValue >=0 && oldValue >= 0) {
|
||||
var oldStep = this.items[oldValue], newStep = this.items[newValue];
|
||||
if (newStep.classList.contains('neon-animating')) {
|
||||
this.cancelAnimation();
|
||||
}
|
||||
if (this._previousAnimatedStep && this._previousAnimatedStep.classList.contains('neon-animating')) {
|
||||
this.cancelAnimation();
|
||||
this.toggleClass('neon-animating', false, this._previousAnimatedStep);
|
||||
}
|
||||
var forward = newValue - oldValue > 0;
|
||||
|
||||
this.animationConfig = {
|
||||
'new-step-entry': {
|
||||
animatable: newStep,
|
||||
type: forward ?
|
||||
newStep.horizontalHigherEntryAnimation && 'higher-step-entry' :
|
||||
newStep.horizontalLowerEntryAnimation && 'lower-step-entry'
|
||||
},
|
||||
'old-step-exit': {
|
||||
animatable: oldStep,
|
||||
type: forward ?
|
||||
oldStep.horizontalLowerExitAnimation && 'lower-step-exit' :
|
||||
oldStep.horizontalHigherExitAnimation && 'higher-step-exit'
|
||||
}
|
||||
};
|
||||
if (this.animationConfig['new-step-entry'].type) {
|
||||
this.playAnimation('new-step-entry', {step: newStep});
|
||||
this.toggleClass('neon-animating', true, newStep);
|
||||
}
|
||||
if (this.animationConfig['old-step-exit'].type) {
|
||||
this.playAnimation('old-step-exit', {step: oldStep});
|
||||
this.toggleClass('neon-animating', true, oldStep);
|
||||
}
|
||||
|
||||
this._set_previousAnimatedStep(oldStep);
|
||||
}
|
||||
},
|
||||
|
||||
_onNeonAnimationFinish: function(event) {
|
||||
var step = event.detail.step;
|
||||
if (step) {
|
||||
this.toggleClass('neon-animating', false, step);
|
||||
}
|
||||
},
|
||||
|
||||
_forwardCanSkip: function(_canSkip, selectedItem) {
|
||||
selectedItem._set_canSkip(_canSkip);
|
||||
},
|
||||
|
||||
_forwardHasBackStep: function(_hasBackStep, selectedItem) {
|
||||
selectedItem._set_hasBackStep(_hasBackStep);
|
||||
},
|
||||
|
||||
_compute__attrForSelectedStepPrimaryButtonText: function(selectedIndex) {
|
||||
/* TODO: compute from selectedItem when https://github.com/PolymerElements/iron-selector/issues/118 is fixed*/
|
||||
if (selectedIndex < 0) {
|
||||
return null;
|
||||
}
|
||||
var _attrForPrimaryButtonText = this.selectedItem.saved ? 'updateText' :
|
||||
( (this.stepNumber - this.savedStepNumber) == 1 ? 'finishText' : 'continueText' );
|
||||
this.selectedItem._set_attrForPrimaryButtonText(_attrForPrimaryButtonText);
|
||||
return _attrForPrimaryButtonText;
|
||||
},
|
||||
|
||||
_initializeSteps: function() {
|
||||
var savedStepNumber = 0;
|
||||
var data = {
|
||||
linear: this.linear,
|
||||
backText: this.backText,
|
||||
optionalText: this.optionalText,
|
||||
finishText: this.finishText,
|
||||
continueText: this.continueText,
|
||||
skipText: this.skipText,
|
||||
updateText: this.updateText,
|
||||
hasSkipButton: this.hasSkipButton,
|
||||
hasBackButton: this.hasBackButton,
|
||||
stepNumber: this.stepNumber
|
||||
};
|
||||
this.items.map(function(step, i) {
|
||||
if (this.horizontalHigherEntryAnimation && !step.horizontalHigherEntryAnimation) {
|
||||
step.horizontalHigherEntryAnimation = this.horizontalHigherEntryAnimation;
|
||||
}
|
||||
if (this.horizontalHigherExitAnimation && !step.horizontalHigherExitAnimation) {
|
||||
step.horizontalHigherExitAnimation = this.horizontalHigherExitAnimation;
|
||||
}
|
||||
if (this.horizontalLowerEntryAnimation && !step.horizontalLowerEntryAnimation) {
|
||||
step.horizontalLowerEntryAnimation = this.horizontalLowerEntryAnimation;
|
||||
}
|
||||
if (this.horizontalLowerExitAnimation && !step.horizontalLowerExitAnimation) {
|
||||
step.horizontalLowerExitAnimation = this.horizontalLowerExitAnimation;
|
||||
}
|
||||
step._setIndex(i + 1);
|
||||
step._set_stepper(this);
|
||||
step._setVertical(this.vertical);
|
||||
step._set_alternativeLabel(this.alternativeLabel);
|
||||
step._set_stepperData(data);
|
||||
// true for index 0
|
||||
step._set_previousSaved(!i);
|
||||
if (step.saved) {
|
||||
savedStepNumber++;
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
this._setSavedStepNumber(savedStepNumber);
|
||||
// method from IronSelectableBehavior
|
||||
this._updateSelected();
|
||||
},
|
||||
|
||||
_compute_skipStepIndex: function(_selectedIndex) {
|
||||
if (_selectedIndex >= 0 && !this.completed) {
|
||||
for (var i=(_selectedIndex+1)%this.stepNumber; i!=_selectedIndex; i=(i+1)%this.stepNumber) {
|
||||
if (this.items[i].selectable && !this.items[i].saved) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_compute_backStepIndex: function(_selectedIndex) {
|
||||
if (_selectedIndex >= 0) {
|
||||
for (var i=_selectedIndex - 1; i >= 0; i--) {
|
||||
if (this.items[i].selectable) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
_isntNull: function(n) {
|
||||
return n != null;
|
||||
},
|
||||
|
||||
_computeCompleted: function(savedStepNumber, stepNumber) {
|
||||
var completed = stepNumber == savedStepNumber;
|
||||
if (completed) {
|
||||
this.fire('paper-stepper-completed');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
_choosePrimaryButtonText: function(_attrForSelectedStepPrimaryButtonText) {
|
||||
return this[_attrForSelectedStepPrimaryButtonText];
|
||||
},
|
||||
|
||||
_resizeHandler: function() {
|
||||
this.debounce('paper-stepper-responsive-check', function() {
|
||||
this._responsiveCheck();
|
||||
}, this.responsiveCheckFrequence);
|
||||
},
|
||||
|
||||
_responsiveCheck: function() {
|
||||
var verticalResponsiveWidth = this.$.verticalResponsiveWidth.clientWidth;
|
||||
if (verticalResponsiveWidth) {
|
||||
this.vertical = !(this.clientWidth > verticalResponsiveWidth);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</dom-module>
|
||||
@@ -0,0 +1,124 @@
|
||||
<link rel="import" href="../../components/iron-flex-layout/iron-flex-layout.html">
|
||||
<link rel="import" href="../../components/iron-icons/iron-icons.html">
|
||||
<link rel="import" href="../../components/iron-icons/editor-icons.html">
|
||||
<link rel="import" href="../../components/paper-styles/color.html">
|
||||
<link rel="import" href="../../components/paper-styles/typography.html">
|
||||
<link rel="import" href="../../components/paper-styles/default-theme.html">
|
||||
<link rel="import" href="../../components/polymer/polymer.html">
|
||||
<link rel="import" href="step-label-behavior.html">
|
||||
<link rel="import" href="step-label-shared-styles.html">
|
||||
|
||||
<dom-module id="step-horizontal-label">
|
||||
<template>
|
||||
<style include="step-label-shared-styles">
|
||||
:host{
|
||||
overflow: hidden;
|
||||
}
|
||||
:host([alternative-label]) {
|
||||
@apply(--layout);
|
||||
}
|
||||
#textWrapper {
|
||||
@apply(--layout-vertical);
|
||||
padding-right: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#textLabel, #optional {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
#badge {
|
||||
margin: 0 8px;
|
||||
}
|
||||
#badgeWrapper, #textWrapper {
|
||||
pointer-events: none;
|
||||
/* to be above paper-ripple*/
|
||||
z-index: 1;
|
||||
}
|
||||
:host(:not([alternative-label])) #label {
|
||||
@apply(--layout-horizontal);
|
||||
@apply(--layout-center);
|
||||
height: 72px;
|
||||
}
|
||||
:host(.firstStep:not([alternative-label])) #badge {
|
||||
margin-left: 24px;
|
||||
}
|
||||
:host(.lastStep:not([alternative-label])) #textWrapper {
|
||||
padding-right: 24px;
|
||||
}
|
||||
:host(:not([alternative-label]):not(.first-step)) #label::before,
|
||||
:host(:not([alternative-label]):not(.last-step)) #label::after,
|
||||
:host([alternative-label]) #badgeWrapper::before,
|
||||
:host([alternative-label]) #badgeWrapper::after {
|
||||
height: 1px;
|
||||
min-width: 16px;
|
||||
background: var(--paper-step-connector-line-color, --divider-color);
|
||||
@apply(--layout-flex);
|
||||
content: '';
|
||||
}
|
||||
:host([alternative-label].first-step) #badgeWrapper::before,
|
||||
:host([alternative-label].last-step) #badgeWrapper::after {
|
||||
visibility: hidden;
|
||||
}
|
||||
:host([alternative-label]) #textWrapper{
|
||||
padding: 0 16px;
|
||||
@apply(--layout-vertical);
|
||||
@apply(--layout-center);
|
||||
}
|
||||
:host([alternative-label]) #textLabel, :host([alternative-label]) #optional{
|
||||
text-align: center;
|
||||
@apply(--layout-self-stretch);
|
||||
}
|
||||
:host([alternative-label]) #label{
|
||||
@apply(--layout-vertical);
|
||||
@apply(--layout-self-stretch);
|
||||
padding: 24px 0;
|
||||
width: 100%;
|
||||
}
|
||||
:host([alternative-label]) #badgeWrapper {
|
||||
@apply(--layout-horizontal);
|
||||
@apply(--layout-center);
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
:host(.first-step:not([alternative-label])) #label {
|
||||
padding-left: 16px;
|
||||
}
|
||||
:host(.last-step:not([alternative-label])) #label {
|
||||
padding-right: 16px;
|
||||
}
|
||||
</style>
|
||||
<!-- use a "label" wrapper to use the same shared css rules with step-vertical -->
|
||||
<div id="label">
|
||||
<div id="badgeWrapper">
|
||||
<div id="badge">
|
||||
<iron-icon hidden$="{{!_computeIsIconBadge(icon)}}" icon="{{icon}}"></iron-icon>
|
||||
<span hidden$="{{_computeIsIconBadge(icon)}}">{{index}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="textWrapper">
|
||||
<span id="textLabel">[[label]]</span>
|
||||
<template is="dom-if" if="[[optional]]">
|
||||
<span id="optional">[[stepperData.optionalText]]</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
Polymer({
|
||||
is: 'step-horizontal-label',
|
||||
|
||||
behaviors: [
|
||||
Stepper.StepLabelBehavior
|
||||
],
|
||||
|
||||
properties: {
|
||||
alternativeLabel: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
reflectToAttribute: true
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
@@ -0,0 +1,58 @@
|
||||
<link rel="import" href="../../components/polymer/polymer.html">
|
||||
|
||||
<script>
|
||||
|
||||
window.Stepper = window.Stepper || {};
|
||||
|
||||
/*
|
||||
* @polymerBehavior Stepper.StepLabelBehavior
|
||||
*/
|
||||
Stepper.StepLabelBehavior = {
|
||||
|
||||
properties: {
|
||||
icon: {
|
||||
type: String,
|
||||
computed: '_computeIcon(saved, editable)'
|
||||
},
|
||||
opened: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true
|
||||
},
|
||||
selectable: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
notify: true
|
||||
},
|
||||
optional: {
|
||||
type: Boolean,
|
||||
notify: true
|
||||
},
|
||||
saved: {
|
||||
type: Boolean,
|
||||
reflectToAttribute: true
|
||||
},
|
||||
index: {
|
||||
type: Number
|
||||
},
|
||||
stepperData: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
|
||||
_computeIcon: function(saved, editable) {
|
||||
return saved ? ( editable ? 'editor:mode-edit' : 'done' ) : '';
|
||||
},
|
||||
|
||||
_computeIsIconBadge: function(icon) {
|
||||
return icon.length > 0;
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,74 @@
|
||||
<link rel="import" href="../../components/iron-flex-layout/iron-flex-layout.html">
|
||||
<link rel="import" href="../../components/paper-styles/default-theme.html">
|
||||
<link rel="import" href="../../components/paper-styles/color.html">
|
||||
<link rel="import" href="../../components/paper-styles/typography.html">
|
||||
<link rel="import" href="../../components/polymer/polymer.html">
|
||||
|
||||
<dom-module id="step-label-shared-styles">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
@apply(--paper-font-common-base);
|
||||
@apply(--layout-flex);
|
||||
}
|
||||
#textWrapper {
|
||||
color: var(--paper-step-disabled-label-text-color, --paper-grey-400);
|
||||
}
|
||||
#textLabel {
|
||||
font-size: var(--paper-step-label-text-font-size, 14px);
|
||||
}
|
||||
#optional{
|
||||
font-size: var(--paper-step-label-optional-text-font-size, 12px);
|
||||
}
|
||||
:host([selectable]) #textWrapper {
|
||||
color: var(--paper-step-selectable-label-text-color, --paper-grey-600);
|
||||
}
|
||||
:host([opened]) #textLabel {
|
||||
color: var(--paper-step-opened-label-text-color, --light-theme-text-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
#label {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
/* For paper-ripple */
|
||||
position: relative;
|
||||
}
|
||||
:host([selectable]) #label {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
#label:hover {
|
||||
/* using alpha chanel for .connectorLine to grow dark */
|
||||
background: var(--paper-step-label-hover-background, rgba(0,0,0,0.04));
|
||||
}
|
||||
#badge {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: var(--paper-step-badge-background, --paper-grey-300);
|
||||
border-radius: 50%;
|
||||
color: var(--paper-step-badge-color, --dark-theme-text-color);
|
||||
font-size: 12px;
|
||||
@apply(--layout);
|
||||
@apply(--layout-center-center);
|
||||
}
|
||||
#badge iron-icon {
|
||||
--iron-icon-height: var(--paper-step-badge-icon-width, 16px);
|
||||
--iron-icon-width: var(--paper-step-badge-icon-height, 16px);
|
||||
}
|
||||
:host([opened]) #badge {
|
||||
background: var(--paper-step-opened-badge-background, --primary-color);
|
||||
}
|
||||
:host([saved]) #badge {
|
||||
background: var(--paper-step-saved-badge-background, --primary-color);
|
||||
}
|
||||
:host([selectable]:not([opened]):not([saved])) #label:hover #badge {
|
||||
background: var(--paper-step-selectable-hovered-badge-background, --paper-grey-500);
|
||||
}
|
||||
paper-ripple {
|
||||
color: var(--paper-step-ink-color, --paper-grey-400);
|
||||
}
|
||||
</style>
|
||||
</template>
|
||||
</dom-module>
|
||||
@@ -0,0 +1,177 @@
|
||||
<link rel="import" href="../../components/iron-flex-layout/iron-flex-layout.html">
|
||||
<link rel="import" href="../../components/paper-button/paper-button.html">
|
||||
<link rel="import" href="../../components/paper-styles/color.html">
|
||||
<link rel="import" href="../../components/paper-styles/default-theme.html">
|
||||
<link rel="import" href="../../components/paper-styles/typography.html">
|
||||
<link rel="import" href="../../components/polymer/polymer.html">
|
||||
<link rel="import" href="../../components/iron-icons/iron-icons.html">
|
||||
<link rel="import" href="../../components/iron-icon/iron-icon.html">
|
||||
<link rel="import" href="../../components/iron-icons/editor-icons.html">
|
||||
<link rel="import" href="../../components/iron-collapse/iron-collapse.html">
|
||||
<link rel="import" href="step-label-behavior.html">
|
||||
<link rel="import" href="step-label-shared-styles.html">
|
||||
|
||||
<dom-module id="step-vertical">
|
||||
<template>
|
||||
<style include="step-label-shared-styles">
|
||||
:host {
|
||||
@apply(--layout-vertical);
|
||||
}
|
||||
#connectedBadge, #textWrapper {
|
||||
pointer-events: none;
|
||||
/* to be above paper-ripple*/
|
||||
z-index: 1;
|
||||
}
|
||||
#collapse {
|
||||
--iron-collapse-transition-duration: var(--paper-vertical-step-transition-duration, 500ms);
|
||||
@apply(--layout-horizontal);
|
||||
}
|
||||
/**
|
||||
* Content
|
||||
*/
|
||||
#connectedStep {
|
||||
@apply(--layout-horizontal);
|
||||
}
|
||||
#contentConnectorLine {
|
||||
width: 1px;
|
||||
background: var(--divider-color, --paper-grey-300);
|
||||
margin-left: 36px;
|
||||
margin-right: 24px;
|
||||
}
|
||||
#stepWrapper {
|
||||
@apply(--layout-flex);
|
||||
/*should be 48px on large screen?*/
|
||||
padding-right: 24px;
|
||||
}
|
||||
#paperStepWrapper {
|
||||
max-height: calc(var(--paper-vertical-step-max-height, 400px) - 92px);
|
||||
@apply(--layout-scroll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Buttons
|
||||
*/
|
||||
#buttonsWrapper {
|
||||
height: 48px;
|
||||
@apply(--layout-horizontal);
|
||||
@apply(--layout-center);
|
||||
@apply(--layout-flex-none);
|
||||
}
|
||||
#buttonsWrapper > paper-button {
|
||||
margin-right: 8px;
|
||||
margin-left: 0;
|
||||
}
|
||||
#continueButton {
|
||||
--paper-button: {
|
||||
background: var(--paper-vertical-step-continue-button-background, --primary-color);
|
||||
color: var(--paper-vertical-step-continue-button-color, --dark-theme-text-color);
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Label
|
||||
*/
|
||||
#textWrapper {
|
||||
@apply(--layout-vertical);
|
||||
padding: 8px 0 8px 8px;
|
||||
}
|
||||
#label {
|
||||
@apply(--layout-horizontal);
|
||||
}
|
||||
#connectedBadge {
|
||||
@apply(--layout-vertical);
|
||||
@apply(--layout-center);
|
||||
margin-left: 24px;
|
||||
}
|
||||
#beforeConnectorLine, #afterConnectorLine {
|
||||
width: 1px;
|
||||
background: var(--paper-step-connector-line-color, --divider-color);
|
||||
}
|
||||
#beforeConnectorLine {
|
||||
height: 10px;
|
||||
}
|
||||
#afterConnectorLine {
|
||||
@apply(--layout-flex);
|
||||
}
|
||||
#badge {
|
||||
margin: 8px 0;
|
||||
}
|
||||
:host(.first-step) #beforeConnectorLine, :host(.lastStep) #contentConnectorLine{
|
||||
visibility: hidden;
|
||||
}
|
||||
:host(.last-step:not([opened])) #afterConnectorLine {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="label">
|
||||
<div id="connectedBadge">
|
||||
<div id="beforeConnectorLine"></div>
|
||||
<div id="badge">
|
||||
<iron-icon hidden$="{{!_computeIsIconBadge(icon)}}" icon="{{icon}}"></iron-icon>
|
||||
<span hidden$="{{_computeIsIconBadge(icon)}}">{{index}}</span>
|
||||
</div>
|
||||
<div id="afterConnectorLine" class="connectorLine"></div>
|
||||
</div>
|
||||
<div id="textWrapper">
|
||||
<span id="textLabel">[[label]]</span>
|
||||
<template is="dom-if" if="[[optional]]">
|
||||
<span id="optional">[[stepperData.optionalText]]</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<iron-collapse id="collapse" opened="[[opened]]">
|
||||
<div id="contentConnectorLine"></div>
|
||||
<div id="stepWrapper">
|
||||
<div id="paperStepWrapper">
|
||||
<content></content>
|
||||
</div>
|
||||
<div id="buttonsWrapper">
|
||||
<paper-button id="continueButton" on-tap="continue">{{choosePrimaryButtonText(_attrForPrimaryButtonText, stepperData.continueText, stepperData.finishText, stepperData.updateText)}}</paper-button>
|
||||
<paper-button id="backButton" disabled="[[!hasBackStep]]" on-tap="back" hidden$="[[!stepperData.hasBackButton]]">
|
||||
[[stepperData.backText]]
|
||||
</paper-button>
|
||||
<paper-button id="skipButton" disabled="[[!canSkip]]" on-tap="skip" hidden$="[[!stepperData.hasSkipButton]]">
|
||||
[[stepperData.skipText]]
|
||||
</paper-button>
|
||||
</div>
|
||||
</div>
|
||||
</iron-collapse>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
Polymer({
|
||||
is: 'step-vertical',
|
||||
|
||||
properties: {
|
||||
canSkip: {
|
||||
type: Boolean
|
||||
},
|
||||
_attrForPrimaryButtonText: {
|
||||
type: String,
|
||||
value: false
|
||||
},
|
||||
hasBackStep: Boolean
|
||||
},
|
||||
|
||||
behaviors: [
|
||||
Stepper.StepLabelBehavior
|
||||
],
|
||||
|
||||
skip: function() {
|
||||
this.fire('paper-step-vertical-skip-tapped');
|
||||
},
|
||||
|
||||
back: function() {
|
||||
this.fire('paper-step-vertical-back-tapped');
|
||||
},
|
||||
|
||||
continue: function() {
|
||||
this.fire('paper-step-vertical-continue-tapped');
|
||||
},
|
||||
|
||||
choosePrimaryButtonText: function(_attrForPrimaryButtonText) {
|
||||
return this.stepperData[_attrForPrimaryButtonText];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</dom-module>
|
||||
Reference in New Issue
Block a user