refactor(Context): remove global Context

This commit is contained in:
Adam Bradley
2017-12-18 13:21:17 -06:00
parent 3324e7a9b9
commit c415bbe1d7
19 changed files with 98 additions and 65 deletions

View File

@ -14,9 +14,9 @@
} }
}, },
"@stencil/core": { "@stencil/core": {
"version": "0.0.9-3", "version": "0.0.9-4",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-0.0.9-3.tgz", "resolved": "https://registry.npmjs.org/@stencil/core/-/core-0.0.9-4.tgz",
"integrity": "sha512-r56SaikZKceTlX0IGAKWKyuVtLI7XW/dUyfFYdRlPOto4Ifq63Pbs4s47Lmh2/NutfGMW1o7l6CWkhmO01tTPg==", "integrity": "sha512-P4eUb6UI1hHSsLrRf8rPRwdL/hWXDh/b0Cv6gkPK/iQPD27ARLy/M1mqjptEORpGkVodAE36JogLz+3zN3DG+Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"chokidar": "1.7.0", "chokidar": "1.7.0",
@ -3428,9 +3428,9 @@
"dev": true "dev": true
}, },
"ionicons": { "ionicons": {
"version": "4.0.0-10", "version": "4.0.0-11",
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-4.0.0-10.tgz", "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-4.0.0-11.tgz",
"integrity": "sha512-Ucr/nsio5YEIawva/Wcdu8zIJX/rs2otf7LiXmGgME09aE4N3id35fAko0LloTNpSxg0Lw0oX/KJEAI4prqVvA==", "integrity": "sha512-AoK+gnAE9ABLI0/swX5By8SXxU8AMpX2vpGMr7/lbc6emPhSV/ESfYMMa88a65tsMp8yG+zGOJI/LSwY6YeAQA==",
"dev": true "dev": true
}, },
"is-arrayish": { "is-arrayish": {

View File

@ -9,12 +9,12 @@
"dist/" "dist/"
], ],
"devDependencies": { "devDependencies": {
"@stencil/core": "0.0.9-3", "@stencil/core": "0.0.9-4",
"@stencil/dev-server": "0.0.18-0", "@stencil/dev-server": "0.0.18-0",
"@stencil/utils": "latest", "@stencil/utils": "latest",
"@types/jest": "^21.1.6", "@types/jest": "^21.1.6",
"chromedriver": "^2.33.2", "chromedriver": "^2.33.2",
"ionicons": "4.0.0-10", "ionicons": "4.0.0-11",
"jest": "^21.2.1", "jest": "^21.2.1",
"mocha": "^4.0.1", "mocha": "^4.0.1",
"np": "^2.17.0", "np": "^2.17.0",

View File

@ -4,11 +4,12 @@ import {
AnimationBuilder, AnimationBuilder,
AnimationController, AnimationController,
Config, Config,
DomController,
OverlayDismissEvent, OverlayDismissEvent,
OverlayDismissEventDetail OverlayDismissEventDetail
} from '../../index'; } from '../../index';
import { domControllerAsync, playAnimationAsync, isDef } from '../../utils/helpers'; import { domControllerAsync, isDef, playAnimationAsync } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme'; import { createThemedClasses } from '../../utils/theme';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
@ -68,6 +69,7 @@ export class ActionSheet {
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
/** /**
* Additional class or classes to apply to the action-sheet * Additional class or classes to apply to the action-sheet
@ -173,7 +175,7 @@ export class ActionSheet {
return playAnimationAsync(animation); return playAnimationAsync(animation);
}).then((animation) => { }).then((animation) => {
animation.destroy(); animation.destroy();
return domControllerAsync(Context.dom.write, () => { return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el); this.el.parentNode.removeChild(this.el);
}); });
}).then(() => { }).then(() => {

View File

@ -1,5 +1,5 @@
import { Component, CssClassMap, Element, Event, EventEmitter, Method, Prop } from '@stencil/core'; import { Component, CssClassMap, Element, Event, EventEmitter, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, AnimationController, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
import { BACKDROP } from '../../utils/overlay-constants'; import { BACKDROP } from '../../utils/overlay-constants';
@ -65,6 +65,7 @@ export class Alert {
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
/** /**
* Additional class or classes to apply to the alert * Additional class or classes to apply to the alert
@ -178,7 +179,7 @@ export class Alert {
}).then((animation) => { }).then((animation) => {
animation.destroy(); animation.destroy();
return domControllerAsync(Context.dom.write, () => { return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el); this.el.parentNode.removeChild(this.el);
}); });
}).then(() => { }).then(() => {

View File

@ -1,5 +1,5 @@
import { Component, Element, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Listen, Method, Prop } from '@stencil/core';
import { Config } from '../../index'; import { Config, DomController } from '../../index';
import { createThemedClasses, getElementClassObject } from '../../utils/theme'; import { createThemedClasses, getElementClassObject } from '../../utils/theme';
import { getPageElement } from '../../utils/helpers'; import { getPageElement } from '../../utils/helpers';
@ -23,6 +23,7 @@ export class Content {
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
/** /**
* @output {ScrollEvent} Emitted when the scrolling first starts. * @output {ScrollEvent} Emitted when the scrolling first starts.
@ -100,13 +101,13 @@ export class Content {
return; return;
} }
if (this.fullscreen) { if (this.fullscreen) {
Context.dom.raf(() => { this.dom.raf(() => {
Context.dom.read(this.readDimensions.bind(this)); this.dom.read(this.readDimensions.bind(this));
Context.dom.write(this.writeDimensions.bind(this)); this.dom.write(this.writeDimensions.bind(this));
}); });
} else { } else {
this.cTop = this.cBottom = null; this.cTop = this.cBottom = null;
Context.dom.write(() => this.scrollEl.removeAttribute('style')); this.dom.write(() => this.scrollEl.removeAttribute('style'));
} }
} }

View File

@ -1,8 +1,12 @@
import { ElementRef, applyStyles, assert, getElementReference, updateDetail } from '../../utils/helpers'; import { ElementRef, applyStyles, assert, getElementReference, updateDetail } from '../../utils/helpers';
import { BLOCK_ALL, BlockerDelegate, GestureController, GestureDelegate } from '../gesture-controller/gesture-controller'; import { BLOCK_ALL, BlockerDelegate, GestureController, GestureDelegate } from '../gesture-controller/gesture-controller';
import { Component, Element, Event, EventEmitter, Listen, Prop, PropDidChange } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Prop, PropDidChange } from '@stencil/core';
import { DomController } from '../../index';
import { PanRecognizer } from './recognizers'; import { PanRecognizer } from './recognizers';
declare const Ionic: { gesture: GestureController };
@Component({ @Component({
tag: 'ion-gesture' tag: 'ion-gesture'
}) })
@ -23,6 +27,9 @@ export class Gesture {
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ context: 'dom' }) dom: DomController;
@Prop({ context: 'enableListener' }) enableListener: any;
@Prop() enabled: boolean = true; @Prop() enabled: boolean = true;
@Prop() attachTo: ElementRef = 'child'; @Prop() attachTo: ElementRef = 'child';
@Prop() autoBlockAll: boolean = false; @Prop() autoBlockAll: boolean = false;
@ -73,7 +80,7 @@ export class Gesture {
// 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
this.ctrl = Context.gesture = Context.gesture || new GestureController; this.ctrl = Ionic.gesture = Ionic.gesture || new GestureController();
this.gesture = this.ctrl.createGesture(this.gestureName, this.gesturePriority, this.disableScroll); this.gesture = this.ctrl.createGesture(this.gestureName, this.gesturePriority, this.disableScroll);
const types = this.type.replace(/\s/g, '').toLowerCase().split(','); const types = this.type.replace(/\s/g, '').toLowerCase().split(',');
@ -84,7 +91,7 @@ export class Gesture {
this.enabledChanged(this.enabled); this.enabledChanged(this.enabled);
if (this.pan || this.hasPress) { if (this.pan || this.hasPress) {
Context.dom.write(() => { this.dom.write(() => {
applyStyles(getElementReference(this.el, this.attachTo), GESTURE_INLINE_STYLES); applyStyles(getElementReference(this.el, this.attachTo), GESTURE_INLINE_STYLES);
}); });
} }
@ -98,8 +105,8 @@ export class Gesture {
@PropDidChange('enabled') @PropDidChange('enabled')
protected enabledChanged(isEnabled: boolean) { protected enabledChanged(isEnabled: boolean) {
if (this.pan || this.hasPress) { if (this.pan || this.hasPress) {
Context.enableListener(this, 'touchstart', isEnabled, this.attachTo); this.enableListener(this, 'touchstart', isEnabled, this.attachTo);
Context.enableListener(this, 'mousedown', isEnabled, this.attachTo); this.enableListener(this, 'mousedown', isEnabled, this.attachTo);
if (!isEnabled) { if (!isEnabled) {
this.abortGesture(); this.abortGesture();
} }
@ -216,7 +223,7 @@ export class Gesture {
if (!this.isMoveQueued && this.hasFiredStart) { if (!this.isMoveQueued && this.hasFiredStart) {
this.isMoveQueued = true; this.isMoveQueued = true;
this.calcGestureData(ev); this.calcGestureData(ev);
Context.dom.write(this.fireOnMove.bind(this)); this.dom.write(this.fireOnMove.bind(this));
} }
return; return;
} }
@ -424,18 +431,18 @@ export class Gesture {
private enableMouse(shouldEnable: boolean) { private enableMouse(shouldEnable: boolean) {
if (this.pan) { if (this.pan) {
Context.enableListener(this, 'document:mousemove', shouldEnable); this.enableListener(this, 'document:mousemove', shouldEnable);
} }
Context.enableListener(this, 'document:mouseup', shouldEnable); this.enableListener(this, 'document:mouseup', shouldEnable);
} }
private enableTouch(shouldEnable: boolean) { private enableTouch(shouldEnable: boolean) {
if (this.pan) { if (this.pan) {
Context.enableListener(this, 'touchmove', shouldEnable, this.attachTo); this.enableListener(this, 'touchmove', shouldEnable, this.attachTo);
} }
Context.enableListener(this, 'touchcancel', shouldEnable, this.attachTo); this.enableListener(this, 'touchcancel', shouldEnable, this.attachTo);
Context.enableListener(this, 'touchend', shouldEnable, this.attachTo); this.enableListener(this, 'touchend', shouldEnable, this.attachTo);
} }

View File

@ -1,5 +1,5 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop, PropDidChange, State } from '@stencil/core';
import { ScrollDetail, StencilElement } from '../../index'; import { DomController, ScrollDetail, StencilElement } from '../../index';
const enum Position { const enum Position {
Top = 'top', Top = 'top',
@ -23,6 +23,9 @@ export class InfiniteScroll {
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@State() isLoading: boolean = false; @State() isLoading: boolean = false;
@Prop({ context: 'dom' }) dom: DomController;
@Prop({ context: 'enableListener' }) enableListener: any;
/** /**
* @input {string} The threshold distance from the bottom * @input {string} The threshold distance from the bottom
* of the content to call the `infinite` output event when scrolled. * of the content to call the `infinite` output event when scrolled.
@ -97,7 +100,7 @@ export class InfiniteScroll {
this.thresholdChanged(this.threshold); this.thresholdChanged(this.threshold);
this.enableScrollEvents(this.enabled); this.enableScrollEvents(this.enabled);
if (this.position === Position.Top) { if (this.position === Position.Top) {
Context.dom.write(() => this.scrollEl.scrollToBottom(0)); this.dom.write(() => this.scrollEl.scrollToBottom(0));
} }
} }
@ -196,14 +199,14 @@ export class InfiniteScroll {
const prev = this.scrollEl.scrollHeight - this.scrollEl.scrollTop; const prev = this.scrollEl.scrollHeight - this.scrollEl.scrollTop;
// ******** DOM READ **************** // ******** DOM READ ****************
Context.dom.read(() => { this.dom.read(() => {
// UI has updated, save the new content dimensions // UI has updated, save the new content dimensions
const scrollHeight = this.scrollEl.scrollHeight; const scrollHeight = this.scrollEl.scrollHeight;
// New content was added on top, so the scroll position should be changed immediately to prevent it from jumping around // New content was added on top, so the scroll position should be changed immediately to prevent it from jumping around
const newScrollTop = scrollHeight - prev; const newScrollTop = scrollHeight - prev;
// ******** DOM WRITE **************** // ******** DOM WRITE ****************
Context.dom.write(() => { this.dom.write(() => {
this.scrollEl.scrollTop = newScrollTop; this.scrollEl.scrollTop = newScrollTop;
this.isBusy = false; this.isBusy = false;
}); });
@ -225,7 +228,7 @@ export class InfiniteScroll {
* @hidden * @hidden
*/ */
private enableScrollEvents(shouldListen: boolean) { private enableScrollEvents(shouldListen: boolean) {
Context.enableListener(this, 'ionScroll', shouldListen, this.scrollEl); this.enableListener(this, 'ionScroll', shouldListen, this.scrollEl);
} }
hostData() { hostData() {
@ -237,7 +240,6 @@ export class InfiniteScroll {
}; };
} }
render() { render() {
return <slot></slot>; return <slot></slot>;
} }

View File

@ -1,10 +1,10 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { import {
Animation, Animation,
AnimationBuilder, AnimationBuilder,
AnimationController, AnimationController,
Config, Config,
DomController,
OverlayDismissEvent, OverlayDismissEvent,
OverlayDismissEventDetail OverlayDismissEventDetail
} from '../../index'; } from '../../index';
@ -71,6 +71,7 @@ export class Loading {
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
/** /**
* Additional classes to apply for custom CSS * Additional classes to apply for custom CSS
@ -173,7 +174,7 @@ export class Loading {
return playAnimationAsync(animation); return playAnimationAsync(animation);
}).then((animation) => { }).then((animation) => {
animation.destroy(); animation.destroy();
return domControllerAsync(Context.dom.write, () => { return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el); this.el.parentNode.removeChild(this.el);
}); });
}).then(() => { }).then(() => {

View File

@ -35,6 +35,7 @@ export class Menu {
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ connect: 'ion-menu-controller' }) lazyMenuCtrl: StencilElement; @Prop({ connect: 'ion-menu-controller' }) lazyMenuCtrl: StencilElement;
@Prop({ context: 'enableListener' }) enableListener: any;
/** /**
* @input {string} The content's id the menu should use. * @input {string} The content's id the menu should use.
@ -374,7 +375,7 @@ export class Menu {
this.isAnimating = false; this.isAnimating = false;
// add/remove backdrop click listeners // add/remove backdrop click listeners
Context.enableListener(this, 'body:click', isOpen); this.enableListener(this, 'body:click', isOpen);
if (isOpen) { if (isOpen) {
// disable swipe to go back gesture // disable swipe to go back gesture

View File

@ -4,6 +4,7 @@ import {
AnimationBuilder, AnimationBuilder,
AnimationController, AnimationController,
Config, Config,
DomController,
FrameworkDelegate, FrameworkDelegate,
OverlayDismissEvent, OverlayDismissEvent,
OverlayDismissEventDetail OverlayDismissEventDetail
@ -63,6 +64,8 @@ export class Modal {
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
@Prop() mode: string; @Prop() mode: string;
@Prop() color: string; @Prop() color: string;
@Prop() component: any; @Prop() component: any;
@ -144,7 +147,7 @@ export class Modal {
this.animation.destroy(); this.animation.destroy();
await domControllerAsync(Context.dom.write, () => {}); await domControllerAsync(this.dom.write, () => {});
// TODO - Figure out how to make DOM controller work with callbacks that return a promise or are async // TODO - Figure out how to make DOM controller work with callbacks that return a promise or are async
const userComponentParent = this.el.querySelector(`.${USER_COMPONENT_MODAL_CONTAINER_CLASS}`); const userComponentParent = this.el.querySelector(`.${USER_COMPONENT_MODAL_CONTAINER_CLASS}`);

View File

@ -1,9 +1,8 @@
import { Component, Element, Prop } from '@stencil/core'; import { Component, Element, Prop } from '@stencil/core';
import { DomController, GestureDetail, PickerColumn, PickerColumnOption } from '../../index';
import { GestureDetail, PickerColumn, PickerColumnOption } from '../../index';
import { clamp } from '../../utils/helpers'; import { clamp } from '../../utils/helpers';
@Component({ @Component({
tag: 'ion-picker-column', tag: 'ion-picker-column',
host: { host: {
@ -14,7 +13,6 @@ export class PickerColumnCmp {
private mode: string; private mode: string;
private bounceFrom: number; private bounceFrom: number;
private colHeight: number;
private lastIndex: number; private lastIndex: number;
private lastTempIndex: number; private lastTempIndex: number;
private minY: number; private minY: number;
@ -31,6 +29,8 @@ export class PickerColumnCmp {
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ context: 'dom' }) dom: DomController;
@Prop() col: PickerColumn; @Prop() col: PickerColumn;
componentWillLoad() { componentWillLoad() {
@ -49,7 +49,6 @@ export class PickerColumnCmp {
componentDidLoad() { componentDidLoad() {
// get the scrollable element within the column // get the scrollable element within the column
let colEle = this.el.querySelector('.picker-opts'); let colEle = this.el.querySelector('.picker-opts');
this.colHeight = colEle.clientHeight;
// get the height of one option // get the height of one option
this.optHeight = (colEle.firstElementChild ? colEle.firstElementChild.clientHeight : 0); this.optHeight = (colEle.firstElementChild ? colEle.firstElementChild.clientHeight : 0);
@ -94,7 +93,6 @@ export class PickerColumnCmp {
let opt: PickerColumnOption; let opt: PickerColumnOption;
let optOffset: number; let optOffset: number;
let visible: boolean; let visible: boolean;
let translateX: number;
let translateY: number; let translateY: number;
let translateZ: number; let translateZ: number;
let rotateX: number; let rotateX: number;
@ -121,13 +119,11 @@ export class PickerColumnCmp {
if (Math.abs(rotateX) > 90) { if (Math.abs(rotateX) > 90) {
visible = false; visible = false;
} else { } else {
translateX = 0;
translateY = 0; translateY = 0;
translateZ = 90; translateZ = 90;
transform = `rotateX(${rotateX}deg) `; transform = `rotateX(${rotateX}deg) `;
} }
} else { } else {
translateX = 0;
translateZ = 0; translateZ = 0;
translateY = optOffset; translateY = optOffset;
if (Math.abs(translateY) > 170) { if (Math.abs(translateY) > 170) {
@ -224,7 +220,7 @@ export class PickerColumnCmp {
if (notLockedIn) { if (notLockedIn) {
// isn't locked in yet, keep decelerating until it is // isn't locked in yet, keep decelerating until it is
Context.dom.raf(() => this.decelerate()); this.dom.raf(() => this.decelerate());
} }
} else if (this.y % this.optHeight !== 0) { } else if (this.y % this.optHeight !== 0) {

View File

@ -5,6 +5,7 @@ import {
AnimationBuilder, AnimationBuilder,
AnimationController, AnimationController,
Config, Config,
DomController,
OverlayDismissEvent, OverlayDismissEvent,
OverlayDismissEventDetail OverlayDismissEventDetail
} from '../../index'; } from '../../index';
@ -66,6 +67,8 @@ export class Picker {
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
@Prop() cssClass: string; @Prop() cssClass: string;
@Prop() content: string; @Prop() content: string;
@Prop() dismissOnPageChange: boolean = false; @Prop() dismissOnPageChange: boolean = false;
@ -130,7 +133,7 @@ export class Picker {
return playAnimationAsync(animation); return playAnimationAsync(animation);
}).then((animation) => { }).then((animation) => {
animation.destroy(); animation.destroy();
return domControllerAsync(Context.dom.write, () => { return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el); this.el.parentNode.removeChild(this.el);
}); });
}).then(() => { }).then(() => {

View File

@ -4,6 +4,7 @@ import {
AnimationBuilder, AnimationBuilder,
AnimationController, AnimationController,
Config, Config,
DomController,
FrameworkDelegate, FrameworkDelegate,
OverlayDismissEvent, OverlayDismissEvent,
OverlayDismissEventDetail OverlayDismissEventDetail
@ -64,6 +65,7 @@ export class Popover {
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
@Prop() mode: string; @Prop() mode: string;
@Prop() color: string; @Prop() color: string;
@ -151,7 +153,7 @@ export class Popover {
return playAnimationAsync(animation); return playAnimationAsync(animation);
}).then((animation) => { }).then((animation) => {
animation.destroy(); animation.destroy();
return domControllerAsync(Context.dom.write, () => {}); return domControllerAsync(this.dom.write, () => {});
}).then(() => { }).then(() => {
// TODO - Figure out how to make DOM controller work with callbacks that return a promise or are async // TODO - Figure out how to make DOM controller work with callbacks that return a promise or are async
const userComponentParent = this.el.querySelector(`.${USER_COMPONENT_POPOVER_CONTAINER_CLASS}`); const userComponentParent = this.el.querySelector(`.${USER_COMPONENT_POPOVER_CONTAINER_CLASS}`);

View File

@ -1,5 +1,5 @@
import { Component, Element, Prop, PropDidChange, State } from '@stencil/core'; import { Component, Element, Prop, PropDidChange, State } from '@stencil/core';
import { GestureDetail } from '../../index'; import { DomController, GestureDetail } from '../../index';
import { clamp, reorderArray } from '../../utils/helpers'; import { clamp, reorderArray } from '../../utils/helpers';
import { hapticSelectionChanged, hapticSelectionEnd, hapticSelectionStart} from '../../utils/haptic'; import { hapticSelectionChanged, hapticSelectionEnd, hapticSelectionStart} from '../../utils/haptic';
import { CSS_PROP } from '../animation-controller/constants'; import { CSS_PROP } from '../animation-controller/constants';
@ -45,6 +45,8 @@ export class ReorderGroup {
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ context: 'dom' }) dom: DomController;
@Prop() enabled: boolean = false; @Prop() enabled: boolean = false;
/** /**
@ -54,7 +56,7 @@ export class ReorderGroup {
protected enabledChanged(enabled: boolean) { protected enabledChanged(enabled: boolean) {
if (enabled) { if (enabled) {
this._enabled = true; this._enabled = true;
Context.dom.raf(() => { this.dom.raf(() => {
this._iconVisible = true; this._iconVisible = true;
}); });
} else { } else {

View File

@ -1,6 +1,6 @@
import { Component, Listen, Prop } from '@stencil/core'; import { Component, Listen, Prop } from '@stencil/core';
import { RouterSegments, generateURL, parseURL, readNavState, writeNavState } from './router-utils'; import { RouterSegments, generateURL, parseURL, readNavState, writeNavState } from './router-utils';
import { Config } from '../../index'; import { Config, DomController } from '../../index';
@Component({ @Component({
@ -13,6 +13,7 @@ export class RouterController {
private basePrefix: string = '#'; private basePrefix: string = '#';
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
componentDidLoad() { componentDidLoad() {
const enabled = this.enabled = this.config.getBoolean('useRouter', false); const enabled = this.enabled = this.config.getBoolean('useRouter', false);
@ -25,7 +26,7 @@ export class RouterController {
} }
} }
Context.dom.raf(() => { this.dom.raf(() => {
console.debug('[OUT] page load -> write nav state'); console.debug('[OUT] page load -> write nav state');
this.writeNavStateRoot(); this.writeNavStateRoot();
}); });
@ -45,7 +46,7 @@ export class RouterController {
if (this.isBlocked()) { if (this.isBlocked()) {
return; return;
} }
debugger;
console.debug('[IN] nav changed -> update URL'); console.debug('[IN] nav changed -> update URL');
const { stack, pivot } = this.readNavState(); const { stack, pivot } = this.readNavState();
if (pivot) { if (pivot) {

View File

@ -1,7 +1,9 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop, PropDidChange } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop, PropDidChange } from '@stencil/core';
import { Config, GestureDetail } from '../../index'; import { Config, DomController, GestureDetail } from '../../index';
import { GestureController, GestureDelegate } from '../gesture-controller/gesture-controller'; import { GestureController, GestureDelegate } from '../gesture-controller/gesture-controller';
declare const Ionic: { gesture: GestureController };
@Component({ @Component({
tag: 'ion-scroll' tag: 'ion-scroll'
@ -21,6 +23,9 @@ export class Scroll {
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ context: 'config'}) config: Config; @Prop({ context: 'config'}) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
@Prop({ context: 'isServer' }) isServer: boolean;
@Prop() enabled: boolean = true; @Prop() enabled: boolean = true;
@Prop() jsScroll: boolean = false; @Prop() jsScroll: boolean = false;
@PropDidChange('jsScroll') @PropDidChange('jsScroll')
@ -50,11 +55,11 @@ export class Scroll {
@Event() ionScrollEnd: EventEmitter; @Event() ionScrollEnd: EventEmitter;
componentDidLoad() { componentDidLoad() {
if (Context.isServer) { if (this.isServer) {
return; return;
} }
const gestureCtrl = Context.gesture = Context.gesture || new GestureController; const gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController();
this.gesture = gestureCtrl.createGesture('scroll', 100, false); this.gesture = gestureCtrl.createGesture('scroll', 100, false);
} }
@ -143,7 +148,7 @@ export class Scroll {
if (easedT < 1) { if (easedT < 1) {
// do not use DomController here // do not use DomController here
// must use nativeRaf in order to fire in the next frame // must use nativeRaf in order to fire in the next frame
Context.dom.raf(step); this.dom.raf(step);
} else { } else {
stopScroll = true; stopScroll = true;
@ -157,8 +162,8 @@ export class Scroll {
self.isScrolling = true; self.isScrolling = true;
// chill out for a frame first // chill out for a frame first
Context.dom.write(() => { this.dom.write(() => {
Context.dom.write(timeStamp => { this.dom.write(timeStamp => {
startTime = timeStamp; startTime = timeStamp;
step(timeStamp); step(timeStamp);
}); });
@ -174,7 +179,7 @@ export class Scroll {
if (!this.queued) { if (!this.queued) {
this.queued = true; this.queued = true;
Context.dom.read((timeStamp) => { this.dom.read(timeStamp => {
this.queued = false; this.queued = false;
this.onScroll(timeStamp); this.onScroll(timeStamp);
}); });
@ -249,7 +254,7 @@ export class Scroll {
// haven't scrolled in a while, so it's a scrollend // haven't scrolled in a while, so it's a scrollend
this.isScrolling = false; this.isScrolling = false;
Context.dom.read((timeStamp) => { this.dom.read(timeStamp => {
if (!this.isScrolling) { if (!this.isScrolling) {
this.onEnd(timeStamp); this.onEnd(timeStamp);
} }

View File

@ -1,4 +1,5 @@
import { Component, Element, Listen, Prop, PropDidChange, State } from '@stencil/core'; import { Component, Element, Listen, Prop, PropDidChange, State } from '@stencil/core';
import { DomController } from '../../index';
import { getParentElement } from '../../utils/helpers'; import { getParentElement } from '../../utils/helpers';
@ -12,6 +13,8 @@ export class TabHighlight {
@State() animated = false; @State() animated = false;
@State() transform = ''; @State() transform = '';
@Prop({ context: 'dom' }) dom: DomController;
@Prop() selectedTab: HTMLIonTabElement; @Prop() selectedTab: HTMLIonTabElement;
@PropDidChange('selectedTab') @PropDidChange('selectedTab')
selectedTabChanged() { selectedTabChanged() {
@ -28,7 +31,7 @@ export class TabHighlight {
} }
protected updateTransform() { protected updateTransform() {
Context.dom.read(() => { this.dom.read(() => {
const btn = this.getSelectedButton(); const btn = this.getSelectedButton();
this.transform = (btn) this.transform = (btn)
? `translate3d(${btn.offsetLeft}px,0,0) scaleX(${btn.offsetWidth})` ? `translate3d(${btn.offsetLeft}px,0,0) scaleX(${btn.offsetWidth})`

View File

@ -1,5 +1,5 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, CssClassMap, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, AnimationController, Config, CssClassMap, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme'; import { createThemedClasses } from '../../utils/theme';
@ -60,6 +60,7 @@ export class Toast {
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController;
@Prop() message: string; @Prop() message: string;
@Prop() cssClass: string; @Prop() cssClass: string;
@ -120,7 +121,7 @@ export class Toast {
return playAnimationAsync(animation); return playAnimationAsync(animation);
}).then((animation) => { }).then((animation) => {
animation.destroy(); animation.destroy();
return domControllerAsync(Context.dom.write, () => { return domControllerAsync(this.dom.write, () => {
this.el.parentNode.removeChild(this.el); this.el.parentNode.removeChild(this.el);
}); });
}).then(() => { }).then(() => {

View File

@ -5,6 +5,8 @@ import { createDomControllerClient } from './dom-controller';
const Ionic = (window as any).Ionic = (window as any).Ionic || {}; const Ionic = (window as any).Ionic = (window as any).Ionic || {};
declare const Context: any;
// add dom controller, used to coordinate DOM reads and write in order to avoid // add dom controller, used to coordinate DOM reads and write in order to avoid
// layout thrashing // layout thrashing
if (!Context.dom) { if (!Context.dom) {