@react-native-reusables/cli 0.0.9 → 0.0.10
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/generated/components/primitives/accordion/accordion.tsx +216 -0
- package/dist/generated/components/primitives/accordion/accordion.web.tsx +295 -0
- package/dist/generated/components/primitives/accordion/index.ts +1 -0
- package/dist/generated/components/primitives/accordion/types.ts +45 -0
- package/dist/generated/components/primitives/alert-dialog/alert-dialog.tsx +237 -0
- package/dist/generated/components/primitives/alert-dialog/alert-dialog.web.tsx +256 -0
- package/dist/generated/components/primitives/alert-dialog/index.ts +1 -0
- package/dist/generated/components/primitives/alert-dialog/types.ts +48 -0
- package/dist/generated/components/primitives/aspect-ratio.tsx +23 -0
- package/dist/generated/components/primitives/avatar/ types.ts +10 -0
- package/dist/generated/components/primitives/avatar/index.tsx +95 -0
- package/dist/generated/components/primitives/checkbox/checkbox.tsx +101 -0
- package/dist/generated/components/primitives/checkbox/checkbox.web.tsx +114 -0
- package/dist/generated/components/primitives/checkbox/index.ts +1 -0
- package/dist/generated/components/primitives/checkbox/types.ts +11 -0
- package/dist/generated/components/primitives/collapsible/collapsible.tsx +119 -0
- package/dist/generated/components/primitives/collapsible/collapsible.web.tsx +157 -0
- package/dist/generated/components/primitives/collapsible/index.ts +1 -0
- package/dist/generated/components/primitives/collapsible/types.ts +18 -0
- package/dist/generated/components/primitives/context-menu/context-menu.tsx +626 -0
- package/dist/generated/components/primitives/context-menu/context-menu.web.tsx +504 -0
- package/dist/generated/components/primitives/context-menu/index.ts +1 -0
- package/dist/generated/components/primitives/context-menu/types.ts +82 -0
- package/dist/generated/components/primitives/dialog/dialog.tsx +211 -0
- package/dist/generated/components/primitives/dialog/dialog.web.tsx +197 -0
- package/dist/generated/components/primitives/dialog/index.ts +1 -0
- package/dist/generated/components/primitives/dialog/types.ts +60 -0
- package/dist/generated/components/primitives/dropdown-menu/dropdown-menu.tsx +584 -0
- package/dist/generated/components/primitives/dropdown-menu/dropdown-menu.web.tsx +521 -0
- package/dist/generated/components/primitives/dropdown-menu/index.ts +1 -0
- package/dist/generated/components/primitives/dropdown-menu/types.ts +71 -0
- package/dist/generated/components/primitives/hooks/index.ts +3 -0
- package/dist/generated/components/primitives/hooks/useAugmentedRef.tsx +29 -0
- package/dist/generated/components/primitives/hooks/useControllableState.tsx +75 -0
- package/dist/generated/components/primitives/hooks/useRelativePosition.tsx +227 -0
- package/dist/generated/components/primitives/hover-card/hover-card.tsx +271 -0
- package/dist/generated/components/primitives/hover-card/hover-card.web.tsx +145 -0
- package/dist/generated/components/primitives/hover-card/index.ts +1 -0
- package/dist/generated/components/primitives/hover-card/types.ts +42 -0
- package/dist/generated/components/primitives/label/index.ts +1 -0
- package/dist/generated/components/primitives/label/label.tsx +31 -0
- package/dist/generated/components/primitives/label/label.web.tsx +36 -0
- package/dist/generated/components/primitives/label/types.ts +15 -0
- package/dist/generated/components/primitives/menubar/index.ts +1 -0
- package/dist/generated/components/primitives/menubar/menubar.tsx +624 -0
- package/dist/generated/components/primitives/menubar/menubar.web.tsx +543 -0
- package/dist/generated/components/primitives/menubar/types.ts +76 -0
- package/dist/generated/components/primitives/navigation-menu/index.ts +1 -0
- package/dist/generated/components/primitives/navigation-menu/navigation-menu.tsx +315 -0
- package/dist/generated/components/primitives/navigation-menu/navigation-menu.web.tsx +264 -0
- package/dist/generated/components/primitives/navigation-menu/types.ts +49 -0
- package/dist/generated/components/primitives/popover/index.ts +1 -0
- package/dist/generated/components/primitives/popover/popover.tsx +286 -0
- package/dist/generated/components/primitives/popover/popover.web.tsx +179 -0
- package/dist/generated/components/primitives/popover/types.ts +30 -0
- package/dist/generated/components/primitives/portal.tsx +67 -0
- package/dist/generated/components/primitives/progress/index.ts +1 -0
- package/dist/generated/components/primitives/progress/progress.tsx +59 -0
- package/dist/generated/components/primitives/progress/progress.web.tsx +36 -0
- package/dist/generated/components/primitives/progress/types.ts +7 -0
- package/dist/generated/components/primitives/radio-group/index.ts +1 -0
- package/dist/generated/components/primitives/radio-group/radio-group.tsx +116 -0
- package/dist/generated/components/primitives/radio-group/radio-group.web.tsx +78 -0
- package/dist/generated/components/primitives/radio-group/types.ts +15 -0
- package/dist/generated/components/primitives/select/index.ts +1 -0
- package/dist/generated/components/primitives/select/select.tsx +455 -0
- package/dist/generated/components/primitives/select/select.web.tsx +319 -0
- package/dist/generated/components/primitives/select/types.ts +87 -0
- package/dist/generated/components/primitives/separator/ types.ts +6 -0
- package/dist/generated/components/primitives/separator/index.tsx +23 -0
- package/dist/generated/components/primitives/slider/index.ts +1 -0
- package/dist/generated/components/primitives/slider/slider.tsx +89 -0
- package/dist/generated/components/primitives/slider/slider.web.tsx +67 -0
- package/dist/generated/components/primitives/slider/types.ts +24 -0
- package/dist/generated/components/primitives/slot.tsx +187 -0
- package/dist/generated/components/primitives/switch/index.ts +1 -0
- package/dist/generated/components/primitives/switch/switch.tsx +65 -0
- package/dist/generated/components/primitives/switch/switch.web.tsx +67 -0
- package/dist/generated/components/primitives/switch/types.ts +11 -0
- package/dist/generated/components/primitives/table.tsx +55 -0
- package/dist/generated/components/primitives/tabs/index.ts +1 -0
- package/dist/generated/components/primitives/tabs/tabs.tsx +133 -0
- package/dist/generated/components/primitives/tabs/tabs.web.tsx +97 -0
- package/dist/generated/components/primitives/tabs/types.ts +24 -0
- package/dist/generated/components/primitives/toast/ types.ts +7 -0
- package/dist/generated/components/primitives/toast/index.tsx +128 -0
- package/dist/generated/components/primitives/toggle/index.ts +1 -0
- package/dist/generated/components/primitives/toggle/toggle.tsx +37 -0
- package/dist/generated/components/primitives/toggle/toggle.web.tsx +26 -0
- package/dist/generated/components/primitives/toggle/types.ts +7 -0
- package/dist/generated/components/primitives/toggle-group/index.ts +1 -0
- package/dist/generated/components/primitives/toggle-group/toggle-group.tsx +125 -0
- package/dist/generated/components/primitives/toggle-group/toggle-group.web.tsx +124 -0
- package/dist/generated/components/primitives/toggle-group/types.ts +37 -0
- package/dist/generated/components/primitives/toolbar/index.ts +1 -0
- package/dist/generated/components/primitives/toolbar/toolbar.tsx +125 -0
- package/dist/generated/components/primitives/toolbar/toolbar.web.tsx +129 -0
- package/dist/generated/components/primitives/toolbar/types.ts +39 -0
- package/dist/generated/components/primitives/tooltip/index.ts +1 -0
- package/dist/generated/components/primitives/tooltip/tooltip.tsx +271 -0
- package/dist/generated/components/primitives/tooltip/tooltip.web.tsx +167 -0
- package/dist/generated/components/primitives/tooltip/types.ts +44 -0
- package/dist/generated/components/primitives/types.ts +105 -0
- package/dist/generated/components/primitives/utils.ts +61 -0
- package/dist/generated/components/ui/accordion.tsx +127 -0
- package/dist/generated/components/ui/alert-dialog.tsx +167 -0
- package/dist/generated/components/ui/aspect-ratio.tsx +5 -0
- package/dist/generated/components/ui/avatar.tsx +44 -0
- package/dist/generated/components/ui/badge.tsx +51 -0
- package/dist/generated/components/ui/button.tsx +88 -0
- package/dist/generated/components/ui/card.tsx +67 -0
- package/dist/generated/components/ui/checkbox.tsx +34 -0
- package/dist/generated/components/ui/collapsible.tsx +9 -0
- package/dist/generated/components/ui/context-menu.tsx +244 -0
- package/dist/generated/components/ui/dialog.tsx +150 -0
- package/dist/generated/components/ui/dropdown-menu.tsx +244 -0
- package/dist/generated/components/ui/hover-card.tsx +45 -0
- package/dist/generated/components/ui/input.tsx +26 -0
- package/dist/generated/components/ui/label.tsx +28 -0
- package/dist/generated/components/ui/menubar.tsx +260 -0
- package/dist/generated/components/ui/navigation-menu.tsx +177 -0
- package/dist/generated/components/ui/popover.tsx +39 -0
- package/dist/generated/components/ui/radio-group.tsx +38 -0
- package/dist/generated/components/ui/select.tsx +181 -0
- package/dist/generated/components/ui/separator.tsx +23 -0
- package/dist/generated/components/ui/skeleton.tsx +39 -0
- package/dist/generated/components/ui/switch.tsx +97 -0
- package/dist/generated/components/ui/table.tsx +99 -0
- package/dist/generated/components/ui/tabs.tsx +65 -0
- package/dist/generated/components/ui/text.tsx +24 -0
- package/dist/generated/components/ui/textarea.tsx +28 -0
- package/dist/generated/components/ui/toggle-group.tsx +86 -0
- package/dist/generated/components/ui/toggle.tsx +85 -0
- package/dist/generated/components/ui/tooltip.tsx +36 -0
- package/dist/generated/components/ui/typography.tsx +204 -0
- package/package.json +8 -8
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Image as RNImage,
|
|
4
|
+
Pressable as RNPressable,
|
|
5
|
+
Text as RNText,
|
|
6
|
+
View as RNView,
|
|
7
|
+
StyleSheet,
|
|
8
|
+
type PressableStateCallbackType,
|
|
9
|
+
type ImageProps as RNImageProps,
|
|
10
|
+
type ImageStyle as RNImageStyle,
|
|
11
|
+
type PressableProps as RNPressableProps,
|
|
12
|
+
type TextProps as RNTextProps,
|
|
13
|
+
type ViewProps as RNViewProps,
|
|
14
|
+
type StyleProp,
|
|
15
|
+
} from 'react-native';
|
|
16
|
+
|
|
17
|
+
const Pressable = React.forwardRef<React.ElementRef<typeof RNPressable>, RNPressableProps>(
|
|
18
|
+
(props, forwardedRef) => {
|
|
19
|
+
const { children, ...pressableSlotProps } = props;
|
|
20
|
+
|
|
21
|
+
if (!React.isValidElement(children)) {
|
|
22
|
+
console.log('Slot.Pressable - Invalid asChild element', children);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return React.cloneElement<
|
|
27
|
+
React.ComponentPropsWithoutRef<typeof RNPressable>,
|
|
28
|
+
React.ElementRef<typeof RNPressable>
|
|
29
|
+
>(isTextChildren(children) ? <></> : children, {
|
|
30
|
+
...mergeProps(pressableSlotProps, children.props),
|
|
31
|
+
ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
Pressable.displayName = 'SlotPressable';
|
|
37
|
+
|
|
38
|
+
const View = React.forwardRef<React.ElementRef<typeof RNView>, RNViewProps>(
|
|
39
|
+
(props, forwardedRef) => {
|
|
40
|
+
const { children, ...viewSlotProps } = props;
|
|
41
|
+
|
|
42
|
+
if (!React.isValidElement(children)) {
|
|
43
|
+
console.log('Slot.View - Invalid asChild element', children);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return React.cloneElement<
|
|
48
|
+
React.ComponentPropsWithoutRef<typeof RNView>,
|
|
49
|
+
React.ElementRef<typeof RNView>
|
|
50
|
+
>(isTextChildren(children) ? <></> : children, {
|
|
51
|
+
...mergeProps(viewSlotProps, children.props),
|
|
52
|
+
ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
View.displayName = 'SlotView';
|
|
58
|
+
|
|
59
|
+
const Text = React.forwardRef<React.ElementRef<typeof RNText>, RNTextProps>(
|
|
60
|
+
(props, forwardedRef) => {
|
|
61
|
+
const { children, ...textSlotProps } = props;
|
|
62
|
+
|
|
63
|
+
if (!React.isValidElement(children)) {
|
|
64
|
+
console.log('Slot.Text - Invalid asChild element', children);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return React.cloneElement<
|
|
69
|
+
React.ComponentPropsWithoutRef<typeof RNText>,
|
|
70
|
+
React.ElementRef<typeof RNText>
|
|
71
|
+
>(isTextChildren(children) ? <></> : children, {
|
|
72
|
+
...mergeProps(textSlotProps, children.props),
|
|
73
|
+
ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
Text.displayName = 'SlotText';
|
|
79
|
+
|
|
80
|
+
type ImageSlotProps = RNImageProps & {
|
|
81
|
+
children?: React.ReactNode;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const Image = React.forwardRef<React.ElementRef<typeof RNImage>, ImageSlotProps>(
|
|
85
|
+
(props, forwardedRef) => {
|
|
86
|
+
const { children, ...imageSlotProps } = props;
|
|
87
|
+
|
|
88
|
+
if (!React.isValidElement(children)) {
|
|
89
|
+
console.log('Slot.Image - Invalid asChild element', children);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return React.cloneElement<
|
|
94
|
+
React.ComponentPropsWithoutRef<typeof RNImage>,
|
|
95
|
+
React.ElementRef<typeof RNImage>
|
|
96
|
+
>(isTextChildren(children) ? <></> : children, {
|
|
97
|
+
...mergeProps(imageSlotProps, children.props),
|
|
98
|
+
ref: forwardedRef ? composeRefs(forwardedRef, (children as any).ref) : (children as any).ref,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
Image.displayName = 'SlotImage';
|
|
104
|
+
|
|
105
|
+
export { Image, Pressable, Text, View };
|
|
106
|
+
|
|
107
|
+
// This project uses code from WorkOS/Radix Primitives.
|
|
108
|
+
// The code is licensed under the MIT License.
|
|
109
|
+
// https://github.com/radix-ui/primitives/tree/main
|
|
110
|
+
|
|
111
|
+
function composeRefs<T>(...refs: (React.Ref<T> | undefined)[]) {
|
|
112
|
+
return (node: T) =>
|
|
113
|
+
refs.forEach((ref) => {
|
|
114
|
+
if (typeof ref === 'function') {
|
|
115
|
+
ref(node);
|
|
116
|
+
} else if (ref != null) {
|
|
117
|
+
(ref as React.MutableRefObject<T>).current = node;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
type AnyProps = Record<string, any>;
|
|
123
|
+
|
|
124
|
+
function mergeProps(slotProps: AnyProps, childProps: AnyProps) {
|
|
125
|
+
// all child props should override
|
|
126
|
+
const overrideProps = { ...childProps };
|
|
127
|
+
|
|
128
|
+
for (const propName in childProps) {
|
|
129
|
+
const slotPropValue = slotProps[propName];
|
|
130
|
+
const childPropValue = childProps[propName];
|
|
131
|
+
|
|
132
|
+
const isHandler = /^on[A-Z]/.test(propName);
|
|
133
|
+
if (isHandler) {
|
|
134
|
+
// if the handler exists on both, we compose them
|
|
135
|
+
if (slotPropValue && childPropValue) {
|
|
136
|
+
overrideProps[propName] = (...args: unknown[]) => {
|
|
137
|
+
childPropValue(...args);
|
|
138
|
+
slotPropValue(...args);
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// but if it exists only on the slot, we use only this one
|
|
142
|
+
else if (slotPropValue) {
|
|
143
|
+
overrideProps[propName] = slotPropValue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// if it's `style`, we merge them
|
|
147
|
+
else if (propName === 'style') {
|
|
148
|
+
overrideProps[propName] = combineStyles(slotPropValue, childPropValue);
|
|
149
|
+
} else if (propName === 'className') {
|
|
150
|
+
overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(' ');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return { ...slotProps, ...overrideProps };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
type PressableStyle = RNPressableProps['style'];
|
|
158
|
+
type ImageStyle = StyleProp<RNImageStyle>;
|
|
159
|
+
type Style = PressableStyle | ImageStyle;
|
|
160
|
+
|
|
161
|
+
function combineStyles(slotStyle?: Style, childValue?: Style) {
|
|
162
|
+
if (typeof slotStyle === 'function' && typeof childValue === 'function') {
|
|
163
|
+
return (state: PressableStateCallbackType) => {
|
|
164
|
+
return StyleSheet.flatten([slotStyle(state), childValue(state)]);
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (typeof slotStyle === 'function') {
|
|
168
|
+
return (state: PressableStateCallbackType) => {
|
|
169
|
+
return childValue ? StyleSheet.flatten([slotStyle(state), childValue]) : slotStyle(state);
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (typeof childValue === 'function') {
|
|
173
|
+
return (state: PressableStateCallbackType) => {
|
|
174
|
+
return slotStyle ? StyleSheet.flatten([slotStyle, childValue(state)]) : childValue(state);
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return StyleSheet.flatten([slotStyle, childValue].filter(Boolean));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export function isTextChildren(
|
|
182
|
+
children: React.ReactNode | ((state: PressableStateCallbackType) => React.ReactNode)
|
|
183
|
+
) {
|
|
184
|
+
return Array.isArray(children)
|
|
185
|
+
? children.every((child) => typeof child === 'string')
|
|
186
|
+
: typeof children === 'string';
|
|
187
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './switch';
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Pressable, View, type GestureResponderEvent } from 'react-native';
|
|
3
|
+
import * as Slot from '@rnr/slot';
|
|
4
|
+
import type {
|
|
5
|
+
PressableRef,
|
|
6
|
+
SlottablePressableProps,
|
|
7
|
+
SlottableViewProps,
|
|
8
|
+
ViewRef,
|
|
9
|
+
} from '@rnr/types';
|
|
10
|
+
import type { SwitchRootProps } from './types';
|
|
11
|
+
|
|
12
|
+
const Root = React.forwardRef<
|
|
13
|
+
PressableRef,
|
|
14
|
+
SlottablePressableProps & SwitchRootProps
|
|
15
|
+
>(
|
|
16
|
+
(
|
|
17
|
+
{
|
|
18
|
+
asChild,
|
|
19
|
+
checked,
|
|
20
|
+
onCheckedChange,
|
|
21
|
+
disabled,
|
|
22
|
+
onPress: onPressProp,
|
|
23
|
+
'aria-valuetext': ariaValueText,
|
|
24
|
+
...props
|
|
25
|
+
},
|
|
26
|
+
ref
|
|
27
|
+
) => {
|
|
28
|
+
function onPress(ev: GestureResponderEvent) {
|
|
29
|
+
if (disabled) return;
|
|
30
|
+
onCheckedChange(!checked);
|
|
31
|
+
onPressProp?.(ev);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const Component = asChild ? Slot.Pressable : Pressable;
|
|
35
|
+
return (
|
|
36
|
+
<Component
|
|
37
|
+
ref={ref}
|
|
38
|
+
aria-disabled={disabled}
|
|
39
|
+
role='switch'
|
|
40
|
+
aria-checked={checked}
|
|
41
|
+
aria-valuetext={ariaValueText ?? checked ? 'on' : 'off'}
|
|
42
|
+
onPress={onPress}
|
|
43
|
+
accessibilityState={{
|
|
44
|
+
checked,
|
|
45
|
+
disabled,
|
|
46
|
+
}}
|
|
47
|
+
disabled={disabled}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
Root.displayName = 'RootNativeSwitch';
|
|
55
|
+
|
|
56
|
+
const Thumb = React.forwardRef<ViewRef, SlottableViewProps>(
|
|
57
|
+
({ asChild, ...props }, ref) => {
|
|
58
|
+
const Component = asChild ? Slot.View : View;
|
|
59
|
+
return <Component ref={ref} role='presentation' {...props} />;
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
Thumb.displayName = 'ThumbNativeSwitch';
|
|
64
|
+
|
|
65
|
+
export { Root, Thumb };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as Switch from '@radix-ui/react-switch';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Pressable, View, type GestureResponderEvent } from 'react-native';
|
|
4
|
+
import * as Slot from '@rnr/slot';
|
|
5
|
+
import type {
|
|
6
|
+
PressableRef,
|
|
7
|
+
SlottablePressableProps,
|
|
8
|
+
SlottableViewProps,
|
|
9
|
+
ViewRef,
|
|
10
|
+
} from '@rnr/types';
|
|
11
|
+
import type { SwitchRootProps } from './types';
|
|
12
|
+
|
|
13
|
+
const Root = React.forwardRef<PressableRef, SlottablePressableProps & SwitchRootProps>(
|
|
14
|
+
(
|
|
15
|
+
{
|
|
16
|
+
asChild,
|
|
17
|
+
checked,
|
|
18
|
+
onCheckedChange,
|
|
19
|
+
disabled,
|
|
20
|
+
onPress: onPressProp,
|
|
21
|
+
onKeyDown: onKeyDownProp,
|
|
22
|
+
...props
|
|
23
|
+
},
|
|
24
|
+
ref
|
|
25
|
+
) => {
|
|
26
|
+
function onPress(ev: GestureResponderEvent) {
|
|
27
|
+
onCheckedChange(!checked);
|
|
28
|
+
onPressProp?.(ev);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function onKeyDown(ev: React.KeyboardEvent) {
|
|
32
|
+
onKeyDownProp?.(ev);
|
|
33
|
+
if (ev.key === ' ') {
|
|
34
|
+
onCheckedChange(!checked);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const Component = asChild ? Slot.Pressable : Pressable;
|
|
39
|
+
return (
|
|
40
|
+
<Switch.Root checked={checked} onCheckedChange={onCheckedChange} disabled={disabled} asChild>
|
|
41
|
+
<Component
|
|
42
|
+
ref={ref}
|
|
43
|
+
disabled={disabled}
|
|
44
|
+
onPress={onPress}
|
|
45
|
+
// @ts-expect-error Web only
|
|
46
|
+
onKeyDown={onKeyDown}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
</Switch.Root>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
Root.displayName = 'RootWebSwitch';
|
|
55
|
+
|
|
56
|
+
const Thumb = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
57
|
+
const Component = asChild ? Slot.View : View;
|
|
58
|
+
return (
|
|
59
|
+
<Switch.Thumb asChild>
|
|
60
|
+
<Component ref={ref} {...props} />
|
|
61
|
+
</Switch.Thumb>
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
Thumb.displayName = 'ThumbWebSwitch';
|
|
66
|
+
|
|
67
|
+
export { Root, Thumb };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Pressable, View } from 'react-native';
|
|
3
|
+
import * as Slot from '@rnr/slot';
|
|
4
|
+
import type {
|
|
5
|
+
PressableRef,
|
|
6
|
+
SlottablePressableProps,
|
|
7
|
+
SlottableViewProps,
|
|
8
|
+
ViewRef,
|
|
9
|
+
} from '@rnr/types';
|
|
10
|
+
|
|
11
|
+
const Root = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
12
|
+
const Component = asChild ? Slot.View : View;
|
|
13
|
+
return <Component role='table' ref={ref} {...props} />;
|
|
14
|
+
});
|
|
15
|
+
Root.displayName = 'RootTable';
|
|
16
|
+
|
|
17
|
+
const Header = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
18
|
+
const Component = asChild ? Slot.View : View;
|
|
19
|
+
return <Component role='rowheader' ref={ref} {...props} />;
|
|
20
|
+
});
|
|
21
|
+
Header.displayName = 'HeaderTable';
|
|
22
|
+
|
|
23
|
+
const Row = React.forwardRef<PressableRef, SlottablePressableProps>(
|
|
24
|
+
({ asChild, ...props }, ref) => {
|
|
25
|
+
const Component = asChild ? Slot.Pressable : Pressable;
|
|
26
|
+
return <Component ref={ref} role='row' {...props} />;
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
Row.displayName = 'RowTable';
|
|
30
|
+
|
|
31
|
+
const Head = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
32
|
+
const Component = asChild ? Slot.View : View;
|
|
33
|
+
return <Component ref={ref} role='columnheader' {...props} />;
|
|
34
|
+
});
|
|
35
|
+
Head.displayName = 'HeadTable';
|
|
36
|
+
|
|
37
|
+
const Body = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
38
|
+
const Component = asChild ? Slot.View : View;
|
|
39
|
+
return <Component ref={ref} role='rowgroup' {...props} />;
|
|
40
|
+
});
|
|
41
|
+
Body.displayName = 'BodyTable';
|
|
42
|
+
|
|
43
|
+
const Cell = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
44
|
+
const Component = asChild ? Slot.View : View;
|
|
45
|
+
return <Component ref={ref} role='cell' {...props} />;
|
|
46
|
+
});
|
|
47
|
+
Cell.displayName = 'CellTable';
|
|
48
|
+
|
|
49
|
+
const Footer = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
50
|
+
const Component = asChild ? Slot.View : View;
|
|
51
|
+
return <Component ref={ref} role='rowgroup' {...props} />;
|
|
52
|
+
});
|
|
53
|
+
Footer.displayName = 'FooterTable';
|
|
54
|
+
|
|
55
|
+
export { Body, Cell, Footer, Head, Header, Root, Row };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './tabs';
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Pressable, View, type GestureResponderEvent } from 'react-native';
|
|
3
|
+
import * as Slot from '@rnr/slot';
|
|
4
|
+
import type { ComponentPropsWithAsChild, SlottableViewProps, ViewRef } from '@rnr/types';
|
|
5
|
+
import type { TabsContentProps, TabsRootProps } from './types';
|
|
6
|
+
|
|
7
|
+
interface RootContext extends TabsRootProps {
|
|
8
|
+
nativeID: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const TabsContext = React.createContext<RootContext | null>(null);
|
|
12
|
+
|
|
13
|
+
const Root = React.forwardRef<ViewRef, SlottableViewProps & TabsRootProps>(
|
|
14
|
+
(
|
|
15
|
+
{
|
|
16
|
+
asChild,
|
|
17
|
+
value,
|
|
18
|
+
onValueChange,
|
|
19
|
+
orientation: _orientation,
|
|
20
|
+
dir: _dir,
|
|
21
|
+
activationMode: _activationMode,
|
|
22
|
+
...viewProps
|
|
23
|
+
},
|
|
24
|
+
ref
|
|
25
|
+
) => {
|
|
26
|
+
const nativeID = React.useId();
|
|
27
|
+
const Component = asChild ? Slot.View : View;
|
|
28
|
+
return (
|
|
29
|
+
<TabsContext.Provider
|
|
30
|
+
value={{
|
|
31
|
+
value,
|
|
32
|
+
onValueChange,
|
|
33
|
+
nativeID,
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<Component ref={ref} {...viewProps} />
|
|
37
|
+
</TabsContext.Provider>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
Root.displayName = 'RootNativeTabs';
|
|
43
|
+
|
|
44
|
+
function useRootContext() {
|
|
45
|
+
const context = React.useContext(TabsContext);
|
|
46
|
+
if (!context) {
|
|
47
|
+
throw new Error('Tabs compound components cannot be rendered outside the Tabs component');
|
|
48
|
+
}
|
|
49
|
+
return context;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const List = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
53
|
+
const Component = asChild ? Slot.View : View;
|
|
54
|
+
return <Component ref={ref} role='tablist' {...props} />;
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
List.displayName = 'ListNativeTabs';
|
|
58
|
+
|
|
59
|
+
const TriggerContext = React.createContext<{ value: string } | null>(null);
|
|
60
|
+
|
|
61
|
+
const Trigger = React.forwardRef<
|
|
62
|
+
React.ElementRef<typeof Pressable>,
|
|
63
|
+
ComponentPropsWithAsChild<typeof Pressable> & {
|
|
64
|
+
value: string;
|
|
65
|
+
}
|
|
66
|
+
>(({ asChild, onPress: onPressProp, disabled, value: tabValue, ...props }, ref) => {
|
|
67
|
+
const { onValueChange, value: rootValue, nativeID } = useRootContext();
|
|
68
|
+
|
|
69
|
+
function onPress(ev: GestureResponderEvent) {
|
|
70
|
+
if (disabled) return;
|
|
71
|
+
onValueChange(tabValue);
|
|
72
|
+
onPressProp?.(ev);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const Component = asChild ? Slot.Pressable : Pressable;
|
|
76
|
+
return (
|
|
77
|
+
<TriggerContext.Provider value={{ value: tabValue }}>
|
|
78
|
+
<Component
|
|
79
|
+
ref={ref}
|
|
80
|
+
nativeID={`${nativeID}-tab-${tabValue}`}
|
|
81
|
+
aria-disabled={!!disabled}
|
|
82
|
+
aria-selected={rootValue === tabValue}
|
|
83
|
+
role='tab'
|
|
84
|
+
onPress={onPress}
|
|
85
|
+
accessibilityState={{
|
|
86
|
+
selected: rootValue === tabValue,
|
|
87
|
+
disabled: !!disabled,
|
|
88
|
+
}}
|
|
89
|
+
disabled={!!disabled}
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
</TriggerContext.Provider>
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
Trigger.displayName = 'TriggerNativeTabs';
|
|
97
|
+
|
|
98
|
+
function useTriggerContext() {
|
|
99
|
+
const context = React.useContext(TriggerContext);
|
|
100
|
+
if (!context) {
|
|
101
|
+
throw new Error(
|
|
102
|
+
'Tabs.Trigger compound components cannot be rendered outside the Tabs.Trigger component'
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
return context;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const Content = React.forwardRef<ViewRef, SlottableViewProps & TabsContentProps>(
|
|
109
|
+
({ asChild, forceMount, value: tabValue, ...props }, ref) => {
|
|
110
|
+
const { value: rootValue, nativeID } = useRootContext();
|
|
111
|
+
|
|
112
|
+
if (!forceMount) {
|
|
113
|
+
if (rootValue !== tabValue) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const Component = asChild ? Slot.View : View;
|
|
119
|
+
return (
|
|
120
|
+
<Component
|
|
121
|
+
ref={ref}
|
|
122
|
+
aria-hidden={!(forceMount || rootValue === tabValue)}
|
|
123
|
+
aria-labelledby={`${nativeID}-tab-${tabValue}`}
|
|
124
|
+
role='tabpanel'
|
|
125
|
+
{...props}
|
|
126
|
+
/>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
Content.displayName = 'ContentNativeTabs';
|
|
132
|
+
|
|
133
|
+
export { Content, List, Root, Trigger, useRootContext, useTriggerContext };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as Tabs from '@radix-ui/react-tabs';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Pressable, View } from 'react-native';
|
|
4
|
+
import * as Slot from '@rnr/slot';
|
|
5
|
+
import type { ComponentPropsWithAsChild, SlottableViewProps, ViewRef } from '@rnr/types';
|
|
6
|
+
import type { TabsContentProps, TabsRootProps } from './types';
|
|
7
|
+
|
|
8
|
+
const TabsContext = React.createContext<TabsRootProps | null>(null);
|
|
9
|
+
const Root = React.forwardRef<ViewRef, SlottableViewProps & TabsRootProps>(
|
|
10
|
+
({ asChild, value, onValueChange, orientation, dir, activationMode, ...viewProps }, ref) => {
|
|
11
|
+
const Component = asChild ? Slot.View : View;
|
|
12
|
+
return (
|
|
13
|
+
<TabsContext.Provider
|
|
14
|
+
value={{
|
|
15
|
+
value,
|
|
16
|
+
onValueChange,
|
|
17
|
+
}}
|
|
18
|
+
>
|
|
19
|
+
<Tabs.Root
|
|
20
|
+
value={value}
|
|
21
|
+
onValueChange={onValueChange}
|
|
22
|
+
orientation={orientation}
|
|
23
|
+
dir={dir}
|
|
24
|
+
activationMode={activationMode}
|
|
25
|
+
asChild
|
|
26
|
+
>
|
|
27
|
+
<Component ref={ref} {...viewProps} />
|
|
28
|
+
</Tabs.Root>
|
|
29
|
+
</TabsContext.Provider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
Root.displayName = 'RootWebTabs';
|
|
35
|
+
|
|
36
|
+
function useRootContext() {
|
|
37
|
+
const context = React.useContext(TabsContext);
|
|
38
|
+
if (!context) {
|
|
39
|
+
throw new Error('Tabs compound components cannot be rendered outside the Tabs component');
|
|
40
|
+
}
|
|
41
|
+
return context;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const List = React.forwardRef<ViewRef, SlottableViewProps>(({ asChild, ...props }, ref) => {
|
|
45
|
+
const Component = asChild ? Slot.View : View;
|
|
46
|
+
return (
|
|
47
|
+
<Tabs.List asChild>
|
|
48
|
+
<Component ref={ref} {...props} />
|
|
49
|
+
</Tabs.List>
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
List.displayName = 'ListWebTabs';
|
|
54
|
+
|
|
55
|
+
const TriggerContext = React.createContext<{ value: string } | null>(null);
|
|
56
|
+
const Trigger = React.forwardRef<
|
|
57
|
+
React.ElementRef<typeof Pressable>,
|
|
58
|
+
ComponentPropsWithAsChild<typeof Pressable> & {
|
|
59
|
+
value: string;
|
|
60
|
+
}
|
|
61
|
+
>(({ asChild, value: tabValue, ...props }, ref) => {
|
|
62
|
+
const Component = asChild ? Slot.Pressable : Pressable;
|
|
63
|
+
return (
|
|
64
|
+
<TriggerContext.Provider value={{ value: tabValue }}>
|
|
65
|
+
<Tabs.Trigger value={tabValue} asChild>
|
|
66
|
+
<Component ref={ref} {...props} />
|
|
67
|
+
</Tabs.Trigger>
|
|
68
|
+
</TriggerContext.Provider>
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
Trigger.displayName = 'TriggerWebTabs';
|
|
73
|
+
|
|
74
|
+
function useTriggerContext() {
|
|
75
|
+
const context = React.useContext(TriggerContext);
|
|
76
|
+
if (!context) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
'Tabs.Trigger compound components cannot be rendered outside the Tabs.Trigger component'
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return context;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const Content = React.forwardRef<ViewRef, SlottableViewProps & TabsContentProps>(
|
|
85
|
+
({ asChild, forceMount, value, ...props }, ref) => {
|
|
86
|
+
const Component = asChild ? Slot.View : View;
|
|
87
|
+
return (
|
|
88
|
+
<Tabs.Content value={value} asChild>
|
|
89
|
+
<Component ref={ref} {...props} />
|
|
90
|
+
</Tabs.Content>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
Content.displayName = 'ContentWebTabs';
|
|
96
|
+
|
|
97
|
+
export { Content, List, Root, Trigger, useRootContext, useTriggerContext };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ForceMountable } from '@rnr/types';
|
|
2
|
+
|
|
3
|
+
interface TabsRootProps {
|
|
4
|
+
value: string;
|
|
5
|
+
onValueChange: (value: string) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Platform: WEB ONLY
|
|
8
|
+
*/
|
|
9
|
+
orientation?: 'horizontal' | 'vertical';
|
|
10
|
+
/**
|
|
11
|
+
* Platform: WEB ONLY
|
|
12
|
+
*/
|
|
13
|
+
dir?: 'ltr' | 'rtl';
|
|
14
|
+
/**
|
|
15
|
+
* Platform: WEB ONLY
|
|
16
|
+
*/
|
|
17
|
+
activationMode?: 'automatic' | 'manual';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface TabsContentProps extends ForceMountable {
|
|
21
|
+
value: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type { TabsContentProps, TabsRootProps };
|