From 9a8057cdf28a863673e6c20127672655a15e29a8 Mon Sep 17 00:00:00 2001 From: Ely Lucas Date: Fri, 17 Jan 2020 15:42:58 -0700 Subject: [PATCH 1/8] fix(react): Don't render overlay children if isOpen is false, fixes #20225 (#20226) --- packages/react/src/components/createOverlayComponent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react/src/components/createOverlayComponent.tsx b/packages/react/src/components/createOverlayComponent.tsx index 63bd121dc1..d1d9ee5c17 100644 --- a/packages/react/src/components/createOverlayComponent.tsx +++ b/packages/react/src/components/createOverlayComponent.tsx @@ -40,7 +40,7 @@ export const createOverlayComponent = Date: Fri, 17 Jan 2020 16:23:26 -0700 Subject: [PATCH 2/8] fix(react): re attach props on update, fixes 20192 (#20228) --- .../react/src/components/createOverlayComponent.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/react/src/components/createOverlayComponent.tsx b/packages/react/src/components/createOverlayComponent.tsx index d1d9ee5c17..170ad7e389 100644 --- a/packages/react/src/components/createOverlayComponent.tsx +++ b/packages/react/src/components/createOverlayComponent.tsx @@ -59,6 +59,10 @@ export const createOverlayComponent = Date: Fri, 17 Jan 2020 16:57:11 -0700 Subject: [PATCH 3/8] fix(react): update icon types to be a string as well, fixes #20229 (#20230) --- packages/react/src/components/IonActionSheet.tsx | 2 +- packages/react/src/components/IonToast.tsx | 2 +- packages/react/src/components/index.ts | 4 ++-- packages/react/src/components/navigation/IonBackButton.tsx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react/src/components/IonActionSheet.tsx b/packages/react/src/components/IonActionSheet.tsx index 00635f6739..1c80c75b6c 100644 --- a/packages/react/src/components/IonActionSheet.tsx +++ b/packages/react/src/components/IonActionSheet.tsx @@ -6,7 +6,7 @@ export interface ActionSheetButton extends Omit { icon?: { ios: string; md: string; - }; + } | string; } export interface ActionSheetOptions extends Omit { diff --git a/packages/react/src/components/IonToast.tsx b/packages/react/src/components/IonToast.tsx index 82486edf55..3ffad9a2ce 100644 --- a/packages/react/src/components/IonToast.tsx +++ b/packages/react/src/components/IonToast.tsx @@ -6,7 +6,7 @@ export interface ToastButton extends Omit { icon?: { ios: string; md: string; - }; + } | string; } export interface ToastOptions extends Omit { diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts index fe04aedc9d..4f3512c6a0 100644 --- a/packages/react/src/components/index.ts +++ b/packages/react/src/components/index.ts @@ -8,11 +8,11 @@ export * from './proxies'; // createControllerComponent export { IonAlert } from './IonAlert'; export { IonLoading } from './IonLoading'; -export { IonToast } from './IonToast'; +export * from './IonToast'; export { IonPicker } from './IonPicker'; // createOverlayComponent -export { IonActionSheet } from './IonActionSheet'; +export * from './IonActionSheet'; export { IonModal } from './IonModal'; export { IonPopover } from './IonPopover'; diff --git a/packages/react/src/components/navigation/IonBackButton.tsx b/packages/react/src/components/navigation/IonBackButton.tsx index 36ff59d992..c3dabde7ff 100644 --- a/packages/react/src/components/navigation/IonBackButton.tsx +++ b/packages/react/src/components/navigation/IonBackButton.tsx @@ -9,7 +9,7 @@ type Props = Omit & IonicReactProps & { icon?: { ios: string; md: string; - }; + } | string; ref?: React.RefObject; }; From 85be000a4c5b2bcdb82f73f883c2803180806e8a Mon Sep 17 00:00:00 2001 From: Ely Lucas Date: Tue, 21 Jan 2020 16:12:42 -0700 Subject: [PATCH 4/8] fix(react): support routes without a path for notfound routes, fixes #20259 (#20261) --- .../src/ReactRouter/IonRouteData.ts | 2 +- .../react-router/src/ReactRouter/Router.tsx | 16 +++++++- .../react-router/src/ReactRouter/View.tsx | 1 + .../src/ReactRouter/ViewStacks.ts | 39 ++++++++++++------- 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/packages/react-router/src/ReactRouter/IonRouteData.ts b/packages/react-router/src/ReactRouter/IonRouteData.ts index 909d2874b9..25ddff604c 100644 --- a/packages/react-router/src/ReactRouter/IonRouteData.ts +++ b/packages/react-router/src/ReactRouter/IonRouteData.ts @@ -1,6 +1,6 @@ import { RouteProps, match } from 'react-router-dom'; export interface IonRouteData { - match: match<{ tab: string }> | null; + match: match | null; childProps: RouteProps; } diff --git a/packages/react-router/src/ReactRouter/Router.tsx b/packages/react-router/src/ReactRouter/Router.tsx index 3d6fb54887..eff626458e 100644 --- a/packages/react-router/src/ReactRouter/Router.tsx +++ b/packages/react-router/src/ReactRouter/Router.tsx @@ -255,12 +255,23 @@ export class RouteManager extends React.Component { const routeId = generateId(); this.routes[routeId] = child; views.push(createViewItem(child, routeId, this.props.history.location)); }); + if (!foundMatch) { + const notFoundRoute = views.find(r => { + // try to find a route that doesn't have a path or from prop, that will be our not found route + return !r.routeData.childProps.path && !r.routeData.childProps.from; + }); + if (notFoundRoute) { + notFoundRoute.show = true; + } + } + this.registerViewStack(id, activeId, views, routerOutlet, this.props.location); function createViewItem(child: React.ReactElement, routeId: string, location: HistoryLocation) { @@ -289,6 +300,9 @@ export class RouteManager extends React.Component { for (const routeKey in this.routes) { const route = this.routes[routeKey]; - if (route.props.path === child.props.path) { + if (typeof route.props.path !== 'undefined' && route.props.path === (child.props.path || child.props.from)) { this.routes[routeKey] = child; } } diff --git a/packages/react-router/src/ReactRouter/View.tsx b/packages/react-router/src/ReactRouter/View.tsx index d31a6f4265..03462da6c4 100644 --- a/packages/react-router/src/ReactRouter/View.tsx +++ b/packages/react-router/src/ReactRouter/View.tsx @@ -65,6 +65,7 @@ export class View extends React.Component { ...value, registerIonPage: this.registerIonPage.bind(this) }; + return ( {this.props.children} diff --git a/packages/react-router/src/ReactRouter/ViewStacks.ts b/packages/react-router/src/ReactRouter/ViewStacks.ts index 1b98d0802f..5990aed853 100644 --- a/packages/react-router/src/ReactRouter/ViewStacks.ts +++ b/packages/react-router/src/ReactRouter/ViewStacks.ts @@ -13,7 +13,7 @@ export interface ViewStack { * The holistic view of all the Routes configured for an application inside of an IonRouterOutlet. */ export class ViewStacks { - private viewStacks: { [key: string]: ViewStack | undefined } = {}; + private viewStacks: { [key: string]: ViewStack | undefined; } = {}; get(key: string) { return this.viewStacks[key]; @@ -31,25 +31,34 @@ export class ViewStacks { delete this.viewStacks[key]; } - findViewInfoByLocation(location: HistoryLocation, viewKey?: string) { + findViewInfoByLocation(location: HistoryLocation, viewKey: string) { let view: ViewItem | undefined; let match: IonRouteData['match'] | null | undefined; let viewStack: ViewStack | undefined; - if (viewKey) { - viewStack = this.viewStacks[viewKey]; - if (viewStack) { - viewStack.views.some(matchView); + + viewStack = this.viewStacks[viewKey]; + if (viewStack) { + viewStack.views.some(matchView); + + if (!view) { + viewStack.views.some(r => { + // try to find a route that doesn't have a path or from prop, that will be our not found route + if (!r.routeData.childProps.path && !r.routeData.childProps.from) { + match = { + path: location.pathname, + url: location.pathname, + isExact: true, + params: {} + }; + view = r; + return true; + } + return false; + }); } - } else { - const keys = this.getKeys(); - keys.some(key => { - viewStack = this.viewStacks[key]; - return viewStack!.views.some(matchView); - }); } - const result = { view, viewStack, match }; - return result; + return { view, viewStack, match }; function matchView(v: ViewItem) { const matchProps = { @@ -61,7 +70,7 @@ export class ViewStacks { if (myMatch) { view = v; match = myMatch; - return view.location === location.pathname; + return true; } return false; } From 9b2680d40deeca4fafb52c8ca0e93728b092b857 Mon Sep 17 00:00:00 2001 From: Ely Lucas Date: Wed, 22 Jan 2020 14:52:21 -0700 Subject: [PATCH 5/8] fix(react): adding missing overlay component events, fixes #19923 (#20266) --- .../src/components/createControllerComponent.tsx | 15 ++++++++++++--- .../src/components/createOverlayComponent.tsx | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/react/src/components/createControllerComponent.tsx b/packages/react/src/components/createControllerComponent.tsx index b0bb79ee4e..551b1395a1 100644 --- a/packages/react/src/components/createControllerComponent.tsx +++ b/packages/react/src/components/createControllerComponent.tsx @@ -11,13 +11,19 @@ interface OverlayBase extends HTMLElement { export interface ReactControllerProps { isOpen: boolean; onDidDismiss?: (event: CustomEvent) => void; + onDidPresent?: (event: CustomEvent) => void; + onWillDismiss?: (event: CustomEvent) => void; + onWillPresent?: (event: CustomEvent) => void; } export const createControllerComponent = ( displayName: string, controller: { create: (options: OptionsType) => Promise; } ) => { - const dismissEventName = `on${displayName}DidDismiss`; + const didDismissEventName = `on${displayName}DidDismiss`; + const didPresentEventName = `on${displayName}DidPresent`; + const willDismissEventName = `on${displayName}WillDismiss`; + const willPresentEventName = `on${displayName}WillPresent`; type Props = OptionsType & ReactControllerProps & { forwardedRef?: React.RefObject; @@ -67,12 +73,15 @@ export const createControllerComponent = this.props.onDidPresent && this.props.onDidPresent(e), + [willDismissEventName]: (e: CustomEvent) => this.props.onWillDismiss && this.props.onWillDismiss(e), + [willPresentEventName]: (e: CustomEvent) => this.props.onWillPresent && this.props.onWillPresent(e) }, prevProps); // Check isOpen again since the value could have changed during the async call to controller.create // It's also possible for the component to have become unmounted. diff --git a/packages/react/src/components/createOverlayComponent.tsx b/packages/react/src/components/createOverlayComponent.tsx index 170ad7e389..7c09c97a0c 100644 --- a/packages/react/src/components/createOverlayComponent.tsx +++ b/packages/react/src/components/createOverlayComponent.tsx @@ -13,13 +13,19 @@ export interface ReactOverlayProps { children?: React.ReactNode; isOpen: boolean; onDidDismiss?: (event: CustomEvent) => void; + onDidPresent?: (event: CustomEvent) => void; + onWillDismiss?: (event: CustomEvent) => void; + onWillPresent?: (event: CustomEvent) => void; } export const createOverlayComponent = ( displayName: string, controller: { create: (options: any) => Promise; } ) => { - const dismissEventName = `on${displayName}DidDismiss`; + const didDismissEventName = `on${displayName}DidDismiss`; + const didPresentEventName = `on${displayName}DidPresent`; + const willDismissEventName = `on${displayName}WillDismiss`; + const willPresentEventName = `on${displayName}WillPresent`; type Props = OverlayComponent & ReactOverlayProps & { forwardedRef?: React.RefObject; @@ -72,11 +78,14 @@ export const createOverlayComponent = this.props.onDidPresent && this.props.onDidPresent(e), + [willDismissEventName]: (e: CustomEvent) => this.props.onWillDismiss && this.props.onWillDismiss(e), + [willPresentEventName]: (e: CustomEvent) => this.props.onWillPresent && this.props.onWillPresent(e) }; this.overlay = await controller.create({ From 5d8e0ed7032265218b96c082d6d57a88d134a295 Mon Sep 17 00:00:00 2001 From: Ely Lucas Date: Wed, 22 Jan 2020 17:07:22 -0700 Subject: [PATCH 6/8] fix(react): remove leaving view when routerdirection is back, fixes #20124 (#20268) --- packages/react-router/src/ReactRouter/Router.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-router/src/ReactRouter/Router.tsx b/packages/react-router/src/ReactRouter/Router.tsx index eff626458e..14e3d144d6 100644 --- a/packages/react-router/src/ReactRouter/Router.tsx +++ b/packages/react-router/src/ReactRouter/Router.tsx @@ -154,7 +154,7 @@ export class RouteManager extends React.Component Date: Thu, 23 Jan 2020 11:15:22 -0700 Subject: [PATCH 7/8] fix(core): updating type of input value to accept numbers, fixes #20173 (#20267) --- core/api.txt | 2 +- core/src/components.d.ts | 4 ++-- core/src/components/input/input.tsx | 7 ++++--- core/src/components/input/readme.md | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/core/api.txt b/core/api.txt index ccbccd1bf4..b8b7919177 100644 --- a/core/api.txt +++ b/core/api.txt @@ -435,7 +435,7 @@ ion-input,prop,size,number | undefined,undefined,false,false ion-input,prop,spellcheck,boolean,false,false,false ion-input,prop,step,string | undefined,undefined,false,false ion-input,prop,type,"date" | "email" | "number" | "password" | "search" | "tel" | "text" | "time" | "url",'text',false,false -ion-input,prop,value,null | string | undefined,'',false,false +ion-input,prop,value,null | number | string | undefined,'',false,false ion-input,method,getInputElement,getInputElement() => Promise ion-input,method,setFocus,setFocus() => Promise ion-input,event,ionBlur,void,true diff --git a/core/src/components.d.ts b/core/src/components.d.ts index b8a7c5f964..a548e96d64 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -978,7 +978,7 @@ export namespace Components { /** * The value of the input. */ - 'value'?: string | null; + 'value'?: string | number | null; } interface IonItem { /** @@ -4232,7 +4232,7 @@ declare namespace LocalJSX { /** * The value of the input. */ - 'value'?: string | null; + 'value'?: string | number | null; } interface IonItem { /** diff --git a/core/src/components/input/input.tsx b/core/src/components/input/input.tsx index 555554726a..8322607383 100644 --- a/core/src/components/input/input.tsx +++ b/core/src/components/input/input.tsx @@ -169,7 +169,7 @@ export class Input implements ComponentInterface { /** * The value of the input. */ - @Prop({ mutable: true }) value?: string | null = ''; + @Prop({ mutable: true }) value?: string | number | null = ''; /** * Update the native input element when the value changes @@ -177,7 +177,7 @@ export class Input implements ComponentInterface { @Watch('value') protected valueChanged() { this.emitStyle(); - this.ionChange.emit({ value: this.value }); + this.ionChange.emit({ value: this.value == null ? this.value : this.value.toString() }); } /** @@ -263,7 +263,8 @@ export class Input implements ComponentInterface { } private getValue(): string { - return this.value || ''; + return typeof this.value === 'number' ? this.value.toString() : + (this.value || '').toString(); } private emitStyle() { diff --git a/core/src/components/input/readme.md b/core/src/components/input/readme.md index e36e6a8006..d2bf31568a 100644 --- a/core/src/components/input/readme.md +++ b/core/src/components/input/readme.md @@ -238,7 +238,7 @@ export const InputExample: React.FC = () => ( | `spellcheck` | `spellcheck` | If `true`, the element will have its spelling and grammar checked. | `boolean` | `false` | | `step` | `step` | Works with the min and max attributes to limit the increments at which a value can be set. Possible values are: `"any"` or a positive floating point number. | `string \| undefined` | `undefined` | | `type` | `type` | The type of control to display. The default type is text. | `"date" \| "email" \| "number" \| "password" \| "search" \| "tel" \| "text" \| "time" \| "url"` | `'text'` | -| `value` | `value` | The value of the input. | `null \| string \| undefined` | `''` | +| `value` | `value` | The value of the input. | `null \| number \| string \| undefined` | `''` | ## Events From 6e0c745703ab346bfebf6e2902d427b052dbbc7b Mon Sep 17 00:00:00 2001 From: Ely Lucas Date: Thu, 23 Jan 2020 13:00:15 -0700 Subject: [PATCH 8/8] 4.11.9 --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98b8dfb38a..f4acb0e967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +## [4.11.9](https://github.com/ionic-team/ionic/compare/v4.11.8...v4.11.9) (2020-01-23) + +### Bug Fixes + +* **core:** updating type of input value to accept numbers, fixes [#20173](https://github.com/ionic-team/ionic/issues/20173) ([#20267](https://github.com/ionic-team/ionic/issues/20267)) ([7080205](https://github.com/ionic-team/ionic/commit/708020551f9c51ca3b32d7b49bf4572db3dda12e)) +* **react:** adding missing overlay component events, fixes [#19923](https://github.com/ionic-team/ionic/issues/19923) ([#20266](https://github.com/ionic-team/ionic/issues/20266)) ([ec6a8dd](https://github.com/ionic-team/ionic/commit/ec6a8dd86f3854edba367f79a6ebac7d60eed839)) +* **react:** Don't render overlay children if isOpen is false, fixes [#20225](https://github.com/ionic-team/ionic/issues/20225) ([#20226](https://github.com/ionic-team/ionic/issues/20226)) ([aff9612](https://github.com/ionic-team/ionic/commit/aff9612d1197dca48eab6eff9d749032c380cf82)) +* **react:** re attach props on update, fixes 20192 ([#20228](https://github.com/ionic-team/ionic/issues/20228)) ([9e35ebe](https://github.com/ionic-team/ionic/commit/9e35ebed4a1590ef2521f5f8c393bdd9dea32a04)) +* **react:** remove leaving view when routerdirection is back, fixes [#20124](https://github.com/ionic-team/ionic/issues/20124) ([#20268](https://github.com/ionic-team/ionic/issues/20268)) ([63d4e87](https://github.com/ionic-team/ionic/commit/63d4e877fb18c90d70c4cbd5f66ffccb8ee6489c)) +* **react:** support routes without a path for notfound routes, fixes [#20259](https://github.com/ionic-team/ionic/issues/20259) ([#20261](https://github.com/ionic-team/ionic/issues/20261)) ([2f8c13b](https://github.com/ionic-team/ionic/commit/2f8c13b6960f9bcfb941c36fa6e1742b96f80ba9)) +* **react:** update icon types to be a string as well, fixes [#20229](https://github.com/ionic-team/ionic/issues/20229) ([#20230](https://github.com/ionic-team/ionic/issues/20230)) ([1411d8a](https://github.com/ionic-team/ionic/commit/1411d8a173bfefd7db5241218fd5641b7e9da823)) + + # [5.0.0-beta.5](https://github.com/ionic-team/ionic/compare/v4.11.8...v5.0.0-beta.5) (2020-01-17)