panelui-native 0.7.0 → 0.12.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 +5 -3
- 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 +53 -3
- package/lib/module/components/bottom-sheet/index.js.map +1 -1
- package/lib/module/components/button/index.js +19 -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 +94 -17
- package/lib/module/components/empty-state/index.js.map +1 -1
- package/lib/module/components/frame/index.js +128 -15
- package/lib/module/components/frame/index.js.map +1 -1
- package/lib/module/components/input/index.js +107 -15
- package/lib/module/components/input/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 +24 -8
- package/lib/module/components/message/index.js.map +1 -1
- 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 +511 -0
- package/lib/module/components/popover/index.js.map +1 -0
- package/lib/module/components/progress/index.js +52 -2
- package/lib/module/components/progress/index.js.map +1 -1
- package/lib/module/components/radio-group/index.js +132 -17
- package/lib/module/components/radio-group/index.js.map +1 -1
- package/lib/module/components/section-rail/index.js +355 -0
- package/lib/module/components/section-rail/index.js.map +1 -0
- package/lib/module/components/select/index.js +245 -56
- 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/slider/index.js +355 -0
- package/lib/module/components/slider/index.js.map +1 -0
- package/lib/module/components/surface/index.js +21 -2
- package/lib/module/components/surface/index.js.map +1 -1
- package/lib/module/components/switch/index.js +10 -1
- package/lib/module/components/switch/index.js.map +1 -1
- package/lib/module/components/tabs/index.js +186 -16
- package/lib/module/components/tabs/index.js.map +1 -1
- package/lib/module/components/toggle-button/index.js +297 -0
- package/lib/module/components/toggle-button/index.js.map +1 -0
- package/lib/module/hooks/index.js +1 -0
- package/lib/module/hooks/index.js.map +1 -1
- package/lib/module/hooks/use-keyboard-avoidance.js +57 -8
- package/lib/module/hooks/use-keyboard-avoidance.js.map +1 -1
- package/lib/module/hooks/use-scroll-sections.js +89 -0
- package/lib/module/hooks/use-scroll-sections.js.map +1 -0
- package/lib/module/icons/index.js +69 -0
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/index.js +11 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/index.js.map +1 -1
- package/lib/module/primitives/keyboard-avoider.js +2 -0
- package/lib/module/primitives/keyboard-avoider.js.map +1 -1
- package/lib/module/primitives/scrim.js +72 -0
- package/lib/module/primitives/scrim.js.map +1 -0
- package/lib/module/utils/haptics.js +57 -0
- package/lib/module/utils/haptics.js.map +1 -0
- 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 +6 -1
- package/lib/typescript/src/components/bottom-sheet/index.d.ts.map +1 -1
- package/lib/typescript/src/components/button/index.d.ts +9 -4
- 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 +152 -2
- package/lib/typescript/src/components/empty-state/index.d.ts.map +1 -1
- package/lib/typescript/src/components/frame/index.d.ts +47 -7
- package/lib/typescript/src/components/frame/index.d.ts.map +1 -1
- package/lib/typescript/src/components/input/index.d.ts +113 -2
- package/lib/typescript/src/components/input/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 +8 -1
- package/lib/typescript/src/components/message/index.d.ts.map +1 -1
- 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 +136 -0
- package/lib/typescript/src/components/popover/index.d.ts.map +1 -0
- package/lib/typescript/src/components/progress/index.d.ts +33 -0
- package/lib/typescript/src/components/progress/index.d.ts.map +1 -1
- package/lib/typescript/src/components/radio-group/index.d.ts +39 -0
- package/lib/typescript/src/components/radio-group/index.d.ts.map +1 -1
- package/lib/typescript/src/components/section-rail/index.d.ts +115 -0
- package/lib/typescript/src/components/section-rail/index.d.ts.map +1 -0
- package/lib/typescript/src/components/select/index.d.ts +46 -7
- 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/slider/index.d.ts +203 -0
- package/lib/typescript/src/components/slider/index.d.ts.map +1 -0
- 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.map +1 -1
- package/lib/typescript/src/components/tabs/index.d.ts +46 -4
- package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
- package/lib/typescript/src/components/toggle-button/index.d.ts +244 -0
- package/lib/typescript/src/components/toggle-button/index.d.ts.map +1 -0
- 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-keyboard-avoidance.d.ts +10 -1
- package/lib/typescript/src/hooks/use-keyboard-avoidance.d.ts.map +1 -1
- package/lib/typescript/src/hooks/use-scroll-sections.d.ts +31 -0
- package/lib/typescript/src/hooks/use-scroll-sections.d.ts.map +1 -0
- package/lib/typescript/src/icons/index.d.ts +6 -0
- package/lib/typescript/src/icons/index.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +13 -4
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native/index.d.ts +16 -1
- package/lib/typescript/src/native/index.d.ts.map +1 -1
- package/lib/typescript/src/primitives/keyboard-avoider.d.ts +8 -1
- package/lib/typescript/src/primitives/keyboard-avoider.d.ts.map +1 -1
- 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/utils/haptics.d.ts +12 -0
- package/lib/typescript/src/utils/haptics.d.ts.map +1 -0
- package/package.json +9 -1
- package/src/components/attachment/index.tsx +279 -0
- package/src/components/bottom-sheet/index.tsx +58 -2
- package/src/components/button/index.tsx +26 -5
- package/src/components/dialog/index.tsx +10 -1
- package/src/components/empty-state/index.tsx +60 -14
- package/src/components/frame/index.tsx +175 -29
- package/src/components/input/index.tsx +122 -16
- package/src/components/line-chart/index.tsx +1224 -0
- package/src/components/marker/index.tsx +194 -0
- package/src/components/message/index.tsx +29 -5
- package/src/components/message-scroller/index.tsx +574 -0
- package/src/components/popover/index.tsx +624 -0
- package/src/components/progress/index.tsx +81 -1
- package/src/components/radio-group/index.tsx +156 -18
- package/src/components/section-rail/index.tsx +459 -0
- package/src/components/select/index.tsx +265 -52
- package/src/components/separator/index.tsx +97 -0
- package/src/components/slider/index.tsx +371 -0
- package/src/components/surface/index.tsx +29 -3
- package/src/components/switch/index.tsx +8 -1
- package/src/components/tabs/index.tsx +208 -28
- package/src/components/toggle-button/index.tsx +374 -0
- package/src/hooks/index.ts +5 -0
- package/src/hooks/use-keyboard-avoidance.ts +73 -7
- package/src/hooks/use-scroll-sections.ts +127 -0
- package/src/icons/index.tsx +48 -0
- package/src/index.ts +97 -6
- package/src/native/index.ts +13 -1
- package/src/primitives/keyboard-avoider.tsx +9 -1
- package/src/primitives/scrim.tsx +95 -0
- package/src/utils/haptics.ts +63 -0
- package/theme.css +64 -2
- package/lib/module/components/inline-select/index.js +0 -284
- package/lib/module/components/inline-select/index.js.map +0 -1
- package/lib/typescript/src/components/inline-select/index.d.ts +0 -48
- package/lib/typescript/src/components/inline-select/index.d.ts.map +0 -1
- package/src/components/inline-select/index.tsx +0 -332
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Marker — an inline note in a conversation.
|
|
3
|
+
*
|
|
4
|
+
* Transcripts are not only messages. Between the turns sit things the
|
|
5
|
+
* conversation did rather than said: a tool that ran, a file that was read, a
|
|
6
|
+
* model that changed, the point where yesterday ended. Those are not messages
|
|
7
|
+
* and should not look like one — a bubble implies a speaker, and none of these
|
|
8
|
+
* have one. A marker is the quieter row that carries them: small, muted, and
|
|
9
|
+
* aligned to the transcript rather than to a side of it.
|
|
10
|
+
*
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <Marker>
|
|
13
|
+
* <Marker.Icon><CheckIcon /></Marker.Icon>
|
|
14
|
+
* <Marker.Content>Explored 4 files</Marker.Content>
|
|
15
|
+
* </Marker>
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* `shimmer` on the content is for the row that is still happening — the sweep
|
|
19
|
+
* runs through the glyphs while a step is in flight, and is dropped the moment
|
|
20
|
+
* it finishes.
|
|
21
|
+
*/
|
|
22
|
+
import { createContext, forwardRef, useContext, type ReactNode } from 'react';
|
|
23
|
+
import { View, type Text as RNText, type ViewProps } from 'react-native';
|
|
24
|
+
import { tv, type VariantProps } from 'tailwind-variants';
|
|
25
|
+
import { useCSSVariable } from 'uniwind';
|
|
26
|
+
import { IconColorProvider } from '../../icons';
|
|
27
|
+
import { AnimatedPressable, type AnimatedPressableProps } from '../../primitives/animated-pressable';
|
|
28
|
+
import { Text, type TextProps } from '../../primitives/text';
|
|
29
|
+
import { cn } from '../../utils/cn';
|
|
30
|
+
import { Separator } from '../separator';
|
|
31
|
+
import { Shimmer } from '../shimmer';
|
|
32
|
+
|
|
33
|
+
type MarkerVariant = 'default' | 'border' | 'separator';
|
|
34
|
+
|
|
35
|
+
const markerVariants = tv({
|
|
36
|
+
slots: {
|
|
37
|
+
root: 'w-full flex-row items-center gap-2 py-1.5',
|
|
38
|
+
content: 'text-sm text-muted-foreground',
|
|
39
|
+
},
|
|
40
|
+
variants: {
|
|
41
|
+
variant: {
|
|
42
|
+
/** The plain row: an icon and a line of muted text. */
|
|
43
|
+
default: {},
|
|
44
|
+
/** Same row, closed by a hairline — for a step that ends a section. */
|
|
45
|
+
border: { root: 'border-b border-border pb-2.5' },
|
|
46
|
+
/**
|
|
47
|
+
* A centred label with a rule running out to each edge. The rules are
|
|
48
|
+
* `Separator`s rather than borders so they follow the same token and
|
|
49
|
+
* thickness as every other rule in the app.
|
|
50
|
+
*/
|
|
51
|
+
separator: { root: 'gap-3 py-3', content: 'text-xs uppercase tracking-wider' },
|
|
52
|
+
},
|
|
53
|
+
disabled: {
|
|
54
|
+
true: { root: 'opacity-[0.64]' },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
defaultVariants: {
|
|
58
|
+
variant: 'default',
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/** The parts read the variant rather than being told it twice. */
|
|
63
|
+
const MarkerContext = createContext<MarkerVariant>('default');
|
|
64
|
+
|
|
65
|
+
export interface MarkerProps
|
|
66
|
+
extends Omit<AnimatedPressableProps, 'children' | 'disabled'>,
|
|
67
|
+
Omit<VariantProps<typeof markerVariants>, 'disabled'> {
|
|
68
|
+
className?: string;
|
|
69
|
+
disabled?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* `default` is the inline status row. `border` closes it with a hairline.
|
|
72
|
+
* `separator` centres the content between two rules — the "Yesterday"
|
|
73
|
+
* divider shape.
|
|
74
|
+
*/
|
|
75
|
+
variant?: MarkerVariant;
|
|
76
|
+
children?: ReactNode;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Renders as a pressable when given `onPress` and as a plain view otherwise,
|
|
81
|
+
* so a marker that does nothing does not announce itself as a button.
|
|
82
|
+
*/
|
|
83
|
+
const MarkerRoot = forwardRef<View, MarkerProps>(
|
|
84
|
+
({ className, variant = 'default', disabled, children, onPress, ...props }, ref) => {
|
|
85
|
+
const { root } = markerVariants({ variant, disabled: !!disabled });
|
|
86
|
+
|
|
87
|
+
// The rules belong to the root, not the content: the content has to stay a
|
|
88
|
+
// single centred child for `flex-1` on either side to split the remainder.
|
|
89
|
+
const inner =
|
|
90
|
+
variant === 'separator' ? (
|
|
91
|
+
<>
|
|
92
|
+
<Separator className="flex-1" />
|
|
93
|
+
{children}
|
|
94
|
+
<Separator className="flex-1" />
|
|
95
|
+
</>
|
|
96
|
+
) : (
|
|
97
|
+
children
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const body = !onPress ? (
|
|
101
|
+
<View
|
|
102
|
+
ref={ref}
|
|
103
|
+
accessibilityState={{ disabled: !!disabled }}
|
|
104
|
+
className={root({ className })}
|
|
105
|
+
{...(props as ViewProps)}
|
|
106
|
+
>
|
|
107
|
+
{inner}
|
|
108
|
+
</View>
|
|
109
|
+
) : (
|
|
110
|
+
<AnimatedPressable
|
|
111
|
+
ref={ref}
|
|
112
|
+
accessibilityRole="button"
|
|
113
|
+
accessibilityState={{ disabled: !!disabled }}
|
|
114
|
+
disabled={disabled}
|
|
115
|
+
onPress={onPress}
|
|
116
|
+
className={root({ className })}
|
|
117
|
+
{...props}
|
|
118
|
+
>
|
|
119
|
+
{inner}
|
|
120
|
+
</AnimatedPressable>
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return <MarkerContext.Provider value={variant}>{body}</MarkerContext.Provider>;
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
MarkerRoot.displayName = 'Marker';
|
|
127
|
+
|
|
128
|
+
export interface MarkerIconProps extends ViewProps {
|
|
129
|
+
className?: string;
|
|
130
|
+
children?: ReactNode;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Decorative leading slot. Hidden from screen readers — the icon repeats what
|
|
135
|
+
* the content already says, and announcing it twice is noise.
|
|
136
|
+
*/
|
|
137
|
+
const MarkerIcon = forwardRef<View, MarkerIconProps>(
|
|
138
|
+
({ className, children, ...props }, ref) => {
|
|
139
|
+
// Icons here take the muted foreground, so a marker reads as chrome next to
|
|
140
|
+
// a message rather than competing with it.
|
|
141
|
+
const muted = useCSSVariable('--color-muted-foreground');
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<View
|
|
145
|
+
ref={ref}
|
|
146
|
+
accessibilityElementsHidden
|
|
147
|
+
importantForAccessibility="no-hide-descendants"
|
|
148
|
+
className={cn('h-4 w-4 shrink-0 items-center justify-center', className)}
|
|
149
|
+
{...props}
|
|
150
|
+
>
|
|
151
|
+
<IconColorProvider color={typeof muted === 'string' ? muted : undefined}>
|
|
152
|
+
{children}
|
|
153
|
+
</IconColorProvider>
|
|
154
|
+
</View>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
MarkerIcon.displayName = 'Marker.Icon';
|
|
159
|
+
|
|
160
|
+
export interface MarkerContentProps extends TextProps {
|
|
161
|
+
className?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Sweep a highlight through the text, for a step that is still running.
|
|
164
|
+
* Drop it when the step finishes — a marker that shimmers forever reads as
|
|
165
|
+
* a stuck one.
|
|
166
|
+
*/
|
|
167
|
+
shimmer?: boolean;
|
|
168
|
+
children?: ReactNode;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const MarkerContent = forwardRef<RNText, MarkerContentProps>(
|
|
172
|
+
({ className, shimmer, children, ...props }, ref) => {
|
|
173
|
+
const variant = useContext(MarkerContext);
|
|
174
|
+
const { content } = markerVariants({ variant });
|
|
175
|
+
|
|
176
|
+
if (shimmer) {
|
|
177
|
+
// Shimmer owns the text so it can mask the sweep to the glyphs; the
|
|
178
|
+
// class goes to the text inside it rather than to the wrapping view.
|
|
179
|
+
return <Shimmer textClassName={content({ className })}>{children}</Shimmer>;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<Text ref={ref} className={content({ className })} {...props}>
|
|
184
|
+
{children}
|
|
185
|
+
</Text>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
);
|
|
189
|
+
MarkerContent.displayName = 'Marker.Content';
|
|
190
|
+
|
|
191
|
+
export const Marker = Object.assign(MarkerRoot, {
|
|
192
|
+
Icon: MarkerIcon,
|
|
193
|
+
Content: MarkerContent,
|
|
194
|
+
});
|
|
@@ -29,8 +29,9 @@ import {
|
|
|
29
29
|
useContext,
|
|
30
30
|
type ReactNode,
|
|
31
31
|
} from 'react';
|
|
32
|
-
import { View, type ViewProps } from 'react-native';
|
|
32
|
+
import { View, type GestureResponderEvent, type ViewProps } from 'react-native';
|
|
33
33
|
import { tv, type VariantProps } from 'tailwind-variants';
|
|
34
|
+
import { AnimatedPressable } from '../../primitives/animated-pressable';
|
|
34
35
|
import { Text, type TextProps } from '../../primitives/text';
|
|
35
36
|
import { cn } from '../../utils/cn';
|
|
36
37
|
|
|
@@ -107,20 +108,43 @@ export interface MessageProps
|
|
|
107
108
|
* this for you.
|
|
108
109
|
*/
|
|
109
110
|
stacked?: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Fires on a long press anywhere on the turn — the gesture a chat uses to
|
|
113
|
+
* surface per-message actions (copy, reply, react). Open a menu from it; the
|
|
114
|
+
* component only exposes the press. When set, the whole row gains press
|
|
115
|
+
* feedback. A plain tap should still do nothing, so there is no `onPress`.
|
|
116
|
+
*/
|
|
117
|
+
onLongPress?: (event: GestureResponderEvent) => void;
|
|
110
118
|
children?: ReactNode;
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
const MessageRoot = forwardRef<View, MessageProps>(
|
|
114
|
-
({ className, align, stacked = false, children, ...props }, ref) => {
|
|
122
|
+
({ className, align, stacked = false, onLongPress, children, ...props }, ref) => {
|
|
115
123
|
const group = useContext(GroupContext);
|
|
116
124
|
const resolvedAlign = align ?? group?.align ?? 'start';
|
|
117
125
|
const { root } = messageVariants({ align: resolvedAlign });
|
|
118
126
|
|
|
127
|
+
const body = onLongPress ? (
|
|
128
|
+
// A long-press target, not a button — a tap does nothing, so no role is
|
|
129
|
+
// announced. The feedback matches every other pressable in the library.
|
|
130
|
+
<AnimatedPressable
|
|
131
|
+
ref={ref}
|
|
132
|
+
onLongPress={onLongPress}
|
|
133
|
+
delayLongPress={300}
|
|
134
|
+
className={root({ className })}
|
|
135
|
+
{...props}
|
|
136
|
+
>
|
|
137
|
+
{children}
|
|
138
|
+
</AnimatedPressable>
|
|
139
|
+
) : (
|
|
140
|
+
<View ref={ref} className={root({ className })} {...props}>
|
|
141
|
+
{children}
|
|
142
|
+
</View>
|
|
143
|
+
);
|
|
144
|
+
|
|
119
145
|
return (
|
|
120
146
|
<MessageContext.Provider value={{ align: resolvedAlign, stacked }}>
|
|
121
|
-
|
|
122
|
-
{children}
|
|
123
|
-
</View>
|
|
147
|
+
{body}
|
|
124
148
|
</MessageContext.Provider>
|
|
125
149
|
);
|
|
126
150
|
}
|