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
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,40 @@ export const ResourcesColumnLayout: Story = {
},
};

export const CustomItemBeforeMainGroup: Story = {
args: {
...baseConfig,
resources,
},
argTypes: iconsShowModeArgType,
render: (args) => {
return (
<Scheduler
{...baseConfig}
resources={resources}
editing={{
form: {
items: [
{
name: "customNotice",
template: () => {
const element = document.createElement("div");
element.className = "custom-form-notice";
element.textContent = "This is a custom element placed before mainGroup. The slide animation should not overlap this area.";
return element;
},
},
"mainGroup",
"recurrenceGroup",
],
iconsShowMode: args["editing.form.iconsShowMode"],
},
} as Properties["editing"]}
/>
);
},
};

export const RTL: Story = {
args: {
...baseConfig,
Expand Down
10 changes: 10 additions & 0 deletions apps/react-storybook/stories/scheduler/form-customization.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,13 @@
.scheduler-form-custom-icon-button * {
padding: 0 !important;
}

.custom-form-notice {
background: #fce4e4;
border: 1px solid #e0a0a0;
border-radius: 4px;
padding: 8px 12px;
color: #8b3a3a;
font-size: 13px;
line-height: 1.4;
}
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ $scheduler-appointment-form-label-padding: 20px;
&.dx-scheduler-form-main-group-hidden {
transform: translateX(-110%);
position: absolute;
top: 0;
top: var(--dx-scheduler-animation-top, 0);
}
}

Expand All @@ -499,7 +499,7 @@ $scheduler-appointment-form-label-padding: 20px;
&.dx-scheduler-form-recurrence-group-hidden {
transform: translateX(110%);
position: absolute;
top: 0;
top: var(--dx-scheduler-animation-top, 0);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import DOMComponent from '@ts/core/widget/dom_component';

import SchedulerWorkSpace from '../../workspaces/m_work_space';

type ClassRects = Record<string, Partial<DOMRect>>;

interface SetupSchedulerTestEnvironmentOptions {
width?: number;
height?: number;
classRects?: ClassRects;
}

export const DEFAULT_CELL_WIDTH = 250;
Expand All @@ -16,6 +19,7 @@ export const DEFAULT_TIMELINE_CELL_HEIGHT = 450;
export const setupSchedulerTestEnvironment = ({
width = DEFAULT_CELL_WIDTH,
height = DEFAULT_CELL_HEIGHT,
classRects = {},
}: SetupSchedulerTestEnvironmentOptions = {}): void => {
jest.spyOn(logger, 'warn').mockImplementation(() => {});
DOMComponent.prototype._isVisible = jest.fn((): boolean => true);
Expand All @@ -42,34 +46,28 @@ export const setupSchedulerTestEnvironment = ({
return styles;
});

const defaultRect: DOMRect = {
width: 0, height: 0, top: 0, left: 0, bottom: 0, right: 0, x: 0, y: 0, toJSON: (): void => {},
};

const cellRect = {
width, height, bottom: height, right: width,
};

const mergedRects: ClassRects = {
'dx-scheduler-date-table-cell': cellRect,
'dx-scheduler-all-day-table-cell': cellRect,
...classRects,
};

Element.prototype.getBoundingClientRect = jest.fn(function (): DOMRect {
const classList: string[] = Array.from(this.classList);
switch (true) {
case classList.includes('dx-scheduler-date-table-cell')
|| classList.includes('dx-scheduler-all-day-table-cell'):
return {
width,
height,
top: 0,
left: 0,
bottom: height,
right: width,
x: 0,
y: 0,
toJSON: (): void => {},
};
default:
return {
width: 0,
height: 0,
top: 0,
left: 0,
bottom: 0,
right: 0,
x: 0,
y: 0,
toJSON: (): void => {},
};

const matchedClass = classList.find((className) => mergedRects[className]);
if (matchedClass) {
return { ...defaultRect, ...mergedRects[matchedClass] };
}

return defaultRect;
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -1594,6 +1594,24 @@ describe('Appointment Form', () => {
expect(document.activeElement).toBe(frequencyEditorInputElement);
});
});

it('should set animation offset CSS variable when switching to recurrence form', async () => {
setupSchedulerTestEnvironment({
height: 600,
classRects: {
'dx-form': { top: 10 },
'dx-scheduler-form-main-group': { top: 60 },
},
});

const { scheduler, POM } = await createScheduler(getDefaultConfig());

scheduler.showAppointmentPopup();
POM.popup.selectRepeatValue('weekly');

const animationTop = POM.popup.dxForm.$element()[0].style.getPropertyValue('--dx-scheduler-animation-top');
expect(animationTop).toBe('50px');
});
});

describe('firstDayOfWeek', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,8 @@ export class AppointmentForm {
repeatEditor.close();
}

this.updateAnimationOffset();

const currentHeight = this.dxPopup.option('height') as string | number | undefined;
Comment thread
aleksei-semikozov marked this conversation as resolved.

if (currentHeight === 'auto' || currentHeight === undefined) {
Expand Down Expand Up @@ -1065,6 +1067,19 @@ export class AppointmentForm {
this.dxForm.endUpdate();
}

private updateAnimationOffset(): void {
if (!this._$mainGroup) {
return;
}

const formElement = this.dxForm.$element()[0];
const mainGroupElement = this._$mainGroup[0];
Comment thread
aleksei-semikozov marked this conversation as resolved.
const formRect = formElement.getBoundingClientRect();
const groupRect = mainGroupElement.getBoundingClientRect();
const topOffset = groupRect.top - formRect.top;
formElement.style.setProperty('--dx-scheduler-animation-top', `${topOffset}px`);
}

private focusFirstFocusableInGroup($group: dxElementWrapper): void {
const focusTarget = $group.find(`.${CLASSES.fieldItemContent} [tabindex]`).first().get(0) as HTMLElement;
focusTarget?.focus({ preventScroll: true });
Expand Down
Loading