Skip to content

Commit 38d288d

Browse files
committed
不要コード削除
1 parent 0ba7464 commit 38d288d

File tree

2 files changed

+2
-310
lines changed

2 files changed

+2
-310
lines changed

301/src/App.tsx

Lines changed: 1 addition & 309 deletions
Original file line numberDiff line numberDiff line change
@@ -1,312 +1,4 @@
1-
import {
2-
type Ref,
3-
type ReactElement,
4-
type ReactNode,
5-
type HTMLProps,
6-
type Dispatch,
7-
type MouseEvent,
8-
type FocusEvent,
9-
type ButtonHTMLAttributes,
10-
type SetStateAction,
11-
useState,
12-
useEffect,
13-
useRef,
14-
useContext,
15-
createContext,
16-
forwardRef,
17-
Fragment,
18-
cloneElement,
19-
} from 'react';
20-
21-
import {
22-
autoUpdate,
23-
flip,
24-
FloatingFocusManager,
25-
FloatingList,
26-
FloatingNode,
27-
FloatingPortal,
28-
FloatingTree,
29-
offset,
30-
safePolygon,
31-
shift,
32-
useClick,
33-
useDismiss,
34-
useFloating,
35-
useFloatingNodeId,
36-
useFloatingParentNodeId,
37-
useFloatingTree,
38-
useHover,
39-
useInteractions,
40-
useListItem,
41-
useListNavigation,
42-
useMergeRefs,
43-
useRole,
44-
useTypeahead
45-
} from '@floating-ui/react';
46-
47-
48-
const MenuContext = createContext<{
49-
getItemProps: ( userProps?: HTMLProps<HTMLElement> ) => Record<string, unknown>;
50-
activeIndex: number | null;
51-
setActiveIndex: Dispatch<SetStateAction<number | null>>;
52-
setHasFocusInside: Dispatch<SetStateAction<boolean>>;
53-
isOpen: boolean;
54-
}>( {
55-
getItemProps: () => ( {} ),
56-
activeIndex: null,
57-
setActiveIndex: () => {},
58-
setHasFocusInside: () => {},
59-
isOpen: false,
60-
} );
61-
62-
type MenuItemProps = {
63-
label: string;
64-
disabled?: boolean;
65-
};
66-
67-
export const MenuItem = forwardRef<
68-
HTMLButtonElement,
69-
MenuItemProps & ButtonHTMLAttributes<HTMLButtonElement>
70-
>( ( { label, disabled, ...props }, forwardedRef ) => {
71-
72-
const menu = useContext( MenuContext );
73-
const item = useListItem( { label: disabled ? null : label } );
74-
const tree = useFloatingTree();
75-
const isActive = item.index === menu.activeIndex;
76-
77-
return (
78-
<button
79-
{ ...props }
80-
ref={ useMergeRefs( [ item.ref, forwardedRef ] ) }
81-
type="button"
82-
role="menuitem"
83-
style={ { display: 'block', width: '100%' } }
84-
tabIndex={ isActive ? 0 : - 1 }
85-
disabled={ disabled }
86-
{ ...menu.getItemProps( {
87-
onClick( event: MouseEvent<HTMLButtonElement> ) {
88-
89-
props.onClick?.( event );
90-
tree?.events.emit( 'click' );
91-
92-
},
93-
onFocus( event: FocusEvent<HTMLButtonElement> ) {
94-
95-
props.onFocus?.( event );
96-
menu.setHasFocusInside( true );
97-
98-
}
99-
} ) }
100-
>
101-
{ label }
102-
</button>
103-
);
104-
105-
} );
106-
107-
type MenuTriggerItemProps = ButtonHTMLAttributes<HTMLButtonElement>;
108-
109-
const MenuTriggerItem = forwardRef<
110-
HTMLButtonElement,
111-
ButtonHTMLAttributes<HTMLButtonElement>
112-
>( ( { children, ...props }: MenuTriggerItemProps, forwardedRef ) => {
113-
114-
const item = useListItem();
115-
116-
return (
117-
<button
118-
{ ...props }
119-
ref={ useMergeRefs( [ item.ref, forwardedRef ] ) }
120-
type="button"
121-
style={ { display: 'block', width: '100%' } }
122-
>
123-
{ children }
124-
</button>
125-
);
126-
127-
} );
128-
129-
type MenuProps = {
130-
trigger: ReactElement<ButtonHTMLAttributes<HTMLButtonElement> & {ref?: Ref<HTMLButtonElement>},"button">;
131-
nested?: boolean;
132-
children?: ReactNode;
133-
};
134-
135-
export const MenuComponent = forwardRef<
136-
HTMLButtonElement,
137-
MenuProps & HTMLProps<HTMLButtonElement>
138-
>( ( { children, trigger, ...props }, forwardedRef ) => {
139-
140-
const [ isOpen, setIsOpen ] = useState( false );
141-
const [ hasFocusInside, setHasFocusInside ] = useState( false );
142-
const [ activeIndex, setActiveIndex ] = useState<number | null>( null );
143-
144-
const elementsRef = useRef<Array<HTMLButtonElement | null>>( [] );
145-
const labelsRef = useRef<Array<string | null>>( [] );
146-
const parent = useContext( MenuContext );
147-
148-
const tree = useFloatingTree();
149-
const nodeId = useFloatingNodeId();
150-
const parentId = useFloatingParentNodeId();
151-
const item = useListItem();
152-
153-
const isNested = parentId !== null;
154-
155-
const { floatingStyles, refs, context } = useFloating<HTMLButtonElement>( {
156-
nodeId,
157-
open: isOpen,
158-
onOpenChange: setIsOpen,
159-
placement: isNested ? 'right-start' : 'bottom-start',
160-
middleware: [
161-
offset( { mainAxis: isNested ? 0 : 4, alignmentAxis: 0 } ),
162-
flip(),
163-
shift()
164-
],
165-
whileElementsMounted: autoUpdate,
166-
} );
167-
168-
const hover = useHover( context, {
169-
enabled: isNested,
170-
delay: { open: 200, close: 200 },
171-
handleClose: safePolygon( { blockPointerEvents: true } ),
172-
} );
173-
174-
const click = useClick( context, {
175-
event: 'mousedown',
176-
toggle: ! isNested,
177-
ignoreMouse: isNested
178-
} );
179-
180-
const role = useRole( context, { role: 'menu' } );
181-
const dismiss = useDismiss( context, { bubbles: true } );
182-
const listNavigation = useListNavigation( context, {
183-
listRef: elementsRef,
184-
activeIndex,
185-
nested: isNested,
186-
onNavigate: setActiveIndex,
187-
} );
188-
189-
const typeahead = useTypeahead( context, {
190-
listRef: labelsRef,
191-
onMatch: isOpen ? setActiveIndex : undefined,
192-
activeIndex,
193-
} );
194-
195-
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions( [
196-
hover, click, role, dismiss, listNavigation, typeahead
197-
] );
198-
199-
useEffect( () => {
200-
201-
if ( ! tree ) return;
202-
203-
function handleTreeClick() {
204-
205-
setIsOpen( false );
206-
207-
}
208-
209-
function onSubMenuOpen( event: { nodeId: string, parentId: string } ) {
210-
211-
if ( event.nodeId !== nodeId && event.parentId === parentId ) {
212-
213-
setIsOpen( false );
214-
215-
}
216-
217-
}
218-
219-
tree.events.on( 'click', handleTreeClick );
220-
tree.events.on( 'menuopen', onSubMenuOpen );
221-
222-
return () => {
223-
224-
tree.events.off( 'click', handleTreeClick );
225-
tree.events.off( 'menuopen', onSubMenuOpen );
226-
227-
};
228-
229-
}, [ tree, nodeId, parentId ] );
230-
231-
useEffect( () => {
232-
233-
if ( isOpen && tree ) {
234-
235-
tree.events.emit( 'menuopen', { parentId, nodeId } );
236-
237-
}
238-
239-
}, [ tree, isOpen, nodeId, parentId ] );
240-
241-
return (
242-
<FloatingNode id={ nodeId }>
243-
{ cloneElement( trigger, {
244-
ref: useMergeRefs( [ refs.setReference, item.ref, forwardedRef ] ),
245-
type: 'button',
246-
tabIndex: ! isNested ? undefined : parent.activeIndex === item.index ? 0 : - 1,
247-
role: isNested ? 'menuitem' : undefined,
248-
style: isNested ? { display: 'block', width: '100%' } : undefined,
249-
...getReferenceProps( parent.getItemProps( {
250-
...props,
251-
onFocus( event: FocusEvent<HTMLButtonElement> ) {
252-
253-
props.onFocus?.( event );
254-
setHasFocusInside( false );
255-
parent.setHasFocusInside( true );
256-
257-
}
258-
} ) ),
259-
} ) }
260-
<MenuContext.Provider
261-
value={ {
262-
activeIndex,
263-
setActiveIndex,
264-
getItemProps,
265-
setHasFocusInside,
266-
isOpen,
267-
} }
268-
>
269-
<FloatingList elementsRef={ elementsRef } labelsRef={ labelsRef }>
270-
{ isOpen && (
271-
<FloatingPortal>
272-
<FloatingFocusManager
273-
context={ context }
274-
modal={ false }
275-
initialFocus={ isNested ? - 1 : 0 }
276-
returnFocus={ ! isNested }
277-
>
278-
<div
279-
ref={ refs.setFloating }
280-
style={ floatingStyles }
281-
{ ...getFloatingProps() }
282-
>
283-
{ children }
284-
</div>
285-
</FloatingFocusManager>
286-
</FloatingPortal>
287-
) }
288-
</FloatingList>
289-
</MenuContext.Provider>
290-
</FloatingNode>
291-
);
292-
293-
} );
294-
295-
export const Menu = forwardRef<
296-
HTMLButtonElement,
297-
MenuProps & HTMLProps<HTMLButtonElement>
298-
>( ( props, ref ) => {
299-
300-
const parentId = useFloatingParentNodeId();
301-
const Wrapper = parentId === null ? FloatingTree : Fragment;
302-
303-
return (
304-
<Wrapper>
305-
<MenuComponent { ...props } ref={ ref } />
306-
</Wrapper>
307-
);
308-
309-
} );
1+
import { Menu, MenuItem, MenuTriggerItem } from './Menu';
3102

3113
export default function App() {
3124

301/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react'
44
// https://vitejs.dev/config/
55
export default defineConfig({
66
plugins: [react()],
7-
base: '/2025-floating-ui-react/107/',
7+
base: '/2025-floating-ui-react/301/',
88
})

0 commit comments

Comments
 (0)