Skip to content

Commit 386791f

Browse files
committed
feat: pointerdownPosition service, used in drawer and slider
1 parent 414910f commit 386791f

File tree

8 files changed

+265
-332
lines changed

8 files changed

+265
-332
lines changed

angular/bootstrap/src/components/drawer/drawer.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ export class DrawerComponent extends BaseWidgetDirective<DrawerWidget> {
224224
readonly resizable = input(undefined, {alias: 'auResizable', transform: auBooleanAttribute});
225225

226226
/**
227-
* An event emitted when the drawer size (width or height depending on the orientation).
227+
* An event emitted when the drawer size changes (width or height depending on the orientation).
228228
*
229229
* Event payload is equal to the newly selected width or height.
230230
*
@@ -268,7 +268,7 @@ export class DrawerComponent extends BaseWidgetDirective<DrawerWidget> {
268268
readonly maximizedChange = output<boolean>({alias: 'auMaximizedChange'});
269269

270270
/**
271-
* Event to be triggered when the user start or stop resizing the drawer.
271+
* Event to be triggered when the user starts or stops resizing the drawer.
272272
*
273273
* @defaultValue
274274
* ```ts

core-bootstrap/src/scss/slider.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
}
172172

173173
.au-slider-handle {
174+
touch-action: none;
174175
background-color: var(--#{variables.$prefix}slider-handle-color);
175176
border: var(--#{variables.$prefix}slider-handle-border);
176177
border-radius: var(--#{variables.$prefix}slider-handle-border-radius);

core/src/components/components.spec-utils.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,19 @@ export function getAttributes(node: HTMLElement) {
2222
* @param args - the args of the directive
2323
* @param sendEvent - the event dispatcher function
2424
* @param nodeType - the type of the DOM element to create
25-
* @param destroyAfterEvent - automatically destroy the directive after use
26-
* @returns the element and the destroy reference
2725
*/
2826
export function attachDirectiveAndSendEvent<T = void>(
2927
directive: Directive<T>,
3028
args: T,
3129
sendEvent: (node: HTMLElement) => void,
3230
nodeType: string = 'div',
33-
destroyAfterEvent = true,
34-
): {element: HTMLElement; destroy: void | {destroy?: () => void}} {
31+
) {
3532
const element = document.createElement(nodeType);
33+
document.body.appendChild(element);
3634
const destroy = directive(element, args);
3735
sendEvent(element);
38-
if (destroyAfterEvent) {
39-
destroy?.destroy?.();
40-
}
41-
return {
42-
element,
43-
destroy,
44-
};
36+
destroy?.destroy?.();
37+
element.remove();
4538
}
4639

4740
/**

core/src/components/drawer/drawer.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ export interface DrawerProps extends DrawerCommonPropsAndState {
152152
*/
153153
onShown: () => void;
154154
/**
155-
* An event emitted when the drawer size (width or height depending on the orientation).
155+
* An event emitted when the drawer size changes (width or height depending on the orientation).
156156
*
157157
* Event payload is equal to the newly selected width or height.
158158
*
@@ -192,7 +192,7 @@ export interface DrawerProps extends DrawerCommonPropsAndState {
192192
*/
193193
onMaximizedChange: (isMaximized: boolean) => void;
194194
/**
195-
* Event to be triggered when the user start or stop resizing the drawer.
195+
* Event to be triggered when the user starts or stops resizing the drawer.
196196
*
197197
* @defaultValue
198198
* ```ts
@@ -445,9 +445,8 @@ export const createDrawer: WidgetFactory<DrawerWidget> = createWidgetFactory('dr
445445
},
446446
}));
447447

448-
const direction = computed(() => (['inline-start', 'block-start'].some((placement) => className$().includes(placement)) ? 1 : -1));
448+
const direction$ = computed(() => (['inline-start', 'block-start'].some((placement) => className$().includes(placement)) ? 1 : -1));
449449

450-
let startSize = 0;
451450
const isMinimized$ = writable(<boolean | undefined>undefined);
452451
const isMaximized$ = writable(<boolean | undefined>undefined);
453452

@@ -465,23 +464,24 @@ export const createDrawer: WidgetFactory<DrawerWidget> = createWidgetFactory('dr
465464
}
466465

467466
const splitterDirective = mergeDirectives(
468-
createPointerdownPositionDirective({
469-
onMoveStart() {
470-
const isVertical = isVertical$();
471-
startSize = drawerElement$()![isVertical ? 'offsetHeight' : 'offsetWidth'];
472-
onResizingChange$()(true);
473-
},
474-
onMove(position) {
475-
setSize(startSize + direction() * position[isVertical$() ? 'dy' : 'dx']);
476-
},
477-
onMoveEnd() {
478-
const isVertical = isVertical$();
479-
const drawerElement = drawerElement$()!;
480-
const newSize = drawerElement[isVertical ? 'offsetHeight' : 'offsetWidth'];
481-
drawerElement.style[isVertical ? 'height' : 'width'] = '';
482-
size$.set(newSize);
483-
onResizingChange$()(false);
484-
},
467+
createPointerdownPositionDirective((event) => {
468+
const drawerElement = drawerElement$()!;
469+
const isVertical = isVertical$();
470+
const startSize = drawerElement[isVertical ? 'offsetHeight' : 'offsetWidth'];
471+
const clientXorY = isVertical ? 'clientY' : 'clientX';
472+
const startPos = event[clientXorY];
473+
const direction = direction$();
474+
onResizingChange$()(true);
475+
476+
return {
477+
onMove(event) {
478+
setSize(startSize + direction * (event[clientXorY] - startPos));
479+
},
480+
onEnd() {
481+
drawerElement.style[isVertical ? 'height' : 'width'] = '';
482+
onResizingChange$()(false);
483+
},
484+
};
485485
}),
486486
createAttributesDirective(() => ({
487487
events: {

core/src/components/slider/slider.spec.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ function keyboardEvent(key: string): KeyboardEvent {
2727
return new KeyboardEvent('keydown', {key});
2828
}
2929

30+
function pointerEvent(type: 'pointerdown' | 'pointerup', pointerType: 'mouse' | 'touch', clientX: number): PointerEvent {
31+
return new PointerEvent(type, {
32+
pointerId: 1,
33+
clientX,
34+
clientY: 0,
35+
pointerType,
36+
isPrimary: true,
37+
bubbles: true,
38+
cancelable: true,
39+
});
40+
}
41+
3042
const defaultHandle: SliderHandle = {id: 0, value: 0, ariaLabel: 'Value', ariaValueText: undefined, ariaLabelledBy: undefined};
3143

3244
const defaultState: () => SliderState = () => ({
@@ -83,15 +95,17 @@ describe(`Slider basic`, () => {
8395
let defConfig: WritableSignal<Partial<SliderProps>>;
8496

8597
const clickAreaX = (clientX: number) => {
86-
attachDirectiveAndSendEvent(slider.directives.clickableAreaDirective, undefined, (node) =>
87-
node.dispatchEvent(new MouseEvent('mousedown', {clientX})),
88-
);
98+
attachDirectiveAndSendEvent(slider.directives.clickableAreaDirective, undefined, (node) => {
99+
node.dispatchEvent(pointerEvent('pointerdown', 'mouse', clientX));
100+
node.dispatchEvent(pointerEvent('pointerup', 'mouse', clientX));
101+
});
89102
};
90103

91104
const touchAreaX = (clientX: number) => {
92-
attachDirectiveAndSendEvent(slider.directives.clickableAreaDirective, undefined, (node) =>
93-
node.dispatchEvent(new TouchEvent('touchstart', {touches: [new Touch({clientX, identifier: 0, target: new EventTarget()})]})),
94-
);
105+
attachDirectiveAndSendEvent(slider.directives.clickableAreaDirective, undefined, (node) => {
106+
node.dispatchEvent(pointerEvent('pointerdown', 'touch', clientX));
107+
node.dispatchEvent(pointerEvent('pointerup', 'touch', clientX));
108+
});
95109
};
96110
const useKeyOnHandle = (key: string) => {
97111
attachDirectiveAndSendEvent(slider.directives.handleEventsDirective, {item: {id: 0}}, (node) => node.dispatchEvent(keyboardEvent(key)));
@@ -1790,9 +1804,10 @@ describe(`Slider range`, () => {
17901804
let defConfig: WritableSignal<Partial<SliderProps>>;
17911805
let currentLowLabel: HTMLDivElement, currentHighLabel: HTMLDivElement, combinedLabel: HTMLDivElement;
17921806
const clickAreaX = (clientX: number) => {
1793-
attachDirectiveAndSendEvent(slider.directives.clickableAreaDirective, undefined, (node) =>
1794-
node.dispatchEvent(new MouseEvent('mousedown', {clientX})),
1795-
);
1807+
attachDirectiveAndSendEvent(slider.directives.clickableAreaDirective, undefined, (node) => {
1808+
node.dispatchEvent(pointerEvent('pointerdown', 'mouse', clientX));
1809+
node.dispatchEvent(pointerEvent('pointerup', 'mouse', clientX));
1810+
});
17961811
};
17971812
const useKeyOnHandle = (key: string, handleId = 0) => {
17981813
attachDirectiveAndSendEvent(slider.directives.handleEventsDirective, {item: {id: handleId}}, (node) => node.dispatchEvent(keyboardEvent(key)));

0 commit comments

Comments
 (0)