fix(prerender): router compatible with prerender

This commit is contained in:
Manu Mtz.-Almeida
2018-04-24 22:33:19 +02:00
parent 053c375521
commit 9c7b0ca15f
9 changed files with 2045 additions and 2013 deletions

3982
core/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,14 +9,14 @@ import { DATA_URL, STORED_DEMO_MODE_KEY, STORED_DEMO_URL_KEY } from '../helpers'
}) })
export class ThemeBuilder { export class ThemeBuilder {
@State() cssText: string = ''; @State() cssText = '';
demoData: { name: string, url: string }[]; demoData: { name: string, url: string }[];
@State() demoMode: string; @State() demoMode: string;
@State() demoUrl: string; @State() demoUrl: string;
@State() hoverProperty: string; @State() hoverProperty: string;
@State() propertiesUsed: string[]; @State() propertiesUsed: string[];
themeData: { name: string }[]; themeData: { name: string }[];
@State() themeName: string = ''; @State() themeName = '';
componentWillLoad () { componentWillLoad () {
return fetch(DATA_URL).then(rsp => { return fetch(DATA_URL).then(rsp => {

View File

@ -856,7 +856,7 @@ declare global {
/** /**
* The type of the button. Possible values are: `"submit"`, `"reset"` and `"button"`. Default value is: `"button"` * The type of the button. Possible values are: `"submit"`, `"reset"` and `"button"`. Default value is: `"button"`
*/ */
'type': string; 'type': 'submit' | 'reset' | 'button';
} }
} }
@ -934,7 +934,7 @@ declare global {
/** /**
* The type of the button. Possible values are: `"submit"`, `"reset"` and `"button"`. Default value is: `"button"` * The type of the button. Possible values are: `"submit"`, `"reset"` and `"button"`. Default value is: `"button"`
*/ */
'type'?: string; 'type'?: 'submit' | 'reset' | 'button';
} }
} }
} }

View File

