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

fix: support resizing widgets in rtl #7803

Merged
merged 1 commit into from
Sep 16, 2024
Merged
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
6 changes: 5 additions & 1 deletion packages/dashboard/src/vaadin-dashboard-widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class DashboardWidget extends ControllerMixin(ElementMixin(PolylitMixin(LitEleme
display: var(--_vaadin-dashboard-widget-actions-display, none);
position: absolute;
bottom: 0;
right: 0;
inset-inline-end: 0;
font-size: 30px;
cursor: grab;
line-height: 1;
Expand All @@ -64,6 +64,10 @@ class DashboardWidget extends ControllerMixin(ElementMixin(PolylitMixin(LitEleme
content: '\\2921';
}
:host([dir='rtl']) #resize-handle::before {
content: '\\2922';
}
:host::after {
content: '';
z-index: 2;
Expand Down
2 changes: 1 addition & 1 deletion packages/dashboard/src/widget-resize-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class WidgetResizeController extends EventTarget {
return;
}

this.__resizeWidth = this.__resizeStartWidth + e.detail.dx;
this.__resizeWidth = this.__resizeStartWidth + (document.dir === 'rtl' ? -e.detail.dx : e.detail.dx);
this.__resizeHeight = this.__resizeStartHeight + e.detail.dy;
this.__updateWidgetStyles();

Expand Down
135 changes: 69 additions & 66 deletions packages/dashboard/test/dashboard-widget-resizing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import '../vaadin-dashboard.js';
import { isSafari } from '@vaadin/component-base/src/browser-utils.js';
import type { Dashboard, DashboardItem } from '../vaadin-dashboard.js';
import {
describeBidirectional,
expectLayout,
fireResizeEnd,
fireResizeOver,
Expand Down Expand Up @@ -51,89 +52,91 @@ describe('dashboard - widget resizing', () => {
});

describe('mouse drag', () => {
it('should resize a widget while dragging (start -> end)', async () => {
// Start dragging the first widget resize handle
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();
describeBidirectional('horizontal', () => {
it('should resize a widget while dragging (start -> end)', async () => {
// Start dragging the first widget resize handle
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();

// Drag over the end edge of the second one
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'end');
await nextFrame();
// Drag over the end edge of the second one
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'end');
await nextFrame();

fireResizeEnd(dashboard);
await nextFrame();
fireResizeEnd(dashboard);
await nextFrame();

// Expect the widgets to be reordered
// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);
});
// Expect the widgets to be reordered
// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);
});

it('should not resize if dragged barely over another widget (start -> end)', async () => {
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();
it('should not resize if dragged barely over another widget (start -> end)', async () => {
fireResizeStart(getElementFromCell(dashboard, 0, 0)!);
await nextFrame();

fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'start');
await nextFrame();
fireResizeOver(getElementFromCell(dashboard, 0, 1)!, 'start');
await nextFrame();

fireResizeEnd(dashboard);
await nextFrame();
fireResizeEnd(dashboard);
await nextFrame();

// prettier-ignore
expectLayout(dashboard, [
[0, 1],
]);
});
// prettier-ignore
expectLayout(dashboard, [
[0, 1],
]);
});

it('should resize a widget while dragging (end -> start)', async () => {
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
await nextFrame();
// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);
it('should resize a widget while dragging (end -> start)', async () => {
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
await nextFrame();
// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);

fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
await nextFrame();
fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
await nextFrame();

fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'start');
await nextFrame();
fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'start');
await nextFrame();

fireResizeEnd(dashboard);
await nextFrame();
fireResizeEnd(dashboard);
await nextFrame();

// prettier-ignore
expectLayout(dashboard, [
[0, 1],
]);
});
// prettier-ignore
expectLayout(dashboard, [
[0, 1],
]);
});

it('should not resize if dragged barely over another widget (end -> start)', async () => {
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
await nextFrame();
// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);
it('should not resize if dragged barely over another widget (end -> start)', async () => {
dashboard.items = [{ id: 0, colspan: 2 }, { id: 1 }];
await nextFrame();
// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);

fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
await nextFrame();
fireResizeStart(getElementFromCell(dashboard, 0, 1)!);
await nextFrame();

fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'end');
await nextFrame();
fireResizeOver(getElementFromCell(dashboard, 0, 0)!, 'end');
await nextFrame();

fireResizeEnd(dashboard);
await nextFrame();
fireResizeEnd(dashboard);
await nextFrame();

// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);
// prettier-ignore
expectLayout(dashboard, [
[0, 0],
[1],
]);
});
});

it('should resize a widget while dragging (top -> bottom)', async () => {
Expand Down
23 changes: 20 additions & 3 deletions packages/dashboard/test/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ function _getRowHeights(dashboard: Element): number[] {
}

function _getElementFromCell(dashboard: HTMLElement, rowIndex: number, columnIndex: number, rowHeights: number[]) {
const { top, left } = dashboard.getBoundingClientRect();
const { top, left, right } = dashboard.getBoundingClientRect();
const columnWidths = getColumnWidths(dashboard);
const x = left + columnWidths.slice(0, columnIndex).reduce((sum, width) => sum + width, 0);
const columnOffset = columnWidths.slice(0, columnIndex).reduce((sum, width) => sum + width, 0);
const rtl = document.dir === 'rtl';
const x = rtl ? right - columnOffset : left + columnOffset;
const y = top + rowHeights.slice(0, rowIndex).reduce((sum, height) => sum + height, 0);

return document
.elementsFromPoint(x + columnWidths[columnIndex] / 2, y + rowHeights[rowIndex] - 1)
.elementsFromPoint(x + (columnWidths[columnIndex] / 2) * (rtl ? -1 : 1), y + rowHeights[rowIndex] - 1)
.reverse()
.find(
(element) =>
Expand Down Expand Up @@ -279,3 +281,18 @@ export function fireResizeEnd(dragOverTarget: Element): void {
export function getRemoveButton(section: DashboardWidget | DashboardSection): HTMLElement {
return section.shadowRoot!.querySelector('#remove-button') as HTMLElement;
}

export function describeBidirectional(name: string, tests: () => void): void {
describe(name, tests);
describe(`${name} (RTL)`, () => {
before(() => {
document.dir = 'rtl';
});

after(() => {
document.dir = 'ltr'; // Reset to default after tests
});

tests();
});
}
Loading