Merge branch 'feature-onboarding'
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);
|
||||
@@ -298,6 +299,7 @@ Characters.calculate = {
|
||||
var fieldSelector = {};
|
||||
fieldSelector[fieldName] = 1;
|
||||
var char = Characters.findOne(charId, {fields: fieldSelector});
|
||||
if (!char) return;
|
||||
var field = char[fieldName];
|
||||
if (field === undefined){
|
||||
throw new Meteor.Error(
|
||||
@@ -331,6 +333,7 @@ Characters.calculate = {
|
||||
},
|
||||
attributeValue: memoize(function(charId, attributeName){
|
||||
var attribute = Characters.calculate.getField(charId, attributeName);
|
||||
if (!attribute) return;
|
||||
//base value
|
||||
var value = Characters.calculate.attributeBase(charId, attributeName);
|
||||
//plus adjustment
|
||||
@@ -342,6 +345,7 @@ Characters.calculate = {
|
||||
}),
|
||||
skillMod: memoize(preventLoop(function(charId, skillName){
|
||||
var skill = Characters.calculate.getField(charId, skillName);
|
||||
if (!skill) return;
|
||||
//get the final value of the ability score
|
||||
var ability = Characters.calculate.attributeValue(charId, skill.ability);
|
||||
|
||||
@@ -393,7 +397,6 @@ Characters.calculate = {
|
||||
return prof && prof.value || 0;
|
||||
}),
|
||||
passiveSkill: memoize(function(charId, skillName){
|
||||
var skill = Characters.calculate.getField(charId, skillName);
|
||||
var mod = +Characters.calculate.skillMod(charId, skillName);
|
||||
var value = 10 + mod;
|
||||
Effects.find(
|
||||
@@ -554,6 +557,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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,8 @@ Template.registerHelper("canEditCharacter", function(charId) {
|
||||
});
|
||||
|
||||
canEditCharacter = function(charId) {
|
||||
var char = Characters.findOne(charId)
|
||||
var char = Characters.findOne(charId);
|
||||
if (!char) return false;
|
||||
var userId = Meteor.userId();
|
||||
return char.owner === userId ||
|
||||
_.contains(char.writers, userId);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -10,7 +10,7 @@ Template.deleteCharacterConfirmation.helpers({
|
||||
if (Template.instance().canDelete.get()) {
|
||||
return "background: #d23f31; color: white;";
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.deleteCharacterConfirmation.events({
|
||||
@@ -20,9 +20,7 @@ Template.deleteCharacterConfirmation.events({
|
||||
},
|
||||
"click #deleteButton": function(event, instance) {
|
||||
if (instance.find("#nameInput").value === this.name) {
|
||||
popDialogStack();
|
||||
Router.go("/characterList");
|
||||
Characters.remove(this._id);
|
||||
popDialogStack(true);
|
||||
}
|
||||
},
|
||||
"click .cancelButton": function(event, instance){
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template name="characterSheet">
|
||||
<div class="fit layout vertical character-sheet">
|
||||
<app-header fixed effects="waterfall">
|
||||
<app-toolbar class="medium-tall {{colorClass}}">
|
||||
<app-toolbar class="medium-tall {{colorClass}}" style="z-index: 2;">
|
||||
<div top-item class="layout horizontal center">
|
||||
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
|
||||
<div class="flex character-name">
|
||||
@@ -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 newUserExperience}}{{> newUserStepper}}{{/if}}
|
||||
</app-header>
|
||||
<div class="flex" style="position: relative;">
|
||||
<iron-pages id="tabPages" class="fit" selected={{selectedTab}}>
|
||||
|
||||
@@ -29,7 +29,7 @@ Template.characterSheet.onRendered(function() {
|
||||
tabFabMenus = _.times(6, (n) =>
|
||||
tabPages[n].find(".mini-holder")
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
//watch this character and make sure their encumbrance is updated
|
||||
//trackEncumbranceConditions(this.data._id, this);
|
||||
@@ -172,6 +172,18 @@ 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){
|
||||
const selected = Session.get(this._id + ".selectedTab")
|
||||
const step = Session.get("newUserExperienceStep");
|
||||
if (selected == tab) return false;
|
||||
return (tab === 1 && step === 0) ||
|
||||
(tab === 5 && step === 1) ||
|
||||
(tab === 0 && step === 2);
|
||||
},
|
||||
});
|
||||
|
||||
Template.characterSheet.events({
|
||||
@@ -187,6 +199,12 @@ Template.characterSheet.events({
|
||||
data: this,
|
||||
template: "deleteCharacterConfirmation",
|
||||
element: event.currentTarget.parentElement.parentElement,
|
||||
callback: (result) => {
|
||||
if (result === true){
|
||||
Router.go("/characterList");
|
||||
Tracker.afterFlush(() => Characters.remove(this._id));
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
"click #shareCharacter": function(event, instance){
|
||||
|
||||
@@ -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,10 @@ Template.featureDetails.events({
|
||||
});
|
||||
|
||||
Template.featureEdit.helpers({
|
||||
showNewUserExperience: function(){
|
||||
return Session.get("newUserExperienceStep") === 0 ||
|
||||
Session.get("newUserExperienceStep") === 1;
|
||||
},
|
||||
usesSet: function(){
|
||||
return _.isString(this.uses);
|
||||
},
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
checked={{enabled}}
|
||||
disabled={{#unless canEditCharacter charId}}true{{/unless}}>
|
||||
</paper-checkbox>
|
||||
<paper-tooltip position="left">Feature enabled</paper-tooltip>
|
||||
{{#simpleTooltip}}Feature enabled{{/simpleTooltip}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
@@ -101,11 +101,13 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
{{#if canEditCharacter _id}}
|
||||
<paper-fab id="addFeature"
|
||||
class="floatyButton"
|
||||
icon="add">
|
||||
<paper-tooltip position="left">Add Feature</paper-tooltip>
|
||||
</paper-fab>
|
||||
<div class="floatyButton">
|
||||
<paper-fab id="addFeature"
|
||||
class="{{#if shouldFloatyButtonBounce}}bounce{{/if}}"
|
||||
icon="add">
|
||||
</paper-fab>
|
||||
{{#simpleTooltip}}Add Feature{{/simpleTooltip}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -110,12 +110,12 @@
|
||||
<div class="paper-font-caption" style="margin-right: 8px">
|
||||
{{round totalWeight}} lbs
|
||||
</div>
|
||||
<div>
|
||||
<div style="position: relative;">
|
||||
<paper-checkbox class="carriedCheckbox"
|
||||
disabled={{#unless canEditCharacter charId}}true{{/unless}}
|
||||
checked={{isCarried}}>
|
||||
</paper-checkbox>
|
||||
<paper-tooltip position="left"> Container carried</paper-tooltip>
|
||||
{{#simpleTooltip}} Container carried{{/simpleTooltip}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom list">
|
||||
@@ -136,21 +136,21 @@
|
||||
class="addContainer"
|
||||
mini>
|
||||
</paper-fab>
|
||||
<paper-tooltip position="left"> New container </paper-tooltip>
|
||||
{{#simpleTooltip class="always"}} Container {{/simpleTooltip}}
|
||||
</div>
|
||||
<div>
|
||||
<paper-fab icon="av:library-books"
|
||||
class="libraryItem"
|
||||
mini>
|
||||
</paper-fab>
|
||||
<paper-tooltip position="left"> Library item </paper-tooltip>
|
||||
{{#simpleTooltip class="always"}} Item from library {{/simpleTooltip}}
|
||||
</div>
|
||||
<div>
|
||||
<paper-fab icon="note-add"
|
||||
class="addItem"
|
||||
mini>
|
||||
</paper-fab>
|
||||
<paper-tooltip position="left"> New item </paper-tooltip>
|
||||
{{#simpleTooltip class="always"}} Item {{/simpleTooltip}}
|
||||
</div>
|
||||
{{/fabMenu}}
|
||||
{{/if}}
|
||||
|
||||
@@ -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>
|
||||
@@ -83,9 +83,12 @@
|
||||
</div>
|
||||
<div class="fab-buffer"></div>
|
||||
{{#if canEditCharacter _id}}
|
||||
<paper-fab id="addNote"
|
||||
class="floatyButton"
|
||||
icon="add"
|
||||
title="Add"></paper-fab>
|
||||
<div class="floatyButton">
|
||||
<paper-fab id="addNote"
|
||||
icon="add"
|
||||
title="Add">
|
||||
</paper-fab>
|
||||
{{#simpleTooltip}}Add Note{{/simpleTooltip}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -1,11 +1,34 @@
|
||||
<template name="raceDialog">
|
||||
{{#baseDialog title="Race" class=color hideColor="true" hideDelete="true" startEditing=startEditing}}
|
||||
{{#if showNewUserExperience}}
|
||||
{{#infoBox}}
|
||||
{{#if stepComplete}}
|
||||
<p>You can add all the effects you need to represent how your race affects your character's attributes.</p>
|
||||
{{else}}
|
||||
<p>Click the edit button to edit your race and add a racial effect</p>
|
||||
{{/if}}
|
||||
{{/infoBox}}
|
||||
{{/if}}
|
||||
<div class="horizontal layout center-justified paper-font-display2">
|
||||
{{race}}
|
||||
</div>
|
||||
{{> effectsViewList charId=charId parentId=charId parentGroup="racial"}}
|
||||
{{> proficiencyViewList charId=charId parentId=charId parentGroup="racial"}}
|
||||
{{else}}
|
||||
{{#if showNewUserExperience}}
|
||||
{{#infoBox}}
|
||||
{{#if stepComplete}}
|
||||
<p>You can add all the effects you need to represent how your race affects your character's attributes.</p>
|
||||
{{else}}
|
||||
<p>
|
||||
Add an effect with the following options: <br>
|
||||
Attribute: <b>stats > speed</b> <br>
|
||||
Operation: <b>Base Value</b> <br>
|
||||
Value: <b>30</b> (might be different for some races)
|
||||
</p>
|
||||
{{/if}}
|
||||
{{/infoBox}}
|
||||
{{/if}}
|
||||
<paper-input id="raceInput" label="Race" value={{race}}></paper-input>
|
||||
{{> effectsEditList parentId=charId parentCollection="Characters" charId=charId parentGroup="racial"}}
|
||||
{{> proficiencyEditList parentId=charId parentCollection="Characters" charId=charId parentGroup="racial"}}
|
||||
|
||||
@@ -19,4 +19,10 @@ Template.raceDialog.helpers({
|
||||
var char = Characters.findOne(this.charId, {fields: {color: 1}});
|
||||
if (char) return getColorClass(char.color);
|
||||
},
|
||||
stepComplete: function(){
|
||||
return Session.get("newUserExperienceStep") > 1;
|
||||
},
|
||||
showNewUserExperience: function(){
|
||||
return Session.get("newUserExperienceStep") >= 1;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
.newUserStepper {
|
||||
height: 180px !important;
|
||||
}
|
||||
|
||||
.newUserStepper paper-step .invalid-step-message {
|
||||
color: #d13b2e;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.newUserStepper paper-step[invalid] .invalid-step-message {
|
||||
visibility: visible;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<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">
|
||||
Done! If you get stuck, be sure to check out the <a href="/guide">guide</a>, or ask for help using the feedback form
|
||||
<div class="layout vertical end">
|
||||
<paper-button class="done-button" style="color: #d13b2e">Finish</paper-button>
|
||||
</div>
|
||||
</paper-step>
|
||||
</paper-stepper>
|
||||
</template>
|
||||
|
||||
<template name="newUserStepperPlaceholder">
|
||||
<div style="height: 300px"></div>
|
||||
</template>
|
||||
@@ -0,0 +1,58 @@
|
||||
Template.newUserStepper.onRendered(function(){
|
||||
Session.set("newUserExperienceStep", 0);
|
||||
let stepper = this.find("paper-stepper");
|
||||
_.defer(() => {
|
||||
this.autorun((c) => {
|
||||
var step = Session.get("newUserExperienceStep");
|
||||
var hasFeatures = Features.find({charId: this.data._id}).count() > 1;
|
||||
if (step === 0 && hasFeatures){
|
||||
stepper.continue();
|
||||
}
|
||||
});
|
||||
this.autorun((c) => {
|
||||
var step = Session.get("newUserExperienceStep");
|
||||
var hasEffect = !!Effects.find({
|
||||
charId: this.data._id,
|
||||
stat: "speed",
|
||||
"parent.group": "racial",
|
||||
operation: "base",
|
||||
value: {$gt: 0},
|
||||
}).count();
|
||||
if (step === 1 && hasEffect){
|
||||
stepper.continue();
|
||||
}
|
||||
});
|
||||
this.autorun((c) => {
|
||||
var step = Session.get("newUserExperienceStep");
|
||||
if (step === 2 && Session.get("viewedSpeed")){
|
||||
Session.set("viewedSpeed", undefined);
|
||||
stepper.continue();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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}});
|
||||
},
|
||||
"click .done-button": function(event, instance){
|
||||
const stepper = instance.find("paper-stepper");
|
||||
stepper.continue();
|
||||
},
|
||||
});
|
||||
|
||||
Template.stats.events({
|
||||
"click .stat-card": function(event, instance){
|
||||
var step = Session.get("newUserExperienceStep");
|
||||
if (this.stat === "speed" && step === 2){
|
||||
Session.set("viewedSpeed", true);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -53,22 +53,22 @@
|
||||
{{numPrepared}} / {{evaluate charId maxPrepared}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div>
|
||||
<paper-tooltip position="left">
|
||||
Done
|
||||
</paper-tooltip>
|
||||
<div style="position: relative;">
|
||||
<paper-icon-button class="finishPrep" icon="done">
|
||||
</paper-icon-button>
|
||||
{{#simpleTooltip}}
|
||||
Done
|
||||
{{/simpleTooltip}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div>
|
||||
<paper-tooltip position="left">
|
||||
Change prepared spells
|
||||
</paper-tooltip>
|
||||
<div style="position: relative;">
|
||||
<paper-icon-button class="prepSpells"
|
||||
disabled={{#unless canEditCharacter charId}}true{{/unless}}
|
||||
icon="book">
|
||||
</paper-icon-button>
|
||||
{{#simpleTooltip}}
|
||||
Change prepared spells
|
||||
{{/simpleTooltip}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
@@ -124,32 +124,31 @@
|
||||
{{#if canEditCharacter _id}}
|
||||
{{#fabMenu}}
|
||||
<div>
|
||||
<paper-tooltip position="left">
|
||||
New spell list
|
||||
</paper-tooltip>
|
||||
<paper-fab icon="work"
|
||||
class="addSpellList"
|
||||
mini>
|
||||
</paper-fab>
|
||||
|
||||
{{#simpleTooltip class="always"}}
|
||||
Spell list
|
||||
{{/simpleTooltip}}
|
||||
</div>
|
||||
<div>
|
||||
<paper-tooltip position="left">
|
||||
Spell library
|
||||
</paper-tooltip>
|
||||
<paper-fab icon="av:library-books"
|
||||
class="librarySpell"
|
||||
mini>
|
||||
</paper-fab>
|
||||
{{#simpleTooltip class="always"}}
|
||||
Spell from library
|
||||
{{/simpleTooltip}}
|
||||
</div>
|
||||
<div>
|
||||
<paper-tooltip position="left">
|
||||
New spell
|
||||
</paper-tooltip>
|
||||
<paper-fab icon="note-add"
|
||||
class="addSpell"
|
||||
mini>
|
||||
</paper-fab>
|
||||
{{#simpleTooltip class="always"}}
|
||||
Spell
|
||||
{{/simpleTooltip}}
|
||||
</div>
|
||||
{{/fabMenu}}
|
||||
{{/if}}
|
||||
|
||||
@@ -6,6 +6,16 @@
|
||||
</template>
|
||||
|
||||
<template name="attributeDialogView">
|
||||
{{#if showNewUserExperience}}
|
||||
{{#infoBox}}
|
||||
<p>
|
||||
This dialog shows how your speed is set by the effect you added to your character's race.
|
||||
</p>
|
||||
<p>
|
||||
In DiceCloud you don't change stats directly, rather you add effects which impact your stats in different ways. This way, you can always tell where your stats came from, and how they got to their current value.
|
||||
</p>
|
||||
{{/infoBox}}
|
||||
{{/if}}
|
||||
<div class="layout horizontal center-justified end">
|
||||
<div class="paper-font-display2">
|
||||
{{attributeValue}}
|
||||
|
||||
@@ -157,4 +157,9 @@ Template.attributeDialogView.helpers({
|
||||
statValue: function(){
|
||||
return evaluateEffect(this.charId, this);
|
||||
},
|
||||
showNewUserExperience: function(){
|
||||
if (this.statName === "speed"){
|
||||
return Session.get("newUserExperienceStep") >= 2;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template name="statCard">
|
||||
<div>
|
||||
<paper-material class="stat-card layout horizontal">
|
||||
<paper-material class="stat-card layout horizontal {{#if bounce}}bounce{{/if}}">
|
||||
<div class="numbers paper-font-display1">
|
||||
{{#if isSkill}}
|
||||
{{prefix}}{{skillMod}}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!--Armor-->
|
||||
{{> statCard stat="armor" name="Armor Class" color="teal"}}
|
||||
<!--Speed-->
|
||||
{{> statCard stat="speed" name="Speed" color="teal"}}
|
||||
{{> statCard stat="speed" name="Speed" color="teal" bounce=shouldSpeedBounce}}
|
||||
<!--Initiative-->
|
||||
{{> statCard stat="initiative" name="Initiative" color="indigo" isSkill="true"}}
|
||||
<!--Proficiency Bonus-->
|
||||
|
||||
@@ -8,6 +8,10 @@ Template.stats.helpers({
|
||||
};
|
||||
return Buffs.find(selector);
|
||||
},
|
||||
// New user experience
|
||||
shouldSpeedBounce: function(){
|
||||
return Session.get("newUserExperienceStep") === 2;
|
||||
},
|
||||
})
|
||||
|
||||
Template.stats.events({
|
||||
@@ -84,8 +88,7 @@ Template.stats.events({
|
||||
callback: (result) => {
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
else Meteor.call("giveCondition", this._id, result)
|
||||
} else Meteor.call("giveCondition", this._id, result)
|
||||
},
|
||||
//returnElement: () => $(`[data-id='${itemId}']`).get(0),
|
||||
})
|
||||
|
||||
@@ -49,14 +49,14 @@
|
||||
class="addParty"
|
||||
mini>
|
||||
</paper-fab>
|
||||
<paper-tooltip position="left"> New Party </paper-tooltip>
|
||||
{{#simpleTooltip class="always"}} New Party {{/simpleTooltip}}
|
||||
</div>
|
||||
<div>
|
||||
<paper-fab icon="face"
|
||||
class="addCharacter"
|
||||
mini>
|
||||
</paper-fab>
|
||||
<paper-tooltip position="left"> New Character </paper-tooltip>
|
||||
{{#simpleTooltip class="always"}} New Character {{/simpleTooltip}}
|
||||
</div>
|
||||
{{/fabMenu}}
|
||||
</div>
|
||||
|
||||
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>
|
||||
@@ -25,7 +25,6 @@
|
||||
{{/ simpleTooltip}}
|
||||
</div>
|
||||
<div class="brackets" style="position: relative">
|
||||
<!--<paper-tooltip position="left" animation-delay="0">This field accepts formulae in {curly brackets}</paper-tooltip>-->
|
||||
<iron-icon icon="dicecloud:code-braces"></iron-icon>
|
||||
{{# simpleTooltip}}
|
||||
This field accepts formulae in {curly brackets}
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
.simple-tooltip:hover .tooltip {
|
||||
.simple-tooltip {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.simple-tooltip:active {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Show the tooltip if a older sibling is hovered */
|
||||
*:hover ~ .simple-tooltip > .tooltip {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
/* Show the tooltip if parent is hovered */
|
||||
*:hover > .simple-tooltip > .tooltip {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
@@ -16,3 +30,7 @@
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tooltip.always {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template name="simpleTooltip">
|
||||
<div class="simple-tooltip fit">
|
||||
<div class="tooltip">
|
||||
<div class="simple-tooltip fit layout vertical center-justified">
|
||||
<div class="tooltip {{class}}">
|
||||
{{> Template.contentBlock}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
{{#if verified}}
|
||||
<span>
|
||||
<iron-icon icon="check"></iron-icon>
|
||||
<paper-tooltip>Verified</paper-tooltip>
|
||||
{{#simpleTooltip}}Verified{{/simpleTooltip}}
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@@ -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: 0;
|
||||
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