@brycemarshall/flexiboard-ionic
A customisable virtual keyboard implementation for the Ionic framework.
A keyboard can be defined either in markup, or in code (by injecting a FlexiboardDefinitionProvider implementation).
Virtual keyboards are rendered using CSS Flexbox layout rules. A keyboard is defined using rows, columns, and key definitions, each of which exposes a flexGrow property.
See the CSS Flexbox specification/documentation for information on the Flexbox layout.
Installation
npm i @brycemarshall/flexiboard-ionic
Component Styling and Themes
The component supports custom themes, and four are provided "out of the box". They include:
It is recommended that both the base styles and any required theme styles are imported from the app.scss file (example below).
@import '@brycemarshall/flexiboard-ionic/flexiboard';
@import '@brycemarshall/flexiboard-ionic/theme-ionic';
FlexiboardModule module Import
The Flexiboard module should be explicitly imported by any module that uses the component. Example:
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { InputPage } from './input';
import { FlexiboardModule } from '@brycemarshall/flexiboard-ionic';
@NgModule({
declarations: [
InputPage,
],
imports: [
FlexiboardModule,
IonicPageModule.forChild(InputPage),
],
})
export class InputPageModule {}
Basic Usage (Markup Keyboard Definition)
<ion-header>
<ion-navbar>
<ion-title>Markup Template Demo</ion-title>
</ion-navbar>
</ion-header>
<flexiboard [visible]="true" theme="ionic" (keyTap)="onTap($event)" (keyPress)="onPress($event)">
<flexiboard-column [flexGrow]="2">
<flexiboard-key id="A"></flexiboard-key>
<flexiboard-row>
<flexiboard-column [flexGrow]="3">
<flexiboard-row>
<flexiboard-key id="1" [value]="1"></flexiboard-key>
<flexiboard-key id="2" [value]="2" subtext="ABC"></flexiboard-key>
<flexiboard-key id="3" [value]="3" subtext="DEF"></flexiboard-key>
</flexiboard-row>
<flexiboard-row>
<flexiboard-key id="mail" iconName="md-mail" subtext="MAIL"></flexiboard-key>
<flexiboard-key id="0" [value]="0" subtext="+"></flexiboard-key>
<flexiboard-key id="keypad" iconName="md-keypad"></flexiboard-key>
</flexiboard-row>
<flexiboard-row>
<flexiboard-key id="B"></flexiboard-key>
<flexiboard-key id="C" [flexGrow]="2"></flexiboard-key>
</flexiboard-row>
</flexiboard-column>
<flexiboard-column [flexGrow]="1">
<flexiboard-key id="D"></flexiboard-key>
<flexiboard-key id="located" iconName="md-locate" subtext="LOCATE" [action]="true"></flexiboard-key>
</flexiboard-column>
</flexiboard-row>
<flexiboard-key id="done" [text]="doneText" [iconName]="doneIcon" [action]="true"></flexiboard-key>
</flexiboard-column>
</flexiboard>
Basic Usage (Injected Keyboard Definition)
<ion-header>
<ion-navbar>
<ion-title>Markup Template Demo</ion-title>
</ion-navbar>
</ion-header>
<flexiboard [visible]="true" theme="ionic" keyboard="number" (keyTap)="onTap($event)" (keyPress)="onPress($event)">
</flexiboard>
Basic Usage (Additional External Components)
Additional components can be included in the markup whether the virtual keyboard definition is described in the markup or in an injected FlexiboardDefinitionProvider.
In this example the root component is an ion-toolbar element, however any element that is not a flexiboard-row or flexiboard-column element will be rendered above the virtual keyboard.
<ion-header>
<ion-navbar>
<ion-title>Markup Template Demo</ion-title>
</ion-navbar>
</ion-header>
<flexiboard [visible]="true" theme="ionic" keyboard="number" (keyTap)="onTap($event)" (keyPress)="onPress($event)">
<ion-toolbar no-border-bottom>
<ion-buttons start>
<button ion-button (click)="hideKeyboard()">Cancel</button>
</ion-buttons>
</ion-toolbar>
</flexiboard>
Page Component Code Example with Injected FlexiboardDefinitionProvider
import { Component } from '@angular/core';
import { FlexiboardComponent, KeyInstance, FlexiboardDefinitionProvider } from '@brycemarshall/flexiboard-ionic';
import { DefinitionProvider } from './my-custom-definition-provider';
@IonicPage()
@Component({
selector: 'page-input',
templateUrl: 'input.html',
providers: [
{ provide: FlexiboardDefinitionProvider, useClass: DefinitionProvider }]
})
export class InputPage {
@ViewChild(FlexiboardComponent) keyboard: FlexiboardComponent;
onTap(key: keyInstance) {
console.log(key.value);
}
onPress(key: keyInstance) {
console.log(key.value);
}
}
FlexiboardDefinitionProvider Implementation Example
@Injectable()
export class DefinitionProvider extends FlexiboardDefinitionProvider {
getKeyboardDefinition(name: string): FlexiItem[] {
switch (name) {
case "number":
return numberFormat();
case "phone":
return phoneFormat();
case "mock":
return mockFormat();
}
return null;
}
}
function numberFormat(): FlexiItem[] {
return [
{ type: "row", items: [{ id: "1", value: 1 }, { id: "2", value: 2 }, { id: "3", value: 3 }, { id: "back", iconName: "backspace", keyMap: "Backspace", action: true }] },
{ type: "row", items: [{ id: "4", value: 4 }, { id: "5", value: 5 }, { id: "6", value: 6 }, { id: "next", text: "Next", keyMap: "ArrowRight;ArrowDown", action: true }] },
{ type: "row", items: [{ id: "7", value: 7 }, { id: "8", value: 8 }, { id: "9", value: 9 }, { id: "done", text: "Done", keyMap: "Enter", action: true }] },
{
type: "row",
items: [
null,
{ id: "0", value: 0 },
{ id: "." },
{ id: "cancel", iconName: "close", keyMap: "Escape", action: true }
]
}
];
}
function phoneFormat(): FlexiItem[] {
return [
{ type: "row", items: [{ id: "1", value: 1 }, { id: "2", value: 2, subtext: "ABC" }, { id: "3", value: 3, subtext: "DEF" }] },
{ type: "row", items: [{ id: "4", value: 4, subtext: "GHI" }, { id: "5", value: 5, subtext: "JKL" }, { id: "6", value: 6, subtext: "MNO" }] },
{ type: "row", items: [{ id: "7", value: 7, subtext: "PQRS" }, { id: "", value: 8, subtext: "TUV" }, { id: "8", value: 9, subtext: "WXYZ" }] },
{ type: "row", items: [{ id: "*" }, { id: "0", value: 0, subtext: "+" }, { id: "#" }] }
];
}
function mockFormat(): FlexiItem[] {
return [
{
type: "column",
items: [
{ id: "A" },
{
type: "row",
items: [
{
type: "column",
flexGrow: 3,
items: [
{
type: "row",
items: [
{ id: "1", value: 1 },
{ type: "blank" },
{ id: "3", value: 3, subtext: "DEF" }
]
},
{
type: "row",
items: [
{ id: "mail", iconName: "md-mail", subtext: "MAIL" },
{ id: "0", value: 0, subtext: "+" },
{ id: "keypad", iconName: "md-keypad" }
]
},
{
type: "row",
items: [
{ id: "B" },
{ flexGrow: 2 }
]
},
]
},
{
type: "column",
flexGrow: 1,
items: [
{ type: "blank" },
{ id: "locate", iconName: "md-locate", subtext: "LOCATE", action: true }
]
}
]
},
{ id: "done", text: "Done", action: true }
]
}
];
}
Package Exports
The package exports the following types:
export declare class FlexiboardModule {
}
export declare abstract class FlexiboardService {
}
export declare class FlexiboardComponent {
private _svc;
constructor(el: ElementRef, _svc: FlexiboardService);
private ngOnInit();
private ngOnDestroy();
readonly keyboardInit: EventEmitter<void>;
readonly keyTap: EventEmitter<KeyInstance>;
readonly keyPress: EventEmitter<KeyInstance>;
readonly visibilityChanged: EventEmitter<boolean>;
readonly transitioned: EventEmitter<boolean>;
keyboard: string;
theme: string;
align: string;
roundButtons: boolean;
swipeEnabled: boolean;
width: string;
hardCapture: boolean;
visible: boolean;
getAllKeys(): KeyInstance[];
getKeys(filter: (key: KeyInstance) => boolean): KeyInstance[];
getKey(id: string): KeyInstance;
forEachKey(handler: (key: KeyInstance) => void): void;
show(callback?: (args?: any) => void, callbackArgs?: any): void;
hide(callback?: (args?: any) => void, callbackArgs?: any): void;
private getBaseClasses();
private readonly textFontSize;
}
export declare abstract class FlexCompBase {
protected _svc: FlexiboardService;
protected abstract _item: FlexiGroup | FlexiKey;
constructor(svc: FlexiboardService);
flexGrow: number;
}
export declare abstract class HostCompBase extends FlexCompBase {
_viewContainer: ViewContainerRef;
protected _item: FlexiGroup;
constructor(svc: FlexiboardService);
ngOnInit(): void;
protected readonly abstract _items: FlexiItem[];
}
export declare class FlexiContainerComponent extends HostCompBase {
private _injector;
private _resolver;
protected _items: FlexiItem[];
constructor(_injector: Injector, _resolver: ComponentFactoryResolver, svc: FlexiboardService);
ngOnInit(): void;
ngAfterContentChecked(): void;
ngOnDestroy(): void;
}
export declare class FlexiRowComponent extends HostCompBase {
private _resolver;
constructor(_resolver: ComponentFactoryResolver, svc: FlexiboardService);
protected readonly _items: FlexiItem[];
}
export declare class FlexiColumnComponent extends HostCompBase {
private _resolver;
constructor(_resolver: ComponentFactoryResolver, svc: FlexiboardService);
protected readonly _items: FlexiItem[];
}
export declare class FlexiKeyComponent extends FlexCompBase {
protected _item: FlexiKey;
constructor(svc: FlexiboardService);
ngOnInit(): void;
id: string;
value: any;
text: string;
subtext: string;
iconName: string;
cssClass: string;
action: boolean;
disabled: boolean;
private btnTap(e);
private btnPress(e);
private readonly minHeight;
private readonly size;
private getWrapperClasses();
private getKeyClasses();
private getText();
private hasIcon();
private hasSubtext();
readonly isDisabled: string;
}
export declare class FlexiBlankComponent extends FlexCompBase {
protected _item: FlexiKey;
constructor(svc: FlexiboardService);
}
export declare abstract class FlexiboardDefinitionProvider {
abstract getKeyboardDefinition(name: string): FlexiItem[];
}
export declare type FlexiItem = FlexiGroup | FlexiKey | FlexiBlank;
export interface FlexiItemBase {
type?: string;
flexGrow?: number;
}
export interface FlexiBlank extends FlexiItemBase {
}
export interface FlexiGroup extends FlexiBlank {
items: FlexiItem[];
}
export interface FlexiKey extends FlexiBlank {
flexGrow?: number;
cssClass?: string;
iconName?: string;
text?: string;
subtext?: string;
action?: boolean;
keyMap?: string;
value?: any;
id: string;
}
export interface KeyInstance {
readonly id: string;
value: any;
text: string;
subtext: string;
iconName: string;
cssClass: string;
action: boolean;
disabled: boolean;
}