@brand-map/primitives 0.0.0-broken.0
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/.changeset/README.md +8 -0
- package/.changeset/config.json +11 -0
- package/.oxfmtrc.json +35 -0
- package/.oxlintrc.json +166 -0
- package/README.md +78 -0
- package/bun.lock +904 -0
- package/mise.toml +3 -0
- package/package.json +61 -0
- package/src/accordion/accordion.tsx +189 -0
- package/src/accordion/accordion.web.tsx +282 -0
- package/src/accordion/index.ts +2 -0
- package/src/accordion/types.ts +44 -0
- package/src/alert-dialog/alert-dialog.tsx +238 -0
- package/src/alert-dialog/alert-dialog.web.tsx +260 -0
- package/src/alert-dialog/index.ts +2 -0
- package/src/alert-dialog/types.ts +81 -0
- package/src/aspect-ratio/aspect-ratio.tsx +27 -0
- package/src/aspect-ratio/index.ts +1 -0
- package/src/avatar/avatar.tsx +122 -0
- package/src/avatar/index.ts +2 -0
- package/src/avatar/types.ts +20 -0
- package/src/checkbox/checkbox.tsx +95 -0
- package/src/checkbox/checkbox.web.tsx +111 -0
- package/src/checkbox/index.ts +2 -0
- package/src/checkbox/types.ts +14 -0
- package/src/collapsible/collapsible.tsx +98 -0
- package/src/collapsible/collapsible.web.tsx +149 -0
- package/src/collapsible/index.ts +2 -0
- package/src/collapsible/types.ts +23 -0
- package/src/context-menu/context-menu.tsx +616 -0
- package/src/context-menu/context-menu.web.tsx +560 -0
- package/src/context-menu/index.ts +2 -0
- package/src/context-menu/types.ts +136 -0
- package/src/dialog/dialog.tsx +286 -0
- package/src/dialog/dialog.web.tsx +215 -0
- package/src/dialog/index.ts +2 -0
- package/src/dialog/types.ts +92 -0
- package/src/dropdown-menu/dropdown-menu.tsx +575 -0
- package/src/dropdown-menu/dropdown-menu.web.tsx +565 -0
- package/src/dropdown-menu/index.ts +2 -0
- package/src/dropdown-menu/types.ts +121 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/use-Isomorphic-layout-effect.tsx +12 -0
- package/src/hooks/use-augmented-ref.tsx +25 -0
- package/src/hooks/use-controllable-state.tsx +70 -0
- package/src/hooks/use-relative-position.tsx +175 -0
- package/src/hover-card/hover-card.tsx +255 -0
- package/src/hover-card/hover-card.web.tsx +161 -0
- package/src/hover-card/index.ts +2 -0
- package/src/hover-card/types.ts +56 -0
- package/src/label/index.ts +2 -0
- package/src/label/label.tsx +36 -0
- package/src/label/label.web.tsx +38 -0
- package/src/label/types.ts +24 -0
- package/src/menubar/index.ts +2 -0
- package/src/menubar/menubar.tsx +602 -0
- package/src/menubar/menubar.web.tsx +575 -0
- package/src/menubar/types.ts +126 -0
- package/src/navigation-menu/index.ts +2 -0
- package/src/navigation-menu/navigation-menu.tsx +302 -0
- package/src/navigation-menu/navigation-menu.web.tsx +259 -0
- package/src/navigation-menu/types.ts +85 -0
- package/src/popover/index.ts +2 -0
- package/src/popover/popover.tsx +279 -0
- package/src/popover/popover.web.tsx +217 -0
- package/src/popover/types.ts +44 -0
- package/src/portal/index.ts +1 -0
- package/src/portal/portal.tsx +56 -0
- package/src/progress/index.ts +2 -0
- package/src/progress/progress.tsx +59 -0
- package/src/progress/progress.web.tsx +46 -0
- package/src/progress/types.ts +14 -0
- package/src/radio-group/index.ts +2 -0
- package/src/radio-group/radio-group.tsx +106 -0
- package/src/radio-group/radio-group.web.tsx +85 -0
- package/src/radio-group/types.ts +24 -0
- package/src/select/index.ts +2 -0
- package/src/select/select.tsx +447 -0
- package/src/select/select.web.tsx +368 -0
- package/src/select/types.ts +145 -0
- package/src/separator/index.ts +2 -0
- package/src/separator/separator.tsx +21 -0
- package/src/separator/types.ts +10 -0
- package/src/slider/index.ts +2 -0
- package/src/slider/slider.tsx +77 -0
- package/src/slider/slider.web.tsx +75 -0
- package/src/slider/types.ts +39 -0
- package/src/slot/index.ts +1 -0
- package/src/slot/slot.tsx +224 -0
- package/src/switch/index.ts +2 -0
- package/src/switch/switch.tsx +49 -0
- package/src/switch/switch.web.tsx +60 -0
- package/src/switch/types.ts +19 -0
- package/src/table/index.ts +1 -0
- package/src/table/table.tsx +121 -0
- package/src/tabs/index.ts +2 -0
- package/src/tabs/tabs.tsx +120 -0
- package/src/tabs/tabs.web.tsx +106 -0
- package/src/tabs/types.ts +37 -0
- package/src/toast/index.ts +2 -0
- package/src/toast/toast.tsx +124 -0
- package/src/toast/types.ts +20 -0
- package/src/toggle/index.ts +2 -0
- package/src/toggle/toggle.tsx +35 -0
- package/src/toggle/toggle.web.tsx +36 -0
- package/src/toggle/types.ts +11 -0
- package/src/toggle-group/index.ts +2 -0
- package/src/toggle-group/toggle-group.tsx +100 -0
- package/src/toggle-group/toggle-group.web.tsx +103 -0
- package/src/toggle-group/types.ts +46 -0
- package/src/toolbar/index.ts +2 -0
- package/src/toolbar/toolbar.tsx +141 -0
- package/src/toolbar/toolbar.web.tsx +158 -0
- package/src/toolbar/types.ts +64 -0
- package/src/tooltip/index.ts +2 -0
- package/src/tooltip/tooltip.tsx +261 -0
- package/src/tooltip/tooltip.web.tsx +175 -0
- package/src/tooltip/types.ts +61 -0
- package/src/types/index.ts +141 -0
- package/src/utils/index.ts +69 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { RenderViewProps, ViewRef } from "../types";
|
|
2
|
+
|
|
3
|
+
type RootProps = RenderViewProps & {
|
|
4
|
+
value: number;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
min?: number;
|
|
7
|
+
max?: number;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @platform: WEB ONLY
|
|
11
|
+
*/
|
|
12
|
+
dir?: "ltr" | "rtl";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @platform: WEB ONLY
|
|
16
|
+
*/
|
|
17
|
+
inverted?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @platform: WEB ONLY
|
|
21
|
+
*/
|
|
22
|
+
step?: number;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @platform: WEB ONLY
|
|
26
|
+
*/
|
|
27
|
+
onValueChange?: (value: number[]) => void;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type TrackProps = RenderViewProps;
|
|
31
|
+
type RangeProps = RenderViewProps;
|
|
32
|
+
type ThumbProps = RenderViewProps;
|
|
33
|
+
|
|
34
|
+
type RootRef = ViewRef;
|
|
35
|
+
type TrackRef = ViewRef;
|
|
36
|
+
type RangeRef = ViewRef;
|
|
37
|
+
type ThumbRef = ViewRef;
|
|
38
|
+
|
|
39
|
+
export type { RangeProps, RangeRef, RootProps, RootRef, ThumbProps, ThumbRef, TrackProps, TrackRef };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./slot";
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cloneElement, isValidElement } from "react";
|
|
3
|
+
import {
|
|
4
|
+
Image as ReactNativeImage,
|
|
5
|
+
Pressable as ReactNativePressable,
|
|
6
|
+
Text as ReactNativeText,
|
|
7
|
+
View as ReactNativeView,
|
|
8
|
+
StyleSheet,
|
|
9
|
+
type PressableStateCallbackType,
|
|
10
|
+
type ImageStyle as ReactNativeImageStyle,
|
|
11
|
+
type PressableProps as ReactNativePressableProps,
|
|
12
|
+
type StyleProp,
|
|
13
|
+
} from "react-native";
|
|
14
|
+
|
|
15
|
+
import { BrandMapUIComponentProps } from "../types";
|
|
16
|
+
|
|
17
|
+
// TODO: handle children as callback
|
|
18
|
+
|
|
19
|
+
const Pressable = (props: BrandMapUIComponentProps<typeof ReactNativePressable>): React.JSX.Element => {
|
|
20
|
+
const { children, render, ...rest } = props;
|
|
21
|
+
|
|
22
|
+
if (!render) {
|
|
23
|
+
return <ReactNativePressable {...rest}>{children}</ReactNativePressable>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!isValidElement(render)) {
|
|
27
|
+
console.log("Slot.Pressable - Invalid render prop", render);
|
|
28
|
+
return <></>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return cloneElement<React.ComponentPropsWithRef<typeof ReactNativePressable>>(
|
|
32
|
+
isTextChildren(render) ? <></> : render,
|
|
33
|
+
|
|
34
|
+
{
|
|
35
|
+
// @ts-expect-error
|
|
36
|
+
...mergeProps(rest, render.props),
|
|
37
|
+
|
|
38
|
+
// @ts-expect-error
|
|
39
|
+
ref: props.ref ? composeRefs(props.ref, render.ref) : render.ref,
|
|
40
|
+
children,
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
// Pressable.displayName = "SlotPressable";
|
|
45
|
+
|
|
46
|
+
const View = (props: BrandMapUIComponentProps<typeof ReactNativeView>): React.JSX.Element => {
|
|
47
|
+
const { children, render, ...rest } = props;
|
|
48
|
+
|
|
49
|
+
if (!render) {
|
|
50
|
+
return <ReactNativeView {...rest}>{children}</ReactNativeView>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (!isValidElement(render)) {
|
|
54
|
+
console.log("Slot.View - Invalid render prop", render);
|
|
55
|
+
return <></>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return cloneElement<React.ComponentPropsWithRef<typeof ReactNativeView>>(
|
|
59
|
+
isTextChildren(render) ? <></> : render,
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
// @ts-expect-error
|
|
63
|
+
...mergeProps(rest, render.props),
|
|
64
|
+
|
|
65
|
+
// @ts-expect-error
|
|
66
|
+
ref: props.ref ? composeRefs(props.ref, render.ref) : render.ref,
|
|
67
|
+
children,
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
};
|
|
71
|
+
// View.displayName = "SlotView";
|
|
72
|
+
|
|
73
|
+
const Text = (props: BrandMapUIComponentProps<typeof ReactNativeText>): React.JSX.Element => {
|
|
74
|
+
const { children, render, ...rest } = props;
|
|
75
|
+
|
|
76
|
+
if (!render) {
|
|
77
|
+
return <ReactNativeText {...rest}>{children}</ReactNativeText>;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!isValidElement(render)) {
|
|
81
|
+
console.log("Slot.Text - Invalid render prop", render);
|
|
82
|
+
return <></>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return cloneElement<React.ComponentPropsWithRef<typeof ReactNativeText>>(
|
|
86
|
+
isTextChildren(render) ? <></> : render,
|
|
87
|
+
|
|
88
|
+
{
|
|
89
|
+
// @ts-expect-error
|
|
90
|
+
...mergeProps(rest, render.props),
|
|
91
|
+
|
|
92
|
+
// @ts-expect-error
|
|
93
|
+
ref: props.ref ? composeRefs(props.ref, render.ref) : render.ref,
|
|
94
|
+
children,
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
// Text.displayName = "SlotText";
|
|
99
|
+
|
|
100
|
+
const Image = (props: BrandMapUIComponentProps<typeof ReactNativeImage> /** & { children?: React.ReactNode } */): React.JSX.Element => {
|
|
101
|
+
const { render, ...rest } = props;
|
|
102
|
+
|
|
103
|
+
if (!render) {
|
|
104
|
+
return <ReactNativeImage {...rest} />;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!isValidElement(render)) {
|
|
108
|
+
console.log("Slot.Image - Invalid render prop", render);
|
|
109
|
+
return <></>;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return cloneElement<React.ComponentPropsWithRef<typeof ReactNativeImage>>(isTextChildren(render) ? <></> : render, {
|
|
113
|
+
// @ts-expect-error
|
|
114
|
+
...mergeProps(rest, render.props),
|
|
115
|
+
|
|
116
|
+
// @ts-expect-error
|
|
117
|
+
ref: props.ref ? composeRefs(props.ref, render.ref) : render.ref,
|
|
118
|
+
// children,
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
// Image.displayName = "SlotImage";
|
|
122
|
+
|
|
123
|
+
export { Image, Pressable, Text, View };
|
|
124
|
+
|
|
125
|
+
// This project uses code from WorkOS/Radix Primitives.
|
|
126
|
+
// The code is licensed under the MIT License.
|
|
127
|
+
// https://github.com/radix-ui/primitives/tree/main
|
|
128
|
+
|
|
129
|
+
function composeRefs<T>(...refs: (React.Ref<T> | undefined)[]) {
|
|
130
|
+
return (node: T) => {
|
|
131
|
+
for (const ref of refs) {
|
|
132
|
+
switch (true) {
|
|
133
|
+
case !ref:
|
|
134
|
+
continue;
|
|
135
|
+
|
|
136
|
+
case typeof ref === "function":
|
|
137
|
+
ref(node);
|
|
138
|
+
continue;
|
|
139
|
+
|
|
140
|
+
case !!ref:
|
|
141
|
+
ref.current = node;
|
|
142
|
+
continue;
|
|
143
|
+
|
|
144
|
+
default:
|
|
145
|
+
throw new Error(`Must never reach. Invalid ref provided: ${ref}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
type AnyProps = Record<string, any>;
|
|
152
|
+
|
|
153
|
+
function mergeProps(slotProps: AnyProps, childProps: AnyProps) {
|
|
154
|
+
// all child props should override
|
|
155
|
+
const overrideProps = { ...childProps };
|
|
156
|
+
|
|
157
|
+
for (const propName in childProps) {
|
|
158
|
+
const slotPropValue = slotProps[propName];
|
|
159
|
+
const childPropValue = childProps[propName];
|
|
160
|
+
|
|
161
|
+
if (propName.startsWith("on")) {
|
|
162
|
+
if (!childPropValue && !slotPropValue) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// if the handler exists on both, we compose them
|
|
167
|
+
if (slotPropValue && childPropValue) {
|
|
168
|
+
overrideProps[propName] = (...args: any[]) => {
|
|
169
|
+
childPropValue(...args);
|
|
170
|
+
slotPropValue(...args);
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// but if it exists only on the slot, we use only this one
|
|
175
|
+
if (slotPropValue) {
|
|
176
|
+
overrideProps[propName] = slotPropValue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// if it's `style`, we merge them
|
|
183
|
+
if (propName === "style") {
|
|
184
|
+
overrideProps[propName] = combineStyles(slotPropValue, childPropValue);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// if it's `className`, we merge them
|
|
188
|
+
if (propName === "className") {
|
|
189
|
+
overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" ");
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return { ...slotProps, ...overrideProps };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
type PressableStyle = ReactNativePressableProps["style"];
|
|
197
|
+
type ImageStyle = StyleProp<ReactNativeImageStyle>;
|
|
198
|
+
type Style = PressableStyle | ImageStyle;
|
|
199
|
+
|
|
200
|
+
function combineStyles(slotStyle?: Style, childValue?: Style) {
|
|
201
|
+
if (typeof slotStyle === "function" && typeof childValue === "function") {
|
|
202
|
+
return (state: PressableStateCallbackType) => {
|
|
203
|
+
return StyleSheet.flatten([slotStyle(state), childValue(state)]);
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (typeof slotStyle === "function") {
|
|
208
|
+
return (state: PressableStateCallbackType) => {
|
|
209
|
+
return childValue ? StyleSheet.flatten([slotStyle(state), childValue]) : slotStyle(state);
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (typeof childValue === "function") {
|
|
214
|
+
return (state: PressableStateCallbackType) => {
|
|
215
|
+
return slotStyle ? StyleSheet.flatten([slotStyle, childValue(state)]) : childValue(state);
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return StyleSheet.flatten([slotStyle, childValue].filter(Boolean));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function isTextChildren(children: React.ReactNode | ((state: PressableStateCallbackType) => React.ReactNode)): children is string | string[] {
|
|
223
|
+
return Array.isArray(children) ? children.every((child) => typeof child === "string") : typeof children === "string";
|
|
224
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Pressable, View, type GestureResponderEvent } from "react-native";
|
|
3
|
+
|
|
4
|
+
import * as Slot from "../slot";
|
|
5
|
+
|
|
6
|
+
import type { RootProps, RootRef, ThumbProps, ThumbRef } from "./types";
|
|
7
|
+
|
|
8
|
+
const Root = React.forwardRef<RootRef, RootProps>(
|
|
9
|
+
({ render, checked, onCheckedChange, disabled, onPress: onPressProp, "aria-valuetext": ariaValueText, ...props }, ref) => {
|
|
10
|
+
function onPress(ev: GestureResponderEvent) {
|
|
11
|
+
if (disabled) return;
|
|
12
|
+
onCheckedChange(!checked);
|
|
13
|
+
onPressProp?.(ev);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Component
|
|
18
|
+
ref={ref}
|
|
19
|
+
aria-disabled={disabled}
|
|
20
|
+
role="switch"
|
|
21
|
+
aria-checked={checked}
|
|
22
|
+
aria-valuetext={(ariaValueText ?? checked) ? "on" : "off"}
|
|
23
|
+
onPress={onPress}
|
|
24
|
+
accessibilityState={{
|
|
25
|
+
checked,
|
|
26
|
+
disabled,
|
|
27
|
+
}}
|
|
28
|
+
disabled={disabled}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
Root.displayName = "RootNativeSwitch";
|
|
36
|
+
|
|
37
|
+
const Thumb = React.forwardRef<ThumbRef, ThumbProps>(({ ...props }, ref) => {
|
|
38
|
+
return (
|
|
39
|
+
<Component
|
|
40
|
+
ref={ref}
|
|
41
|
+
role="presentation"
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
Thumb.displayName = "ThumbNativeSwitch";
|
|
48
|
+
|
|
49
|
+
export { Root, Thumb };
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
|
|
5
|
+
// import * as Slot from "../slot";
|
|
6
|
+
|
|
7
|
+
// import type { RootProps, RootRef, ThumbProps, ThumbRef } from "./types";
|
|
8
|
+
|
|
9
|
+
// const Root = React.forwardRef<RootRef, RootProps>(
|
|
10
|
+
// ({ render, checked, onCheckedChange, disabled, onPress: onPressProp, onKeyDown: onKeyDownProp, ...props }, ref) => {
|
|
11
|
+
// function onPress(ev: GestureResponderEvent) {
|
|
12
|
+
// onCheckedChange(!checked);
|
|
13
|
+
// onPressProp?.(ev);
|
|
14
|
+
// }
|
|
15
|
+
|
|
16
|
+
// function onKeyDown(ev: React.KeyboardEvent) {
|
|
17
|
+
// onKeyDownProp?.(ev);
|
|
18
|
+
// if (ev.key === " ") {
|
|
19
|
+
// onCheckedChange(!checked);
|
|
20
|
+
// }
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
//
|
|
24
|
+
// return (
|
|
25
|
+
// <Switch.Root
|
|
26
|
+
// checked={checked}
|
|
27
|
+
// onCheckedChange={onCheckedChange}
|
|
28
|
+
// disabled={disabled}
|
|
29
|
+
// render
|
|
30
|
+
// >
|
|
31
|
+
// <Component
|
|
32
|
+
// ref={ref}
|
|
33
|
+
// disabled={disabled}
|
|
34
|
+
// onPress={onPress}
|
|
35
|
+
// // @ts-expect-error Web only
|
|
36
|
+
// onKeyDown={onKeyDown}
|
|
37
|
+
// {...props}
|
|
38
|
+
// />
|
|
39
|
+
// </Switch.Root>
|
|
40
|
+
// );
|
|
41
|
+
// },
|
|
42
|
+
// );
|
|
43
|
+
|
|
44
|
+
// Root.displayName = "RootWebSwitch";
|
|
45
|
+
|
|
46
|
+
// const Thumb = React.forwardRef<ThumbRef, ThumbProps>(({ ...props }, ref) => {
|
|
47
|
+
//
|
|
48
|
+
// return (
|
|
49
|
+
// <Switch.Thumb render>
|
|
50
|
+
// <Component
|
|
51
|
+
// ref={ref}
|
|
52
|
+
// {...props}
|
|
53
|
+
// />
|
|
54
|
+
// </Switch.Thumb>
|
|
55
|
+
// );
|
|
56
|
+
// });
|
|
57
|
+
|
|
58
|
+
// Thumb.displayName = "ThumbWebSwitch";
|
|
59
|
+
|
|
60
|
+
// export { Root, Thumb };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PressableRef, RenderPressableProps, RenderViewProps, ViewRef } from "../types";
|
|
2
|
+
|
|
3
|
+
type RootProps = RenderPressableProps & {
|
|
4
|
+
checked: boolean;
|
|
5
|
+
onCheckedChange: (checked: boolean) => void;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @platform: WEB ONLY
|
|
10
|
+
*/
|
|
11
|
+
onKeyDown?: (ev: React.KeyboardEvent) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type ThumbProps = RenderViewProps;
|
|
15
|
+
|
|
16
|
+
type RootRef = PressableRef;
|
|
17
|
+
type ThumbRef = ViewRef;
|
|
18
|
+
|
|
19
|
+
export type { RootProps, RootRef, ThumbProps, ThumbRef };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./table";
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Pressable, View } from "react-native";
|
|
3
|
+
|
|
4
|
+
import * as Slot from "../slot";
|
|
5
|
+
import type { PressableRef, RenderPressableProps, RenderViewProps, ViewRef } from "../types";
|
|
6
|
+
|
|
7
|
+
type RootProps = RenderViewProps;
|
|
8
|
+
type RootRef = ViewRef;
|
|
9
|
+
|
|
10
|
+
const Root = React.forwardRef<RootRef, RootProps>(({ ...props }, ref) => {
|
|
11
|
+
return (
|
|
12
|
+
<Component
|
|
13
|
+
role="table"
|
|
14
|
+
ref={ref}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
Root.displayName = "RootTable";
|
|
20
|
+
|
|
21
|
+
type HeaderProps = RenderViewProps;
|
|
22
|
+
type HeaderRef = ViewRef;
|
|
23
|
+
|
|
24
|
+
const Header = React.forwardRef<HeaderRef, HeaderProps>(({ ...props }, ref) => {
|
|
25
|
+
return (
|
|
26
|
+
<Component
|
|
27
|
+
role="rowheader"
|
|
28
|
+
ref={ref}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
Header.displayName = "HeaderTable";
|
|
34
|
+
|
|
35
|
+
type RowProps = RenderPressableProps;
|
|
36
|
+
type RowRef = PressableRef;
|
|
37
|
+
|
|
38
|
+
const Row = React.forwardRef<RowRef, RowProps>(({ ...props }, ref) => {
|
|
39
|
+
return (
|
|
40
|
+
<Component
|
|
41
|
+
ref={ref}
|
|
42
|
+
role="row"
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
Row.displayName = "RowTable";
|
|
48
|
+
|
|
49
|
+
type HeadProps = RenderViewProps;
|
|
50
|
+
type HeadRef = ViewRef;
|
|
51
|
+
|
|
52
|
+
const Head = React.forwardRef<HeadRef, HeadProps>(({ ...props }, ref) => {
|
|
53
|
+
return (
|
|
54
|
+
<Component
|
|
55
|
+
ref={ref}
|
|
56
|
+
role="columnheader"
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
Head.displayName = "HeadTable";
|
|
62
|
+
|
|
63
|
+
type BodyProps = RenderViewProps;
|
|
64
|
+
type BodyRef = ViewRef;
|
|
65
|
+
|
|
66
|
+
const Body = React.forwardRef<BodyRef, BodyProps>(({ ...props }, ref) => {
|
|
67
|
+
return (
|
|
68
|
+
<Component
|
|
69
|
+
ref={ref}
|
|
70
|
+
role="rowgroup"
|
|
71
|
+
{...props}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
Body.displayName = "BodyTable";
|
|
76
|
+
|
|
77
|
+
type CellProps = RenderViewProps;
|
|
78
|
+
type CellRef = ViewRef;
|
|
79
|
+
|
|
80
|
+
const Cell = React.forwardRef<CellRef, CellProps>(({ ...props }, ref) => {
|
|
81
|
+
return (
|
|
82
|
+
<Component
|
|
83
|
+
ref={ref}
|
|
84
|
+
role="cell"
|
|
85
|
+
{...props}
|
|
86
|
+
/>
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
Cell.displayName = "CellTable";
|
|
90
|
+
|
|
91
|
+
type FooterProps = RenderViewProps;
|
|
92
|
+
type FooterRef = ViewRef;
|
|
93
|
+
|
|
94
|
+
const Footer = React.forwardRef<FooterRef, FooterProps>(({ ...props }, ref) => {
|
|
95
|
+
return (
|
|
96
|
+
<Component
|
|
97
|
+
ref={ref}
|
|
98
|
+
role="rowgroup"
|
|
99
|
+
{...props}
|
|
100
|
+
/>
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
Footer.displayName = "FooterTable";
|
|
104
|
+
|
|
105
|
+
export { Body, Cell, Footer, Head, Header, Root, Row };
|
|
106
|
+
export type {
|
|
107
|
+
BodyProps,
|
|
108
|
+
BodyRef,
|
|
109
|
+
CellProps,
|
|
110
|
+
CellRef,
|
|
111
|
+
FooterProps,
|
|
112
|
+
FooterRef,
|
|
113
|
+
HeaderProps,
|
|
114
|
+
HeaderRef,
|
|
115
|
+
HeadProps,
|
|
116
|
+
HeadRef,
|
|
117
|
+
RootProps,
|
|
118
|
+
RootRef,
|
|
119
|
+
RowProps,
|
|
120
|
+
RowRef,
|
|
121
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Pressable, View, type GestureResponderEvent } from "react-native";
|
|
3
|
+
|
|
4
|
+
import * as Slot from "../slot";
|
|
5
|
+
|
|
6
|
+
import type { ContentProps, ContentRef, ListProps, ListRef, RootProps, RootRef, TriggerProps, TriggerRef } from "./types";
|
|
7
|
+
|
|
8
|
+
interface RootContext extends RootProps {
|
|
9
|
+
nativeID: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const TabsContext = React.createContext<RootContext | null>(null);
|
|
13
|
+
|
|
14
|
+
const Root = React.forwardRef<RootRef, RootProps>(
|
|
15
|
+
({ render, value, onValueChange, orientation: _orientation, dir: _dir, activationMode: _activationMode, ...viewProps }, ref) => {
|
|
16
|
+
const nativeID = React.useId();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<TabsContext.Provider
|
|
20
|
+
value={{
|
|
21
|
+
value,
|
|
22
|
+
onValueChange,
|
|
23
|
+
nativeID,
|
|
24
|
+
}}
|
|
25
|
+
>
|
|
26
|
+
<Component
|
|
27
|
+
ref={ref}
|
|
28
|
+
{...viewProps}
|
|
29
|
+
/>
|
|
30
|
+
</TabsContext.Provider>
|
|
31
|
+
);
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
Root.displayName = "RootNativeTabs";
|
|
36
|
+
|
|
37
|
+
function useRootContext() {
|
|
38
|
+
const context = React.useContext(TabsContext);
|
|
39
|
+
if (!context) {
|
|
40
|
+
throw new Error("Tabs compound components cannot be rendered outside the Tabs component");
|
|
41
|
+
}
|
|
42
|
+
return context;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const List = React.forwardRef<ListRef, ListProps>(({ ...props }, ref) => {
|
|
46
|
+
return (
|
|
47
|
+
<Component
|
|
48
|
+
ref={ref}
|
|
49
|
+
role="tablist"
|
|
50
|
+
{...props}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
List.displayName = "ListNativeTabs";
|
|
56
|
+
|
|
57
|
+
const TriggerContext = React.createContext<{ value: string } | null>(null);
|
|
58
|
+
|
|
59
|
+
const Trigger = React.forwardRef<TriggerRef, TriggerProps>(({ onPress: onPressProp, disabled, value: tabValue, ...props }, ref) => {
|
|
60
|
+
const { onValueChange, value: rootValue, nativeID } = useRootContext();
|
|
61
|
+
|
|
62
|
+
function onPress(ev: GestureResponderEvent) {
|
|
63
|
+
if (disabled) return;
|
|
64
|
+
onValueChange(tabValue);
|
|
65
|
+
onPressProp?.(ev);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return (
|
|
69
|
+
<TriggerContext.Provider value={{ value: tabValue }}>
|
|
70
|
+
<Component
|
|
71
|
+
ref={ref}
|
|
72
|
+
nativeID={`${nativeID}-tab-${tabValue}`}
|
|
73
|
+
aria-disabled={!!disabled}
|
|
74
|
+
aria-selected={rootValue === tabValue}
|
|
75
|
+
role="tab"
|
|
76
|
+
onPress={onPress}
|
|
77
|
+
accessibilityState={{
|
|
78
|
+
selected: rootValue === tabValue,
|
|
79
|
+
disabled: !!disabled,
|
|
80
|
+
}}
|
|
81
|
+
disabled={!!disabled}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
</TriggerContext.Provider>
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
Trigger.displayName = "TriggerNativeTabs";
|
|
89
|
+
|
|
90
|
+
function useTriggerContext() {
|
|
91
|
+
const context = React.useContext(TriggerContext);
|
|
92
|
+
if (!context) {
|
|
93
|
+
throw new Error("Tabs.Trigger compound components cannot be rendered outside the Tabs.Trigger component");
|
|
94
|
+
}
|
|
95
|
+
return context;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const Content = React.forwardRef<ContentRef, ContentProps>(({ keepMounted, value: tabValue, ...props }, ref) => {
|
|
99
|
+
const { value: rootValue, nativeID } = useRootContext();
|
|
100
|
+
|
|
101
|
+
if (!keepMounted) {
|
|
102
|
+
if (rootValue !== tabValue) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return (
|
|
108
|
+
<Component
|
|
109
|
+
ref={ref}
|
|
110
|
+
aria-hidden={!(keepMounted || rootValue === tabValue)}
|
|
111
|
+
aria-labelledby={`${nativeID}-tab-${tabValue}`}
|
|
112
|
+
role="tabpanel"
|
|
113
|
+
{...props}
|
|
114
|
+
/>
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
Content.displayName = "ContentNativeTabs";
|
|
119
|
+
|
|
120
|
+
export { Content, List, Root, Trigger, useRootContext, useTriggerContext };
|