Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

siblings direction #620

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 102 additions & 87 deletions packages/dflex-core-instance/src/Element/DFlexCoreElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ export interface DFlexElementInput {
readonly: boolean;
}

function resetDOMStyle(DOM: HTMLElement): void {
DOM.style.removeProperty("transform");

if (!DOM.getAttribute("style")) {
DOM.removeAttribute("style");
}
}

class DFlexCoreElement extends DFlexBaseElement {
private _initialPosition: PointNum;

Expand Down Expand Up @@ -127,23 +135,6 @@ class DFlexCoreElement extends DFlexBaseElement {
this.rect.setByPointAndDimensions(top, left, height, width);
}

private _updateCurrentIndicators(newPos: AxesPoint): void {
this.translate!.increase(newPos);

/**
* This offset related directly to translate Y and Y. It's isolated from
* element current offset and effects only top and left.
*/
this.rect.setAxes(
this._initialPosition.x + this.translate!.x,
this._initialPosition.y + this.translate!.y
);

if (!this.isVisible) {
this.hasPendingTransform = true;
}
}

getDimensions(DOM: HTMLElement): PointNum {
if (this._computedDimensions) {
return this._computedDimensions;
Expand Down Expand Up @@ -185,23 +176,27 @@ class DFlexCoreElement extends DFlexBaseElement {
this.isVisible = isVisible;

if (this.hasPendingTransform && this.isVisible) {
this.transform(DOM);
this._transform(DOM);
this.hasPendingTransform = false;
}
}

transform(DOM: HTMLElement): void {
private _transform(DOM: HTMLElement, cb?: () => void): void {
if (this.animatedFrame !== null) {
cancelAnimationFrame(this.animatedFrame);
}

this.animatedFrame = requestAnimationFrame(() => {
DFlexCoreElement.transform(DOM, this.translate!.x, this.translate!.y);
DFlexCoreElement.transform(DOM, this.translate.x, this.translate.y);

if (this.hasPendingTransform) {
this.hasPendingTransform = false;
}

if (cb) {
cb();
}

this.animatedFrame = null;
});
}
Expand All @@ -211,17 +206,7 @@ class DFlexCoreElement extends DFlexBaseElement {
this.VDOMOrder.self = i;
}

private _updateOrderIndexing(DOM: HTMLElement, i: number) {
const { self: oldIndex } = this.VDOMOrder;

const newIndex = oldIndex + i;

this.updateIndex(DOM, newIndex);

return { oldIndex, newIndex };
}

assignNewPosition(branchIDsOrder: string[], newIndex: number): void {
assignNewIndex(branchIDsOrder: string[], newIndex: number): void {
if (newIndex < 0 || newIndex > branchIDsOrder.length - 1) {
if (__DEV__) {
// eslint-disable-next-line no-console
Expand Down Expand Up @@ -252,7 +237,7 @@ class DFlexCoreElement extends DFlexBaseElement {
branchIDsOrder[newIndex] = this.id;
}

private _leaveToNewPosition(
private _leaveToNewIndex(
branchIDsOrder: string[],
newIndex: number,
oldIndex: number
Expand All @@ -262,40 +247,34 @@ class DFlexCoreElement extends DFlexBaseElement {
branchIDsOrder[newIndex] = this.id;
}

/**
* Set a new translate position and store the old one.
*/
private _seTranslate(
axis: Axes,
DOM: HTMLElement,
elmPos: AxesPoint,
operationID?: string,
hasToFlushTransform = false
): void {
if (operationID) {
const elmAxesHistory: TransitionHistory = {
ID: operationID,
axis,
translate: { x: this.translate!.x, y: this.translate!.y },
};

if (Array.isArray(this._translateHistory)) {
this._translateHistory.push(elmAxesHistory);
} else {
this._translateHistory = [elmAxesHistory];
}
private _pushToTranslateHistory(axis: Axes, operationID: string) {
const translate = this.translate.getInstance();

const elmAxesHistory: TransitionHistory = {
ID: operationID,
axis,
translate,
};

if (!Array.isArray(this._translateHistory)) {
this._translateHistory = [];
}

this._updateCurrentIndicators(elmPos);
this._translateHistory.push(elmAxesHistory);
}

private _transformOrPend(
DOM: HTMLElement,
hasToFlushTransform: boolean
): void {
if (hasToFlushTransform) {
if (!this.isVisible && this.hasPendingTransform) {
this.hasPendingTransform = false;

return;
}

this.transform(DOM);
this._transform(DOM);

return;
}
Expand All @@ -306,7 +285,35 @@ class DFlexCoreElement extends DFlexBaseElement {
return;
}

this.transform(DOM);
this._transform(DOM);
}

private _transformationProcess(
DOM: HTMLElement,
newPos: AxesPoint,
hasToFlushTransform: boolean,
increment: number
) {
this.translate.increase(newPos);

/**
* This offset related directly to translate Y and Y. It's isolated from
* element current offset and effects only top and left.
*/
this.rect.setAxes(
this._initialPosition.x + this.translate.x,
this._initialPosition.y + this.translate.y
);

this._transformOrPend(DOM, hasToFlushTransform);

const { self: oldIndex } = this.VDOMOrder;

const newIndex = oldIndex + increment;

this.updateIndex(DOM, newIndex);

return { oldIndex, newIndex };
}

/**
Expand Down Expand Up @@ -338,10 +345,12 @@ class DFlexCoreElement extends DFlexBaseElement {
elmPos[axis] *= direction;
}

this._seTranslate(axis, DOM, elmPos, operationID);
this._pushToTranslateHistory(axis, operationID);

const { oldIndex, newIndex } = this._updateOrderIndexing(
const { oldIndex, newIndex } = this._transformationProcess(
DOM,
elmPos,
false,
direction * numberOfPassedElm
);

Expand All @@ -352,7 +361,7 @@ class DFlexCoreElement extends DFlexBaseElement {
this.DOMGrid[axis] += direction * numberOfPassedElm;
}

this._leaveToNewPosition(siblings, newIndex, oldIndex);
this._leaveToNewIndex(siblings, newIndex, oldIndex);

if (__DEV__) {
if (featureFlags.enablePositionAssertion) {
Expand All @@ -365,40 +374,40 @@ class DFlexCoreElement extends DFlexBaseElement {
}
}

hasTransformed(): boolean {
return (
Array.isArray(this._translateHistory) && this._translateHistory.length > 0
);
}
restorePosition(DOM: HTMLElement): void {
this._transform(DOM);

hasTransformedFromOrigin(): boolean {
return this._initialPosition.isNotEqual(this.rect.left, this.rect.top);
this.setAttribute(DOM, "INDEX", this.VDOMOrder.self);
}

needDOMReconciliation(): boolean {
return this.VDOMOrder.self !== this.DOMOrder.self;
assignNewPosition(DOM: HTMLElement, t: PointNum): void {
this.translate.clone(t);
this._transform(DOM);
}

/**
* Roll back element position.
*
* @param cycleID
*/
rollBack(DOM: HTMLElement, cycleID: string): void {
if (
!this.hasTransformed() ||
this._translateHistory![this._translateHistory!.length - 1].ID !== cycleID
) {
rollBackPosition(DOM: HTMLElement, cycleID: string): void {
if (!Array.isArray(this._translateHistory)) {
return;
}

const lastMovement = this._translateHistory!.pop()!;
const { length } = this._translateHistory;

const stillInSameCycle = this._translateHistory[length - 1].ID === cycleID;

if (!stillInSameCycle) {
return;
}

const { translate: preTranslate, axis } = lastMovement;
const { translate: preTranslate, axis } = this._translateHistory.pop()!;

const elmPos = {
x: preTranslate.x - this.translate!.x,
y: preTranslate.y - this.translate!.y,
x: preTranslate.x - this.translate.x,
y: preTranslate.y - this.translate.y,
};

let increment = 0;
Expand All @@ -413,12 +422,22 @@ class DFlexCoreElement extends DFlexBaseElement {
this.DOMGrid[axis] += increment;
}

// Don't update UI if it's zero and wasn't transformed.
this._seTranslate(axis, DOM, elmPos, undefined, true);
this._transformationProcess(DOM, elmPos, true, increment);

this._updateOrderIndexing(DOM, increment);
if (this._translateHistory.length === 0) {
this._translateHistory = undefined;
return;
}

this.rollBack(DOM, cycleID);
this.rollBackPosition(DOM, cycleID);
}

hasTransformedFromOrigin(): boolean {
return this._initialPosition.isNotEqual(this.rect.left, this.rect.top);
}

needDOMReconciliation(): boolean {
return this.VDOMOrder.self !== this.DOMOrder.self;
}

refreshIndicators(DOM: HTMLElement): void {
Expand All @@ -430,11 +449,7 @@ class DFlexCoreElement extends DFlexBaseElement {

this.DOMOrder.self = this.VDOMOrder.self;

DOM.style.removeProperty("transform");

if (!DOM.getAttribute("style")) {
DOM.removeAttribute("style");
}
resetDOMStyle(DOM);

this.initElmRect(DOM);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ test.describe("Stream incremental element then transform mutate and check the ne
});

test("Siblings have the correct order in DOM", async () => {
const idsA = [];
const idsB = [];
const idsA: string[] = [];
const idsB: string[] = [];

for (let i = 1; i < 5; i += 1) {
idsA.push(`a-${i}`);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
test,
Page,
Locator,
BrowserContext,
Browser,
expect,
} from "@playwright/test";

import {
assertDefaultChildrenIndex,
getDraggedRect,
initialize,
moveDragged,
} from "../utils";

test.describe("Stream incremental element then transform mutate and check the new positions", async () => {
let page: Page;
let context: BrowserContext;
let activeBrowser: Browser;

let elmGrandParent: Locator;

let elmP1: Locator;
let elmP2: Locator;
let elmP3: Locator;

test.beforeAll(async ({ browser, browserName, baseURL }) => {
activeBrowser = browser;

context = await activeBrowser.newContext();
page = await context.newPage();
initialize(page, browserName);
await page.goto(baseURL!);

[elmGrandParent, elmP1, elmP2, elmP3] = await Promise.all([
page.locator("#dflex_id_0"),
page.locator("#id-p1"),
page.locator("#id-p2"),
page.locator("#id-p3"),
]);
});

test.afterAll(async () => {
await page.close();
await context.close();
// await activeBrowser.close();
});

test("Siblings index initiated correctly at depth: 1", async () => {
await assertDefaultChildrenIndex(elmGrandParent);
});

test("Transforms element (#id-p3) to the left", async () => {
await getDraggedRect(elmP3);
await moveDragged(-230, -1);
await page.dispatchEvent("#id-p3", "mouseup", {
button: 0,
force: true,
});
});
});
Loading