Skip to content

Commit

Permalink
feat(input): added number stepper (#49)
Browse files Browse the repository at this point in the history
* feat(navbar): collapse optimisation

* feat(navbar): collapse optimisation

* feat(input): Added stepper

* feat(input): Added stepper

* feat(input): Added stepper

* feat(input): Added stepper

* feat(input): Added stepper

* feat(input): Added stepper

* conflicts fixed
select test fixed

* conflicts fixes

* move back select test due to it fails on CI but no localy

* mozornin fixes

* a bit refactored

* just to update ci

* ci fix try
  • Loading branch information
roll314 authored and pimenovoleg committed Oct 9, 2018
1 parent 3242689 commit 8ad947f
Show file tree
Hide file tree
Showing 24 changed files with 1,139 additions and 160 deletions.
205 changes: 85 additions & 120 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/cdk/keycodes/keycodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const SEMICOLON = 186; // Firefox (Gecko) fires 59 for SEMICOLON
export const EQUALS = 187; // Firefox (Gecko) fires 61 for EQUALS
export const COMMA = 188;
export const DASH = 189; // Firefox (Gecko) fires 173 for DASH/MINUS
export const PERIOD = 190;
export const SLASH = 191;
export const APOSTROPHE = 192;
export const TILDE = 192;
Expand Down
12 changes: 9 additions & 3 deletions src/cdk/testing/dispatch-events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,30 @@ export function dispatchEvent(node: Node | Window, event: Event): Event {
}

/** Shorthand to dispatch a fake event on a specified node. */
// tslint:disable-next-line:no-reserved-keywords
export function dispatchFakeEvent(node: Node | Window, type: string, canBubble?: boolean): Event {
return dispatchEvent(node, createFakeEvent(type, canBubble));
}

/** Shorthand to dispatch a keyboard event with a specified key code. */
export function dispatchKeyboardEvent(node: Node, type: string, keyCode: number, target?: Element):
// tslint:disable-next-line:no-reserved-keywords
export function dispatchKeyboardEvent(node: Node, type: string, keyCode: number, target?: Element,
shiftKey = false, ctrlKey = false, altKey = false):
KeyboardEvent {
return dispatchEvent(node, createKeyboardEvent(type, keyCode, target)) as KeyboardEvent;
const event = createKeyboardEvent(type, keyCode, target, undefined, shiftKey, ctrlKey, altKey);

return dispatchEvent(node, event) as KeyboardEvent;
}

/** Shorthand to dispatch a mouse event on the specified coordinates. */
// tslint:disable-next-line
// tslint:disable-next-line:no-reserved-keywords
export function dispatchMouseEvent(node: Node, type: string, x = 0, y = 0,
event = createMouseEvent(type, x, y)): MouseEvent {
return dispatchEvent(node, event) as MouseEvent;
}

/** Shorthand to dispatch a touch event on the specified coordinates. */
// tslint:disable-next-line:no-reserved-keywords
export function dispatchTouchEvent(node: Node, type: string, x = 0, y = 0) {
return dispatchEvent(node, createTouchEvent(type, x, y));
}
24 changes: 14 additions & 10 deletions src/cdk/testing/event-objects.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** Creates a browser MouseEvent with the specified options. */
// tslint:disable-next-line
// tslint:disable-next-line:no-reserved-keywords
export function createMouseEvent(type: string, x = 0, y = 0) {
const event = document.createEvent('MouseEvent');

Expand All @@ -23,27 +23,28 @@ export function createMouseEvent(type: string, x = 0, y = 0) {
}

/** Creates a browser TouchEvent with the specified pointer coordinates. */
// tslint:disable-next-line
// tslint:disable-next-line:no-reserved-keywords
export function createTouchEvent(type: string, pageX = 0, pageY = 0) {
// In favor of creating events that work for most of the browsers, the event is created
// as a basic UI Event. The necessary details for the event will be set manually.
const event = document.createEvent('UIEvent');
const touchDetails = {pageX, pageY};
const touchDetails = { pageX, pageY };

event.initUIEvent(type, true, true, window, 0);

// Most of the browsers don't have a "initTouchEvent" method that can be used to define
// the touch details.
Object.defineProperties(event, {
touches: {value: [touchDetails]}
touches: { value: [touchDetails] }
});

return event;
}

/** Dispatches a keydown event from an element. */
// tslint:disable-next-line
export function createKeyboardEvent(type: string, keyCode: number, target?: Element, key?: string) {
// tslint:disable-next-line:no-reserved-keywords
export function createKeyboardEvent(type: string, keyCode: number, target?: Element, key?: string,
shiftKey = false, ctrlKey = false, altKey = false) {
const event = document.createEvent('KeyboardEvent') as any;
// Firefox does not support `initKeyboardEvent`, but supports `initKeyEvent`.
const initEventFn = (event.initKeyEvent || event.initKeyboardEvent).bind(event);
Expand All @@ -54,9 +55,12 @@ export function createKeyboardEvent(type: string, keyCode: number, target?: Elem
// Webkit Browsers don't set the keyCode when calling the init function.
// See related bug https://bugs.webkit.org/show_bug.cgi?id=16735
Object.defineProperties(event, {
keyCode: {get: () => keyCode},
key: {get: () => key},
target: {get: () => target}
keyCode: { get: () => keyCode },
key: { get: () => key },
target: { get: () => target },
shiftKey: { get: () => shiftKey },
ctrlKey: { get: () => ctrlKey },
altKey: { get: () => altKey }
});

// IE won't set `defaultPrevented` on synthetic events so we need to do it manually.
Expand All @@ -70,7 +74,7 @@ export function createKeyboardEvent(type: string, keyCode: number, target?: Elem
}

/** Creates a fake event object with any desired event type. */
// tslint:disable-next-line
// tslint:disable-next-line:no-reserved-keywords
export function createFakeEvent(type: string, canBubble = false, cancelable = true) {
const event = document.createEvent('Event');
event.initEvent(type, canBubble, cancelable);
Expand Down
2 changes: 2 additions & 0 deletions src/lib-dev/input/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { McInputModule } from '../../lib/input/';
})
export class InputDemoComponent {
value: string = '';
numberValue: number | null = null;
}


Expand All @@ -36,6 +37,7 @@ export class InputDemoComponent {
})
export class InputDemoModule {}

// tslint:disable:no-console
platformBrowserDynamic()
.bootstrapModule(InputDemoModule)
.catch((error) => console.error(error));
Expand Down
56 changes: 56 additions & 0 deletions src/lib-dev/input/template.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,62 @@
<div class="container">

<header>Number Value: {{numberValue}}</header>
<br>

<header>Without placeholder:</header>
<mc-form-field>
<input mcInput [(ngModel)]="numberValue" type="number">
<mc-stepper></mc-stepper>
</mc-form-field>

<br><br>

<header>With placeholder:</header>
<mc-form-field>
<input mcInput [(ngModel)]="numberValue" type="number" placeholder="Number Value">
<mc-stepper></mc-stepper>
</mc-form-field>

<br><br>

<header>Min = -5 Max = 7 Step = 0.5 Big step = 1.5 </header>
<mc-form-field>
<input mcInput [(ngModel)]="numberValue" type="number" placeholder="Number MaxMin Step"
min="-5" max="7" step="0.5" big-step="1.5">
<mc-stepper></mc-stepper>
</mc-form-field>

<br><br>

<header>Min = -5 </header>
<mc-form-field>
<input mcInput [(ngModel)]="numberValue" type="number" placeholder="Min only" min="-5">
<mc-stepper></mc-stepper>
</mc-form-field>

<br><br>

<header>Step = 0.5 </header>
<mc-form-field>
<input mcInput [(ngModel)]="numberValue" type="number" placeholder="Step only" step="0.5">
<mc-stepper></mc-stepper>
</mc-form-field>

<br><br>

<header>Without placeholder:</header>
<mc-form-field>
<input mcInput [(ngModel)]="numberValue" type="number" disabled>
<mc-stepper></mc-stepper>
</mc-form-field>

<br><br>


<header>Value: {{value}}</header>
<br>

<header>Without placeholder:</header>
<mc-form-field>
<input mcInput [(ngModel)]="value">
</mc-form-field>
Expand Down
2 changes: 2 additions & 0 deletions src/lib/core/utils/__test__/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// tslint:disable:no-magic-numbers
import { toBoolean } from '../utils';


describe('[Core]::utils', () => {
it('should work for null values', () => {
expect(toBoolean(null)).toBe(false);
Expand Down
12 changes: 11 additions & 1 deletion src/lib/form-field/_form-field-theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
color: mc-color($second, 400);
}

mc-cleaner {
mc-cleaner {
.mc-cleaner__icon {
color: mc-color($second, 200);
}
Expand All @@ -79,6 +79,16 @@
color: darken(mc-color($second, 200), $hover-darken);
}
}

mc-stepper {
.mc-stepper-step-up, .mc-stepper-step-down {
color: mc-color($second, 200);

&:hover {
color: darken(mc-color($second, 200), $hover-darken);
}
}
}
}
}

Expand Down
28 changes: 28 additions & 0 deletions src/lib/form-field/form-field-number-control.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Observable } from 'rxjs';


/** An interface which allows a control to work inside of a `MсFormField`. */
export abstract class McFormFieldNumberControl<T> {
/** The value of the control. */
value: T | null;

/**
* Stream that emits whenever the state of the control changes such that the parent `MсFormField`
* needs to run change detection.
*/
readonly stateChanges: Observable<void>;

/** the number step */
step: number;

/** the number big step */
bigStep: number;

/** Whether the control is focused. */
readonly focused: boolean;

/** Handles step up and down */
abstract stepUp(step: number): void;

abstract stepDown(step: number): void;
}
2 changes: 2 additions & 0 deletions src/lib/form-field/form-field.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
(click)="clearValue($event)">
<ng-content select="mc-cleaner"></ng-content>
</div>

<ng-content *ngIf="canShowStepper" select="mc-stepper"></ng-content>
</div>

<div class="mc-form-field__hint" *ngIf="hasHint">
Expand Down
7 changes: 5 additions & 2 deletions src/lib/form-field/form-field.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { McCleaner } from './cleaner';
import { McFormField, McFormFieldWithoutBorders } from './form-field';
import { McHint } from './hint';
import { McPrefix } from './prefix';
import { McStepper } from './stepper';
import { McSuffix } from './suffix';


Expand All @@ -17,7 +18,8 @@ import { McSuffix } from './suffix';
McHint,
McPrefix,
McSuffix,
McCleaner
McCleaner,
McStepper
],
imports: [CommonModule, McIconModule],
exports: [
Expand All @@ -26,7 +28,8 @@ import { McSuffix } from './suffix';
McHint,
McPrefix,
McSuffix,
McCleaner
McCleaner,
McStepper
]
})
export class McFormFieldModule {
Expand Down
23 changes: 22 additions & 1 deletion src/lib/form-field/form-field.scss
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ $mc-form-field-border-size: 1px;
}

.mc-form-field_has-suffix,
.mc-form-field_has-cleaner {
.mc-form-field_has-cleaner,
.mc-form-field_has-stepper {
.mc-input {
padding-right: 32px;
}
Expand All @@ -78,5 +79,25 @@ mc-cleaner {
width: 32px;

cursor: pointer;
}

mc-stepper {
position: absolute;

display: flex;
flex-direction: column;
justify-content: center;
align-items: center;

top: 0;
bottom: 0;
right: 0;

width: 32px;

.mc-stepper-step-up, .mc-stepper-step-down {
cursor: pointer;
width: 32px;
text-align: center;
}
}
Loading

0 comments on commit 8ad947f

Please sign in to comment.