@vvedantb/ui 0.3.2 → 0.4.0-rc.1
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 +66 -19
- package/app/README.md +8 -8
- package/package.json +5 -30
- package/src/composer/Composer.tsx +1 -0
- package/src/composer/index.ts +1 -0
- package/src/composer/input-area/ComposerSlashMenu.tsx +137 -0
- package/src/composer/input-area/ComposerSlashRow.tsx +75 -0
- package/src/composer/input-area/ConnectionStatusMenuItem.tsx +34 -0
- package/src/composer/input-area/FadePresence.tsx +31 -0
- package/src/composer/input-area/InputActions.tsx +63 -0
- package/src/composer/input-area/InputArea.tsx +513 -0
- package/src/composer/input-area/InputBanners.tsx +61 -0
- package/src/composer/input-area/PromoBanner.tsx +53 -0
- package/src/composer/input-area/composerCompact.ts +52 -0
- package/src/composer/input-area/composerPrediction.ts +51 -0
- package/src/composer/input-area/composerSlashItems.ts +206 -0
- package/src/composer/input-area/composerSlashOptionId.ts +7 -0
- package/src/composer/input-area/composerSlashPosition.ts +40 -0
- package/src/composer/input-area/composerSlashTrigger.ts +50 -0
- package/src/composer/input-area/index.ts +30 -0
- package/src/composer/input-area/inputPresets.ts +14 -0
- package/src/composer/input-area/motion.ts +7 -0
- package/src/composer/input-area/types.ts +25 -0
- package/src/composer/input-area/useComposerCompact.ts +46 -0
- package/src/composer/input-area/useComposerSlashMenu.ts +203 -0
- package/src/composer/input-area/useInputAreaPrediction.ts +49 -0
- package/src/index.ts +21 -0
- package/src/ui/button.tsx +11 -2
- package/src/ui/dropdown-menu.tsx +35 -7
- package/tokens/README.md +2 -2
- package/src/sonner.ts +0 -2
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
ghostSuggestion,
|
|
4
|
+
scheduleCompletion,
|
|
5
|
+
shouldSkipPrediction,
|
|
6
|
+
} from "./composerPrediction";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* As-you-type ghost text for `InputArea`. The caller renders `suggestion` and
|
|
10
|
+
* owns accepting it. A result shows only while the draft it was requested for
|
|
11
|
+
* is still the current draft. Pass `getPrediction` to make the request.
|
|
12
|
+
*/
|
|
13
|
+
export function useInputAreaPrediction({
|
|
14
|
+
value,
|
|
15
|
+
suspended = false,
|
|
16
|
+
enabled = true,
|
|
17
|
+
getPrediction,
|
|
18
|
+
}: {
|
|
19
|
+
value: string;
|
|
20
|
+
suspended?: boolean;
|
|
21
|
+
enabled?: boolean;
|
|
22
|
+
getPrediction?: (text: string) => Promise<string>;
|
|
23
|
+
}): { suggestion: string | undefined; dismiss: () => void } {
|
|
24
|
+
const [result, setResult] = useState<{ forValue: string; text: string }>();
|
|
25
|
+
const [dismissedFor, setDismissedFor] = useState<string>();
|
|
26
|
+
|
|
27
|
+
const idle =
|
|
28
|
+
!enabled ||
|
|
29
|
+
getPrediction === undefined ||
|
|
30
|
+
suspended ||
|
|
31
|
+
shouldSkipPrediction(value);
|
|
32
|
+
const settled = result?.forValue === value || dismissedFor === value;
|
|
33
|
+
|
|
34
|
+
// Debounced request: it has to react to the draft changing.
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (idle || settled || getPrediction === undefined) return;
|
|
37
|
+
return scheduleCompletion(
|
|
38
|
+
value,
|
|
39
|
+
getPrediction,
|
|
40
|
+
(text) => setResult({ forValue: value, text }),
|
|
41
|
+
);
|
|
42
|
+
}, [value, idle, settled, getPrediction]);
|
|
43
|
+
|
|
44
|
+
const visible = !idle && dismissedFor !== value && result?.forValue === value;
|
|
45
|
+
return {
|
|
46
|
+
suggestion: visible ? ghostSuggestion(value, result.text) : undefined,
|
|
47
|
+
dismiss: () => setDismissedFor(value),
|
|
48
|
+
};
|
|
49
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -100,3 +100,24 @@ export * from "./ai-elements/suggestion";
|
|
|
100
100
|
export * from "./audio";
|
|
101
101
|
|
|
102
102
|
export * from "./composer";
|
|
103
|
+
export { toast } from "sonner";
|
|
104
|
+
|
|
105
|
+
// Shell: router-free pieces. Shell's own `cn` and `ClassValue` are not re-exported;
|
|
106
|
+
// use the root `cn` (clsx + tailwind-merge).
|
|
107
|
+
export { SidebarHeader } from "../shell/src/SidebarHeader";
|
|
108
|
+
export type { SidebarHeaderProps } from "../shell/src/SidebarHeader";
|
|
109
|
+
export { PillTabs } from "../shell/src/PillTabs";
|
|
110
|
+
export type { PillTabItem, PillTabsProps } from "../shell/src/PillTabs";
|
|
111
|
+
export { SessionsHoverCard } from "../shell/src/SessionsHoverCard";
|
|
112
|
+
export type {
|
|
113
|
+
SessionsHoverCardContext,
|
|
114
|
+
SessionsHoverCardProps,
|
|
115
|
+
SessionsHoverCardSurface,
|
|
116
|
+
} from "../shell/src/SessionsHoverCard";
|
|
117
|
+
|
|
118
|
+
// App helpers: confirm skip, update watcher, settings chrome, stable auth.
|
|
119
|
+
export * from "../app/src/index";
|
|
120
|
+
|
|
121
|
+
// Native tokens (JS values that match tokens.css).
|
|
122
|
+
export { tokens } from "../tokens/src/native";
|
|
123
|
+
export type { Tokens } from "../tokens/src/native";
|
package/src/ui/button.tsx
CHANGED
|
@@ -39,17 +39,26 @@ export interface ButtonProps
|
|
|
39
39
|
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
40
40
|
VariantProps<typeof buttonVariants> {
|
|
41
41
|
asChild?: boolean;
|
|
42
|
+
/** Rendered before the children. Ignored with `asChild`. */
|
|
43
|
+
startContent?: React.ReactNode;
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
45
|
-
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
47
|
+
({ className, variant, size, asChild = false, startContent, children, ...props }, ref) => {
|
|
46
48
|
const Comp = asChild ? Slot : "button";
|
|
47
49
|
return (
|
|
48
50
|
<Comp
|
|
49
51
|
className={cn(buttonVariants({ variant, size, className }))}
|
|
50
52
|
ref={ref}
|
|
51
53
|
{...props}
|
|
52
|
-
|
|
54
|
+
>
|
|
55
|
+
{asChild ? children : (
|
|
56
|
+
<>
|
|
57
|
+
{startContent}
|
|
58
|
+
{children}
|
|
59
|
+
</>
|
|
60
|
+
)}
|
|
61
|
+
</Comp>
|
|
53
62
|
);
|
|
54
63
|
},
|
|
55
64
|
);
|
package/src/ui/dropdown-menu.tsx
CHANGED
|
@@ -75,14 +75,42 @@ const DropdownMenuItem = React.forwardRef<
|
|
|
75
75
|
React.ComponentRef<typeof DropdownMenuPrimitive.Item>,
|
|
76
76
|
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
77
77
|
inset?: boolean;
|
|
78
|
+
/** Leading icon or mark. Ignored with `asChild`. */
|
|
79
|
+
startContent?: React.ReactNode;
|
|
80
|
+
/** Second line under the label. Ignored with `asChild`. */
|
|
81
|
+
description?: React.ReactNode;
|
|
78
82
|
}
|
|
79
|
-
>(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
>(
|
|
84
|
+
(
|
|
85
|
+
{ className, inset, startContent, description, children, asChild, ...props },
|
|
86
|
+
ref,
|
|
87
|
+
) => (
|
|
88
|
+
<DropdownMenuPrimitive.Item
|
|
89
|
+
ref={ref}
|
|
90
|
+
asChild={asChild}
|
|
91
|
+
className={cn(menuItemClass, inset && "pl-8", className)}
|
|
92
|
+
{...props}
|
|
93
|
+
>
|
|
94
|
+
{asChild || (startContent === undefined && description === undefined) ? (
|
|
95
|
+
children
|
|
96
|
+
) : (
|
|
97
|
+
<>
|
|
98
|
+
{startContent}
|
|
99
|
+
{description === undefined ? (
|
|
100
|
+
children
|
|
101
|
+
) : (
|
|
102
|
+
<span className="flex min-w-0 flex-col">
|
|
103
|
+
<span>{children}</span>
|
|
104
|
+
<span className="text-xs text-muted-foreground">
|
|
105
|
+
{description}
|
|
106
|
+
</span>
|
|
107
|
+
</span>
|
|
108
|
+
)}
|
|
109
|
+
</>
|
|
110
|
+
)}
|
|
111
|
+
</DropdownMenuPrimitive.Item>
|
|
112
|
+
),
|
|
113
|
+
);
|
|
86
114
|
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
87
115
|
|
|
88
116
|
const DropdownMenuCheckboxItem = React.forwardRef<
|
package/tokens/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# `@vvedantb/ui/tokens`
|
|
2
2
|
|
|
3
|
-
Design tokens and shared Tailwind v4 CSS for the vvedantb web apps
|
|
3
|
+
Design tokens and shared Tailwind v4 CSS for the vvedantb web apps. The CSS and Tailwind preset are subpaths of `@vvedantb/ui`; the native JS tokens are named exports of the root (`tokens`, `Tokens`). Source-exported: no build step. Paths in the `File` column are relative to `packages/ui/tokens/`.
|
|
4
4
|
|
|
5
5
|
## Exports
|
|
6
6
|
|
|
7
7
|
| Export | File | What it is |
|
|
8
8
|
| --- | --- | --- |
|
|
9
9
|
| `@vvedantb/ui/tokens`, `@vvedantb/ui/tokens/tokens.css` | `src/tokens.css` | Colour, radius, shadow, ease and font tokens (`@theme`), light/dark variables, `dark` variant, `*` border and `body` defaults. In 0.2.1 it also defines shadcn-style aliases (`primary`, `muted-foreground`, `secondary`, `destructive`, `card`, `popover`, `input`, `ring`) that point at the same tokens. |
|
|
10
|
-
| `@vvedantb/ui
|
|
10
|
+
| `tokens` and `Tokens` from `@vvedantb/ui` | `src/native.ts` | JS colours, radii and spacing for React Native. `@vvedantb/native-ui` keeps its own copy in `src/tokens.ts`; a test keeps the two equal. |
|
|
11
11
|
| `@vvedantb/ui/tokens/css/base.css` | `src/css/base.css` | `html` touch/accent, `::selection`, control transitions, pointer cursor, range accent (`@layer base`). |
|
|
12
12
|
| `@vvedantb/ui/tokens/css/dialog.css` | `src/css/dialog.css` | Unlayered `max-width: none` for `@vvedantb/ui` compact (bottom-sheet) dialogs. |
|
|
13
13
|
| `@vvedantb/ui/tokens/css/modal.css` | `src/css/modal.css` | `.t-modal`, `.is-open`, `.is-closing` and `t-modal-presence-wait` (`@layer components`). |
|
package/src/sonner.ts
DELETED