fix(range): adds css var

fixes #15064
This commit is contained in:
Manu Mtz.-Almeida
2018-08-11 16:02:54 +02:00
parent b53ce4b0e8
commit 3ab835c302
8 changed files with 192 additions and 377 deletions

View File

@@ -27,7 +27,6 @@ import {
InputChangeEvent,
ItemHeightFn,
ItemRenderFn,
Knob,
LoadingOptions,
Menu,
MenuChangeEventDetail,
@@ -1763,18 +1762,6 @@ declare global {
'value': string;
}
interface IonRangeKnob {
'disabled': boolean;
'knob': Knob;
'labelId': string;
'max': number;
'min': number;
'pin': boolean;
'pressed': boolean;
'ratio': number;
'value': number;
}
interface IonRange {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
@@ -3227,14 +3214,6 @@ declare global {
};
interface HTMLIonRangeKnobElement extends StencilComponents.IonRangeKnob, HTMLStencilElement {}
var HTMLIonRangeKnobElement: {
prototype: HTMLIonRangeKnobElement;
new (): HTMLIonRangeKnobElement;
};
interface HTMLIonRangeElement extends StencilComponents.IonRange, HTMLStencilElement {}
var HTMLIonRangeElement: {
@@ -3591,7 +3570,6 @@ declare global {
'ion-popover': JSXElements.IonPopoverAttributes;
'ion-radio-group': JSXElements.IonRadioGroupAttributes;
'ion-radio': JSXElements.IonRadioAttributes;
'ion-range-knob': JSXElements.IonRangeKnobAttributes;
'ion-range': JSXElements.IonRangeAttributes;
'ion-refresher-content': JSXElements.IonRefresherContentAttributes;
'ion-refresher': JSXElements.IonRefresherAttributes;
@@ -5278,20 +5256,6 @@ declare global {
'value'?: string;
}
export interface IonRangeKnobAttributes extends HTMLAttributes {
'disabled'?: boolean;
'knob'?: Knob;
'labelId'?: string;
'max'?: number;
'min'?: number;
'onIonDecrease'?: (event: CustomEvent) => void;
'onIonIncrease'?: (event: CustomEvent) => void;
'pin'?: boolean;
'pressed'?: boolean;
'ratio'?: number;
'value'?: number;
}
export interface IonRangeAttributes extends HTMLAttributes {
/**
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
@@ -6411,7 +6375,6 @@ declare global {
'ion-popover': HTMLIonPopoverElement
'ion-radio-group': HTMLIonRadioGroupElement
'ion-radio': HTMLIonRadioElement
'ion-range-knob': HTMLIonRangeKnobElement
'ion-range': HTMLIonRangeElement
'ion-refresher-content': HTMLIonRefresherContentElement
'ion-refresher': HTMLIonRefresherElement
@@ -6516,7 +6479,6 @@ declare global {
'ion-popover': HTMLIonPopoverElement;
'ion-radio-group': HTMLIonRadioGroupElement;
'ion-radio': HTMLIonRadioElement;
'ion-range-knob': HTMLIonRangeKnobElement;
'ion-range': HTMLIonRangeElement;
'ion-refresher-content': HTMLIonRefresherContentElement;
'ion-refresher': HTMLIonRefresherElement;

View File

@@ -1,76 +0,0 @@
import { Component, Event, EventEmitter, Listen, Prop } from '@stencil/core';
import { Knob } from '../../interface';
/** @hidden */
@Component({
tag: 'ion-range-knob'
})
export class RangeKnob {
@Prop() pressed!: boolean;
@Prop() pin!: boolean;
@Prop() min!: number;
@Prop() max!: number;
@Prop() value!: number;
@Prop() ratio!: number;
@Prop() disabled!: boolean;
@Prop() labelId!: string;
@Prop() knob!: Knob;
@Event() ionIncrease!: EventEmitter;
@Event() ionDecrease!: EventEmitter;
@Listen('keydown')
handleKeyBoard(ev: KeyboardEvent) {
const key = ev.key;
if (key === 'ArrowLeft' || key === 'ArrowDown') {
this.ionDecrease.emit({ isIncrease: false, knob: this.knob });
ev.preventDefault();
ev.stopPropagation();
} else if (key === 'ArrowRight' || key === 'ArrowUp') {
this.ionIncrease.emit({ isIncrease: true, knob: this.knob });
ev.preventDefault();
ev.stopPropagation();
}
}
hostData() {
const { value, min, max } = this;
const pos = this.ratio * 100;
return {
class: {
'range-knob-handle': true,
'range-knob-pressed': this.pressed,
'range-knob-min': value === min,
'range-knob-max': value === max
},
style: {
'left': `${pos}%`
},
'role': 'slider',
'tabindex': this.disabled ? -1 : 0,
'aria-valuemin': min,
'aria-valuemax': max,
'aria-disabled': this.disabled ? 'true' : null,
'aria-labelledby': this.labelId,
'aria-valuenow': value
};
}
render() {
if (this.pin) {
return [
<div class="range-pin" role="presentation">{Math.round(this.value)}</div>,
<div class="range-knob" role="presentation" />
];
}
return <div class="range-knob" role="presentation" />;
}
}
export const KEY_LEFT = 37;
export const KEY_UP = 38;
export const KEY_RIGHT = 39;
export const KEY_DOWN = 40;

View File

@@ -1,114 +0,0 @@
# ion-range-knob
RangeKnob is an internal component of Range.
<!-- Auto Generated Below -->
## Properties
#### disabled
boolean
#### knob
string
#### labelId
string
#### max
number
#### min
number
#### pin
boolean
#### pressed
boolean
#### ratio
number
#### value
number
## Attributes
#### disabled
boolean
#### knob
string
#### label-id
string
#### max
number
#### min
number
#### pin
boolean
#### pressed
boolean
#### ratio
number
#### value
number
## Events
#### ionDecrease
#### ionIncrease
----------------------------------------------
*Built with [StencilJS](https://stenciljs.com/)*

View File

@@ -5,48 +5,24 @@
// --------------------------------------------------
:host {
--knob-border-radius: 50%;
--knob-background: #{$range-ios-knob-background-color};
--knob-box-shadow: #{$range-ios-knob-box-shadow};
--knob-size: 28px;
--bar-height: #{$range-ios-bar-height};
--bar-background: #{$range-ios-bar-background-color};
--height: #{$range-ios-slider-height};
@include padding($range-ios-padding-vertical, $range-ios-padding-horizontal);
font-family: $range-ios-font-family;
}
// .range-ios [range-left] {
// @include margin(0, 20px, 0, 0);
// }
// .range-ios [range-right] {
// @include margin(0, 0, 0, 20px);
// }
:host(.range-has-pin) {
@include padding($range-ios-padding-vertical + $range-ios-pin-font-size, null, null, null);
}
.range-slider {
height: $range-ios-slider-height;
}
.range-bar {
@include position(($range-ios-slider-height / 2), null, null, 0);
@include border-radius(1px);
position: absolute;
width: 100%;
height: $range-ios-bar-height;
background: $range-ios-bar-background-color;
pointer-events: none;
}
:host(.range-pressed) .range-bar-active {
will-change: left, right;
}
:host(.range-pressed) .range-knob-handle {
will-change: left;
}
.range-bar-active {
bottom: 0;
@@ -55,34 +31,6 @@
background: $range-ios-bar-active-background-color;
}
.range-knob-handle {
@include position(($range-ios-slider-height / 2), null, null, 0);
@include margin(-($range-ios-hit-height / 2), null, null, -($range-ios-hit-width / 2));
position: absolute;
width: $range-ios-hit-width;
height: $range-ios-hit-height;
text-align: center;
}
.range-knob {
@include position(($range-ios-hit-height / 2) - ($range-ios-knob-height / 2) + ($range-ios-bar-height / 2) - .5px,
null, null, ($range-ios-hit-width / 2) - ($range-ios-knob-width / 2));
@include border-radius($range-ios-knob-border-radius);
position: absolute;
width: $range-ios-knob-width;
height: $range-ios-knob-height;
background: $range-ios-knob-background-color;
box-shadow: $range-ios-knob-box-shadow;
pointer-events: none;
}
.range-tick {
@include margin-horizontal(-($range-ios-tick-width / 2), null);
@include border-radius($range-ios-tick-border-radius);
@@ -102,7 +50,6 @@
}
.range-pin {
@include border-radius(50px);
@include transform(translate3d(0, 28px, 0), scale(.01));
@include padding($range-ios-pin-padding-top, $range-ios-pin-padding-end, $range-ios-pin-padding-bottom, $range-ios-pin-padding-start);

View File

@@ -5,9 +5,18 @@
// --------------------------------------------------
:host {
--knob-border-radius: 50%;
--knob-background: #{$range-md-knob-background-color};
--knob-box-shadow: none;
--knob-size: 18px;
--bar-height: #{$range-md-bar-height};
--bar-background: #{$range-md-bar-background-color};
--height: #{$range-md-slider-height};
@include padding($range-md-padding-vertical, $range-md-padding-horizontal);
font-family: $range-md-font-family;
font-size: $range-md-pin-font-size;
}
// TODO: REVIEW
@@ -23,30 +32,6 @@
@include padding($range-md-padding-vertical + $range-md-pin-font-size + $range-md-pin-padding-vertical, null, null, null);
}
.range-slider {
height: $range-md-slider-height;
}
.range-bar {
@include position(($range-md-slider-height / 2), null, null, 0);
position: absolute;
width: 100%;
height: $range-md-bar-height;
background: $range-md-bar-background-color;
pointer-events: none;
}
:host(.range-pressed) .range-bar-active {
will-change: left, right;
}
:host(.range-pressed) .range-knob-handle {
will-change: left;
}
.range-bar-active {
bottom: 0;
@@ -55,38 +40,14 @@
background: $range-md-bar-active-background-color;
}
.range-knob-handle {
@include position(($range-md-slider-height / 2), null, null, 0);
@include margin(-($range-md-hit-height / 2), null, null, -($range-md-hit-width / 2));
position: absolute;
width: $range-md-hit-width;
height: $range-md-hit-height;
text-align: center;
}
.range-knob {
@include position(($range-md-hit-height / 2) - ($range-md-knob-height / 2) + ($range-md-bar-height / 2),
null, null, ($range-md-hit-width / 2) - ($range-md-knob-width / 2));
@include border-radius(50%);
position: absolute;
width: $range-md-knob-width;
height: $range-md-knob-height;
transform: scale(.67);
transition-duration: 120ms;
transition-property: transform, background-color, border;
transition-timing-function: ease;
background: $range-md-knob-background-color;
z-index: 2;
pointer-events: none;
}
.range-tick {
@@ -123,11 +84,6 @@
transition: transform 120ms ease, background-color 120ms ease;
background: $range-md-pin-background-color;
color: $range-md-pin-color;
font-size: $range-md-pin-font-size;
text-align: center;
&::before {
@@ -159,24 +115,20 @@
transform: scale(1);
}
@mixin md-range-min() {
.range-knob-min.range-knob-min {
.range-knob {
border: $range-md-knob-min-border;
.range-knob-min.range-knob-min {
.range-knob {
border: $range-md-knob-min-border;
background: $range-md-knob-min-background-color;
}
background: $range-md-knob-min-background-color;
}
.range-pin,
.range-pin::before {
background: $range-md-pin-min-background-color;
color: ion-color(primary, contrast);
}
.range-pin,
.range-pin::before {
background: $range-md-pin-min-background-color;
color: ion-color(primary, contrast);
}
}
@include md-range-min();
:host(.range-disabled) .range-bar-active {
background-color: $range-md-bar-background-color;
}

View File

@@ -4,6 +4,7 @@
// --------------------------------------------------
:host {
--knob-handle-size: calc(var(--knob-size) * 2);
--ion-color-base: #{ion-color(primary, base)};
--ion-color-contrast: #{ion-color(primary, contrast)};
@@ -24,25 +25,99 @@
font-size: 24px;
}
.range-slider {
position: relative;
flex: 1;
cursor: pointer;
width: 100%;
height: var(--height);
contain: size layout style;
cursor: grab;
}
:host(.range-pressed) .range-slider {
cursor: grabbing;
}
.range-pin {
position: absolute;
background: current-color(base);
color: current-color(contrast);
text-align: center;
box-sizing: border-box;
}
.range-knob-handle {
@include position(
calc((var(--height) - var(--knob-handle-size)) / 2),
null, null, 0
);
@include margin-horizontal(
calc(0px - var(--knob-handle-size) / 2),
null
);
position: absolute;
width: var(--knob-handle-size);
height: var(--knob-handle-size);
text-align: center;
&:active,
&:focus {
outline: none;
}
}
.range-bar {
@include position(calc((var(--height) - var(--bar-height)) / 2), null, null, 0);
position: absolute;
width: 100%;
height: var(--bar-height);
background: var(--bar-background);
pointer-events: none;
}
.range-knob {
@include border-radius(var(--knob-border-radius));
@include position(
calc(50% - var(--knob-size) / 2),
null, null,
calc(50% - var(--knob-size) / 2)
);
position: absolute;
width: var(--knob-size);
height: var(--knob-size);
background: var(--knob-background);
box-shadow: var(--knob-box-shadow);
z-index: 2;
pointer-events: none;
}
:host(.range-pressed) .range-bar-active {
will-change: left, right;
}
:host(.range-pressed) .range-knob-handle {
will-change: left;
}
// Range in Item
// ----------------------------
@@ -60,6 +135,8 @@
// width: 100%;
// }
:host(.in-item) {
width: 100%;
}

View File

@@ -174,6 +174,21 @@ export class Range implements BaseInput {
this.updateValue();
}
private handleKeyboard(knob: string, isIncrease: boolean) {
let step = this.step;
step = step > 0 ? step : 1;
step = step / (this.max - this.min);
if (!isIncrease) {
step *= -1;
}
if (knob === 'A') {
this.ratioA += step;
} else {
this.ratioB += step;
}
this.updateValue();
}
private getValue(): RangeValue {
const value = this.value || 0;
if (this.dualKnobs) {
@@ -364,32 +379,84 @@ export class Range implements BaseInput {
right: barR
}}
/>
<ion-range-knob
knob="A"
pressed={this.pressedKnob === 'A'}
value={this.valA}
ratio={this.ratioA}
pin={this.pin}
min={min}
max={max}
/>
{this.dualKnobs && (
<ion-range-knob
knob="B"
pressed={this.pressedKnob === 'B'}
value={this.valB}
ratio={this.ratioB}
pin={this.pin}
min={min}
max={max}
/>
)}
{ renderKnob({
knob: 'A',
pressed: this.pressedKnob === 'A',
value: this.valA,
ratio: this.ratioA,
pin: this.pin,
disabled: this.disabled,
handleKeyboard: this.handleKeyboard.bind(this),
min,
max
})}
{ this.dualKnobs && renderKnob({
knob: 'B',
pressed: this.pressedKnob === 'B',
value: this.valB,
ratio: this.ratioB,
pin: this.pin,
disabled: this.disabled,
handleKeyboard: this.handleKeyboard.bind(this),
min,
max
})}
</div>,
<slot name="end"></slot>
];
}
}
interface RangeKnob {
knob: string;
value: number;
ratio: number;
min: number;
max: number;
disabled: boolean;
pressed: boolean;
pin: boolean;
handleKeyboard: (name: string, isIncrease: boolean) => void;
}
function renderKnob({ knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard }: RangeKnob) {
return (
<div
onKeyDown={(ev: KeyboardEvent) => {
const key = ev.key;
if (key === 'ArrowLeft' || key === 'ArrowDown') {
handleKeyboard(knob, false);
ev.preventDefault();
ev.stopPropagation();
} else if (key === 'ArrowRight' || key === 'ArrowUp') {
handleKeyboard(knob, true);
ev.preventDefault();
ev.stopPropagation();
}
}}
class={{
'range-knob-handle': true,
'range-knob-pressed': pressed,
'range-knob-min': value === min,
'range-knob-max': value === max
}}
style={{
'left': `${ratio * 100}%`
}}
role="slider"
tabindex={disabled ? -1 : 0}
aria-valuemin={min}
aria-valuemax={max}
aria-disabled={disabled ? 'true' : null}
aria-valuenow={value}>
{ pin && <div class="range-pin" role="presentation">{Math.round(value)}</div>}
<div class="range-knob" role="presentation" />
</div>
);
}
function ratioToValue(
ratio: number,

View File

@@ -30,7 +30,7 @@ exports.config = {
{ components: ['ion-img'] },
{ components: ['ion-popover', 'ion-popover-controller'] },
{ components: ['ion-radio', 'ion-radio-group'] },
{ components: ['ion-range', 'ion-range-knob'] },
{ components: ['ion-range'] },
{ components: ['ion-refresher', 'ion-refresher-content'] },
{ components: ['ion-reorder', 'ion-reorder-group'] },
{ components: ['ion-ripple-effect'] },