@streamsai/ui 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +57 -2
- package/dist/components/ui/agent-avatar.d.ts +50 -0
- package/dist/components/ui/agent-avatar.js +38 -0
- package/dist/components/ui/alert-dialog.d.ts +12 -0
- package/dist/components/ui/alert-dialog.js +37 -0
- package/dist/components/ui/alert.d.ts +10 -0
- package/dist/components/ui/alert.js +28 -0
- package/dist/components/ui/assets/loader.json.js +1 -0
- package/dist/components/ui/avatar-frame.d.ts +11 -0
- package/dist/components/ui/avatar-frame.js +20 -0
- package/dist/components/ui/avatar.d.ts +23 -0
- package/dist/components/ui/avatar.js +54 -0
- package/dist/components/ui/badge.d.ts +7 -0
- package/dist/components/ui/badge.js +36 -0
- package/dist/components/ui/bar-list.d.ts +40 -0
- package/dist/components/ui/bar-list.js +37 -0
- package/dist/components/ui/breadcrumb.d.ts +8 -0
- package/dist/components/ui/breadcrumb.js +21 -0
- package/dist/components/ui/button-group.d.ts +10 -0
- package/dist/components/ui/button-group.js +41 -0
- package/dist/components/ui/button.d.ts +9 -0
- package/dist/components/ui/button.js +39 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/card.js +25 -0
- package/dist/components/ui/checkbox.d.ts +3 -0
- package/dist/components/ui/checkbox.js +16 -0
- package/dist/components/ui/chip.d.ts +13 -0
- package/dist/components/ui/chip.js +22 -0
- package/dist/components/ui/clickable.d.ts +27 -0
- package/dist/components/ui/clickable.js +54 -0
- package/dist/components/ui/code-block.d.ts +68 -0
- package/dist/components/ui/code-block.js +112 -0
- package/dist/components/ui/code-view.d.ts +21 -0
- package/dist/components/ui/code-view.js +20 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/collapsible.js +18 -0
- package/dist/components/ui/combobox.d.ts +14 -0
- package/dist/components/ui/combobox.js +37 -0
- package/dist/components/ui/command.d.ts +15 -0
- package/dist/components/ui/command.js +34 -0
- package/dist/components/ui/context-menu.d.ts +21 -0
- package/dist/components/ui/context-menu.js +60 -0
- package/dist/components/ui/counter.d.ts +11 -0
- package/dist/components/ui/counter.js +20 -0
- package/dist/components/ui/dialog.d.ts +17 -0
- package/dist/components/ui/dialog.js +41 -0
- package/dist/components/ui/disabled-reason.d.ts +22 -0
- package/dist/components/ui/disabled-reason.js +16 -0
- package/dist/components/ui/dropdown-menu.d.ts +33 -0
- package/dist/components/ui/dropdown-menu.js +58 -0
- package/dist/components/ui/editable-text.d.ts +95 -0
- package/dist/components/ui/editable-text.js +191 -0
- package/dist/components/ui/heading.d.ts +24 -0
- package/dist/components/ui/heading.js +92 -0
- package/dist/components/ui/hover-card.d.ts +9 -0
- package/dist/components/ui/hover-card.js +16 -0
- package/dist/components/ui/icon-button.d.ts +23 -0
- package/dist/components/ui/icon-button.js +32 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.js +8 -0
- package/dist/components/ui/kbd.d.ts +12 -0
- package/dist/components/ui/kbd.js +12 -0
- package/dist/components/ui/label.d.ts +3 -0
- package/dist/components/ui/label.js +7 -0
- package/dist/components/ui/loader.d.ts +19 -0
- package/dist/components/ui/loader.js +157 -0
- package/dist/components/ui/message-toolbar.d.ts +20 -0
- package/dist/components/ui/message-toolbar.js +17 -0
- package/dist/components/ui/modal.d.ts +30 -0
- package/dist/components/ui/modal.js +41 -0
- package/dist/components/ui/nav-item.d.ts +25 -0
- package/dist/components/ui/nav-item.js +66 -0
- package/dist/components/ui/panel-section.d.ts +22 -0
- package/dist/components/ui/panel-section.js +26 -0
- package/dist/components/ui/popover.d.ts +14 -0
- package/dist/components/ui/popover.js +30 -0
- package/dist/components/ui/progress.d.ts +5 -0
- package/dist/components/ui/progress.js +16 -0
- package/dist/components/ui/provider-badge.d.ts +22 -0
- package/dist/components/ui/provider-badge.js +38 -0
- package/dist/components/ui/radio-group.d.ts +5 -0
- package/dist/components/ui/radio-group.js +21 -0
- package/dist/components/ui/reply-summary.d.ts +16 -0
- package/dist/components/ui/reply-summary.js +8 -0
- package/dist/components/ui/resizable.d.ts +8 -0
- package/dist/components/ui/resizable.js +15 -0
- package/dist/components/ui/rich-text-editor.d.ts +447 -0
- package/dist/components/ui/rich-text-editor.js +2419 -0
- package/dist/components/ui/running-indicator.d.ts +17 -0
- package/dist/components/ui/running-indicator.js +34 -0
- package/dist/components/ui/sandboxed-frame.d.ts +29 -0
- package/dist/components/ui/sandboxed-frame.js +77 -0
- package/dist/components/ui/scroll-area.d.ts +14 -0
- package/dist/components/ui/scroll-area.js +17 -0
- package/dist/components/ui/section-header.d.ts +12 -0
- package/dist/components/ui/section-header.js +12 -0
- package/dist/components/ui/select.d.ts +15 -0
- package/dist/components/ui/select.js +40 -0
- package/dist/components/ui/separator.d.ts +3 -0
- package/dist/components/ui/separator.js +13 -0
- package/dist/components/ui/sheet.d.ts +23 -0
- package/dist/components/ui/sheet.js +48 -0
- package/dist/components/ui/shimmer-text.d.ts +26 -0
- package/dist/components/ui/shimmer-text.js +32 -0
- package/dist/components/ui/sidebar.d.ts +63 -0
- package/dist/components/ui/sidebar.js +283 -0
- package/dist/components/ui/skeleton.d.ts +14 -0
- package/dist/components/ui/skeleton.js +12 -0
- package/dist/components/ui/sonner.d.ts +4 -0
- package/dist/components/ui/sonner.js +14 -0
- package/dist/components/ui/spark-bars.d.ts +29 -0
- package/dist/components/ui/spark-bars.js +24 -0
- package/dist/components/ui/spinner.d.ts +16 -0
- package/dist/components/ui/spinner.js +26 -0
- package/dist/components/ui/stacked-bar.d.ts +37 -0
- package/dist/components/ui/stacked-bar.js +56 -0
- package/dist/components/ui/status-dot.d.ts +16 -0
- package/dist/components/ui/status-dot.js +32 -0
- package/dist/components/ui/switch.d.ts +5 -0
- package/dist/components/ui/switch.js +13 -0
- package/dist/components/ui/tabs.d.ts +14 -0
- package/dist/components/ui/tabs.js +55 -0
- package/dist/components/ui/text.d.ts +27 -0
- package/dist/components/ui/text.js +100 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.js +7 -0
- package/dist/components/ui/theme-toggle.d.ts +21 -0
- package/dist/components/ui/theme-toggle.js +17 -0
- package/dist/components/ui/toggle-group.d.ts +6 -0
- package/dist/components/ui/toggle-group.js +12 -0
- package/dist/components/ui/tooltip.d.ts +11 -0
- package/dist/components/ui/tooltip.js +21 -0
- package/dist/components/ui/trace.d.ts +24 -0
- package/dist/components/ui/trace.js +57 -0
- package/dist/components/ui/trend-line.d.ts +93 -0
- package/dist/components/ui/trend-line.js +215 -0
- package/dist/components/ui/truncate.d.ts +30 -0
- package/dist/components/ui/truncate.js +54 -0
- package/dist/components/ui/viewer-shell.d.ts +55 -0
- package/dist/components/ui/viewer-shell.js +15 -0
- package/dist/components/ui/virtual-list.d.ts +91 -0
- package/dist/components/ui/virtual-list.js +406 -0
- package/dist/components/ui/visually-hidden.d.ts +15 -0
- package/dist/components/ui/visually-hidden.js +19 -0
- package/dist/direction/index.d.ts +19 -0
- package/dist/direction/index.js +32 -0
- package/dist/hooks/use-code-highlighting.d.ts +22 -0
- package/dist/hooks/use-code-highlighting.js +47 -0
- package/dist/hooks/use-is-truncated.d.ts +7 -0
- package/dist/hooks/use-is-truncated.js +23 -0
- package/dist/hooks/use-mobile.d.ts +2 -0
- package/dist/hooks/use-mobile.js +15 -0
- package/dist/icons/custom.d.ts +29 -0
- package/dist/icons/custom.js +48 -0
- package/dist/icons/index.d.ts +49 -0
- package/dist/icons/index.js +50 -0
- package/dist/icons/provider-logos.d.ts +17 -0
- package/dist/icons/provider-logos.js +28 -0
- package/dist/icons/providers.d.ts +9 -0
- package/dist/icons/providers.js +51 -0
- package/dist/index.d.ts +102 -0
- package/dist/index.js +124 -0
- package/dist/lib/code-highlighter.d.ts +9 -0
- package/dist/lib/code-highlighter.js +65 -0
- package/dist/lib/code-language.d.ts +13 -0
- package/dist/lib/code-language.js +103 -0
- package/dist/lib/code-tokens.d.ts +9 -0
- package/dist/lib/code-tokens.js +27 -0
- package/dist/lib/copy-text.d.ts +6 -0
- package/dist/lib/copy-text.js +46 -0
- package/dist/lib/home-tile.d.ts +12 -0
- package/dist/lib/home-tile.js +45 -0
- package/dist/lib/reveal-mask.d.ts +9 -0
- package/dist/lib/reveal-mask.js +16 -0
- package/dist/lib/text-direction.d.ts +28 -0
- package/dist/lib/text-direction.js +119 -0
- package/dist/lib/utils.d.ts +11 -0
- package/dist/lib/utils.js +30 -0
- package/dist/motion/components.d.ts +184 -0
- package/dist/motion/components.js +211 -0
- package/dist/motion/config.d.ts +849 -0
- package/dist/motion/config.js +429 -0
- package/dist/motion/index.d.ts +8 -0
- package/dist/motion/index.js +8 -0
- package/dist/motion/modal-presence.d.ts +5 -0
- package/dist/motion/modal-presence.js +27 -0
- package/dist/motion/popup.d.ts +77 -0
- package/dist/motion/popup.js +103 -0
- package/dist/platform/index.d.ts +29 -0
- package/dist/platform/index.js +63 -0
- package/dist/styles/base.css +319 -0
- package/dist/styles/fonts/Figtree-Variable.woff2 +0 -0
- package/dist/styles/fonts/OFL.txt +93 -0
- package/dist/styles/fonts/Poppins-Medium.woff2 +0 -0
- package/dist/styles/fonts/Poppins-Regular.woff2 +0 -0
- package/dist/styles/fonts/Poppins-SemiBold.woff2 +0 -0
- package/dist/styles/fonts.css +28 -0
- package/dist/styles/globals.css +8 -0
- package/dist/styles/mcp-host.css +76 -0
- package/dist/styles/tokens.css +387 -0
- package/dist/styles/tokens.d.mts +57 -0
- package/dist/styles/tokens.mjs +59 -0
- package/dist/theme/index.d.ts +28 -0
- package/dist/theme/index.js +65 -0
- package/package.json +136 -3
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface RunningIndicatorProps {
|
|
2
|
+
label: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* The "an agent is working" cue, the twin of iOS `RunningIndicator`: an 8px green core that
|
|
7
|
+
* breathes inside a fixed 12px box, with a flat 2px halo that fades on the same loop. The box never
|
|
8
|
+
* changes size, so a row's geometry is stable while it animates. Reduced motion renders the core
|
|
9
|
+
* static with no halo.
|
|
10
|
+
*
|
|
11
|
+
* The loops start imperatively, not with `animate` keyframes on a `motion` element: inside an
|
|
12
|
+
* `AnimatePresence initial={false}` (the leading slot of a NavItem row) motion skips an animation
|
|
13
|
+
* that starts on mount, so a declarative loop sat still in rows while the same dot pulsed in the
|
|
14
|
+
* filter chips.
|
|
15
|
+
*/
|
|
16
|
+
declare function RunningIndicator({ label, className }: RunningIndicatorProps): import("react").JSX.Element;
|
|
17
|
+
export { RunningIndicator, type RunningIndicatorProps };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { animate, usePrefersReducedMotion } from '../../motion/index.js';
|
|
4
|
+
import { runningIndicator } from '../../motion/config.js';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
|
+
/**
|
|
7
|
+
* The "an agent is working" cue, the twin of iOS `RunningIndicator`: an 8px green core that
|
|
8
|
+
* breathes inside a fixed 12px box, with a flat 2px halo that fades on the same loop. The box never
|
|
9
|
+
* changes size, so a row's geometry is stable while it animates. Reduced motion renders the core
|
|
10
|
+
* static with no halo.
|
|
11
|
+
*
|
|
12
|
+
* The loops start imperatively, not with `animate` keyframes on a `motion` element: inside an
|
|
13
|
+
* `AnimatePresence initial={false}` (the leading slot of a NavItem row) motion skips an animation
|
|
14
|
+
* that starts on mount, so a declarative loop sat still in rows while the same dot pulsed in the
|
|
15
|
+
* filter chips.
|
|
16
|
+
*/
|
|
17
|
+
function RunningIndicator({ label, className }) {
|
|
18
|
+
const pulsing = !usePrefersReducedMotion();
|
|
19
|
+
const coreRef = useRef(null);
|
|
20
|
+
const haloRef = useRef(null);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const core = coreRef.current;
|
|
23
|
+
const halo = haloRef.current;
|
|
24
|
+
if (!pulsing || !core || !halo)
|
|
25
|
+
return;
|
|
26
|
+
const controls = [
|
|
27
|
+
animate(core, runningIndicator.core, runningIndicator.transition),
|
|
28
|
+
animate(halo, runningIndicator.halo, runningIndicator.transition),
|
|
29
|
+
];
|
|
30
|
+
return () => controls.forEach((control) => control.cancel());
|
|
31
|
+
}, [pulsing]);
|
|
32
|
+
return (_jsxs("span", { role: "img", "aria-label": label, "data-slot": "running-indicator", className: cn('relative inline-grid size-3 shrink-0 place-items-center', className), children: [pulsing ? (_jsx("span", { ref: haloRef, "aria-hidden": true, "data-slot": "running-indicator-halo", className: "absolute inset-0 rounded-full bg-home-running-halo" })) : null, _jsx("span", { ref: coreRef, "aria-hidden": true, "data-slot": "running-indicator-core", className: "relative size-2 rounded-full bg-home-running" })] }));
|
|
33
|
+
}
|
|
34
|
+
export { RunningIndicator };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
type FrameSource = {
|
|
3
|
+
kind: 'url';
|
|
4
|
+
url: string;
|
|
5
|
+
} | {
|
|
6
|
+
kind: 'html';
|
|
7
|
+
html: string;
|
|
8
|
+
}
|
|
9
|
+
/** An upload on its own throwaway origin (user content domain): framed by url, never trusted. */
|
|
10
|
+
| {
|
|
11
|
+
kind: 'usercontent';
|
|
12
|
+
url: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* `allow-same-origin` together with `allow-scripts` lets a document remove its own sandbox
|
|
16
|
+
* and read its origin's storage. Inline `html` (user uploads, agent output) never gets it or
|
|
17
|
+
* `allow-forms`. The `url` source is for hosted previews that are already on their own origin,
|
|
18
|
+
* where same-origin only lets that document use its own cookies and storage. Never point it at
|
|
19
|
+
* an upload on the shared storage origin: uploaded files must render as `html` (srcdoc) or not at all.
|
|
20
|
+
*/
|
|
21
|
+
declare function sandboxFor(source: FrameSource): string;
|
|
22
|
+
/** Props that grant a frame powers or decide what it loads: only `source` and the component set them. */
|
|
23
|
+
type SecurityProps = 'src' | 'srcDoc' | 'sandbox' | 'allow' | 'allowFullScreen' | 'referrerPolicy' | 'name' | 'csp' | 'credentialless';
|
|
24
|
+
interface SandboxedFrameProps extends Omit<ComponentProps<'iframe'>, SecurityProps> {
|
|
25
|
+
source: FrameSource;
|
|
26
|
+
title: string;
|
|
27
|
+
}
|
|
28
|
+
declare function SandboxedFrame({ source, title, className, ...props }: SandboxedFrameProps): import("react").JSX.Element;
|
|
29
|
+
export { SandboxedFrame, sandboxFor, type FrameSource, type SandboxedFrameProps };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from '../../lib/utils.js';
|
|
3
|
+
// No `allow-forms`: a page that cannot submit cannot pose as a login form that posts somewhere.
|
|
4
|
+
// No `allow-popups`: `window.open(url)` would carry whatever the page read out to any host.
|
|
5
|
+
// No `allow-same-origin`: see below.
|
|
6
|
+
const HTML_SANDBOX = 'allow-scripts';
|
|
7
|
+
const URL_SANDBOX = 'allow-scripts allow-forms allow-popups';
|
|
8
|
+
/**
|
|
9
|
+
* `allow-same-origin` together with `allow-scripts` lets a document remove its own sandbox
|
|
10
|
+
* and read its origin's storage. Inline `html` (user uploads, agent output) never gets it or
|
|
11
|
+
* `allow-forms`. The `url` source is for hosted previews that are already on their own origin,
|
|
12
|
+
* where same-origin only lets that document use its own cookies and storage. Never point it at
|
|
13
|
+
* an upload on the shared storage origin: uploaded files must render as `html` (srcdoc) or not at all.
|
|
14
|
+
*/
|
|
15
|
+
function sandboxFor(source) {
|
|
16
|
+
// `usercontent` gets the srcdoc sandbox exactly: never the `url` branch's same-origin grant.
|
|
17
|
+
if (source.kind === 'html' || source.kind === 'usercontent')
|
|
18
|
+
return HTML_SANDBOX;
|
|
19
|
+
let origin;
|
|
20
|
+
try {
|
|
21
|
+
origin = new URL(source.url, location.href).origin;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return URL_SANDBOX;
|
|
25
|
+
}
|
|
26
|
+
if (origin === location.origin)
|
|
27
|
+
return URL_SANDBOX;
|
|
28
|
+
return 'allow-scripts allow-same-origin allow-forms allow-popups';
|
|
29
|
+
}
|
|
30
|
+
const escapeAttribute = (value) => value.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
31
|
+
/**
|
|
32
|
+
* The page cannot be stopped from navigating its own frame (`location.href = "https://x/?k=" +
|
|
33
|
+
* typed`, a link, a meta refresh): no header on the page's own response can forbid that, but the
|
|
34
|
+
* CSP of the document that embeds a frame governs where that frame may go. So an uploaded page is
|
|
35
|
+
* framed inside a static wrapper whose CSP allows exactly the page's origin as a frame source. A
|
|
36
|
+
* navigation anywhere else is refused before a request leaves the browser.
|
|
37
|
+
*
|
|
38
|
+
* The wrapper is deliberately NOT sandboxed. The edge answers with `frame-ancestors <app origins>`,
|
|
39
|
+
* and a sandboxed wrapper has an opaque origin that no `frame-ancestors` source (not even `*`)
|
|
40
|
+
* matches, so the browser would refuse to show the page at all. An unsandboxed `srcdoc` takes the
|
|
41
|
+
* app's origin and passes. It is inert: its own CSP is `default-src 'none'` (no script can run in
|
|
42
|
+
* it), it holds no data, and the page below it is sandboxed by the inner frame's attribute and by
|
|
43
|
+
* the edge's `sandbox` header, so the page is an opaque origin that can reach neither the wrapper
|
|
44
|
+
* nor the app. Keep every byte interpolated into it escaped.
|
|
45
|
+
*/
|
|
46
|
+
function guardedDocument(url) {
|
|
47
|
+
let source;
|
|
48
|
+
try {
|
|
49
|
+
const parsed = new URL(url, location.href);
|
|
50
|
+
source = parsed.protocol === 'blob:' ? 'blob:' : parsed.origin;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
if (source === 'null')
|
|
56
|
+
return '';
|
|
57
|
+
return (`<!doctype html><meta http-equiv="Content-Security-Policy" content="default-src 'none'; ` +
|
|
58
|
+
`style-src 'unsafe-inline'; frame-src ${escapeAttribute(source)}">` +
|
|
59
|
+
`<style>html,body{margin:0;height:100%}iframe{display:block;border:0;width:100%;height:100%}</style>` +
|
|
60
|
+
`<iframe sandbox="${HTML_SANDBOX}" referrerpolicy="no-referrer" allow="" src="${escapeAttribute(url)}"></iframe>`);
|
|
61
|
+
}
|
|
62
|
+
function SandboxedFrame({ source, title, className, ...props }) {
|
|
63
|
+
// A wrapped page is sandboxed by the frame inside the wrapper; see `guardedDocument`.
|
|
64
|
+
const sandbox = source.kind === 'usercontent' ? undefined : sandboxFor(source);
|
|
65
|
+
// Both attributes are always set, so a stray `src` or `srcDoc` in `props` can never win.
|
|
66
|
+
const sourceProps = source.kind === 'html'
|
|
67
|
+
? { src: undefined, srcDoc: source.html }
|
|
68
|
+
: source.kind === 'usercontent'
|
|
69
|
+
? { src: undefined, srcDoc: guardedDocument(source.url) }
|
|
70
|
+
: { src: source.url, srcDoc: undefined };
|
|
71
|
+
return (_jsx("iframe", { ...props, title: title, "data-slot": "sandboxed-frame", className: cn('size-full border-0 bg-background', className),
|
|
72
|
+
// After the spread, so nothing a caller passes (even past the types) can override them.
|
|
73
|
+
sandbox: sandbox, referrerPolicy: "no-referrer",
|
|
74
|
+
// Delegate no powers (camera, clipboard, fullscreen, ...) to framed content.
|
|
75
|
+
allow: "", allowFullScreen: false, name: undefined, csp: undefined, credentialless: undefined, ...sourceProps }));
|
|
76
|
+
}
|
|
77
|
+
export { SandboxedFrame, sandboxFor };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area';
|
|
2
|
+
type ScrollbarVisibility = 'always' | 'hover';
|
|
3
|
+
type ScrollAreaProps = ScrollAreaPrimitive.Root.Props & {
|
|
4
|
+
/**
|
|
5
|
+
* `hover` shows a lighter bar only while the pointer is over the area or it is scrolling, and
|
|
6
|
+
* keeps the track 16px off the top and bottom so rounded corners never clip it.
|
|
7
|
+
*/
|
|
8
|
+
scrollbar?: ScrollbarVisibility;
|
|
9
|
+
};
|
|
10
|
+
declare function ScrollArea({ className, children, scrollbar, ...props }: ScrollAreaProps): import("react").JSX.Element;
|
|
11
|
+
declare function ScrollBar({ className, orientation, visibility, ...props }: ScrollAreaPrimitive.Scrollbar.Props & {
|
|
12
|
+
visibility?: ScrollbarVisibility;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
14
|
+
export { ScrollArea, ScrollBar, type ScrollAreaProps };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { ScrollArea as ScrollAreaPrimitive } from '@base-ui/react/scroll-area';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
function ScrollArea({ className, children, scrollbar = 'always', ...props }) {
|
|
5
|
+
return (_jsxs(ScrollAreaPrimitive.Root, { "data-slot": "scroll-area", className: cn('relative overflow-hidden', className), ...props, children: [_jsx(ScrollAreaPrimitive.Viewport, { "data-slot": "scroll-area-viewport", className: "h-full w-full rounded-[inherit]", children: scrollbar === 'hover' ? (
|
|
6
|
+
// Content is observed for size, so a section opening inside shows the bar without a
|
|
7
|
+
// scroll first. Its default `min-width: fit-content` would stop rows from truncating.
|
|
8
|
+
_jsx(ScrollAreaPrimitive.Content, { className: "min-w-0!", children: children })) : (children) }), _jsx(ScrollBar, { visibility: scrollbar }), _jsx(ScrollAreaPrimitive.Corner, {})] }));
|
|
9
|
+
}
|
|
10
|
+
function ScrollBar({ className, orientation = 'vertical', visibility = 'always', ...props }) {
|
|
11
|
+
const hover = visibility === 'hover';
|
|
12
|
+
return (_jsx(ScrollAreaPrimitive.Scrollbar, { "data-slot": "scroll-area-scrollbar", "data-visibility": visibility, orientation: orientation, className: cn('flex touch-none select-none border-0 bg-transparent transition-colors', orientation === 'vertical' && 'h-full w-2.5 p-px', orientation === 'horizontal' && 'h-2.5 flex-col p-px',
|
|
13
|
+
// Base UI positions the bar with inline top/bottom (left/right), so the inset needs `!`.
|
|
14
|
+
hover && orientation === 'vertical' && 'h-auto! top-4! bottom-4!', hover && orientation === 'horizontal' && 'w-auto! right-4! left-4!', hover &&
|
|
15
|
+
'opacity-0 transition-opacity data-hovering:opacity-100 data-scrolling:opacity-100', className), ...props, children: _jsx(ScrollAreaPrimitive.Thumb, { "data-slot": "scroll-area-thumb", className: cn('relative flex-1 rounded-full', hover ? 'bg-border/60' : 'bg-border') }) }));
|
|
16
|
+
}
|
|
17
|
+
export { ScrollArea, ScrollBar };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
interface SectionHeaderProps {
|
|
3
|
+
title: ReactNode;
|
|
4
|
+
open: boolean;
|
|
5
|
+
onOpenChange: (open: boolean) => void;
|
|
6
|
+
count?: number;
|
|
7
|
+
actions?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Sidebar group title (Figma "Collapsible section title"): 12px semibold, chevron after the title (shown on hover or focus only), actions right. */
|
|
11
|
+
declare function SectionHeader({ title, open, onOpenChange, count, actions, className, }: SectionHeaderProps): import("react").JSX.Element;
|
|
12
|
+
export { SectionHeader, type SectionHeaderProps };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { motion } from '../../motion/index.js';
|
|
4
|
+
import { transitions } from '../../motion/config.js';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
|
+
import { ChevronDown } from '../../icons/index.js';
|
|
7
|
+
import { Counter } from './counter.js';
|
|
8
|
+
/** Sidebar group title (Figma "Collapsible section title"): 12px semibold, chevron after the title (shown on hover or focus only), actions right. */
|
|
9
|
+
function SectionHeader({ title, open, onOpenChange, count, actions, className, }) {
|
|
10
|
+
return (_jsxs("div", { className: cn('flex h-8 items-center gap-1 pr-1 pl-2', className), children: [_jsxs("button", { type: "button", "aria-expanded": open, onClick: () => onOpenChange(!open), className: "group/section flex min-w-0 flex-1 items-center gap-1 rounded-sm text-left text-body-3 font-semibold text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx("span", { className: "truncate", children: title }), _jsx(motion.span, { animate: { rotate: open ? 0 : -90 }, transition: transitions.base, className: "flex size-3 shrink-0 items-center justify-center text-icon opacity-0 transition-opacity group-hover/section:opacity-100 group-focus-visible/section:opacity-100", "aria-hidden": "true", children: _jsx(ChevronDown, { className: "size-3" }) }), count != null ? _jsx(Counter, { count: count, className: "ml-1" }) : null] }), actions ? _jsx("span", { className: "flex shrink-0 items-center gap-0.5", children: actions }) : null] }));
|
|
11
|
+
}
|
|
12
|
+
export { SectionHeader };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Select as SelectPrimitive } from '@base-ui/react/select';
|
|
3
|
+
declare function Select<Value, Multiple extends boolean | undefined = false>({ actionsRef, onOpenChange, ...props }: SelectPrimitive.Root.Props<Value, Multiple>): React.JSX.Element;
|
|
4
|
+
declare function SelectGroup({ className, ...props }: SelectPrimitive.Group.Props): React.JSX.Element;
|
|
5
|
+
declare function SelectValue({ className, ...props }: SelectPrimitive.Value.Props): React.JSX.Element;
|
|
6
|
+
declare function SelectTrigger({ className, size, children, ...props }: SelectPrimitive.Trigger.Props & {
|
|
7
|
+
size?: 'sm' | 'default';
|
|
8
|
+
}): React.JSX.Element;
|
|
9
|
+
declare function SelectContent({ className, children, side, sideOffset, align, alignOffset, alignItemWithTrigger, ...props }: SelectPrimitive.Popup.Props & Pick<SelectPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset' | 'alignItemWithTrigger'>): React.JSX.Element;
|
|
10
|
+
declare function SelectLabel({ className, ...props }: SelectPrimitive.GroupLabel.Props): React.JSX.Element;
|
|
11
|
+
declare function SelectItem({ className, children, ...props }: SelectPrimitive.Item.Props): React.JSX.Element;
|
|
12
|
+
declare function SelectSeparator({ className, ...props }: SelectPrimitive.Separator.Props): React.JSX.Element;
|
|
13
|
+
declare function SelectScrollUpButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollUpArrow>): React.JSX.Element;
|
|
14
|
+
declare function SelectScrollDownButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollDownArrow>): React.JSX.Element;
|
|
15
|
+
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Select as SelectPrimitive } from '@base-ui/react/select';
|
|
5
|
+
import { cn } from '../../lib/utils.js';
|
|
6
|
+
import { PopupExitContext, usePopupExit, usePopupRender } from '../../motion/popup.js';
|
|
7
|
+
import { Check as CheckIcon, ChevronDown as ChevronDownIcon, ChevronUp as ChevronUpIcon, } from '../../icons/index.js';
|
|
8
|
+
function Select({ actionsRef, onOpenChange, ...props }) {
|
|
9
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
10
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(SelectPrimitive.Root, { ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
11
|
+
}
|
|
12
|
+
function SelectGroup({ className, ...props }) {
|
|
13
|
+
return (_jsx(SelectPrimitive.Group, { "data-slot": "select-group", className: cn('scroll-my-1 p-1', className), ...props }));
|
|
14
|
+
}
|
|
15
|
+
function SelectValue({ className, ...props }) {
|
|
16
|
+
return (_jsx(SelectPrimitive.Value, { "data-slot": "select-value", className: cn('flex flex-1 text-left', className), ...props }));
|
|
17
|
+
}
|
|
18
|
+
function SelectTrigger({ className, size = 'default', children, ...props }) {
|
|
19
|
+
return (_jsxs(SelectPrimitive.Trigger, { "data-slot": "select-trigger", "data-size": size, className: cn("flex w-fit items-center justify-between gap-1.5 rounded-lg border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap transition-colors outline-none select-none focus-visible:border-ring disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { render: _jsx(ChevronDownIcon, { className: "pointer-events-none size-4 text-muted-foreground" }) })] }));
|
|
20
|
+
}
|
|
21
|
+
function SelectContent({ className, children, side = 'bottom', sideOffset = 4, align = 'center', alignOffset = 0, alignItemWithTrigger = true, ...props }) {
|
|
22
|
+
const renderPopup = usePopupRender();
|
|
23
|
+
return (_jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Positioner, { side: side, sideOffset: sideOffset, align: align, alignOffset: alignOffset, alignItemWithTrigger: alignItemWithTrigger, className: "isolate z-(--z-dropdown)", children: _jsxs(SelectPrimitive.Popup, { render: renderPopup, "data-slot": "select-content", "data-align-trigger": alignItemWithTrigger, className: cn('relative isolate z-(--z-dropdown) max-h-(--available-height) w-(--anchor-width) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10', className), ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.List, { className: "in-data-[platform=mobile]:flex in-data-[platform=mobile]:flex-col in-data-[platform=mobile]:gap-0.5", children: children }), _jsx(SelectScrollDownButton, {})] }) }) }));
|
|
24
|
+
}
|
|
25
|
+
function SelectLabel({ className, ...props }) {
|
|
26
|
+
return (_jsx(SelectPrimitive.GroupLabel, { "data-slot": "select-label", className: cn('px-1.5 py-1 text-xs text-muted-foreground', className), ...props }));
|
|
27
|
+
}
|
|
28
|
+
function SelectItem({ className, children, ...props }) {
|
|
29
|
+
return (_jsxs(SelectPrimitive.Item, { "data-slot": "select-item", className: cn("relative flex w-full cursor-pointer items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm in-data-[platform=mobile]:text-base outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className), ...props, children: [_jsx(SelectPrimitive.ItemText, { className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap", children: children }), _jsx(SelectPrimitive.ItemIndicator, { render: _jsx("span", { className: "pointer-events-none absolute right-2 flex size-4 items-center justify-center" }), children: _jsx(CheckIcon, { className: "pointer-events-none" }) })] }));
|
|
30
|
+
}
|
|
31
|
+
function SelectSeparator({ className, ...props }) {
|
|
32
|
+
return (_jsx(SelectPrimitive.Separator, { "data-slot": "select-separator", className: cn('pointer-events-none -mx-1 my-1 h-px bg-border', className), ...props }));
|
|
33
|
+
}
|
|
34
|
+
function SelectScrollUpButton({ className, ...props }) {
|
|
35
|
+
return (_jsx(SelectPrimitive.ScrollUpArrow, { "data-slot": "select-scroll-up-button", className: cn("top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: _jsx(ChevronUpIcon, {}) }));
|
|
36
|
+
}
|
|
37
|
+
function SelectScrollDownButton({ className, ...props }) {
|
|
38
|
+
return (_jsx(SelectPrimitive.ScrollDownArrow, { "data-slot": "select-scroll-down-button", className: cn("bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4", className), ...props, children: _jsx(ChevronDownIcon, {}) }));
|
|
39
|
+
}
|
|
40
|
+
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Separator as SeparatorPrimitive } from '@base-ui/react/separator';
|
|
3
|
+
import { cn } from '../../lib/utils.js';
|
|
4
|
+
function Separator({ className, orientation = 'horizontal', ...props }) {
|
|
5
|
+
return (_jsx(SeparatorPrimitive, { "data-slot": "separator", orientation: orientation, className: cn(
|
|
6
|
+
// Deliberate edit to generated output: the registry ships `data-horizontal:` /
|
|
7
|
+
// `data-vertical:`, which Tailwind compiles to `[data-horizontal]` / `[data-vertical]`.
|
|
8
|
+
// Base UI actually emits `data-orientation="horizontal"|"vertical"`, so those never match
|
|
9
|
+
// and the separator renders with no height or width at all. Re-check on the next
|
|
10
|
+
// `shadcn add separator` in case upstream fixes it.
|
|
11
|
+
'shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch', className), ...props }));
|
|
12
|
+
}
|
|
13
|
+
export { Separator };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
3
|
+
type SheetSide = 'left' | 'right' | 'top' | 'bottom';
|
|
4
|
+
/**
|
|
5
|
+
* Bottom-sheet height preset (only meaningful when `side="bottom"`).
|
|
6
|
+
* - `medium` — 50dvh; good for pickers and compact profiles.
|
|
7
|
+
* - `large` — almost full-height (safe-area inset + 1.5rem gap); good for content viewers.
|
|
8
|
+
*/
|
|
9
|
+
type SheetDetent = 'medium' | 'large';
|
|
10
|
+
declare function Sheet({ actionsRef, onOpenChange, ...props }: DialogPrimitive.Root.Props): React.JSX.Element;
|
|
11
|
+
declare function SheetTrigger({ ...props }: DialogPrimitive.Trigger.Props): React.JSX.Element;
|
|
12
|
+
declare function SheetClose({ ...props }: DialogPrimitive.Close.Props): React.JSX.Element;
|
|
13
|
+
declare function SheetContent({ className, children, side, detent, showCloseButton, ...props }: DialogPrimitive.Popup.Props & {
|
|
14
|
+
side?: SheetSide;
|
|
15
|
+
detent?: SheetDetent;
|
|
16
|
+
showCloseButton?: boolean;
|
|
17
|
+
}): React.JSX.Element;
|
|
18
|
+
declare function SheetHeader({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
19
|
+
declare function SheetFooter({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
20
|
+
declare function SheetTitle({ className, ...props }: DialogPrimitive.Title.Props): React.JSX.Element;
|
|
21
|
+
declare function SheetDescription({ className, ...props }: DialogPrimitive.Description.Props): React.JSX.Element;
|
|
22
|
+
export type { SheetDetent };
|
|
23
|
+
export { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription, };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
|
+
import { PopupExitContext, renderBackdrop, useModalRender, usePopupExit } from '../../motion/popup.js';
|
|
6
|
+
import { X as XIcon } from '../../icons/index.js';
|
|
7
|
+
import { sheet } from '../../motion/config.js';
|
|
8
|
+
const DETENT_CLASSES = {
|
|
9
|
+
medium: 'h-[50dvh] rounded-t-2xl',
|
|
10
|
+
large: 'h-[calc(100dvh-env(safe-area-inset-top)-1.5rem)] rounded-t-2xl',
|
|
11
|
+
};
|
|
12
|
+
const SHEET_PRESETS = {
|
|
13
|
+
left: sheet('left'),
|
|
14
|
+
right: sheet('right'),
|
|
15
|
+
top: sheet('top'),
|
|
16
|
+
bottom: sheet('bottom'),
|
|
17
|
+
};
|
|
18
|
+
function Sheet({ actionsRef, onOpenChange, ...props }) {
|
|
19
|
+
const exit = usePopupExit(actionsRef, onOpenChange);
|
|
20
|
+
return (_jsx(PopupExitContext, { value: exit.unmount, children: _jsx(DialogPrimitive.Root, { "data-slot": "sheet", ...props, actionsRef: exit.actionsRef, onOpenChange: exit.onOpenChange }) }));
|
|
21
|
+
}
|
|
22
|
+
function SheetTrigger({ ...props }) {
|
|
23
|
+
return _jsx(DialogPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
|
|
24
|
+
}
|
|
25
|
+
function SheetClose({ ...props }) {
|
|
26
|
+
return _jsx(DialogPrimitive.Close, { "data-slot": "sheet-close", ...props });
|
|
27
|
+
}
|
|
28
|
+
function SheetContent({ className, children, side = 'right', detent, showCloseButton = true, ...props }) {
|
|
29
|
+
const renderPopup = useModalRender(SHEET_PRESETS[side]);
|
|
30
|
+
return (_jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Backdrop, { render: renderBackdrop, "data-slot": "sheet-overlay", className: "fixed inset-y-0 left-[var(--overlay-inset-left,0px)] right-[var(--overlay-inset-right,0px)] z-(--z-modal) bg-black/10" }), _jsxs(DialogPrimitive.Popup, { render: renderPopup, "data-slot": "sheet-content", "data-side": side, className: cn('fixed z-(--z-modal) flex flex-col gap-4 bg-background p-6 shadow-lg', side === 'right' &&
|
|
31
|
+
'safe-border-t safe-border-r safe-border-b top-0 right-[var(--overlay-inset-right,0px)] h-full w-3/4 sm:max-w-sm', side === 'left' &&
|
|
32
|
+
'safe-border-t safe-border-l safe-border-b top-0 left-[var(--overlay-inset-left,0px)] h-full w-3/4 sm:max-w-sm', side === 'top' &&
|
|
33
|
+
'safe-border-t safe-border-l safe-border-r top-0 left-[var(--overlay-inset-left,0px)] right-[var(--overlay-inset-right,0px)] h-auto', side === 'bottom' && (detent ? DETENT_CLASSES[detent] : 'h-auto'), side === 'bottom' &&
|
|
34
|
+
'safe-border-b safe-border-l safe-border-r bottom-0 left-[var(--overlay-inset-left,0px)] right-[var(--overlay-inset-right,0px)]', className), ...props, children: [children, showCloseButton ? (_jsxs(DialogPrimitive.Close, { "data-slot": "sheet-close-btn", className: "absolute top-4 right-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:outline-none", children: [_jsx(XIcon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "Close" })] })) : null] })] }));
|
|
35
|
+
}
|
|
36
|
+
function SheetHeader({ className, ...props }) {
|
|
37
|
+
return (_jsx("div", { "data-slot": "sheet-header", className: cn('flex flex-col gap-2', className), ...props }));
|
|
38
|
+
}
|
|
39
|
+
function SheetFooter({ className, ...props }) {
|
|
40
|
+
return (_jsx("div", { "data-slot": "sheet-footer", className: cn('mt-auto flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className), ...props }));
|
|
41
|
+
}
|
|
42
|
+
function SheetTitle({ className, ...props }) {
|
|
43
|
+
return (_jsx(DialogPrimitive.Title, { "data-slot": "sheet-title", className: cn('text-base leading-none font-semibold', className), ...props }));
|
|
44
|
+
}
|
|
45
|
+
function SheetDescription({ className, ...props }) {
|
|
46
|
+
return (_jsx(DialogPrimitive.Description, { "data-slot": "sheet-description", className: cn('text-sm text-muted-foreground', className), ...props }));
|
|
47
|
+
}
|
|
48
|
+
export { Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription, };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
type SpanProps = Omit<ComponentPropsWithoutRef<'span'>, 'children' | 'onDrag' | 'onDragStart' | 'onDragEnd' | 'onAnimationStart'>;
|
|
3
|
+
export type ShimmerTextProps = {
|
|
4
|
+
/** Label text. Must be a string so the gradient width can scale with length (shadcn AI Shimmer). */
|
|
5
|
+
children: string;
|
|
6
|
+
/**
|
|
7
|
+
* When false, render plain muted text with no sweep (e.g. after a title arrives, or when the
|
|
8
|
+
* pending window has expired). Default true.
|
|
9
|
+
*/
|
|
10
|
+
active?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Multiplier for how wide the shine is relative to character count. Default 2 — same as
|
|
13
|
+
* [shadcn AI Shimmer](https://www.shadcn.io/ai/shimmer).
|
|
14
|
+
*/
|
|
15
|
+
spread?: number;
|
|
16
|
+
} & SpanProps;
|
|
17
|
+
/**
|
|
18
|
+
* AI-style loading label: muted text with an animated gradient that sweeps across the glyphs
|
|
19
|
+
* (`bg-clip-text` + `backgroundPosition`). Same effect as
|
|
20
|
+
* [shadcn AI Shimmer](https://www.shadcn.io/ai/shimmer) / AI Elements.
|
|
21
|
+
*
|
|
22
|
+
* Used for provisional UI copy (e.g. “Untitled” while a session title generates). Under reduced
|
|
23
|
+
* motion — or when `active={false}` — the sweep is dropped and the label stays muted.
|
|
24
|
+
*/
|
|
25
|
+
declare function ShimmerText({ className, children, active, spread, style, ...props }: ShimmerTextProps): import("react").JSX.Element;
|
|
26
|
+
export { ShimmerText };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { motion, useReducedMotion } from '../../motion/index.js';
|
|
3
|
+
import { loopAnimate, loopTransition } from '../../motion/config.js';
|
|
4
|
+
import { cn } from '../../lib/utils.js';
|
|
5
|
+
/**
|
|
6
|
+
* AI-style loading label: muted text with an animated gradient that sweeps across the glyphs
|
|
7
|
+
* (`bg-clip-text` + `backgroundPosition`). Same effect as
|
|
8
|
+
* [shadcn AI Shimmer](https://www.shadcn.io/ai/shimmer) / AI Elements.
|
|
9
|
+
*
|
|
10
|
+
* Used for provisional UI copy (e.g. “Untitled” while a session title generates). Under reduced
|
|
11
|
+
* motion — or when `active={false}` — the sweep is dropped and the label stays muted.
|
|
12
|
+
*/
|
|
13
|
+
function ShimmerText({ className, children, active = true, spread = 2, style, ...props }) {
|
|
14
|
+
const reduceMotion = useReducedMotion();
|
|
15
|
+
const shimmer = active && reduceMotion !== true;
|
|
16
|
+
const dynamicSpread = children.length * spread;
|
|
17
|
+
if (!shimmer) {
|
|
18
|
+
return (_jsx("span", { "data-slot": "shimmer-text", className: cn('inline-block max-w-full align-middle truncate text-muted-foreground', className), style: style, ...props, children: children }));
|
|
19
|
+
}
|
|
20
|
+
return (_jsx(motion.span, { "data-slot": "shimmer-text", className: cn('relative inline-block max-w-full align-middle truncate bg-clip-text text-transparent', className),
|
|
21
|
+
// Stable keyframe bag (`loopAnimate.shimmer`): same identity across re-renders so agent
|
|
22
|
+
// Trace / session-title updates do not restart the sweep and leave it looking stuck.
|
|
23
|
+
animate: loopAnimate.shimmer, transition: loopTransition.shimmer, ...props, style: {
|
|
24
|
+
...style,
|
|
25
|
+
'--spread': `${dynamicSpread}px`,
|
|
26
|
+
// Shine band + solid muted fill underneath (shadcn AI Shimmer / AI Elements).
|
|
27
|
+
backgroundImage: 'linear-gradient(90deg, transparent calc(50% - var(--spread)), var(--color-background), transparent calc(50% + var(--spread))), linear-gradient(var(--color-muted-foreground), var(--color-muted-foreground))',
|
|
28
|
+
backgroundSize: '250% 100%, auto',
|
|
29
|
+
backgroundRepeat: 'no-repeat, padding-box',
|
|
30
|
+
}, children: children }));
|
|
31
|
+
}
|
|
32
|
+
export { ShimmerText };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
4
|
+
import { Button } from './button.js';
|
|
5
|
+
import { Input } from './input.js';
|
|
6
|
+
import { Separator } from './separator.js';
|
|
7
|
+
import { TooltipContent } from './tooltip.js';
|
|
8
|
+
type SidebarContextProps = {
|
|
9
|
+
state: 'expanded' | 'collapsed';
|
|
10
|
+
open: boolean;
|
|
11
|
+
setOpen: (open: boolean) => void;
|
|
12
|
+
openMobile: boolean;
|
|
13
|
+
setOpenMobile: (open: boolean) => void;
|
|
14
|
+
isMobile: boolean;
|
|
15
|
+
toggleSidebar: () => void;
|
|
16
|
+
};
|
|
17
|
+
declare function useSidebar(): SidebarContextProps;
|
|
18
|
+
declare function SidebarProvider({ defaultOpen, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }: React.ComponentProps<'div'> & {
|
|
19
|
+
defaultOpen?: boolean;
|
|
20
|
+
open?: boolean;
|
|
21
|
+
onOpenChange?: (open: boolean) => void;
|
|
22
|
+
}): React.JSX.Element;
|
|
23
|
+
declare function Sidebar({ side, variant, collapsible, className, children, dir, ...props }: React.ComponentProps<'div'> & {
|
|
24
|
+
side?: 'left' | 'right';
|
|
25
|
+
variant?: 'sidebar' | 'floating' | 'inset';
|
|
26
|
+
collapsible?: 'offcanvas' | 'icon' | 'none';
|
|
27
|
+
}): React.JSX.Element;
|
|
28
|
+
declare function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>): React.JSX.Element;
|
|
29
|
+
declare function SidebarRail({ className, ...props }: React.ComponentProps<'button'>): React.JSX.Element;
|
|
30
|
+
declare function SidebarInset({ className, ...props }: React.ComponentProps<'main'>): React.JSX.Element;
|
|
31
|
+
declare function SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>): React.JSX.Element;
|
|
32
|
+
declare function SidebarHeader({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
33
|
+
declare function SidebarFooter({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
34
|
+
declare function SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>): React.JSX.Element;
|
|
35
|
+
declare function SidebarContent({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
36
|
+
declare function SidebarGroup({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
37
|
+
declare function SidebarGroupLabel({ className, render, ...props }: useRender.ComponentProps<'div'> & React.ComponentProps<'div'>): React.JSX.Element;
|
|
38
|
+
declare function SidebarGroupAction({ className, render, ...props }: useRender.ComponentProps<'button'> & React.ComponentProps<'button'>): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
|
|
39
|
+
declare function SidebarGroupContent({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
40
|
+
declare function SidebarMenu({ className, ...props }: React.ComponentProps<'ul'>): React.JSX.Element;
|
|
41
|
+
declare function SidebarMenuItem({ className, ...props }: React.ComponentProps<'li'>): React.JSX.Element;
|
|
42
|
+
declare const sidebarMenuButtonVariants: (props?: ({
|
|
43
|
+
variant?: "outline" | "default" | null | undefined;
|
|
44
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
45
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
46
|
+
declare function SidebarMenuButton({ render, isActive, variant, size, tooltip, className, ...props }: useRender.ComponentProps<'button'> & React.ComponentProps<'button'> & {
|
|
47
|
+
isActive?: boolean;
|
|
48
|
+
tooltip?: string | React.ComponentProps<typeof TooltipContent>;
|
|
49
|
+
} & VariantProps<typeof sidebarMenuButtonVariants>): React.JSX.Element;
|
|
50
|
+
declare function SidebarMenuAction({ className, render, showOnHover, ...props }: useRender.ComponentProps<'button'> & React.ComponentProps<'button'> & {
|
|
51
|
+
showOnHover?: boolean;
|
|
52
|
+
}): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
|
|
53
|
+
declare function SidebarMenuBadge({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
54
|
+
declare function SidebarMenuSkeleton({ className, showIcon, ...props }: React.ComponentProps<'div'> & {
|
|
55
|
+
showIcon?: boolean;
|
|
56
|
+
}): React.JSX.Element;
|
|
57
|
+
declare function SidebarMenuSub({ className, ...props }: React.ComponentProps<'ul'>): React.JSX.Element;
|
|
58
|
+
declare function SidebarMenuSubItem({ className, ...props }: React.ComponentProps<'li'>): React.JSX.Element;
|
|
59
|
+
declare function SidebarMenuSubButton({ render, size, isActive, className, ...props }: useRender.ComponentProps<'a'> & React.ComponentProps<'a'> & {
|
|
60
|
+
size?: 'sm' | 'md';
|
|
61
|
+
isActive?: boolean;
|
|
62
|
+
}): React.ReactElement<unknown, string | React.JSXElementConstructor<any>>;
|
|
63
|
+
export { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, useSidebar, };
|