Skip to content

Commit a46ef1d

Browse files
authored
fix: issue with tabs and accordion for react 19 (#4030)
* fix: issue with tabs and accordion for react 19 * chore: update from main
1 parent 32df7d5 commit a46ef1d

File tree

8 files changed

+86
-9
lines changed

8 files changed

+86
-9
lines changed
612 Bytes
Loading
-1.76 KB
Loading

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import {
22
onMount,
3+
onUpdate,
34
Show,
45
Slot,
56
useDefaultProps,
67
useMetadata,
78
useRef,
8-
useStore
9+
useStore,
10+
useTarget
911
} from '@builder.io/mitosis';
1012
import { DBAccordionItemProps, DBAccordionItemState } from './model';
1113
import { cls, getBooleanAsString, uuid } from '../../utils';
@@ -22,6 +24,19 @@ export default function DBAccordionItem(props: DBAccordionItemProps) {
2224
const state = useStore<DBAccordionItemState>({
2325
_id: DEFAULT_ID,
2426
_open: false,
27+
_name: undefined,
28+
initialized: false,
29+
handleNameAttribute: () => {
30+
if (_ref) {
31+
const setAttribute = _ref.setAttribute;
32+
_ref.setAttribute = (attribute: string, value: string) => {
33+
setAttribute.call(_ref, attribute, value);
34+
if (attribute === 'name') {
35+
state._name = value;
36+
}
37+
};
38+
}
39+
},
2540
toggle: (event: ClickEvent<HTMLElement>) => {
2641
// We need this for react https://github.com/facebook/react/issues/15486#issuecomment-488028431
2742
event?.preventDefault();
@@ -38,14 +53,31 @@ export default function DBAccordionItem(props: DBAccordionItemProps) {
3853
if (props.defaultOpen) {
3954
state._open = props.defaultOpen;
4055
}
56+
57+
state.initialized = true;
4158
});
59+
60+
onUpdate(() => {
61+
if (_ref && state.initialized) {
62+
useTarget({ react: () => state.handleNameAttribute() });
63+
}
64+
}, [_ref, state.initialized]);
65+
66+
onUpdate(() => {
67+
if (props.name) {
68+
state._name = props.name;
69+
}
70+
}, [props.name]);
71+
4272
// jscpd:ignore-end
4373

4474
return (
4575
<li id={state._id} class={cls('db-accordion-item', props.className)}>
4676
<details
4777
aria-disabled={getBooleanAsString(props.disabled)}
4878
ref={_ref}
79+
/* @ts-expect-error This is a new api for details */
80+
name={state._name}
4981
open={state._open}>
5082
<summary onClick={(event) => state.toggle(event)}>
5183
<Show when={props.headlinePlain}>

packages/components/src/components/accordion-item/model.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import {
22
GlobalProps,
33
GlobalState,
4+
InitializedState,
5+
NameProps,
6+
NameState,
47
TextProps,
58
ToggleEventProps,
69
ToggleEventState
@@ -27,12 +30,15 @@ export type DBAccordionItemDefaultProps = {
2730

2831
export type DBAccordionItemProps = DBAccordionItemDefaultProps &
2932
GlobalProps &
30-
ToggleEventProps;
33+
ToggleEventProps &
34+
NameProps;
3135

3236
export type DBAccordionItemDefaultState = {
3337
_open: boolean;
3438
};
3539

3640
export type DBAccordionItemState = DBAccordionItemDefaultState &
3741
GlobalState &
38-
ToggleEventState<HTMLElement>;
42+
ToggleEventState<HTMLElement> &
43+
InitializedState &
44+
NameState;

packages/components/src/components/tab-item/model.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
IconAfterProps,
99
IconProps,
1010
InitializedState,
11+
NameProps,
12+
NameState,
1113
ShowIconProps
1214
} from '../../shared/model';
1315

@@ -38,7 +40,8 @@ export type DBTabItemProps = GlobalProps &
3840
ActiveProps &
3941
AriaControlsProps &
4042
ChangeEventProps<HTMLInputElement> &
41-
ShowIconProps;
43+
ShowIconProps &
44+
NameProps;
4245

4346
export type DBTabItemDefaultState = {
4447
_selected: boolean;
@@ -47,4 +50,5 @@ export type DBTabItemDefaultState = {
4750
export type DBTabItemState = DBTabItemDefaultState &
4851
GlobalState &
4952
ChangeEventState<HTMLInputElement> &
50-
InitializedState;
53+
InitializedState &
54+
NameState;

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

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,20 @@ export default function DBTabItem(props: DBTabItemProps) {
2626
const _ref = useRef<HTMLInputElement | null>(null);
2727
// jscpd:ignore-start
2828
const state = useStore<DBTabItemState>({
29-
initialized: false,
3029
_selected: false,
30+
_name: undefined,
31+
initialized: false,
32+
handleNameAttribute: () => {
33+
if (_ref) {
34+
const setAttribute = _ref.setAttribute;
35+
_ref.setAttribute = (attribute: string, value: string) => {
36+
setAttribute.call(_ref, attribute, value);
37+
if (attribute === 'name') {
38+
state._name = value;
39+
}
40+
};
41+
}
42+
},
3143
handleChange: (event: any) => {
3244
if (props.onChange) {
3345
props.onChange(event);
@@ -63,12 +75,22 @@ export default function DBTabItem(props: DBTabItemProps) {
6375
// jscpd:ignore-end
6476

6577
onUpdate(() => {
66-
if (props.active && state.initialized && _ref) {
67-
_ref.click();
78+
if (state.initialized && _ref) {
79+
if (props.active) {
80+
_ref.click();
81+
}
82+
83+
useTarget({ react: () => state.handleNameAttribute() });
6884
state.initialized = false;
6985
}
7086
}, [_ref, state.initialized]);
7187

88+
onUpdate(() => {
89+
if (props.name) {
90+
state._name = props.name;
91+
}
92+
}, [props.name]);
93+
7294
return (
7395
<li class={cls('db-tab-item', props.className)} role="none">
7496
<label
@@ -86,6 +108,7 @@ export default function DBTabItem(props: DBTabItemProps) {
86108
ref={_ref}
87109
type="radio"
88110
role="tab"
111+
name={state._name}
89112
id={props.id}
90113
onInput={(event: any) => state.handleChange(event)}
91114
/>

packages/components/src/shared/model.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,18 @@ export type PopoverState = {
207207
handleAutoPlacement: () => void;
208208
};
209209

210+
export type NameProps = {
211+
/**
212+
* The name attribute gives the name of the element to group it.
213+
*/
214+
name?: string;
215+
};
216+
217+
export type NameState = {
218+
_name?: string;
219+
handleNameAttribute: () => void;
220+
};
221+
210222
export type ContentSlotProps = {
211223
/**
212224
* Default slot which is used to pass in additional content.

0 commit comments

Comments
 (0)