feat(all): strong typed ComponentProps

This commit is contained in:
Manu Mtz.-Almeida
2018-08-27 00:47:10 +02:00
parent c446d1b6d1
commit 57d23753a6
17 changed files with 57 additions and 47 deletions

View File

@@ -71,7 +71,7 @@ export namespace Components {
/**
* Create an action sheet overlay with action sheet options.
*/
'create': (opts?: ActionSheetOptions | undefined) => Promise<HTMLIonActionSheetElement>;
'create': (opts: ActionSheetOptions) => Promise<HTMLIonActionSheetElement>;
/**
* Dismiss the open action sheet overlay.
*/
@@ -220,7 +220,7 @@ export namespace Components {
/**
* Create an alert overlay with alert options
*/
'create': (opts?: AlertOptions | undefined) => Promise<HTMLIonAlertElement>;
'create': (opts: AlertOptions) => Promise<HTMLIonAlertElement>;
/**
* Dismiss the open alert overlay.
*/
@@ -2569,7 +2569,7 @@ export namespace Components {
/**
* Create a modal overlay with modal options.
*/
'create': (opts?: ModalOptions | undefined) => Promise<HTMLIonModalElement>;
'create': <T extends ComponentRef>(opts: ModalOptions<T>) => Promise<HTMLIonModalElement>;
/**
* Dismiss the open modal overlay.
*/
@@ -2768,7 +2768,7 @@ export namespace Components {
/**
* Inserts a component into the nav stack at the specified index. This is useful if you need to add a component at any point in your navigation stack.
*/
'insert': (insertIndex: number, component: NavComponent, componentProps?: ComponentProps | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
'insert': <T extends NavComponent>(insertIndex: number, component: T, componentProps?: ComponentProps<T> | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
/**
* Inserts an array of components into the nav stack at the specified index. The last component in the array will become instantiated as a view, and animate in to become the active view.
*/
@@ -2792,7 +2792,7 @@ export namespace Components {
/**
* Push a new component onto the current navigation stack. Pass any aditional information along as an object. This additional information is accessible through NavParams
*/
'push': (component: NavComponent, componentProps?: ComponentProps | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
'push': <T extends NavComponent>(component: T, componentProps?: ComponentProps<T> | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
/**
* Removes a page from the nav stack at the specified index.
*/
@@ -2812,7 +2812,7 @@ export namespace Components {
/**
* Set the root for the current navigation stack.
*/
'setRoot': (component: NavComponent, componentProps?: ComponentProps | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
'setRoot': <T extends NavComponent>(component: T, componentProps?: ComponentProps<T> | null | undefined, opts?: NavOptions | null | undefined, done?: TransitionDoneFn | undefined) => Promise<boolean>;
'setRouteId': (id: string, params: any, direction: number) => Promise<RouteWrite>;
/**
* If the nav component should allow for swipe-to-go-back
@@ -2880,7 +2880,7 @@ export namespace Components {
}
interface IonPickerController {
'create': (opts?: PickerOptions | undefined) => Promise<HTMLIonPickerElement>;
'create': (opts: PickerOptions) => Promise<HTMLIonPickerElement>;
'dismiss': (data?: any, role?: string | undefined, pickerId?: number | undefined) => Promise<void>;
'getTop': () => HTMLIonPickerElement;
}
@@ -3021,7 +3021,7 @@ export namespace Components {
/**
* Create a popover overlay with popover options.
*/
'create': (opts?: PopoverOptions | undefined) => Promise<HTMLIonPopoverElement>;
'create': <T extends ComponentRef>(opts: PopoverOptions<T>) => Promise<HTMLIonPopoverElement>;
/**
* Dismiss the open popover overlay.
*/
@@ -3591,7 +3591,7 @@ export namespace Components {
/**
* Set the root component for the given navigation stack
*/
'setRoot': (component: ComponentRef, params?: ComponentProps | undefined, opts?: RouterOutletOptions | undefined) => Promise<boolean>;
'setRoot': (component: ComponentRef, params?: { [key: string]: any; } | undefined, opts?: RouterOutletOptions | undefined) => Promise<boolean>;
'setRouteId': (id: string, params: any, direction: number) => Promise<RouteWrite>;
}
interface IonRouterOutletAttributes extends StencilHTMLAttributes {

View File

@@ -14,7 +14,7 @@ export class ActionSheetController implements OverlayController {
* Create an action sheet overlay with action sheet options.
*/
@Method()
create(opts?: ActionSheetOptions): Promise<HTMLIonActionSheetElement> {
create(opts: ActionSheetOptions): Promise<HTMLIonActionSheetElement> {
return createOverlay(this.doc.createElement('ion-action-sheet'), opts);
}

View File

@@ -14,7 +14,7 @@ export class AlertController implements OverlayController {
* Create an alert overlay with alert options
*/
@Method()
create(opts?: AlertOptions): Promise<HTMLIonAlertElement> {
create(opts: AlertOptions): Promise<HTMLIonAlertElement> {
return createOverlay(this.doc.createElement('ion-alert'), opts);
}

View File

@@ -1,7 +1,7 @@
import { TextFieldTypes } from '../../interface';
export interface AlertOptions {
header?: string;
header: string;
subHeader?: string;
message?: string;
cssClass?: string | string[];

View File

@@ -11,10 +11,10 @@
| Property | Attribute | Description | Type |
| ------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- |
| `mediaQuery` | `media-query` | If the current media query matches this value, the element will hide. | `string` |
| `mode` | `mode` | If the current platform matches the given value, the element will hide. Accepts a comma separated list of modes to match against. | `Mode` |
| `modes` | `modes` | If the current platform matches the given value, the element will hide. Accepts a comma separated list of modes to match against. | `string` |
| `or` | `or` | If false, and two or more conditions are set, the element will hide when all are true. If true, and two or more conditions are set, the element will hide when at least one is true. | `boolean` |
| `orientation` | `orientation` | If the current orientation matches this value, the element will hide. | `string` |
| `platform` | `platform` | If the current platform matches the given value, the element will hide. Accepts a comma separated list of platform to match against. | `string` |
| `platform` | `platform` | If the current platform matches the given value, the element will hide. Accepts a comma separated list of platforms to match against. | `string` |
| `size` | `size` | If the current screen width matches the given size, the element will hide. Uses the build in sizes of xs, sm, md, lg, xl. | `string` |

View File

@@ -1,6 +1,6 @@
import { Component, Method, Prop } from '@stencil/core';
import { ModalOptions, OverlayController } from '../../interface';
import { ComponentRef, ModalOptions, OverlayController } from '../../interface';
import { createOverlay, dismissOverlay, getOverlay } from '../../utils/overlays';
@Component({
@@ -14,7 +14,7 @@ export class ModalController implements OverlayController {
* Create a modal overlay with modal options.
*/
@Method()
create(opts?: ModalOptions): Promise<HTMLIonModalElement> {
create<T extends ComponentRef>(opts: ModalOptions<T>): Promise<HTMLIonModalElement> {
return createOverlay(this.doc.createElement('ion-modal'), opts);
}

View File

@@ -1,8 +1,8 @@
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate } from '../../interface';
export interface ModalOptions {
component: ComponentRef;
componentProps?: ComponentProps;
export interface ModalOptions<T extends ComponentRef = ComponentRef> {
component: T;
componentProps?: ComponentProps<T>;
showBackdrop?: boolean;
backdropDismiss?: boolean;
enterAnimation?: AnimationBuilder;

View File

@@ -145,9 +145,9 @@ export class Nav implements NavOutlet {
* Push a new component onto the current navigation stack. Pass any aditional information along as an object. This additional information is accessible through NavParams
*/
@Method()
push(
component: NavComponent,
componentProps?: ComponentProps | null,
push<T extends NavComponent>(
component: T,
componentProps?: ComponentProps<T> | null,
opts?: NavOptions | null,
done?: TransitionDoneFn
): Promise<boolean> {
@@ -165,10 +165,10 @@ export class Nav implements NavOutlet {
* Inserts a component into the nav stack at the specified index. This is useful if you need to add a component at any point in your navigation stack.
*/
@Method()
insert(
insert<T extends NavComponent>(
insertIndex: number,
component: NavComponent,
componentProps?: ComponentProps | null,
component: T,
componentProps?: ComponentProps<T> | null,
opts?: NavOptions | null,
done?: TransitionDoneFn
): Promise<boolean> {
@@ -282,9 +282,9 @@ export class Nav implements NavOutlet {
* Set the root for the current navigation stack.
*/
@Method()
setRoot(
component: NavComponent,
componentProps?: ComponentProps | null,
setRoot<T extends NavComponent>(
component: T,
componentProps?: ComponentProps<T> | null,
opts?: NavOptions | null,
done?: TransitionDoneFn
): Promise<boolean> {

View File

@@ -15,7 +15,7 @@ export class PickerController implements OverlayController {
* Create a picker overlay with picker options.
*/
@Method()
create(opts?: PickerOptions): Promise<HTMLIonPickerElement> {
create(opts: PickerOptions): Promise<HTMLIonPickerElement> {
return createOverlay(this.doc.createElement('ion-picker'), opts);
}

View File

@@ -1,7 +1,7 @@
export interface PickerOptions {
columns: PickerColumn[];
buttons?: PickerButton[];
columns?: PickerColumn[];
cssClass?: string | string[];
backdropDismiss?: boolean;
animated?: boolean;

View File

@@ -1,6 +1,6 @@
import { Component, Method, Prop } from '@stencil/core';
import { OverlayController, PopoverOptions } from '../../interface';
import { ComponentRef, OverlayController, PopoverOptions } from '../../interface';
import { createOverlay, dismissOverlay, getOverlay } from '../../utils/overlays';
@Component({
@@ -14,7 +14,7 @@ export class PopoverController implements OverlayController {
* Create a popover overlay with popover options.
*/
@Method()
create(opts?: PopoverOptions): Promise<HTMLIonPopoverElement> {
create<T extends ComponentRef>(opts: PopoverOptions<T>): Promise<HTMLIonPopoverElement> {
return createOverlay(this.doc.createElement('ion-popover'), opts);
}

View File

@@ -1,8 +1,8 @@
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate } from '../../interface';
export interface PopoverOptions {
component: ComponentRef;
componentProps?: ComponentProps;
export interface PopoverOptions<T extends ComponentRef = ComponentRef> {
component: T;
componentProps?: ComponentProps<T>;
showBackdrop?: boolean;
backdropDismiss?: boolean;
translucent?: boolean;

View File

@@ -12,7 +12,7 @@ ShowWhen can watch for platform changes, mode changes, css media queries, and de
| Property | Attribute | Description | Type |
| ------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- |
| `mediaQuery` | `media-query` | If the current media query matches this value, the element will show. | `string` |
| `mode` | `mode` | If the current platform matches the given value, the element will show. Accepts a comma separated list of modes to match against. | `Mode` |
| `modes` | `modes` | If the current platform matches the given value, the element will show. Accepts a comma separated list of modes to match against. | `string` |
| `or` | `or` | If false, and two or more conditions are set, the element will show when all are true. If true, and two or more conditions are set, the element will show when at least one is true. | `boolean` |
| `orientation` | `orientation` | If the current orientation matches this value, the element will show. | `string` |
| `platform` | `platform` | If the current platform matches the given value, the element will show. Accepts a comma separated list of platform to match against. | `string` |

View File

@@ -30,23 +30,17 @@ export * from './utils/input-interface';
export * from './global/config';
export * from './utils/overlays-interface';
// Global types
export type TextFieldTypes = 'date' | 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url';
export type Side = 'start' | 'end';
export type PredefinedColors = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'light' | 'medium' | 'dark';
export type Color = PredefinedColors | string;
export type Mode = 'ios' | 'md';
export type ComponentTags = keyof StencilIntrinsicElements;
export type ComponentRef = Function | HTMLElement | string;
export type ComponentProps = {[key: string]: any};
export type ComponentProps<T = null> = T extends ComponentTags ? StencilIntrinsicElements[T] : {[key: string]: any};
export type CssClassMap = { [className: string]: boolean };
export interface FrameworkDelegate {
attachViewToDom(container: any, component: any, propsOrDataObj?: any, cssClasses?: string[]): Promise<HTMLElement>;
removeViewFromDom(container: any, component: any): Promise<void>;
}
declare global {
interface StencilGlobalHTMLAttributes {
// for ion-menu and ion-split-pane

View File

@@ -1,4 +1,9 @@
import { ComponentRef, FrameworkDelegate } from '../interface';
import { ComponentRef } from '../interface';
export interface FrameworkDelegate {
attachViewToDom(container: any, component: any, propsOrDataObj?: any, cssClasses?: string[]): Promise<HTMLElement>;
removeViewFromDom(container: any, component: any): Promise<void>;
}
export async function attachComponent(
delegate: FrameworkDelegate | undefined,

View File

@@ -1,6 +1,6 @@
import { EventEmitter } from '@stencil/core';
import { Animation, AnimationBuilder, Config, Mode } from '../interface';
import { ActionSheetOptions, AlertOptions, Animation, AnimationBuilder, Config, Conforms, LoadingOptions, ModalOptions, Mode, PickerOptions, PopoverOptions, ToastOptions } from '../interface';
export interface OverlayEventDetail<T = any> {
data?: T;
@@ -42,3 +42,14 @@ export interface HTMLIonOverlayElement extends HTMLStencilElement {
dismiss(data?: any, role?: string): Promise<void>;
}
// Overlay checks
export type Conforms<T extends Required<B>, B> = T;
export type HTMLOverlaysElement =
Conforms<HTMLIonModalElement, ModalOptions> |
Conforms<HTMLIonToastElement, ToastOptions> |
Conforms<HTMLIonActionSheetElement, ActionSheetOptions> |
Conforms<HTMLIonAlertElement, AlertOptions> |
Conforms<HTMLIonPopoverElement, PopoverOptions> |
Conforms<HTMLIonPickerElement, PickerOptions> |
Conforms<HTMLIonLoadingElement, LoadingOptions>;

View File

@@ -2,7 +2,7 @@ import { AnimationBuilder, HTMLIonOverlayElement, IonicConfig, OverlayInterface
let lastId = 0;
export function createOverlay<T extends HTMLIonOverlayElement & Required<B>, B>(element: T, opts: B): Promise<T> {
export function createOverlay<T extends HTMLIonOverlayElement>(element: T, opts: object | undefined): Promise<T> {
const doc = element.ownerDocument;
connectListeners(doc);