refactor(components): update to use shadow DOM and work with css variables

- updates components to use shadow DOM or scoped if they require css variables
- moves global styles to an external stylesheet that needs to be imported
- adds support for additional colors and removes the Sass loops to generate colors for each component
- several property renames, bug fixes, and test updates

Co-authored-by: Manu Mtz.-Almeida <manu.mtza@gmail.com>
Co-authored-by: Adam Bradley <adambradley25@gmail.com>
Co-authored-by: Cam Wiegert <cam@camwiegert.com>
This commit is contained in:
Brandy Carney
2018-07-09 12:57:21 -04:00
parent a4659f03b4
commit a7f1f4daa7
710 changed files with 20999 additions and 20853 deletions

View File

@ -1,8 +1,10 @@
import { Component, Element, EventListenerEnable, Listen, Method, Prop, Watch } from '@stencil/core';
import { QueueController } from '../../interface';
import { Cell, CellType, DomRenderFn, HeaderFn, ItemHeightFn,
ItemRenderFn, Range,
VirtualNode, calcCells, calcHeightIndex, doRender,
import { Component, Element, EventListenerEnable, Listen, Method, Prop, QueueApi, State, Watch } from '@stencil/core';
import { Cell, DomRenderFn, HeaderFn, ItemHeightFn, ItemRenderFn, VirtualNode } from '../../interface';
import { CellType } from './virtual-scroll-interface';
import {
Range,
calcCells, calcHeightIndex, doRender,
findCellIndex, getRange, getShouldUpdate, getViewport,
inplaceUpdate, positionForIndex, resizeBuffer, updateVDom } from './virtual-scroll-utils';
@ -24,13 +26,13 @@ export class VirtualScroll {
private viewportOffset = 0;
private currentScrollTop = 0;
private indexDirty = 0;
private totalHeight = 0;
private heightChanged = false;
private lastItemLen = 0;
@Element() el!: HTMLStencilElement;
@Prop({ context: 'queue' }) queue!: QueueController;
@State() totalHeight = 0;
@Prop({ context: 'queue' }) queue!: QueueApi;
@Prop({ context: 'enableListener' }) enableListener!: EventListenerEnable;
@Prop({ context: 'window' }) win!: Window;
@ -116,13 +118,13 @@ export class VirtualScroll {
}
componentDidLoad() {
const scrollEl = this.el.closest('ion-scroll');
if (!scrollEl) {
const contentEl = this.el.closest('ion-content');
if (!contentEl) {
console.error('virtual-scroll must be used inside ion-scroll/ion-content');
return;
}
this.scrollEl = scrollEl;
scrollEl.componentOnReady().then(() => {
contentEl.componentOnReady().then(() => {
this.scrollEl = contentEl.getScrollElement();
this.calcDimensions();
this.calcCells();
this.updateState();
@ -204,29 +206,33 @@ export class VirtualScroll {
}
private updateVirtualScroll() {
// do nothing if there is a scheduled update
// do nothing if virtual-scroll is disabled
if (!this.isEnabled || !this.scrollEl) {
return;
}
// unschedule future updates
if (this.timerUpdate) {
clearTimeout(this.timerUpdate);
this.timerUpdate = null;
}
// schedule DOM operations into the stencil queue
this.queue.read(this.readVS.bind(this));
this.queue.write(this.writeVS.bind(this));
}
private readVS() {
const { scrollEl, el } = this;
let topOffset = 0;
let node: HTMLElement | null = this.el;
while (node && node !== this.scrollEl) {
let node: HTMLElement | null = el;
while (node && node !== scrollEl) {
topOffset += node.offsetTop;
node = node.parentElement;
}
this.viewportOffset = topOffset;
if (this.scrollEl) {
this.currentScrollTop = this.scrollEl.scrollTop;
if (scrollEl) {
this.currentScrollTop = scrollEl.scrollTop;
}
}
@ -258,7 +264,8 @@ export class VirtualScroll {
range
);
// write DOM
// Write DOM
// Different code paths taken depending of the render API used
if (this.nodeRender) {
doRender(this.el, this.nodeRender, this.virtualDom, this.updateCellHeight.bind(this));
} else if (this.domRender) {
@ -266,13 +273,9 @@ export class VirtualScroll {
} else if (this.renderItem) {
this.el.forceUpdate();
}
if (this.heightChanged) {
this.el.style.height = this.totalHeight + 'px';
this.heightChanged = false;
}
}
private updateCellHeight(cell: Cell, node: HTMLStencilElement | HTMLElement) {
private updateCellHeight(cell: Cell, node: HTMLElement) {
const update = () => {
if ((node as any)['$ionCell'] === cell) {
const style = this.win.getComputedStyle(node);
@ -351,12 +354,8 @@ export class VirtualScroll {
private calcHeightIndex(index = 0) {
// TODO: optimize, we don't need to calculate all the cells
this.heightIndex = resizeBuffer(this.heightIndex, this.cells.length);
const totalHeight = calcHeightIndex(this.heightIndex, this.cells, index);
if (totalHeight !== this.totalHeight) {
console.debug(`[virtual] total height changed: ${this.totalHeight}px -> ${totalHeight}px`);
this.totalHeight = totalHeight;
this.heightChanged = true;
}
this.totalHeight = calcHeightIndex(this.heightIndex, this.cells, index);
console.debug('[virtual] height index recalculated', this.heightIndex.length - index);
this.indexDirty = Infinity;
}
@ -374,15 +373,23 @@ export class VirtualScroll {
}
}
renderVirtualNode(node: VirtualNode) {
const cell = node.cell;
switch (cell.type) {
case CellType.Item: return this.renderItem!(cell.value, cell.index);
case CellType.Header: return this.renderHeader!(cell.value, cell.index);
case CellType.Footer: return this.renderFooter!(cell.value, cell.index);
private renderVirtualNode(node: VirtualNode) {
const { type, value, index } = node.cell;
switch (type) {
case CellType.Item: return this.renderItem!(value, index);
case CellType.Header: return this.renderHeader!(value, index);
case CellType.Footer: return this.renderFooter!(value, index);
}
}
hostData() {
return {
style: {
height: `${this.totalHeight}px`
}
};
}
render() {
const renderItem = this.renderItem;
if (renderItem) {
@ -392,11 +399,10 @@ export class VirtualScroll {
if (!item.vattrs) {
item.vattrs = {};
}
item.vattrs.class += ' virtual-item';
if (!node.visible) {
classes.push('virtual-loading');
}
item.vattrs.class += ' ' + classes.join(' ');
item.vattrs.class += classes.join(' ');
if (!item.vattrs.style) {
item.vattrs.style = {};
}