fix(buttons): custom cssClass

This commit is contained in:
Manu Mtz.-Almeida
2018-02-03 19:16:37 +01:00
parent ba9327979a
commit 6d52b722e4
12 changed files with 157 additions and 271 deletions

View File

@ -10,7 +10,7 @@ import {
} from '../../index';
import { domControllerAsync, isDef, playAnimationAsync } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme';
import { createThemedClasses, getClassMap } from '../../utils/theme';
import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave';
@ -208,22 +208,6 @@ export class ActionSheet {
}
}
buttonClass(button: ActionSheetButton): CssClassMap {
const buttonClass: string[] = !button.role
? ['action-sheet-button']
: [`action-sheet-button`, `action-sheet-${button.role}`];
if (button.cssClass) {
const customClass = button.cssClass.split(' ').filter(b => b.trim() !== '').join(' ');
buttonClass.push(customClass);
}
return buttonClass.reduce((prevValue: any, cssClass: any) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
}
protected buttonClick(button: ActionSheetButton) {
let shouldDismiss = true;
if (button.handler) {
@ -239,22 +223,15 @@ export class ActionSheet {
hostData() {
const themedClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'action-sheet-translucent') : {};
const hostClasses = {
...themedClasses
};
return {
class: hostClasses
class: {
...themedClasses,
...getClassMap(this.cssClass)
}
};
}
render() {
if (this.cssClass) {
this.cssClass.split(' ').forEach(cssClass => {
if (cssClass.trim() !== '') this.el.classList.add(cssClass);
});
}
let cancelButton: ActionSheetButton;
const buttons = this.buttons
.map(b => {
@ -289,7 +266,7 @@ export class ActionSheet {
</div>
: null}
{buttons.map(b =>
<button class={this.buttonClass(b)} onClick={() => this.buttonClick(b)}>
<button class={buttonClass(b)} onClick={() => this.buttonClick(b)}>
<span class='button-inner'>
{b.icon
? <ion-icon name={b.icon} class='action-sheet-icon' />
@ -302,7 +279,7 @@ export class ActionSheet {
{cancelButton
? <div class='action-sheet-group action-sheet-group-cancel'>
<button
class={this.buttonClass(cancelButton)}
class={buttonClass(cancelButton)}
onClick={() => this.buttonClick(cancelButton)}
>
<span class='button-inner'>
@ -324,6 +301,17 @@ export class ActionSheet {
}
}
function buttonClass(button: ActionSheetButton): CssClassMap {
const buttonClasses: any = {
'action-sheet-button': true,
...getClassMap(button.cssClass),
};
if (button.role) {
buttonClasses[`action-sheet-${button.role}`] = true;
}
return buttonClasses;
}
export interface ActionSheetOptions {
title?: string;
subTitle?: string;

View File

@ -3,7 +3,7 @@ import { Animation, AnimationBuilder, AnimationController, Config, DomController
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
import { BACKDROP } from '../../utils/overlay-constants';
import { createThemedClasses } from '../../utils/theme';
import { createThemedClasses, getClassMap } from '../../utils/theme';
import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave';
@ -285,19 +285,6 @@ export class Alert {
return values;
}
buttonClass(button: AlertButton): CssClassMap {
const buttonClass: string[] = ['alert-button'];
if (button.cssClass) {
const customClass = button.cssClass.split(' ').filter(b => b.trim() !== '').join(' ');
buttonClass.push(customClass);
}
return buttonClass.reduce((prevValue: any, cssClass: any) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
}
renderCheckbox(inputs: AlertInput[]) {
if (inputs.length === 0) return null;
@ -363,12 +350,11 @@ export class Alert {
hostData() {
const themedClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'alert-translucent') : {};
const hostClasses = {
...themedClasses
};
return {
class: hostClasses,
class: {
...themedClasses,
...getClassMap(this.cssClass)
},
id: this.alertId
};
}
@ -378,13 +364,6 @@ export class Alert {
const subHdrId = `${this.alertId}-sub-hdr`;
const msgId = `${this.alertId}-msg`;
if (this.cssClass) {
this.cssClass.split(' ').forEach(cssClass => {
if (cssClass.trim() !== '') this.el.classList.add(cssClass);
});
}
if (this.title || !this.subTitle) {
this.hdrId = hdrId;
@ -472,7 +451,7 @@ export class Alert {
<div class={alertButtonGroupClass}>
{buttons.map(b =>
<button class={this.buttonClass(b)} tabIndex={0} onClick={() => this.buttonClick(b)}>
<button class={buttonClass(b)} tabIndex={0} onClick={() => this.buttonClick(b)}>
<span class='button-inner'>
{b.text}
</span>
@ -482,7 +461,13 @@ export class Alert {
</div>
];
}
}
function buttonClass(button: AlertButton): CssClassMap {
return {
'alert-button': true,
...getClassMap(button.cssClass)
};
}
export interface AlertOptions {

View File

@ -1,6 +1,6 @@
import { Component, CssClassMap, Element, Event, EventEmitter, Prop, State } from '@stencil/core';
import { BlurEvent, FocusEvent } from '../../utils/input-interfaces';
import { Component, Element, Event, EventEmitter, Prop, State } from '@stencil/core';
import { getElementClassObject } from '../../utils/theme';
import { getButtonClassMap, getElementClassMap } from '../../utils/theme';
@Component({
@ -111,19 +111,15 @@ export class Button {
strong
} = this;
const elementClasses = [
...getButtonClassList(buttonType, mode),
...getClassList(buttonType, expand, mode),
...getClassList(buttonType, size, mode),
...getClassList(buttonType, round ? 'round' : null, mode),
...getClassList(buttonType, strong ? 'strong' : null, mode),
...getColorClassList(buttonType, color, fill, mode),
];
const TagType = this.href ? 'a' : 'button';
const buttonClasses = {
...getElementClassObject(this.el.classList),
...getElementClassObject(elementClasses),
...getButtonClassMap(buttonType, mode),
...getButtonTypeClassMap(buttonType, expand, mode),
...getButtonTypeClassMap(buttonType, size, mode),
...getButtonTypeClassMap(buttonType, round ? 'round' : null, mode),
...getButtonTypeClassMap(buttonType, strong ? 'strong' : null, mode),
...getColorClassMap(buttonType, color, fill, mode),
...getElementClassMap(this.el.classList),
'focused': this.keyFocus
};
@ -147,37 +143,23 @@ export class Button {
}
}
/**
* Get the classes based on the button type
* e.g. alert-button, action-sheet-button
*/
function getButtonClassList(buttonType: string, mode: string): string[] {
if (!buttonType) {
return [];
}
return [
buttonType,
`${buttonType}-${mode}`
];
}
/**
* Get the classes based on the type
* e.g. block, full, round, large
*/
function getClassList(buttonType: string, type: string, mode: string): string[] {
function getButtonTypeClassMap(buttonType: string, type: string, mode: string): CssClassMap {
if (!type) {
return [];
return {};
}
type = type.toLocaleLowerCase();
return [
`${buttonType}-${type}`,
`${buttonType}-${type}-${mode}`
];
return {
[`${buttonType}-${type}`]: true,
[`${buttonType}-${type}-${mode}`]: true
};
}
function getColorClassList(buttonType: string, color: string, fill: string, mode: string): string[] {
function getColorClassMap(buttonType: string, color: string, fill: string, mode: string): CssClassMap {
let className = buttonType;
if (buttonType !== 'bar-button' && fill === 'solid') {
@ -197,9 +179,12 @@ function getColorClassList(buttonType: string, color: string, fill: string, mode
className += '-' + fill.toLowerCase();
}
}
return [`${className}-${mode}`].concat(
fill !== 'default' ? `${className}` : [],
color ? `${className}-${mode}-${color}` : []
);
const map: CssClassMap = {
[className]: true,
[`${className}-${mode}`]: true,
};
if (color) {
map[`${className}-${mode}-${color}`] = true;
}
return map;
}

View File

@ -1,6 +1,5 @@
import { Component, CssClassMap, Element, Prop } from '@stencil/core';
import { getElementClassObject } from '../../utils/theme';
import { getButtonClassMap, getElementClassMap } from '../../utils/theme';
@Component({
tag: 'ion-chip-button',
@ -40,60 +39,24 @@ export class ChipButton {
*/
@Prop() href: string;
/**
* Get the classes based on the button type
* e.g. alert-button, action-sheet-button
*/
private getButtonClassList(buttonType: string, mode: string): string[] {
if (!buttonType) {
return [];
}
return [
buttonType,
`${buttonType}-${mode}`
];
}
/**
* Get the classes for the color
*/
private getColorClassList(color: string, buttonType: string, style: string, mode: string): string[] {
const className = (style === 'default') ? `${buttonType}` : `${buttonType}-${style}`;
return [`${className}-${mode}`].concat(
style !== 'default' ? `${className}` : [],
color ? `${className}-${mode}-${color}` : []
);
}
/**
* Get the classes for the style
* Chip buttons can only be clear or default (solid)
*/
private getStyleClassList(buttonType: string): string[] {
return this.getColorClassList(this.color, buttonType, this.fill || 'default', this.mode);
private getStyleClassMap(buttonType: string): CssClassMap {
return getColorClassMap(this.color, buttonType, this.fill || 'default', this.mode);
}
render() {
const buttonType = 'chip-button';
const hostClasses = getElementClassObject(this.el.classList);
const elementClasses: CssClassMap = []
.concat(
this.getButtonClassList(buttonType, this.mode),
this.getStyleClassList(buttonType)
)
.reduce((prevValue, cssClass) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
const hostClasses = getElementClassMap(this.el.classList);
const TagType = this.href ? 'a' : 'button';
const buttonClasses = {
...hostClasses,
...elementClasses
...getButtonClassMap(buttonType, this.mode),
...this.getStyleClassMap(buttonType),
};
return (
@ -109,3 +72,19 @@ export class ChipButton {
);
}
}
/**
* Get the classes for the color
*/
function getColorClassMap(color: string, buttonType: string, style: string, mode: string): CssClassMap {
const className = (style === 'default') ? `${buttonType}` : `${buttonType}-${style}`;
const map: CssClassMap = {
[className]: true,
[`${className}-${mode}`]: true
};
if (color) {
map[`${className}-${mode}-${color}`] = true;
}
return map;
}

View File

@ -1,6 +1,6 @@
import { Component, Element, Listen, Method, Prop } from '@stencil/core';
import { Config, DomController } from '../../index';
import { createThemedClasses, getElementClassObject } from '../../utils/theme';
import { createThemedClasses, getElementClassMap } from '../../utils/theme';
import { getPageElement } from '../../utils/helpers';
@Component({
@ -128,7 +128,7 @@ export class Content {
render() {
const themedClasses = createThemedClasses(this.mode, this.color, 'content');
const hostClasses = getElementClassObject(this.el.classList);
const hostClasses = getElementClassMap(this.el.classList);
const scrollClasses = {
...themedClasses,

View File

@ -1,5 +1,5 @@
import { Component, CssClassMap, Element, Prop, State } from '@stencil/core';
import { createThemedClasses, getElementClassObject } from '../../utils/theme';
import { createThemedClasses, getElementClassMap } from '../../utils/theme';
@Component({
@ -68,69 +68,30 @@ export class FabButton {
/**
* Get the classes for fab buttons in lists
*/
getFabListClassList() {
if (!this.inList) {
return [];
}
const listClasses = [
`fab-button-in-list`,
`fab-button-${this.mode}-in-list`
];
getFabClassMap(): CssClassMap {
return {
'fab-button-in-list': this.inList,
[`fab-button-${this.mode}-in-list`]: this.inList,
[`fab-button-translucent-${this.mode}-in-list`]: (this.inList && this.translucent),
if (this.translucent) {
listClasses.push(`fab-button-translucent-${this.mode}-in-list`);
}
return listClasses;
}
/**
* Get the close active class for fab buttons
*/
getFabActiveClassList() {
if (!this.activated) {
return [];
}
return [
`fab-button-close-active`
];
}
/**
* Get the show class for fab buttons
*/
getFabShowClassList() {
if (!this.show) {
return [];
}
return [
`fab-button-show`
];
'fab-button-close-active': this.activated,
'fab-button-show': this.show,
};
}
render() {
const themedClasses = createThemedClasses(this.mode, this.color, 'fab-button');
const translucentClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'fab-button-translucent') : {};
const hostClasses = getElementClassObject(this.el.classList);
const hostClasses = getElementClassMap(this.el.classList);
const elementClasses: CssClassMap = []
.concat(
this.getFabListClassList(),
this.getFabActiveClassList(),
this.getFabShowClassList()
)
.reduce((prevValue, cssClass) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
const TagType = this.href ? 'a' : 'button';
const fabClasses = {
...this.getFabClassMap(),
...themedClasses,
...translucentClasses,
...hostClasses,
...elementClasses
};
return (

View File

@ -9,7 +9,7 @@ import {
OverlayDismissEventDetail
} from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme';
import { createThemedClasses, getClassMap } from '../../utils/theme';
import iosEnterAnimation from './animations/ios.enter';
@ -225,22 +225,15 @@ export class Loading {
hostData() {
const themedClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'loading-translucent') : {};
const hostClasses = {
...themedClasses
};
return {
class: hostClasses
class: {
...themedClasses,
...getClassMap(this.cssClass)
}
};
}
render() {
if (this.cssClass) {
this.cssClass.split(' ').forEach(cssClass => {
if (cssClass.trim() !== '') this.el.classList.add(cssClass);
});
}
const loadingInner: any[] = [];
if (this.spinner !== 'hide') {

View File

@ -14,6 +14,7 @@ import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave';
import { getClassMap } from '../../utils/theme';
@Component({
tag: 'ion-picker',
@ -334,8 +335,8 @@ export class Picker {
<div class='picker-wrapper' role='dialog'>
<div class='picker-toolbar'>
{buttons.map(b =>
<div class={this.buttonWrapperClass(b)}>
<button onClick={() => this.buttonClick(b)} class={this.buttonClass(b)}>
<div class={buttonWrapperClass(b)}>
<button onClick={() => this.buttonClick(b)} class={buttonClass(b)}>
{b.text}
</button>
</div>
@ -351,28 +352,24 @@ export class Picker {
</div>
];
}
buttonWrapperClass(button: PickerButton): CssClassMap {
const buttonClass: string[] = !button.role
? ['picker-toolbar-button']
: [`picker-toolbar-button`, `picker-toolbar-${button.role}`];
return buttonClass.reduce((prevValue: any, cssClass: any) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
}
buttonClass(button: PickerButton): CssClassMap {
const buttonClass: string[] = !button.cssClass
? ['picker-button']
: [`picker-button`, `${button.cssClass}`];
return buttonClass.reduce((prevValue: any, cssClass: any) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
}
}
function buttonWrapperClass(button: PickerButton): CssClassMap {
const buttonClass: CssClassMap = {
'picker-toolbar-button': true,
};
if (button.role) {
buttonClass[`picker-toolbar-${button.role}`] = true;
}
return buttonClass;
}
function buttonClass(button: PickerButton): CssClassMap {
return {
'picker-button': true,
...getClassMap(button.cssClass)
};
}
export interface PickerButton {
text?: string;

View File

@ -1,6 +1,5 @@
import { Component, Element, Event, EventEmitter, Prop } from '@stencil/core';
import { CssClassMap } from '../../index';
import { createThemedClasses, getElementClassObject } from '../../utils/theme';
import { createThemedClasses, getElementClassMap } from '../../utils/theme';
@Component({
@ -62,35 +61,16 @@ export class SegmentButton {
});
}
/**
* Get the classes for the segment button state
*/
getElementClassList() {
const classList = [].concat(
this.disabled ? 'segment-button-disabled' : [],
this.activated ? 'segment-activated' : [],
);
return classList;
}
render() {
const themedClasses = createThemedClasses(this.mode, this.color, 'segment-button');
const hostClasses = getElementClassObject(this.el.classList);
const elementClasses: CssClassMap = []
.concat(
this.getElementClassList()
)
.reduce((prevValue, cssClass) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
const hostClasses = getElementClassMap(this.el.classList);
const buttonClasses = {
'segment-button-disabled': this.disabled,
'segment-activated': this.activated,
...themedClasses,
...hostClasses,
...elementClasses
};
const TagType = this.href ? 'a' : 'button';

View File

@ -2,7 +2,7 @@ import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@
import { Animation, AnimationBuilder, AnimationController, Config, CssClassMap, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme';
import { createThemedClasses, getClassMap } from '../../utils/theme';
import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave';
@ -157,35 +157,26 @@ export class Toast {
this.dismiss();
}
wrapperClass(): CssClassMap {
const wrapperClass: string[] = !this.position
? ['toast-wrapper', 'toast-bottom']
: [`toast-wrapper`, `toast-${this.position}`];
return wrapperClass.reduce((prevValue: any, cssClass: any) => {
prevValue[cssClass] = true;
return prevValue;
}, {});
private wrapperClass(): CssClassMap {
const position = this.position ? this.position : 'bottom';
return {
'toast-wrapper': true,
[`toast-${position}`]: true
};
}
hostData() {
const themedClasses = this.translucent ? createThemedClasses(this.mode, this.color, 'toast-translucent') : {};
const hostClasses = {
...themedClasses
};
return {
class: hostClasses
class: {
...themedClasses,
...getClassMap(this.cssClass)
}
};
}
render() {
if (this.cssClass) {
this.cssClass.split(' ').forEach(cssClass => {
if (cssClass.trim() !== '') this.el.classList.add(cssClass);
});
}
return (
<div class={this.wrapperClass()}>
<div class='toast-container'>

View File

@ -1,4 +1,4 @@
import { CellType, HeaderFn, ItemHeightFn, VirtualNode, calcCells, calcHeightIndex, getRange, getViewport, resizeBuffer, updateVDom, ItemRenderFn, Range, getShouldUpdate, positionForIndex } from '../virtual-scroll-utils';
import { CellType, HeaderFn, ItemHeightFn, Range, VirtualNode, calcCells, calcHeightIndex, getRange, getShouldUpdate, getViewport, positionForIndex, resizeBuffer, updateVDom } from '../virtual-scroll-utils';
describe('getViewport', () => {

View File

@ -26,7 +26,7 @@ export function createThemedClasses(mode: string, color: string, classes: string
/**
* Get the classes from a class list and return them as an object
*/
export function getElementClassObject(classList: DOMTokenList | string[]): CssClassMap {
export function getElementClassMap(classList: DOMTokenList | string[]): CssClassMap {
const classObj: CssClassMap = {};
for (let i = 0; i < classList.length; i++) {
@ -35,3 +35,30 @@ export function getElementClassObject(classList: DOMTokenList | string[]): CssCl
return classObj;
}
/**
* Get the classes based on the button type
* e.g. alert-button, action-sheet-button
*/
export function getButtonClassMap(buttonType: string, mode: string): CssClassMap {
if (!buttonType) {
return {};
}
return {
[buttonType]: true,
[`${buttonType}-${mode}`]: true
};
}
export function getClassMap(classes: string): CssClassMap {
const map: CssClassMap = {};
if (classes) {
classes
.split(' ')
.filter(c => c.trim() !== '')
.forEach(c => map[c] = true);
}
return map;
}