tamagui 1.5.19 → 1.5.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/views/Group.js +162 -80
- package/dist/cjs/views/Group.js.map +2 -2
- package/dist/esm/views/Group.js +164 -82
- package/dist/esm/views/Group.js.map +2 -2
- package/dist/esm/views/Group.mjs +164 -82
- package/dist/esm/views/Group.mjs.map +2 -2
- package/dist/jsx/views/Group.js +155 -78
- package/dist/jsx/views/Group.js.map +2 -2
- package/dist/jsx/views/Group.mjs +155 -78
- package/dist/jsx/views/Group.mjs.map +2 -2
- package/package.json +49 -48
- package/src/views/Group.tsx +212 -94
- package/types/views/Group.d.ts +127 -14
- package/types/views/Group.d.ts.map +1 -1
package/dist/jsx/views/Group.js
CHANGED
|
@@ -7,16 +7,28 @@ import {
|
|
|
7
7
|
mergeProps,
|
|
8
8
|
spacedChildren,
|
|
9
9
|
styled,
|
|
10
|
-
useMediaPropsActive
|
|
10
|
+
useMediaPropsActive,
|
|
11
|
+
withStaticProperties
|
|
11
12
|
} from "@tamagui/core";
|
|
13
|
+
import { createContextScope } from "@tamagui/create-context";
|
|
12
14
|
import { ThemeableStack } from "@tamagui/stacks";
|
|
13
|
-
import
|
|
15
|
+
import { useControllableState } from "@tamagui/use-controllable-state";
|
|
16
|
+
import React, { Children, cloneElement, forwardRef, isValidElement } from "react";
|
|
14
17
|
import { ScrollView } from "react-native";
|
|
18
|
+
import { useIndex, useIndexedChildren } from "reforest";
|
|
19
|
+
const GROUP_NAME = "Group";
|
|
20
|
+
const [createGroupContext, createGroupScope] = createContextScope(GROUP_NAME);
|
|
21
|
+
const [GroupProvider, useGroupContext] = createGroupContext(GROUP_NAME);
|
|
15
22
|
const GroupFrame = styled(ThemeableStack, {
|
|
16
23
|
name: "GroupFrame",
|
|
17
|
-
backgroundColor: "$background",
|
|
18
|
-
y: 0,
|
|
19
24
|
variants: {
|
|
25
|
+
unstyled: {
|
|
26
|
+
false: {
|
|
27
|
+
y: 0,
|
|
28
|
+
backgroundColor: "$background",
|
|
29
|
+
size: "$true"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
20
32
|
size: (val, { tokens }) => {
|
|
21
33
|
const borderRadius = tokens.radius[val] ?? val ?? tokens.radius["$true"];
|
|
22
34
|
return {
|
|
@@ -25,102 +37,167 @@ const GroupFrame = styled(ThemeableStack, {
|
|
|
25
37
|
}
|
|
26
38
|
},
|
|
27
39
|
defaultVariants: {
|
|
28
|
-
|
|
40
|
+
unstyled: false
|
|
29
41
|
}
|
|
30
42
|
});
|
|
31
43
|
function createGroup(verticalDefault) {
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
...hasRadius && {
|
|
63
|
-
...isFirst && !vertical && {
|
|
64
|
-
borderTopLeftRadius: radius,
|
|
65
|
-
borderBottomLeftRadius: radius
|
|
66
|
-
},
|
|
67
|
-
...isFirst && vertical && {
|
|
68
|
-
borderTopLeftRadius: radius,
|
|
69
|
-
borderTopRightRadius: radius
|
|
70
|
-
},
|
|
71
|
-
...isLast && !vertical && {
|
|
72
|
-
borderTopRightRadius: radius,
|
|
73
|
-
borderBottomRightRadius: radius
|
|
74
|
-
},
|
|
75
|
-
...isLast && vertical && {
|
|
76
|
-
borderBottomLeftRadius: radius,
|
|
77
|
-
borderBottomRightRadius: radius
|
|
78
|
-
}
|
|
44
|
+
return withStaticProperties(
|
|
45
|
+
forwardRef((props, ref) => {
|
|
46
|
+
const activeProps = useMediaPropsActive(props);
|
|
47
|
+
const {
|
|
48
|
+
__scopeGroup,
|
|
49
|
+
children: childrenProp,
|
|
50
|
+
space,
|
|
51
|
+
size = "$true",
|
|
52
|
+
spaceDirection,
|
|
53
|
+
separator,
|
|
54
|
+
scrollable,
|
|
55
|
+
axis = verticalDefault ? "vertical" : "horizontal",
|
|
56
|
+
disabled: disabledProp,
|
|
57
|
+
disablePassBorderRadius: disablePassBorderRadiusProp,
|
|
58
|
+
borderRadius,
|
|
59
|
+
forceUseItem,
|
|
60
|
+
...restProps
|
|
61
|
+
} = getExpandedShorthands(activeProps);
|
|
62
|
+
const vertical = axis === "vertical";
|
|
63
|
+
const [itemChildrenCount, setItemChildrenCount] = useControllableState({
|
|
64
|
+
defaultProp: forceUseItem ? 1 : 0
|
|
65
|
+
});
|
|
66
|
+
const isUsingItems = itemChildrenCount > 0;
|
|
67
|
+
const radius = borderRadius ?? (size ? getVariableValue(getTokens().radius[size]) - 1 : void 0);
|
|
68
|
+
const hasRadius = radius !== void 0;
|
|
69
|
+
const disablePassBorderRadius = disablePassBorderRadiusProp ?? !hasRadius;
|
|
70
|
+
const childrenArray = Children.toArray(childrenProp);
|
|
71
|
+
const children = isUsingItems ? childrenProp : childrenArray.map((child, i) => {
|
|
72
|
+
if (!isValidElement(child)) {
|
|
73
|
+
return child;
|
|
79
74
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
const disabled = child.props.disabled ?? disabledProp;
|
|
76
|
+
const isFirst = i === 0;
|
|
77
|
+
const isLast = i === childrenArray.length - 1;
|
|
78
|
+
const radiusStyles = disablePassBorderRadius ? null : getBorderRadius({ isFirst, isLast, radius, vertical });
|
|
79
|
+
const props2 = {
|
|
80
|
+
disabled,
|
|
81
|
+
...isTamaguiElement(child) ? radiusStyles : { style: radiusStyles }
|
|
82
|
+
};
|
|
83
|
+
return cloneElementWithPropOrder(child, props2);
|
|
84
|
+
});
|
|
85
|
+
const indexedChildren = useIndexedChildren(
|
|
86
|
+
spacedChildren({
|
|
87
|
+
direction: spaceDirection,
|
|
88
|
+
separator,
|
|
89
|
+
space,
|
|
90
|
+
children
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
const onItemMount = React.useCallback(
|
|
94
|
+
() => setItemChildrenCount((prev) => prev + 1),
|
|
95
|
+
[]
|
|
96
|
+
);
|
|
97
|
+
const onItemUnmount = React.useCallback(
|
|
98
|
+
() => setItemChildrenCount((prev) => prev - 1),
|
|
99
|
+
[]
|
|
100
|
+
);
|
|
101
|
+
return <GroupProvider
|
|
102
|
+
disablePassBorderRadius={disablePassBorderRadius}
|
|
103
|
+
vertical={axis === "vertical"}
|
|
104
|
+
radius={radius}
|
|
105
|
+
disabled={disabledProp}
|
|
106
|
+
onItemMount={onItemMount}
|
|
107
|
+
onItemUnmount={onItemUnmount}
|
|
108
|
+
scope={__scopeGroup}
|
|
109
|
+
><GroupFrame
|
|
110
|
+
ref={ref}
|
|
111
|
+
size={size}
|
|
112
|
+
flexDirection={axis === "horizontal" ? "row" : "column"}
|
|
113
|
+
borderRadius={borderRadius}
|
|
114
|
+
{...restProps}
|
|
115
|
+
>{wrapScroll({ ...activeProps, axis }, indexedChildren)}</GroupFrame></GroupProvider>;
|
|
116
|
+
}),
|
|
117
|
+
{
|
|
118
|
+
Item: GroupItem
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
const GroupItem = (props) => {
|
|
123
|
+
const { __scopeGroup, children } = props;
|
|
124
|
+
const treeIndex = useIndex();
|
|
125
|
+
const context = useGroupContext("GroupItem", __scopeGroup);
|
|
126
|
+
React.useEffect(() => {
|
|
127
|
+
context.onItemMount();
|
|
128
|
+
return () => {
|
|
129
|
+
context.onItemUnmount();
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
132
|
+
if (!isValidElement(children)) {
|
|
133
|
+
return children;
|
|
134
|
+
}
|
|
135
|
+
const disabled = children.props.disabled ?? context.disabled;
|
|
136
|
+
if (!treeIndex) {
|
|
137
|
+
throw Error("<Group.Item/> should only be used within a <Group/>");
|
|
138
|
+
}
|
|
139
|
+
const isFirst = treeIndex.index === 0;
|
|
140
|
+
const isLast = treeIndex.index === treeIndex.maxIndex;
|
|
141
|
+
let propsToPass = {
|
|
142
|
+
disabled
|
|
143
|
+
};
|
|
144
|
+
if (!context.disablePassBorderRadius) {
|
|
145
|
+
const radiusStyles = getBorderRadius({
|
|
146
|
+
radius: context.radius,
|
|
147
|
+
isFirst,
|
|
148
|
+
isLast,
|
|
149
|
+
vertical: context.vertical
|
|
86
150
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
})
|
|
101
|
-
)}</GroupFrame>;
|
|
151
|
+
if (isTamaguiElement(children)) {
|
|
152
|
+
propsToPass = { ...propsToPass, ...radiusStyles };
|
|
153
|
+
} else {
|
|
154
|
+
propsToPass.style = radiusStyles;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return cloneElement(children, {
|
|
158
|
+
...propsToPass,
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
style: {
|
|
161
|
+
...children.props?.["style"],
|
|
162
|
+
...propsToPass.style
|
|
163
|
+
}
|
|
102
164
|
});
|
|
103
|
-
}
|
|
104
|
-
const
|
|
165
|
+
};
|
|
166
|
+
const Group = createGroup(true);
|
|
167
|
+
const YGroup = Group;
|
|
105
168
|
const XGroup = createGroup(false);
|
|
106
|
-
const wrapScroll = ({ scrollable,
|
|
169
|
+
const wrapScroll = ({ scrollable, axis, showScrollIndicator = false }, children) => {
|
|
107
170
|
if (scrollable)
|
|
108
171
|
return <ScrollView
|
|
109
|
-
{...vertical && {
|
|
172
|
+
{...axis === "vertical" && {
|
|
110
173
|
showsVerticalScrollIndicator: showScrollIndicator
|
|
111
174
|
}}
|
|
112
|
-
{
|
|
175
|
+
{...axis === "horizontal" && {
|
|
113
176
|
horizontal: true,
|
|
114
177
|
showsHorizontalScrollIndicator: showScrollIndicator
|
|
115
178
|
}}
|
|
116
179
|
>{children}</ScrollView>;
|
|
117
180
|
return children;
|
|
118
181
|
};
|
|
182
|
+
const getBorderRadius = ({
|
|
183
|
+
isFirst,
|
|
184
|
+
isLast,
|
|
185
|
+
radius,
|
|
186
|
+
vertical
|
|
187
|
+
}) => {
|
|
188
|
+
return {
|
|
189
|
+
borderTopLeftRadius: isFirst ? radius : 0,
|
|
190
|
+
borderTopRightRadius: vertical && isFirst || !vertical && isLast ? radius : 0,
|
|
191
|
+
borderBottomLeftRadius: vertical && isLast || !vertical && isFirst ? radius : 0,
|
|
192
|
+
borderBottomRightRadius: isLast ? radius : 0
|
|
193
|
+
};
|
|
194
|
+
};
|
|
119
195
|
const cloneElementWithPropOrder = (child, props) => {
|
|
120
196
|
const next = mergeProps(child.props, props, false, getConfig().shorthands)[0];
|
|
121
197
|
return React.cloneElement({ ...child, props: null }, next);
|
|
122
198
|
};
|
|
123
199
|
export {
|
|
200
|
+
Group,
|
|
124
201
|
GroupFrame,
|
|
125
202
|
XGroup,
|
|
126
203
|
YGroup
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/views/Group.tsx"],
|
|
4
|
-
"sourcesContent": ["import {\n GetProps,\n TamaguiElement,\n getConfig,\n getExpandedShorthands,\n getTokens,\n getVariableValue,\n isTamaguiElement,\n mergeProps,\n spacedChildren,\n styled,\n useMediaPropsActive,\n} from '@tamagui/core'\nimport { ThemeableStack } from '@tamagui/stacks'\nimport React, { Children, forwardRef, isValidElement } from 'react'\nimport { ScrollView } from 'react-native'\n\nexport const GroupFrame = styled(ThemeableStack, {\n name: 'GroupFrame',\n backgroundColor: '$background',\n
|
|
5
|
-
"mappings": "AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import {\n GetProps,\n TamaguiElement,\n UnionableString,\n Variable,\n getConfig,\n getExpandedShorthands,\n getTokens,\n getVariableValue,\n isTamaguiElement,\n mergeProps,\n spacedChildren,\n styled,\n useMediaPropsActive,\n withStaticProperties,\n} from '@tamagui/core'\nimport { Scope, createContextScope } from '@tamagui/create-context'\nimport { ThemeableStack } from '@tamagui/stacks'\nimport { useControllableState } from '@tamagui/use-controllable-state'\nimport React, { Children, cloneElement, forwardRef, isValidElement } from 'react'\nimport { ScrollView } from 'react-native'\nimport { useIndex, useIndexedChildren } from 'reforest'\n\ninterface GroupContextValue {\n vertical: boolean\n disablePassBorderRadius: boolean\n onItemMount: () => void\n onItemUnmount: () => void\n radius?: number | UnionableString | Variable<any>\n disabled?: boolean\n}\n\nconst GROUP_NAME = 'Group'\n\ntype ScopedProps<P> = P & { __scopeGroup?: Scope }\nconst [createGroupContext, createGroupScope] = createContextScope(GROUP_NAME)\nconst [GroupProvider, useGroupContext] = createGroupContext<GroupContextValue>(GROUP_NAME)\n\nexport const GroupFrame = styled(ThemeableStack, {\n name: 'GroupFrame',\n\n variants: {\n unstyled: {\n false: {\n y: 0,\n backgroundColor: '$background',\n size: '$true',\n },\n },\n\n size: (val, { tokens }) => {\n const borderRadius = tokens.radius[val] ?? val ?? tokens.radius['$true']\n return {\n borderRadius,\n }\n },\n } as const,\n\n defaultVariants: {\n unstyled: false,\n },\n})\n\nexport type GroupProps = GetProps<typeof GroupFrame> & {\n axis?: 'horizontal' | 'vertical'\n\n scrollable?: boolean\n /**\n * @default false\n */\n showScrollIndicator?: boolean\n disabled?: boolean\n disablePassBorderRadius?: boolean\n /**\n * forces the group to use the Group.Item API\n */\n forceUseItem?: boolean\n}\n\nfunction createGroup(verticalDefault: boolean) {\n return withStaticProperties(\n forwardRef<TamaguiElement, ScopedProps<GroupProps>>((props, ref) => {\n const activeProps = useMediaPropsActive(props)\n\n const {\n __scopeGroup,\n children: childrenProp,\n space,\n size = '$true',\n spaceDirection,\n separator,\n scrollable,\n axis = verticalDefault ? 'vertical' : 'horizontal',\n disabled: disabledProp,\n disablePassBorderRadius: disablePassBorderRadiusProp,\n borderRadius,\n forceUseItem,\n ...restProps\n } = getExpandedShorthands(activeProps)\n\n const vertical = axis === 'vertical'\n const [itemChildrenCount, setItemChildrenCount] = useControllableState({\n defaultProp: forceUseItem ? 1 : 0,\n })\n const isUsingItems = itemChildrenCount > 0\n\n // 1 off given border to adjust for border radius? This should be user controllable\n const radius =\n borderRadius ??\n (size ? getVariableValue(getTokens().radius[size]) - 1 : undefined)\n\n const hasRadius = radius !== undefined\n const disablePassBorderRadius = disablePassBorderRadiusProp ?? !hasRadius\n\n const childrenArray = Children.toArray(childrenProp)\n const children = isUsingItems\n ? childrenProp\n : childrenArray.map((child, i) => {\n if (!isValidElement(child)) {\n return child\n }\n const disabled = child.props.disabled ?? disabledProp\n\n const isFirst = i === 0\n const isLast = i === childrenArray.length - 1\n\n const radiusStyles = disablePassBorderRadius\n ? null\n : getBorderRadius({ isFirst, isLast, radius, vertical })\n const props = {\n disabled,\n ...(isTamaguiElement(child) ? radiusStyles : { style: radiusStyles }),\n }\n\n return cloneElementWithPropOrder(child, props)\n })\n\n const indexedChildren = useIndexedChildren(\n spacedChildren({\n direction: spaceDirection,\n separator,\n space,\n children,\n })\n )\n\n const onItemMount = React.useCallback(\n () => setItemChildrenCount((prev) => prev + 1),\n []\n )\n const onItemUnmount = React.useCallback(\n () => setItemChildrenCount((prev) => prev - 1),\n []\n )\n\n return (\n <GroupProvider\n disablePassBorderRadius={disablePassBorderRadius}\n vertical={axis === 'vertical'}\n radius={radius}\n disabled={disabledProp}\n onItemMount={onItemMount}\n onItemUnmount={onItemUnmount}\n scope={__scopeGroup}\n >\n <GroupFrame\n ref={ref}\n size={size}\n flexDirection={axis === 'horizontal' ? 'row' : 'column'}\n borderRadius={borderRadius}\n {...restProps}\n >\n {wrapScroll({ ...activeProps, axis }, indexedChildren)}\n </GroupFrame>\n </GroupProvider>\n )\n }),\n {\n Item: GroupItem,\n }\n )\n}\n\nconst GroupItem = (props: ScopedProps<{ children: React.ReactNode }>) => {\n const { __scopeGroup, children } = props\n const treeIndex = useIndex()\n const context = useGroupContext('GroupItem', __scopeGroup)\n\n React.useEffect(() => {\n context.onItemMount()\n return () => {\n context.onItemUnmount()\n }\n }, [])\n\n if (!isValidElement(children)) {\n return children as any\n }\n\n const disabled = children.props.disabled ?? context.disabled\n\n if (!treeIndex) {\n throw Error('<Group.Item/> should only be used within a <Group/>')\n }\n\n const isFirst = treeIndex.index === 0\n const isLast = treeIndex.index === treeIndex.maxIndex\n\n let propsToPass: Record<string, any> = {\n disabled,\n }\n\n if (!context.disablePassBorderRadius) {\n const radiusStyles = getBorderRadius({\n radius: context.radius,\n isFirst,\n isLast,\n vertical: context.vertical,\n })\n if (isTamaguiElement(children)) {\n propsToPass = { ...propsToPass, ...radiusStyles }\n } else {\n propsToPass.style = radiusStyles\n }\n }\n\n return cloneElement(children, {\n ...propsToPass,\n // @ts-ignore\n style: {\n ...children.props?.['style'],\n ...propsToPass.style,\n },\n })\n}\n\nexport const Group = createGroup(true)\nexport const YGroup = Group\nexport const XGroup = createGroup(false)\n\nconst wrapScroll = (\n { scrollable, axis, showScrollIndicator = false }: GroupProps,\n children: any\n) => {\n if (scrollable)\n return (\n <ScrollView\n {...(axis === 'vertical' && {\n showsVerticalScrollIndicator: showScrollIndicator,\n })}\n {...(axis === 'horizontal' && {\n horizontal: true,\n showsHorizontalScrollIndicator: showScrollIndicator,\n })}\n >\n {children}\n </ScrollView>\n )\n return children\n}\n\nconst getBorderRadius = ({\n isFirst,\n isLast,\n radius,\n vertical,\n}: {\n radius: any\n vertical: boolean\n isFirst: boolean\n isLast: boolean\n}) => {\n // TODO: RTL support would be nice here\n return {\n borderTopLeftRadius: isFirst ? radius : 0,\n borderTopRightRadius: (vertical && isFirst) || (!vertical && isLast) ? radius : 0,\n borderBottomLeftRadius: (vertical && isLast) || (!vertical && isFirst) ? radius : 0,\n borderBottomRightRadius: isLast ? radius : 0,\n }\n}\n\nconst cloneElementWithPropOrder = (child: any, props: Object) => {\n const next = mergeProps(child.props, props, false, getConfig().shorthands)[0]\n return React.cloneElement({ ...child, props: null }, next)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["props"]
|
|
7
7
|
}
|
package/dist/jsx/views/Group.mjs
CHANGED
|
@@ -7,16 +7,28 @@ import {
|
|
|
7
7
|
mergeProps,
|
|
8
8
|
spacedChildren,
|
|
9
9
|
styled,
|
|
10
|
-
useMediaPropsActive
|
|
10
|
+
useMediaPropsActive,
|
|
11
|
+
withStaticProperties
|
|
11
12
|
} from "@tamagui/core";
|
|
13
|
+
import { createContextScope } from "@tamagui/create-context";
|
|
12
14
|
import { ThemeableStack } from "@tamagui/stacks";
|
|
13
|
-
import
|
|
15
|
+
import { useControllableState } from "@tamagui/use-controllable-state";
|
|
16
|
+
import React, { Children, cloneElement, forwardRef, isValidElement } from "react";
|
|
14
17
|
import { ScrollView } from "react-native";
|
|
18
|
+
import { useIndex, useIndexedChildren } from "reforest";
|
|
19
|
+
const GROUP_NAME = "Group";
|
|
20
|
+
const [createGroupContext, createGroupScope] = createContextScope(GROUP_NAME);
|
|
21
|
+
const [GroupProvider, useGroupContext] = createGroupContext(GROUP_NAME);
|
|
15
22
|
const GroupFrame = styled(ThemeableStack, {
|
|
16
23
|
name: "GroupFrame",
|
|
17
|
-
backgroundColor: "$background",
|
|
18
|
-
y: 0,
|
|
19
24
|
variants: {
|
|
25
|
+
unstyled: {
|
|
26
|
+
false: {
|
|
27
|
+
y: 0,
|
|
28
|
+
backgroundColor: "$background",
|
|
29
|
+
size: "$true"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
20
32
|
size: (val, { tokens }) => {
|
|
21
33
|
const borderRadius = tokens.radius[val] ?? val ?? tokens.radius["$true"];
|
|
22
34
|
return {
|
|
@@ -25,102 +37,167 @@ const GroupFrame = styled(ThemeableStack, {
|
|
|
25
37
|
}
|
|
26
38
|
},
|
|
27
39
|
defaultVariants: {
|
|
28
|
-
|
|
40
|
+
unstyled: false
|
|
29
41
|
}
|
|
30
42
|
});
|
|
31
43
|
function createGroup(verticalDefault) {
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
...hasRadius && {
|
|
63
|
-
...isFirst && !vertical && {
|
|
64
|
-
borderTopLeftRadius: radius,
|
|
65
|
-
borderBottomLeftRadius: radius
|
|
66
|
-
},
|
|
67
|
-
...isFirst && vertical && {
|
|
68
|
-
borderTopLeftRadius: radius,
|
|
69
|
-
borderTopRightRadius: radius
|
|
70
|
-
},
|
|
71
|
-
...isLast && !vertical && {
|
|
72
|
-
borderTopRightRadius: radius,
|
|
73
|
-
borderBottomRightRadius: radius
|
|
74
|
-
},
|
|
75
|
-
...isLast && vertical && {
|
|
76
|
-
borderBottomLeftRadius: radius,
|
|
77
|
-
borderBottomRightRadius: radius
|
|
78
|
-
}
|
|
44
|
+
return withStaticProperties(
|
|
45
|
+
forwardRef((props, ref) => {
|
|
46
|
+
const activeProps = useMediaPropsActive(props);
|
|
47
|
+
const {
|
|
48
|
+
__scopeGroup,
|
|
49
|
+
children: childrenProp,
|
|
50
|
+
space,
|
|
51
|
+
size = "$true",
|
|
52
|
+
spaceDirection,
|
|
53
|
+
separator,
|
|
54
|
+
scrollable,
|
|
55
|
+
axis = verticalDefault ? "vertical" : "horizontal",
|
|
56
|
+
disabled: disabledProp,
|
|
57
|
+
disablePassBorderRadius: disablePassBorderRadiusProp,
|
|
58
|
+
borderRadius,
|
|
59
|
+
forceUseItem,
|
|
60
|
+
...restProps
|
|
61
|
+
} = getExpandedShorthands(activeProps);
|
|
62
|
+
const vertical = axis === "vertical";
|
|
63
|
+
const [itemChildrenCount, setItemChildrenCount] = useControllableState({
|
|
64
|
+
defaultProp: forceUseItem ? 1 : 0
|
|
65
|
+
});
|
|
66
|
+
const isUsingItems = itemChildrenCount > 0;
|
|
67
|
+
const radius = borderRadius ?? (size ? getVariableValue(getTokens().radius[size]) - 1 : void 0);
|
|
68
|
+
const hasRadius = radius !== void 0;
|
|
69
|
+
const disablePassBorderRadius = disablePassBorderRadiusProp ?? !hasRadius;
|
|
70
|
+
const childrenArray = Children.toArray(childrenProp);
|
|
71
|
+
const children = isUsingItems ? childrenProp : childrenArray.map((child, i) => {
|
|
72
|
+
if (!isValidElement(child)) {
|
|
73
|
+
return child;
|
|
79
74
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
const disabled = child.props.disabled ?? disabledProp;
|
|
76
|
+
const isFirst = i === 0;
|
|
77
|
+
const isLast = i === childrenArray.length - 1;
|
|
78
|
+
const radiusStyles = disablePassBorderRadius ? null : getBorderRadius({ isFirst, isLast, radius, vertical });
|
|
79
|
+
const props2 = {
|
|
80
|
+
disabled,
|
|
81
|
+
...isTamaguiElement(child) ? radiusStyles : { style: radiusStyles }
|
|
82
|
+
};
|
|
83
|
+
return cloneElementWithPropOrder(child, props2);
|
|
84
|
+
});
|
|
85
|
+
const indexedChildren = useIndexedChildren(
|
|
86
|
+
spacedChildren({
|
|
87
|
+
direction: spaceDirection,
|
|
88
|
+
separator,
|
|
89
|
+
space,
|
|
90
|
+
children
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
const onItemMount = React.useCallback(
|
|
94
|
+
() => setItemChildrenCount((prev) => prev + 1),
|
|
95
|
+
[]
|
|
96
|
+
);
|
|
97
|
+
const onItemUnmount = React.useCallback(
|
|
98
|
+
() => setItemChildrenCount((prev) => prev - 1),
|
|
99
|
+
[]
|
|
100
|
+
);
|
|
101
|
+
return <GroupProvider
|
|
102
|
+
disablePassBorderRadius={disablePassBorderRadius}
|
|
103
|
+
vertical={axis === "vertical"}
|
|
104
|
+
radius={radius}
|
|
105
|
+
disabled={disabledProp}
|
|
106
|
+
onItemMount={onItemMount}
|
|
107
|
+
onItemUnmount={onItemUnmount}
|
|
108
|
+
scope={__scopeGroup}
|
|
109
|
+
><GroupFrame
|
|
110
|
+
ref={ref}
|
|
111
|
+
size={size}
|
|
112
|
+
flexDirection={axis === "horizontal" ? "row" : "column"}
|
|
113
|
+
borderRadius={borderRadius}
|
|
114
|
+
{...restProps}
|
|
115
|
+
>{wrapScroll({ ...activeProps, axis }, indexedChildren)}</GroupFrame></GroupProvider>;
|
|
116
|
+
}),
|
|
117
|
+
{
|
|
118
|
+
Item: GroupItem
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
const GroupItem = (props) => {
|
|
123
|
+
const { __scopeGroup, children } = props;
|
|
124
|
+
const treeIndex = useIndex();
|
|
125
|
+
const context = useGroupContext("GroupItem", __scopeGroup);
|
|
126
|
+
React.useEffect(() => {
|
|
127
|
+
context.onItemMount();
|
|
128
|
+
return () => {
|
|
129
|
+
context.onItemUnmount();
|
|
130
|
+
};
|
|
131
|
+
}, []);
|
|
132
|
+
if (!isValidElement(children)) {
|
|
133
|
+
return children;
|
|
134
|
+
}
|
|
135
|
+
const disabled = children.props.disabled ?? context.disabled;
|
|
136
|
+
if (!treeIndex) {
|
|
137
|
+
throw Error("<Group.Item/> should only be used within a <Group/>");
|
|
138
|
+
}
|
|
139
|
+
const isFirst = treeIndex.index === 0;
|
|
140
|
+
const isLast = treeIndex.index === treeIndex.maxIndex;
|
|
141
|
+
let propsToPass = {
|
|
142
|
+
disabled
|
|
143
|
+
};
|
|
144
|
+
if (!context.disablePassBorderRadius) {
|
|
145
|
+
const radiusStyles = getBorderRadius({
|
|
146
|
+
radius: context.radius,
|
|
147
|
+
isFirst,
|
|
148
|
+
isLast,
|
|
149
|
+
vertical: context.vertical
|
|
86
150
|
});
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
})
|
|
101
|
-
)}</GroupFrame>;
|
|
151
|
+
if (isTamaguiElement(children)) {
|
|
152
|
+
propsToPass = { ...propsToPass, ...radiusStyles };
|
|
153
|
+
} else {
|
|
154
|
+
propsToPass.style = radiusStyles;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return cloneElement(children, {
|
|
158
|
+
...propsToPass,
|
|
159
|
+
// @ts-ignore
|
|
160
|
+
style: {
|
|
161
|
+
...children.props?.["style"],
|
|
162
|
+
...propsToPass.style
|
|
163
|
+
}
|
|
102
164
|
});
|
|
103
|
-
}
|
|
104
|
-
const
|
|
165
|
+
};
|
|
166
|
+
const Group = createGroup(true);
|
|
167
|
+
const YGroup = Group;
|
|
105
168
|
const XGroup = createGroup(false);
|
|
106
|
-
const wrapScroll = ({ scrollable,
|
|
169
|
+
const wrapScroll = ({ scrollable, axis, showScrollIndicator = false }, children) => {
|
|
107
170
|
if (scrollable)
|
|
108
171
|
return <ScrollView
|
|
109
|
-
{...vertical && {
|
|
172
|
+
{...axis === "vertical" && {
|
|
110
173
|
showsVerticalScrollIndicator: showScrollIndicator
|
|
111
174
|
}}
|
|
112
|
-
{
|
|
175
|
+
{...axis === "horizontal" && {
|
|
113
176
|
horizontal: true,
|
|
114
177
|
showsHorizontalScrollIndicator: showScrollIndicator
|
|
115
178
|
}}
|
|
116
179
|
>{children}</ScrollView>;
|
|
117
180
|
return children;
|
|
118
181
|
};
|
|
182
|
+
const getBorderRadius = ({
|
|
183
|
+
isFirst,
|
|
184
|
+
isLast,
|
|
185
|
+
radius,
|
|
186
|
+
vertical
|
|
187
|
+
}) => {
|
|
188
|
+
return {
|
|
189
|
+
borderTopLeftRadius: isFirst ? radius : 0,
|
|
190
|
+
borderTopRightRadius: vertical && isFirst || !vertical && isLast ? radius : 0,
|
|
191
|
+
borderBottomLeftRadius: vertical && isLast || !vertical && isFirst ? radius : 0,
|
|
192
|
+
borderBottomRightRadius: isLast ? radius : 0
|
|
193
|
+
};
|
|
194
|
+
};
|
|
119
195
|
const cloneElementWithPropOrder = (child, props) => {
|
|
120
196
|
const next = mergeProps(child.props, props, false, getConfig().shorthands)[0];
|
|
121
197
|
return React.cloneElement({ ...child, props: null }, next);
|
|
122
198
|
};
|
|
123
199
|
export {
|
|
200
|
+
Group,
|
|
124
201
|
GroupFrame,
|
|
125
202
|
XGroup,
|
|
126
203
|
YGroup
|