panelui-native 0.6.0 → 0.9.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/README.md +1 -1
- package/lib/module/components/accordion/index.js +7 -5
- package/lib/module/components/accordion/index.js.map +1 -1
- package/lib/module/components/alert/index.js +3 -6
- package/lib/module/components/alert/index.js.map +1 -1
- package/lib/module/components/attachment/index.js +219 -0
- package/lib/module/components/attachment/index.js.map +1 -0
- package/lib/module/components/bottom-sheet/index.js +82 -4
- package/lib/module/components/bottom-sheet/index.js.map +1 -1
- package/lib/module/components/button/index.js +36 -1
- package/lib/module/components/button/index.js.map +1 -1
- package/lib/module/components/dialog/index.js +6 -2
- package/lib/module/components/dialog/index.js.map +1 -1
- package/lib/module/components/empty-state/index.js +98 -22
- package/lib/module/components/empty-state/index.js.map +1 -1
- package/lib/module/components/inline-select/index.js +171 -46
- package/lib/module/components/inline-select/index.js.map +1 -1
- package/lib/module/components/input/index.js +28 -5
- package/lib/module/components/input/index.js.map +1 -1
- package/lib/module/components/input-group/index.js +0 -1
- package/lib/module/components/input-group/index.js.map +1 -1
- package/lib/module/components/item/index.js +359 -0
- package/lib/module/components/item/index.js.map +1 -0
- package/lib/module/components/label/index.js +5 -3
- package/lib/module/components/label/index.js.map +1 -1
- package/lib/module/components/line-chart/index.js +1024 -0
- package/lib/module/components/line-chart/index.js.map +1 -0
- package/lib/module/components/marker/index.js +190 -0
- package/lib/module/components/marker/index.js.map +1 -0
- package/lib/module/components/message/index.js +334 -0
- package/lib/module/components/message/index.js.map +1 -0
- package/lib/module/components/message-scroller/index.js +451 -0
- package/lib/module/components/message-scroller/index.js.map +1 -0
- package/lib/module/components/popover/index.js +500 -0
- package/lib/module/components/popover/index.js.map +1 -0
- package/lib/module/components/radio-group/index.js +104 -16
- package/lib/module/components/radio-group/index.js.map +1 -1
- package/lib/module/components/scroll-fade/index.js +119 -71
- package/lib/module/components/scroll-fade/index.js.map +1 -1
- package/lib/module/components/select/index.js +35 -6
- package/lib/module/components/select/index.js.map +1 -1
- package/lib/module/components/separator/index.js +91 -0
- package/lib/module/components/separator/index.js.map +1 -0
- package/lib/module/components/shimmer/index.js +111 -64
- package/lib/module/components/shimmer/index.js.map +1 -1
- package/lib/module/components/surface/index.js +24 -4
- package/lib/module/components/surface/index.js.map +1 -1
- package/lib/module/components/switch/index.js +20 -1
- package/lib/module/components/switch/index.js.map +1 -1
- package/lib/module/components/toast/index.js +7 -8
- package/lib/module/components/toast/index.js.map +1 -1
- package/lib/module/components/typography/index.js +3 -3
- package/lib/module/hooks/index.js +1 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/use-breakpoint.js +2 -2
- package/lib/module/hooks/use-copy-to-clipboard.js +0 -2
- package/lib/module/hooks/use-copy-to-clipboard.js.map +1 -1
- package/lib/module/hooks/use-keyboard-avoidance.js +120 -0
- package/lib/module/hooks/use-keyboard-avoidance.js.map +1 -0
- package/lib/module/icons/index.js +73 -4
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/index.js +13 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/index.js +53 -0
- package/lib/module/native/index.js.map +1 -0
- package/lib/module/primitives/keyboard-avoider.js +40 -0
- package/lib/module/primitives/keyboard-avoider.js.map +1 -0
- package/lib/module/primitives/scrim.js +72 -0
- package/lib/module/primitives/scrim.js.map +1 -0
- package/lib/module/providers/panel-ui-provider.js +24 -4
- package/lib/module/providers/panel-ui-provider.js.map +1 -1
- package/lib/module/theme/use-theme.js +1 -1
- package/lib/typescript/src/components/accordion/index.d.ts +7 -5
- package/lib/typescript/src/components/accordion/index.d.ts.map +1 -1
- package/lib/typescript/src/components/alert/index.d.ts +3 -6
- package/lib/typescript/src/components/alert/index.d.ts.map +1 -1
- package/lib/typescript/src/components/attachment/index.d.ts +93 -0
- package/lib/typescript/src/components/attachment/index.d.ts.map +1 -0
- package/lib/typescript/src/components/bottom-sheet/index.d.ts +27 -2
- package/lib/typescript/src/components/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/src/components/button/index.d.ts +11 -0
- package/lib/typescript/src/components/button/index.d.ts.map +1 -1
- package/lib/typescript/src/components/dialog/index.d.ts +7 -1
- package/lib/typescript/src/components/dialog/index.d.ts.map +1 -1
- package/lib/typescript/src/components/empty-state/index.d.ts +156 -7
- package/lib/typescript/src/components/empty-state/index.d.ts.map +1 -1
- package/lib/typescript/src/components/inline-select/index.d.ts +29 -6
- package/lib/typescript/src/components/inline-select/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input/index.d.ts +13 -0
- package/lib/typescript/src/components/input/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input-group/index.d.ts +0 -1
- package/lib/typescript/src/components/input-group/index.d.ts.map +1 -1
- package/lib/typescript/src/components/item/index.d.ts +286 -0
- package/lib/typescript/src/components/item/index.d.ts.map +1 -0
- package/lib/typescript/src/components/label/index.d.ts +5 -3
- package/lib/typescript/src/components/label/index.d.ts.map +1 -1
- package/lib/typescript/src/components/line-chart/index.d.ts +247 -0
- package/lib/typescript/src/components/line-chart/index.d.ts.map +1 -0
- package/lib/typescript/src/components/marker/index.d.ts +137 -0
- package/lib/typescript/src/components/marker/index.d.ts.map +1 -0
- package/lib/typescript/src/components/message/index.d.ts +177 -0
- package/lib/typescript/src/components/message/index.d.ts.map +1 -0
- package/lib/typescript/src/components/message-scroller/index.d.ts +150 -0
- package/lib/typescript/src/components/message-scroller/index.d.ts.map +1 -0
- package/lib/typescript/src/components/popover/index.d.ts +130 -0
- package/lib/typescript/src/components/popover/index.d.ts.map +1 -0
- package/lib/typescript/src/components/radio-group/index.d.ts +32 -0
- package/lib/typescript/src/components/radio-group/index.d.ts.map +1 -1
- package/lib/typescript/src/components/scroll-fade/index.d.ts +18 -9
- package/lib/typescript/src/components/scroll-fade/index.d.ts.map +1 -1
- package/lib/typescript/src/components/select/index.d.ts +16 -1
- package/lib/typescript/src/components/select/index.d.ts.map +1 -1
- package/lib/typescript/src/components/separator/index.d.ts +47 -0
- package/lib/typescript/src/components/separator/index.d.ts.map +1 -0
- package/lib/typescript/src/components/shimmer/index.d.ts +38 -20
- package/lib/typescript/src/components/shimmer/index.d.ts.map +1 -1
- package/lib/typescript/src/components/surface/index.d.ts +51 -2
- package/lib/typescript/src/components/surface/index.d.ts.map +1 -1
- package/lib/typescript/src/components/switch/index.d.ts +10 -0
- package/lib/typescript/src/components/switch/index.d.ts.map +1 -1
- package/lib/typescript/src/components/toast/index.d.ts +4 -4
- package/lib/typescript/src/components/toast/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/index.d.ts +1 -0
- package/lib/typescript/src/hooks/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-breakpoint.d.ts +2 -2
- package/lib/typescript/src/hooks/use-copy-to-clipboard.d.ts +0 -2
- package/lib/typescript/src/hooks/use-copy-to-clipboard.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts +20 -0
- package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts.map +1 -0
- package/lib/typescript/src/icons/index.d.ts +10 -4
- package/lib/typescript/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +11 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native/index.d.ts +35 -0
- package/lib/typescript/src/native/index.d.ts.map +1 -0
- package/lib/typescript/src/primitives/keyboard-avoider.d.ts +22 -0
- package/lib/typescript/src/primitives/keyboard-avoider.d.ts.map +1 -0
- package/lib/typescript/src/primitives/scrim.d.ts +21 -0
- package/lib/typescript/src/primitives/scrim.d.ts.map +1 -0
- package/lib/typescript/src/providers/panel-ui-provider.d.ts +1 -1
- package/lib/typescript/src/providers/panel-ui-provider.d.ts.map +1 -1
- package/lib/typescript/src/theme/use-theme.d.ts +1 -1
- package/package.json +16 -3
- package/src/components/accordion/index.tsx +7 -5
- package/src/components/alert/index.tsx +3 -6
- package/src/components/attachment/index.tsx +279 -0
- package/src/components/bottom-sheet/index.tsx +102 -2
- package/src/components/button/index.tsx +52 -0
- package/src/components/dialog/index.tsx +10 -1
- package/src/components/empty-state/index.tsx +64 -19
- package/src/components/inline-select/index.tsx +191 -44
- package/src/components/input/index.tsx +39 -3
- package/src/components/input-group/index.tsx +0 -1
- package/src/components/item/index.tsx +387 -0
- package/src/components/label/index.tsx +5 -3
- package/src/components/line-chart/index.tsx +1224 -0
- package/src/components/marker/index.tsx +194 -0
- package/src/components/message/index.tsx +336 -0
- package/src/components/message-scroller/index.tsx +574 -0
- package/src/components/popover/index.tsx +599 -0
- package/src/components/radio-group/index.tsx +108 -17
- package/src/components/scroll-fade/index.tsx +163 -51
- package/src/components/select/index.tsx +54 -9
- package/src/components/separator/index.tsx +97 -0
- package/src/components/shimmer/index.tsx +151 -58
- package/src/components/surface/index.tsx +32 -5
- package/src/components/switch/index.tsx +27 -1
- package/src/components/toast/index.tsx +7 -8
- package/src/components/typography/index.tsx +3 -3
- package/src/hooks/index.ts +5 -0
- package/src/hooks/use-breakpoint.ts +2 -2
- package/src/hooks/use-copy-to-clipboard.ts +0 -2
- package/src/hooks/use-keyboard-avoidance.ts +140 -0
- package/src/icons/index.tsx +52 -4
- package/src/index.ts +92 -0
- package/src/native/index.ts +79 -0
- package/src/primitives/keyboard-avoider.tsx +49 -0
- package/src/primitives/scrim.tsx +95 -0
- package/src/providers/panel-ui-provider.tsx +30 -9
- package/src/theme/use-theme.ts +1 -1
- package/theme.css +63 -3
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Item — a row of content: media on one side, a title and description in the
|
|
3
|
+
* middle, actions on the other side.
|
|
4
|
+
*
|
|
5
|
+
* It is the shape almost every list in an app already has — a settings row, a
|
|
6
|
+
* file in a picker, a member in a team list, a tool call in a transcript — so
|
|
7
|
+
* it exists as one composable primitive rather than being rebuilt per screen
|
|
8
|
+
* with slightly different padding each time.
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <Item variant="outline">
|
|
12
|
+
* <Item.Media variant="icon"><ReceiptIcon /></Item.Media>
|
|
13
|
+
* <Item.Content>
|
|
14
|
+
* <Item.Title>Invoice.pdf</Item.Title>
|
|
15
|
+
* <Item.Description>2.4 MB · Updated yesterday</Item.Description>
|
|
16
|
+
* </Item.Content>
|
|
17
|
+
* <Item.Actions><Button size="sm">Open</Button></Item.Actions>
|
|
18
|
+
* </Item>
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Two axes, and they are independent. `orientation` on the item decides
|
|
22
|
+
* whether its own parts sit side by side or stack into a card; `orientation`
|
|
23
|
+
* on `Item.Group` decides whether the items themselves run down the screen or
|
|
24
|
+
* across it. A carousel wants both set to the non-default: a horizontal group
|
|
25
|
+
* of vertical items.
|
|
26
|
+
*/
|
|
27
|
+
import { createContext, forwardRef, useContext, type ReactNode } from 'react';
|
|
28
|
+
import { View, type ViewProps } from 'react-native';
|
|
29
|
+
import { tv, type VariantProps } from 'tailwind-variants';
|
|
30
|
+
import { AnimatedPressable, type AnimatedPressableProps } from '../../primitives/animated-pressable';
|
|
31
|
+
import { Text, type TextProps } from '../../primitives/text';
|
|
32
|
+
import { cn } from '../../utils/cn';
|
|
33
|
+
|
|
34
|
+
type ItemSize = 'default' | 'sm' | 'xs';
|
|
35
|
+
type ItemOrientation = 'horizontal' | 'vertical';
|
|
36
|
+
|
|
37
|
+
const itemVariants = tv({
|
|
38
|
+
slots: {
|
|
39
|
+
root: 'gap-3 rounded-xl',
|
|
40
|
+
title: 'font-medium text-foreground',
|
|
41
|
+
description: 'text-muted-foreground',
|
|
42
|
+
},
|
|
43
|
+
variants: {
|
|
44
|
+
variant: {
|
|
45
|
+
default: {},
|
|
46
|
+
outline: { root: 'border border-border' },
|
|
47
|
+
muted: { root: 'bg-muted' },
|
|
48
|
+
},
|
|
49
|
+
size: {
|
|
50
|
+
default: { root: 'p-4', title: 'text-base', description: 'text-sm' },
|
|
51
|
+
sm: { root: 'p-3', title: 'text-sm', description: 'text-xs' },
|
|
52
|
+
xs: { root: 'gap-2 p-2', title: 'text-sm', description: 'text-xs' },
|
|
53
|
+
},
|
|
54
|
+
orientation: {
|
|
55
|
+
/** Media, text and actions side by side — the list-row shape. */
|
|
56
|
+
horizontal: { root: 'w-full flex-row items-center' },
|
|
57
|
+
/** Stacked into a card — the shape a horizontal carousel wants. */
|
|
58
|
+
vertical: { root: 'flex-col items-start' },
|
|
59
|
+
},
|
|
60
|
+
disabled: {
|
|
61
|
+
true: { root: 'opacity-[0.64]' },
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
defaultVariants: {
|
|
65
|
+
variant: 'default',
|
|
66
|
+
size: 'default',
|
|
67
|
+
orientation: 'horizontal',
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
/** Sub-components inherit the row's density and axis rather than repeating them. */
|
|
72
|
+
const ItemContext = createContext<{ size: ItemSize; orientation: ItemOrientation }>({
|
|
73
|
+
size: 'default',
|
|
74
|
+
orientation: 'horizontal',
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const mediaVariants = tv({
|
|
78
|
+
base: 'shrink-0 items-center justify-center',
|
|
79
|
+
variants: {
|
|
80
|
+
variant: {
|
|
81
|
+
/** No box — for an Avatar or anything that styles itself. */
|
|
82
|
+
default: '',
|
|
83
|
+
/** Rounded square tile sized for an icon. */
|
|
84
|
+
icon: 'rounded-lg border border-border bg-muted',
|
|
85
|
+
/** Clipped frame for an image or thumbnail. */
|
|
86
|
+
image: 'overflow-hidden rounded-lg bg-muted',
|
|
87
|
+
},
|
|
88
|
+
size: {
|
|
89
|
+
default: '',
|
|
90
|
+
sm: '',
|
|
91
|
+
xs: '',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
compoundVariants: [
|
|
95
|
+
{ variant: 'icon', size: 'default', class: 'h-10 w-10' },
|
|
96
|
+
{ variant: 'icon', size: 'sm', class: 'h-8 w-8' },
|
|
97
|
+
{ variant: 'icon', size: 'xs', class: 'h-6 w-6' },
|
|
98
|
+
{ variant: 'image', size: 'default', class: 'h-12 w-12' },
|
|
99
|
+
{ variant: 'image', size: 'sm', class: 'h-10 w-10' },
|
|
100
|
+
{ variant: 'image', size: 'xs', class: 'h-8 w-8' },
|
|
101
|
+
],
|
|
102
|
+
defaultVariants: {
|
|
103
|
+
variant: 'default',
|
|
104
|
+
size: 'default',
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export interface ItemProps
|
|
109
|
+
extends Omit<AnimatedPressableProps, 'children' | 'disabled'>,
|
|
110
|
+
Omit<VariantProps<typeof itemVariants>, 'disabled'> {
|
|
111
|
+
className?: string;
|
|
112
|
+
disabled?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Row density. `Item.Media`, `Item.Title` and `Item.Description` follow it,
|
|
115
|
+
* so it only needs setting here.
|
|
116
|
+
*/
|
|
117
|
+
size?: ItemSize;
|
|
118
|
+
/**
|
|
119
|
+
* `horizontal` is the list row: media, text and actions side by side.
|
|
120
|
+
* `vertical` stacks them into a card, which is what a horizontal carousel
|
|
121
|
+
* wants — and it is also what `Item.Header` and `Item.Footer` need, since
|
|
122
|
+
* both are full-width strips.
|
|
123
|
+
*/
|
|
124
|
+
orientation?: ItemOrientation;
|
|
125
|
+
children?: ReactNode;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Renders as a pressable when given `onPress`, and as a plain view otherwise,
|
|
130
|
+
* so a static row does not announce itself as a button.
|
|
131
|
+
*/
|
|
132
|
+
const ItemRoot = forwardRef<View, ItemProps>(
|
|
133
|
+
(
|
|
134
|
+
{
|
|
135
|
+
className,
|
|
136
|
+
variant,
|
|
137
|
+
size = 'default',
|
|
138
|
+
orientation = 'horizontal',
|
|
139
|
+
disabled,
|
|
140
|
+
children,
|
|
141
|
+
onPress,
|
|
142
|
+
...props
|
|
143
|
+
},
|
|
144
|
+
ref
|
|
145
|
+
) => {
|
|
146
|
+
const { root } = itemVariants({ variant, size, orientation, disabled: !!disabled });
|
|
147
|
+
|
|
148
|
+
const body = !onPress ? (
|
|
149
|
+
<View
|
|
150
|
+
ref={ref}
|
|
151
|
+
accessibilityState={{ disabled: !!disabled }}
|
|
152
|
+
className={root({ className })}
|
|
153
|
+
{...(props as ViewProps)}
|
|
154
|
+
>
|
|
155
|
+
{children}
|
|
156
|
+
</View>
|
|
157
|
+
) : (
|
|
158
|
+
<AnimatedPressable
|
|
159
|
+
ref={ref}
|
|
160
|
+
accessibilityRole="button"
|
|
161
|
+
accessibilityState={{ disabled: !!disabled }}
|
|
162
|
+
disabled={disabled}
|
|
163
|
+
onPress={onPress}
|
|
164
|
+
className={root({ className })}
|
|
165
|
+
{...props}
|
|
166
|
+
>
|
|
167
|
+
{children}
|
|
168
|
+
</AnimatedPressable>
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<ItemContext.Provider value={{ size, orientation }}>{body}</ItemContext.Provider>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
ItemRoot.displayName = 'Item';
|
|
177
|
+
|
|
178
|
+
export interface ItemGroupProps extends ViewProps {
|
|
179
|
+
className?: string;
|
|
180
|
+
/**
|
|
181
|
+
* `vertical` stacks the items — the settings-list shape. `horizontal` runs
|
|
182
|
+
* them across instead, for a carousel; pair it with a scrollable and
|
|
183
|
+
* `orientation="vertical"` on each item so every entry reads as a card.
|
|
184
|
+
*/
|
|
185
|
+
orientation?: ItemOrientation;
|
|
186
|
+
children?: ReactNode;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Stack of items. Pair with `Item.Separator` between them. */
|
|
190
|
+
const ItemGroup = forwardRef<View, ItemGroupProps>(
|
|
191
|
+
({ className, orientation = 'vertical', children, ...props }, ref) => (
|
|
192
|
+
<View
|
|
193
|
+
ref={ref}
|
|
194
|
+
accessibilityRole="list"
|
|
195
|
+
className={cn(
|
|
196
|
+
orientation === 'horizontal'
|
|
197
|
+
? 'flex-row items-stretch gap-3'
|
|
198
|
+
: 'w-full',
|
|
199
|
+
className
|
|
200
|
+
)}
|
|
201
|
+
{...props}
|
|
202
|
+
>
|
|
203
|
+
{children}
|
|
204
|
+
</View>
|
|
205
|
+
)
|
|
206
|
+
);
|
|
207
|
+
ItemGroup.displayName = 'Item.Group';
|
|
208
|
+
|
|
209
|
+
export interface ItemSeparatorProps extends ViewProps {
|
|
210
|
+
className?: string;
|
|
211
|
+
/** Match the group's axis: a horizontal group needs vertical hairlines. */
|
|
212
|
+
orientation?: ItemOrientation;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Hairline between rows in a group. */
|
|
216
|
+
const ItemSeparator = forwardRef<View, ItemSeparatorProps>(
|
|
217
|
+
({ className, orientation = 'vertical', ...props }, ref) => (
|
|
218
|
+
<View
|
|
219
|
+
ref={ref}
|
|
220
|
+
className={cn(
|
|
221
|
+
orientation === 'horizontal' ? 'h-full w-px' : 'h-px w-full',
|
|
222
|
+
'bg-border',
|
|
223
|
+
className
|
|
224
|
+
)}
|
|
225
|
+
{...props}
|
|
226
|
+
/>
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
ItemSeparator.displayName = 'Item.Separator';
|
|
230
|
+
|
|
231
|
+
export interface ItemMediaProps
|
|
232
|
+
extends ViewProps,
|
|
233
|
+
VariantProps<typeof mediaVariants> {
|
|
234
|
+
className?: string;
|
|
235
|
+
children?: ReactNode;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Leading slot: an icon tile, a thumbnail, or an avatar passed through. */
|
|
239
|
+
const ItemMedia = forwardRef<View, ItemMediaProps>(
|
|
240
|
+
({ className, variant, size, children, ...props }, ref) => {
|
|
241
|
+
const item = useContext(ItemContext);
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<View
|
|
245
|
+
ref={ref}
|
|
246
|
+
className={mediaVariants({ variant, size: size ?? item.size, className })}
|
|
247
|
+
{...props}
|
|
248
|
+
>
|
|
249
|
+
{children}
|
|
250
|
+
</View>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
ItemMedia.displayName = 'Item.Media';
|
|
255
|
+
|
|
256
|
+
export interface ItemContentProps extends ViewProps {
|
|
257
|
+
className?: string;
|
|
258
|
+
children?: ReactNode;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The text column. In a horizontal item it takes the remaining width so the
|
|
263
|
+
* actions stay pinned to the trailing edge; in a vertical one it just fills
|
|
264
|
+
* the width, because there is nothing beside it to push against.
|
|
265
|
+
*/
|
|
266
|
+
const ItemContent = forwardRef<View, ItemContentProps>(
|
|
267
|
+
({ className, children, ...props }, ref) => {
|
|
268
|
+
const { orientation } = useContext(ItemContext);
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
<View
|
|
272
|
+
ref={ref}
|
|
273
|
+
className={cn(
|
|
274
|
+
orientation === 'horizontal' ? 'flex-1' : 'w-full',
|
|
275
|
+
'gap-0.5',
|
|
276
|
+
className
|
|
277
|
+
)}
|
|
278
|
+
{...props}
|
|
279
|
+
>
|
|
280
|
+
{children}
|
|
281
|
+
</View>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
);
|
|
285
|
+
ItemContent.displayName = 'Item.Content';
|
|
286
|
+
|
|
287
|
+
export interface ItemTitleProps extends TextProps {
|
|
288
|
+
className?: string;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const ItemTitle = forwardRef<React.ElementRef<typeof Text>, ItemTitleProps>(
|
|
292
|
+
({ className, ...props }, ref) => {
|
|
293
|
+
const { size } = useContext(ItemContext);
|
|
294
|
+
const { title } = itemVariants({ size });
|
|
295
|
+
|
|
296
|
+
return <Text ref={ref} className={title({ className })} {...props} />;
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
ItemTitle.displayName = 'Item.Title';
|
|
300
|
+
|
|
301
|
+
export interface ItemDescriptionProps extends TextProps {
|
|
302
|
+
className?: string;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const ItemDescription = forwardRef<
|
|
306
|
+
React.ElementRef<typeof Text>,
|
|
307
|
+
ItemDescriptionProps
|
|
308
|
+
>(({ className, ...props }, ref) => {
|
|
309
|
+
const { size } = useContext(ItemContext);
|
|
310
|
+
const { description } = itemVariants({ size });
|
|
311
|
+
|
|
312
|
+
return <Text ref={ref} className={description({ className })} {...props} />;
|
|
313
|
+
});
|
|
314
|
+
ItemDescription.displayName = 'Item.Description';
|
|
315
|
+
|
|
316
|
+
export interface ItemActionsProps extends ViewProps {
|
|
317
|
+
className?: string;
|
|
318
|
+
children?: ReactNode;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** Trailing slot: buttons, a chevron, a switch. */
|
|
322
|
+
const ItemActions = forwardRef<View, ItemActionsProps>(
|
|
323
|
+
({ className, children, ...props }, ref) => (
|
|
324
|
+
<View
|
|
325
|
+
ref={ref}
|
|
326
|
+
className={cn('shrink-0 flex-row items-center gap-1.5', className)}
|
|
327
|
+
{...props}
|
|
328
|
+
>
|
|
329
|
+
{children}
|
|
330
|
+
</View>
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
ItemActions.displayName = 'Item.Actions';
|
|
334
|
+
|
|
335
|
+
export interface ItemHeaderProps extends ViewProps {
|
|
336
|
+
className?: string;
|
|
337
|
+
children?: ReactNode;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Full-width strip above the item's main content — an eyebrow label, a badge
|
|
342
|
+
* row. Needs `orientation="vertical"` on the item, since a strip only makes
|
|
343
|
+
* sense once the item stacks.
|
|
344
|
+
*/
|
|
345
|
+
const ItemHeader = forwardRef<View, ItemHeaderProps>(
|
|
346
|
+
({ className, children, ...props }, ref) => (
|
|
347
|
+
<View
|
|
348
|
+
ref={ref}
|
|
349
|
+
className={cn('w-full flex-row items-center justify-between gap-2', className)}
|
|
350
|
+
{...props}
|
|
351
|
+
>
|
|
352
|
+
{children}
|
|
353
|
+
</View>
|
|
354
|
+
)
|
|
355
|
+
);
|
|
356
|
+
ItemHeader.displayName = 'Item.Header';
|
|
357
|
+
|
|
358
|
+
export interface ItemFooterProps extends ViewProps {
|
|
359
|
+
className?: string;
|
|
360
|
+
children?: ReactNode;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/** Full-width strip below the row's main content. */
|
|
364
|
+
const ItemFooter = forwardRef<View, ItemFooterProps>(
|
|
365
|
+
({ className, children, ...props }, ref) => (
|
|
366
|
+
<View
|
|
367
|
+
ref={ref}
|
|
368
|
+
className={cn('w-full flex-row items-center gap-2', className)}
|
|
369
|
+
{...props}
|
|
370
|
+
>
|
|
371
|
+
{children}
|
|
372
|
+
</View>
|
|
373
|
+
)
|
|
374
|
+
);
|
|
375
|
+
ItemFooter.displayName = 'Item.Footer';
|
|
376
|
+
|
|
377
|
+
export const Item = Object.assign(ItemRoot, {
|
|
378
|
+
Group: ItemGroup,
|
|
379
|
+
Separator: ItemSeparator,
|
|
380
|
+
Media: ItemMedia,
|
|
381
|
+
Content: ItemContent,
|
|
382
|
+
Title: ItemTitle,
|
|
383
|
+
Description: ItemDescription,
|
|
384
|
+
Actions: ItemActions,
|
|
385
|
+
Header: ItemHeader,
|
|
386
|
+
Footer: ItemFooter,
|
|
387
|
+
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Label — text that names a form field.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* A string child is wrapped in `Label.Text` automatically, so the common case
|
|
5
|
+
* stays one line; pass the parts explicitly when the label needs more than
|
|
6
|
+
* text. `isRequired`, `isInvalid` and `isDisabled` are visual *and* semantic —
|
|
7
|
+
* they recolour and they set the accessibility state, so the two cannot drift
|
|
8
|
+
* apart.
|
|
7
9
|
*/
|
|
8
10
|
import {
|
|
9
11
|
createContext,
|