Skip to content

Commit

Permalink
Merge 1f6e2d4 into 3e7f157
Browse files Browse the repository at this point in the history
  • Loading branch information
daybrush committed May 28, 2021
2 parents 3e7f157 + 1f6e2d4 commit 49cd006
Show file tree
Hide file tree
Showing 9 changed files with 595 additions and 40 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,4 @@ dist/
packages/*/dist/
test/e2e/log/
test/e2e/screenshots/diff/
storybook/build/
110 changes: 70 additions & 40 deletions src/InfiniteGrid.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { ContainerManager, GridItem } from "@egjs/grid";
// import { MOUNT_STATE } from "@egjs/grid";
import { Infinite } from "./Infinite";
import { OnRendererUpdated, Renderer } from "./Renderer/Renderer";
import { GridRendererItem } from "./Renderer/VanillaGridRenderer";
import { ScrollManager } from "./ScrollManager";
import { isString } from "./utils";

Expand All @@ -8,6 +11,7 @@ export class InfiniteGrid {
protected scrollManager: ScrollManager;
protected containerManager: ContainerManager;
protected infinite: Infinite;
protected renderer: Renderer;
constructor(wrapper: HTMLElement | string) {
// options.container === false, wrapper = container, scrollContainer = document.body
// options.container === true, wrapper = scrollContainer, container = wrapper's child
Expand All @@ -29,61 +33,37 @@ export class InfiniteGrid {
"requestAppend": this._onRequestAppend,
"requestPrepend": this._onRequestPrepend,
});
const renderer: Renderer = null as any;

renderer.setContainer(scrollManager.getContainer());
renderer.on("updated", this._onRendererUpdated);

this.wrapperElement = wrapperElement;
this.scrollManager = scrollManager;
this.containerManager = containerManager;
this.infinite = infinite;
}
public syncItems() {
// item sync
// const {
// added,
// removed,
// ordered,
// } = this.groupManager.syncItems([]);
// infinite sync
// const prevVisbleItems = this.getVisibleItems();
this.infinite.sync([]);
// const nextVisbleItems = this.getVisibleItems();
// const container = this.scrollManager.getContainer();
// const {
// added,
// ordered,
// removed,
// } = diff(prevVisbleItems, nextVisbleItems, (item) => item.key);
// this.groupManager.syncItems(nextItems);
const groups: any[] = [];

// if (added.length || ordered.length) {
// container.innerHTML = "";
this.infinite.sync(groups.map((item) => {
return {
key: item.key,
startOutline: item.startOutline,
endOutline: item.endOutline,
};
}));

// const fragment = document.createDocumentFragment();
// nextVisbleItems.forEach((item) => {
// if (!item.element) {
// // create element
// }
// fragment.appendChild(item.element!);
// });
// container.appendChild(fragment);
// } else if (removed.length) {
// removed.forEach((index) => {
// const item = nextVisbleItems[index];


// if (item.mountState === MOUNT_STATE.MOUNTED) {
// const element = item.element;

// container.removeChild(element!);
// }
// });
// }
// save sync info
// this.status.isChange = isChange;
this._render();
}

public syncElements() {
return;
}
public setCursors(startCursor: number, endCursor: number) {
this.infinite.setCursors(startCursor, endCursor);
this._update();
}
public getVisibleItems(): GridItem[] {
return [];
Expand All @@ -95,6 +75,20 @@ export class InfiniteGrid {
// // return this.groupManager.getItem(item.key);
// });
}
private _render() {
this.renderer.render(this.getVisibleItems().map((item) => {
return {
element: item.element,
key: item.key,
orgItem: item,
};
}));
}
private _update() {
if (this.renderer.update()) {
this._render();
}
}
private _onChange = () => {
//
}
Expand All @@ -104,4 +98,40 @@ export class InfiniteGrid {
private _onRequestPrepend = () => {
//
}
private _onRendererUpdated = (e: OnRendererUpdated<GridRendererItem>) => {
if (!e.isChanged) {
return;
}
const rendererItems = e.items;

// const {
// added,
// removed,
// prevList,
// list,
// } = e.diffResult;

// removed.forEach((index) => {
// const orgItem = prevList[index].orgItem;

// orgItem.mountState = MOUNT_STATE.UNMOUNTED;
// });
// added.forEach((index) => {
// const orgItem = list[index].orgItem;

// orgItem.mountState = MOUNT_STATE.MOUNTED;
// });

rendererItems.forEach((item) => {
if (item.key === "infinite_unique_loading") {
// set loading element
} else {
// set grid element
// const gridItem = this.groupManager.findItemByKey(item.key);

// gridItem.element = item.element;
}
});
// this.renderItems();
}
}
94 changes: 94 additions & 0 deletions src/Renderer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
## How to use
### Component
```js
import { VanillaRenderer, Renderer } from "@egjs/infinitegrid";

// Use VanillaRenderer or Renderer

// Component
class Component {
constructor(renderer: Renderer) {
this.renderer = renderer;
}
// Sync items and elements
render(items) {
this.renderer.render(items);
}

// Force update if you want to show only part of it internally
update() {
// If true is returned, the update event is not called. (for vanilla)
// If false is returned, the update event is called. (for framework)
if (this.renderer.update()) {
// vanilla
this.render();
}
}

// set renderer container for vanilla
setContainer(container) {
this.renderer.setContainer(container);
}
}

```
### Vanilla
```js
const component = new Component(new VanillaRenderer());

// render item with element
component.render([
{ key: 1, element: element1 },
{ key: 2, element: element2 },
{ key: 3, element: element3 },
]);


component.update();
```

### Framework
```jsx
import * as React from "react";
import { Renderer } from "@egjs/infinitegrid";

class ReactComponent extends React.Component {
containerRef = React.createRef();
render() {
const items = [
{ key: 1 },
{ key: 2 },
{ key: 3 },
];
// render only items
this.component?.render(items);
return <div ref={this.containerRef} onClick={() => {
this.component.update();
}}>
{items.map((item) => (<div key={item.key}>{item.key}</div>))}
</div>;
}
componentDidUpdate() {
// update elements in items
this.renderer.updated(this.containerRef.current!.children);
}
componentDidMount() {
const renderer = new Renderer();
const component = new Component(renderer);

this.renderer = renderer;
this.component = component;

component.render([
{ key: 1 },
{ key: 2 },
{ key: 3 },
]);
renderer.updated(this.containerRef.current!.children);
renderer.on("update", () => {
this.forceUpdate();
});
}
}
```
68 changes: 68 additions & 0 deletions src/Renderer/Renderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import Component from "@egjs/component";
import { diff, DiffResult } from "@egjs/list-differ";

export interface RendererItem {
key: string | number;
element?: Element | null;
}

export interface OnRendererUpdated<T extends RendererItem = RendererItem> {
items: T[];
elements: Element[];
isChanged: boolean;
diffResult: DiffResult<T>;
}

export interface RendererEvents<T extends RendererItem = RendererItem> {
update: void;
updated: OnRendererUpdated<T>;
}

export class Renderer<T extends RendererItem = RendererItem> extends Component<RendererEvents> {
protected items: T[] = [];
protected container: Element | null = null;
private _diffResult: DiffResult<T>;

public getItems() {
return this.items;
}
public setContainer(container: Element) {
this.container = container;
}
public setItems(items: T[]) {
this.items = items;
}
public render(nextItems: T[]) {
return this.syncItems(nextItems);
}
public update() {
this.trigger("update");
return false;
}
public updated(nextElements: ArrayLike<Element>) {
const items = this.items;
const diffResult = this._diffResult;
const isChanged = !!(diffResult.added.length || diffResult.removed.length || diffResult.changed.length);

items.forEach((item, i) => {
item.element = nextElements[i];
});

this.trigger("updated", {
items,
elements: [].slice.call(nextElements),
diffResult: this._diffResult,
isChanged,
});

return isChanged;
}
protected syncItems(nextItems: T[]) {
const result = diff(this.items, nextItems, (item) => item.key);

this._diffResult = result;
this.items = nextItems;

return result;
}
}
29 changes: 29 additions & 0 deletions src/Renderer/VanillaGridRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { GridItem } from "@egjs/grid";
import { RendererItem } from "./Renderer";
import { VanillaRenderer } from "./VanillaRenderer";

export interface GridRendererItem extends RendererItem {
orgItem: GridItem;
}

export class VanillaGridRenderer extends VanillaRenderer<GridRendererItem> {
constructor() {
super();
}
public syncItems(nextItems: GridRendererItem[]) {
const result = super.syncItems(nextItems);
const {
added,
list,
} = result;
added.forEach((index) => {
const orgItem = nextItems[index].orgItem;

// createElement(orgItem.element);

list[index].element = orgItem.element!;
});

return result;
}
}
38 changes: 38 additions & 0 deletions src/Renderer/VanillaRenderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Renderer, RendererItem } from "./Renderer";

export class VanillaRenderer<T extends RendererItem = RendererItem> extends Renderer<T> {
public render(nextItems: T[]) {
const container = this.container!;
const result = this.syncItems(nextItems);
const {
prevList,
removed,
ordered,
added,
} = result;
const diffList = [...prevList];

removed.forEach((index) => {
diffList.splice(index, 1);
container.removeChild(prevList[index].element!);
});
ordered.forEach(([prevIndex, nextIndex]) => {
const item = diffList.splice(prevIndex, 1)[0];

diffList.splice(nextIndex, 0, item);
container.insertBefore(item.element!, diffList[nextIndex + 1]?.element ?? null);
});
added.forEach((index) => {
const item = nextItems[index];

diffList.splice(index, 0, item);
container.insertBefore(item.element!, diffList[index + 1]?.element ?? null);
});

this.updated(container.children);
return result;
}
public update() {
return true;
}
}

0 comments on commit 49cd006

Please sign in to comment.