Skip to content

Commit 2747329

Browse files
fix(types): adapt types of events to reduce the usage of any-type (#4328)
* fix(types): adapt types of events to reduce the usage of any-type * fix(types): use basic event type instead of specific type * chore: update proper typings for components --------- Co-authored-by: Nicolas Merget <[email protected]>
1 parent fc6cf34 commit 2747329

File tree

15 files changed

+192
-92
lines changed

15 files changed

+192
-92
lines changed

packages/components/scripts/post-build/react.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ const overwriteEvents = (tmp?: boolean) => {
2727
'export type InteractionEvent<T> = FocusEvent;',
2828
'export type InteractionEvent<T> = React.FocusEvent<T>;'
2929
);
30+
modelFileContent = modelFileContent.replace(
31+
'export type GeneralEvent<T> = Event;',
32+
'export type GeneralEvent<T> = React.SyntheticEvent<T>;'
33+
);
34+
modelFileContent = modelFileContent.replace(
35+
'export type GeneralKeyboardEvent<T> = KeyboardEvent;',
36+
'export type GeneralKeyboardEvent<T> = React.KeyboardEvent<T>;'
37+
);
3038
writeFileSync(modelFilePath, modelFileContent);
3139
};
3240

packages/components/src/components/accordion-item/accordion-item.lite.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ export default function DBAccordionItem(props: DBAccordionItemProps) {
8080
<details
8181
aria-disabled={getBooleanAsString(props.disabled)}
8282
ref={_ref}
83-
/* @ts-expect-error This is a new api for details */
8483
name={state._name}
8584
open={state._open}>
8685
<summary onClick={(event) => state.handleToggle(event)}>

packages/components/src/components/custom-select/custom-select.lite.tsx

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ import {
4242
DEFAULT_VALID_MESSAGE,
4343
DEFAULT_VALID_MESSAGE_ID_SUFFIX
4444
} from '../../shared/constants';
45-
import { ChangeEvent, ClickEvent } from '../../shared/model';
45+
import {
46+
ClickEvent,
47+
GeneralEvent,
48+
InputEvent,
49+
InteractionEvent
50+
} from '../../shared/model';
4651
import DBCustomSelectList from '../custom-select-list/custom-select-list.lite';
4752
import DBCustomSelectListItem from '../custom-select-list-item/custom-select-list-item.lite';
4853
import DBCustomSelectDropdown from '../custom-select-dropdown/custom-select-dropdown.lite';
@@ -157,12 +162,15 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
157162
state._validity = props.validation ?? 'no-validation';
158163
}
159164
},
160-
handleDropdownToggle: (event: any) => {
165+
handleDropdownToggle: (event: GeneralEvent<HTMLDetailsElement>) => {
161166
if (props.onDropdownToggle) {
162167
event.stopPropagation();
163168
props.onDropdownToggle(event);
164169
}
165-
if (event.target.open) {
170+
if (
171+
event.target instanceof HTMLDetailsElement &&
172+
event.target.open
173+
) {
166174
state._documentClickListenerCallbackId =
167175
new DocumentClickListener().addCallback((event) =>
168176
state.handleDocumentClose(event)
@@ -175,7 +183,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
175183

176184
state.handleAutoPlacement();
177185
state._observer?.observe(detailsRef);
178-
if (!event.target.dataset.test) {
186+
if (!event.target.dataset['test']) {
179187
// We need this workaround for snapshot testing
180188
state.handleOpenByKeyboardFocus();
181189
}
@@ -239,8 +247,14 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
239247
}`;
240248
}
241249
},
242-
handleTagRemove: (option: CustomSelectOptionType, event: any) => {
243-
event.stopPropagation();
250+
handleTagRemove: (
251+
option: CustomSelectOptionType,
252+
event?: ClickEvent<HTMLButtonElement> | void
253+
) => {
254+
if (event) {
255+
event.stopPropagation();
256+
}
257+
244258
state.handleSelect(option.value);
245259
state.handleSummaryFocus();
246260
},
@@ -328,7 +342,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
328342
(event.key === 'ArrowUp' ||
329343
event.key === 'ArrowLeft')
330344
) {
331-
state.handleClose('close');
345+
state.handleClose(undefined, true);
332346
state.handleSummaryFocus();
333347
} else {
334348
// 3. Otherwise, we need to move to the first checkbox
@@ -357,7 +371,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
357371
handleKeyboardPress: (event: any) => {
358372
event.stopPropagation();
359373
if (event.key === 'Escape' && detailsRef?.open) {
360-
state.handleClose('close');
374+
state.handleClose(undefined, true);
361375
state.handleSummaryFocus();
362376
} else if (
363377
event.key === 'ArrowDown' ||
@@ -368,17 +382,23 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
368382
state.handleArrowDownUp(event);
369383
}
370384
},
371-
handleClose: (event: any) => {
385+
handleClose: (
386+
event?: InteractionEvent<HTMLDetailsElement> | void,
387+
forceClose?: boolean
388+
) => {
372389
if (detailsRef) {
373-
if (event === 'close') {
390+
if (forceClose) {
374391
detailsRef.open = false;
375392
state.handleSummaryFocus();
376-
} else if (detailsRef.open && event?.relatedTarget) {
377-
const relatedTarget = event.relatedTarget as HTMLElement;
378-
if (!detailsRef.contains(relatedTarget)) {
379-
// We need to use delay here because the combination of `contains`
380-
// and changing the DOM element causes a race condition inside browser
381-
delay(() => (detailsRef.open = false), 1);
393+
} else if (detailsRef.open && event) {
394+
if (event.relatedTarget) {
395+
const relatedTarget =
396+
event.relatedTarget as HTMLElement;
397+
if (!detailsRef.contains(relatedTarget)) {
398+
// We need to use delay here because the combination of `contains`
399+
// and changing the DOM element causes a race condition inside browser
400+
delay(() => (detailsRef.open = false), 1);
401+
}
382402
}
383403
}
384404
}
@@ -444,7 +464,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
444464
}
445465
} else {
446466
state.handleOptionSelected([value]);
447-
state.handleClose('close');
467+
state.handleClose(undefined, true);
448468
}
449469
}
450470
},
@@ -515,12 +535,19 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
515535
}
516536
},
517537
// Don't trigger onOptionSelected event
518-
handleSearch: (event: any) => {
538+
handleSearch: (
539+
valueOrEvent?: InputEvent<HTMLInputElement> | string | void
540+
) => {
541+
if (valueOrEvent === undefined) {
542+
return;
543+
}
544+
519545
let filterText;
520546

521-
if (typeof event === 'string') {
522-
filterText = event;
547+
if (typeof valueOrEvent === 'string') {
548+
filterText = valueOrEvent;
523549
} else {
550+
const event = valueOrEvent as InputEvent<HTMLInputElement>;
524551
event.stopPropagation();
525552

526553
if (props.onSearch) {
@@ -596,8 +623,10 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
596623

597624
onUpdate(() => {
598625
if (detailsRef) {
599-
detailsRef.addEventListener('focusout', (event: any) =>
600-
state.handleClose(event)
626+
detailsRef.addEventListener(
627+
'focusout',
628+
(event: InteractionEvent<HTMLDetailsElement>) =>
629+
state.handleClose(event)
601630
);
602631
}
603632
}, [detailsRef]);
@@ -833,7 +862,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
833862
ref={detailsRef}
834863
open={props.open}
835864
/* @ts-expect-error details as an event named onToggle */
836-
onToggle={(event: any) => state.handleDropdownToggle(event)}
865+
onToggle={(event) => state.handleDropdownToggle(event)}
837866
onKeyDown={(event) => state.handleKeyboardPress(event)}>
838867
{props.children}
839868
<Show when={props.options}>
@@ -872,7 +901,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
872901
index
873902
)}
874903
onRemove={(
875-
event: ClickEvent<HTMLButtonElement>
904+
event?: ClickEvent<HTMLButtonElement> | void
876905
) =>
877906
state.handleTagRemove(
878907
option,
@@ -909,7 +938,7 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
909938
: undefined
910939
}
911940
onInput={(
912-
event: ChangeEvent<HTMLInputElement>
941+
event: InputEvent<HTMLInputElement>
913942
) => state.handleSearch(event)}
914943
/>
915944
</div>
@@ -1028,7 +1057,9 @@ export default function DBCustomSelect(props: DBCustomSelectProps) {
10281057
size="small"
10291058
name={state._id}
10301059
form={state._id}
1031-
onClick={() => state.handleClose('close')}>
1060+
onClick={() =>
1061+
state.handleClose(undefined, true)
1062+
}>
10321063
{props.mobileCloseButtonText ??
10331064
DEFAULT_CLOSE_BUTTON}
10341065
</DBButton>

packages/components/src/components/custom-select/model.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import {
22
BaseFormProps,
3+
ClickEvent,
34
CloseEventState,
45
CustomFormProps,
56
DocumentScrollState,
67
FormMessageProps,
78
FormState,
89
FromValidState,
10+
GeneralEvent,
911
GlobalProps,
1012
GlobalState,
1113
IconProps,
14+
InputEvent,
15+
InteractionEvent,
1216
PlacementVerticalType,
13-
PopoverState,
1417
RequiredProps,
1518
ShowIconProps,
1619
ShowLabelProps,
@@ -72,20 +75,20 @@ export type DBCustomSelectEvents = {
7275
/**
7376
* Informs the user when dropdown was toggled.
7477
*/
75-
onDropdownToggle?: (event: any) => void;
78+
onDropdownToggle?: (event: GeneralEvent<HTMLDetailsElement>) => void;
7679
/**
7780
* Informs the user when dropdown was toggled.
7881
*/
79-
dropdownToggle?: (event: any) => void;
82+
dropdownToggle?: (event: GeneralEvent<HTMLDetailsElement>) => void;
8083

8184
/**
8285
* Informs the user when a search was performed.
8386
*/
84-
onSearch?: (event: any) => void;
87+
onSearch?: (event: InputEvent<HTMLInputElement>) => void;
8588
/**
8689
* Informs the user when a search was performed.
8790
*/
88-
search?: (event: any) => void;
91+
search?: (event: InputEvent<HTMLInputElement>) => void;
8992
};
9093

9194
export type DBCustomSelectDefaultProps = {
@@ -266,7 +269,10 @@ export type DBCustomSelectDefaultState = {
266269
searchEnabled: boolean;
267270
amountOptions: number;
268271
setDescById: (descId?: string) => void;
269-
handleTagRemove: (option: CustomSelectOptionType, event?: any) => void;
272+
handleTagRemove: (
273+
option: CustomSelectOptionType,
274+
event?: ClickEvent<HTMLButtonElement> | void
275+
) => void;
270276
handleSummaryFocus: () => void;
271277
handleSelect: (value?: string) => void;
272278
handleSelectAll: (event: any) => void;
@@ -289,5 +295,5 @@ export type DBCustomSelectState = DBCustomSelectDefaultState &
289295
GlobalState &
290296
FormState &
291297
FromValidState &
292-
CloseEventState &
298+
CloseEventState<InteractionEvent<HTMLDetailsElement>> &
293299
DocumentScrollState;

packages/components/src/components/drawer/drawer.lite.tsx

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {
1010
import { DBDrawerProps, DBDrawerState } from './model';
1111
import DBButton from '../button/button.lite';
1212
import { DEFAULT_CLOSE_BUTTON } from '../../shared/constants';
13-
import { cls, delay, getBooleanAsString } from '../../utils';
13+
import { cls, delay, getBooleanAsString, isKeyboardEvent } from '../../utils';
14+
import { ClickEvent, GeneralKeyboardEvent } from '../../shared/model';
1415

1516
useMetadata({});
1617

@@ -21,24 +22,40 @@ export default function DBDrawer(props: DBDrawerProps) {
2122
const dialogContainerRef = useRef<HTMLDivElement | any>(null);
2223
const state = useStore<DBDrawerState>({
2324
// eslint-disable-next-line @typescript-eslint/no-explicit-any
24-
handleClose: (event: any, forceClose?: boolean) => {
25-
if (event.key === 'Escape') {
26-
event.preventDefault();
27-
}
25+
handleClose: (
26+
event?:
27+
| ClickEvent<HTMLButtonElement | HTMLDialogElement>
28+
| GeneralKeyboardEvent<HTMLDialogElement>
29+
| void,
30+
forceClose?: boolean
31+
) => {
32+
if (!event) return;
2833

29-
if (forceClose) {
30-
event.stopPropagation();
31-
}
34+
if (isKeyboardEvent<HTMLButtonElement | HTMLDialogElement>(event)) {
35+
if (event.key === 'Escape') {
36+
event.preventDefault();
37+
38+
if (props.onClose) {
39+
props.onClose(event);
40+
}
41+
}
42+
} else {
43+
if (forceClose) {
44+
event.stopPropagation();
3245

33-
if (
34-
forceClose ||
35-
event.key === 'Escape' ||
36-
(event.target.nodeName === 'DIALOG' &&
46+
if (props.onClose) {
47+
props.onClose(event);
48+
}
49+
}
50+
51+
if (
52+
(event.target as any)?.nodeName === 'DIALOG' &&
3753
event.type === 'click' &&
38-
props.backdrop !== 'none')
39-
) {
40-
if (props.onClose) {
41-
props.onClose(event);
54+
props.backdrop !== 'none'
55+
) {
56+
if (props.onClose) {
57+
props.onClose(event);
58+
}
4259
}
4360
}
4461
},

packages/components/src/components/drawer/model.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import {
2+
ClickEvent,
23
CloseEventProps,
34
CloseEventState,
5+
GeneralEvent,
6+
GeneralKeyboardEvent,
47
GlobalProps,
58
GlobalState,
69
InnerCloseButtonProps,
@@ -56,7 +59,10 @@ export type DBDrawerDefaultProps = {
5659

5760
export type DBDrawerProps = DBDrawerDefaultProps &
5861
GlobalProps &
59-
CloseEventProps &
62+
CloseEventProps<
63+
| ClickEvent<HTMLButtonElement | HTMLDialogElement>
64+
| GeneralKeyboardEvent<HTMLDialogElement>
65+
> &
6066
InnerCloseButtonProps &
6167
WidthProps &
6268
SpacingProps;
@@ -67,4 +73,7 @@ export type DBDrawerDefaultState = {
6773

6874
export type DBDrawerState = DBDrawerDefaultState &
6975
GlobalState &
70-
CloseEventState;
76+
CloseEventState<
77+
| ClickEvent<HTMLButtonElement | HTMLDialogElement>
78+
| GeneralKeyboardEvent<HTMLDialogElement>
79+
>;

packages/components/src/components/notification/model.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
ClickEvent,
23
CloseEventProps,
34
CloseEventState,
45
GlobalProps,
@@ -85,7 +86,7 @@ export type DBNotificationDefaultProps = {
8586

8687
export type DBNotificationProps = DBNotificationDefaultProps &
8788
GlobalProps &
88-
CloseEventProps &
89+
CloseEventProps<ClickEvent<HTMLButtonElement>> &
8990
IconProps &
9091
SemanticProps &
9192
InnerCloseButtonProps &
@@ -97,4 +98,4 @@ export type DBNotificationDefaultState = {};
9798

9899
export type DBNotificationState = DBNotificationDefaultState &
99100
GlobalState &
100-
CloseEventState;
101+
CloseEventState<ClickEvent<HTMLButtonElement>>;

0 commit comments

Comments
 (0)