1 | import * as React from "react";
|
2 | import { createComponent } from "reakit-system/createComponent";
|
3 | import { createHook } from "reakit-system/createHook";
|
4 | import { useForkRef } from "reakit-utils/useForkRef";
|
5 | import { useIsomorphicEffect } from "reakit-utils/useIsomorphicEffect";
|
6 | import { GroupOptions, GroupHTMLProps, useGroup } from "../Group/Group";
|
7 | import {
|
8 | unstable_useId,
|
9 | unstable_IdOptions,
|
10 | unstable_IdHTMLProps,
|
11 | } from "../Id/Id";
|
12 | import { CompositeStateReturn } from "./CompositeState";
|
13 | import { findEnabledItemById } from "./__utils/findEnabledItemById";
|
14 | import { COMPOSITE_GROUP_KEYS } from "./__keys";
|
15 |
|
16 | export type CompositeGroupOptions = GroupOptions &
|
17 | unstable_IdOptions &
|
18 | Pick<CompositeStateReturn, "registerGroup" | "unregisterGroup"> &
|
19 | Pick<Partial<CompositeStateReturn>, "currentId" | "unstable_moves" | "items">;
|
20 |
|
21 | export type CompositeGroupHTMLProps = GroupHTMLProps & unstable_IdHTMLProps;
|
22 |
|
23 | export type CompositeGroupProps = CompositeGroupOptions &
|
24 | CompositeGroupHTMLProps;
|
25 |
|
26 | export const useCompositeGroup = createHook<
|
27 | CompositeGroupOptions,
|
28 | CompositeGroupHTMLProps
|
29 | >({
|
30 | name: "CompositeGroup",
|
31 | compose: [useGroup, unstable_useId],
|
32 | keys: COMPOSITE_GROUP_KEYS,
|
33 |
|
34 | propsAreEqual(prev, next) {
|
35 | if (!next.id || prev.id !== next.id) {
|
36 | return useGroup.unstable_propsAreEqual(prev, next);
|
37 | }
|
38 | const {
|
39 | currentId: prevCurrentId,
|
40 | unstable_moves: prevMoves,
|
41 | ...prevProps
|
42 | } = prev;
|
43 | const {
|
44 | currentId: nextCurrentId,
|
45 | unstable_moves: nextMoves,
|
46 | ...nextProps
|
47 | } = next;
|
48 | if (prev.items && next.items) {
|
49 | const prevCurrentItem = findEnabledItemById(prev.items, prevCurrentId);
|
50 | const nextCurrentItem = findEnabledItemById(next.items, nextCurrentId);
|
51 | const prevGroupId = prevCurrentItem?.groupId;
|
52 | const nextGroupId = nextCurrentItem?.groupId;
|
53 | if (next.id === nextGroupId || next.id === prevGroupId) {
|
54 | return false;
|
55 | }
|
56 | }
|
57 | return useGroup.unstable_propsAreEqual(prevProps, nextProps);
|
58 | },
|
59 |
|
60 | useProps(options, { ref: htmlRef, ...htmlProps }) {
|
61 | const ref = React.useRef<HTMLElement>(null);
|
62 | const { id } = options;
|
63 |
|
64 |
|
65 | useIsomorphicEffect(() => {
|
66 | if (!id) return undefined;
|
67 | options.registerGroup?.({ id, ref });
|
68 | return () => {
|
69 | options.unregisterGroup?.(id);
|
70 | };
|
71 | }, [id, options.registerGroup, options.unregisterGroup]);
|
72 |
|
73 | return { ref: useForkRef(ref, htmlRef), ...htmlProps };
|
74 | },
|
75 | });
|
76 |
|
77 | export const CompositeGroup = createComponent({
|
78 | as: "div",
|
79 | useHook: useCompositeGroup,
|
80 | });
|