@ -88,7 +88,7 @@ export class Button {
* Possible values are: `"submit"`, `"reset"` and `"button"`. * Possible values are: `"submit"`, `"reset"` and `"button"`.
* Default value is: `"button"` * Default value is: `"button"`
*/ */
@Prop() type = 'button'; @Prop() type: 'submit' | 'reset' | 'button' = 'button';
/** /**
* Emitted when the button has focus. * Emitted when the button has focus.

View File

@ -15,7 +15,7 @@ export class Gesture {
private detail: GestureDetail; private detail: GestureDetail;
private positions: number[] = []; private positions: number[] = [];
private gesture!: GestureDelegate; private gesture?: GestureDelegate;
private lastTouch = 0; private lastTouch = 0;
private pan!: PanRecognizer; private pan!: PanRecognizer;
private hasCapturedPan = false; private hasCapturedPan = false;
@ -27,6 +27,7 @@ export class Gesture {
@Prop({ connect: 'ion-gesture-controller' }) gestureCtrl!: HTMLIonGestureControllerElement; @Prop({ connect: 'ion-gesture-controller' }) gestureCtrl!: HTMLIonGestureControllerElement;
@Prop({ context: 'queue' }) queue!: QueueController; @Prop({ context: 'queue' }) queue!: QueueController;
@Prop({ context: 'enableListener' }) enableListener!: EventListenerEnable; @Prop({ context: 'enableListener' }) enableListener!: EventListenerEnable;
@Prop({ context: 'isServer' }) isServer!: boolean;
@Prop() disabled = false; @Prop() disabled = false;
@Prop() attachTo: string | HTMLElement = 'child'; @Prop() attachTo: string | HTMLElement = 'child';
@ -65,6 +66,9 @@ export class Gesture {
} }
async componentWillLoad() { async componentWillLoad() {
if (this.isServer) {
return;
}
this.gesture = await this.gestureCtrl.create({ this.gesture = await this.gestureCtrl.create({
name: this.gestureName, name: this.gestureName,
priority: this.gesturePriority, priority: this.gesturePriority,
@ -73,6 +77,9 @@ export class Gesture {
} }
componentDidLoad() { componentDidLoad() {
if (this.isServer) {
return;
}
// in this case, we already know the GestureController and Gesture are already // in this case, we already know the GestureController and Gesture are already
// apart of the same bundle, so it's safe to load it this way // apart of the same bundle, so it's safe to load it this way
// only create one instance of GestureController, and reuse the same one later // only create one instance of GestureController, and reuse the same one later
@ -91,7 +98,9 @@ export class Gesture {
this.blocker.destroy(); this.blocker.destroy();
this.blocker = undefined; this.blocker = undefined;
} }
this.gesture.destroy(); if (this.gesture) {
this.gesture.destroy();
}
} }
@Watch('disabled') @Watch('disabled')
@ -267,7 +276,7 @@ export class Gesture {
} }
private tryToCapturePan(): boolean { private tryToCapturePan(): boolean {
if (!this.gesture.capture()) { if (this.gesture && !this.gesture.capture()) {
return false; return false;
} }
this.hasCapturedPan = true; this.hasCapturedPan = true;

View File

@ -126,7 +126,11 @@ export class Menu {
if (this.type == null) { if (this.type == null) {
this.type = this.mode === 'ios' ? 'reveal' : 'overlay'; this.type = this.mode === 'ios' ? 'reveal' : 'overlay';
} }
this.menuCtrl = await this.lazyMenuCtrl.componentOnReady(); if (this.isServer) {
this.disabled = true;
} else {
this.menuCtrl = await this.lazyMenuCtrl.componentOnReady();
}
} }
componentDidLoad() { componentDidLoad() {

View File

@ -25,25 +25,37 @@ export class Router {
@Prop({ context: 'config' }) config!: Config; @Prop({ context: 'config' }) config!: Config;
@Prop({ context: 'queue' }) queue!: QueueController; @Prop({ context: 'queue' }) queue!: QueueController;
@Prop({ context: 'window' }) win!: Window; @Prop({ context: 'window' }) win!: Window;
@Prop({ context: 'isServer' }) isServer!: boolean;
@Prop() base = ''; @Prop() base = '';
@Prop() useHash = true; @Prop() useHash = true;
@Event() ionRouteChanged!: EventEmitter<RouterEventDetail>; @Event() ionRouteChanged!: EventEmitter<RouterEventDetail>;
componentDidLoad() { componentWillLoad() {
this.init = true; console.debug('[ion-router] router will load');
console.debug('[ion-router] router did load');
const tree = readRoutes(this.el); const tree = readRoutes(this.el);
this.routes = flattenRouterTree(tree); this.routes = flattenRouterTree(tree);
this.redirects = readRedirects(this.el); this.redirects = readRedirects(this.el);
// TODO: use something else return this.writeNavStateRoot(this.getPath(), RouterDirection.None);
requestAnimationFrame(() => { }
this.historyDirection();
this.writeNavStateRoot(this.getPath(), RouterDirection.None); componentDidLoad() {
}); this.init = true;
console.debug('[ion-router] router did load');
// const tree = readRoutes(this.el);
// this.routes = flattenRouterTree(tree);
// this.redirects = readRedirects(this.el);
// // TODO: use something else
// requestAnimationFrame(() => {
// this.historyDirection();
// this.writeNavStateRoot(this.getPath(), RouterDirection.None);
// });
} }
@Listen('ionRouteRedirectChanged') @Listen('ionRouteRedirectChanged')

View File

@ -35,7 +35,7 @@ export function isTablet(win: Window) {
} }
export function isDevice(win: Window) { export function isDevice(win: Window) {
return win.matchMedia('(any-pointer:coarse)').matches; return matchMedia(win, '(any-pointer:coarse)');
} }
export function isHybrid(win: Window) { export function isHybrid(win: Window) {
@ -63,3 +63,9 @@ export function needInputShims(win: Window) {
export function testUserAgent(win: Window, expr: RegExp) { export function testUserAgent(win: Window, expr: RegExp) {
return expr.test(win.navigator.userAgent); return expr.test(win.navigator.userAgent);
} }
export function matchMedia(win: Window, query: string, fallback = false): boolean {
return win.matchMedia
? win.matchMedia(query).matches
: fallback;
}

View File

@ -1,4 +1,4 @@
import { isAndroid, isCordova, isElectron, isIOS, isIpad, isIphone, isPhablet, isTablet } from './platform'; import { isAndroid, isCordova, isElectron, isIOS, isIpad, isIphone, isPhablet, isTablet, matchMedia } from './platform';
import { Config, Mode } from '../interface'; import { Config, Mode } from '../interface';
export function updateTestResults(displayWhen: DisplayWhen) { export function updateTestResults(displayWhen: DisplayWhen) {
@ -29,7 +29,7 @@ export function isSizeMatch(win: Window, multiSizeString: string) {
const sizes = multiSizeString.replace(/\s/g, '').split(','); const sizes = multiSizeString.replace(/\s/g, '').split(',');
for (const size of sizes) { for (const size of sizes) {
const mediaQuery = SIZE_TO_MEDIA[size]; const mediaQuery = SIZE_TO_MEDIA[size];
if (mediaQuery && win.matchMedia(mediaQuery).matches) { if (mediaQuery && matchMedia(win, mediaQuery)) {
return true; return true;
} }
} }
@ -39,7 +39,7 @@ export function isSizeMatch(win: Window, multiSizeString: string) {
export function getTestResult(displayWhen: DisplayWhen) { export function getTestResult(displayWhen: DisplayWhen) {
const resultsToConsider: boolean[] = []; const resultsToConsider: boolean[] = [];
if (displayWhen.mediaQuery) { if (displayWhen.mediaQuery) {
resultsToConsider.push(displayWhen.win.matchMedia(displayWhen.mediaQuery).matches); resultsToConsider.push(matchMedia(displayWhen.win, displayWhen.mediaQuery));
} }
if (displayWhen.size) { if (displayWhen.size) {
resultsToConsider.push(isSizeMatch(displayWhen.win, displayWhen.size)); resultsToConsider.push(isSizeMatch(displayWhen.win, displayWhen.size));
@ -80,9 +80,10 @@ export function isOrientationMatch(win: Window, orientation: string) {
} }
export function isPortrait(win: Window): boolean { export function isPortrait(win: Window): boolean {
return win.matchMedia('(orientation: portrait)').matches; return matchMedia(win, '(orientation: portrait)');
} }
const SIZE_TO_MEDIA: any = { const SIZE_TO_MEDIA: any = {
'xs': '(min-width: 0px)', 'xs': '(min-width: 0px)',
'sm': '(min-width: 576px)', 'sm': '(min-width: 576px)',