Skip to content

Commit e0482e6

Browse files
committed
release: 6.3.0
1 parent 173315a commit e0482e6

File tree

14 files changed

+833
-782
lines changed

14 files changed

+833
-782
lines changed

README.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MDB 5 React
22

3-
Version: FREE 6.2.0
3+
Version: FREE 6.3.0
44

55
Documentation:
66
https://mdbootstrap.com/docs/b5/react/

app/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mdb-react-ui-kit-demo",
3-
"version": "6.2.0",
3+
"version": "6.3.0",
44
"main": "index.js",
55
"repository": {
66
"type": "git",

app/src/components/Accordion/Accordion.tsx

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
11
import clsx from 'clsx';
2-
import React, { useEffect, useState } from 'react';
2+
import React, { useMemo, useState } from 'react';
33
import type { AccordionProps } from './types';
44
import { AccordionContext } from './AccordionContext';
55

66
const MDBAccordion: React.FC<AccordionProps> = React.forwardRef<HTMLAllCollection, AccordionProps>(
77
(
8-
{ alwaysOpen, borderless, className, flush, initialActive = 0, tag: Tag = 'div', children, onChange, ...props },
8+
{
9+
alwaysOpen,
10+
borderless,
11+
className,
12+
flush,
13+
active,
14+
initialActive = 0,
15+
tag: Tag = 'div',
16+
children,
17+
onChange,
18+
...props
19+
},
920
ref
1021
) => {
22+
const isControlled = useMemo(() => typeof active !== 'undefined', [active]);
1123
const classes = clsx('accordion', flush && 'accordion-flush', borderless && 'accordion-borderless', className);
1224

1325
const [activeItem, setActiveItem] = useState(initialActive);
1426

15-
useEffect(() => {
16-
if (!activeItem) return;
17-
18-
onChange && onChange(activeItem);
19-
}, [onChange, activeItem]);
20-
2127
return (
2228
<Tag className={classes} ref={ref} {...props}>
23-
<AccordionContext.Provider value={{ activeItem, setActiveItem, alwaysOpen, initialActive }}>
29+
<AccordionContext.Provider
30+
value={{ activeItem: isControlled ? active : activeItem, setActiveItem, alwaysOpen, initialActive, onChange }}
31+
>
2432
{children}
2533
</AccordionContext.Provider>
2634
</Tag>

app/src/components/Accordion/AccordionContext.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import React from 'react';
22

33
interface AccordionProps {
4-
activeItem?: number;
4+
activeItem?: number | number[];
55
setActiveItem: React.SetStateAction<any>;
66
alwaysOpen?: boolean;
7-
initialActive?: number;
7+
initialActive?: number | number[];
8+
onChange?: (id: number | number[]) => void;
89
}
910

1011
const AccordionContext = React.createContext<AccordionProps>({

app/src/components/Accordion/AccordionItem/AccordionItem.tsx

+32-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import clsx from 'clsx';
2-
import React, { useContext, useState } from 'react';
2+
import React, { useContext, useMemo, useCallback } from 'react';
33
import { AccordionContext } from '../AccordionContext';
44
import type { AccordionItemProps } from './types';
55
import MDBCollapse from '../../Collapse/Collapse';
@@ -21,26 +21,42 @@ const MDBAccordionItem: React.FC<AccordionItemProps> = React.forwardRef<HTMLAllC
2121
},
2222
ref
2323
) => {
24-
const { activeItem, setActiveItem, alwaysOpen, initialActive } = useContext(AccordionContext);
24+
const { activeItem, setActiveItem, alwaysOpen, onChange } = useContext(AccordionContext);
2525

26-
const [openState, setOpenState] = useState(initialActive);
26+
const isCollapsed: boolean = useMemo(() => {
27+
const isArray = Array.isArray(activeItem);
28+
if (isArray) {
29+
return activeItem.includes(collapseId);
30+
}
31+
return activeItem === collapseId;
32+
}, [activeItem, collapseId]);
2733

2834
const classes = clsx('accordion-item', className);
2935
const headerClasses = clsx('accordion-header', headerClassName);
3036
const bodyClasses = clsx('accordion-body', bodyClassName);
31-
const buttonClasses = clsx(
32-
'accordion-button',
33-
alwaysOpen ? collapseId !== openState && 'collapsed' : collapseId !== activeItem && 'collapsed',
34-
btnClassName
35-
);
37+
const buttonClasses = clsx('accordion-button', !isCollapsed && 'collapsed', btnClassName);
3638

37-
const toggleAccordion = (value: number) => {
38-
if (alwaysOpen) {
39-
value !== openState ? setOpenState(value) : setOpenState(0);
40-
} else {
41-
value !== activeItem ? setActiveItem(value) : setActiveItem(0);
42-
}
43-
};
39+
const toggleAccordion = useCallback(
40+
(itemId: number) => {
41+
let newValue: number | number[] = itemId;
42+
const isArray = Array.isArray(activeItem);
43+
44+
if (isArray) {
45+
activeItem.includes(itemId)
46+
? (newValue = activeItem.filter((item) => item !== itemId))
47+
: (newValue = alwaysOpen ? [...activeItem, itemId] : [itemId]);
48+
} else {
49+
newValue = activeItem === itemId ? 0 : itemId;
50+
51+
// if alwaysOpen is true, we must convert newValue to array
52+
alwaysOpen && (newValue = [newValue]);
53+
}
54+
55+
onChange?.(newValue);
56+
setActiveItem(newValue);
57+
},
58+
[onChange, activeItem, setActiveItem, alwaysOpen]
59+
);
4460

4561
return (
4662
<Tag className={classes} ref={ref} {...props}>
@@ -49,10 +65,7 @@ const MDBAccordionItem: React.FC<AccordionItemProps> = React.forwardRef<HTMLAllC
4965
{headerTitle}
5066
</button>
5167
</h2>
52-
<MDBCollapse
53-
id={collapseId.toString()}
54-
show={alwaysOpen ? openState === collapseId : activeItem === collapseId}
55-
>
68+
<MDBCollapse id={collapseId.toString()} show={isCollapsed}>
5669
<div className={bodyClasses} style={bodyStyle}>
5770
{children}
5871
</div>

app/src/components/Accordion/types.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ interface AccordionProps extends BaseComponent {
55
alwaysOpen?: boolean;
66
borderless?: boolean;
77
flush?: boolean;
8-
initialActive?: number;
9-
onChange?: (id: number) => void;
8+
active?: number | number[];
9+
initialActive?: number | number[];
10+
onChange?: (id: number | number[]) => void;
1011
ref?: React.ForwardedRef<HTMLAllCollection>;
1112
tag?: React.ComponentProps<any>;
1213
}

app/src/forms/Validation/Validation.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import clsx from 'clsx';
22
import type { ValidationProps } from './types';
3-
import React, { useState } from 'react';
3+
import React, { useEffect, useState } from 'react';
44

55
const MDBValidation: React.FC<ValidationProps> = React.forwardRef<HTMLFormElement, ValidationProps>(
6-
({ className, children, isValidated, onReset, onSubmit, noValidate = true, ...props }, ref) => {
6+
({ className, children, isValidated = false, onReset, onSubmit, noValidate = true, ...props }, ref) => {
77
const [validated, setValidated] = useState(isValidated);
88

99
const classes = clsx('needs-validation', validated && 'was-validated', className);
@@ -22,6 +22,10 @@ const MDBValidation: React.FC<ValidationProps> = React.forwardRef<HTMLFormElemen
2222
onReset && onReset(e);
2323
};
2424

25+
useEffect(() => {
26+
setValidated(isValidated);
27+
}, [isValidated]);
28+
2529
return (
2630
<form
2731
className={classes}

app/src/utils/hooks.tsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,15 @@ const useOnScreen = (ref: RefObject<HTMLElement>) => {
1717
return isIntersecting;
1818
};
1919

20-
export { useOnScreen };
20+
const useOpenStatus = (openState: boolean, openProp?: boolean) => {
21+
const isOpen = useMemo(() => {
22+
if (openProp !== undefined) {
23+
return openProp;
24+
}
25+
return openState;
26+
}, [openProp, openState]);
27+
28+
return isOpen;
29+
};
30+
31+
export { useOnScreen, useOpenStatus };

0 commit comments

Comments
 (0)