Skip to content
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
55 changes: 31 additions & 24 deletions packages/devextreme/js/__internal/ui/toolbar/toolbar.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import { BindableTemplate } from '@js/core/templates/bindable_template';
import { each } from '@js/core/utils/iterator';
import { getBoundingRect } from '@js/core/utils/position';
import { getHeight, getOuterWidth, getWidth } from '@js/core/utils/size';
import { isDefined, isPlainObject } from '@js/core/utils/type';
import {
Expand Down Expand Up @@ -47,8 +46,8 @@ export interface ToolbarBaseProperties<
TKey extends CollectionItemKey = CollectionItemKey,
> extends Properties<TItem, TKey>,
Omit<
CollectionWidgetBaseProperties<ToolbarBase, TItem, TKey>,
keyof Properties<TItem, TKey> & keyof CollectionWidgetBaseProperties<ToolbarBase, TItem, TKey>
CollectionWidgetBaseProperties<ToolbarBase, TItem, TKey>,
keyof Properties<TItem, TKey> & keyof CollectionWidgetBaseProperties<ToolbarBase, TItem, TKey>
> {
grouped: boolean;
renderAs: 'topToolbar';
Expand All @@ -68,7 +67,6 @@ class ToolbarBase<

_$afterSection!: dxElementWrapper;

// eslint-disable-next-line no-restricted-globals
_waitParentAnimationTimeout?: ReturnType<typeof setTimeout>;

_getSynchronizableOptionsForCreateComponent(): (keyof TProperties)[] {
Expand Down Expand Up @@ -230,10 +228,10 @@ class ToolbarBase<
float: 'none',
});

const beforeRect = getBoundingRect(this._$beforeSection?.get(0));
const afterRect = getBoundingRect(this._$afterSection?.get(0));
const beforeWidth = getOuterWidth(this._$beforeSection?.get(0)) ?? 0;
const afterWidth = getOuterWidth(this._$afterSection?.get(0)) ?? 0;

this._alignCenterSection(beforeRect, afterRect, elementWidth);
this._alignCenterSection(beforeWidth, afterWidth, elementWidth);

const $label = this._$toolbarItemsContainer.find(`.${TOOLBAR_LABEL_CLASS}`).eq(0);
const $section: dxElementWrapper = $label.parent();
Expand All @@ -242,9 +240,9 @@ class ToolbarBase<
return;
}

const labelOffset = beforeRect.width ? beforeRect.width : $label.position()?.left;
const labelOffset = beforeWidth ?? $label.position()?.left;
const widthBeforeSection = $section.hasClass(TOOLBAR_BEFORE_CLASS) ? 0 : labelOffset;
const widthAfterSection = $section.hasClass(TOOLBAR_AFTER_CLASS) ? 0 : afterRect.width;
const widthAfterSection = $section.hasClass(TOOLBAR_AFTER_CLASS) ? 0 : afterWidth;
let elemsAtSectionWidth = 0;

// @ts-expect-error ts error
Expand All @@ -265,27 +263,35 @@ class ToolbarBase<
}
}

_alignCenterSection(
beforeRect: DOMRect,
afterRect: DOMRect,
elementWidth: number,
): void {
_alignCenterSection(beforeWidth: number, afterWidth: number, elementWidth: number): void {
if (!this._$centerSection) {
return;
}

this._alignSection(this._$centerSection, elementWidth - beforeRect.width - afterRect.width);
this._alignSection(this._$centerSection, elementWidth - beforeWidth - afterWidth);

const isRTL = this.option('rtlEnabled');
const leftRect = isRTL ? afterRect : beforeRect;
const rightRect = isRTL ? beforeRect : afterRect;
const centerRect = getBoundingRect(this._$centerSection.get(0));

if (leftRect.right > centerRect.left || centerRect.right > rightRect.left) {
const leftWidth = isRTL ? afterWidth : beforeWidth;
const rightWidth = isRTL ? beforeWidth : afterWidth;

const centerEl = this._$centerSection.get(0) as HTMLElement;
const centerLeft = centerEl.offsetLeft;
const centerRight = centerLeft + centerEl.offsetWidth;

const beforeEl = this._$beforeSection?.get(0) as HTMLElement | undefined;
const afterEl = this._$afterSection?.get(0) as HTMLElement | undefined;
const leftSectionRight = afterEl ? afterEl.offsetLeft + afterEl.offsetWidth : 0;
const leftSectionRightLTR = beforeEl ? beforeEl.offsetLeft + beforeEl.offsetWidth : 0;
const leftRight = isRTL ? leftSectionRight : leftSectionRightLTR;
const rightLeft = isRTL
? beforeEl?.offsetLeft ?? elementWidth
: afterEl?.offsetLeft ?? elementWidth;

if (leftRight > centerLeft || centerRight > rightLeft) {
this._$centerSection.css({
marginLeft: leftRect.width,
marginRight: rightRect.width,
float: leftRect.width > rightRect.width ? 'none' : 'right',
marginLeft: leftWidth,
marginRight: rightWidth,
float: leftWidth > rightWidth ? 'none' : 'right',
});
}
}
Expand All @@ -312,7 +318,8 @@ class ToolbarBase<
difference: number,
expanding: boolean,
): void {
const getRealLabelWidth = (label: Element): number => (getBoundingRect(label) as DOMRect).width;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
const getRealLabelWidth = (label: Element): number => getOuterWidth(label) ?? 0;

// eslint-disable-next-line @typescript-eslint/prefer-for-of, no-plusplus
for (let i = 0; i < labels.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,35 @@ QUnit.module('render', {
assert.ok(labelWidth <= labelMaxWidth, 'Real label width less or equal to the max width');
});

QUnit.test('label max-width should be calculated correctly when parent has CSS transform scale (T1245421)', function(assert) {
const $container = $('<div>').appendTo('#qunit-fixture').css('width', '400px');
const $element = $('<div>').appendTo($container);

$element.dxToolbar({
items: [
{ location: 'before', text: 'Very long toolbar label text that should be truncated' },
{ location: 'after', widget: 'dxButton', options: { text: 'Action' } }
]
});

const toolbar = $element.dxToolbar('instance');
const $label = $element.find(`.${TOOLBAR_LABEL_CLASS}`).eq(0);
const maxWidthBefore = parseFloat($label.css('max-width'));

$container.css('transform', 'scale(0.5)');
toolbar._dimensionChanged();
const maxWidthDuringScale = parseFloat($label.css('max-width'));

$container.css('transform', '');
toolbar._dimensionChanged();
const maxWidthAfter = parseFloat($label.css('max-width'));

assert.roughEqual(maxWidthDuringScale, maxWidthBefore, 1, 'max-width is not affected by CSS transform scale');
assert.roughEqual(maxWidthAfter, maxWidthBefore, 1, 'max-width is restored correctly after transform is removed');

$container.remove();
});

QUnit.test('items - long labels', function(assert) {
this.$element.dxToolbar({
items: [
Expand Down
Loading