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
|
@@ -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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tamagui",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.21",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"*.css",
|
|
6
6
|
"setup.js"
|
|
@@ -40,59 +40,60 @@
|
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@tamagui/adapt": "^1.5.
|
|
44
|
-
"@tamagui/alert-dialog": "^1.5.
|
|
45
|
-
"@tamagui/animate-presence": "^1.5.
|
|
46
|
-
"@tamagui/avatar": "^1.5.
|
|
47
|
-
"@tamagui/button": "^1.5.
|
|
48
|
-
"@tamagui/card": "^1.5.
|
|
49
|
-
"@tamagui/checkbox": "^1.5.
|
|
50
|
-
"@tamagui/compose-refs": "^1.5.
|
|
51
|
-
"@tamagui/core": "^1.5.
|
|
52
|
-
"@tamagui/create-context": "^1.5.
|
|
53
|
-
"@tamagui/dialog": "^1.5.
|
|
54
|
-
"@tamagui/fake-react-native": "^1.5.
|
|
55
|
-
"@tamagui/focusable": "^1.5.
|
|
56
|
-
"@tamagui/font-size": "^1.5.
|
|
57
|
-
"@tamagui/form": "^1.5.
|
|
58
|
-
"@tamagui/get-button-sized": "^1.5.
|
|
59
|
-
"@tamagui/get-font-sized": "^1.5.
|
|
60
|
-
"@tamagui/get-size": "^1.5.
|
|
61
|
-
"@tamagui/helpers": "^1.5.
|
|
62
|
-
"@tamagui/helpers-tamagui": "^1.5.
|
|
63
|
-
"@tamagui/image": "^1.5.
|
|
64
|
-
"@tamagui/label": "^1.5.
|
|
65
|
-
"@tamagui/linear-gradient": "^1.5.
|
|
66
|
-
"@tamagui/list-item": "^1.5.
|
|
67
|
-
"@tamagui/popover": "^1.5.
|
|
68
|
-
"@tamagui/popper": "^1.5.
|
|
69
|
-
"@tamagui/portal": "^1.5.
|
|
70
|
-
"@tamagui/progress": "^1.5.
|
|
71
|
-
"@tamagui/radio-group": "^1.5.
|
|
72
|
-
"@tamagui/react-native-media-driver": "^1.5.
|
|
73
|
-
"@tamagui/scroll-view": "^1.5.
|
|
74
|
-
"@tamagui/select": "^1.5.
|
|
75
|
-
"@tamagui/separator": "^1.5.
|
|
76
|
-
"@tamagui/shapes": "^1.5.
|
|
77
|
-
"@tamagui/sheet": "^1.5.
|
|
78
|
-
"@tamagui/slider": "^1.5.
|
|
79
|
-
"@tamagui/stacks": "^1.5.
|
|
80
|
-
"@tamagui/switch": "^1.5.
|
|
81
|
-
"@tamagui/text": "^1.5.
|
|
82
|
-
"@tamagui/tooltip": "^1.5.
|
|
83
|
-
"@tamagui/use-controllable-state": "^1.5.
|
|
84
|
-
"@tamagui/use-debounce": "^1.5.
|
|
85
|
-
"@tamagui/use-event": "^1.5.
|
|
86
|
-
"@tamagui/use-force-update": "^1.5.
|
|
87
|
-
"@tamagui/use-window-dimensions": "^1.5.
|
|
88
|
-
"@tamagui/visually-hidden": "^1.5.
|
|
43
|
+
"@tamagui/adapt": "^1.5.21",
|
|
44
|
+
"@tamagui/alert-dialog": "^1.5.21",
|
|
45
|
+
"@tamagui/animate-presence": "^1.5.21",
|
|
46
|
+
"@tamagui/avatar": "^1.5.21",
|
|
47
|
+
"@tamagui/button": "^1.5.21",
|
|
48
|
+
"@tamagui/card": "^1.5.21",
|
|
49
|
+
"@tamagui/checkbox": "^1.5.21",
|
|
50
|
+
"@tamagui/compose-refs": "^1.5.21",
|
|
51
|
+
"@tamagui/core": "^1.5.21",
|
|
52
|
+
"@tamagui/create-context": "^1.5.21",
|
|
53
|
+
"@tamagui/dialog": "^1.5.21",
|
|
54
|
+
"@tamagui/fake-react-native": "^1.5.21",
|
|
55
|
+
"@tamagui/focusable": "^1.5.21",
|
|
56
|
+
"@tamagui/font-size": "^1.5.21",
|
|
57
|
+
"@tamagui/form": "^1.5.21",
|
|
58
|
+
"@tamagui/get-button-sized": "^1.5.21",
|
|
59
|
+
"@tamagui/get-font-sized": "^1.5.21",
|
|
60
|
+
"@tamagui/get-size": "^1.5.21",
|
|
61
|
+
"@tamagui/helpers": "^1.5.21",
|
|
62
|
+
"@tamagui/helpers-tamagui": "^1.5.21",
|
|
63
|
+
"@tamagui/image": "^1.5.21",
|
|
64
|
+
"@tamagui/label": "^1.5.21",
|
|
65
|
+
"@tamagui/linear-gradient": "^1.5.21",
|
|
66
|
+
"@tamagui/list-item": "^1.5.21",
|
|
67
|
+
"@tamagui/popover": "^1.5.21",
|
|
68
|
+
"@tamagui/popper": "^1.5.21",
|
|
69
|
+
"@tamagui/portal": "^1.5.21",
|
|
70
|
+
"@tamagui/progress": "^1.5.21",
|
|
71
|
+
"@tamagui/radio-group": "^1.5.21",
|
|
72
|
+
"@tamagui/react-native-media-driver": "^1.5.21",
|
|
73
|
+
"@tamagui/scroll-view": "^1.5.21",
|
|
74
|
+
"@tamagui/select": "^1.5.21",
|
|
75
|
+
"@tamagui/separator": "^1.5.21",
|
|
76
|
+
"@tamagui/shapes": "^1.5.21",
|
|
77
|
+
"@tamagui/sheet": "^1.5.21",
|
|
78
|
+
"@tamagui/slider": "^1.5.21",
|
|
79
|
+
"@tamagui/stacks": "^1.5.21",
|
|
80
|
+
"@tamagui/switch": "^1.5.21",
|
|
81
|
+
"@tamagui/text": "^1.5.21",
|
|
82
|
+
"@tamagui/tooltip": "^1.5.21",
|
|
83
|
+
"@tamagui/use-controllable-state": "^1.5.21",
|
|
84
|
+
"@tamagui/use-debounce": "^1.5.21",
|
|
85
|
+
"@tamagui/use-event": "^1.5.21",
|
|
86
|
+
"@tamagui/use-force-update": "^1.5.21",
|
|
87
|
+
"@tamagui/use-window-dimensions": "^1.5.21",
|
|
88
|
+
"@tamagui/visually-hidden": "^1.5.21",
|
|
89
|
+
"reforest": "^0.12.1"
|
|
89
90
|
},
|
|
90
91
|
"peerDependencies": {
|
|
91
92
|
"react": "*",
|
|
92
93
|
"react-native-web": "*"
|
|
93
94
|
},
|
|
94
95
|
"devDependencies": {
|
|
95
|
-
"@tamagui/build": "^1.5.
|
|
96
|
+
"@tamagui/build": "^1.5.21",
|
|
96
97
|
"@types/node": "^16.11.9",
|
|
97
98
|
"@types/react": "^18.0.15",
|
|
98
99
|
"react": "^18.2.0",
|
package/src/views/Group.tsx
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GetProps,
|
|
3
3
|
TamaguiElement,
|
|
4
|
+
UnionableString,
|
|
5
|
+
Variable,
|
|
4
6
|
getConfig,
|
|
5
7
|
getExpandedShorthands,
|
|
6
8
|
getTokens,
|
|
@@ -10,17 +12,42 @@ import {
|
|
|
10
12
|
spacedChildren,
|
|
11
13
|
styled,
|
|
12
14
|
useMediaPropsActive,
|
|
15
|
+
withStaticProperties,
|
|
13
16
|
} from '@tamagui/core'
|
|
17
|
+
import { Scope, createContextScope } from '@tamagui/create-context'
|
|
14
18
|
import { ThemeableStack } from '@tamagui/stacks'
|
|
15
|
-
import
|
|
19
|
+
import { useControllableState } from '@tamagui/use-controllable-state'
|
|
20
|
+
import React, { Children, cloneElement, forwardRef, isValidElement } from 'react'
|
|
16
21
|
import { ScrollView } from 'react-native'
|
|
22
|
+
import { useIndex, useIndexedChildren } from 'reforest'
|
|
23
|
+
|
|
24
|
+
interface GroupContextValue {
|
|
25
|
+
vertical: boolean
|
|
26
|
+
disablePassBorderRadius: boolean
|
|
27
|
+
onItemMount: () => void
|
|
28
|
+
onItemUnmount: () => void
|
|
29
|
+
radius?: number | UnionableString | Variable<any>
|
|
30
|
+
disabled?: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const GROUP_NAME = 'Group'
|
|
34
|
+
|
|
35
|
+
type ScopedProps<P> = P & { __scopeGroup?: Scope }
|
|
36
|
+
const [createGroupContext, createGroupScope] = createContextScope(GROUP_NAME)
|
|
37
|
+
const [GroupProvider, useGroupContext] = createGroupContext<GroupContextValue>(GROUP_NAME)
|
|
17
38
|
|
|
18
39
|
export const GroupFrame = styled(ThemeableStack, {
|
|
19
40
|
name: 'GroupFrame',
|
|
20
|
-
backgroundColor: '$background',
|
|
21
|
-
y: 0,
|
|
22
41
|
|
|
23
42
|
variants: {
|
|
43
|
+
unstyled: {
|
|
44
|
+
false: {
|
|
45
|
+
y: 0,
|
|
46
|
+
backgroundColor: '$background',
|
|
47
|
+
size: '$true',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
|
|
24
51
|
size: (val, { tokens }) => {
|
|
25
52
|
const borderRadius = tokens.radius[val] ?? val ?? tokens.radius['$true']
|
|
26
53
|
return {
|
|
@@ -30,127 +57,198 @@ export const GroupFrame = styled(ThemeableStack, {
|
|
|
30
57
|
} as const,
|
|
31
58
|
|
|
32
59
|
defaultVariants: {
|
|
33
|
-
|
|
60
|
+
unstyled: false,
|
|
34
61
|
},
|
|
35
62
|
})
|
|
36
63
|
|
|
37
64
|
export type GroupProps = GetProps<typeof GroupFrame> & {
|
|
65
|
+
axis?: 'horizontal' | 'vertical'
|
|
66
|
+
|
|
38
67
|
scrollable?: boolean
|
|
39
68
|
/**
|
|
40
69
|
* @default false
|
|
41
70
|
*/
|
|
42
71
|
showScrollIndicator?: boolean
|
|
43
72
|
disabled?: boolean
|
|
44
|
-
vertical?: boolean
|
|
45
73
|
disablePassBorderRadius?: boolean
|
|
74
|
+
/**
|
|
75
|
+
* forces the group to use the Group.Item API
|
|
76
|
+
*/
|
|
77
|
+
forceUseItem?: boolean
|
|
46
78
|
}
|
|
47
79
|
|
|
48
80
|
function createGroup(verticalDefault: boolean) {
|
|
49
|
-
return
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const {
|
|
53
|
-
children: childrenProp,
|
|
54
|
-
space,
|
|
55
|
-
size = '$true',
|
|
56
|
-
spaceDirection,
|
|
57
|
-
separator,
|
|
58
|
-
scrollable,
|
|
59
|
-
vertical = verticalDefault,
|
|
60
|
-
disabled: disabledProp,
|
|
61
|
-
disablePassBorderRadius: disablePassBorderRadiusProp,
|
|
62
|
-
borderRadius,
|
|
63
|
-
...restProps
|
|
64
|
-
} = getExpandedShorthands(activeProps)
|
|
65
|
-
|
|
66
|
-
const radius =
|
|
67
|
-
borderRadius ?? (size ? getVariableValue(getTokens().radius[size]) - 1 : undefined)
|
|
68
|
-
|
|
69
|
-
const hasRadius = radius !== undefined
|
|
70
|
-
const disablePassBorderRadius = disablePassBorderRadiusProp ?? !hasRadius
|
|
71
|
-
const childrens = Children.toArray(childrenProp)
|
|
72
|
-
const children = childrens.map((child, i) => {
|
|
73
|
-
if (!isValidElement(child)) return child
|
|
74
|
-
const disabled = child.props.disabled ?? disabledProp
|
|
75
|
-
|
|
76
|
-
const isFirst = i === 0
|
|
77
|
-
const isLast = i === childrens.length - 1
|
|
78
|
-
|
|
79
|
-
const radiusStyles = disablePassBorderRadius
|
|
80
|
-
? null
|
|
81
|
-
: {
|
|
82
|
-
borderTopLeftRadius: 0,
|
|
83
|
-
borderTopRightRadius: 0,
|
|
84
|
-
borderBottomLeftRadius: 0,
|
|
85
|
-
borderBottomRightRadius: 0,
|
|
86
|
-
...(hasRadius && {
|
|
87
|
-
...(isFirst &&
|
|
88
|
-
!vertical && {
|
|
89
|
-
borderTopLeftRadius: radius,
|
|
90
|
-
borderBottomLeftRadius: radius,
|
|
91
|
-
}),
|
|
92
|
-
...(isFirst &&
|
|
93
|
-
vertical && {
|
|
94
|
-
borderTopLeftRadius: radius,
|
|
95
|
-
borderTopRightRadius: radius,
|
|
96
|
-
}),
|
|
97
|
-
...(isLast &&
|
|
98
|
-
!vertical && {
|
|
99
|
-
borderTopRightRadius: radius,
|
|
100
|
-
borderBottomRightRadius: radius,
|
|
101
|
-
}),
|
|
102
|
-
...(isLast &&
|
|
103
|
-
vertical && {
|
|
104
|
-
borderBottomLeftRadius: radius,
|
|
105
|
-
borderBottomRightRadius: radius,
|
|
106
|
-
}),
|
|
107
|
-
}),
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const props = {
|
|
111
|
-
disabled,
|
|
112
|
-
...(isTamaguiElement(child) ? radiusStyles : { style: radiusStyles }),
|
|
113
|
-
}
|
|
81
|
+
return withStaticProperties(
|
|
82
|
+
forwardRef<TamaguiElement, ScopedProps<GroupProps>>((props, ref) => {
|
|
83
|
+
const activeProps = useMediaPropsActive(props)
|
|
114
84
|
|
|
115
|
-
|
|
116
|
-
|
|
85
|
+
const {
|
|
86
|
+
__scopeGroup,
|
|
87
|
+
children: childrenProp,
|
|
88
|
+
space,
|
|
89
|
+
size = '$true',
|
|
90
|
+
spaceDirection,
|
|
91
|
+
separator,
|
|
92
|
+
scrollable,
|
|
93
|
+
axis = verticalDefault ? 'vertical' : 'horizontal',
|
|
94
|
+
disabled: disabledProp,
|
|
95
|
+
disablePassBorderRadius: disablePassBorderRadiusProp,
|
|
96
|
+
borderRadius,
|
|
97
|
+
forceUseItem,
|
|
98
|
+
...restProps
|
|
99
|
+
} = getExpandedShorthands(activeProps)
|
|
117
100
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
101
|
+
const vertical = axis === 'vertical'
|
|
102
|
+
const [itemChildrenCount, setItemChildrenCount] = useControllableState({
|
|
103
|
+
defaultProp: forceUseItem ? 1 : 0,
|
|
104
|
+
})
|
|
105
|
+
const isUsingItems = itemChildrenCount > 0
|
|
106
|
+
|
|
107
|
+
// 1 off given border to adjust for border radius? This should be user controllable
|
|
108
|
+
const radius =
|
|
109
|
+
borderRadius ??
|
|
110
|
+
(size ? getVariableValue(getTokens().radius[size]) - 1 : undefined)
|
|
111
|
+
|
|
112
|
+
const hasRadius = radius !== undefined
|
|
113
|
+
const disablePassBorderRadius = disablePassBorderRadiusProp ?? !hasRadius
|
|
114
|
+
|
|
115
|
+
const childrenArray = Children.toArray(childrenProp)
|
|
116
|
+
const children = isUsingItems
|
|
117
|
+
? childrenProp
|
|
118
|
+
: childrenArray.map((child, i) => {
|
|
119
|
+
if (!isValidElement(child)) {
|
|
120
|
+
return child
|
|
121
|
+
}
|
|
122
|
+
const disabled = child.props.disabled ?? disabledProp
|
|
123
|
+
|
|
124
|
+
const isFirst = i === 0
|
|
125
|
+
const isLast = i === childrenArray.length - 1
|
|
126
|
+
|
|
127
|
+
const radiusStyles = disablePassBorderRadius
|
|
128
|
+
? null
|
|
129
|
+
: getBorderRadius({ isFirst, isLast, radius, vertical })
|
|
130
|
+
const props = {
|
|
131
|
+
disabled,
|
|
132
|
+
...(isTamaguiElement(child) ? radiusStyles : { style: radiusStyles }),
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return cloneElementWithPropOrder(child, props)
|
|
133
136
|
})
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
+
|
|
138
|
+
const indexedChildren = useIndexedChildren(
|
|
139
|
+
spacedChildren({
|
|
140
|
+
direction: spaceDirection,
|
|
141
|
+
separator,
|
|
142
|
+
space,
|
|
143
|
+
children,
|
|
144
|
+
})
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
const onItemMount = React.useCallback(
|
|
148
|
+
() => setItemChildrenCount((prev) => prev + 1),
|
|
149
|
+
[]
|
|
150
|
+
)
|
|
151
|
+
const onItemUnmount = React.useCallback(
|
|
152
|
+
() => setItemChildrenCount((prev) => prev - 1),
|
|
153
|
+
[]
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
<GroupProvider
|
|
158
|
+
disablePassBorderRadius={disablePassBorderRadius}
|
|
159
|
+
vertical={axis === 'vertical'}
|
|
160
|
+
radius={radius}
|
|
161
|
+
disabled={disabledProp}
|
|
162
|
+
onItemMount={onItemMount}
|
|
163
|
+
onItemUnmount={onItemUnmount}
|
|
164
|
+
scope={__scopeGroup}
|
|
165
|
+
>
|
|
166
|
+
<GroupFrame
|
|
167
|
+
ref={ref}
|
|
168
|
+
size={size}
|
|
169
|
+
flexDirection={axis === 'horizontal' ? 'row' : 'column'}
|
|
170
|
+
borderRadius={borderRadius}
|
|
171
|
+
{...restProps}
|
|
172
|
+
>
|
|
173
|
+
{wrapScroll({ ...activeProps, axis }, indexedChildren)}
|
|
174
|
+
</GroupFrame>
|
|
175
|
+
</GroupProvider>
|
|
176
|
+
)
|
|
177
|
+
}),
|
|
178
|
+
{
|
|
179
|
+
Item: GroupItem,
|
|
180
|
+
}
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const GroupItem = (props: ScopedProps<{ children: React.ReactNode }>) => {
|
|
185
|
+
const { __scopeGroup, children } = props
|
|
186
|
+
const treeIndex = useIndex()
|
|
187
|
+
const context = useGroupContext('GroupItem', __scopeGroup)
|
|
188
|
+
|
|
189
|
+
React.useEffect(() => {
|
|
190
|
+
context.onItemMount()
|
|
191
|
+
return () => {
|
|
192
|
+
context.onItemUnmount()
|
|
193
|
+
}
|
|
194
|
+
}, [])
|
|
195
|
+
|
|
196
|
+
if (!isValidElement(children)) {
|
|
197
|
+
return children as any
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const disabled = children.props.disabled ?? context.disabled
|
|
201
|
+
|
|
202
|
+
if (!treeIndex) {
|
|
203
|
+
throw Error('<Group.Item/> should only be used within a <Group/>')
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const isFirst = treeIndex.index === 0
|
|
207
|
+
const isLast = treeIndex.index === treeIndex.maxIndex
|
|
208
|
+
|
|
209
|
+
let propsToPass: Record<string, any> = {
|
|
210
|
+
disabled,
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!context.disablePassBorderRadius) {
|
|
214
|
+
const radiusStyles = getBorderRadius({
|
|
215
|
+
radius: context.radius,
|
|
216
|
+
isFirst,
|
|
217
|
+
isLast,
|
|
218
|
+
vertical: context.vertical,
|
|
219
|
+
})
|
|
220
|
+
if (isTamaguiElement(children)) {
|
|
221
|
+
propsToPass = { ...propsToPass, ...radiusStyles }
|
|
222
|
+
} else {
|
|
223
|
+
propsToPass.style = radiusStyles
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return cloneElement(children, {
|
|
228
|
+
...propsToPass,
|
|
229
|
+
// @ts-ignore
|
|
230
|
+
style: {
|
|
231
|
+
...children.props?.['style'],
|
|
232
|
+
...propsToPass.style,
|
|
233
|
+
},
|
|
137
234
|
})
|
|
138
235
|
}
|
|
139
236
|
|
|
140
|
-
export const
|
|
237
|
+
export const Group = createGroup(true)
|
|
238
|
+
export const YGroup = Group
|
|
141
239
|
export const XGroup = createGroup(false)
|
|
142
240
|
|
|
143
241
|
const wrapScroll = (
|
|
144
|
-
{ scrollable,
|
|
242
|
+
{ scrollable, axis, showScrollIndicator = false }: GroupProps,
|
|
145
243
|
children: any
|
|
146
244
|
) => {
|
|
147
245
|
if (scrollable)
|
|
148
246
|
return (
|
|
149
247
|
<ScrollView
|
|
150
|
-
{...(vertical && {
|
|
248
|
+
{...(axis === 'vertical' && {
|
|
151
249
|
showsVerticalScrollIndicator: showScrollIndicator,
|
|
152
250
|
})}
|
|
153
|
-
{...(
|
|
251
|
+
{...(axis === 'horizontal' && {
|
|
154
252
|
horizontal: true,
|
|
155
253
|
showsHorizontalScrollIndicator: showScrollIndicator,
|
|
156
254
|
})}
|
|
@@ -161,6 +259,26 @@ const wrapScroll = (
|
|
|
161
259
|
return children
|
|
162
260
|
}
|
|
163
261
|
|
|
262
|
+
const getBorderRadius = ({
|
|
263
|
+
isFirst,
|
|
264
|
+
isLast,
|
|
265
|
+
radius,
|
|
266
|
+
vertical,
|
|
267
|
+
}: {
|
|
268
|
+
radius: any
|
|
269
|
+
vertical: boolean
|
|
270
|
+
isFirst: boolean
|
|
271
|
+
isLast: boolean
|
|
272
|
+
}) => {
|
|
273
|
+
// TODO: RTL support would be nice here
|
|
274
|
+
return {
|
|
275
|
+
borderTopLeftRadius: isFirst ? radius : 0,
|
|
276
|
+
borderTopRightRadius: (vertical && isFirst) || (!vertical && isLast) ? radius : 0,
|
|
277
|
+
borderBottomLeftRadius: (vertical && isLast) || (!vertical && isFirst) ? radius : 0,
|
|
278
|
+
borderBottomRightRadius: isLast ? radius : 0,
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
164
282
|
const cloneElementWithPropOrder = (child: any, props: Object) => {
|
|
165
283
|
const next = mergeProps(child.props, props, false, getConfig().shorthands)[0]
|
|
166
284
|
return React.cloneElement({ ...child, props: null }, next)
|